From 2c42fd533336a88bdf381cd0784a00256c50430d Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 7 Aug 2024 10:32:33 +0100 Subject: [PATCH 1/5] WiP restructure --- Cargo.lock | 1646 +++++++++-------- Cargo.toml | 51 +- .../coordinator/Cargo.toml | 20 + .../coordinator/src/external_attestation.rs | 200 ++ .../coordinator/src/lib.rs | 52 + .../coordinator/tests/config.rs | 141 ++ .../tests/external_id_attestation.rs | 318 ++++ .../external_attestation/integrity/Cargo.toml | 16 + .../src/agent_external_id_attestation.rs | 42 + .../integrity/src/entry_types.rs | 25 + .../integrity/src/external_id_attestation.rs | 18 + .../src/external_id_to_attestation.rs | 49 + .../external_attestation/integrity/src/lib.rs | 140 ++ .../integrity/src/link_types.rs | 67 + crates/holoom_recipe/coordinator/Cargo.toml | 24 + .../coordinator/src/holoom_recipe.rs | 13 + crates/holoom_recipe/coordinator/src/lib.rs | 48 + .../holoom_recipe/coordinator/tests/config.rs | 141 ++ .../holoom_recipe/coordinator/tests/recipe.rs | 364 ++++ crates/holoom_recipe/integrity/Cargo.toml | 16 + .../integrity/src/entry_types.rs | 22 + .../integrity/src/holoom_recipe.rs} | 0 crates/holoom_recipe/integrity/src/lib.rs | 139 ++ .../holoom_recipe/integrity/src/link_types.rs | 43 + .../integrity}/src/name_to_recipe.rs | 0 .../coordinator/Cargo.toml | 26 + .../src/holoom_recipe_execution.rs | 279 +++ .../coordinator/src/lib.rs | 52 + .../integrity/Cargo.toml | 18 + .../integrity/src/entry_types.rs | 23 + .../integrity/src/holoom_recipe_execution.rs | 231 +++ .../integrity/src/lib.rs | 137 ++ .../integrity/src/link_types.rs | 34 + crates/holoom_types/src/evm_signing_offer.rs | 16 +- crates/holoom_types/src/lib.rs | 1 + crates/holoom_types/src/recipe.rs | 7 + crates/oracle_document/coordinator/Cargo.toml | 24 + crates/oracle_document/coordinator/src/lib.rs | 30 + .../coordinator/src/oracle_document.rs | 126 ++ .../coordinator/tests/config.rs | 141 ++ .../coordinator/tests/oracle_document.rs | 73 + crates/oracle_document/integrity/Cargo.toml | 15 + .../integrity/src/entry_types.rs | 23 + crates/oracle_document/integrity/src/lib.rs | 141 ++ .../integrity/src/link_types.rs | 65 + .../integrity/src/name_oracle_document.rs | 41 + .../integrity}/src/oracle_document.rs | 0 .../src/relate_oracle_document_name.rs | 39 + crates/shared_utils/Cargo.toml | 24 + crates/shared_utils/src/helpers.rs | 34 + crates/shared_utils/src/lib.rs | 2 + .../coordinator/Cargo.toml | 20 + .../coordinator/src/lib.rs | 30 + .../coordinator/src/user_metadata.rs | 77 + .../coordinator/src/username_attestation.rs | 135 ++ .../coordinator/tests/config.rs | 141 ++ .../coordinator/tests/username_attestation.rs | 424 +++++ .../username_attestation/integrity/Cargo.toml | 15 + .../src/agent_username_attestation.rs | 42 + .../integrity/src/entry_types.rs | 25 + .../username_attestation/integrity/src/lib.rs | 140 ++ .../integrity/src/link_types.rs | 64 + .../integrity}/src/user_metadata.rs | 0 .../integrity/src/username_attestation.rs | 92 + .../wallet_attestation/coordinator/Cargo.toml | 24 + .../wallet_attestation/coordinator/src/lib.rs | 26 + .../coordinator/src/wallet_attestation.rs | 74 + .../coordinator/tests/config.rs | 141 ++ .../coordinator/tests/wallet_attestation.rs | 152 ++ .../wallet_attestation/integrity/Cargo.toml | 15 + .../src/agent_wallet_attestation.rs | 0 .../integrity/src/entry_types.rs | 25 + .../wallet_attestation/integrity/src/lib.rs | 138 ++ .../integrity/src/link_types.rs | 50 + .../integrity}/src/wallet_attestation.rs | 0 .../holoom_dna_tests/Cargo.toml | 0 .../holoom_dna_tests/src/lib.rs | 0 .../holoom_dna_tests/src/tests/mod.rs | 0 .../holoom_dna_tests/src/tests/signer.rs | 0 .../external_id_attestation.rs | 0 .../src/tests/username_registry/mod.rs | 0 .../src/tests/username_registry/oracle.rs | 0 .../src/tests/username_registry/recipe.rs | 0 .../tests/username_registry/user_metadata.rs | 0 .../username_registry/username_attestation.rs | 0 .../username_registry/wallet_attestation.rs | 0 old_crates/holoom_types/Cargo.toml | 15 + .../holoom_types/src/evm_signing_offer.rs | 81 + old_crates/holoom_types/src/external_id.rs | 49 + old_crates/holoom_types/src/lib.rs | 86 + old_crates/holoom_types/src/metadata.rs | 27 + old_crates/holoom_types/src/oracle.rs | 19 + old_crates/holoom_types/src/recipe.rs | 104 ++ old_crates/holoom_types/src/username.rs | 22 + old_crates/holoom_types/src/wallet.rs | 36 + old_crates/jaq_wrapper/Cargo.toml | 16 + old_crates/jaq_wrapper/src/lib.rs | 147 ++ .../ping_coordinator/Cargo.toml | 0 .../ping_coordinator/src/lib.rs | 0 .../records_coordinator/Cargo.toml | 0 .../records_coordinator/src/lib.rs | 0 .../signer_coordinator/Cargo.toml | 0 .../signer_coordinator/src/lib.rs | 0 .../username_registry_coordinator/Cargo.toml | 0 .../src/evm_signing_offer.rs | 0 .../src/external_id_attestation.rs | 0 .../username_registry_coordinator/src/lib.rs | 0 .../src/oracle_document.rs | 0 .../src/recipe.rs | 0 .../src/recipe_execution.rs | 0 .../src/user_metadata.rs | 0 .../src/username_attestation.rs | 0 .../src/wallet_attestation.rs | 0 .../username_registry_integrity/Cargo.toml | 0 .../src/entry_types.rs | 0 .../username_registry_integrity/src/lib.rs | 0 .../src/link_types.rs | 0 .../username_registry_utils/Cargo.toml | 0 .../username_registry_utils/src/lib.rs | 0 .../username_registry_validation/Cargo.toml | 0 .../src/agent_external_id_attestation.rs | 0 .../src/agent_username_attestation.rs | 0 .../src/agent_wallet_attestation.rs | 52 + .../src/evm_address_to_signing_offer.rs | 0 .../src/evm_signing_offer.rs | 0 .../src/external_id_attestation.rs | 0 .../src/external_id_to_attestation.rs | 0 .../username_registry_validation/src/lib.rs | 0 .../src/name_oracle_document.rs | 0 .../src/name_to_evm_signing_offer.rs | 0 .../src/name_to_recipe.rs | 21 + .../src/oracle_document.rs | 9 + .../src/recipe.rs | 69 + .../src/recipe_execution.rs | 0 .../src/relate_oracle_document_name.rs | 0 .../src/user_metadata.rs | 44 + .../src/username_attestation.rs | 0 .../src/wallet_attestation.rs | 109 ++ scripts/build_dna.sh | 5 +- workdir/dna.yaml | 58 +- 140 files changed, 7206 insertions(+), 810 deletions(-) create mode 100644 crates/external_attestation/coordinator/Cargo.toml create mode 100644 crates/external_attestation/coordinator/src/external_attestation.rs create mode 100644 crates/external_attestation/coordinator/src/lib.rs create mode 100644 crates/external_attestation/coordinator/tests/config.rs create mode 100644 crates/external_attestation/coordinator/tests/external_id_attestation.rs create mode 100644 crates/external_attestation/integrity/Cargo.toml create mode 100644 crates/external_attestation/integrity/src/agent_external_id_attestation.rs create mode 100644 crates/external_attestation/integrity/src/entry_types.rs create mode 100644 crates/external_attestation/integrity/src/external_id_attestation.rs create mode 100644 crates/external_attestation/integrity/src/external_id_to_attestation.rs create mode 100644 crates/external_attestation/integrity/src/lib.rs create mode 100644 crates/external_attestation/integrity/src/link_types.rs create mode 100644 crates/holoom_recipe/coordinator/Cargo.toml create mode 100644 crates/holoom_recipe/coordinator/src/holoom_recipe.rs create mode 100644 crates/holoom_recipe/coordinator/src/lib.rs create mode 100644 crates/holoom_recipe/coordinator/tests/config.rs create mode 100644 crates/holoom_recipe/coordinator/tests/recipe.rs create mode 100644 crates/holoom_recipe/integrity/Cargo.toml create mode 100644 crates/holoom_recipe/integrity/src/entry_types.rs rename crates/{username_registry_validation/src/recipe.rs => holoom_recipe/integrity/src/holoom_recipe.rs} (100%) create mode 100644 crates/holoom_recipe/integrity/src/lib.rs create mode 100644 crates/holoom_recipe/integrity/src/link_types.rs rename crates/{username_registry_validation => holoom_recipe/integrity}/src/name_to_recipe.rs (100%) create mode 100644 crates/holoom_recipe_execution/coordinator/Cargo.toml create mode 100644 crates/holoom_recipe_execution/coordinator/src/holoom_recipe_execution.rs create mode 100644 crates/holoom_recipe_execution/coordinator/src/lib.rs create mode 100644 crates/holoom_recipe_execution/integrity/Cargo.toml create mode 100644 crates/holoom_recipe_execution/integrity/src/entry_types.rs create mode 100644 crates/holoom_recipe_execution/integrity/src/holoom_recipe_execution.rs create mode 100644 crates/holoom_recipe_execution/integrity/src/lib.rs create mode 100644 crates/holoom_recipe_execution/integrity/src/link_types.rs create mode 100644 crates/oracle_document/coordinator/Cargo.toml create mode 100644 crates/oracle_document/coordinator/src/lib.rs create mode 100644 crates/oracle_document/coordinator/src/oracle_document.rs create mode 100644 crates/oracle_document/coordinator/tests/config.rs create mode 100644 crates/oracle_document/coordinator/tests/oracle_document.rs create mode 100644 crates/oracle_document/integrity/Cargo.toml create mode 100644 crates/oracle_document/integrity/src/entry_types.rs create mode 100644 crates/oracle_document/integrity/src/lib.rs create mode 100644 crates/oracle_document/integrity/src/link_types.rs create mode 100644 crates/oracle_document/integrity/src/name_oracle_document.rs rename crates/{username_registry_validation => oracle_document/integrity}/src/oracle_document.rs (100%) create mode 100644 crates/oracle_document/integrity/src/relate_oracle_document_name.rs create mode 100644 crates/shared_utils/Cargo.toml create mode 100644 crates/shared_utils/src/helpers.rs create mode 100644 crates/shared_utils/src/lib.rs create mode 100644 crates/username_attestation/coordinator/Cargo.toml create mode 100644 crates/username_attestation/coordinator/src/lib.rs create mode 100644 crates/username_attestation/coordinator/src/user_metadata.rs create mode 100644 crates/username_attestation/coordinator/src/username_attestation.rs create mode 100644 crates/username_attestation/coordinator/tests/config.rs create mode 100644 crates/username_attestation/coordinator/tests/username_attestation.rs create mode 100644 crates/username_attestation/integrity/Cargo.toml create mode 100644 crates/username_attestation/integrity/src/agent_username_attestation.rs create mode 100644 crates/username_attestation/integrity/src/entry_types.rs create mode 100644 crates/username_attestation/integrity/src/lib.rs create mode 100644 crates/username_attestation/integrity/src/link_types.rs rename crates/{username_registry_validation => username_attestation/integrity}/src/user_metadata.rs (100%) create mode 100644 crates/username_attestation/integrity/src/username_attestation.rs create mode 100644 crates/wallet_attestation/coordinator/Cargo.toml create mode 100644 crates/wallet_attestation/coordinator/src/lib.rs create mode 100644 crates/wallet_attestation/coordinator/src/wallet_attestation.rs create mode 100644 crates/wallet_attestation/coordinator/tests/config.rs create mode 100644 crates/wallet_attestation/coordinator/tests/wallet_attestation.rs create mode 100644 crates/wallet_attestation/integrity/Cargo.toml rename crates/{username_registry_validation => wallet_attestation/integrity}/src/agent_wallet_attestation.rs (100%) create mode 100644 crates/wallet_attestation/integrity/src/entry_types.rs create mode 100644 crates/wallet_attestation/integrity/src/lib.rs create mode 100644 crates/wallet_attestation/integrity/src/link_types.rs rename crates/{username_registry_validation => wallet_attestation/integrity}/src/wallet_attestation.rs (100%) rename {crates => old_crates}/holoom_dna_tests/Cargo.toml (100%) rename {crates => old_crates}/holoom_dna_tests/src/lib.rs (100%) rename {crates => old_crates}/holoom_dna_tests/src/tests/mod.rs (100%) rename {crates => old_crates}/holoom_dna_tests/src/tests/signer.rs (100%) rename {crates => old_crates}/holoom_dna_tests/src/tests/username_registry/external_id_attestation.rs (100%) rename {crates => old_crates}/holoom_dna_tests/src/tests/username_registry/mod.rs (100%) rename {crates => old_crates}/holoom_dna_tests/src/tests/username_registry/oracle.rs (100%) rename {crates => old_crates}/holoom_dna_tests/src/tests/username_registry/recipe.rs (100%) rename {crates => old_crates}/holoom_dna_tests/src/tests/username_registry/user_metadata.rs (100%) rename {crates => old_crates}/holoom_dna_tests/src/tests/username_registry/username_attestation.rs (100%) rename {crates => old_crates}/holoom_dna_tests/src/tests/username_registry/wallet_attestation.rs (100%) create mode 100644 old_crates/holoom_types/Cargo.toml create mode 100644 old_crates/holoom_types/src/evm_signing_offer.rs create mode 100644 old_crates/holoom_types/src/external_id.rs create mode 100644 old_crates/holoom_types/src/lib.rs create mode 100644 old_crates/holoom_types/src/metadata.rs create mode 100644 old_crates/holoom_types/src/oracle.rs create mode 100644 old_crates/holoom_types/src/recipe.rs create mode 100644 old_crates/holoom_types/src/username.rs create mode 100644 old_crates/holoom_types/src/wallet.rs create mode 100644 old_crates/jaq_wrapper/Cargo.toml create mode 100644 old_crates/jaq_wrapper/src/lib.rs rename {crates => old_crates}/ping_coordinator/Cargo.toml (100%) rename {crates => old_crates}/ping_coordinator/src/lib.rs (100%) rename {crates => old_crates}/records_coordinator/Cargo.toml (100%) rename {crates => old_crates}/records_coordinator/src/lib.rs (100%) rename {crates => old_crates}/signer_coordinator/Cargo.toml (100%) rename {crates => old_crates}/signer_coordinator/src/lib.rs (100%) rename {crates => old_crates}/username_registry_coordinator/Cargo.toml (100%) rename {crates => old_crates}/username_registry_coordinator/src/evm_signing_offer.rs (100%) rename {crates => old_crates}/username_registry_coordinator/src/external_id_attestation.rs (100%) rename {crates => old_crates}/username_registry_coordinator/src/lib.rs (100%) rename {crates => old_crates}/username_registry_coordinator/src/oracle_document.rs (100%) rename {crates => old_crates}/username_registry_coordinator/src/recipe.rs (100%) rename {crates => old_crates}/username_registry_coordinator/src/recipe_execution.rs (100%) rename {crates => old_crates}/username_registry_coordinator/src/user_metadata.rs (100%) rename {crates => old_crates}/username_registry_coordinator/src/username_attestation.rs (100%) rename {crates => old_crates}/username_registry_coordinator/src/wallet_attestation.rs (100%) rename {crates => old_crates}/username_registry_integrity/Cargo.toml (100%) rename {crates => old_crates}/username_registry_integrity/src/entry_types.rs (100%) rename {crates => old_crates}/username_registry_integrity/src/lib.rs (100%) rename {crates => old_crates}/username_registry_integrity/src/link_types.rs (100%) rename {crates => old_crates}/username_registry_utils/Cargo.toml (100%) rename {crates => old_crates}/username_registry_utils/src/lib.rs (100%) rename {crates => old_crates}/username_registry_validation/Cargo.toml (100%) rename {crates => old_crates}/username_registry_validation/src/agent_external_id_attestation.rs (100%) rename {crates => old_crates}/username_registry_validation/src/agent_username_attestation.rs (100%) create mode 100644 old_crates/username_registry_validation/src/agent_wallet_attestation.rs rename {crates => old_crates}/username_registry_validation/src/evm_address_to_signing_offer.rs (100%) rename {crates => old_crates}/username_registry_validation/src/evm_signing_offer.rs (100%) rename {crates => old_crates}/username_registry_validation/src/external_id_attestation.rs (100%) rename {crates => old_crates}/username_registry_validation/src/external_id_to_attestation.rs (100%) rename {crates => old_crates}/username_registry_validation/src/lib.rs (100%) rename {crates => old_crates}/username_registry_validation/src/name_oracle_document.rs (100%) rename {crates => old_crates}/username_registry_validation/src/name_to_evm_signing_offer.rs (100%) create mode 100644 old_crates/username_registry_validation/src/name_to_recipe.rs create mode 100644 old_crates/username_registry_validation/src/oracle_document.rs create mode 100644 old_crates/username_registry_validation/src/recipe.rs rename {crates => old_crates}/username_registry_validation/src/recipe_execution.rs (100%) rename {crates => old_crates}/username_registry_validation/src/relate_oracle_document_name.rs (100%) create mode 100644 old_crates/username_registry_validation/src/user_metadata.rs rename {crates => old_crates}/username_registry_validation/src/username_attestation.rs (100%) create mode 100644 old_crates/username_registry_validation/src/wallet_attestation.rs diff --git a/Cargo.lock b/Cargo.lock index 733b70a..ddac8e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,11 +14,11 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ - "gimli 0.28.1", + "gimli 0.29.0", ] [[package]] @@ -77,9 +77,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -93,7 +93,7 @@ dependencies = [ "anyhow", "derive_more", "holochain_trace", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "petgraph", "regex", "serde", @@ -112,9 +112,9 @@ checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alloy-primitives" @@ -140,9 +140,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.4" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" +checksum = "a43b18702501396fa9bcdeecd533bc85fac75150d308fc0f6800a01e6234a003" dependencies = [ "arrayvec", "bytes", @@ -174,47 +174,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -222,9 +223,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app_dirs2" @@ -382,9 +383,9 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" [[package]] name = "arrayvec" @@ -415,28 +416,26 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" dependencies = [ "concurrent-queue", - "event-listener 5.2.0", - "event-listener-strategy 0.5.0", + "event-listener-strategy", "futures-core", "pin-project-lite", ] [[package]] name = "async-executor" -version = "1.8.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" +checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" dependencies = [ - "async-lock 3.3.0", "async-task", "concurrent-queue", - "fastrand 2.0.1", - "futures-lite 2.2.0", + "fastrand 2.1.0", + "futures-lite 2.3.0", "slab", ] @@ -446,12 +445,12 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel 2.2.0", + "async-channel 2.3.1", "async-executor", - "async-io 2.3.2", - "async-lock 3.3.0", + "async-io 2.3.3", + "async-lock 3.4.0", "blocking", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "once_cell", ] @@ -462,7 +461,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ "async-lock 2.8.0", - "autocfg 1.1.0", + "autocfg 1.3.0", "cfg-if 1.0.0", "concurrent-queue", "futures-lite 1.13.0", @@ -477,18 +476,18 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" +checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" dependencies = [ - "async-lock 3.3.0", + "async-lock 3.4.0", "cfg-if 1.0.0", "concurrent-queue", "futures-io", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "parking", - "polling 3.5.0", - "rustix 0.38.31", + "polling 3.7.2", + "rustix 0.38.34", "slab", "tracing", "windows-sys 0.52.0", @@ -505,12 +504,12 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 4.0.3", - "event-listener-strategy 0.4.0", + "event-listener 5.3.1", + "event-listener-strategy", "pin-project-lite", ] @@ -533,7 +532,7 @@ dependencies = [ "cfg-if 1.0.0", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.31", + "rustix 0.38.34", "windows-sys 0.48.0", ] @@ -545,25 +544,25 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] name = "async-signal" -version = "0.2.5" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" +checksum = "dfb3634b73397aa844481f814fad23bbf07fdb0eabec10f2eb95e58944b1ec32" dependencies = [ - "async-io 2.3.2", - "async-lock 2.8.0", + "async-io 2.3.3", + "async-lock 3.4.0", "atomic-waker", "cfg-if 1.0.0", "futures-core", "futures-io", - "rustix 0.38.31", + "rustix 0.38.34", "signal-hook-registry", "slab", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -617,19 +616,19 @@ dependencies = [ [[package]] name = "async-task" -version = "4.7.0" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -657,7 +656,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -666,14 +665,14 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "automap" @@ -689,11 +688,11 @@ dependencies = [ [[package]] name = "backon" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c491fa80d69c03084223a4e73c378dd9f9a1e612eb54051213f88b2d5249b458" +checksum = "d67782c3f868daa71d3533538e98a8e13713231969def7536e8039606fc46bf0" dependencies = [ - "fastrand 2.0.1", + "fastrand 2.1.0", "futures-core", "pin-project", "tokio", @@ -701,9 +700,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -799,7 +798,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ - "bit-vec", + "bit-vec 0.6.3", ] [[package]] @@ -807,6 +806,12 @@ name = "bit-vec" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bit-vec" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22" dependencies = [ "serde", ] @@ -825,9 +830,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitvec" @@ -933,27 +938,24 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blocking" -version = "1.5.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ - "async-channel 2.2.0", - "async-lock 3.3.0", + "async-channel 2.3.1", "async-task", - "fastrand 2.0.1", "futures-io", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "piper", - "tracing", ] [[package]] name = "bloomfilter" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b64d54e47a7f4fd723f082e8f11429f3df6ba8adaeca355a76556f9f0602bbcf" +checksum = "bc0bdbcf2078e0ba8a74e1fe0cf36f54054a04485759b61dfd60b174658e9607" dependencies = [ - "bit-vec", + "bit-vec 0.7.0", "getrandom 0.2.15", "siphasher", ] @@ -966,9 +968,9 @@ checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bs58" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ "tinyvec", ] @@ -1015,9 +1017,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.14.3" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" +checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" [[package]] name = "byteorder" @@ -1027,9 +1029,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" dependencies = [ "serde", ] @@ -1051,18 +1053,18 @@ checksum = "4964518bd3b4a8190e832886cdc0da9794f12e8e6c1613a9e90ff331c4c8724b" [[package]] name = "camino" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.3" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" dependencies = [ "serde", ] @@ -1075,7 +1077,7 @@ checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" dependencies = [ "camino", "cargo-platform", - "semver 1.0.20", + "semver 1.0.23", "serde", "serde_json", "thiserror", @@ -1083,9 +1085,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.90" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" [[package]] name = "cesu8" @@ -1107,9 +1109,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1117,7 +1119,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.4", + "windows-targets 0.52.6", ] [[package]] @@ -1126,7 +1128,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -1155,9 +1157,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.10" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6b81fb3c84f5563d509c59b5a48d935f689e993afa90fe39047f05adef9142" +checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc" dependencies = [ "clap_builder", "clap_derive", @@ -1165,34 +1167,34 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.10" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca6706fd5224857d9ac5eb9355f6683563cc0541c7cd9d014043b57cbec78ac" +checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.0", + "strsim 0.11.1", "terminal_size", ] [[package]] name = "clap_derive" -version = "4.5.8" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "cloudabi" @@ -1261,9 +1263,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "colored" @@ -1287,18 +1289,18 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] [[package]] name = "const-hex" -version = "1.11.3" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ba00838774b4ab0233e355d26710fbfc8327a05c017f6dc4873f876d1f79f78" +checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -1384,7 +1386,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80128832c58ea9cbd041d2a759ec449224487b2c1e400453d99d244eead87a8e" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", "cfg-if 1.0.0", "libc", "scopeguard", @@ -1485,9 +1487,9 @@ checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if 1.0.0", ] @@ -1505,9 +1507,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] @@ -1542,9 +1544,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -1629,16 +1631,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if 1.0.0", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "platforms", "rustc_version 0.4.0", "subtle", "zeroize", @@ -1652,7 +1653,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -1667,12 +1668,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core 0.20.8", - "darling_macro 0.20.8", + "darling_core 0.20.10", + "darling_macro 0.20.10", ] [[package]] @@ -1691,16 +1692,16 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 2.0.52", + "strsim 0.11.1", + "syn 2.0.72", ] [[package]] @@ -1716,13 +1717,13 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core 0.20.8", + "darling_core 0.20.10", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -1748,17 +1749,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if 1.0.0", - "hashbrown 0.14.3", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core 0.9.10", +] + +[[package]] +name = "dashmap" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804c8821570c3f8b70230c2ba75ffa5c0f9a4189b9a432b6656c536712acae28" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", + "hashbrown 0.14.5", "lock_api", "once_cell", - "parking_lot_core 0.9.9", + "parking_lot_core 0.9.10", ] [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "der" @@ -1780,9 +1795,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid 0.9.6", "zeroize", @@ -1817,7 +1832,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -1856,10 +1871,10 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" dependencies = [ - "darling 0.20.8", + "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -1879,20 +1894,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" dependencies = [ "derive_builder_core 0.20.0", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version 0.4.0", - "syn 1.0.109", + "syn 2.0.72", ] [[package]] @@ -1966,7 +1981,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -1996,9 +2011,9 @@ checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" [[package]] name = "dunce" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "dyn-clone" @@ -2024,7 +2039,7 @@ version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der 0.7.8", + "der 0.7.9", "digest 0.10.7", "elliptic-curve 0.13.8", "rfc6979", @@ -2060,9 +2075,9 @@ dependencies = [ [[package]] name = "either" -version = "1.10.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elliptic-curve" @@ -2116,9 +2131,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if 1.0.0", ] @@ -2145,31 +2160,41 @@ dependencies = [ [[package]] name = "enumset" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d" +checksum = "d07a4b049558765cef5f0c1a273c3fc57084d768b44d2f98127aef4cceb17293" dependencies = [ "enumset_derive", ] [[package]] name = "enumset_derive" -version = "0.8.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" +checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242" dependencies = [ - "darling 0.20.8", + "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", +] + +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", ] [[package]] name = "env_logger" -version = "0.10.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" dependencies = [ + "env_filter", "log", ] @@ -2209,9 +2234,9 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2326,7 +2351,7 @@ dependencies = [ "futures-util", "hex", "rand 0.8.5", - "semver 1.0.20", + "semver 1.0.23", "sha2 0.9.9", "thiserror", ] @@ -2350,9 +2375,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "4.0.3" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ "concurrent-queue", "parking", @@ -2360,34 +2385,36 @@ dependencies = [ ] [[package]] -name = "event-listener" -version = "5.2.0" +name = "event-listener-strategy" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "concurrent-queue", - "parking", + "event-listener 5.3.1", "pin-project-lite", ] [[package]] -name = "event-listener-strategy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +name = "external_attestation" +version = "0.0.1" dependencies = [ - "event-listener 4.0.3", - "pin-project-lite", + "external_attestation_integrity", + "hdk", + "holochain", + "holoom_types", + "serde", + "shared_utils", + "tokio", ] [[package]] -name = "event-listener-strategy" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +name = "external_attestation_integrity" +version = "0.0.1" dependencies = [ - "event-listener 5.2.0", - "pin-project-lite", + "hdi", + "holoom_types", + "serde", + "shared_utils", ] [[package]] @@ -2425,9 +2452,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fastrlp" @@ -2462,9 +2489,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.6" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "filetime" @@ -2516,7 +2543,7 @@ checksum = "58f00f6a51bfb4b9f808a7fc2accb891682bda7cfcafbf08a283393f7db49a80" dependencies = [ "holochain_serialized_bytes", "lazy_static", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "paste", "rand 0.8.5", "rand_core 0.6.4", @@ -2527,9 +2554,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" dependencies = [ "crc32fast", "miniz_oxide", @@ -2663,11 +2690,11 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ - "fastrand 2.0.1", + "fastrand 2.1.0", "futures-core", "futures-io", "parking", @@ -2682,7 +2709,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -2843,9 +2870,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "gloo-timers" @@ -2900,9 +2927,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -2910,7 +2937,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.2.6", + "indexmap 2.3.0", "slab", "tokio", "tokio-util", @@ -2929,7 +2956,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.1.0", - "indexmap 2.2.6", + "indexmap 2.3.0", "slab", "tokio", "tokio-util", @@ -2949,7 +2976,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" dependencies = [ "ahash 0.3.8", - "autocfg 1.1.0", + "autocfg 1.3.0", ] [[package]] @@ -2963,9 +2990,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash 0.8.11", "allocator-api2", @@ -2977,7 +3004,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -3020,7 +3047,7 @@ dependencies = [ "holochain_types", "kitsune_p2p", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "petgraph", "regex", "serde", @@ -3143,6 +3170,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "hex" version = "0.4.3" @@ -3160,9 +3193,9 @@ checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" [[package]] name = "hifijson" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18ae468bcb4dfecf0e4949ee28abbc99076b6a0077f51ddbc94dbfff8e6a870c" +checksum = "9958ab3ce3170c061a27679916bd9b969eceeb5e8b120438e6751d0987655c42" [[package]] name = "hmac" @@ -3201,7 +3234,7 @@ dependencies = [ "kitsune_p2p_dht_arc", "must_future", "proptest", - "proptest-derive", + "proptest-derive 0.5.0", "rand 0.8.5", "rusqlite", "serde", @@ -3272,9 +3305,9 @@ dependencies = [ "once_cell", "one_err", "opentelemetry_api", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "petgraph", - "predicates 3.1.0", + "predicates 3.1.2", "rand 0.8.5", "rand-utf8", "rand_chacha 0.3.1", @@ -3296,7 +3329,7 @@ dependencies = [ "tiny-keccak", "tokio", "tokio-stream", - "toml 0.8.15", + "toml", "tracing", "tracing-futures", "tracing-subscriber", @@ -3388,7 +3421,7 @@ dependencies = [ "holochain_util", "kitsune_p2p_timestamp", "proptest", - "proptest-derive", + "proptest-derive 0.5.0", "serde", "serde_bytes", "subtle", @@ -3415,7 +3448,7 @@ dependencies = [ "must_future", "nanoid", "one_err", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "serde", "serde_bytes", "shrinkwraprs", @@ -3498,7 +3531,7 @@ dependencies = [ "arbitrary", "holochain_serialized_bytes_derive", "proptest", - "proptest-derive", + "proptest-derive 0.4.0", "rmp-serde", "serde", "serde-transcode", @@ -3544,7 +3577,7 @@ dependencies = [ "num_cpus", "once_cell", "opentelemetry_api", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pretty_assertions", "r2d2", "rmp-serde", @@ -3586,7 +3619,7 @@ dependencies = [ "kitsune_p2p", "nanoid", "one_err", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "serde", "serde_json", "shrinkwraprs", @@ -3668,9 +3701,9 @@ dependencies = [ "must_future", "nanoid", "one_err", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "proptest", - "proptest-derive", + "proptest-derive 0.5.0", "rand 0.8.5", "regex", "rusqlite", @@ -3717,7 +3750,7 @@ dependencies = [ "holochain_util", "strum", "strum_macros 0.18.0", - "toml 0.8.15", + "toml", "walkdir", ] @@ -3743,7 +3776,7 @@ checksum = "fce20cd8eb137a355394e57612cf2cf7836dab57948d56af9f9fe080ea168d41" dependencies = [ "holochain_serialized_bytes", "holochain_wasmer_common", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "paste", "serde", "tracing", @@ -3760,7 +3793,7 @@ dependencies = [ "hex", "holochain_serialized_bytes", "holochain_wasmer_common", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand 0.8.5", "serde", "tracing", @@ -3781,7 +3814,7 @@ dependencies = [ "serde", "serde_bytes", "tokio", - "tokio-tungstenite 0.21.0", + "tokio-tungstenite", "tracing", ] @@ -3808,7 +3841,7 @@ dependencies = [ "num_enum", "once_cell", "proptest", - "proptest-derive", + "proptest-derive 0.5.0", "rand 0.8.5", "rusqlite", "serde", @@ -3823,20 +3856,54 @@ dependencies = [ ] [[package]] -name = "holoom_dna_tests" +name = "holoom_recipe" version = "0.0.1" dependencies = [ - "bs58 0.5.0", - "ed25519-dalek", - "ethers-signers", "hdk", "holochain", - "holochain_keystore", + "holoom_recipe_integrity", "holoom_types", "serde", + "shared_utils", "tokio", - "username_registry_utils", - "username_registry_validation", +] + +[[package]] +name = "holoom_recipe_execution" +version = "0.0.1" +dependencies = [ + "external_attestation", + "hdk", + "holoom_recipe_execution_integrity", + "holoom_types", + "indexmap 2.3.0", + "jaq_wrapper", + "oracle_document", + "serde", + "shared_utils", +] + +[[package]] +name = "holoom_recipe_execution_integrity" +version = "0.0.1" +dependencies = [ + "hdi", + "holoom_types", + "indexmap 2.3.0", + "jaq_wrapper", + "serde", + "shared_utils", +] + +[[package]] +name = "holoom_recipe_integrity" +version = "0.0.1" +dependencies = [ + "hdi", + "holoom_types", + "jaq_wrapper", + "serde", + "shared_utils", ] [[package]] @@ -3939,9 +4006,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -3951,9 +4018,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "human-panic" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c5d0e9120f6bca6120d142c7ede1ba376dd6bf276d69dd3dbe6cbeb7824179" +checksum = "1c5a08ed290eac04006e21e63d32e90086b6182c7cd0452d10f4264def1fec9a" dependencies = [ "anstream", "anstyle", @@ -3961,28 +4028,28 @@ dependencies = [ "os_info", "serde", "serde_derive", - "toml 0.8.15", + "toml", "uuid 1.10.0", ] [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", - "h2 0.3.24", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.6", + "socket2 0.5.7", "tokio", "tower-service", "tracing", @@ -4009,6 +4076,23 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.4.1", + "hyper-util", + "rustls 0.23.12", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.0", + "tower-service", +] + [[package]] name = "hyper-tls" version = "0.6.0" @@ -4038,7 +4122,7 @@ dependencies = [ "http-body 1.0.1", "hyper 1.4.1", "pin-project-lite", - "socket2 0.5.6", + "socket2 0.5.7", "tokio", "tower", "tower-service", @@ -4115,7 +4199,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" dependencies = [ - "parity-scale-codec 3.6.3", + "parity-scale-codec 3.6.12", ] [[package]] @@ -4153,35 +4237,35 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", "hashbrown 0.12.3", "serde", ] [[package]] name = "indexmap" -version = "2.2.6" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "serde", ] [[package]] name = "inferno" -version = "0.11.19" +version = "0.11.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" +checksum = "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88" dependencies = [ "ahash 0.8.11", - "clap 4.5.10", + "clap 4.5.13", "crossbeam-channel", "crossbeam-utils", - "dashmap 5.5.3", + "dashmap 6.0.1", "env_logger", - "indexmap 2.2.6", + "indexmap 2.3.0", "is-terminal", "itoa", "log", @@ -4203,9 +4287,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if 1.0.0", ] @@ -4251,6 +4335,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "isotest" version = "0.1.0" @@ -4290,9 +4380,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jaq-core" @@ -4317,7 +4407,7 @@ source = "git+https://github.com/8e8b2c/jaq?rev=1870c7c#1870c7cdcdea4682afcea627 dependencies = [ "dyn-clone", "hifijson", - "indexmap 2.2.6", + "indexmap 2.3.0", "jaq-syn", "once_cell", "serde_json", @@ -4431,9 +4521,9 @@ dependencies = [ [[package]] name = "keccak-asm" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb8515fff80ed850aea4a1595f2e519c003e2a00a82fe168ebf5269196caf444" +checksum = "47a3633291834c4fbebf8673acbc1b04ec9d151418ff9b8e26dcd79129928758" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -4441,9 +4531,9 @@ dependencies = [ [[package]] name = "kitsune_p2p" -version = "0.4.0-dev.13" +version = "0.4.0-dev.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d9d144e82567987196afabdf19fce4905087bf592a053fe6ba04d58c6d7792" +checksum = "f91c1ee5d791599a64c14bd476eef8ca6f8767747ffb50bd1720795c58a5a051" dependencies = [ "arrayref", "base64 0.22.1", @@ -4472,7 +4562,7 @@ dependencies = [ "num-traits", "once_cell", "opentelemetry_api", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand 0.8.5", "serde", "serde_bytes", @@ -4498,7 +4588,7 @@ dependencies = [ "holochain_util", "kitsune_p2p_dht_arc", "proptest", - "proptest-derive", + "proptest-derive 0.5.0", "serde", "serde_bytes", "shrinkwraprs", @@ -4521,11 +4611,11 @@ version = "0.3.0-dev.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90a648ea247a1a98e4f76c5a76dacd2d625a98e8587e6fcfdf72df33af082e56" dependencies = [ - "clap 4.5.10", + "clap 4.5.13", "futures", "kitsune_p2p_bin_data", "kitsune_p2p_types", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand 0.8.5", "reqwest", "serde", @@ -4566,7 +4656,7 @@ dependencies = [ "must_future", "num-traits", "proptest", - "proptest-derive", + "proptest-derive 0.5.0", "rand 0.8.5", "serde", "statrs", @@ -4587,7 +4677,7 @@ dependencies = [ "kitsune_p2p_timestamp", "num-traits", "proptest", - "proptest-derive", + "proptest-derive 0.5.0", "rusqlite", "serde", ] @@ -4600,7 +4690,7 @@ checksum = "f27059a6bdeb1ba89e0acba55b1b446f92642a4ac756c1374c7eb7eb4ae95b66" dependencies = [ "backon", "derive_more", - "indexmap 2.2.6", + "indexmap 2.3.0", "kitsune_p2p_timestamp", "kitsune_p2p_types", "serde", @@ -4650,7 +4740,7 @@ dependencies = [ "chrono", "once_cell", "proptest", - "proptest-derive", + "proptest-derive 0.5.0", "rand 0.8.5", "rusqlite", "serde", @@ -4676,10 +4766,10 @@ dependencies = [ "lair_keystore_api", "mockall", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "paste", "proptest", - "proptest-derive", + "proptest-derive 0.5.0", "rmp-serde", "rustls 0.21.12", "serde", @@ -4729,14 +4819,14 @@ dependencies = [ "lru", "nanoid", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rcgen", "serde", "serde_json", "serde_yaml", "time", "tokio", - "toml 0.8.15", + "toml", "tracing", "url", "winapi 0.3.9", @@ -4745,9 +4835,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "leb128" @@ -4781,18 +4871,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e0d73b369f386f1c44abd9c570d5318f55ccde816ff4b562fa452e5182863d" dependencies = [ "core2", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "rle-decode-fast", ] [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.52.4", + "windows-targets 0.52.6", ] [[package]] @@ -4823,20 +4913,19 @@ dependencies = [ [[package]] name = "libredox" -version = "0.0.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "libc", - "redox_syscall 0.4.1", ] [[package]] name = "libsodium-sys-stable" -version = "1.20.9" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad52c454200cd0178a04ef7642a240a7e81b4d8c59f0865eb98c477daf7d3b84" +checksum = "5fd1882b85f01cdd4021c0664fd897710a04c5d01b593a5a70e1b0baa999c1f8" dependencies = [ "cc", "libc", @@ -4846,7 +4935,7 @@ dependencies = [ "tar", "ureq", "vcpkg", - "zip 2.1.1", + "zip 2.1.6", ] [[package]] @@ -4869,9 +4958,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litrs" @@ -4881,11 +4970,11 @@ checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", "scopeguard", ] @@ -4897,20 +4986,20 @@ checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" dependencies = [ "value-bag", ] [[package]] name = "lru" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -4922,6 +5011,15 @@ dependencies = [ "libc", ] +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + [[package]] name = "maplit" version = "1.0.2" @@ -4951,11 +5049,11 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "matrixmultiply" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2" +checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", "rawpointer", ] @@ -5005,16 +5103,16 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", ] [[package]] name = "memoffset" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", ] [[package]] @@ -5025,9 +5123,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -5047,9 +5145,9 @@ checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] @@ -5111,7 +5209,7 @@ dependencies = [ "futures", "holochain_util", "proptest", - "proptest-derive", + "proptest-derive 0.5.0", "reqwest", "rmp-serde", "serde", @@ -5198,11 +5296,10 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -5296,9 +5393,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ "num-bigint", "num-complex", @@ -5310,20 +5407,19 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg 1.1.0", "num-integer", "num-traits", ] [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -5355,22 +5451,21 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", "num-integer", "num-traits", ] [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg 1.1.0", "num-bigint", "num-integer", "num-traits", @@ -5378,11 +5473,11 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", "libm", ] @@ -5398,30 +5493,30 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ - "proc-macro-crate 2.0.0", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] name = "object" -version = "0.32.2" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" dependencies = [ "memchr", ] @@ -5458,11 +5553,11 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.64" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "cfg-if 1.0.0", "foreign-types", "libc", @@ -5479,7 +5574,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -5499,9 +5594,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.101" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -5532,15 +5627,38 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "oracle_document" +version = "0.0.1" +dependencies = [ + "hdk", + "holochain", + "holoom_types", + "oracle_document_integrity", + "serde", + "shared_utils", + "tokio", +] + +[[package]] +name = "oracle_document_integrity" +version = "0.0.1" +dependencies = [ + "hdi", + "holoom_types", + "serde", + "shared_utils", +] + [[package]] name = "os_info" -version = "3.7.0" +version = "3.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e" +checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" dependencies = [ "log", "serde", - "winapi 0.3.9", + "windows-sys 0.52.0", ] [[package]] @@ -5588,15 +5706,15 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.3" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "756d439303e94fae44f288ba881ad29670c65b0c4b0e05674ca81061bb65f2c5" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec", "bitvec 1.0.1", "byte-slice-cast", "impl-trait-for-tuples", - "parity-scale-codec-derive 3.6.9", + "parity-scale-codec-derive 3.6.12", "serde", ] @@ -5614,11 +5732,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 2.0.0", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -5643,12 +5761,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.9", + "parking_lot_core 0.9.10", ] [[package]] @@ -5667,15 +5785,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.3", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -5691,9 +5809,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pbkdf2" @@ -5725,9 +5843,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.8" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ "memchr", "thiserror", @@ -5741,7 +5859,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.2.6", + "indexmap 2.3.0", "quickcheck", ] @@ -5762,14 +5880,14 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -5777,22 +5895,14 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "ping_coordinator" -version = "0.0.1" -dependencies = [ - "hdk", - "serde", -] - [[package]] name = "piper" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" dependencies = [ "atomic-waker", - "fastrand 2.0.1", + "fastrand 2.1.0", "futures-io", ] @@ -5812,7 +5922,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.8", + "der 0.7.9", "spki 0.7.3", ] @@ -5822,19 +5932,13 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" -[[package]] -name = "platforms" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" - [[package]] name = "polling" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", "bitflags 1.3.2", "cfg-if 1.0.0", "concurrent-queue", @@ -5846,14 +5950,15 @@ dependencies = [ [[package]] name = "polling" -version = "3.5.0" +version = "3.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24f040dee2588b4963afb4e420540439d126f73fdacf4a9c486a96d840bac3c9" +checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" dependencies = [ "cfg-if 1.0.0", "concurrent-queue", + "hermit-abi 0.4.0", "pin-project-lite", - "rustix 0.38.31", + "rustix 0.38.34", "tracing", "windows-sys 0.52.0", ] @@ -5866,9 +5971,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "predicates" @@ -5886,9 +5994,9 @@ dependencies = [ [[package]] name = "predicates" -version = "3.1.0" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" +checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" dependencies = [ "anstyle", "difflib", @@ -5900,15 +6008,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" +checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" [[package]] name = "predicates-tree" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" dependencies = [ "predicates-core", "termtree", @@ -5960,11 +6068,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_edit 0.20.2", + "toml_edit 0.21.1", ] [[package]] @@ -5993,28 +6101,28 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" dependencies = [ "bit-set", - "bit-vec", - "bitflags 2.4.2", + "bit-vec 0.6.3", + "bitflags 2.6.0", "lazy_static", "num-traits", "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift 0.3.0", - "regex-syntax 0.8.2", + "regex-syntax 0.8.4", "rusty-fork", "tempfile", "unarray", @@ -6031,6 +6139,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "proptest-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff7ff745a347b87471d859a377a9a404361e7efc2a971d73424a6d183c0fc77" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + [[package]] name = "ptr_meta" version = "0.1.4" @@ -6088,9 +6207,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -6102,7 +6221,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" dependencies = [ "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "scheduled-thread-pool", ] @@ -6337,9 +6456,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -6377,14 +6496,6 @@ dependencies = [ "rand_core 0.3.1", ] -[[package]] -name = "records_coordinator" -version = "0.0.1" -dependencies = [ - "hdk", - "serde", -] - [[package]] name = "redox_syscall" version = "0.2.16" @@ -6403,11 +6514,20 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +dependencies = [ + "bitflags 2.6.0", +] + [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom 0.2.15", "libredox", @@ -6428,14 +6548,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.3" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -6449,13 +6569,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.4", ] [[package]] @@ -6466,20 +6586,20 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "region" -version = "3.0.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" +checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" dependencies = [ "bitflags 1.3.2", "libc", - "mach", - "winapi 0.3.9", + "mach2", + "windows-sys 0.52.0", ] [[package]] @@ -6493,9 +6613,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ "base64 0.22.1", "bytes", @@ -6507,6 +6627,7 @@ dependencies = [ "http-body 1.0.1", "http-body-util", "hyper 1.4.1", + "hyper-rustls", "hyper-tls", "hyper-util", "ipnet", @@ -6517,7 +6638,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile 2.1.2", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", @@ -6545,9 +6666,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.37" +version = "0.8.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" +checksum = "e12bc8d2f72df26a5d3178022df33720fbede0d31d82c7291662eff89836994d" dependencies = [ "bytemuck", ] @@ -6707,9 +6828,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.12.0" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b1d9521f889713d1221270fdd63370feca7e5c71a18745343402fa86e4f04f" +checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", @@ -6718,7 +6839,7 @@ dependencies = [ "fastrlp", "num-bigint", "num-traits", - "parity-scale-codec 3.6.3", + "parity-scale-codec 3.6.12", "primitive-types 0.12.2", "proptest", "rand 0.8.5", @@ -6731,9 +6852,9 @@ dependencies = [ [[package]] name = "ruint-macro" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" [[package]] name = "rusqlite" @@ -6741,7 +6862,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "fallible-iterator 0.3.0", "fallible-streaming-iterator", "hashlink", @@ -6751,9 +6872,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hex" @@ -6776,7 +6897,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.20", + "semver 1.0.23", ] [[package]] @@ -6795,14 +6916,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys 0.4.13", + "linux-raw-sys 0.4.14", "windows-sys 0.52.0", ] @@ -6832,6 +6953,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki 0.102.6", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.7.1" @@ -6839,7 +6973,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba" dependencies = [ "openssl-probe", - "rustls-pemfile 2.1.2", + "rustls-pemfile", "rustls-pki-types", "schannel", "security-framework", @@ -6847,18 +6981,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - -[[package]] -name = "rustls-pemfile" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" dependencies = [ "base64 0.22.1", "rustls-pki-types", @@ -6893,9 +7018,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "rusty-fork" @@ -6911,9 +7036,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safe_arch" @@ -6955,8 +7080,8 @@ dependencies = [ "rustls 0.22.4", "rustls-native-certs", "tokio", - "tokio-rustls", - "tokio-tungstenite 0.21.0", + "tokio-rustls 0.25.0", + "tokio-tungstenite", "tracing", "webpki-roots", ] @@ -6982,16 +7107,16 @@ dependencies = [ "anstyle", "base64 0.22.1", "bytes", - "clap 4.5.10", + "clap 4.5.13", "ed25519-dalek", "futures", "rand 0.8.5", "rustls 0.22.4", - "rustls-pemfile 2.1.2", + "rustls-pemfile", "slab", "tokio", - "tokio-rustls", - "tokio-tungstenite 0.21.0", + "tokio-rustls 0.25.0", + "tokio-tungstenite", ] [[package]] @@ -7009,7 +7134,7 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" dependencies = [ - "parking_lot 0.12.1", + "parking_lot 0.12.3", ] [[package]] @@ -7034,7 +7159,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -7065,12 +7190,12 @@ dependencies = [ [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -7092,7 +7217,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct 0.2.0", - "der 0.7.8", + "der 0.7.9", "generic-array 0.14.7", "pkcs8 0.10.2", "subtle", @@ -7101,11 +7226,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -7114,9 +7239,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" dependencies = [ "core-foundation-sys", "libc", @@ -7124,9 +7249,9 @@ dependencies = [ [[package]] name = "self_cell" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba" +checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" [[package]] name = "semver" @@ -7139,9 +7264,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] @@ -7186,9 +7311,9 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.14" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" dependencies = [ "serde", ] @@ -7211,7 +7336,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -7222,26 +7347,27 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] name = "serde_json" -version = "1.0.109" +version = "1.0.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9" +checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -7260,15 +7386,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.6", + "indexmap 2.3.0", "serde", "serde_derive", "serde_json", @@ -7278,14 +7404,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" dependencies = [ - "darling 0.20.8", + "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -7294,7 +7420,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "itoa", "ryu", "serde", @@ -7373,9 +7499,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac61da6b35ad76b195eb4771210f947734321a8d81d7738e1580d953bc7a15e" +checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" dependencies = [ "cc", "cfg-if 1.0.0", @@ -7400,6 +7526,15 @@ dependencies = [ "memmap2 0.6.2", ] +[[package]] +name = "shared_utils" +version = "0.0.1" +dependencies = [ + "hdi", + "holoom_types", + "serde", +] + [[package]] name = "shrinkwraprs" version = "0.3.0" @@ -7415,9 +7550,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -7442,15 +7577,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "signer_coordinator" -version = "0.0.1" -dependencies = [ - "hdk", - "holoom_types", - "serde", -] - [[package]] name = "simba" version = "0.6.0" @@ -7478,9 +7604,9 @@ checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" [[package]] name = "siphasher" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54ac45299ccbd390721be55b412d41931911f654fa99e2cb8bfb57184b2061fe" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" dependencies = [ "serde", ] @@ -7491,7 +7617,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", ] [[package]] @@ -7502,9 +7628,9 @@ checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" @@ -7518,9 +7644,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -7537,7 +7663,7 @@ dependencies = [ "num_cpus", "once_cell", "one_err", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "tokio", ] @@ -7579,16 +7705,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der 0.7.8", + "der 0.7.9", ] [[package]] name = "sqlformat" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" +checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f" dependencies = [ - "itertools 0.12.1", "nom", "unicode_categories", ] @@ -7638,31 +7763,31 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "structmeta" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ad9e09554f0456d67a69c1584c9798ba733a5b50349a6c0d0948710523922d" +checksum = "2e1575d8d40908d70f6fd05537266b90ae71b15dbbe7a8b7dffa2b759306d329" dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] name = "structmeta-derive" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" +checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -7758,9 +7883,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.52" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -7769,9 +7894,9 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "0.1.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" [[package]] name = "synstructure" @@ -7829,9 +7954,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" dependencies = [ "filetime", "libc", @@ -7840,9 +7965,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.14" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "task-motel" @@ -7851,20 +7976,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7228e85537ffb5943539a46bf561786323f6112114005ba055e496192a6f8f41" dependencies = [ "futures", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "tokio", "tracing", ] [[package]] name = "tempfile" -version = "3.10.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" dependencies = [ "cfg-if 1.0.0", - "fastrand 2.0.1", - "rustix 0.38.31", + "fastrand 2.1.0", + "once_cell", + "rustix 0.38.34", "windows-sys 0.52.0", ] @@ -7883,7 +8009,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ - "rustix 0.38.31", + "rustix 0.38.34", "windows-sys 0.48.0", ] @@ -7952,14 +8078,14 @@ dependencies = [ [[package]] name = "test-strategy" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8361c808554228ad09bfed70f5c823caf8a3450b6881cc3a38eb57e8c08c1d9" +checksum = "2bf41af45e3f54cc184831d629d41d5b2bda8297e29c81add7ae4f362ed5e01b" dependencies = [ "proc-macro2", "quote", "structmeta", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -7973,22 +8099,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -8043,9 +8169,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -8058,18 +8184,18 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.1" +version = "1.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d040ac2b29ab03b09d4129c2f5bbd012a3ac2f79d38ff506a4bf8dd34b0eac8a" +checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" dependencies = [ "backtrace", "bytes", "libc", "mio", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.6", + "socket2 0.5.7", "tokio-macros", "windows-sys 0.52.0", ] @@ -8082,7 +8208,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -8107,27 +8233,26 @@ dependencies = [ ] [[package]] -name = "tokio-stream" -version = "0.1.14" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "futures-core", - "pin-project-lite", + "rustls 0.23.12", + "rustls-pki-types", "tokio", - "tokio-util", ] [[package]] -name = "tokio-tungstenite" -version = "0.20.1" +name = "tokio-stream" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ - "futures-util", - "log", + "futures-core", + "pin-project-lite", "tokio", - "tungstenite 0.20.1", + "tokio-util", ] [[package]] @@ -8141,53 +8266,40 @@ dependencies = [ "rustls 0.22.4", "rustls-pki-types", "tokio", - "tokio-rustls", - "tungstenite 0.21.0", + "tokio-rustls 0.25.0", + "tungstenite", ] [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", -] - -[[package]] -name = "toml" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.19.15", ] [[package]] name = "toml" -version = "0.8.15" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.16", + "toml_edit 0.22.20", ] [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] @@ -8198,35 +8310,33 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.2.6", - "serde", - "serde_spanned", + "indexmap 2.3.0", "toml_datetime", "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "toml_datetime", "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.22.16" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.13", + "winnow 0.6.18", ] [[package]] @@ -8289,7 +8399,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -8385,29 +8495,10 @@ checksum = "c88cc88fd23b5a04528f3a8436024f20010a16ec18eb23c164b1242f65860130" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", "termcolor", ] -[[package]] -name = "tungstenite" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 0.2.12", - "httparse", - "log", - "rand 0.8.5", - "sha1", - "thiserror", - "url", - "utf-8", -] - [[package]] name = "tungstenite" version = "0.21.0" @@ -8431,9 +8522,9 @@ dependencies = [ [[package]] name = "tx5" -version = "0.1.0-beta" +version = "0.1.1-beta" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43c0b3457f7b3120fbdcb2e8247b7c9d7187f2d140341ea4264248289367e881" +checksum = "26078978741a1237fee7d124776de80c17649e68d7aba7b134d78706c5723b48" dependencies = [ "base64 0.22.1", "influxive-otel-atomic-obs", @@ -8447,9 +8538,9 @@ dependencies = [ [[package]] name = "tx5-connection" -version = "0.1.0-beta" +version = "0.1.1-beta" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75812e4b79f889675cca44e79f8e8f39a69c0df53a96bdc92b3e3955c07104c" +checksum = "ad420c899bbc0de3aa9d3a807a90b755af023e3e5b2e59610ab6cc3231efc416" dependencies = [ "bit_field", "tokio", @@ -8461,9 +8552,9 @@ dependencies = [ [[package]] name = "tx5-core" -version = "0.1.0-beta" +version = "0.1.1-beta" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48a97f9525ca81f320b0cddcba3ce8b8b16c6b7db65b2f3f1aa285119c423329" +checksum = "bb5b0fb40e1431da4750cdf91f781959cb468aaf6fd892a5ebaacb5e2f327130" dependencies = [ "app_dirs2", "base64 0.22.1", @@ -8480,12 +8571,12 @@ dependencies = [ [[package]] name = "tx5-go-pion" -version = "0.1.0-beta" +version = "0.1.1-beta" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b27f9fb5d0e10a333dc24ba2dfe9d6ddf7c913faa441a5319ea67ff66b6068d" +checksum = "dee6c3c85fdfcc4b76387024fd4e18296e58cca194ea2c9dd82061173a9cb666" dependencies = [ "futures", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "tokio", "tracing", "tx5-go-pion-sys", @@ -8494,9 +8585,9 @@ dependencies = [ [[package]] name = "tx5-go-pion-sys" -version = "0.1.0-beta" +version = "0.1.1-beta" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c3a98e21debbb837f73024ecdafa052b7cc9f516399cd934a3cd44ed0740c0" +checksum = "5823a9e4b1abbf68f818d2d48ec4c4e026a0856181eb982589ab4052b35675d4" dependencies = [ "Inflector", "base64 0.22.1", @@ -8513,9 +8604,9 @@ dependencies = [ [[package]] name = "tx5-signal" -version = "0.1.0-beta" +version = "0.1.1-beta" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40bfdbf14f0e3a53f15a6832d7e89864435a4ce522652c723121c701b57ee455" +checksum = "bca771cf1564e5d124cdf58d1cb469fcd5c6f5bc8c1e27235aefd176134a0020" dependencies = [ "rand 0.8.5", "sbd-e2e-crypto-client", @@ -8592,9 +8683,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" @@ -8657,9 +8748,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -8684,61 +8775,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] -name = "username_registry_coordinator" +name = "username_attestation" version = "0.0.1" dependencies = [ "bincode", "hdk", - "hex", - "holoom_types", - "indexmap 2.2.6", - "jaq_wrapper", - "serde", - "serde_json", - "username_registry_integrity", - "username_registry_utils", - "username_registry_validation", -] - -[[package]] -name = "username_registry_integrity" -version = "0.0.1" -dependencies = [ - "hdi", - "holoom_types", - "serde", - "username_registry_validation", -] - -[[package]] -name = "username_registry_utils" -version = "0.0.1" -dependencies = [ - "bincode", - "bs58 0.5.0", - "ed25519-dalek", - "hdi", - "holo_hash", + "holochain", "holoom_types", - "jaq_wrapper", "serde", + "shared_utils", + "tokio", + "username_attestation_integrity", ] [[package]] -name = "username_registry_validation" +name = "username_attestation_integrity" version = "0.0.1" dependencies = [ "bincode", - "bs58 0.5.0", - "ed25519-dalek", "hdi", - "holo_hash", "holoom_types", - "indexmap 2.2.6", - "jaq_wrapper", "serde", - "serde_json", - "username_registry_utils", + "shared_utils", ] [[package]] @@ -8749,9 +8807,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" @@ -8782,9 +8840,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec26a25bd6fca441cdd0f769fd7f891bae119f996de31f86a5eddccef54c1d" +checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" [[package]] name = "vcpkg" @@ -8800,9 +8858,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wait-timeout" @@ -8815,9 +8873,9 @@ dependencies = [ [[package]] name = "waker-fn" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" [[package]] name = "walkdir" @@ -8829,6 +8887,33 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wallet_attestation" +version = "0.0.1" +dependencies = [ + "bs58 0.5.1", + "ed25519-dalek", + "ethers-signers", + "hdk", + "holochain", + "holoom_types", + "serde", + "shared_utils", + "tokio", + "wallet_attestation_integrity", +] + +[[package]] +name = "wallet_attestation_integrity" +version = "0.0.1" +dependencies = [ + "bs58 0.5.1", + "hdi", + "holoom_types", + "serde", + "shared_utils", +] + [[package]] name = "want" version = "0.3.1" @@ -8840,30 +8925,28 @@ dependencies = [ [[package]] name = "warp" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e92e22e03ff1230c03a1a8ee37d2f89cd489e2e541b7550d6afad96faed169" +checksum = "4378d202ff965b011c64817db11d5829506d3404edeadb61f190d111da3f231c" dependencies = [ "bytes", "futures-channel", "futures-util", "headers", "http 0.2.12", - "hyper 0.14.28", + "hyper 0.14.30", "log", "mime", "mime_guess", "multer", "percent-encoding", "pin-project", - "rustls-pemfile 1.0.4", "scoped-tls", "serde", "serde_json", "serde_urlencoded", "tokio", - "tokio-stream", - "tokio-tungstenite 0.20.1", + "tokio-tungstenite", "tokio-util", "tower-service", "tracing", @@ -8902,7 +8985,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", "wasm-bindgen-shared", ] @@ -8936,7 +9019,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -9034,23 +9117,23 @@ dependencies = [ [[package]] name = "wasmer-config" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a0f70c177b1c5062cfe0f5308c3317751796fef9403c22a0cd7b4cacd4ccd8" +checksum = "4b4a632496950fde9ad821e195ef1a301440076f7c7d80de55239a140359bcbd" dependencies = [ "anyhow", "bytesize", "derive_builder 0.12.0", "hex", - "indexmap 2.2.6", + "indexmap 2.3.0", "schemars", - "semver 1.0.20", + "semver 1.0.23", "serde", "serde_cbor", "serde_json", "serde_yaml", "thiserror", - "toml 0.8.15", + "toml", "url", ] @@ -9117,7 +9200,7 @@ dependencies = [ "lazy_static", "libc", "mach", - "memoffset 0.9.0", + "memoffset 0.9.1", "more-asserts", "region", "scopeguard", @@ -9132,9 +9215,9 @@ version = "0.121.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" dependencies = [ - "bitflags 2.4.2", - "indexmap 2.2.6", - "semver 1.0.20", + "bitflags 2.6.0", + "indexmap 2.3.0", + "semver 1.0.23", ] [[package]] @@ -9170,12 +9253,12 @@ dependencies = [ [[package]] name = "webc" -version = "6.0.0-rc1" +version = "6.0.0-rc2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fc686c7b43c9bc630a499f6ae1f0a4c4bd656576a53ae8a147b0cc9bc983ad" +checksum = "fb3e2ccb43d303c5bd48f31db7a129481a9aaa5343d623f92951751df190df81" dependencies = [ "anyhow", - "base64 0.21.7", + "base64 0.22.1", "bytes", "cfg-if 1.0.0", "document-features", @@ -9183,7 +9266,7 @@ dependencies = [ "indexmap 1.9.3", "libc", "once_cell", - "semver 1.0.20", + "semver 1.0.23", "serde", "serde_cbor", "serde_json", @@ -9192,7 +9275,7 @@ dependencies = [ "tar", "tempfile", "thiserror", - "toml 0.7.8", + "toml", "url", "wasmer-config", ] @@ -9208,9 +9291,9 @@ dependencies = [ [[package]] name = "wide" -version = "0.7.25" +version = "0.7.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2caba658a80831539b30698ae9862a72db6697dfdd7151e46920f5f2755c3ce2" +checksum = "901e8597c777fa042e9e245bd56c0dc4418c5db3f845b6ff94fbac732c6a0692" dependencies = [ "bytemuck", "safe_arch", @@ -9240,11 +9323,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi 0.3.9", + "windows-sys 0.59.0", ] [[package]] @@ -9260,7 +9343,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core", - "windows-targets 0.52.4", + "windows-targets 0.52.6", ] [[package]] @@ -9269,7 +9352,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.6", ] [[package]] @@ -9309,7 +9392,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -9344,17 +9436,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -9371,9 +9464,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -9395,9 +9488,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -9419,9 +9512,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -9443,9 +9542,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -9467,9 +9566,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -9485,9 +9584,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -9509,9 +9608,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" @@ -9524,9 +9623,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.13" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] @@ -9563,8 +9662,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" dependencies = [ "libc", - "linux-raw-sys 0.4.13", - "rustix 0.38.31", + "linux-raw-sys 0.4.14", + "rustix 0.38.34", ] [[package]] @@ -9575,9 +9674,9 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "xxhash-rust" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63658493314859b4dfdf3fb8c1defd61587839def09582db50b8a4e93afca6bb" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" [[package]] name = "yansi" @@ -9596,29 +9695,30 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -9631,7 +9731,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -9648,16 +9748,16 @@ dependencies = [ [[package]] name = "zip" -version = "2.1.1" +version = "2.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd56a4d5921bc2f99947ac5b3abe5f510b1be7376fdc5e9fce4a23c6a93e87c" +checksum = "40dd8c92efc296286ce1fbd16657c5dbefff44f1b4ca01cc5f517d8b7b3d3e2e" dependencies = [ "arbitrary", "crc32fast", "crossbeam-utils", "displaydoc", "flate2", - "indexmap 2.2.6", + "indexmap 2.3.0", "memchr", "thiserror", "zopfli", diff --git a/Cargo.toml b/Cargo.toml index 99c5a37..3b6f01d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ opt-level = "z" [workspace] resolver = "2" -members = ["crates/*"] +members = ["crates/*/coordinator","crates/*/integrity"] [workspace.dependencies] hdi = "=0.5.0-dev.9" @@ -24,6 +24,7 @@ holochain = { version = "=0.4.0-dev.12", default-features = false, features = [ "test_utils", ] } holochain_keystore = "=0.4.0-dev.12" +holochain_integrity_types = "0.3" [workspace.dependencies.holoom_types] path = "crates/holoom_types" @@ -31,17 +32,45 @@ path = "crates/holoom_types" [workspace.dependencies.jaq_wrapper] path = "crates/jaq_wrapper" -[workspace.dependencies.username_registry_utils] -path = "crates/username_registry_utils" +[workspace.dependencies.shared_utils] +path = "crates/shared_utils" -[workspace.dependencies.username_registry_validation] -path = "crates/username_registry_validation" +[workspace.dependencies.shared_tests] +path = "crates/shared_tests" -[workspace.dependencies.username_registry_integrity] -path = "crates/username_registry_integrity" +[workspace.dependencies.username_attestation_coordinator] +path = "crates/username_attestation/coordinator" -[workspace.dependencies.username_registry_coordinator] -path = "crates/username_registry_coordinator" +[workspace.dependencies.username_attestation_integrity] +path = "crates/username_attestation/integrity" + +[workspace.dependencies.external_attestation] +path = "crates/external_attestation/coordinator" + +[workspace.dependencies.external_attestation_integrity] +path = "crates/external_attestation/integrity" + +[workspace.dependencies.wallet_attestation] +path = "crates/wallet_attestation/coordinator" + +[workspace.dependencies.wallet_attestation_integrity] +path = "crates/wallet_attestation/integrity" + +[workspace.dependencies.oracle_document] +path = "crates/oracle_document/coordinator" + +[workspace.dependencies.oracle_document_integrity] +path = "crates/oracle_document/integrity" + +[workspace.dependencies.holoom_recipe] +path = "crates/holoom_recipe/coordinator" + +[workspace.dependencies.holoom_recipe_integrity] +path = "crates/holoom_recipe/integrity" + +[workspace.dependencies.holoom_recipe_execution] +path = "crates/holoom_recipe_execution/coordinator" + +[workspace.dependencies.holoom_recipe_execution_integrity] +path = "crates/holoom_recipe_execution/integrity" -[workspace.dependencies.signer_coordinator] -path = "crates/signer_coordinator" diff --git a/crates/external_attestation/coordinator/Cargo.toml b/crates/external_attestation/coordinator/Cargo.toml new file mode 100644 index 0000000..a1018f9 --- /dev/null +++ b/crates/external_attestation/coordinator/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "external_attestation" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "external_attestation" + +[dependencies] +hdk = { workspace = true } +serde = { workspace = true } +holoom_types = { workspace = true } +shared_utils = { workspace = true } +external_attestation_integrity = { workspace = true } + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] #avoids mio bug +holochain = { workspace = true, default-features = false, features = ["test_utils"] } +tokio = "1.38.0" + diff --git a/crates/external_attestation/coordinator/src/external_attestation.rs b/crates/external_attestation/coordinator/src/external_attestation.rs new file mode 100644 index 0000000..50a6f3b --- /dev/null +++ b/crates/external_attestation/coordinator/src/external_attestation.rs @@ -0,0 +1,200 @@ +use hdk::prelude::*; +use holoom_types::{ + ConfirmExternalIdRequestPayload, ExternalIdAttestation, + IngestExternalIdAttestationRequestPayload, LocalHoloomSignal, RejectExternalIdRequestPayload, + RemoteHoloomSignal, SendExternalIdAttestationRequestPayload, +}; +use external_attestation_integrity::{EntryTypes, LinkTypes, UnitEntryTypes}; +use shared_utils::{get_authority_agent, hash_identifier}; + +#[hdk_extern] +pub fn send_external_id_attestation_request( + payload: SendExternalIdAttestationRequestPayload, +) -> ExternResult<()> { + let payload = IngestExternalIdAttestationRequestPayload { + request_id: payload.request_id, + code_verifier: payload.code_verifier, + code: payload.code, + }; + + let authority_agent = get_authority_agent()?; + + let zome_name = zome_info()?.name; + let fn_name = FunctionName::from("ingest_external_id_attestation_request"); + let resp = call_remote(authority_agent, zome_name, fn_name, None, payload)?; + match resp { + ZomeCallResponse::Ok(result) => result.decode().map_err(|err| wasm_error!(err)), + ZomeCallResponse::NetworkError(err) => Err(wasm_error!(WasmErrorInner::Guest(format!( + "There was a network error: {:?}", + err + )))), + ZomeCallResponse::Unauthorized(..) => { + Err(wasm_error!(WasmErrorInner::Guest("Unauthorized".into()))) + } + ZomeCallResponse::CountersigningSession(_) => Err(wasm_error!(WasmErrorInner::Guest( + "Unexpected countersigning session".into() + ))), + } +} + +/// Remote called by user seeking attestation +/// +/// Whether or not the request is successful is messaged via a callback +#[hdk_extern] +pub fn ingest_external_id_attestation_request( + payload: IngestExternalIdAttestationRequestPayload, +) -> ExternResult<()> { + let signal = LocalHoloomSignal::ExternalIdAttestationRequested { + request_id: payload.request_id, + requestor_pubkey: call_info()?.provenance, + code_verifier: payload.code_verifier, + code: payload.code, + }; + emit_signal(signal)?; + Ok(()) +} + + +//authority confirms the users request +#[hdk_extern] +pub fn confirm_external_id_request( + payload: ConfirmExternalIdRequestPayload, +) -> ExternResult { + let attestation = ExternalIdAttestation { + request_id: payload.request_id.clone(), + internal_pubkey: payload.requestor.clone(), + external_id: payload.external_id, + display_name: payload.display_name, + }; + let result = create_external_id_attestation(attestation); + let signal = match &result { + Ok(record) => RemoteHoloomSignal::ExternalIdAttested { + request_id: payload.request_id, + record: record.clone(), + }, + Err(err) => RemoteHoloomSignal::ExternalIdRejected { + request_id: payload.request_id, + reason: err.to_string(), + }, + }; + let signal_encoded = ExternIO::encode(signal) + .map_err(|err: SerializedBytesError| wasm_error!(WasmErrorInner::Serialize(err)))?; + let recipients = vec![payload.requestor]; + send_remote_signal(signal_encoded, recipients)?; + + result +} + +#[hdk_extern] +pub fn reject_external_id_request(payload: RejectExternalIdRequestPayload) -> ExternResult<()> { + let signal = RemoteHoloomSignal::ExternalIdRejected { + request_id: payload.request_id, + reason: payload.reason, + }; + let signal_encoded = ExternIO::encode(signal) + .map_err(|err: SerializedBytesError| wasm_error!(WasmErrorInner::Serialize(err)))?; + let recipients = vec![payload.requestor]; + send_remote_signal(signal_encoded, recipients)?; + + Ok(()) +} + +#[hdk_extern] +pub fn create_external_id_attestation(attestation: ExternalIdAttestation) -> ExternResult { + let agent = attestation.internal_pubkey.clone(); + let external_id_hash = hash_identifier(attestation.external_id.clone())?; + let attestation_action_hash = create_entry(EntryTypes::ExternalIdAttestation(attestation))?; + create_link( + agent, + attestation_action_hash.clone(), + LinkTypes::AgentToExternalIdAttestation, + (), + )?; + create_link( + external_id_hash, + attestation_action_hash.clone(), + LinkTypes::ExternalIdToAttestation, + (), + )?; + let record = get(attestation_action_hash, GetOptions::network())?.ok_or(wasm_error!( + WasmErrorInner::Guest(String::from( + "Could not find the newly created ExternalIdAttestation" + )) + ))?; + + Ok(record) +} + +#[hdk_extern] +pub fn get_external_id_attestation(external_id_ah: ActionHash) -> ExternResult> { + get(external_id_ah, GetOptions::network()) +} + +#[hdk_extern] +pub fn get_external_id_attestations_for_agent( + agent_pubkey: AgentPubKey, +) -> ExternResult> { + let mut links = get_links( + GetLinksInputBuilder::try_new(agent_pubkey, LinkTypes::AgentToExternalIdAttestation)? + .build(), + )?; + links.sort_by_key(|link| link.timestamp); + let maybe_records = links + .into_iter() + .map(|link| { + let action_hash = ActionHash::try_from(link.target).map_err(|_| { + wasm_error!(WasmErrorInner::Guest( + "ExternalIdToAttestation link doesn't point at action".into() + )) + })?; + get(action_hash, GetOptions::network()) + }) + .collect::>>()?; + Ok(maybe_records.into_iter().flatten().collect()) +} + + +#[hdk_extern] +pub fn get_attestation_for_external_id(external_id: String) -> ExternResult> { + let base = hash_identifier(external_id)?; + let mut links = get_links( + GetLinksInputBuilder::try_new(base, LinkTypes::ExternalIdToAttestation)?.build(), + )?; + links.sort_by_key(|link| link.timestamp); + let Some(link) = links.pop() else { + return Ok(None); + }; + let action_hash = ActionHash::try_from(link.target).map_err(|_| { + wasm_error!(WasmErrorInner::Guest( + "ExternalIdToAttestation link doesn't point at action".into() + )) + })?; + get(action_hash, GetOptions::network()) +} + +#[hdk_extern] +pub fn get_all_external_id_ahs(_: ()) -> ExternResult> { + if agent_info()?.agent_initial_pubkey != get_authority_agent()? { + return Err(wasm_error!(WasmErrorInner::Guest( + "Only callable by authority agent".into() + ))); + } + let entry_type: EntryType = UnitEntryTypes::ExternalIdAttestation + .try_into() + .expect("ExternalIdAttestation is an entry type"); + let filter = ChainQueryFilter::default() + .entry_type(entry_type) + .include_entries(false); + let ahs = query(filter)? + .into_iter() + .map(|record| record.action_address().to_owned()) + .collect(); + Ok(ahs) +} + +#[hdk_extern] +pub fn delete_external_id_attestation( + original_attestation_hash: ActionHash, +) -> ExternResult { + delete_entry(original_attestation_hash) +} diff --git a/crates/external_attestation/coordinator/src/lib.rs b/crates/external_attestation/coordinator/src/lib.rs new file mode 100644 index 0000000..96ea26d --- /dev/null +++ b/crates/external_attestation/coordinator/src/lib.rs @@ -0,0 +1,52 @@ +pub mod external_attestation; + +use hdk::prelude::*; +use holoom_types::{LocalHoloomSignal, RemoteHoloomSignal}; +use shared_utils::get_authority_agent; + +#[hdk_extern] +pub fn init(_: ()) -> ExternResult { + let authority_agent = get_authority_agent()?; + let my_pubkey = agent_info()?.agent_initial_pubkey; + let mut functions = BTreeSet::new(); + let zome_name = zome_info()?.name; + if my_pubkey == authority_agent { + functions.insert(( + zome_name.clone(), + "ingest_external_id_attestation_request".into(), + )); + } + functions.insert((zome_name, "recv_remote_signal".into())); + create_cap_grant(CapGrantEntry { + tag: "".into(), + access: ().into(), + functions: GrantedFunctions::Listed(functions), + })?; + + Ok(InitCallbackResult::Pass) +} + +#[hdk_extern] +fn recv_remote_signal(signal_io: ExternIO) -> ExternResult<()> { + let remote_holoom_signal: RemoteHoloomSignal = signal_io + .decode() + .map_err(|e| wasm_error!(WasmErrorInner::Serialize(e)))?; + + match remote_holoom_signal { + RemoteHoloomSignal::ExternalIdAttested { request_id, record } => { + emit_signal(LocalHoloomSignal::ExternalIdAttested { request_id, record })? + } + RemoteHoloomSignal::ExternalIdRejected { request_id, reason } => { + emit_signal(LocalHoloomSignal::ExternalIdRejected { request_id, reason })? + } + _=> () + + } + + Ok(()) +} + +#[hdk_extern] +fn get_authority(_: ()) -> ExternResult { + get_authority_agent() +} diff --git a/crates/external_attestation/coordinator/tests/config.rs b/crates/external_attestation/coordinator/tests/config.rs new file mode 100644 index 0000000..2fb7580 --- /dev/null +++ b/crates/external_attestation/coordinator/tests/config.rs @@ -0,0 +1,141 @@ +use std::time::Duration; + +use hdk::prelude::*; +use holochain::{ + conductor::{api::error::ConductorApiResult, config::ConductorConfig}, + prelude::DnaFile, + sweettest::{await_consistency, SweetAgents, SweetCell, SweetConductorBatch, SweetDnaFile}, +}; +use holoom_types::HoloomDnaProperties; + +//#[cfg(test)] +//mod tests; + +async fn load_dna() -> DnaFile { + // Use prebuilt dna file + let dna_path = std::env::current_dir() + .unwrap() + .join("../../../workdir/holoom.dna"); + + SweetDnaFile::from_bundle(&dna_path).await.unwrap() +} + +pub async fn holoom_dna_with_authority(authority_agent: &AgentPubKey) -> DnaFile { + let dna = load_dna().await; + let properties = SerializedBytes::try_from(HoloomDnaProperties { + authority_agent: authority_agent.to_string(), + }) + .unwrap(); + dna.update_modifiers(DnaModifiersOpt { + network_seed: None, + properties: Some(properties), + origin_time: None, + quantum_time: None, + }) +} + +pub struct TestSetup { + pub conductors: SweetConductorBatch, + cells: Vec, +} + +impl TestSetup { + pub async fn new(user_count: usize) -> Self { + // Set up conductors + let mut conductors: SweetConductorBatch = + SweetConductorBatch::from_config(1 + user_count, ConductorConfig::default()).await; + + let authority_agent_pubkey = SweetAgents::one(conductors[0].keystore()).await; + + let dnas = &[holoom_dna_with_authority(&authority_agent_pubkey).await]; + + let authority_app = conductors[0] + .setup_app_for_agent("holoom", authority_agent_pubkey.clone(), dnas) + .await + .unwrap(); + let (authority_cell,) = authority_app.into_tuple(); + let mut cells = Vec::from([authority_cell]); + for i in 1..1 + user_count { + let user_app = conductors[i].setup_app("holoom", dnas).await.unwrap(); + let (user_cell,) = user_app.into_tuple(); + cells.push(user_cell); + } + + TestSetup { conductors, cells } + } + + pub async fn authority_only() -> Self { + Self::new(0).await + } + + pub async fn authority_and_alice() -> Self { + Self::new(1).await + } + + //pub async fn authority_and_alice_bob() -> Self { + // Self::new(2).await + // } + + pub async fn authority_call( + &self, + zome_name: &str, + fn_name: &str, + payload: I, + ) -> ConductorApiResult + where + I: serde::Serialize + std::fmt::Debug, + O: serde::de::DeserializeOwned + std::fmt::Debug, + { + self.conductors[0] + .call_fallible(&self.cells[0].zome(zome_name), fn_name, payload) + .await + } + + pub async fn alice_call( + &self, + zome_name: &str, + fn_name: &str, + payload: I, + ) -> ConductorApiResult + where + I: serde::Serialize + std::fmt::Debug, + O: serde::de::DeserializeOwned + std::fmt::Debug, + { + self.conductors[1] + .call_fallible(&self.cells[1].zome(zome_name), fn_name, payload) + .await + } + + /* pub async fn bob_call( + &self, + zome_name: &str, + fn_name: &str, + payload: I, + ) -> ConductorApiResult + where + I: serde::Serialize + std::fmt::Debug, + O: serde::de::DeserializeOwned + std::fmt::Debug, + { + self.conductors[2] + .call_fallible(&self.cells[2].zome(zome_name), fn_name, payload) + .await + } */ + + //pub fn authority_pubkey(&self) -> AgentPubKey { + // self.cells[0].agent_pubkey().clone() + // } + + pub fn alice_pubkey(&self) -> AgentPubKey { + self.cells[1].agent_pubkey().clone() + } + + //pub fn bob_pubkey(&self) -> AgentPubKey { + // self.cells[1].agent_pubkey().clone() + // } + + pub async fn consistency(&self) { + await_consistency(Duration::from_secs(60), self.cells.iter()) + .await + .unwrap(); + } +} diff --git a/crates/external_attestation/coordinator/tests/external_id_attestation.rs b/crates/external_attestation/coordinator/tests/external_id_attestation.rs new file mode 100644 index 0000000..ec3b2e7 --- /dev/null +++ b/crates/external_attestation/coordinator/tests/external_id_attestation.rs @@ -0,0 +1,318 @@ +use hdk::prelude::*; +use holochain::conductor::api::error::ConductorApiError; +use holoom_types::{ConfirmExternalIdRequestPayload, ExternalIdAttestation}; +mod config; +use crate::config::TestSetup; + + +#[cfg(test)] + + +#[tokio::test(flavor = "multi_thread")] +async fn only_authority_can_create_external_id_attestation() { + let setup = TestSetup::authority_and_alice().await; + + // Authority creates a external id Attestation for alice + let _: Record = setup + .authority_call( + "external_attestation", + "create_external_id_attestation", + ExternalIdAttestation { + request_id: "1234".into(), + internal_pubkey: setup.alice_pubkey(), + external_id: "4546".into(), + display_name: "alice".into() + }, + ) + .await + .unwrap(); + + // Alice cannot create an external id Attestation + let result: Result = setup + .alice_call( + "external_attestation", + "create_external_id_attestation", + ExternalIdAttestation { + request_id: "9876".into(), + internal_pubkey: setup.alice_pubkey(), + external_id: "abcd".into(), + display_name: "alice2".into() + }, + ) + .await; + + assert!(result.is_err()); +} + + + +#[tokio::test(flavor = "multi_thread")] +async fn only_authority_can_confirm_request() { + let setup = TestSetup::authority_and_alice().await; + + let _: Record = setup + .authority_call( + "external_attestation", + "confirm_external_id_request", + ConfirmExternalIdRequestPayload { + request_id:"1234".into(), + external_id: "4567".into(), + display_name: "alice".into(), + requestor: setup.alice_pubkey() + }) + .await + .unwrap(); + + let result2: Result = setup + .alice_call( + "external_attestation", + "confirm_external_id_request", + ConfirmExternalIdRequestPayload { + request_id:"1234".into(), + external_id: "4567".into(), + display_name: "alice".into(), + requestor: setup.alice_pubkey() + }) + .await; + assert!(result2.is_err()); +} + + +#[tokio::test(flavor = "multi_thread")] +async fn nobody_can_delete_external_id_attestation() { + let setup = TestSetup::authority_and_alice().await; + setup.conductors.exchange_peer_info().await; + + // Authority creates a external_id Attestation + let record: Record = setup + .authority_call( + "external_attestation", + "create_external_id_attestation", + ExternalIdAttestation { + request_id: "1234".into(), + internal_pubkey: fake_agent_pubkey_1(), + external_id: "4546".into(), + display_name: "alice".into() + }, + ) + .await + .unwrap(); + + setup.consistency().await; + + // Authority cannot delete a external_id Attestation + let result: Result = setup + .authority_call( + "external_attestation", + "delete_external_id_attestation", + record.action_address(), + ) + .await; + + assert!(result.is_err()); + + // Alice cannot delete a external_id Attestation + let result2: Result = setup + .alice_call( + "external_attestation", + "delete_external_id_attestation", + record.action_address(), + ) + .await; + + assert!(result2.is_err()); +} + + + +#[tokio::test(flavor = "multi_thread")] +async fn all_can_get_external_id_attestations() { + let setup = TestSetup::authority_and_alice().await; + setup.conductors.exchange_peer_info().await; + + // Authority creates an external_id Attestation + let record: Record = setup + .authority_call( + "external_attestation", + "create_external_id_attestation", + ExternalIdAttestation { + request_id: "1234".into(), + internal_pubkey: fake_agent_pubkey_1(), + external_id: "4546".into(), + display_name: "alice".into() + }, + ) + .await + .unwrap(); + + setup.consistency().await; + + // Authority gets the external_id Attestation + let maybe_record: Option = setup + .authority_call( + "external_attestation", + "get_external_id_attestation", + record.action_address(), + ) + .await + .unwrap(); + + assert!(maybe_record.is_some()); + + // Alice gets the external_id Attestation + let maybe_record2: Option = setup + .alice_call( + "external_attestation", + "get_external_id_attestation", + record.action_address(), + ) + .await + .unwrap(); + + assert!(maybe_record2.is_some()); +} + + +#[tokio::test(flavor = "multi_thread")] +async fn all_can_get_external_id_attestation_for_agent() { + let setup = TestSetup::authority_and_alice().await; + setup.conductors.exchange_peer_info().await; + + // Authority's complete list of attestations initially empty + let all_records1: Vec = setup + .authority_call("external_attestation", "get_all_external_id_ahs", ()) + .await + .unwrap(); + assert_eq!(all_records1, vec![]); + + // Authority creates an external_id Attestation + let _: Record = setup + .authority_call( + "external_attestation", + "create_external_id_attestation", + ExternalIdAttestation { + request_id: "1234".into(), + internal_pubkey: setup.alice_pubkey(), + external_id: "4546".into(), + display_name: "alice".into() + }, + ) + .await + .unwrap(); + + // Authority gets the external_id Attestation + let maybe_record: Option = setup + .authority_call( + "external_attestation", + "get_attestation_for_external_id", + "4546".to_string() + ) + .await + .unwrap(); + let entry = maybe_record + .clone() + .unwrap() + .entry() + .to_app_option::() + .unwrap() + .unwrap(); + + assert_eq!(entry.external_id, "4546"); + assert_eq!(entry.internal_pubkey, setup.alice_pubkey()); + + // Alice gets the external_id Attestation + setup.consistency().await; + + let maybe_vector_record: Vec = setup + .alice_call( + "external_attestation", + "get_external_id_attestations_for_agent", + setup.alice_pubkey(), + ) + .await + .unwrap(); + let entry2 = maybe_vector_record.first() + .unwrap() + .entry() + .to_app_option::() + .unwrap() + .unwrap(); + + assert_eq!(entry2.external_id, "4546"); + assert_eq!(entry2.internal_pubkey, setup.alice_pubkey()); + + // Authority can see the attestation in their complete list + let all_records2: Vec = setup + .authority_call("external_attestation", "get_all_external_id_ahs", ()) + .await + .unwrap(); + + let first_record: Record = maybe_vector_record.first().unwrap().clone(); + + let search_record: Record = setup + .authority_call("external_attestation", "get_external_id_attestation", first_record.action_address()) + .await + .unwrap(); + assert_eq!(all_records2.first().unwrap(), search_record.action_address()); +} + + + +#[tokio::test(flavor = "multi_thread")] +async fn cannot_get_external_id_attestation_for_agent_that_doesnt_exist() { + let setup = TestSetup::authority_only().await; + + // Authority tries to get external_id Attestation + let res: Vec> = setup + .authority_call( + "external_attestation", + "get_external_id_attestations_for_agent", + fake_agent_pubkey_1(), + ) + .await + .unwrap(); + + assert!(res.is_empty()); +} + + +//this test anticipates future code changes that change the behaviour +//of allowing another pub key to use the same external id +// commented for now + +/*#[tokio::test(flavor = "multi_thread")] +async fn same_external_id_cannot_be_registered_twice_from_another_user() { + // Set up conductors + let setup = TestSetup::authority_only().await; + + // Authority creates an external id attestation + let _: Record = setup + .authority_call( + "external_attestation", + "create_external_id_attestation", + ExternalIdAttestation { + request_id: "1234".into(), + internal_pubkey: fake_agent_pubkey_1(), + external_id: "4546".into(), + display_name: "alice".into() + }, + ) + .await + .unwrap(); + + // Authority creates a UsernameAttestation with an identical username + let result: Result = setup + .authority_call( + "external_attestation", + "create_external_id_attestation", + ExternalIdAttestation { + request_id: "1234".into(), + internal_pubkey: fake_agent_pubkey_2(), + external_id: "4546".into(), + display_name: "bob".into() + }, + ) + .await; + + assert!(result.is_err()); +}*/ diff --git a/crates/external_attestation/integrity/Cargo.toml b/crates/external_attestation/integrity/Cargo.toml new file mode 100644 index 0000000..1aa8311 --- /dev/null +++ b/crates/external_attestation/integrity/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "external_attestation_integrity" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "external_attestation_integrity" + +[dependencies] +hdi = { workspace = true } +serde = { workspace = true } +holoom_types = { workspace = true } +shared_utils = { workspace = true } +#external_attestation_validation = { workspace = true } + diff --git a/crates/external_attestation/integrity/src/agent_external_id_attestation.rs b/crates/external_attestation/integrity/src/agent_external_id_attestation.rs new file mode 100644 index 0000000..19176a8 --- /dev/null +++ b/crates/external_attestation/integrity/src/agent_external_id_attestation.rs @@ -0,0 +1,42 @@ +use hdi::prelude::*; +use holoom_types::ExternalIdAttestation; +use shared_utils::get_authority_agent; + +pub fn validate_create_link_agent_to_external_id_attestations( + action: CreateLink, + _base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + // Only the authority can create link + let authority_agent = get_authority_agent()?; + if action.author != authority_agent { + return Ok(ValidateCallbackResult::Invalid( + "Only the Username Registry Authority can create external ID attestation links".into(), + )); + } + + // Check the entry type for the given action hash + let action_hash = ActionHash::try_from(target_address).map_err(|e| wasm_error!(e))?; + let record = must_get_valid_record(action_hash)?; + let _external_id_attestation: ExternalIdAttestation = record + .entry() + .to_app_option() + .map_err(|e| wasm_error!(e))? + .ok_or(wasm_error!(WasmErrorInner::Guest(String::from( + "Linked action must reference an entry" + ))))?; + + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_delete_link_agent_to_external_id_attestations( + _action: DeleteLink, + _original_action: CreateLink, + _base: AnyLinkableHash, + _target: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + Ok(ValidateCallbackResult::Invalid(String::from( + "External ID Attestation links cannot be deleted", + ))) +} diff --git a/crates/external_attestation/integrity/src/entry_types.rs b/crates/external_attestation/integrity/src/entry_types.rs new file mode 100644 index 0000000..b2dc3bc --- /dev/null +++ b/crates/external_attestation/integrity/src/entry_types.rs @@ -0,0 +1,25 @@ +use hdi::prelude::*; +use holoom_types::ExternalIdAttestation; +use crate::external_id_attestation::*; +//use external_attestation_validation::*; + +#[derive(Serialize, Deserialize)] +#[serde(tag = "type")] +#[hdk_entry_types] +#[unit_enum(UnitEntryTypes)] +pub enum EntryTypes { + ExternalIdAttestation(ExternalIdAttestation), +} + +impl EntryTypes { + pub fn validate_create(self, action: Create) -> ExternResult { + match self { + EntryTypes::ExternalIdAttestation(external_id_attestation) => { + validate_create_external_id_attestation( + EntryCreationAction::Create(action), + external_id_attestation, + ) + } + } + } +} diff --git a/crates/external_attestation/integrity/src/external_id_attestation.rs b/crates/external_attestation/integrity/src/external_id_attestation.rs new file mode 100644 index 0000000..8165eb6 --- /dev/null +++ b/crates/external_attestation/integrity/src/external_id_attestation.rs @@ -0,0 +1,18 @@ +use hdi::prelude::*; +use holoom_types::ExternalIdAttestation; +use shared_utils::get_authority_agent; + +pub fn validate_create_external_id_attestation( + action: EntryCreationAction, + _external_id_attestation: ExternalIdAttestation, +) -> ExternResult { + // Only the authority can publish + let authority_agent = get_authority_agent()?; + if action.author() != &authority_agent { + return Ok(ValidateCallbackResult::Invalid( + "Only the Username Registry Authority can create external ID attestations".into(), + )); + } + + Ok(ValidateCallbackResult::Valid) +} diff --git a/crates/external_attestation/integrity/src/external_id_to_attestation.rs b/crates/external_attestation/integrity/src/external_id_to_attestation.rs new file mode 100644 index 0000000..4aa48a1 --- /dev/null +++ b/crates/external_attestation/integrity/src/external_id_to_attestation.rs @@ -0,0 +1,49 @@ +use hdi::prelude::*; +use holoom_types::ExternalIdAttestation; +use shared_utils::{get_authority_agent, hash_identifier}; + +pub fn validate_create_link_external_id_to_attestation( + action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + // Only the authority can create link + let authority_agent = get_authority_agent()?; + if action.author != authority_agent { + return Ok(ValidateCallbackResult::Invalid( + "Only the Username Registry Authority can create external ID attestation links".into(), + )); + } + + // Check the entry type for the given action hash + let action_hash = ActionHash::try_from(target_address).map_err(|e| wasm_error!(e))?; + let record = must_get_valid_record(action_hash)?; + let external_id_attestation: ExternalIdAttestation = record + .entry() + .to_app_option() + .map_err(|e| wasm_error!(e))? + .ok_or(wasm_error!(WasmErrorInner::Guest(String::from( + "Linked action must reference an entry" + ))))?; + + let expected_base_address = hash_identifier(external_id_attestation.external_id)?; + if AnyLinkableHash::from(expected_base_address) != base_address { + return Ok(ValidateCallbackResult::Invalid( + "ExternalIdToAttestation base_address not derived from external_id".into(), + )); + } + + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_delete_link_external_id_to_attestation( + _action: DeleteLink, + _original_action: CreateLink, + _base: AnyLinkableHash, + _target: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + Ok(ValidateCallbackResult::Invalid(String::from( + "External ID Attestation links cannot be deleted", + ))) +} diff --git a/crates/external_attestation/integrity/src/lib.rs b/crates/external_attestation/integrity/src/lib.rs new file mode 100644 index 0000000..6ac7366 --- /dev/null +++ b/crates/external_attestation/integrity/src/lib.rs @@ -0,0 +1,140 @@ +use hdi::prelude::*; +pub mod entry_types; +pub use entry_types::*; +pub mod link_types; +pub use link_types::*; +pub mod agent_external_id_attestation; +pub use agent_external_id_attestation::*; +pub mod external_id_attestation; +pub use external_id_attestation::*; +pub mod external_id_to_attestation; +pub use external_id_to_attestation::*; + +#[hdk_extern] +pub fn genesis_self_check(_data: GenesisSelfCheckData) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_agent_joining( + _agent_pub_key: AgentPubKey, + _membrane_proof: &Option, +) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} +#[hdk_extern] +pub fn validate(op: Op) -> ExternResult { + match op.flattened::()? { + FlatOp::StoreEntry(store_entry) => match store_entry { + OpEntry::CreateEntry { app_entry, action } => app_entry.validate_create(action), + OpEntry::UpdateEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + _ => Ok(ValidateCallbackResult::Valid), + }, + FlatOp::RegisterUpdate(update_entry) => match update_entry { + OpUpdate::Entry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + _ => Ok(ValidateCallbackResult::Valid), + }, + FlatOp::RegisterDelete(_) => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be deleted".into(), + )), + FlatOp::RegisterCreateLink { + link_type, + base_address, + target_address, + tag, + action, + } => link_type.validate_create(action, base_address, target_address, tag), + FlatOp::RegisterDeleteLink { + link_type, + base_address, + target_address, + tag, + original_action, + action, + } => link_type.validate_delete(action, original_action, base_address, target_address, tag), + FlatOp::StoreRecord(store_record) => { + match store_record { + OpRecord::CreateEntry { app_entry, action } => app_entry.validate_create(action), + OpRecord::UpdateEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + OpRecord::DeleteEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be deleted".into(), + )), + OpRecord::CreateLink { + base_address, + target_address, + tag, + link_type, + action, + } => link_type.validate_create(action, base_address, target_address, tag), + OpRecord::DeleteLink { + original_action_hash, + base_address, + action, + } => { + let record = must_get_valid_record(original_action_hash)?; + let create_link = match record.action() { + Action::CreateLink(create_link) => create_link.clone(), + _ => { + return Ok(ValidateCallbackResult::Invalid( + "The action that a DeleteLink deletes must be a CreateLink" + .to_string(), + )); + } + }; + let link_type = match LinkTypes::from_type( + create_link.zome_index, + create_link.link_type, + )? { + Some(lt) => lt, + None => { + // @todo This must be treated as valid due to holochain bug + // see https://github.com/holochain/holochain/issues/2868 + return Ok(ValidateCallbackResult::Valid); + } + }; + link_type.validate_delete( + action, + create_link.clone(), + base_address, + create_link.target_address, + create_link.tag, + ) + } + OpRecord::CreatePrivateEntry { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdatePrivateEntry { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CreateCapClaim { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CreateCapGrant { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdateCapClaim { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdateCapGrant { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::Dna { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::OpenChain { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CloseChain { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::InitZomesComplete { .. } => Ok(ValidateCallbackResult::Valid), + _ => Ok(ValidateCallbackResult::Valid), + } + } + FlatOp::RegisterAgentActivity(agent_activity) => match agent_activity { + OpActivity::CreateAgent { agent, action } => { + let previous_action = must_get_action(action.prev_action)?; + match previous_action.action() { + Action::AgentValidationPkg( + AgentValidationPkg { membrane_proof, .. }, + ) => validate_agent_joining(agent, membrane_proof), + _ => { + Ok( + ValidateCallbackResult::Invalid( + "The previous action for a `CreateAgent` action must be an `AgentValidationPkg`" + .to_string(), + ), + ) + } + } + } + _ => Ok(ValidateCallbackResult::Valid), + }, + } +} diff --git a/crates/external_attestation/integrity/src/link_types.rs b/crates/external_attestation/integrity/src/link_types.rs new file mode 100644 index 0000000..a000928 --- /dev/null +++ b/crates/external_attestation/integrity/src/link_types.rs @@ -0,0 +1,67 @@ +use hdi::prelude::*; +use crate::agent_external_id_attestation::*; +use crate::external_id_to_attestation::*; +//use external_attestation_validation::*; + +#[derive(Serialize, Deserialize)] +#[hdk_link_types] +pub enum LinkTypes { + AgentToExternalIdAttestation, + ExternalIdToAttestation, + +} + +impl LinkTypes { + pub fn validate_create( + self, + action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + tag: LinkTag, + ) -> ExternResult { + match self { + LinkTypes::AgentToExternalIdAttestation => { + validate_create_link_agent_to_external_id_attestations( + action, + base_address, + target_address, + tag, + ) + } + LinkTypes::ExternalIdToAttestation => validate_create_link_external_id_to_attestation( + action, + base_address, + target_address, + tag, + ), + } + } + + pub fn validate_delete( + self, + action: DeleteLink, + original_action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + tag: LinkTag, + ) -> ExternResult { + match self { + LinkTypes::AgentToExternalIdAttestation => { + validate_delete_link_agent_to_external_id_attestations( + action, + original_action, + base_address, + target_address, + tag, + ) + } + LinkTypes::ExternalIdToAttestation => validate_delete_link_external_id_to_attestation( + action, + original_action, + base_address, + target_address, + tag, + ), + } + } +} diff --git a/crates/holoom_recipe/coordinator/Cargo.toml b/crates/holoom_recipe/coordinator/Cargo.toml new file mode 100644 index 0000000..50eb8bc --- /dev/null +++ b/crates/holoom_recipe/coordinator/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "holoom_recipe" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "holoom_recipe" + +[dependencies] +hdk = { workspace = true } +serde = { workspace = true } +holoom_types = { workspace = true } +shared_utils = { workspace = true } +holoom_recipe_integrity = { workspace = true } + + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] #avoids mio bug +holochain = { workspace = true, default-features = false, features = ["test_utils"] } +tokio = "1.38.0" +#ethers-signers = { workspace = true } +#ed25519-dalek = { workspace = true } +#bs58 = { workspace = true } + diff --git a/crates/holoom_recipe/coordinator/src/holoom_recipe.rs b/crates/holoom_recipe/coordinator/src/holoom_recipe.rs new file mode 100644 index 0000000..10d1867 --- /dev/null +++ b/crates/holoom_recipe/coordinator/src/holoom_recipe.rs @@ -0,0 +1,13 @@ +use hdk::prelude::*; +use holoom_types::Recipe; +use holoom_recipe_integrity::EntryTypes; + +#[hdk_extern] +pub fn create_recipe(recipe: Recipe) -> ExternResult { + let recipe_ah = create_entry(EntryTypes::Recipe(recipe))?; + let record = get(recipe_ah, GetOptions::network())?.ok_or(wasm_error!( + WasmErrorInner::Guest(String::from("Could not find the newly created Recipe")) + ))?; + + Ok(record) +} diff --git a/crates/holoom_recipe/coordinator/src/lib.rs b/crates/holoom_recipe/coordinator/src/lib.rs new file mode 100644 index 0000000..c5234f6 --- /dev/null +++ b/crates/holoom_recipe/coordinator/src/lib.rs @@ -0,0 +1,48 @@ +pub mod holoom_recipe; +use hdk::prelude::*; +use holoom_types::{LocalHoloomSignal, RemoteHoloomSignal}; +use shared_utils::get_authority_agent; + +#[hdk_extern] +pub fn init(_: ()) -> ExternResult { + let authority_agent = get_authority_agent()?; + let my_pubkey = agent_info()?.agent_initial_pubkey; + let mut functions = BTreeSet::new(); + let zome_name = zome_info()?.name; + if my_pubkey == authority_agent { + } + functions.insert((zome_name, "recv_remote_signal".into())); + create_cap_grant(CapGrantEntry { + tag: "".into(), + access: ().into(), + functions: GrantedFunctions::Listed(functions), + })?; + + Ok(InitCallbackResult::Pass) +} + +#[hdk_extern] +fn recv_remote_signal(signal_io: ExternIO) -> ExternResult<()> { + let remote_holoom_signal: RemoteHoloomSignal = signal_io + .decode() + .map_err(|e| wasm_error!(WasmErrorInner::Serialize(e)))?; + match remote_holoom_signal { + RemoteHoloomSignal::EvmSignatureProvided { + request_id, + signed_u256_array, + } => emit_signal(LocalHoloomSignal::EvmSignatureProvided { + request_id, + signed_u256_array, + })?, + RemoteHoloomSignal::EvmSignatureRequestRejected { request_id, reason } => { + emit_signal(LocalHoloomSignal::EvmSignatureRequestRejected { request_id, reason })? + } + _=> () + } + Ok(()) +} + +#[hdk_extern] +fn get_authority(_: ()) -> ExternResult { + get_authority_agent() +} diff --git a/crates/holoom_recipe/coordinator/tests/config.rs b/crates/holoom_recipe/coordinator/tests/config.rs new file mode 100644 index 0000000..54eaab9 --- /dev/null +++ b/crates/holoom_recipe/coordinator/tests/config.rs @@ -0,0 +1,141 @@ +use std::time::Duration; + +use hdk::prelude::*; +use holochain::{ + conductor::{api::error::ConductorApiResult, config::ConductorConfig}, + prelude::DnaFile, + sweettest::{await_consistency, SweetAgents, SweetCell, SweetConductorBatch, SweetDnaFile}, +}; +use holoom_types::HoloomDnaProperties; + +//#[cfg(test)] +//mod tests; + +async fn load_dna() -> DnaFile { + // Use prebuilt dna file + let dna_path = std::env::current_dir() + .unwrap() + .join("../../../workdir/holoom.dna"); + + SweetDnaFile::from_bundle(&dna_path).await.unwrap() +} + +pub async fn holoom_dna_with_authority(authority_agent: &AgentPubKey) -> DnaFile { + let dna = load_dna().await; + let properties = SerializedBytes::try_from(HoloomDnaProperties { + authority_agent: authority_agent.to_string(), + }) + .unwrap(); + dna.update_modifiers(DnaModifiersOpt { + network_seed: None, + properties: Some(properties), + origin_time: None, + quantum_time: None, + }) +} + +pub struct TestSetup { + pub conductors: SweetConductorBatch, + cells: Vec, +} + +impl TestSetup { + pub async fn new(user_count: usize) -> Self { + // Set up conductors + let mut conductors: SweetConductorBatch = + SweetConductorBatch::from_config(1 + user_count, ConductorConfig::default()).await; + + let authority_agent_pubkey = SweetAgents::one(conductors[0].keystore()).await; + + let dnas = &[holoom_dna_with_authority(&authority_agent_pubkey).await]; + + let authority_app = conductors[0] + .setup_app_for_agent("holoom", authority_agent_pubkey.clone(), dnas) + .await + .unwrap(); + let (authority_cell,) = authority_app.into_tuple(); + let mut cells = Vec::from([authority_cell]); + for i in 1..1 + user_count { + let user_app = conductors[i].setup_app("holoom", dnas).await.unwrap(); + let (user_cell,) = user_app.into_tuple(); + cells.push(user_cell); + } + + TestSetup { conductors, cells } + } + + pub async fn authority_only() -> Self { + Self::new(0).await + } + + pub async fn authority_and_alice() -> Self { + Self::new(1).await + } + + //pub async fn authority_and_alice_bob() -> Self { + // Self::new(2).await + // } + + pub async fn authority_call( + &self, + zome_name: &str, + fn_name: &str, + payload: I, + ) -> ConductorApiResult + where + I: serde::Serialize + std::fmt::Debug, + O: serde::de::DeserializeOwned + std::fmt::Debug, + { + self.conductors[0] + .call_fallible(&self.cells[0].zome(zome_name), fn_name, payload) + .await + } + + pub async fn alice_call( + &self, + zome_name: &str, + fn_name: &str, + payload: I, + ) -> ConductorApiResult + where + I: serde::Serialize + std::fmt::Debug, + O: serde::de::DeserializeOwned + std::fmt::Debug, + { + self.conductors[1] + .call_fallible(&self.cells[1].zome(zome_name), fn_name, payload) + .await + } + + /*pub async fn bob_call( + &self, + zome_name: &str, + fn_name: &str, + payload: I, + ) -> ConductorApiResult + where + I: serde::Serialize + std::fmt::Debug, + O: serde::de::DeserializeOwned + std::fmt::Debug, + { + self.conductors[2] + .call_fallible(&self.cells[2].zome(zome_name), fn_name, payload) + .await + }*/ + + pub fn authority_pubkey(&self) -> AgentPubKey { + self.cells[0].agent_pubkey().clone() + } + + pub fn alice_pubkey(&self) -> AgentPubKey { + self.cells[1].agent_pubkey().clone() + } + + //pub fn bob_pubkey(&self) -> AgentPubKey { + // self.cells[1].agent_pubkey().clone() + //} + + pub async fn consistency(&self) { + await_consistency(Duration::from_secs(60), self.cells.iter()) + .await + .unwrap(); + } +} diff --git a/crates/holoom_recipe/coordinator/tests/recipe.rs b/crates/holoom_recipe/coordinator/tests/recipe.rs new file mode 100644 index 0000000..45861cc --- /dev/null +++ b/crates/holoom_recipe/coordinator/tests/recipe.rs @@ -0,0 +1,364 @@ +use hdk::prelude::*; + +use holochain::conductor::api::error::ConductorApiResult; +use holoom_types::{ + recipe::{ + ExecuteRecipePayload, JqInstructionArgumentNames, Recipe, RecipeArgument, + RecipeArgumentType, RecipeExecution, RecipeInstruction, RecipeInstructionExecution, + }, + ExternalIdAttestation, OracleDocument, +}; +use shared_utils::deserialize_record_entry; + +mod config; +use config::TestSetup; + +#[cfg(test)] + +#[tokio::test(flavor = "multi_thread")] +async fn can_execute_basic_recipe() { + let setup = TestSetup::authority_and_alice().await; + setup.conductors.exchange_peer_info().await; + + // Materials: + + // Doc: foo/1234 -> { value: 1, owner: "1234" } + // Doc: foo/5678 -> { value: 4, owner: "5678" } + // Doc: foo -> [foo/1234, foo/5678] + // ExternalId: authority_agent_pub_key -> { id: 1234, display_name: "some-user-1" } + // ExternalId: alice_agent_pub_key -> { id: 5678, display_name: "some-user-2" } + + // Recipe: + // Calculate value share of caller + // { + // "$arguments": [{ name" "greeting", type: "string" }], + // "foo_name_list_name": { inst: "get_doc", var_name: `"foo"` }, + // "foo_name_list": { inst: "get_docs", var_name: `"foo"` }, + // "foos": { inst: "get_docs", var_name: "foo_name_list" }, + // "caller_external_id": { inst: "get_caller_external_id" }, + // "$return": { + // inst: "jq", + // input_vars: ["foos", "caller_external_id", "greeting"], + // program: ` + // .caller_external_id.external_id as $id | + // .foos as $foos | + // "\(.greeting) \(.caller_external_id.display_name)" as $msg | + // [$foos[].value] | add as $total | + // $foos[] | select(.owner==$id) | .value / $total | + // { share: ., msg: $msg } + // ` + // } + // } + + // Expected outputs: + // Authority with greeting: 'Hi' -> { share: 0.2, msg: "Hi some-user-1" } + // Alice with greeting: 'Hello' -> { share: 0.8, msg: "Hello some-user-2" } + + let _foo1_record: Record = setup + .authority_call( + "oracle_document", + "create_oracle_document", + OracleDocument { + name: "foo/1234".into(), + json_data: "{\"value\":1,\"owner\":\"1234\"}".into(), + }, + ) + .await + .unwrap(); + + let _foo2_record: Record = setup + .authority_call( + "oracle_document", + "create_oracle_document", + OracleDocument { + name: "foo/5678".into(), + json_data: "{\"value\":4,\"owner\":\"5678\"}".into(), + }, + ) + .await + .unwrap(); + + let _foo_name_list_record: Record = setup + .authority_call( + "oracle_document", + "create_oracle_document", + OracleDocument { + name: "foo".into(), + json_data: "[\"foo/1234\",\"foo/5678\"]".into(), + }, + ) + .await + .unwrap(); + + let res: ConductorApiResult = setup + .authority_call( + "external_attestation", + "create_external_id_attestation", + ExternalIdAttestation { + request_id: "".into(), + internal_pubkey: setup.authority_pubkey(), + external_id: "1234".into(), + display_name: "some-user-1".into(), + }, + ) + .await; + assert!(res.is_ok()); + + let res: ConductorApiResult = setup + .authority_call( + "external_attestation", + "create_external_id_attestation", + ExternalIdAttestation { + request_id: "".into(), + internal_pubkey: setup.alice_pubkey(), + external_id: "5678".into(), + display_name: "some-user-2".into(), + }, + ) + .await; + assert!(res.is_ok()); + + let recipe_record: Record = setup + .authority_call( + "holoom_recipe", + "create_recipe", + Recipe { + trusted_authors: vec![setup.authority_pubkey()], + arguments: vec![("greeting".into(),RecipeArgumentType::String)], + instructions: vec![ + ( + "foo_name_list_name".into(), + RecipeInstruction::Constant { + value: "\"foo\"".into(), + }, + ), + ( + "foo_name_list".into(), + RecipeInstruction::GetLatestDocWithIdentifier { + var_name: "foo_name_list_name".into(), + }, + ), + ( + "foos".into(), + RecipeInstruction::GetDocsListedByVar { + var_name: "foo_name_list".into(), + }, + ), + ( + "caller_external_id".into(), + RecipeInstruction::GetLatestCallerExternalId, + ), + ( + "$return".into(), + RecipeInstruction::Jq { + input_var_names: JqInstructionArgumentNames::List{var_names: vec!["foos".into(),"caller_external_id".into(), "greeting".into()]}, + program: ".caller_external_id.external_id as $id | .foos as $foos | \"\\(.greeting) \\(.caller_external_id.display_name)\" as $msg | [$foos[].value] | add as $total | $foos[] | select(.owner==$id) | .value / $total | { share: ., msg: $msg }".into() + } + ) + ], + }, + ) + .await + .unwrap(); + + // Make sure both agents know recipe + setup.consistency().await; + + let authority_execution_record: Record = setup + .authority_call( + "holoom_recipe_execution", + "execute_recipe", + ExecuteRecipePayload { + recipe_ah: recipe_record.action_address().clone(), + arguments: vec![RecipeArgument::String { value: "Hi".into() }], + }, + ) + .await + .unwrap(); + + let authority_execution: RecipeExecution = + deserialize_record_entry(authority_execution_record).unwrap(); + assert_eq!( + authority_execution.output, + String::from("{\"share\":0.2,\"msg\":\"Hi some-user-1\"}") + ); + + let alice_execution_record: Record = setup + .alice_call( + "holoom_recipe_execution", + "execute_recipe", + ExecuteRecipePayload { + recipe_ah: recipe_record.action_address().clone(), + arguments: vec![RecipeArgument::String { + value: "Hello".into(), + }], + }, + ) + .await + .unwrap(); + + let alice_execution: RecipeExecution = + deserialize_record_entry(alice_execution_record).unwrap(); + assert_eq!( + alice_execution.output, + String::from("{\"share\":0.8,\"msg\":\"Hello some-user-2\"}") + ); + + // Alice's untrusted document isn't able to censor the outcome + + let _alice_foo_name_list_record: Record = setup + .alice_call( + "oracle_document", + "create_oracle_document", + OracleDocument { + name: "foo".into(), + json_data: "[\"foo/5678\"]".into(), + }, + ) + .await + .unwrap(); + + let alice_execution_record2: Record = setup + .alice_call( + "holoom_recipe_execution", + "execute_recipe", + ExecuteRecipePayload { + recipe_ah: recipe_record.action_address().clone(), + arguments: vec![RecipeArgument::String { + value: "Hello".into(), + }], + }, + ) + .await + .unwrap(); + + let alice_execution2: RecipeExecution = + deserialize_record_entry(alice_execution_record2).unwrap(); + // Result should be unchanged, rather than the dishonestly attempted alteration of: + // { "share": 1, "msg": "Hello some-user-2" } + assert_eq!( + alice_execution2.output, + String::from("{\"share\":0.8,\"msg\":\"Hello some-user-2\"}") + ); +} + +#[tokio::test(flavor = "multi_thread")] +async fn cannot_use_untrusted_docs() { + let setup = TestSetup::authority_only().await; + + let single_doc_recipe_record: Record = setup + .authority_call( + "holoom_recipe", + "create_recipe", + Recipe { + trusted_authors: vec![fake_agent_pub_key(0)], + arguments: vec![], + instructions: vec![ + ( + "doc_name".into(), + RecipeInstruction::Constant { + value: "\"foo\"".into(), + }, + ), + ( + "$return".into(), + RecipeInstruction::GetLatestDocWithIdentifier { + var_name: "doc_name".into(), + }, + ), + ], + }, + ) + .await + .unwrap(); + + let doc_record: Record = setup + .authority_call( + "oracle_document", + "create_oracle_document", + OracleDocument { + name: "foo".into(), + json_data: "\"suspicious\"".into(), + }, + ) + .await + .unwrap(); + + let result: ConductorApiResult = setup + .authority_call( + "holoom_recipe_execution", + "create_recipe_execution", + RecipeExecution { + recipe_ah: single_doc_recipe_record.action_address().clone(), + arguments: Vec::new(), + instruction_executions: vec![ + RecipeInstructionExecution::Constant, + RecipeInstructionExecution::GetLatestDocWithIdentifier { + doc_ah: doc_record.action_address().clone(), + }, + ], + output: "\"suspicious\"".into(), + }, + ) + .await; + match result { + Ok(_) => { + panic!("Execution should be invalid"); + } + Err(err) => { + assert!(err.to_string().contains("Untrusted author")) + } + } + + let doc_list_recipe_record: Record = setup + .authority_call( + "holoom_recipe", + "create_recipe", + Recipe { + trusted_authors: vec![fake_agent_pub_key(0)], + arguments: vec![], + instructions: vec![ + ( + "doc_names".into(), + RecipeInstruction::Constant { + value: "[\"foo\"]".into(), + }, + ), + ( + "$return".into(), + RecipeInstruction::GetDocsListedByVar { + var_name: "doc_names".into(), + }, + ), + ], + }, + ) + .await + .unwrap(); + + let result: ConductorApiResult = setup + .authority_call( + "holoom_recipe_execution", + "create_recipe_execution", + RecipeExecution { + recipe_ah: doc_list_recipe_record.action_address().clone(), + arguments: Vec::new(), + instruction_executions: vec![ + RecipeInstructionExecution::Constant, + RecipeInstructionExecution::GetDocsListedByVar { + doc_ahs: vec![doc_record.action_address().clone()], + }, + ], + output: "[\"suspicious\"]".into(), + }, + ) + .await; + match result { + Ok(_) => { + panic!("Execution should be invalid"); + } + Err(err) => { + assert!(err.to_string().contains("Untrusted author")) + } + } +} diff --git a/crates/holoom_recipe/integrity/Cargo.toml b/crates/holoom_recipe/integrity/Cargo.toml new file mode 100644 index 0000000..d68a7e8 --- /dev/null +++ b/crates/holoom_recipe/integrity/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "holoom_recipe_integrity" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "holoom_recipe_integrity" + +[dependencies] +hdi = { workspace = true } +serde = { workspace = true } +holoom_types = { workspace = true } +shared_utils = { workspace = true } +jaq_wrapper = { workspace = true } + diff --git a/crates/holoom_recipe/integrity/src/entry_types.rs b/crates/holoom_recipe/integrity/src/entry_types.rs new file mode 100644 index 0000000..d20d3f9 --- /dev/null +++ b/crates/holoom_recipe/integrity/src/entry_types.rs @@ -0,0 +1,22 @@ +use hdi::prelude::*; +use holoom_types::recipe::Recipe; +use crate::holoom_recipe::*; +//use external_attestation_validation::*; + +#[derive(Serialize, Deserialize)] +#[serde(tag = "type")] +#[hdk_entry_types] +#[unit_enum(UnitEntryTypes)] +pub enum EntryTypes { + Recipe(Recipe), +} + +impl EntryTypes { + pub fn validate_create(self, action: Create) -> ExternResult { + match self { + EntryTypes::Recipe(recipe) => { + validate_create_recipe(EntryCreationAction::Create(action), recipe) + } + } + } +} diff --git a/crates/username_registry_validation/src/recipe.rs b/crates/holoom_recipe/integrity/src/holoom_recipe.rs similarity index 100% rename from crates/username_registry_validation/src/recipe.rs rename to crates/holoom_recipe/integrity/src/holoom_recipe.rs diff --git a/crates/holoom_recipe/integrity/src/lib.rs b/crates/holoom_recipe/integrity/src/lib.rs new file mode 100644 index 0000000..ea5c0fc --- /dev/null +++ b/crates/holoom_recipe/integrity/src/lib.rs @@ -0,0 +1,139 @@ +use hdi::prelude::*; +pub mod entry_types; +pub use entry_types::*; +pub mod link_types; +pub use link_types::*; +pub mod holoom_recipe; +pub use holoom_recipe::*; +pub mod name_to_recipe; +pub use name_to_recipe::*; + + +#[hdk_extern] +pub fn genesis_self_check(_data: GenesisSelfCheckData) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_agent_joining( + _agent_pub_key: AgentPubKey, + _membrane_proof: &Option, +) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} +#[hdk_extern] +pub fn validate(op: Op) -> ExternResult { + match op.flattened::()? { + FlatOp::StoreEntry(store_entry) => match store_entry { + OpEntry::CreateEntry { app_entry, action } => app_entry.validate_create(action), + OpEntry::UpdateEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + _ => Ok(ValidateCallbackResult::Valid), + }, + FlatOp::RegisterUpdate(update_entry) => match update_entry { + OpUpdate::Entry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + _ => Ok(ValidateCallbackResult::Valid), + }, + FlatOp::RegisterDelete(_) => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be deleted".into(), + )), + FlatOp::RegisterCreateLink { + link_type, + base_address, + target_address, + tag, + action, + } => link_type.validate_create(action, base_address, target_address, tag), + FlatOp::RegisterDeleteLink { + link_type, + base_address, + target_address, + tag, + original_action, + action, + } => link_type.validate_delete(action, original_action, base_address, target_address, tag), + FlatOp::StoreRecord(store_record) => { + match store_record { + OpRecord::CreateEntry { app_entry, action } => app_entry.validate_create(action), + OpRecord::UpdateEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + OpRecord::DeleteEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be deleted".into(), + )), + OpRecord::CreateLink { + base_address, + target_address, + tag, + link_type, + action, + } => link_type.validate_create(action, base_address, target_address, tag), + OpRecord::DeleteLink { + original_action_hash, + base_address, + action, + } => { + let record = must_get_valid_record(original_action_hash)?; + let create_link = match record.action() { + Action::CreateLink(create_link) => create_link.clone(), + _ => { + return Ok(ValidateCallbackResult::Invalid( + "The action that a DeleteLink deletes must be a CreateLink" + .to_string(), + )); + } + }; + let link_type = match LinkTypes::from_type( + create_link.zome_index, + create_link.link_type, + )? { + Some(lt) => lt, + None => { + // @todo This must be treated as valid due to holochain bug + // see https://github.com/holochain/holochain/issues/2868 + return Ok(ValidateCallbackResult::Valid); + } + }; + link_type.validate_delete( + action, + create_link.clone(), + base_address, + create_link.target_address, + create_link.tag, + ) + } + OpRecord::CreatePrivateEntry { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdatePrivateEntry { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CreateCapClaim { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CreateCapGrant { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdateCapClaim { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdateCapGrant { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::Dna { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::OpenChain { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CloseChain { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::InitZomesComplete { .. } => Ok(ValidateCallbackResult::Valid), + _ => Ok(ValidateCallbackResult::Valid), + } + } + FlatOp::RegisterAgentActivity(agent_activity) => match agent_activity { + OpActivity::CreateAgent { agent, action } => { + let previous_action = must_get_action(action.prev_action)?; + match previous_action.action() { + Action::AgentValidationPkg( + AgentValidationPkg { membrane_proof, .. }, + ) => validate_agent_joining(agent, membrane_proof), + _ => { + Ok( + ValidateCallbackResult::Invalid( + "The previous action for a `CreateAgent` action must be an `AgentValidationPkg`" + .to_string(), + ), + ) + } + } + } + _ => Ok(ValidateCallbackResult::Valid), + }, + } +} diff --git a/crates/holoom_recipe/integrity/src/link_types.rs b/crates/holoom_recipe/integrity/src/link_types.rs new file mode 100644 index 0000000..6875df8 --- /dev/null +++ b/crates/holoom_recipe/integrity/src/link_types.rs @@ -0,0 +1,43 @@ +use hdi::prelude::*; +use crate::name_to_recipe::*; + +#[derive(Serialize, Deserialize)] +#[hdk_link_types] +pub enum LinkTypes { + NameToRecipe +} + +impl LinkTypes { + pub fn validate_create( + self, + action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + tag: LinkTag, + ) -> ExternResult { + match self { + LinkTypes::NameToRecipe => { + validate_create_link_name_to_recipe(action, base_address, target_address, tag) + } + } + } + + pub fn validate_delete( + self, + action: DeleteLink, + original_action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + tag: LinkTag, + ) -> ExternResult { + match self { + LinkTypes::NameToRecipe => validate_delete_link_name_to_recipe( + action, + original_action, + base_address, + target_address, + tag, + ), + } + } +} diff --git a/crates/username_registry_validation/src/name_to_recipe.rs b/crates/holoom_recipe/integrity/src/name_to_recipe.rs similarity index 100% rename from crates/username_registry_validation/src/name_to_recipe.rs rename to crates/holoom_recipe/integrity/src/name_to_recipe.rs diff --git a/crates/holoom_recipe_execution/coordinator/Cargo.toml b/crates/holoom_recipe_execution/coordinator/Cargo.toml new file mode 100644 index 0000000..cc5f5e0 --- /dev/null +++ b/crates/holoom_recipe_execution/coordinator/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "holoom_recipe_execution" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "holoom_recipe_execution" + +[dependencies] +hdk = { workspace = true } +serde = { workspace = true } +holoom_types = { workspace = true } +shared_utils = { workspace = true } +holoom_recipe_execution_integrity = { workspace = true } +indexmap = "2.2.6" +jaq_wrapper = { workspace = true } +external_attestation = { workspace = true} +oracle_document = {workspace = true} + + +#[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] #avoids mio bug +#holochain = { workspace = true, default-features = false, features = ["test_utils"] } +#tokio = "1.38.0" + + diff --git a/crates/holoom_recipe_execution/coordinator/src/holoom_recipe_execution.rs b/crates/holoom_recipe_execution/coordinator/src/holoom_recipe_execution.rs new file mode 100644 index 0000000..98361f8 --- /dev/null +++ b/crates/holoom_recipe_execution/coordinator/src/holoom_recipe_execution.rs @@ -0,0 +1,279 @@ +use std::{collections::HashMap, rc::Rc}; + +use hdk::prelude::*; +use holoom_types::{recipe::*, ExternalIdAttestation, OracleDocument}; +use indexmap::IndexMap; +use jaq_wrapper::{compile_filter, parse_single_json, run_filter, Val}; +use holoom_recipe_execution_integrity::EntryTypes; +use shared_utils::deserialize_record_entry; +//use external_attestation::external_attestation::get_external_id_attestations_for_agent; +//use oracle_document::oracle_document::{ get_latest_oracle_document_ah_for_name, get_latest_oracle_document_for_name}; + +//use crate::{ + //external_attestation::get_external_id_attestations_for_agent, + // oracle_document::{ + // get_latest_oracle_document_ah_for_name, get_latest_oracle_document_for_name, + // }, +//}; + +#[hdk_extern] +pub fn create_recipe_execution(recipe_execution: RecipeExecution) -> ExternResult { + let recipe_execution_ah = create_entry(EntryTypes::RecipeExecution(recipe_execution))?; + let record = get(recipe_execution_ah, GetOptions::network())?.ok_or(wasm_error!( + WasmErrorInner::Guest(String::from( + "Could not find the newly created RecipeExecution" + )) + ))?; + + Ok(record) +} + +#[hdk_extern] +pub fn execute_recipe(payload: ExecuteRecipePayload) -> ExternResult { + let recipe_record = get(payload.recipe_ah.clone(), GetOptions::network())?.ok_or( + wasm_error!(WasmErrorInner::Guest("Recipe not found".into())), + )?; + let recipe: Recipe = deserialize_record_entry(recipe_record)?; + + let mut vars: HashMap = HashMap::default(); + let mut instruction_executions: Vec = Vec::default(); + + if payload.arguments.len() != recipe.arguments.len() { + return Err(wasm_error!(WasmErrorInner::Guest( + "Incorrect number of arguments".into() + ))); + } + for (arg, (arg_name, arg_type)) in payload.arguments.iter().zip(recipe.arguments) { + let val = match (arg, arg_type) { + (RecipeArgument::String { value }, RecipeArgumentType::String) => { + Val::str(value.clone()) + } + (RecipeArgument::EvmAddress { value }, RecipeArgumentType::EvmAddress) => { + Val::str(value.to_string()) + } + _ => { + return Err(wasm_error!(WasmErrorInner::Guest( + "Bad recipe argument".into() + ))) + } + }; + vars.insert(arg_name, val); + } + + for (out_var_name, instruction) in recipe.instructions { + if vars.contains_key(&out_var_name) { + unreachable!("Bad impl: A valid Recipe doesn't reassign vars"); + } + let (val, instruction_execution) = match instruction { + RecipeInstruction::Constant { value } => { + let val = parse_single_json(&value)?; + (val, RecipeInstructionExecution::Constant) + } + RecipeInstruction::GetCallerAgentPublicKey => { + let val = Val::Str(Rc::new(agent_info()?.agent_initial_pubkey.to_string())); + (val, RecipeInstructionExecution::GetCallerAgentPublicKey) + } + RecipeInstruction::GetDocsListedByVar { var_name } => { + let list_val = vars + .get(&var_name) + .expect("Bad impl: A valid recipe doesn't use unassigned vars"); + let Val::Arr(item_vals) = list_val else { + return Err(wasm_error!(WasmErrorInner::Guest(format!( + "var '{}' expected to contain array", + &var_name + )))); + }; + let doc_ahs = item_vals + .iter() + .map(|val| { + let Val::Str(identifier) = val else { + return Err(wasm_error!(WasmErrorInner::Guest(format!( + "var '{}' expected to contain array of string elements", + &var_name + )))); + }; + get_latest_oracle_document_ah_for_name( + ExecuteOracleRecipePayload { name:identifier.as_ref().clone(), + trusted:recipe.trusted_authors, + }.into()?)? + .ok_or(wasm_error!(WasmErrorInner::Guest( + format!("No OracleDocument for identifier '{}'", &identifier) + ))) + }) + .collect::>>()?; + let doc_vals = doc_ahs + .iter() + .map(|doc_ah| { + let doc_record = get(doc_ah.clone(), GetOptions::network())?.ok_or( + wasm_error!(WasmErrorInner::Guest("OracleDocument not found".into())), + )?; + let doc: OracleDocument = deserialize_record_entry(doc_record)?; + let val = parse_single_json(&doc.json_data)?; + Ok(val) + }) + .collect::>>()?; + let val = Val::arr(doc_vals); + let instruction_execution = + RecipeInstructionExecution::GetDocsListedByVar { doc_ahs }; + (val, instruction_execution) + } + RecipeInstruction::GetLatestCallerExternalId => { + let mut attestation_records = + get_external_id_attestations_for_agent(SerializedBytes::try_from(agent_info()?.agent_initial_pubkey))?; + let attestation_record = + attestation_records + .pop() + .ok_or(wasm_error!(WasmErrorInner::Guest( + "Agent has no External ID Attestations".into() + )))?; + let attestation_ah = attestation_record.action_address().clone(); + let attestation: ExternalIdAttestation = + deserialize_record_entry(attestation_record)?; + let val = Val::obj(IndexMap::from([ + ( + Rc::new(String::from("agent_pubkey")), + Val::str(attestation.internal_pubkey.to_string()), + ), + ( + Rc::new(String::from("external_id")), + Val::str(attestation.external_id), + ), + ( + Rc::new(String::from("display_name")), + Val::str(attestation.display_name), + ), + ])); + let instruction_execution = + RecipeInstructionExecution::GetLatestCallerExternalId { attestation_ah }; + (val, instruction_execution) + } + RecipeInstruction::GetLatestDocWithIdentifier { var_name } => { + let identifier_val = vars + .get(&var_name) + .expect("Bad impl: A valid recipe doesn't use unassigned vars"); + let Val::Str(identifier) = identifier_val else { + return Err(wasm_error!(WasmErrorInner::Guest(format!( + "var '{}' expected to contain string", + &var_name + )))); + }; + let doc_record = get_latest_oracle_document_for_name( + ExecuteOracleRecipePayload { name:identifier.as_ref().clone(), + trusted:recipe.trusted_authors, + }.into()?)? + .ok_or(wasm_error!(WasmErrorInner::Guest(format!( + "No OracleDocument found for identifier '{}'", + identifier + ))))?; + let doc_ah = doc_record.action_address().clone(); + let doc: OracleDocument = deserialize_record_entry(doc_record)?; + let val = parse_single_json(&doc.json_data)?; + let instruction_execution = + RecipeInstructionExecution::GetLatestDocWithIdentifier { doc_ah }; + (val, instruction_execution) + } + RecipeInstruction::Jq { + input_var_names, + program, + } => { + let input_val = match input_var_names { + JqInstructionArgumentNames::Single { var_name } => vars + .get(&var_name) + .expect("Bad impl: A valid recipe doesn't use unassigned vars") + .clone(), + JqInstructionArgumentNames::List { var_names } => { + let map: IndexMap, Val> = var_names + .into_iter() + .map(|var_name| { + let val = vars + .get(&var_name) + .expect("Bad impl: A valid recipe doesn't use unassigned vars") + .clone(); + (Rc::new(var_name), val) + }) + .collect(); + Val::obj(map) + } + }; + let filter = compile_filter(&program)?; + let val = run_filter(filter, input_val)?; + let instruction_execution = RecipeInstructionExecution::Jq; + (val, instruction_execution) + } + }; + vars.insert(out_var_name, val); + instruction_executions.push(instruction_execution) + } + + let return_val = vars + .remove("$return") + .expect("Bad impl: A valid recipe has a $return"); + let output = return_val.to_string(); + + let recipe_execution = RecipeExecution { + recipe_ah: payload.recipe_ah, + arguments: payload.arguments, + instruction_executions, + output, + }; + + create_recipe_execution(recipe_execution) +} + + +fn get_latest_oracle_document_ah_for_name(payload: SerializedBytes) -> ExternResult>{ + let call_response = call(CallTargetCell::Local, ZomeName::from("oracle_document"), FunctionName("get_latest_oracle_document_ah_for_name".into()), None, payload)?; + match call_response { + ZomeCallResponse::Ok(result) => { // Of type ExternIO, wrapper around byte array + //let posts: Vec = result.decode().map_err(|err| wasm_error!(err))?; + let data: Option> = result.decode().map_err(|err| wasm_error!(err))?; + //debug!("{:?}",data.signed_action.into()); + return Ok(data) + }, + ZomeCallResponse::NetworkError(err) => { + Err(wasm_error!(WasmErrorInner::Guest(format!("There was a network error: {:?}", err))))? + }, + _ => Err(wasm_error!(WasmErrorInner::Guest( + "Failed to handle remote call".into() + )))? + } + Err(wasm_error!(WasmErrorInner::Guest("no data returned".into()))) +} + +fn get_latest_oracle_document_for_name(payload: SerializedBytes) -> ExternResult>{ + let call_response = call(CallTargetCell::Local, ZomeName::from("oracle_document"), FunctionName("get_latest_oracle_document_for_name".into()), None, payload)?; + match call_response { + ZomeCallResponse::Ok(result) => { // Of type ExternIO, wrapper around byte array + //let posts: Vec = result.decode().map_err(|err| wasm_error!(err))?; + let data: Option = result.decode().map_err(|err| wasm_error!(err))?; + //debug!("{:?}",data.signed_action.into()); + return Ok(data) + }, + ZomeCallResponse::NetworkError(err) => { + Err(wasm_error!(WasmErrorInner::Guest(format!("There was a network error: {:?}", err))))? + }, + _ => Err(wasm_error!(WasmErrorInner::Guest( + "Failed to handle remote call".into() + )))? + } + Err(wasm_error!(WasmErrorInner::Guest("no data returned".into()))) +} + +fn get_external_id_attestations_for_agent(payload: SerializedBytes) -> ExternResult>{ + let call_response = call(CallTargetCell::Local, ZomeName::from("external_attestation"), FunctionName("get_external_id_attestations_for_agent".into()), None, payload)?; + match call_response { + ZomeCallResponse::Ok(result) => { // Of type ExternIO, wrapper around byte array + //let posts: Vec = result.decode().map_err(|err| wasm_error!(err))?; + let data: Vec = result.decode().map_err(|err| wasm_error!(err))?; + //debug!("{:?}",data.signed_action.into()); + return Ok(data) + }, + ZomeCallResponse::NetworkError(err) => { + Err(wasm_error!(WasmErrorInner::Guest(format!("There was a network error: {:?}", err))))? + }, + _ => Err(wasm_error!(WasmErrorInner::Guest( + "Failed to handle remote call".into() + )))? + } + Err(wasm_error!(WasmErrorInner::Guest("no data returned".into()))) +} \ No newline at end of file diff --git a/crates/holoom_recipe_execution/coordinator/src/lib.rs b/crates/holoom_recipe_execution/coordinator/src/lib.rs new file mode 100644 index 0000000..b534867 --- /dev/null +++ b/crates/holoom_recipe_execution/coordinator/src/lib.rs @@ -0,0 +1,52 @@ +pub mod holoom_recipe_execution; +use hdk::prelude::*; +use holoom_types::{LocalHoloomSignal, RemoteHoloomSignal}; +use shared_utils::get_authority_agent; + +#[hdk_extern] +pub fn init(_: ()) -> ExternResult { + let authority_agent = get_authority_agent()?; + let my_pubkey = agent_info()?.agent_initial_pubkey; + let mut functions = BTreeSet::new(); + let zome_name = zome_info()?.name; + if my_pubkey == authority_agent { + functions.insert(( + zome_name.clone(), + "ingest_evm_signature_over_recipe_execution_request".into(), + )); + } + functions.insert((zome_name, "recv_remote_signal".into())); + create_cap_grant(CapGrantEntry { + tag: "".into(), + access: ().into(), + functions: GrantedFunctions::Listed(functions), + })?; + + Ok(InitCallbackResult::Pass) +} + +#[hdk_extern] +fn recv_remote_signal(signal_io: ExternIO) -> ExternResult<()> { + let remote_holoom_signal: RemoteHoloomSignal = signal_io + .decode() + .map_err(|e| wasm_error!(WasmErrorInner::Serialize(e)))?; + match remote_holoom_signal { + RemoteHoloomSignal::EvmSignatureProvided { + request_id, + signed_u256_array, + } => emit_signal(LocalHoloomSignal::EvmSignatureProvided { + request_id, + signed_u256_array, + })?, + RemoteHoloomSignal::EvmSignatureRequestRejected { request_id, reason } => { + emit_signal(LocalHoloomSignal::EvmSignatureRequestRejected { request_id, reason })? + } + _=> () + } + Ok(()) +} + +#[hdk_extern] +fn get_authority(_: ()) -> ExternResult { + get_authority_agent() +} diff --git a/crates/holoom_recipe_execution/integrity/Cargo.toml b/crates/holoom_recipe_execution/integrity/Cargo.toml new file mode 100644 index 0000000..b16d8d6 --- /dev/null +++ b/crates/holoom_recipe_execution/integrity/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "holoom_recipe_execution_integrity" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "holoom_recipe_execution_integrity" + +[dependencies] +hdi = { workspace = true } +serde = { workspace = true } +holoom_types = { workspace = true } +shared_utils = { workspace = true } +jaq_wrapper = { workspace = true } +indexmap = "2.2.6" + + diff --git a/crates/holoom_recipe_execution/integrity/src/entry_types.rs b/crates/holoom_recipe_execution/integrity/src/entry_types.rs new file mode 100644 index 0000000..cd744f7 --- /dev/null +++ b/crates/holoom_recipe_execution/integrity/src/entry_types.rs @@ -0,0 +1,23 @@ +use hdi::prelude::*; +use holoom_types::recipe::RecipeExecution; +use crate::holoom_recipe_execution::*; +//use external_attestation_validation::*; + +#[derive(Serialize, Deserialize)] +#[serde(tag = "type")] +#[hdk_entry_types] +#[unit_enum(UnitEntryTypes)] +pub enum EntryTypes { + RecipeExecution(RecipeExecution), +} + +impl EntryTypes { + pub fn validate_create(self, action: Create) -> ExternResult { + match self { + EntryTypes::RecipeExecution(recipe_execution) => validate_create_recipe_execution( + EntryCreationAction::Create(action), + recipe_execution, + ), + } + } +} diff --git a/crates/holoom_recipe_execution/integrity/src/holoom_recipe_execution.rs b/crates/holoom_recipe_execution/integrity/src/holoom_recipe_execution.rs new file mode 100644 index 0000000..6344fd6 --- /dev/null +++ b/crates/holoom_recipe_execution/integrity/src/holoom_recipe_execution.rs @@ -0,0 +1,231 @@ +use std::{collections::HashMap, rc::Rc}; + +use hdi::prelude::*; +use holoom_types::{ + recipe::{ + JqInstructionArgumentNames, Recipe, RecipeArgument, RecipeArgumentType, RecipeExecution, + RecipeInstruction, RecipeInstructionExecution, + }, + ExternalIdAttestation, OracleDocument, +}; +use indexmap::IndexMap; +use jaq_wrapper::{compile_filter, parse_single_json, run_filter, Val}; +use shared_utils::deserialize_record_entry; + +pub fn validate_create_recipe_execution( + action: EntryCreationAction, + recipe_execution: RecipeExecution, +) -> ExternResult { + let recipe_record = must_get_valid_record(recipe_execution.recipe_ah)?; + let recipe: Recipe = deserialize_record_entry(recipe_record)?; + + let mut vars: HashMap = HashMap::default(); + + if recipe_execution.arguments.len() != recipe.arguments.len() { + return Ok(ValidateCallbackResult::Invalid( + "Incorrect number of arguments".into(), + )); + } + + for (arg, (arg_name, arg_type)) in recipe_execution + .arguments + .into_iter() + .zip(recipe.arguments.into_iter()) + { + let val = match (arg, arg_type) { + (RecipeArgument::String { value }, RecipeArgumentType::String) => { + Val::str(value.clone()) + } + (RecipeArgument::EvmAddress { value }, RecipeArgumentType::EvmAddress) => { + Val::str(value.to_string()) + } + _ => { + return Ok(ValidateCallbackResult::Invalid( + "Bad recipe argument".into(), + )) + } + }; + vars.insert(arg_name, val); + } + + if recipe_execution.instruction_executions.len() != recipe.instructions.len() { + return Ok(ValidateCallbackResult::Invalid( + "Incorrect number of instruction executions".into(), + )); + } + + for (instruction_execution, (out_var_name, instruction)) in recipe_execution + .instruction_executions + .into_iter() + .zip(recipe.instructions.into_iter()) + { + if vars.contains_key(&out_var_name) { + unreachable!("Bad impl: A valid Recipe doesn't reassign vars"); + } + + let val = match (instruction_execution, instruction) { + (RecipeInstructionExecution::Constant, RecipeInstruction::Constant { value }) => { + // TODO: validate constant value in validate_create_recipe + parse_single_json(&value)? + } + ( + RecipeInstructionExecution::GetCallerAgentPublicKey, + RecipeInstruction::GetCallerAgentPublicKey, + ) => Val::str(action.author().to_string()), + ( + RecipeInstructionExecution::GetDocsListedByVar { doc_ahs }, + RecipeInstruction::GetDocsListedByVar { var_name }, + ) => { + let list_val = vars + .get(&var_name) + .expect("Bad impl: A valid recipe doesn't use unassigned vars"); + let Val::Arr(item_vals) = list_val else { + return Ok(ValidateCallbackResult::Invalid(format!( + "var '{}' expected to contain array", + &var_name + ))); + }; + let mut expected_names = Vec::new(); + for val in item_vals.iter() { + match val { + Val::Str(identifier) => expected_names.push(identifier.as_ref().clone()), + _ => { + return Ok(ValidateCallbackResult::Invalid(format!( + "var '{}' expected to contain array of string elements", + &var_name + ))) + } + } + } + + let mut docs = Vec::new(); + for doc_ah in doc_ahs { + let doc_record = must_get_valid_record(doc_ah.clone())?; + if !recipe + .trusted_authors + .contains(doc_record.action().author()) + { + return Ok(ValidateCallbackResult::Invalid("Untrusted author".into())); + } + let doc: OracleDocument = deserialize_record_entry(doc_record)?; + docs.push(doc); + } + + let actual_names: Vec = docs.iter().map(|doc| doc.name.clone()).collect(); + if expected_names != actual_names { + return Ok(ValidateCallbackResult::Invalid( + "Listed document name doesn't match".into(), + )); + } + let doc_vals = docs + .iter() + .map(|doc| { + let val = parse_single_json(&doc.json_data)?; + Ok(val) + }) + .collect::>>()?; + Val::arr(doc_vals) + } + ( + RecipeInstructionExecution::GetLatestCallerExternalId { attestation_ah }, + RecipeInstruction::GetLatestCallerExternalId, + ) => { + let attestation_record = must_get_valid_record(attestation_ah)?; + let attestation: ExternalIdAttestation = + deserialize_record_entry(attestation_record)?; + Val::obj(IndexMap::from([ + ( + Rc::new(String::from("agent_pubkey")), + Val::str(attestation.internal_pubkey.to_string()), + ), + ( + Rc::new(String::from("external_id")), + Val::str(attestation.external_id), + ), + ( + Rc::new(String::from("display_name")), + Val::str(attestation.display_name), + ), + ])) + } + ( + RecipeInstructionExecution::GetLatestDocWithIdentifier { doc_ah }, + RecipeInstruction::GetLatestDocWithIdentifier { var_name }, + ) => { + let name_val = vars + .get(&var_name) + .expect("Bad impl: A valid recipe doesn't use unassigned vars"); + let Val::Str(name) = name_val else { + return Ok(ValidateCallbackResult::Invalid(format!( + "var '{}' expected to contain string", + &var_name + ))); + }; + let expected_name = name.as_ref().clone(); + let doc_record = must_get_valid_record(doc_ah)?; + if !recipe + .trusted_authors + .contains(doc_record.action().author()) + { + return Ok(ValidateCallbackResult::Invalid("Untrusted author".into())); + } + let doc: OracleDocument = deserialize_record_entry(doc_record)?; + + if doc.name != expected_name { + return Ok(ValidateCallbackResult::Invalid( + "Specified document name doesn't match".into(), + )); + } + parse_single_json(&doc.json_data)? + } + ( + RecipeInstructionExecution::Jq, + RecipeInstruction::Jq { + input_var_names, + program, + }, + ) => { + let input_val = match input_var_names { + JqInstructionArgumentNames::Single { var_name } => vars + .get(&var_name) + .expect("Bad impl: A valid recipe doesn't use unassigned vars") + .clone(), + JqInstructionArgumentNames::List { var_names } => { + let map: IndexMap, Val> = var_names + .into_iter() + .map(|var_name| { + let val = vars + .get(&var_name) + .expect("Bad impl: A valid recipe doesn't use unassigned vars") + .clone(); + (Rc::new(var_name), val) + }) + .collect(); + Val::obj(map) + } + }; + let filter = compile_filter(&program)?; + run_filter(filter, input_val)? + } + _ => { + return Ok(ValidateCallbackResult::Invalid( + "Bad RecipeInstructionExecution".into(), + )) + } + }; + vars.insert(out_var_name, val); + } + + let return_val = vars + .remove("$return") + .expect("Bad impl: A valid recipe has a $return"); + let output = return_val.to_string(); + + if output != recipe_execution.output { + return Ok(ValidateCallbackResult::Invalid( + "Provided output doesn't match execution's".into(), + )); + } + + Ok(ValidateCallbackResult::Valid) +} diff --git a/crates/holoom_recipe_execution/integrity/src/lib.rs b/crates/holoom_recipe_execution/integrity/src/lib.rs new file mode 100644 index 0000000..0580bc1 --- /dev/null +++ b/crates/holoom_recipe_execution/integrity/src/lib.rs @@ -0,0 +1,137 @@ +use hdi::prelude::*; +pub mod entry_types; +pub use entry_types::*; +pub mod link_types; +pub use link_types::*; +pub mod holoom_recipe_execution; +pub use holoom_recipe_execution::*; + + +#[hdk_extern] +pub fn genesis_self_check(_data: GenesisSelfCheckData) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_agent_joining( + _agent_pub_key: AgentPubKey, + _membrane_proof: &Option, +) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} +#[hdk_extern] +pub fn validate(op: Op) -> ExternResult { + match op.flattened::()? { + FlatOp::StoreEntry(store_entry) => match store_entry { + OpEntry::CreateEntry { app_entry, action } => app_entry.validate_create(action), + OpEntry::UpdateEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + _ => Ok(ValidateCallbackResult::Valid), + }, + FlatOp::RegisterUpdate(update_entry) => match update_entry { + OpUpdate::Entry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + _ => Ok(ValidateCallbackResult::Valid), + }, + FlatOp::RegisterDelete(_) => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be deleted".into(), + )), + FlatOp::RegisterCreateLink { + link_type, + base_address, + target_address, + tag, + action, + } => link_type.validate_create(action, base_address, target_address, tag), + FlatOp::RegisterDeleteLink { + link_type, + base_address, + target_address, + tag, + original_action, + action, + } => link_type.validate_delete(action, original_action, base_address, target_address, tag), + FlatOp::StoreRecord(store_record) => { + match store_record { + OpRecord::CreateEntry { app_entry, action } => app_entry.validate_create(action), + OpRecord::UpdateEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + OpRecord::DeleteEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be deleted".into(), + )), + OpRecord::CreateLink { + base_address, + target_address, + tag, + link_type, + action, + } => link_type.validate_create(action, base_address, target_address, tag), + OpRecord::DeleteLink { + original_action_hash, + base_address, + action, + } => { + let record = must_get_valid_record(original_action_hash)?; + let create_link = match record.action() { + Action::CreateLink(create_link) => create_link.clone(), + _ => { + return Ok(ValidateCallbackResult::Invalid( + "The action that a DeleteLink deletes must be a CreateLink" + .to_string(), + )); + } + }; + let link_type = match LinkTypes::from_type( + create_link.zome_index, + create_link.link_type, + )? { + Some(lt) => lt, + None => { + // @todo This must be treated as valid due to holochain bug + // see https://github.com/holochain/holochain/issues/2868 + return Ok(ValidateCallbackResult::Valid); + } + }; + link_type.validate_delete( + action, + create_link.clone(), + base_address, + create_link.target_address, + create_link.tag, + ) + } + OpRecord::CreatePrivateEntry { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdatePrivateEntry { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CreateCapClaim { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CreateCapGrant { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdateCapClaim { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdateCapGrant { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::Dna { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::OpenChain { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CloseChain { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::InitZomesComplete { .. } => Ok(ValidateCallbackResult::Valid), + _ => Ok(ValidateCallbackResult::Valid), + } + } + FlatOp::RegisterAgentActivity(agent_activity) => match agent_activity { + OpActivity::CreateAgent { agent, action } => { + let previous_action = must_get_action(action.prev_action)?; + match previous_action.action() { + Action::AgentValidationPkg( + AgentValidationPkg { membrane_proof, .. }, + ) => validate_agent_joining(agent, membrane_proof), + _ => { + Ok( + ValidateCallbackResult::Invalid( + "The previous action for a `CreateAgent` action must be an `AgentValidationPkg`" + .to_string(), + ), + ) + } + } + } + _ => Ok(ValidateCallbackResult::Valid), + }, + } +} diff --git a/crates/holoom_recipe_execution/integrity/src/link_types.rs b/crates/holoom_recipe_execution/integrity/src/link_types.rs new file mode 100644 index 0000000..aceac1f --- /dev/null +++ b/crates/holoom_recipe_execution/integrity/src/link_types.rs @@ -0,0 +1,34 @@ +use hdi::prelude::*; + +#[derive(Serialize, Deserialize)] +#[hdk_link_types] +pub enum LinkTypes { + NameToRecipe +} + +impl LinkTypes { + pub fn validate_create( + self, + action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + tag: LinkTag, + ) -> ExternResult { + match self { + _=> Ok(ValidateCallbackResult::Valid) + } + } + + pub fn validate_delete( + self, + action: DeleteLink, + original_action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + tag: LinkTag, + ) -> ExternResult { + match self { + _=> Ok(ValidateCallbackResult::Valid) + } + } +} diff --git a/crates/holoom_types/src/evm_signing_offer.rs b/crates/holoom_types/src/evm_signing_offer.rs index 905e2b2..277e2b6 100644 --- a/crates/holoom_types/src/evm_signing_offer.rs +++ b/crates/holoom_types/src/evm_signing_offer.rs @@ -13,7 +13,8 @@ pub enum EvmU256Item { HoloAgent, } -#[derive(Clone, PartialEq, TS, Serialize, Deserialize, Debug)] +#[hdk_entry_helper] +#[derive(Clone, PartialEq, TS)] #[ts(export)] pub struct EvmSigningOffer { #[ts(type = "ActionHash")] @@ -21,22 +22,11 @@ pub struct EvmSigningOffer { pub u256_items: Vec, } -#[hdk_entry_helper] -#[derive(Clone, PartialEq, TS)] -#[ts(export)] -pub struct SignedEvmSigningOffer { - #[ts(type = "Uint8Array")] - pub signer: EvmAddress, - #[ts(type = "[Uint8Array, Uint8Array, number]")] - pub signature: EvmSignature, - pub offer: EvmSigningOffer, -} - #[derive(Serialize, Deserialize, Debug, TS)] #[ts(export)] pub struct CreateEvmSigningOfferPayload { pub identifier: String, - pub signed_offer: SignedEvmSigningOffer, + pub evm_signing_offer: EvmSigningOffer, } #[derive(Serialize, Deserialize, Debug, TS)] diff --git a/crates/holoom_types/src/lib.rs b/crates/holoom_types/src/lib.rs index a43508a..ce4206b 100644 --- a/crates/holoom_types/src/lib.rs +++ b/crates/holoom_types/src/lib.rs @@ -8,6 +8,7 @@ pub use external_id::*; pub mod evm_signing_offer; pub mod metadata; pub mod recipe; +pub use recipe::*; pub use metadata::*; pub mod wallet; pub use wallet::*; diff --git a/crates/holoom_types/src/recipe.rs b/crates/holoom_types/src/recipe.rs index e11f2ce..f0fb4a9 100644 --- a/crates/holoom_types/src/recipe.rs +++ b/crates/holoom_types/src/recipe.rs @@ -102,3 +102,10 @@ pub struct ExecuteRecipePayload { pub recipe_ah: ActionHash, pub arguments: Vec, } + +#[derive(Clone, Debug, Serialize, Deserialize, SerializedBytes)] +#[serde(tag = "type")] +pub struct ExecuteOracleRecipePayload { + pub name: String, + pub trusted: Vec, +} diff --git a/crates/oracle_document/coordinator/Cargo.toml b/crates/oracle_document/coordinator/Cargo.toml new file mode 100644 index 0000000..e641d20 --- /dev/null +++ b/crates/oracle_document/coordinator/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "oracle_document" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "oracle_document" + +[dependencies] +hdk = { workspace = true } +serde = { workspace = true } +holoom_types = { workspace = true } +shared_utils = { workspace = true } +oracle_document_integrity = { workspace = true } + + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] #avoids mio bug +holochain = { workspace = true, default-features = false, features = ["test_utils"] } +tokio = "1.38.0" +#ethers-signers = { workspace = true } +#ed25519-dalek = { workspace = true } +#bs58 = { workspace = true } + diff --git a/crates/oracle_document/coordinator/src/lib.rs b/crates/oracle_document/coordinator/src/lib.rs new file mode 100644 index 0000000..04a7fa8 --- /dev/null +++ b/crates/oracle_document/coordinator/src/lib.rs @@ -0,0 +1,30 @@ +pub mod oracle_document; +use hdk::prelude::*; +use shared_utils::get_authority_agent; + +#[hdk_extern] +pub fn init(_: ()) -> ExternResult { + let authority_agent = get_authority_agent()?; + let my_pubkey = agent_info()?.agent_initial_pubkey; + let mut functions = BTreeSet::new(); + let zome_name = zome_info()?.name; + if my_pubkey == authority_agent { + functions.insert(( + zome_name.clone(), + "get_latest_oracle_document_ah_for_name".into(), + )); + } + functions.insert((zome_name, "recv_remote_signal".into())); + create_cap_grant(CapGrantEntry { + tag: "".into(), + access: ().into(), + functions: GrantedFunctions::Listed(functions), + })?; + + Ok(InitCallbackResult::Pass) +} + +#[hdk_extern] +fn get_authority(_: ()) -> ExternResult { + get_authority_agent() +} diff --git a/crates/oracle_document/coordinator/src/oracle_document.rs b/crates/oracle_document/coordinator/src/oracle_document.rs new file mode 100644 index 0000000..9c7015b --- /dev/null +++ b/crates/oracle_document/coordinator/src/oracle_document.rs @@ -0,0 +1,126 @@ +use hdk::prelude::*; +use holoom_types::{DocumentRelationTag, OracleDocument}; +use oracle_document_integrity::{EntryTypes, LinkTypes}; +use shared_utils::hash_identifier; + +#[hdk_extern] +pub fn create_oracle_document(oracle_document: OracleDocument) -> ExternResult { + let base_address = hash_identifier(oracle_document.name.clone())?; + let link_tag = oracle_document.name.as_bytes().to_vec(); + let oracle_document_ah = create_entry(EntryTypes::OracleDocument(oracle_document))?; + create_link( + base_address, + oracle_document_ah.clone(), + LinkTypes::NameToOracleDocument, + link_tag, + )?; + let record = get(oracle_document_ah, GetOptions::network())?.ok_or(wasm_error!( + WasmErrorInner::Guest(String::from( + "Could not find the newly created OracleDocument" + )) + ))?; + + Ok(record) +} +pub fn get_latest_oracle_document_ah_for_name( + name: String, + trusted_authors: &[AgentPubKey], +) -> ExternResult> { + let base_address = hash_identifier(name)?; + let mut links = get_links( + GetLinksInputBuilder::try_new(base_address, LinkTypes::NameToOracleDocument)?.build(), + )?; + links.sort_by_key(|link| link.timestamp); + let Some(link) = links + .into_iter() + .filter(|link| trusted_authors.contains(&link.author)) + .last() + else { + return Ok(None); + }; + let action_hash = ActionHash::try_from(link.target).map_err(|_| { + wasm_error!(WasmErrorInner::Guest( + "Link target isn't an ActionHash".into() + )) + })?; + Ok(Some(action_hash)) +} + +#[hdk_extern] +pub fn get_oracle_document_link_ahs_for_name(name: String) -> ExternResult> { + let base_address = hash_identifier(name)?; + let mut links = get_links( + GetLinksInputBuilder::try_new(base_address, LinkTypes::NameToOracleDocument)?.build(), + )?; + links.sort_by_key(|link| link.timestamp); + let action_hashes = links + .into_iter() + .filter_map(|link| ActionHash::try_from(link.create_link_hash).ok()) + .collect(); + Ok(action_hashes) +} + +pub fn get_latest_oracle_document_for_name( + name: String, + trusted_authors: &[AgentPubKey], +) -> ExternResult> { + let Some(action_hash) = get_latest_oracle_document_ah_for_name(name, trusted_authors)? else { + return Ok(None); + }; + get(action_hash, GetOptions::network()) +} + +#[hdk_extern] +pub fn relate_oracle_document(relation_tag: DocumentRelationTag) -> ExternResult<()> { + let tag_bytes = + ExternIO::encode(&relation_tag).expect("Couldn't serialize DocumentRelationTag"); + + let base_address = hash_identifier(relation_tag.relation)?; + let target_address = hash_identifier(relation_tag.name.clone())?; + create_link( + base_address, + target_address, + LinkTypes::RelateOracleDocumentName, + tag_bytes.0, + )?; + + Ok(()) +} + +#[hdk_extern] +pub fn get_related_oracle_document_names(relation_name: String) -> ExternResult> { + // BTreeSet ensures order an no repeats + let identifiers: BTreeSet = get_links( + GetLinksInputBuilder::try_new( + hash_identifier(relation_name)?, + LinkTypes::RelateOracleDocumentName, + )? + .build(), + )? + .into_iter() + .map(|link| { + let document_relation: DocumentRelationTag = ExternIO(link.tag.into_inner()) + .decode() + .map_err(|_| wasm_error!(WasmErrorInner::Guest("LinkTag isn't utf8".into())))?; + Ok(document_relation.name) + }) + .collect::>()?; + Ok(identifiers.into_iter().collect()) +} + +#[hdk_extern] +pub fn get_relation_link_ahs(relation_name: String) -> ExternResult> { + let mut links = get_links( + GetLinksInputBuilder::try_new( + hash_identifier(relation_name)?, + LinkTypes::RelateOracleDocumentName, + )? + .build(), + )?; + links.sort_by_key(|link| link.timestamp); + let action_hashes = links + .into_iter() + .filter_map(|link| ActionHash::try_from(link.create_link_hash).ok()) + .collect(); + Ok(action_hashes) +} diff --git a/crates/oracle_document/coordinator/tests/config.rs b/crates/oracle_document/coordinator/tests/config.rs new file mode 100644 index 0000000..f06bd3a --- /dev/null +++ b/crates/oracle_document/coordinator/tests/config.rs @@ -0,0 +1,141 @@ +//use std::time::Duration; + +use hdk::prelude::*; +use holochain::{ + conductor::{api::error::ConductorApiResult, config::ConductorConfig}, + prelude::DnaFile, + sweettest::{SweetAgents, SweetCell, SweetConductorBatch, SweetDnaFile}, +}; +use holoom_types::HoloomDnaProperties; + +//#[cfg(test)] +//mod tests; + +async fn load_dna() -> DnaFile { + // Use prebuilt dna file + let dna_path = std::env::current_dir() + .unwrap() + .join("../../../workdir/holoom.dna"); + + SweetDnaFile::from_bundle(&dna_path).await.unwrap() +} + +pub async fn holoom_dna_with_authority(authority_agent: &AgentPubKey) -> DnaFile { + let dna = load_dna().await; + let properties = SerializedBytes::try_from(HoloomDnaProperties { + authority_agent: authority_agent.to_string(), + }) + .unwrap(); + dna.update_modifiers(DnaModifiersOpt { + network_seed: None, + properties: Some(properties), + origin_time: None, + quantum_time: None, + }) +} + +pub struct TestSetup { + pub conductors: SweetConductorBatch, + cells: Vec, +} + +impl TestSetup { + pub async fn new(user_count: usize) -> Self { + // Set up conductors + let mut conductors: SweetConductorBatch = + SweetConductorBatch::from_config(1 + user_count, ConductorConfig::default()).await; + + let authority_agent_pubkey = SweetAgents::one(conductors[0].keystore()).await; + + let dnas = &[holoom_dna_with_authority(&authority_agent_pubkey).await]; + + let authority_app = conductors[0] + .setup_app_for_agent("holoom", authority_agent_pubkey.clone(), dnas) + .await + .unwrap(); + let (authority_cell,) = authority_app.into_tuple(); + let mut cells = Vec::from([authority_cell]); + for i in 1..1 + user_count { + let user_app = conductors[i].setup_app("holoom", dnas).await.unwrap(); + let (user_cell,) = user_app.into_tuple(); + cells.push(user_cell); + } + + TestSetup { conductors, cells } + } + + pub async fn authority_only() -> Self { + Self::new(0).await + } + + //pub async fn authority_and_alice() -> Self { + // Self::new(1).await + // } + + //pub async fn authority_and_alice_bob() -> Self { + // Self::new(2).await + // } + + pub async fn authority_call( + &self, + zome_name: &str, + fn_name: &str, + payload: I, + ) -> ConductorApiResult + where + I: serde::Serialize + std::fmt::Debug, + O: serde::de::DeserializeOwned + std::fmt::Debug, + { + self.conductors[0] + .call_fallible(&self.cells[0].zome(zome_name), fn_name, payload) + .await + } + + /*pub async fn alice_call( + &self, + zome_name: &str, + fn_name: &str, + payload: I, + ) -> ConductorApiResult + where + I: serde::Serialize + std::fmt::Debug, + O: serde::de::DeserializeOwned + std::fmt::Debug, + { + self.conductors[1] + .call_fallible(&self.cells[1].zome(zome_name), fn_name, payload) + .await + }*/ + + /*pub async fn bob_call( + &self, + zome_name: &str, + fn_name: &str, + payload: I, + ) -> ConductorApiResult + where + I: serde::Serialize + std::fmt::Debug, + O: serde::de::DeserializeOwned + std::fmt::Debug, + { + self.conductors[2] + .call_fallible(&self.cells[2].zome(zome_name), fn_name, payload) + .await + }*/ + + //pub fn authority_pubkey(&self) -> AgentPubKey { + // self.cells[0].agent_pubkey().clone() + // } + + //pub fn alice_pubkey(&self) -> AgentPubKey { + // self.cells[1].agent_pubkey().clone() + // } + + //pub fn bob_pubkey(&self) -> AgentPubKey { + // self.cells[1].agent_pubkey().clone() + //} + + //pub async fn consistency(&self) { + // await_consistency(Duration::from_secs(60), self.cells.iter()) + // .await + // .unwrap(); + //} +} diff --git a/crates/oracle_document/coordinator/tests/oracle_document.rs b/crates/oracle_document/coordinator/tests/oracle_document.rs new file mode 100644 index 0000000..9e0aea0 --- /dev/null +++ b/crates/oracle_document/coordinator/tests/oracle_document.rs @@ -0,0 +1,73 @@ +use hdk::prelude::*; +use holochain::conductor::api::error::ConductorApiResult; +use holoom_types::{DocumentRelationTag, OracleDocument}; + +mod config; +use config::TestSetup; + +#[cfg(test)] + +#[tokio::test(flavor = "multi_thread")] +async fn can_fetch_documents_by_relation() { + let setup = TestSetup::authority_only().await; + + let _foo1_record: Record = setup + .authority_call( + "oracle_document", + "create_oracle_document", + OracleDocument { + name: "foo/1".into(), + json_data: "{\"type\":\"foo\",\"value\":1}".into(), + }, + ) + .await + .unwrap(); + + let _foo2_record: Record = setup + .authority_call( + "oracle_document", + "create_oracle_document", + OracleDocument { + name: "foo/2".into(), + json_data: "{\"type\":\"foo\",\"value\":2}".into(), + }, + ) + .await + .unwrap(); + + let res: ConductorApiResult<()> = setup + .authority_call( + "oracle_document", + "relate_oracle_document", + DocumentRelationTag { + name: "foo/1".into(), + relation: "foo".into(), + }, + ) + .await; + assert!(res.is_ok()); + + let res: ConductorApiResult<()> = setup + .authority_call( + "oracle_document", + "relate_oracle_document", + DocumentRelationTag { + name: "foo/2".into(), + relation: "foo".into(), + }, + ) + .await; + assert!(res.is_ok()); + + let identifiers: Vec = setup + .authority_call( + "oracle_document", + "get_related_oracle_document_names", + String::from("foo"), + ) + .await + .unwrap(); + + let expected_identifiers = vec![String::from("foo/1"), String::from("foo/2")]; + assert_eq!(identifiers, expected_identifiers); +} diff --git a/crates/oracle_document/integrity/Cargo.toml b/crates/oracle_document/integrity/Cargo.toml new file mode 100644 index 0000000..e02235a --- /dev/null +++ b/crates/oracle_document/integrity/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "oracle_document_integrity" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "oracle_document_integrity" + +[dependencies] +hdi = { workspace = true } +serde = { workspace = true } +holoom_types = { workspace = true } +shared_utils = { workspace = true } +#bs58 = { workspace = true } diff --git a/crates/oracle_document/integrity/src/entry_types.rs b/crates/oracle_document/integrity/src/entry_types.rs new file mode 100644 index 0000000..8ea524d --- /dev/null +++ b/crates/oracle_document/integrity/src/entry_types.rs @@ -0,0 +1,23 @@ +use hdi::prelude::*; +use holoom_types::OracleDocument; +use crate::oracle_document::*; +//use external_attestation_validation::*; + +#[derive(Serialize, Deserialize)] +#[serde(tag = "type")] +#[hdk_entry_types] +#[unit_enum(UnitEntryTypes)] +pub enum EntryTypes { + OracleDocument(OracleDocument), +} + +impl EntryTypes { + pub fn validate_create(self, action: Create) -> ExternResult { + match self { + EntryTypes::OracleDocument(oracle_document) => validate_create_oracle_document( + EntryCreationAction::Create(action), + oracle_document, + ), + } + } +} diff --git a/crates/oracle_document/integrity/src/lib.rs b/crates/oracle_document/integrity/src/lib.rs new file mode 100644 index 0000000..d4c817d --- /dev/null +++ b/crates/oracle_document/integrity/src/lib.rs @@ -0,0 +1,141 @@ +use hdi::prelude::*; +pub mod entry_types; +pub use entry_types::*; +pub mod link_types; +pub use link_types::*; +pub mod oracle_document; +pub use oracle_document::*; +pub mod name_oracle_document; +pub use name_oracle_document::*; +pub mod relate_oracle_document_name; +pub use relate_oracle_document_name::*; + + +#[hdk_extern] +pub fn genesis_self_check(_data: GenesisSelfCheckData) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_agent_joining( + _agent_pub_key: AgentPubKey, + _membrane_proof: &Option, +) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} +#[hdk_extern] +pub fn validate(op: Op) -> ExternResult { + match op.flattened::()? { + FlatOp::StoreEntry(store_entry) => match store_entry { + OpEntry::CreateEntry { app_entry, action } => app_entry.validate_create(action), + OpEntry::UpdateEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + _ => Ok(ValidateCallbackResult::Valid), + }, + FlatOp::RegisterUpdate(update_entry) => match update_entry { + OpUpdate::Entry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + _ => Ok(ValidateCallbackResult::Valid), + }, + FlatOp::RegisterDelete(_) => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be deleted".into(), + )), + FlatOp::RegisterCreateLink { + link_type, + base_address, + target_address, + tag, + action, + } => link_type.validate_create(action, base_address, target_address, tag), + FlatOp::RegisterDeleteLink { + link_type, + base_address, + target_address, + tag, + original_action, + action, + } => link_type.validate_delete(action, original_action, base_address, target_address, tag), + FlatOp::StoreRecord(store_record) => { + match store_record { + OpRecord::CreateEntry { app_entry, action } => app_entry.validate_create(action), + OpRecord::UpdateEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + OpRecord::DeleteEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be deleted".into(), + )), + OpRecord::CreateLink { + base_address, + target_address, + tag, + link_type, + action, + } => link_type.validate_create(action, base_address, target_address, tag), + OpRecord::DeleteLink { + original_action_hash, + base_address, + action, + } => { + let record = must_get_valid_record(original_action_hash)?; + let create_link = match record.action() { + Action::CreateLink(create_link) => create_link.clone(), + _ => { + return Ok(ValidateCallbackResult::Invalid( + "The action that a DeleteLink deletes must be a CreateLink" + .to_string(), + )); + } + }; + let link_type = match LinkTypes::from_type( + create_link.zome_index, + create_link.link_type, + )? { + Some(lt) => lt, + None => { + // @todo This must be treated as valid due to holochain bug + // see https://github.com/holochain/holochain/issues/2868 + return Ok(ValidateCallbackResult::Valid); + } + }; + link_type.validate_delete( + action, + create_link.clone(), + base_address, + create_link.target_address, + create_link.tag, + ) + } + OpRecord::CreatePrivateEntry { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdatePrivateEntry { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CreateCapClaim { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CreateCapGrant { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdateCapClaim { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdateCapGrant { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::Dna { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::OpenChain { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CloseChain { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::InitZomesComplete { .. } => Ok(ValidateCallbackResult::Valid), + _ => Ok(ValidateCallbackResult::Valid), + } + } + FlatOp::RegisterAgentActivity(agent_activity) => match agent_activity { + OpActivity::CreateAgent { agent, action } => { + let previous_action = must_get_action(action.prev_action)?; + match previous_action.action() { + Action::AgentValidationPkg( + AgentValidationPkg { membrane_proof, .. }, + ) => validate_agent_joining(agent, membrane_proof), + _ => { + Ok( + ValidateCallbackResult::Invalid( + "The previous action for a `CreateAgent` action must be an `AgentValidationPkg`" + .to_string(), + ), + ) + } + } + } + _ => Ok(ValidateCallbackResult::Valid), + }, + } +} diff --git a/crates/oracle_document/integrity/src/link_types.rs b/crates/oracle_document/integrity/src/link_types.rs new file mode 100644 index 0000000..65277e5 --- /dev/null +++ b/crates/oracle_document/integrity/src/link_types.rs @@ -0,0 +1,65 @@ +use hdi::prelude::*; +use crate::name_oracle_document::*; +use crate::relate_oracle_document_name::*; + +#[derive(Serialize, Deserialize)] +#[hdk_link_types] +pub enum LinkTypes { + NameToOracleDocument, + RelateOracleDocumentName, +} + +impl LinkTypes { + pub fn validate_create( + self, + action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + tag: LinkTag, + ) -> ExternResult { + match self { + LinkTypes::NameToOracleDocument => validate_create_link_name_to_oracle_document( + action, + base_address, + target_address, + tag, + ), + LinkTypes::RelateOracleDocumentName => { + validate_create_link_relate_oracle_document_name( + action, + base_address, + target_address, + tag, + ) + } + } + } + + pub fn validate_delete( + self, + action: DeleteLink, + original_action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + tag: LinkTag, + ) -> ExternResult { + match self { + LinkTypes::NameToOracleDocument => validate_delete_link_name_to_oracle_document( + action, + original_action, + base_address, + target_address, + tag, + ), + LinkTypes::RelateOracleDocumentName => { + validate_delete_link_relate_oracle_document_name( + action, + original_action, + base_address, + target_address, + tag, + ) + } + } + } +} diff --git a/crates/oracle_document/integrity/src/name_oracle_document.rs b/crates/oracle_document/integrity/src/name_oracle_document.rs new file mode 100644 index 0000000..b9001f8 --- /dev/null +++ b/crates/oracle_document/integrity/src/name_oracle_document.rs @@ -0,0 +1,41 @@ +use hdi::prelude::*; +use holoom_types::OracleDocument; +use shared_utils::hash_identifier; + +pub fn validate_create_link_name_to_oracle_document( + _action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + // Check the entry type for the given action hash + let action_hash = ActionHash::try_from(target_address).map_err(|e| wasm_error!(e))?; + let record = must_get_valid_record(action_hash)?; + let oracle_document: OracleDocument = record + .entry() + .to_app_option() + .map_err(|e| wasm_error!(e))? + .ok_or(wasm_error!(WasmErrorInner::Guest(String::from( + "Linked action must reference an entry" + ))))?; + + let expected_base_address = hash_identifier(oracle_document.name)?; + if AnyLinkableHash::from(expected_base_address) != base_address { + return Ok(ValidateCallbackResult::Invalid( + "OracleDocument name doesn't hash to base address".into(), + )); + } + + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_delete_link_name_to_oracle_document( + _action: DeleteLink, + _original_action: CreateLink, + _base: AnyLinkableHash, + _target: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + Ok(ValidateCallbackResult::Invalid(String::from( + "OracleDocument links cannot be deleted", + ))) +} diff --git a/crates/username_registry_validation/src/oracle_document.rs b/crates/oracle_document/integrity/src/oracle_document.rs similarity index 100% rename from crates/username_registry_validation/src/oracle_document.rs rename to crates/oracle_document/integrity/src/oracle_document.rs diff --git a/crates/oracle_document/integrity/src/relate_oracle_document_name.rs b/crates/oracle_document/integrity/src/relate_oracle_document_name.rs new file mode 100644 index 0000000..9aaeab8 --- /dev/null +++ b/crates/oracle_document/integrity/src/relate_oracle_document_name.rs @@ -0,0 +1,39 @@ +use hdi::prelude::*; +use holoom_types::DocumentRelationTag; +use shared_utils::hash_identifier; + +pub fn validate_create_link_relate_oracle_document_name( + _action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + tag: LinkTag, +) -> ExternResult { + let Ok(document_relation) = ExternIO(tag.into_inner()).decode::() else { + return Ok(ValidateCallbackResult::Invalid( + "Tag must be a DocumentRelationTag".into(), + )); + }; + if base_address != hash_identifier(document_relation.relation)?.into() { + return Ok(ValidateCallbackResult::Invalid( + "Base address must be the hash of the document relation".into(), + )); + } + if target_address != hash_identifier(document_relation.name)?.into() { + return Ok(ValidateCallbackResult::Invalid( + "Target address must be the hash of the target document name".into(), + )); + } + + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_delete_link_relate_oracle_document_name( + _action: DeleteLink, + _original_action: CreateLink, + _base_address: AnyLinkableHash, + _target_address: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + Ok(ValidateCallbackResult::Invalid( + "Cannot delete oracle document relation links".into(), + )) +} diff --git a/crates/shared_utils/Cargo.toml b/crates/shared_utils/Cargo.toml new file mode 100644 index 0000000..a9049fa --- /dev/null +++ b/crates/shared_utils/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "shared_utils" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "shared_utils" + +[dependencies] +hdi = { workspace = true } +#holo_hash = { workspace = true } +serde = { workspace = true } +#bincode = { workspace = true } +holoom_types = { workspace = true } +#ed25519-dalek = { workspace = true } +#bs58 = { workspace = true } +#jaq_wrapper = { workspace = true } + + +#[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] #avoids mio bug +#holochain = { workspace = true, default-features = false, features = ["test_utils"] } +#hdk = { workspace = true, features = ["encoding", "test_utils"] } + diff --git a/crates/shared_utils/src/helpers.rs b/crates/shared_utils/src/helpers.rs new file mode 100644 index 0000000..d2d032b --- /dev/null +++ b/crates/shared_utils/src/helpers.rs @@ -0,0 +1,34 @@ +use hdi::prelude::*; +use holoom_types::HoloomDnaProperties; + +pub fn deserialize_record_entry(record: Record) -> ExternResult +where + O: TryFrom, +{ + let entry: O = record + .entry() + .to_app_option() + .map_err(|e| wasm_error!(e))? + .ok_or(wasm_error!(WasmErrorInner::Guest( + "Entry not present in Record".into() + )))?; + Ok(entry) +} + +pub fn hash_identifier(identifier: String) -> ExternResult { + #[derive(SerializedBytes, Serialize, Debug, Deserialize)] + struct SerializableIdentifier(String); + + let bytes = SerializedBytes::try_from(SerializableIdentifier(identifier)) + .map_err(|err| wasm_error!(err))?; + hash_entry(Entry::App(AppEntryBytes(bytes))) +} + +pub fn get_authority_agent() -> ExternResult { + let dna_props = HoloomDnaProperties::try_from_dna_properties()?; + AgentPubKey::try_from(dna_props.authority_agent).map_err(|_| { + wasm_error!(WasmErrorInner::Guest( + "Failed to deserialize AgentPubKey from dna properties".into() + )) + }) +} diff --git a/crates/shared_utils/src/lib.rs b/crates/shared_utils/src/lib.rs new file mode 100644 index 0000000..0d01fc3 --- /dev/null +++ b/crates/shared_utils/src/lib.rs @@ -0,0 +1,2 @@ +pub mod helpers; +pub use helpers::*; \ No newline at end of file diff --git a/crates/username_attestation/coordinator/Cargo.toml b/crates/username_attestation/coordinator/Cargo.toml new file mode 100644 index 0000000..2f7bcfe --- /dev/null +++ b/crates/username_attestation/coordinator/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "username_attestation" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "username_attestation" + +[dependencies] +hdk = { workspace = true } +serde = { workspace = true } +holoom_types = { workspace = true } +shared_utils = { workspace = true } +username_attestation_integrity = { workspace = true } +bincode = { workspace = true } + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] #avoids mio bug +holochain = { workspace = true, default-features = false, features = ["test_utils"] } +tokio = "1.38.0" diff --git a/crates/username_attestation/coordinator/src/lib.rs b/crates/username_attestation/coordinator/src/lib.rs new file mode 100644 index 0000000..2ca9dfc --- /dev/null +++ b/crates/username_attestation/coordinator/src/lib.rs @@ -0,0 +1,30 @@ +pub mod username_attestation; +pub mod user_metadata; +use hdk::prelude::*; +use shared_utils::get_authority_agent; + +#[hdk_extern] +pub fn init(_: ()) -> ExternResult { + let authority_agent = get_authority_agent()?; + let my_pubkey = agent_info()?.agent_initial_pubkey; + let mut functions = BTreeSet::new(); + let zome_name = zome_info()?.name; + if my_pubkey == authority_agent { + functions.insert(( + zome_name.clone(), "ingest_signed_username".into(), + )); + } + functions.insert((zome_name, "recv_remote_signal".into())); + create_cap_grant(CapGrantEntry { + tag: "".into(), + access: ().into(), + functions: GrantedFunctions::Listed(functions), + })?; + + Ok(InitCallbackResult::Pass) +} + +#[hdk_extern] +fn get_authority(_: ()) -> ExternResult { + get_authority_agent() +} diff --git a/crates/username_attestation/coordinator/src/user_metadata.rs b/crates/username_attestation/coordinator/src/user_metadata.rs new file mode 100644 index 0000000..34a277c --- /dev/null +++ b/crates/username_attestation/coordinator/src/user_metadata.rs @@ -0,0 +1,77 @@ +use std::collections::HashMap; + +use hdk::prelude::*; +use holoom_types::{GetMetadataItemValuePayload, MetadataItem, UpdateMetadataItemPayload}; +use username_attestation_integrity::*; + +#[hdk_extern] +pub fn update_metadata_item(payload: UpdateMetadataItemPayload) -> ExternResult<()> { + let links = get_links( + GetLinksInputBuilder::try_new(payload.agent_pubkey.clone(), LinkTypes::AgentMetadata)? + .build(), + )?; + for link in links { + let existing_item: MetadataItem = + bincode::deserialize(&link.tag.into_inner()).map_err(|_| { + wasm_error!(WasmErrorInner::Guest( + "Failed to deserialize MetadataItem".into() + )) + })?; + if existing_item.name == payload.name { + // Remove old MetadataItem + delete_link(link.create_link_hash)?; + } + } + let item = MetadataItem { + name: payload.name, + value: payload.value, + }; + let tag_bytes = bincode::serialize(&item).map_err(|_| { + wasm_error!(WasmErrorInner::Guest( + "Failed to serialize MetadataItem".into() + )) + })?; + create_link( + payload.agent_pubkey.clone(), + payload.agent_pubkey, // unused and irrelevant + LinkTypes::AgentMetadata, + LinkTag(tag_bytes), + )?; + Ok(()) +} + +#[hdk_extern] +pub fn get_metadata_item_value( + payload: GetMetadataItemValuePayload, +) -> ExternResult> { + let links = get_links( + GetLinksInputBuilder::try_new(payload.agent_pubkey, LinkTypes::AgentMetadata)?.build(), + )?; + for link in links { + let item: MetadataItem = bincode::deserialize(&link.tag.into_inner()).map_err(|_| { + wasm_error!(WasmErrorInner::Guest( + "Failed to deserialize MetadataItem".into() + )) + })?; + if payload.name == item.name { + return Ok(Some(item.value)); + } + } + Ok(None) +} + +#[hdk_extern] +pub fn get_metadata(agent_pubkey: AgentPubKey) -> ExternResult> { + let links = + get_links(GetLinksInputBuilder::try_new(agent_pubkey, LinkTypes::AgentMetadata)?.build())?; + let mut out = HashMap::default(); + for link in links { + let item: MetadataItem = bincode::deserialize(&link.tag.into_inner()).map_err(|_| { + wasm_error!(WasmErrorInner::Guest( + "Failed to deserialize MetadataItem".into() + )) + })?; + out.insert(item.name, item.value); + } + Ok(out) +} diff --git a/crates/username_attestation/coordinator/src/username_attestation.rs b/crates/username_attestation/coordinator/src/username_attestation.rs new file mode 100644 index 0000000..0d7872d --- /dev/null +++ b/crates/username_attestation/coordinator/src/username_attestation.rs @@ -0,0 +1,135 @@ +use hdk::prelude::*; +use holoom_types::{SignedUsername, UsernameAttestation, SignableBytes}; +use username_attestation_integrity::*; +use shared_utils::get_authority_agent; + +#[hdk_extern] +pub fn create_username_attestation( + username_attestation: UsernameAttestation, +) -> ExternResult { + let username_attestation_hash = create_entry(&EntryTypes::UsernameAttestation( + username_attestation.clone(), + ))?; + create_link( + username_attestation.agent.clone(), + username_attestation_hash.clone(), + LinkTypes::AgentToUsernameAttestations, + (), + )?; + let record = get(username_attestation_hash.clone(), GetOptions::network())?.ok_or( + wasm_error!(WasmErrorInner::Guest(String::from( + "Could not find the newly created UsernameAttestation" + ))), + )?; + Ok(record) +} +#[hdk_extern] +pub fn get_username_attestation( + username_attestation_hash: ActionHash, +) -> ExternResult> { + get(username_attestation_hash, GetOptions::network()) +} +#[hdk_extern] +pub fn delete_username_attestation( + original_username_attestation_hash: ActionHash, +) -> ExternResult { + delete_entry(original_username_attestation_hash) +} +#[hdk_extern] +pub fn get_username_attestation_for_agent(agent: AgentPubKey) -> ExternResult> { + let links = get_links( + GetLinksInputBuilder::try_new(agent, LinkTypes::AgentToUsernameAttestations)?.build(), + )?; + + match links.first() { + Some(l) => get( + ActionHash::try_from(l.clone().target).unwrap(), + GetOptions::network(), + ), + None => Ok(None), + } +} + +#[hdk_extern] +pub fn does_agent_have_username(agent: AgentPubKey) -> ExternResult { + let count = count_links(LinkQuery::new( + agent, + LinkTypes::AgentToUsernameAttestations.try_into_filter()?, + ))?; + + Ok(count > 0) +} + +#[hdk_extern] +pub fn get_all_username_attestations(_: ()) -> ExternResult> { + let my_pubkey = agent_info()?.agent_initial_pubkey; + if my_pubkey != get_authority_agent()? { + return Err(wasm_error!(WasmErrorInner::Host( + "Only callable by authority agent".into() + ))); + } + let username_attestation_type: EntryType = UnitEntryTypes::UsernameAttestation.try_into()?; + let filter = ChainQueryFilter::new() + .include_entries(true) + .entry_type(username_attestation_type); + query(filter) +} + + +/// Sign secret message with agent key as transferable proof that user owns this account +#[hdk_extern] +pub fn sign_message(message: SignableBytes) -> ExternResult { + sign(agent_info()?.agent_initial_pubkey, message) +} + +/// Called by the user who wishes to register a username. Returns a UsernameAttestation Record. +#[hdk_extern] +pub fn sign_username_to_attest(username: String) -> ExternResult { + // TODO: devise scheme akin to signing a nonce + let my_pubkey = agent_info()?.agent_initial_pubkey; + let signature = sign(my_pubkey.clone(), &username)?; + let payload = SignedUsername { + username, + signature, + signer: my_pubkey, + }; + + let authority_agent = get_authority_agent()?; + + let zome_name = zome_info()?.name; + let fn_name = FunctionName::from("ingest_signed_username"); + let resp = call_remote(authority_agent, zome_name, fn_name, None, payload)?; + match resp { + ZomeCallResponse::Ok(result) => result.decode().map_err(|err| wasm_error!(err)), + ZomeCallResponse::NetworkError(err) => Err(wasm_error!(WasmErrorInner::Guest(format!( + "There was a network error: {:?}", + err + )))), + ZomeCallResponse::Unauthorized(..) => { + Err(wasm_error!(WasmErrorInner::Guest("Unauthorized".into()))) + } + ZomeCallResponse::CountersigningSession(_) => Err(wasm_error!(WasmErrorInner::Guest( + "Unexpected countersigning session".into() + ))), + } +} + +/// Remotely invoked on the authority agent. Returns a UsernameAttestation Record. +#[hdk_extern] +pub fn ingest_signed_username(signed_username: SignedUsername) -> ExternResult { + let is_valid = verify_signature( + signed_username.signer.clone(), + signed_username.signature, + signed_username.username.clone(), + )?; + if !is_valid { + return Err(wasm_error!(WasmErrorInner::Host( + "Invalid username signature".into() + ))); + } + let username_attestation = UsernameAttestation { + username: signed_username.username, + agent: signed_username.signer, + }; + create_username_attestation(username_attestation) +} diff --git a/crates/username_attestation/coordinator/tests/config.rs b/crates/username_attestation/coordinator/tests/config.rs new file mode 100644 index 0000000..54eaab9 --- /dev/null +++ b/crates/username_attestation/coordinator/tests/config.rs @@ -0,0 +1,141 @@ +use std::time::Duration; + +use hdk::prelude::*; +use holochain::{ + conductor::{api::error::ConductorApiResult, config::ConductorConfig}, + prelude::DnaFile, + sweettest::{await_consistency, SweetAgents, SweetCell, SweetConductorBatch, SweetDnaFile}, +}; +use holoom_types::HoloomDnaProperties; + +//#[cfg(test)] +//mod tests; + +async fn load_dna() -> DnaFile { + // Use prebuilt dna file + let dna_path = std::env::current_dir() + .unwrap() + .join("../../../workdir/holoom.dna"); + + SweetDnaFile::from_bundle(&dna_path).await.unwrap() +} + +pub async fn holoom_dna_with_authority(authority_agent: &AgentPubKey) -> DnaFile { + let dna = load_dna().await; + let properties = SerializedBytes::try_from(HoloomDnaProperties { + authority_agent: authority_agent.to_string(), + }) + .unwrap(); + dna.update_modifiers(DnaModifiersOpt { + network_seed: None, + properties: Some(properties), + origin_time: None, + quantum_time: None, + }) +} + +pub struct TestSetup { + pub conductors: SweetConductorBatch, + cells: Vec, +} + +impl TestSetup { + pub async fn new(user_count: usize) -> Self { + // Set up conductors + let mut conductors: SweetConductorBatch = + SweetConductorBatch::from_config(1 + user_count, ConductorConfig::default()).await; + + let authority_agent_pubkey = SweetAgents::one(conductors[0].keystore()).await; + + let dnas = &[holoom_dna_with_authority(&authority_agent_pubkey).await]; + + let authority_app = conductors[0] + .setup_app_for_agent("holoom", authority_agent_pubkey.clone(), dnas) + .await + .unwrap(); + let (authority_cell,) = authority_app.into_tuple(); + let mut cells = Vec::from([authority_cell]); + for i in 1..1 + user_count { + let user_app = conductors[i].setup_app("holoom", dnas).await.unwrap(); + let (user_cell,) = user_app.into_tuple(); + cells.push(user_cell); + } + + TestSetup { conductors, cells } + } + + pub async fn authority_only() -> Self { + Self::new(0).await + } + + pub async fn authority_and_alice() -> Self { + Self::new(1).await + } + + //pub async fn authority_and_alice_bob() -> Self { + // Self::new(2).await + // } + + pub async fn authority_call( + &self, + zome_name: &str, + fn_name: &str, + payload: I, + ) -> ConductorApiResult + where + I: serde::Serialize + std::fmt::Debug, + O: serde::de::DeserializeOwned + std::fmt::Debug, + { + self.conductors[0] + .call_fallible(&self.cells[0].zome(zome_name), fn_name, payload) + .await + } + + pub async fn alice_call( + &self, + zome_name: &str, + fn_name: &str, + payload: I, + ) -> ConductorApiResult + where + I: serde::Serialize + std::fmt::Debug, + O: serde::de::DeserializeOwned + std::fmt::Debug, + { + self.conductors[1] + .call_fallible(&self.cells[1].zome(zome_name), fn_name, payload) + .await + } + + /*pub async fn bob_call( + &self, + zome_name: &str, + fn_name: &str, + payload: I, + ) -> ConductorApiResult + where + I: serde::Serialize + std::fmt::Debug, + O: serde::de::DeserializeOwned + std::fmt::Debug, + { + self.conductors[2] + .call_fallible(&self.cells[2].zome(zome_name), fn_name, payload) + .await + }*/ + + pub fn authority_pubkey(&self) -> AgentPubKey { + self.cells[0].agent_pubkey().clone() + } + + pub fn alice_pubkey(&self) -> AgentPubKey { + self.cells[1].agent_pubkey().clone() + } + + //pub fn bob_pubkey(&self) -> AgentPubKey { + // self.cells[1].agent_pubkey().clone() + //} + + pub async fn consistency(&self) { + await_consistency(Duration::from_secs(60), self.cells.iter()) + .await + .unwrap(); + } +} diff --git a/crates/username_attestation/coordinator/tests/username_attestation.rs b/crates/username_attestation/coordinator/tests/username_attestation.rs new file mode 100644 index 0000000..c5bedb6 --- /dev/null +++ b/crates/username_attestation/coordinator/tests/username_attestation.rs @@ -0,0 +1,424 @@ +use hdk::prelude::*; +use holochain::conductor::api::error::ConductorApiError; +use holoom_types::{SignableBytes, SignedUsername, UsernameAttestation}; +mod config; +use config::TestSetup; + +#[cfg(test)] + +#[tokio::test(flavor = "multi_thread")] +async fn only_authority_can_create_username_attestation() { + let setup = TestSetup::authority_and_alice().await; + + // Authority creates a UsernameAttestation for alice + let _: Record = setup + .authority_call( + "username_attestation", + "create_username_attestation", + UsernameAttestation { + username: "a_cool_guy1".into(), + agent: setup.alice_pubkey(), + }, + ) + .await + .unwrap(); + + // Alice cannot create an UsernameAttestation + let result: Result = setup + .alice_call( + "username_attestation", + "create_username_attestation", + UsernameAttestation { + username: "a_cool_guy2".into(), + agent: setup.alice_pubkey(), + }, + ) + .await; + + assert!(result.is_err()); +} + +#[tokio::test(flavor = "multi_thread")] +async fn same_username_cannot_be_registered_twice() { + // Set up conductors + let setup = TestSetup::authority_only().await; + + // Authority creates an UsernameAttestation + let _: Record = setup + .authority_call( + "username_attestation", + "create_username_attestation", + UsernameAttestation { + username: "a_cool_guy".into(), + agent: fake_agent_pub_key(0), + }, + ) + .await + .unwrap(); + + // Authority creates a UsernameAttestation with an identical username + let result: Result = setup + .authority_call( + "username_attestation", + "create_username_attestation", + UsernameAttestation { + username: "a_cool_guy".into(), + agent: fake_agent_pub_key(1), + }, + ) + .await; + + assert!(result.is_err()); + + // Authority creates a UsernameAttestation with a different username + let _: Record = setup + .authority_call( + "username_attestation", + "create_username_attestation", + UsernameAttestation { + username: "a_cool_guy2".into(), + agent: fake_agent_pub_key(2), + }, + ) + .await + .unwrap(); +} + +#[tokio::test(flavor = "multi_thread")] +async fn same_agent_cannot_be_registered_twice() { + // Set up conductors + let setup = TestSetup::authority_only().await; + + // Authority creates an UsernameAttestation + let _: Record = setup + .authority_call( + "username_attestation", + "create_username_attestation", + UsernameAttestation { + username: "a_cool_guy".into(), + agent: fake_agent_pubkey_1(), + }, + ) + .await + .unwrap(); + + // Authority creates a UsernameAttestation with an identical agent + let result: Result = setup + .authority_call( + "username_attestation", + "create_username_attestation", + UsernameAttestation { + username: "a_different_guy".into(), + agent: fake_agent_pubkey_1(), + }, + ) + .await; + + assert!(result.is_err()); + + // Authority creates a UsernameAttestation with a different agent + let _: Record = setup + .authority_call( + "username_attestation", + "create_username_attestation", + UsernameAttestation { + username: "a_third_guy".into(), + agent: fake_agent_pubkey_2(), + }, + ) + .await + .unwrap(); +} + +#[tokio::test(flavor = "multi_thread")] +async fn username_must_be_within_character_limit() { + let setup = TestSetup::authority_only().await; + + // Authority creates an username of 5 characters + let result1: Result = setup + .authority_call( + "username_attestation", + "create_username_attestation", + UsernameAttestation { + username: "abcde".into(), + agent: fake_agent_pubkey_1(), + }, + ) + .await; + + assert!(result1.is_err()); + + // Alice creates an username of 33 characters + let result2: Result = setup + .authority_call( + "username_attestation", + "create_username_attestation", + UsernameAttestation { + username: "abcdeabcdeabcdeabcdeabcdeabcdeabc".into(), + agent: fake_agent_pubkey_1(), + }, + ) + .await; + + assert!(result2.is_err()); + + // Alice creates an username of 15 characters + let result3: Result = setup + .authority_call( + "username_attestation", + "create_username_attestation", + UsernameAttestation { + username: "abcdeabcdeabcde".into(), + agent: fake_agent_pubkey_1(), + }, + ) + .await; + + assert!(result3.is_ok()); +} + +#[tokio::test(flavor = "multi_thread")] +async fn nobody_can_delete_username_attestation() { + let setup = TestSetup::authority_and_alice().await; + setup.conductors.exchange_peer_info().await; + + // Authority creates a UsernameAttestation + let record: Record = setup + .authority_call( + "username_attestation", + "create_username_attestation", + UsernameAttestation { + username: "asodijsadvjsadlkj".into(), + agent: fake_agent_pubkey_1(), + }, + ) + .await + .unwrap(); + + setup.consistency().await; + + // Authority cannot delete a UsernameAttestation + let result: Result = setup + .authority_call( + "username_attestation", + "delete_username_attestation", + record.action_address(), + ) + .await; + + assert!(result.is_err()); + + // Alice cannot delete a UsernameAttestation + let result2: Result = setup + .alice_call( + "username_attestation", + "delete_username_attestation", + record.action_address(), + ) + .await; + + assert!(result2.is_err()); +} + +#[tokio::test(flavor = "multi_thread")] +async fn all_can_get_username_attestations() { + let setup = TestSetup::authority_and_alice().await; + setup.conductors.exchange_peer_info().await; + + // Authority creates an UsernameAttestation + let record: Record = setup + .authority_call( + "username_attestation", + "create_username_attestation", + UsernameAttestation { + username: "asodijsadvjsadlkj".into(), + agent: fake_agent_pubkey_1(), + }, + ) + .await + .unwrap(); + + setup.consistency().await; + + // Authority gets the UsernameAttestation + let maybe_record: Option = setup + .authority_call( + "username_attestation", + "get_username_attestation", + record.action_address(), + ) + .await + .unwrap(); + + assert!(maybe_record.is_some()); + + // Alice gets the UsernameAttestation + let maybe_record2: Option = setup + .alice_call( + "username_attestation", + "get_username_attestation", + record.action_address(), + ) + .await + .unwrap(); + + assert!(maybe_record2.is_some()); +} + +#[tokio::test(flavor = "multi_thread")] +async fn all_can_get_username_attestation_for_agent() { + let setup = TestSetup::authority_and_alice().await; + setup.conductors.exchange_peer_info().await; + + // Authority's complete list of attestations initially empty + let all_records1: Vec = setup + .authority_call("username_attestation", "get_all_username_attestations", ()) + .await + .unwrap(); + assert_eq!(all_records1, vec![]); + + // Authority creates an UsernameAttestation + let _: Record = setup + .authority_call( + "username_attestation", + "create_username_attestation", + UsernameAttestation { + username: "username1".into(), + agent: fake_agent_pubkey_1(), + }, + ) + .await + .unwrap(); + + // Authority gets the UsernameAttestation + let maybe_record: Option = setup + .authority_call( + "username_attestation", + "get_username_attestation_for_agent", + fake_agent_pubkey_1(), + ) + .await + .unwrap(); + let entry = maybe_record + .clone() + .unwrap() + .entry() + .to_app_option::() + .unwrap() + .unwrap(); + + assert_eq!(entry.username, "username1"); + assert_eq!(entry.agent, fake_agent_pubkey_1()); + + // Alice gets the UsernameAttestation + setup.consistency().await; + + let maybe_record2: Option = setup + .alice_call( + "username_attestation", + "get_username_attestation_for_agent", + fake_agent_pubkey_1(), + ) + .await + .unwrap(); + let entry2 = maybe_record2 + .unwrap() + .entry() + .to_app_option::() + .unwrap() + .unwrap(); + + assert_eq!(entry2.username, "username1"); + assert_eq!(entry2.agent, fake_agent_pubkey_1()); + + // Authority can see the attestation in their complete list + let all_records2: Vec = setup + .authority_call("username_attestation", "get_all_username_attestations", ()) + .await + .unwrap(); + assert_eq!(all_records2, vec![maybe_record.unwrap()]); +} + +#[tokio::test(flavor = "multi_thread")] +async fn cannot_get_username_attestation_for_agent_that_doesnt_exist() { + let setup = TestSetup::authority_only().await; + + // Authority tries to get UsernameAttestation + let res: Option = setup + .authority_call( + "username_attestation", + "get_username_attestation_for_agent", + fake_agent_pubkey_1(), + ) + .await + .unwrap(); + + assert!(res.is_none()); +} + +#[tokio::test(flavor = "multi_thread")] +async fn can_attest_username_via_remote_call() { + let setup = TestSetup::authority_and_alice().await; + setup.conductors.exchange_peer_info().await; + + // Alice creates a UsernameAttestation + let record: Record = setup + .alice_call( + "username_attestation", + "sign_username_to_attest", + "asodijsadvjsadlkj".to_string(), + ) + .await + .unwrap(); + + setup.consistency().await; + + // UsernameAttestation has been created + let result: Result, ConductorApiError> = setup + .authority_call( + "username_attestation", + "get_username_attestation", + record.action_address(), + ) + .await; + + let same_record = result + .expect(" get_username_attestation should have succeeded") + .expect("Record should exist"); + assert_eq!(same_record.action_address(), record.action_address()); + let entry = record + .entry() + .to_app_option::() + .unwrap() + .unwrap(); + assert_ne!(entry.agent, setup.authority_pubkey()); + assert_eq!(entry.agent, setup.alice_pubkey()); +} + +#[tokio::test(flavor = "multi_thread")] +async fn authority_wont_ingest_invalid_username_signature() { + let setup = TestSetup::authority_and_alice().await; + setup.conductors.exchange_peer_info().await; + + // Alice signs username + let signature: Signature = setup + .alice_call("username_attestation", "sign_message", SignableBytes("whatever".into())) + .await + .unwrap(); + let invalid_signed_username = SignedUsername { + username: "a_different_name".into(), + signature, + signer: setup.alice_pubkey(), + }; + + // Authority ingests signed username + let result: Result = setup + .authority_call( + "username_attestation", + "ingest_signed_username", + invalid_signed_username, + ) + .await; + + assert!(result.is_err()); +} diff --git a/crates/username_attestation/integrity/Cargo.toml b/crates/username_attestation/integrity/Cargo.toml new file mode 100644 index 0000000..043e994 --- /dev/null +++ b/crates/username_attestation/integrity/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "username_attestation_integrity" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "username_attestation_integrity" + +[dependencies] +hdi = { workspace = true } +serde = { workspace = true } +holoom_types = { workspace = true } +shared_utils = { workspace = true } +bincode = { workspace = true } \ No newline at end of file diff --git a/crates/username_attestation/integrity/src/agent_username_attestation.rs b/crates/username_attestation/integrity/src/agent_username_attestation.rs new file mode 100644 index 0000000..471cb08 --- /dev/null +++ b/crates/username_attestation/integrity/src/agent_username_attestation.rs @@ -0,0 +1,42 @@ +use hdi::prelude::*; +use holoom_types::UsernameAttestation; +use shared_utils::get_authority_agent; + +pub fn validate_create_link_agent_to_username_attestations( + action: CreateLink, + _base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + // Only the authority can create link + let authority_agent = get_authority_agent()?; + if action.author != authority_agent { + return Ok(ValidateCallbackResult::Invalid( + "Only the Username Registry Authority can create attestation links".into(), + )); + } + + // Check the entry type for the given action hash + let action_hash = ActionHash::try_from(target_address).map_err(|e| wasm_error!(e))?; + let record = must_get_valid_record(action_hash)?; + let _username_attestation: UsernameAttestation = record + .entry() + .to_app_option() + .map_err(|e| wasm_error!(e))? + .ok_or(wasm_error!(WasmErrorInner::Guest(String::from( + "Linked action must reference an entry" + ))))?; + + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_delete_link_agent_to_username_attestations( + _action: DeleteLink, + _original_action: CreateLink, + _base: AnyLinkableHash, + _target: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + Ok(ValidateCallbackResult::Invalid(String::from( + "Username Attestation links cannot be deleted", + ))) +} diff --git a/crates/username_attestation/integrity/src/entry_types.rs b/crates/username_attestation/integrity/src/entry_types.rs new file mode 100644 index 0000000..50ea9fd --- /dev/null +++ b/crates/username_attestation/integrity/src/entry_types.rs @@ -0,0 +1,25 @@ +use hdi::prelude::*; +use holoom_types::UsernameAttestation; +use crate::username_attestation::*; +//use external_attestation_validation::*; + +#[derive(Serialize, Deserialize)] +#[serde(tag = "type")] +#[hdk_entry_types] +#[unit_enum(UnitEntryTypes)] +pub enum EntryTypes { + UsernameAttestation(UsernameAttestation), +} + +impl EntryTypes { + pub fn validate_create(self, action: Create) -> ExternResult { + match self { + EntryTypes::UsernameAttestation(username_attestation) => { + validate_create_username_attestation( + EntryCreationAction::Create(action), + username_attestation, + ) + } + } + } +} diff --git a/crates/username_attestation/integrity/src/lib.rs b/crates/username_attestation/integrity/src/lib.rs new file mode 100644 index 0000000..2310b88 --- /dev/null +++ b/crates/username_attestation/integrity/src/lib.rs @@ -0,0 +1,140 @@ +use hdi::prelude::*; +pub mod entry_types; +pub use entry_types::*; +pub mod link_types; +pub use link_types::*; +pub mod username_attestation; +pub use username_attestation::*; +pub mod agent_username_attestation; +pub use agent_username_attestation::*; +pub mod user_metadata; +pub use user_metadata::*; + +#[hdk_extern] +pub fn genesis_self_check(_data: GenesisSelfCheckData) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_agent_joining( + _agent_pub_key: AgentPubKey, + _membrane_proof: &Option, +) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} +#[hdk_extern] +pub fn validate(op: Op) -> ExternResult { + match op.flattened::()? { + FlatOp::StoreEntry(store_entry) => match store_entry { + OpEntry::CreateEntry { app_entry, action } => app_entry.validate_create(action), + OpEntry::UpdateEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + _ => Ok(ValidateCallbackResult::Valid), + }, + FlatOp::RegisterUpdate(update_entry) => match update_entry { + OpUpdate::Entry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + _ => Ok(ValidateCallbackResult::Valid), + }, + FlatOp::RegisterDelete(_) => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be deleted".into(), + )), + FlatOp::RegisterCreateLink { + link_type, + base_address, + target_address, + tag, + action, + } => link_type.validate_create(action, base_address, target_address, tag), + FlatOp::RegisterDeleteLink { + link_type, + base_address, + target_address, + tag, + original_action, + action, + } => link_type.validate_delete(action, original_action, base_address, target_address, tag), + FlatOp::StoreRecord(store_record) => { + match store_record { + OpRecord::CreateEntry { app_entry, action } => app_entry.validate_create(action), + OpRecord::UpdateEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + OpRecord::DeleteEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be deleted".into(), + )), + OpRecord::CreateLink { + base_address, + target_address, + tag, + link_type, + action, + } => link_type.validate_create(action, base_address, target_address, tag), + OpRecord::DeleteLink { + original_action_hash, + base_address, + action, + } => { + let record = must_get_valid_record(original_action_hash)?; + let create_link = match record.action() { + Action::CreateLink(create_link) => create_link.clone(), + _ => { + return Ok(ValidateCallbackResult::Invalid( + "The action that a DeleteLink deletes must be a CreateLink" + .to_string(), + )); + } + }; + let link_type = match LinkTypes::from_type( + create_link.zome_index, + create_link.link_type, + )? { + Some(lt) => lt, + None => { + // @todo This must be treated as valid due to holochain bug + // see https://github.com/holochain/holochain/issues/2868 + return Ok(ValidateCallbackResult::Valid); + } + }; + link_type.validate_delete( + action, + create_link.clone(), + base_address, + create_link.target_address, + create_link.tag, + ) + } + OpRecord::CreatePrivateEntry { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdatePrivateEntry { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CreateCapClaim { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CreateCapGrant { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdateCapClaim { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdateCapGrant { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::Dna { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::OpenChain { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CloseChain { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::InitZomesComplete { .. } => Ok(ValidateCallbackResult::Valid), + _ => Ok(ValidateCallbackResult::Valid), + } + } + FlatOp::RegisterAgentActivity(agent_activity) => match agent_activity { + OpActivity::CreateAgent { agent, action } => { + let previous_action = must_get_action(action.prev_action)?; + match previous_action.action() { + Action::AgentValidationPkg( + AgentValidationPkg { membrane_proof, .. }, + ) => validate_agent_joining(agent, membrane_proof), + _ => { + Ok( + ValidateCallbackResult::Invalid( + "The previous action for a `CreateAgent` action must be an `AgentValidationPkg`" + .to_string(), + ), + ) + } + } + } + _ => Ok(ValidateCallbackResult::Valid), + }, + } +} diff --git a/crates/username_attestation/integrity/src/link_types.rs b/crates/username_attestation/integrity/src/link_types.rs new file mode 100644 index 0000000..a890a7b --- /dev/null +++ b/crates/username_attestation/integrity/src/link_types.rs @@ -0,0 +1,64 @@ +use hdi::prelude::*; +use crate::agent_username_attestation::*; +use crate::user_metadata::*; +//use external_attestation_validation::*; + +#[derive(Serialize, Deserialize)] +#[hdk_link_types] +pub enum LinkTypes { + AgentToUsernameAttestations, + AgentMetadata, + +} + +impl LinkTypes { + pub fn validate_create( + self, + action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + tag: LinkTag, + ) -> ExternResult { + match self { + LinkTypes::AgentToUsernameAttestations => { + validate_create_link_agent_to_username_attestations( + action, + base_address, + target_address, + tag, + ) + } + LinkTypes::AgentMetadata => { + validate_create_link_user_metadata(action, base_address, target_address, tag) + } + } + } + + pub fn validate_delete( + self, + action: DeleteLink, + original_action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + tag: LinkTag, + ) -> ExternResult { + match self { + LinkTypes::AgentToUsernameAttestations => { + validate_delete_link_agent_to_username_attestations( + action, + original_action, + base_address, + target_address, + tag, + ) + } + LinkTypes::AgentMetadata => validate_delete_link_user_metadata( + action, + original_action, + base_address, + target_address, + tag, + ), + } + } +} diff --git a/crates/username_registry_validation/src/user_metadata.rs b/crates/username_attestation/integrity/src/user_metadata.rs similarity index 100% rename from crates/username_registry_validation/src/user_metadata.rs rename to crates/username_attestation/integrity/src/user_metadata.rs diff --git a/crates/username_attestation/integrity/src/username_attestation.rs b/crates/username_attestation/integrity/src/username_attestation.rs new file mode 100644 index 0000000..ccfc901 --- /dev/null +++ b/crates/username_attestation/integrity/src/username_attestation.rs @@ -0,0 +1,92 @@ +use hdi::prelude::*; +use holoom_types::UsernameAttestation; +use shared_utils::get_authority_agent; + +pub fn validate_create_username_attestation( + action: EntryCreationAction, + username_attestation: UsernameAttestation, +) -> ExternResult { + // Username length is 6-32 characters + let username_len = username_attestation.username.chars().count(); + if !(6..=32).contains(&username_len) { + return Ok(ValidateCallbackResult::Invalid( + "Username must be between 6-32 characters".into(), + )); + } + + // Only the authority can publish + let authority_agent = get_authority_agent()?; + if action.author() != &authority_agent { + return Ok(ValidateCallbackResult::Invalid( + "Only the Username Registry Authority can create attestations".into(), + )); + } + + let agent_activity = must_get_agent_activity( + authority_agent.clone(), + ChainFilter::new(action.prev_action().clone()).include_cached_entries(), + )?; + let created_usernames: Vec = agent_activity + .into_iter() + .filter_map( + |agent_activity| match agent_activity.action.action().action_type() { + ActionType::Create => agent_activity + .action + .clone() + .action() + .entry_type() + .and_then(|entry_type: &EntryType| match entry_type.clone() { + EntryType::App(app_entry_def) => { + match (app_entry_def.zome_index, app_entry_def.entry_index) { + (ZomeIndex(0), EntryDefIndex(0)) => Some(agent_activity), + _ => None, + } + } + _ => None, + }), + _ => None, + }, + ) + .filter_map(|agent_activity| { + agent_activity + .action + .action() + .entry_data() + .and_then(|(entry_hash, ..)| { + must_get_entry(entry_hash.clone()) + .ok() + .and_then(|entry| UsernameAttestation::try_from(entry.as_content()).ok()) + }) + }) + .collect(); + + // Each username is unique + let identical_usernames_count = created_usernames + .clone() + .into_iter() + .filter(|ua| ua.username == username_attestation.username) + .count(); + + if identical_usernames_count > 0 { + return Ok(ValidateCallbackResult::Invalid(format!( + "Username {:} has already been registered", + username_attestation.username + ))); + } + + // Each agent is unique + let identical_agents_count = created_usernames + .clone() + .iter() + .filter(|ua| ua.agent == username_attestation.agent) + .count(); + + if identical_agents_count > 0 { + return Ok(ValidateCallbackResult::Invalid(format!( + "Agent {:} has already set a Username", + username_attestation.agent + ))); + } + + Ok(ValidateCallbackResult::Valid) +} diff --git a/crates/wallet_attestation/coordinator/Cargo.toml b/crates/wallet_attestation/coordinator/Cargo.toml new file mode 100644 index 0000000..4ee5c6f --- /dev/null +++ b/crates/wallet_attestation/coordinator/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "wallet_attestation" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "wallet_attestation" + +[dependencies] +hdk = { workspace = true } +serde = { workspace = true } +holoom_types = { workspace = true } +shared_utils = { workspace = true } +wallet_attestation_integrity = { workspace = true } + + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] #avoids mio bug +holochain = { workspace = true, default-features = false, features = ["test_utils"] } +tokio = "1.38.0" +ethers-signers = { workspace = true } +ed25519-dalek = { workspace = true } +bs58 = { workspace = true } + diff --git a/crates/wallet_attestation/coordinator/src/lib.rs b/crates/wallet_attestation/coordinator/src/lib.rs new file mode 100644 index 0000000..4f80099 --- /dev/null +++ b/crates/wallet_attestation/coordinator/src/lib.rs @@ -0,0 +1,26 @@ +pub mod wallet_attestation; +use hdk::prelude::*; +use shared_utils::get_authority_agent; + +#[hdk_extern] +pub fn init(_: ()) -> ExternResult { + let authority_agent = get_authority_agent()?; + let my_pubkey = agent_info()?.agent_initial_pubkey; + let mut functions = BTreeSet::new(); + let zome_name = zome_info()?.name; + if my_pubkey == authority_agent { + } + functions.insert((zome_name, "recv_remote_signal".into())); + create_cap_grant(CapGrantEntry { + tag: "".into(), + access: ().into(), + functions: GrantedFunctions::Listed(functions), + })?; + + Ok(InitCallbackResult::Pass) +} + +#[hdk_extern] +fn get_authority(_: ()) -> ExternResult { + get_authority_agent() +} diff --git a/crates/wallet_attestation/coordinator/src/wallet_attestation.rs b/crates/wallet_attestation/coordinator/src/wallet_attestation.rs new file mode 100644 index 0000000..d01eb5b --- /dev/null +++ b/crates/wallet_attestation/coordinator/src/wallet_attestation.rs @@ -0,0 +1,74 @@ +use hdk::prelude::*; +use holoom_types::{ChainWalletSignature, EvmAddress, SolanaAddress, WalletAttestation}; +use wallet_attestation_integrity::*; + +#[hdk_extern] +pub fn get_evm_wallet_binding_message(evm_address: EvmAddress) -> ExternResult { + let info = agent_info()?; + let message = evm_signing_message(&evm_address, info.agent_initial_pubkey, info.chain_head.0); + Ok(message) +} + +#[hdk_extern] +pub fn get_solana_wallet_binding_message(solana_address: SolanaAddress) -> ExternResult { + let info = agent_info()?; + let message = solana_signing_message( + &solana_address, + info.agent_initial_pubkey, + info.chain_head.0, + ); + Ok(message) +} + +#[hdk_extern] +pub fn attest_wallet_signature( + chain_wallet_signature: ChainWalletSignature, +) -> ExternResult { + let wallet_attestation = WalletAttestation { + agent: agent_info()?.agent_initial_pubkey, + chain_wallet_signature, + prev_action: agent_info()?.chain_head.0, + }; + create_wallet_attestation(wallet_attestation) +} + +#[hdk_extern] +pub fn create_wallet_attestation(wallet_attestation: WalletAttestation) -> ExternResult { + let wallet_attestation_hash = + create_entry(&EntryTypes::WalletAttestation(wallet_attestation.clone()))?; + create_link( + wallet_attestation.agent.clone(), + wallet_attestation_hash.clone(), + LinkTypes::AgentToWalletAttestations, + (), + )?; + let record = get(wallet_attestation_hash.clone(), GetOptions::network())?.ok_or( + wasm_error!(WasmErrorInner::Guest(String::from( + "Could not find the newly created WalletAttestation" + ))), + )?; + Ok(record) +} + +#[hdk_extern] +pub fn get_wallet_attestation(wallet_attestation_hash: ActionHash) -> ExternResult> { + get(wallet_attestation_hash, GetOptions::network()) +} + +#[hdk_extern] +pub fn get_wallet_attestations_for_agent(agent: AgentPubKey) -> ExternResult> { + get_links(GetLinksInputBuilder::try_new(agent, LinkTypes::AgentToWalletAttestations)?.build())? + .into_iter() + .map(|l| { + let record = get( + ActionHash::try_from(l.clone().target).unwrap(), + GetOptions::network(), + )?; + record.ok_or_else(|| { + wasm_error!(WasmErrorInner::Guest( + "Broken Wallet Attestation link".into() + )) + }) + }) + .collect::>>() +} diff --git a/crates/wallet_attestation/coordinator/tests/config.rs b/crates/wallet_attestation/coordinator/tests/config.rs new file mode 100644 index 0000000..9afae1e --- /dev/null +++ b/crates/wallet_attestation/coordinator/tests/config.rs @@ -0,0 +1,141 @@ +//use std::time::Duration; + +use hdk::prelude::*; +use holochain::{ + conductor::{api::error::ConductorApiResult, config::ConductorConfig}, + prelude::DnaFile, + sweettest::{SweetAgents, SweetCell, SweetConductorBatch, SweetDnaFile}, +}; +use holoom_types::HoloomDnaProperties; + +//#[cfg(test)] +//mod tests; + +async fn load_dna() -> DnaFile { + // Use prebuilt dna file + let dna_path = std::env::current_dir() + .unwrap() + .join("../../../workdir/holoom.dna"); + + SweetDnaFile::from_bundle(&dna_path).await.unwrap() +} + +pub async fn holoom_dna_with_authority(authority_agent: &AgentPubKey) -> DnaFile { + let dna = load_dna().await; + let properties = SerializedBytes::try_from(HoloomDnaProperties { + authority_agent: authority_agent.to_string(), + }) + .unwrap(); + dna.update_modifiers(DnaModifiersOpt { + network_seed: None, + properties: Some(properties), + origin_time: None, + quantum_time: None, + }) +} + +pub struct TestSetup { + pub conductors: SweetConductorBatch, + cells: Vec, +} + +impl TestSetup { + pub async fn new(user_count: usize) -> Self { + // Set up conductors + let mut conductors: SweetConductorBatch = + SweetConductorBatch::from_config(1 + user_count, ConductorConfig::default()).await; + + let authority_agent_pubkey = SweetAgents::one(conductors[0].keystore()).await; + + let dnas = &[holoom_dna_with_authority(&authority_agent_pubkey).await]; + + let authority_app = conductors[0] + .setup_app_for_agent("holoom", authority_agent_pubkey.clone(), dnas) + .await + .unwrap(); + let (authority_cell,) = authority_app.into_tuple(); + let mut cells = Vec::from([authority_cell]); + for i in 1..1 + user_count { + let user_app = conductors[i].setup_app("holoom", dnas).await.unwrap(); + let (user_cell,) = user_app.into_tuple(); + cells.push(user_cell); + } + + TestSetup { conductors, cells } + } + + //pub async fn authority_only() -> Self { + // Self::new(0).await + // } + + pub async fn authority_and_alice() -> Self { + Self::new(1).await + } + + //pub async fn authority_and_alice_bob() -> Self { + // Self::new(2).await + // } + + /*pub async fn authority_call( + &self, + zome_name: &str, + fn_name: &str, + payload: I, + ) -> ConductorApiResult + where + I: serde::Serialize + std::fmt::Debug, + O: serde::de::DeserializeOwned + std::fmt::Debug, + { + self.conductors[0] + .call_fallible(&self.cells[0].zome(zome_name), fn_name, payload) + .await + }*/ + + pub async fn alice_call( + &self, + zome_name: &str, + fn_name: &str, + payload: I, + ) -> ConductorApiResult + where + I: serde::Serialize + std::fmt::Debug, + O: serde::de::DeserializeOwned + std::fmt::Debug, + { + self.conductors[1] + .call_fallible(&self.cells[1].zome(zome_name), fn_name, payload) + .await + } + + /*pub async fn bob_call( + &self, + zome_name: &str, + fn_name: &str, + payload: I, + ) -> ConductorApiResult + where + I: serde::Serialize + std::fmt::Debug, + O: serde::de::DeserializeOwned + std::fmt::Debug, + { + self.conductors[2] + .call_fallible(&self.cells[2].zome(zome_name), fn_name, payload) + .await + }*/ + + //pub fn authority_pubkey(&self) -> AgentPubKey { + // self.cells[0].agent_pubkey().clone() + // } + + pub fn alice_pubkey(&self) -> AgentPubKey { + self.cells[1].agent_pubkey().clone() + } + + //pub fn bob_pubkey(&self) -> AgentPubKey { + // self.cells[1].agent_pubkey().clone() + //} + + //pub async fn consistency(&self) { + // await_consistency(Duration::from_secs(60), self.cells.iter()) + // .await + // .unwrap(); + //} +} diff --git a/crates/wallet_attestation/coordinator/tests/wallet_attestation.rs b/crates/wallet_attestation/coordinator/tests/wallet_attestation.rs new file mode 100644 index 0000000..5727f34 --- /dev/null +++ b/crates/wallet_attestation/coordinator/tests/wallet_attestation.rs @@ -0,0 +1,152 @@ +use hdk::prelude::*; +use holochain::conductor::api::error::ConductorApiResult; +use holoom_types::{ChainWalletSignature, EvmAddress, EvmSignature, WalletAttestation}; +use wallet_attestation_integrity::{evm_signing_message, solana_signing_message}; +mod config; +use config::TestSetup; + +#[cfg(test)] + +#[tokio::test(flavor = "multi_thread")] +async fn checks_validity_of_evm_wallet_attestation() { + let setup = TestSetup::authority_and_alice().await; + + // Create WalletAttestation for alice at address 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 + + // First account of seed phrase: test test test test test test test test test test test junk + let signer_private_key = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; + use std::str::FromStr; + + use ethers_signers::{LocalWallet, Signer}; + let signer_wallet = LocalWallet::from_str(signer_private_key).unwrap(); + let wallet_address = signer_wallet.address(); + let wallet_address = EvmAddress::try_from(wallet_address.as_bytes()).unwrap(); + assert_eq!( + wallet_address.to_checksum(None), + String::from("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266") + ); + let message: String = setup + .alice_call( + "wallet_attestation", + "get_evm_wallet_binding_message", + wallet_address, + ) + .await + .unwrap(); + + let signature = signer_wallet.sign_message(message).await.unwrap(); + let signature_bytes = signature.to_vec(); + let signature = EvmSignature::try_from(&signature_bytes[..]).unwrap(); + + let chain_wallet_signature = ChainWalletSignature::Evm { + evm_address: wallet_address, + evm_signature: signature, + }; + + // Genuine attestation should be accepted + let res: ConductorApiResult = setup + .alice_call( + "wallet_attestation", + "attest_wallet_signature", + chain_wallet_signature, + ) + .await; + assert!(res.is_ok()); + + let prev_action = res.unwrap().action_address().clone(); + let malicious_message = + evm_signing_message(&wallet_address, fake_agent_pubkey_1(), prev_action.clone()); + let signature = signer_wallet.sign_message(malicious_message).await.unwrap(); + let signature_bytes = signature.to_vec(); + let signature = EvmSignature::try_from(&signature_bytes[..]).unwrap(); + + let malicious_attestation = WalletAttestation { + chain_wallet_signature: ChainWalletSignature::Evm { + evm_address: wallet_address, + evm_signature: signature, + }, + agent: setup.alice_pubkey(), + prev_action, + }; + + // Malicious attestation should be rejected + let res: ConductorApiResult = setup + .alice_call( + "wallet_attestation", + "create_wallet_attestation", + malicious_attestation, + ) + .await; + assert!(res.is_err()); +} + +#[tokio::test(flavor = "multi_thread")] +async fn checks_validity_of_solana_wallet_attestation() { + let setup = TestSetup::authority_and_alice().await; + + // Create WalletAttestation for alice at address oeYf6KAJkLYhBuR8CiGc6L4D4Xtfepr85fuDgA9kq96 + + // First account of seed phrase: test test test test test test test test test test test junk + let private_key = + "4Cfc4TJ6dsWwLcw8aJ5uhx7UJKPR5VGXTu2iJr5bVRoTDsxzb6qfJrzR5HNhBcwGwsXqGeHzDR3eUWLr7MRnska8"; + let private_key_bytes = bs58::decode(private_key).into_vec().unwrap(); + + use ed25519_dalek::{Signer, SigningKey, SECRET_KEY_LENGTH}; + + let signing_key = SigningKey::try_from(&private_key_bytes[..SECRET_KEY_LENGTH]).unwrap(); + let solana_address = signing_key.verifying_key(); + + assert_eq!( + bs58::encode(solana_address.as_bytes()).into_string(), + String::from("oeYf6KAJkLYhBuR8CiGc6L4D4Xtfepr85fuDgA9kq96") + ); + + let message: String = setup + .alice_call( + "wallet_attestation", + "get_solana_wallet_binding_message", + solana_address, + ) + .await + .unwrap(); + let solana_signature = signing_key.try_sign(message.as_bytes()).unwrap(); + + let chain_wallet_signature = ChainWalletSignature::Solana { + solana_address: Box::new(solana_address), + solana_signature, + }; + + // Genuine attestation should be accepted + let res: ConductorApiResult = setup + .alice_call( + "wallet_attestation", + "attest_wallet_signature", + chain_wallet_signature, + ) + .await; + assert!(res.is_ok()); + + let prev_action = res.unwrap().action_address().clone(); + let malicious_message = + solana_signing_message(&solana_address, fake_agent_pubkey_1(), prev_action.clone()); + let solana_signature = signing_key.try_sign(malicious_message.as_bytes()).unwrap(); + + let malicious_attestation = WalletAttestation { + chain_wallet_signature: ChainWalletSignature::Solana { + solana_address: Box::new(solana_address), + solana_signature, + }, + agent: setup.alice_pubkey(), + prev_action, + }; + + // Genuine attestation should be rejected + let res: ConductorApiResult = setup + .alice_call( + "wallet_attestation", + "create_wallet_attestation", + malicious_attestation, + ) + .await; + assert!(res.is_err()); +} diff --git a/crates/wallet_attestation/integrity/Cargo.toml b/crates/wallet_attestation/integrity/Cargo.toml new file mode 100644 index 0000000..3dfe82e --- /dev/null +++ b/crates/wallet_attestation/integrity/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "wallet_attestation_integrity" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "wallet_attestation_integrity" + +[dependencies] +hdi = { workspace = true } +serde = { workspace = true } +holoom_types = { workspace = true } +shared_utils = { workspace = true } +bs58 = { workspace = true } diff --git a/crates/username_registry_validation/src/agent_wallet_attestation.rs b/crates/wallet_attestation/integrity/src/agent_wallet_attestation.rs similarity index 100% rename from crates/username_registry_validation/src/agent_wallet_attestation.rs rename to crates/wallet_attestation/integrity/src/agent_wallet_attestation.rs diff --git a/crates/wallet_attestation/integrity/src/entry_types.rs b/crates/wallet_attestation/integrity/src/entry_types.rs new file mode 100644 index 0000000..7b485c9 --- /dev/null +++ b/crates/wallet_attestation/integrity/src/entry_types.rs @@ -0,0 +1,25 @@ +use hdi::prelude::*; +use holoom_types::WalletAttestation; +use crate::wallet_attestation::*; +//use external_attestation_validation::*; + +#[derive(Serialize, Deserialize)] +#[serde(tag = "type")] +#[hdk_entry_types] +#[unit_enum(UnitEntryTypes)] +pub enum EntryTypes { + WalletAttestation(WalletAttestation), +} + +impl EntryTypes { + pub fn validate_create(self, action: Create) -> ExternResult { + match self { + EntryTypes::WalletAttestation(wallet_attestation) => { + validate_create_wallet_attestation( + EntryCreationAction::Create(action), + wallet_attestation, + ) + } + } + } +} diff --git a/crates/wallet_attestation/integrity/src/lib.rs b/crates/wallet_attestation/integrity/src/lib.rs new file mode 100644 index 0000000..5b00408 --- /dev/null +++ b/crates/wallet_attestation/integrity/src/lib.rs @@ -0,0 +1,138 @@ +use hdi::prelude::*; +pub mod entry_types; +pub use entry_types::*; +pub mod link_types; +pub use link_types::*; +pub mod wallet_attestation; +pub use wallet_attestation::*; +pub mod agent_wallet_attestation; +pub use agent_wallet_attestation::*; + +#[hdk_extern] +pub fn genesis_self_check(_data: GenesisSelfCheckData) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_agent_joining( + _agent_pub_key: AgentPubKey, + _membrane_proof: &Option, +) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} +#[hdk_extern] +pub fn validate(op: Op) -> ExternResult { + match op.flattened::()? { + FlatOp::StoreEntry(store_entry) => match store_entry { + OpEntry::CreateEntry { app_entry, action } => app_entry.validate_create(action), + OpEntry::UpdateEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + _ => Ok(ValidateCallbackResult::Valid), + }, + FlatOp::RegisterUpdate(update_entry) => match update_entry { + OpUpdate::Entry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + _ => Ok(ValidateCallbackResult::Valid), + }, + FlatOp::RegisterDelete(_) => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be deleted".into(), + )), + FlatOp::RegisterCreateLink { + link_type, + base_address, + target_address, + tag, + action, + } => link_type.validate_create(action, base_address, target_address, tag), + FlatOp::RegisterDeleteLink { + link_type, + base_address, + target_address, + tag, + original_action, + action, + } => link_type.validate_delete(action, original_action, base_address, target_address, tag), + FlatOp::StoreRecord(store_record) => { + match store_record { + OpRecord::CreateEntry { app_entry, action } => app_entry.validate_create(action), + OpRecord::UpdateEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be updated".into(), + )), + OpRecord::DeleteEntry { .. } => Ok(ValidateCallbackResult::Invalid( + "App EntryTypes cannot be deleted".into(), + )), + OpRecord::CreateLink { + base_address, + target_address, + tag, + link_type, + action, + } => link_type.validate_create(action, base_address, target_address, tag), + OpRecord::DeleteLink { + original_action_hash, + base_address, + action, + } => { + let record = must_get_valid_record(original_action_hash)?; + let create_link = match record.action() { + Action::CreateLink(create_link) => create_link.clone(), + _ => { + return Ok(ValidateCallbackResult::Invalid( + "The action that a DeleteLink deletes must be a CreateLink" + .to_string(), + )); + } + }; + let link_type = match LinkTypes::from_type( + create_link.zome_index, + create_link.link_type, + )? { + Some(lt) => lt, + None => { + // @todo This must be treated as valid due to holochain bug + // see https://github.com/holochain/holochain/issues/2868 + return Ok(ValidateCallbackResult::Valid); + } + }; + link_type.validate_delete( + action, + create_link.clone(), + base_address, + create_link.target_address, + create_link.tag, + ) + } + OpRecord::CreatePrivateEntry { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdatePrivateEntry { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CreateCapClaim { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CreateCapGrant { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdateCapClaim { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::UpdateCapGrant { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::Dna { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::OpenChain { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::CloseChain { .. } => Ok(ValidateCallbackResult::Valid), + OpRecord::InitZomesComplete { .. } => Ok(ValidateCallbackResult::Valid), + _ => Ok(ValidateCallbackResult::Valid), + } + } + FlatOp::RegisterAgentActivity(agent_activity) => match agent_activity { + OpActivity::CreateAgent { agent, action } => { + let previous_action = must_get_action(action.prev_action)?; + match previous_action.action() { + Action::AgentValidationPkg( + AgentValidationPkg { membrane_proof, .. }, + ) => validate_agent_joining(agent, membrane_proof), + _ => { + Ok( + ValidateCallbackResult::Invalid( + "The previous action for a `CreateAgent` action must be an `AgentValidationPkg`" + .to_string(), + ), + ) + } + } + } + _ => Ok(ValidateCallbackResult::Valid), + }, + } +} diff --git a/crates/wallet_attestation/integrity/src/link_types.rs b/crates/wallet_attestation/integrity/src/link_types.rs new file mode 100644 index 0000000..150e5e1 --- /dev/null +++ b/crates/wallet_attestation/integrity/src/link_types.rs @@ -0,0 +1,50 @@ +use hdi::prelude::*; +use crate::agent_wallet_attestation::*; + +#[derive(Serialize, Deserialize)] +#[hdk_link_types] +pub enum LinkTypes { + AgentToWalletAttestations +} + +impl LinkTypes { + pub fn validate_create( + self, + action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + tag: LinkTag, + ) -> ExternResult { + match self { + LinkTypes::AgentToWalletAttestations => { + validate_create_link_agent_to_wallet_attestations( + action, + base_address, + target_address, + tag, + ) + } + } + } + + pub fn validate_delete( + self, + action: DeleteLink, + original_action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + tag: LinkTag, + ) -> ExternResult { + match self { + LinkTypes::AgentToWalletAttestations => { + validate_delete_link_agent_to_wallet_attestations( + action, + original_action, + base_address, + target_address, + tag, + ) + } + } + } +} diff --git a/crates/username_registry_validation/src/wallet_attestation.rs b/crates/wallet_attestation/integrity/src/wallet_attestation.rs similarity index 100% rename from crates/username_registry_validation/src/wallet_attestation.rs rename to crates/wallet_attestation/integrity/src/wallet_attestation.rs diff --git a/crates/holoom_dna_tests/Cargo.toml b/old_crates/holoom_dna_tests/Cargo.toml similarity index 100% rename from crates/holoom_dna_tests/Cargo.toml rename to old_crates/holoom_dna_tests/Cargo.toml diff --git a/crates/holoom_dna_tests/src/lib.rs b/old_crates/holoom_dna_tests/src/lib.rs similarity index 100% rename from crates/holoom_dna_tests/src/lib.rs rename to old_crates/holoom_dna_tests/src/lib.rs diff --git a/crates/holoom_dna_tests/src/tests/mod.rs b/old_crates/holoom_dna_tests/src/tests/mod.rs similarity index 100% rename from crates/holoom_dna_tests/src/tests/mod.rs rename to old_crates/holoom_dna_tests/src/tests/mod.rs diff --git a/crates/holoom_dna_tests/src/tests/signer.rs b/old_crates/holoom_dna_tests/src/tests/signer.rs similarity index 100% rename from crates/holoom_dna_tests/src/tests/signer.rs rename to old_crates/holoom_dna_tests/src/tests/signer.rs diff --git a/crates/holoom_dna_tests/src/tests/username_registry/external_id_attestation.rs b/old_crates/holoom_dna_tests/src/tests/username_registry/external_id_attestation.rs similarity index 100% rename from crates/holoom_dna_tests/src/tests/username_registry/external_id_attestation.rs rename to old_crates/holoom_dna_tests/src/tests/username_registry/external_id_attestation.rs diff --git a/crates/holoom_dna_tests/src/tests/username_registry/mod.rs b/old_crates/holoom_dna_tests/src/tests/username_registry/mod.rs similarity index 100% rename from crates/holoom_dna_tests/src/tests/username_registry/mod.rs rename to old_crates/holoom_dna_tests/src/tests/username_registry/mod.rs diff --git a/crates/holoom_dna_tests/src/tests/username_registry/oracle.rs b/old_crates/holoom_dna_tests/src/tests/username_registry/oracle.rs similarity index 100% rename from crates/holoom_dna_tests/src/tests/username_registry/oracle.rs rename to old_crates/holoom_dna_tests/src/tests/username_registry/oracle.rs diff --git a/crates/holoom_dna_tests/src/tests/username_registry/recipe.rs b/old_crates/holoom_dna_tests/src/tests/username_registry/recipe.rs similarity index 100% rename from crates/holoom_dna_tests/src/tests/username_registry/recipe.rs rename to old_crates/holoom_dna_tests/src/tests/username_registry/recipe.rs diff --git a/crates/holoom_dna_tests/src/tests/username_registry/user_metadata.rs b/old_crates/holoom_dna_tests/src/tests/username_registry/user_metadata.rs similarity index 100% rename from crates/holoom_dna_tests/src/tests/username_registry/user_metadata.rs rename to old_crates/holoom_dna_tests/src/tests/username_registry/user_metadata.rs diff --git a/crates/holoom_dna_tests/src/tests/username_registry/username_attestation.rs b/old_crates/holoom_dna_tests/src/tests/username_registry/username_attestation.rs similarity index 100% rename from crates/holoom_dna_tests/src/tests/username_registry/username_attestation.rs rename to old_crates/holoom_dna_tests/src/tests/username_registry/username_attestation.rs diff --git a/crates/holoom_dna_tests/src/tests/username_registry/wallet_attestation.rs b/old_crates/holoom_dna_tests/src/tests/username_registry/wallet_attestation.rs similarity index 100% rename from crates/holoom_dna_tests/src/tests/username_registry/wallet_attestation.rs rename to old_crates/holoom_dna_tests/src/tests/username_registry/wallet_attestation.rs diff --git a/old_crates/holoom_types/Cargo.toml b/old_crates/holoom_types/Cargo.toml new file mode 100644 index 0000000..83bc085 --- /dev/null +++ b/old_crates/holoom_types/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "holoom_types" +version = "0.0.3" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "holoom_types" + +[dependencies] +hdi = { workspace = true } +serde = { workspace = true } +alloy-primitives = { workspace = true } +ed25519-dalek = { workspace = true } +ts-rs = "9" diff --git a/old_crates/holoom_types/src/evm_signing_offer.rs b/old_crates/holoom_types/src/evm_signing_offer.rs new file mode 100644 index 0000000..905e2b2 --- /dev/null +++ b/old_crates/holoom_types/src/evm_signing_offer.rs @@ -0,0 +1,81 @@ +use hdi::prelude::*; +use serde::{Deserialize, Serialize}; +use ts_rs::TS; + +use crate::{EvmAddress, EvmSignature}; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, TS)] +#[serde(tag = "type")] +#[ts(export)] +pub enum EvmU256Item { + Uint, + Hex, + HoloAgent, +} + +#[derive(Clone, PartialEq, TS, Serialize, Deserialize, Debug)] +#[ts(export)] +pub struct EvmSigningOffer { + #[ts(type = "ActionHash")] + pub recipe_ah: ActionHash, + pub u256_items: Vec, +} + +#[hdk_entry_helper] +#[derive(Clone, PartialEq, TS)] +#[ts(export)] +pub struct SignedEvmSigningOffer { + #[ts(type = "Uint8Array")] + pub signer: EvmAddress, + #[ts(type = "[Uint8Array, Uint8Array, number]")] + pub signature: EvmSignature, + pub offer: EvmSigningOffer, +} + +#[derive(Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub struct CreateEvmSigningOfferPayload { + pub identifier: String, + pub signed_offer: SignedEvmSigningOffer, +} + +#[derive(Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub struct EvmSignatureOverRecipeExecutionRequest { + pub request_id: String, + #[ts(type = "ActionHash")] + pub recipe_execution_ah: ActionHash, + #[ts(type = "ActionHash")] + pub signing_offer_ah: ActionHash, +} + +#[derive(Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub struct ResolveEvmSignatureOverRecipeExecutionRequestPayload { + pub request_id: String, + #[ts(type = "AgentPubKey")] + pub requestor: AgentPubKey, + pub signed_u256_array: SignedEvmU256Array, +} + +#[derive(Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub struct RejectEvmSignatureOverRecipeExecutionRequestPayload { + pub request_id: String, + #[ts(type = "AgentPubKey")] + pub requestor: AgentPubKey, + pub reason: String, +} + +pub type EvmU256 = alloy_primitives::U256; + +#[derive(Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub struct SignedEvmU256Array { + #[ts(type = "Uint8Array[]")] + pub raw: Vec, + #[ts(type = "[Uint8Array, Uint8Array, number]")] + pub signature: EvmSignature, + #[ts(type = "Uint8Array")] + pub signer: EvmAddress, +} diff --git a/old_crates/holoom_types/src/external_id.rs b/old_crates/holoom_types/src/external_id.rs new file mode 100644 index 0000000..3eeb4cc --- /dev/null +++ b/old_crates/holoom_types/src/external_id.rs @@ -0,0 +1,49 @@ +use hdi::prelude::*; +use serde::{Deserialize, Serialize}; +use ts_rs::TS; + +#[hdk_entry_helper] +#[derive(Clone, PartialEq, TS)] +#[ts(export)] +pub struct ExternalIdAttestation { + pub request_id: String, + #[ts(type = "AgentPubKey")] + pub internal_pubkey: AgentPubKey, + pub external_id: String, + pub display_name: String, +} + +#[derive(Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub struct SendExternalIdAttestationRequestPayload { + pub request_id: String, + pub code_verifier: String, + pub code: String, +} + +#[derive(Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub struct IngestExternalIdAttestationRequestPayload { + pub request_id: String, + pub code_verifier: String, + pub code: String, +} + +#[derive(Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub struct ConfirmExternalIdRequestPayload { + pub request_id: String, + pub external_id: String, + pub display_name: String, + #[ts(type = "AgentPubKey")] + pub requestor: AgentPubKey, +} + +#[derive(Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub struct RejectExternalIdRequestPayload { + pub request_id: String, + #[ts(type = "AgentPubKey")] + pub requestor: AgentPubKey, + pub reason: String, +} diff --git a/old_crates/holoom_types/src/lib.rs b/old_crates/holoom_types/src/lib.rs new file mode 100644 index 0000000..a43508a --- /dev/null +++ b/old_crates/holoom_types/src/lib.rs @@ -0,0 +1,86 @@ +use evm_signing_offer::{EvmU256, SignedEvmU256Array}; +use hdi::prelude::*; +use serde::{Deserialize, Serialize}; +use ts_rs::TS; + +pub mod external_id; +pub use external_id::*; +pub mod evm_signing_offer; +pub mod metadata; +pub mod recipe; +pub use metadata::*; +pub mod wallet; +pub use wallet::*; +pub mod username; +pub use username::*; +pub mod oracle; +pub use oracle::*; + +#[derive(Serialize, Deserialize, Debug, TS)] +#[serde(tag = "type")] +#[ts(export)] +pub enum LocalHoloomSignal { + ExternalIdAttestationRequested { + request_id: String, + #[ts(type = "AgentPubKey")] + requestor_pubkey: AgentPubKey, + code_verifier: String, + code: String, + }, + ExternalIdAttested { + request_id: String, + #[ts(type = "Record")] + record: Record, + }, + ExternalIdRejected { + request_id: String, + reason: String, + }, + EvmSignatureRequested { + request_id: String, + #[ts(type = "AgentPubKey")] + requestor_pubkey: AgentPubKey, + #[ts(type = "Uint8Array[]")] + u256_array: Vec, + }, + EvmSignatureProvided { + request_id: String, + signed_u256_array: SignedEvmU256Array, + }, + EvmSignatureRequestRejected { + request_id: String, + reason: String, + }, +} + +#[derive(Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub enum RemoteHoloomSignal { + ExternalIdAttested { + request_id: String, + #[ts(type = "Record")] + record: Record, + }, + ExternalIdRejected { + request_id: String, + reason: String, + }, + EvmSignatureProvided { + request_id: String, + signed_u256_array: SignedEvmU256Array, + }, + EvmSignatureRequestRejected { + request_id: String, + reason: String, + }, +} + +#[derive(Serialize, Deserialize, Debug, Clone, SerializedBytes, TS)] +#[ts(export)] +pub struct SignableBytes(pub Vec); + +#[dna_properties] +#[derive(Clone)] +pub struct HoloomDnaProperties { + pub authority_agent: String, +} diff --git a/old_crates/holoom_types/src/metadata.rs b/old_crates/holoom_types/src/metadata.rs new file mode 100644 index 0000000..1ee6e4b --- /dev/null +++ b/old_crates/holoom_types/src/metadata.rs @@ -0,0 +1,27 @@ +use hdi::prelude::*; +use serde::{Deserialize, Serialize}; +use ts_rs::TS; + +#[derive(Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub struct MetadataItem { + pub name: String, + pub value: String, +} + +#[derive(Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub struct UpdateMetadataItemPayload { + #[ts(type = "AgentPubKey")] + pub agent_pubkey: AgentPubKey, + pub name: String, + pub value: String, +} + +#[derive(Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub struct GetMetadataItemValuePayload { + #[ts(type = "AgentPubKey")] + pub agent_pubkey: AgentPubKey, + pub name: String, +} diff --git a/old_crates/holoom_types/src/oracle.rs b/old_crates/holoom_types/src/oracle.rs new file mode 100644 index 0000000..7002a2e --- /dev/null +++ b/old_crates/holoom_types/src/oracle.rs @@ -0,0 +1,19 @@ +use hdi::prelude::*; +use serde::{Deserialize, Serialize}; +use ts_rs::TS; + +#[hdk_entry_helper] +#[derive(Clone, PartialEq, TS)] +#[ts(export)] +pub struct OracleDocument { + // E.g. organizers/1234/championship-ids + pub name: String, + pub json_data: String, +} + +#[derive(Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub struct DocumentRelationTag { + pub name: String, + pub relation: String, +} diff --git a/old_crates/holoom_types/src/recipe.rs b/old_crates/holoom_types/src/recipe.rs new file mode 100644 index 0000000..e11f2ce --- /dev/null +++ b/old_crates/holoom_types/src/recipe.rs @@ -0,0 +1,104 @@ +use hdi::prelude::*; +use serde::{Deserialize, Serialize}; +use ts_rs::TS; + +use crate::EvmAddress; + +#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, TS)] +#[ts(export)] +#[serde(tag = "type")] +pub enum RecipeArgumentType { + String, + EvmAddress, +} + +#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, TS)] +#[ts(export)] +#[serde(tag = "type")] +pub enum JqInstructionArgumentNames { + Single { var_name: String }, + List { var_names: Vec }, +} + +#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, TS)] +#[ts(export)] +#[serde(tag = "type")] +pub enum RecipeInstruction { + Constant { + value: String, + }, + GetLatestDocWithIdentifier { + var_name: String, + }, + Jq { + input_var_names: JqInstructionArgumentNames, + program: String, + }, + GetDocsListedByVar { + var_name: String, + }, + GetLatestCallerExternalId, + GetCallerAgentPublicKey, +} + +#[hdk_entry_helper] +#[derive(Clone, PartialEq, TS)] +#[ts(export)] +pub struct Recipe { + #[ts(type = "AgentPubKey[]")] + pub trusted_authors: Vec, + pub arguments: Vec<(String, RecipeArgumentType)>, + pub instructions: Vec<(String, RecipeInstruction)>, +} + +#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, TS)] +#[ts(export)] +#[serde(tag = "type")] +pub enum RecipeArgument { + String { + value: String, + }, + EvmAddress { + #[ts(type = "Uint8Array")] + value: EvmAddress, + }, +} + +#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub enum RecipeInstructionExecution { + Constant, // In memory + GetLatestDocWithIdentifier { + #[ts(type = "ActionHash")] + doc_ah: ActionHash, + }, + Jq, // In memory + GetDocsListedByVar { + #[ts(type = "ActionHash")] + doc_ahs: Vec, + }, + GetLatestCallerExternalId { + #[ts(type = "ActionHash")] + attestation_ah: ActionHash, + }, + GetCallerAgentPublicKey, // In memory +} + +#[hdk_entry_helper] +#[derive(Clone, PartialEq, TS)] +#[ts(export)] +pub struct RecipeExecution { + #[ts(type = "ActionHash")] + pub recipe_ah: ActionHash, + pub arguments: Vec, + pub instruction_executions: Vec, + pub output: String, +} + +#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub struct ExecuteRecipePayload { + #[ts(type = "ActionHash")] + pub recipe_ah: ActionHash, + pub arguments: Vec, +} diff --git a/old_crates/holoom_types/src/username.rs b/old_crates/holoom_types/src/username.rs new file mode 100644 index 0000000..e638c84 --- /dev/null +++ b/old_crates/holoom_types/src/username.rs @@ -0,0 +1,22 @@ +use hdi::prelude::*; +use serde::{Deserialize, Serialize}; +use ts_rs::TS; + +#[hdk_entry_helper] +#[derive(Clone, PartialEq, TS)] +#[ts(export)] +pub struct UsernameAttestation { + #[ts(type = "AgentPubKey")] + pub agent: AgentPubKey, + pub username: String, +} + +#[derive(Serialize, Deserialize, Debug, TS)] +#[ts(export)] +pub struct SignedUsername { + pub username: String, + #[ts(type = "Signature")] + pub signature: Signature, + #[ts(type = "AgentPubKey")] + pub signer: AgentPubKey, +} diff --git a/old_crates/holoom_types/src/wallet.rs b/old_crates/holoom_types/src/wallet.rs new file mode 100644 index 0000000..9495cb7 --- /dev/null +++ b/old_crates/holoom_types/src/wallet.rs @@ -0,0 +1,36 @@ +use hdi::prelude::*; +use serde::{Deserialize, Serialize}; +use ts_rs::TS; + +pub type EvmAddress = alloy_primitives::Address; +pub type EvmSignature = alloy_primitives::Signature; +pub type SolanaAddress = ed25519_dalek::VerifyingKey; +pub type SolanaSignature = ed25519_dalek::Signature; + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, TS)] +#[ts(export)] +pub enum ChainWalletSignature { + Evm { + #[ts(type = "Uint8Array")] + evm_address: EvmAddress, + #[ts(type = "[Uint8Array, Uint8Array, number]")] + evm_signature: EvmSignature, + }, + Solana { + #[ts(type = "Uint8Array")] + solana_address: Box, + #[ts(type = "number[]")] + solana_signature: SolanaSignature, + }, +} + +#[hdk_entry_helper] +#[derive(Clone, PartialEq, TS)] +#[ts(export)] +pub struct WalletAttestation { + #[ts(type = "AgentPubKey")] + pub agent: AgentPubKey, + pub chain_wallet_signature: ChainWalletSignature, + #[ts(type = "ActionHash")] + pub prev_action: ActionHash, +} diff --git a/old_crates/jaq_wrapper/Cargo.toml b/old_crates/jaq_wrapper/Cargo.toml new file mode 100644 index 0000000..09354de --- /dev/null +++ b/old_crates/jaq_wrapper/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "jaq_wrapper" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "jaq_wrapper" + +[dependencies] +hdi = { workspace = true } +jaq-interpret = { git = "https://github.com/8e8b2c/jaq", rev = "1870c7c" } +jaq-parse = { git = "https://github.com/8e8b2c/jaq", rev = "1870c7c" } +jaq-core = { git = "https://github.com/8e8b2c/jaq", rev = "1870c7c" } +jaq-std = { git = "https://github.com/8e8b2c/jaq", rev = "1870c7c" } +hifijson = "0.2.0" diff --git a/old_crates/jaq_wrapper/src/lib.rs b/old_crates/jaq_wrapper/src/lib.rs new file mode 100644 index 0000000..23a0e12 --- /dev/null +++ b/old_crates/jaq_wrapper/src/lib.rs @@ -0,0 +1,147 @@ +use hdi::prelude::*; +use jaq_interpret::{Ctx, Filter, FilterT, ParseCtx, RcIter}; +use std::io::{self, BufRead}; + +// Re-export Val +pub use jaq_interpret::Val; + +pub enum JqProgramInput { + Single(String), + Slurp(Vec), +} + +pub fn compile_and_run_jq(program_str: &str, input: JqProgramInput) -> ExternResult { + let filter = compile_filter(program_str)?; + let input = input.parse()?; + let output = run_filter(filter, input)?; + Ok(output.to_string()) +} + +impl JqProgramInput { + fn parse(self) -> ExternResult { + match self { + Self::Single(json) => parse_single_json(&json), + Self::Slurp(jsons) => { + let items = jsons + .into_iter() + .map(|json| parse_single_json(&json)) + .collect::>>()?; + Ok(Val::arr(items)) + } + } + } +} + +pub fn compile_filter(program_str: &str) -> ExternResult { + let (maybe_main, errs) = jaq_parse::parse(program_str, jaq_parse::main()); + + if !errs.is_empty() { + return Err(wasm_error!(format!( + "jq program compilation failed with {} error(s)", + errs.len() + ))); + } + let Some(main) = maybe_main else { + return Err(wasm_error!(String::from("no main filter"))); + }; + let mut defs = ParseCtx::new(vec![]); + defs.insert_natives(jaq_core::core()); + defs.insert_defs(jaq_std::std()); + let filter = defs.compile(main); + if !defs.errs.is_empty() { + return Err(wasm_error!(format!( + "jq program compilation failed with {} def error(s)", + defs.errs.len() + ))); + } + Ok(filter) +} + +pub fn run_filter(filter: Filter, input: Val) -> ExternResult { + // Seems jaq is designed to pipe errors forwards, whilst tracking a global reference - hence + // the iterator gubbins. + let vars = vec![]; + let inputs: Vec> = vec![Ok(input)]; + let iter = Box::new(inputs.into_iter()) as Box>; + let iter = RcIter::new(iter); + let ctx = Ctx::new(vars, &iter); + + // The above iterator dance makes it very hard for me to understand how to take just one item. + // As a workaround I use a for loop (which the compiler seems happy with) and then error if + // the loop repeats. + let mut looped_once = false; + let mut output: Option = None; + for input in &iter { + if looped_once { + return Err(wasm_error!(WasmErrorInner::Guest( + "Unexpected continued input".into() + ))); + } + let input = input.map_err(|err| { + wasm_error!(WasmErrorInner::Guest(format!( + "Error in jq program input: {}", + err + ))) + })?; + let mut outputs = filter + .run((ctx.clone(), input)) + .collect::, _>>() + .map_err(|err| { + wasm_error!(WasmErrorInner::Guest(format!( + "jq execution error: {}", + err + ))) + })?; + if outputs.len() > 1 { + return Err(wasm_error!(WasmErrorInner::Guest( + "Unexpected multiple outputs to jq program".into() + ))); + } + if let Some(val) = outputs.pop() { + output = Some(val); + } + looped_once = true; + } + output.ok_or(wasm_error!(WasmErrorInner::Guest( + "jq program produced no output".into() + ))) +} + +pub fn parse_single_json(json: &str) -> ExternResult { + let mut iter = json_read(json.as_bytes()); + let val = iter + .next() + .ok_or(wasm_error!(WasmErrorInner::Guest("No input parsed".into())))? + .map_err(|err| { + wasm_error!(WasmErrorInner::Guest(format!( + "Input parse failed: {}", + err + ))) + })?; + if iter.next().is_some() { + return Err(wasm_error!(WasmErrorInner::Guest( + "Unexpected continuation of input".into() + ))); + } + Ok(val) +} + +fn json_read<'a>(read: impl BufRead + 'a) -> impl Iterator> + 'a { + let mut lexer = hifijson::IterLexer::new(read.bytes()); + core::iter::from_fn(move || { + use hifijson::token::Lex; + let v = Val::parse(lexer.ws_token()?, &mut lexer); + Some(v.map_err(|e| core::mem::take(&mut lexer.error).unwrap_or_else(|| invalid_data(e)))) + }) +} + +fn invalid_data(e: impl std::error::Error + Send + Sync + 'static) -> std::io::Error { + io::Error::new(io::ErrorKind::InvalidData, e) +} + +// Regression test for https://github.com/holochain-open-dev/holoom/issues/59 +#[test] +fn no_undefined_vars() { + let result = compile_filter("$missing"); + assert!(result.is_err()) +} diff --git a/crates/ping_coordinator/Cargo.toml b/old_crates/ping_coordinator/Cargo.toml similarity index 100% rename from crates/ping_coordinator/Cargo.toml rename to old_crates/ping_coordinator/Cargo.toml diff --git a/crates/ping_coordinator/src/lib.rs b/old_crates/ping_coordinator/src/lib.rs similarity index 100% rename from crates/ping_coordinator/src/lib.rs rename to old_crates/ping_coordinator/src/lib.rs diff --git a/crates/records_coordinator/Cargo.toml b/old_crates/records_coordinator/Cargo.toml similarity index 100% rename from crates/records_coordinator/Cargo.toml rename to old_crates/records_coordinator/Cargo.toml diff --git a/crates/records_coordinator/src/lib.rs b/old_crates/records_coordinator/src/lib.rs similarity index 100% rename from crates/records_coordinator/src/lib.rs rename to old_crates/records_coordinator/src/lib.rs diff --git a/crates/signer_coordinator/Cargo.toml b/old_crates/signer_coordinator/Cargo.toml similarity index 100% rename from crates/signer_coordinator/Cargo.toml rename to old_crates/signer_coordinator/Cargo.toml diff --git a/crates/signer_coordinator/src/lib.rs b/old_crates/signer_coordinator/src/lib.rs similarity index 100% rename from crates/signer_coordinator/src/lib.rs rename to old_crates/signer_coordinator/src/lib.rs diff --git a/crates/username_registry_coordinator/Cargo.toml b/old_crates/username_registry_coordinator/Cargo.toml similarity index 100% rename from crates/username_registry_coordinator/Cargo.toml rename to old_crates/username_registry_coordinator/Cargo.toml diff --git a/crates/username_registry_coordinator/src/evm_signing_offer.rs b/old_crates/username_registry_coordinator/src/evm_signing_offer.rs similarity index 100% rename from crates/username_registry_coordinator/src/evm_signing_offer.rs rename to old_crates/username_registry_coordinator/src/evm_signing_offer.rs diff --git a/crates/username_registry_coordinator/src/external_id_attestation.rs b/old_crates/username_registry_coordinator/src/external_id_attestation.rs similarity index 100% rename from crates/username_registry_coordinator/src/external_id_attestation.rs rename to old_crates/username_registry_coordinator/src/external_id_attestation.rs diff --git a/crates/username_registry_coordinator/src/lib.rs b/old_crates/username_registry_coordinator/src/lib.rs similarity index 100% rename from crates/username_registry_coordinator/src/lib.rs rename to old_crates/username_registry_coordinator/src/lib.rs diff --git a/crates/username_registry_coordinator/src/oracle_document.rs b/old_crates/username_registry_coordinator/src/oracle_document.rs similarity index 100% rename from crates/username_registry_coordinator/src/oracle_document.rs rename to old_crates/username_registry_coordinator/src/oracle_document.rs diff --git a/crates/username_registry_coordinator/src/recipe.rs b/old_crates/username_registry_coordinator/src/recipe.rs similarity index 100% rename from crates/username_registry_coordinator/src/recipe.rs rename to old_crates/username_registry_coordinator/src/recipe.rs diff --git a/crates/username_registry_coordinator/src/recipe_execution.rs b/old_crates/username_registry_coordinator/src/recipe_execution.rs similarity index 100% rename from crates/username_registry_coordinator/src/recipe_execution.rs rename to old_crates/username_registry_coordinator/src/recipe_execution.rs diff --git a/crates/username_registry_coordinator/src/user_metadata.rs b/old_crates/username_registry_coordinator/src/user_metadata.rs similarity index 100% rename from crates/username_registry_coordinator/src/user_metadata.rs rename to old_crates/username_registry_coordinator/src/user_metadata.rs diff --git a/crates/username_registry_coordinator/src/username_attestation.rs b/old_crates/username_registry_coordinator/src/username_attestation.rs similarity index 100% rename from crates/username_registry_coordinator/src/username_attestation.rs rename to old_crates/username_registry_coordinator/src/username_attestation.rs diff --git a/crates/username_registry_coordinator/src/wallet_attestation.rs b/old_crates/username_registry_coordinator/src/wallet_attestation.rs similarity index 100% rename from crates/username_registry_coordinator/src/wallet_attestation.rs rename to old_crates/username_registry_coordinator/src/wallet_attestation.rs diff --git a/crates/username_registry_integrity/Cargo.toml b/old_crates/username_registry_integrity/Cargo.toml similarity index 100% rename from crates/username_registry_integrity/Cargo.toml rename to old_crates/username_registry_integrity/Cargo.toml diff --git a/crates/username_registry_integrity/src/entry_types.rs b/old_crates/username_registry_integrity/src/entry_types.rs similarity index 100% rename from crates/username_registry_integrity/src/entry_types.rs rename to old_crates/username_registry_integrity/src/entry_types.rs diff --git a/crates/username_registry_integrity/src/lib.rs b/old_crates/username_registry_integrity/src/lib.rs similarity index 100% rename from crates/username_registry_integrity/src/lib.rs rename to old_crates/username_registry_integrity/src/lib.rs diff --git a/crates/username_registry_integrity/src/link_types.rs b/old_crates/username_registry_integrity/src/link_types.rs similarity index 100% rename from crates/username_registry_integrity/src/link_types.rs rename to old_crates/username_registry_integrity/src/link_types.rs diff --git a/crates/username_registry_utils/Cargo.toml b/old_crates/username_registry_utils/Cargo.toml similarity index 100% rename from crates/username_registry_utils/Cargo.toml rename to old_crates/username_registry_utils/Cargo.toml diff --git a/crates/username_registry_utils/src/lib.rs b/old_crates/username_registry_utils/src/lib.rs similarity index 100% rename from crates/username_registry_utils/src/lib.rs rename to old_crates/username_registry_utils/src/lib.rs diff --git a/crates/username_registry_validation/Cargo.toml b/old_crates/username_registry_validation/Cargo.toml similarity index 100% rename from crates/username_registry_validation/Cargo.toml rename to old_crates/username_registry_validation/Cargo.toml diff --git a/crates/username_registry_validation/src/agent_external_id_attestation.rs b/old_crates/username_registry_validation/src/agent_external_id_attestation.rs similarity index 100% rename from crates/username_registry_validation/src/agent_external_id_attestation.rs rename to old_crates/username_registry_validation/src/agent_external_id_attestation.rs diff --git a/crates/username_registry_validation/src/agent_username_attestation.rs b/old_crates/username_registry_validation/src/agent_username_attestation.rs similarity index 100% rename from crates/username_registry_validation/src/agent_username_attestation.rs rename to old_crates/username_registry_validation/src/agent_username_attestation.rs diff --git a/old_crates/username_registry_validation/src/agent_wallet_attestation.rs b/old_crates/username_registry_validation/src/agent_wallet_attestation.rs new file mode 100644 index 0000000..6c506ec --- /dev/null +++ b/old_crates/username_registry_validation/src/agent_wallet_attestation.rs @@ -0,0 +1,52 @@ +use hdi::prelude::*; +use holoom_types::WalletAttestation; + +pub fn validate_create_link_agent_to_wallet_attestations( + action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + // Check the entry type for the given action hash + let action_hash = ActionHash::try_from(target_address).map_err(|e| wasm_error!(e))?; + let record = must_get_valid_record(action_hash)?; + let wallet_attestation: WalletAttestation = record + .entry() + .to_app_option() + .map_err(|e| wasm_error!(e))? + .ok_or(wasm_error!(WasmErrorInner::Guest(String::from( + "Linked action must reference an entry" + ))))?; + + if action.author != wallet_attestation.agent { + return Ok(ValidateCallbackResult::Invalid( + "Only the owner can create wallet attestation links".into(), + )); + } + let base_address_agent = match AgentPubKey::try_from(base_address) { + Ok(agent) => agent, + Err(_) => { + return Ok(ValidateCallbackResult::Invalid( + "Base address must be an agent".into(), + )); + } + }; + if wallet_attestation.agent != base_address_agent { + return Ok(ValidateCallbackResult::Invalid( + "Link must be from agent in attestation".into(), + )); + } + + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_delete_link_agent_to_wallet_attestations( + _action: DeleteLink, + _original_action: CreateLink, + _base: AnyLinkableHash, + _target: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + Ok(ValidateCallbackResult::Invalid(String::from( + "Wallet Attestation links cannot be deleted", + ))) +} diff --git a/crates/username_registry_validation/src/evm_address_to_signing_offer.rs b/old_crates/username_registry_validation/src/evm_address_to_signing_offer.rs similarity index 100% rename from crates/username_registry_validation/src/evm_address_to_signing_offer.rs rename to old_crates/username_registry_validation/src/evm_address_to_signing_offer.rs diff --git a/crates/username_registry_validation/src/evm_signing_offer.rs b/old_crates/username_registry_validation/src/evm_signing_offer.rs similarity index 100% rename from crates/username_registry_validation/src/evm_signing_offer.rs rename to old_crates/username_registry_validation/src/evm_signing_offer.rs diff --git a/crates/username_registry_validation/src/external_id_attestation.rs b/old_crates/username_registry_validation/src/external_id_attestation.rs similarity index 100% rename from crates/username_registry_validation/src/external_id_attestation.rs rename to old_crates/username_registry_validation/src/external_id_attestation.rs diff --git a/crates/username_registry_validation/src/external_id_to_attestation.rs b/old_crates/username_registry_validation/src/external_id_to_attestation.rs similarity index 100% rename from crates/username_registry_validation/src/external_id_to_attestation.rs rename to old_crates/username_registry_validation/src/external_id_to_attestation.rs diff --git a/crates/username_registry_validation/src/lib.rs b/old_crates/username_registry_validation/src/lib.rs similarity index 100% rename from crates/username_registry_validation/src/lib.rs rename to old_crates/username_registry_validation/src/lib.rs diff --git a/crates/username_registry_validation/src/name_oracle_document.rs b/old_crates/username_registry_validation/src/name_oracle_document.rs similarity index 100% rename from crates/username_registry_validation/src/name_oracle_document.rs rename to old_crates/username_registry_validation/src/name_oracle_document.rs diff --git a/crates/username_registry_validation/src/name_to_evm_signing_offer.rs b/old_crates/username_registry_validation/src/name_to_evm_signing_offer.rs similarity index 100% rename from crates/username_registry_validation/src/name_to_evm_signing_offer.rs rename to old_crates/username_registry_validation/src/name_to_evm_signing_offer.rs diff --git a/old_crates/username_registry_validation/src/name_to_recipe.rs b/old_crates/username_registry_validation/src/name_to_recipe.rs new file mode 100644 index 0000000..41d8bff --- /dev/null +++ b/old_crates/username_registry_validation/src/name_to_recipe.rs @@ -0,0 +1,21 @@ +use hdi::prelude::*; + +pub fn validate_create_link_name_to_recipe( + _action: CreateLink, + _base_address: AnyLinkableHash, + _target_address: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_delete_link_name_to_recipe( + _action: DeleteLink, + _original_action: CreateLink, + _base_address: AnyLinkableHash, + _target_address: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + Ok(ValidateCallbackResult::Invalid( + "Cannot delete NameToRecipe links".into(), + )) +} diff --git a/old_crates/username_registry_validation/src/oracle_document.rs b/old_crates/username_registry_validation/src/oracle_document.rs new file mode 100644 index 0000000..f69983f --- /dev/null +++ b/old_crates/username_registry_validation/src/oracle_document.rs @@ -0,0 +1,9 @@ +use hdi::prelude::*; +use holoom_types::OracleDocument; + +pub fn validate_create_oracle_document( + _action: EntryCreationAction, + _oracle_document: OracleDocument, +) -> ExternResult { + Ok(ValidateCallbackResult::Valid) +} diff --git a/old_crates/username_registry_validation/src/recipe.rs b/old_crates/username_registry_validation/src/recipe.rs new file mode 100644 index 0000000..0b0ad5f --- /dev/null +++ b/old_crates/username_registry_validation/src/recipe.rs @@ -0,0 +1,69 @@ +use hdi::prelude::*; +use holoom_types::recipe::{JqInstructionArgumentNames, Recipe, RecipeInstruction}; +use jaq_wrapper::compile_filter; + +pub fn validate_create_recipe( + _action: EntryCreationAction, + recipe: Recipe, +) -> ExternResult { + if recipe.trusted_authors.is_empty() { + return Ok(ValidateCallbackResult::Invalid( + "Recipe needs at least 1 trusted author".into(), + )); + } + + match recipe.instructions.last() { + None => { + return Ok(ValidateCallbackResult::Invalid( + "Recipe must contain at least 1 instruction".into(), + )) + } + Some((var_name, _)) => { + if var_name != "$return" { + return Ok(ValidateCallbackResult::Invalid( + "Last instruction must be named '$return'".into(), + )); + } + } + } + + let mut declared_vars_names: HashSet = HashSet::default(); + for (arg_name, _) in recipe.arguments { + declared_vars_names.insert(arg_name); + } + + for (out_var_name, inst) in recipe.instructions { + let var_dependencies = match inst { + RecipeInstruction::Constant { .. } + | RecipeInstruction::GetCallerAgentPublicKey + | RecipeInstruction::GetLatestCallerExternalId => Vec::new(), + RecipeInstruction::GetDocsListedByVar { var_name } => vec![var_name], + RecipeInstruction::GetLatestDocWithIdentifier { var_name } => vec![var_name], + RecipeInstruction::Jq { + input_var_names, + program, + } => { + if compile_filter(&program).is_err() { + return Ok(ValidateCallbackResult::Invalid("Invalid jq program".into())); + } + match input_var_names { + JqInstructionArgumentNames::List { var_names } => var_names, + JqInstructionArgumentNames::Single { var_name } => vec![var_name], + } + } + }; + for dependency in var_dependencies { + if !declared_vars_names.contains(&dependency) { + return Ok(ValidateCallbackResult::Invalid( + "var used before declaration".into(), + )); + } + } + if declared_vars_names.contains(&out_var_name) { + return Ok(ValidateCallbackResult::Invalid("var redeclared".into())); + } + declared_vars_names.insert(out_var_name); + } + + Ok(ValidateCallbackResult::Valid) +} diff --git a/crates/username_registry_validation/src/recipe_execution.rs b/old_crates/username_registry_validation/src/recipe_execution.rs similarity index 100% rename from crates/username_registry_validation/src/recipe_execution.rs rename to old_crates/username_registry_validation/src/recipe_execution.rs diff --git a/crates/username_registry_validation/src/relate_oracle_document_name.rs b/old_crates/username_registry_validation/src/relate_oracle_document_name.rs similarity index 100% rename from crates/username_registry_validation/src/relate_oracle_document_name.rs rename to old_crates/username_registry_validation/src/relate_oracle_document_name.rs diff --git a/old_crates/username_registry_validation/src/user_metadata.rs b/old_crates/username_registry_validation/src/user_metadata.rs new file mode 100644 index 0000000..06ef711 --- /dev/null +++ b/old_crates/username_registry_validation/src/user_metadata.rs @@ -0,0 +1,44 @@ +use hdi::prelude::*; +use holoom_types::MetadataItem; + +pub fn validate_create_link_user_metadata( + action: CreateLink, + base_address: AnyLinkableHash, + _target_address: AnyLinkableHash, + tag: LinkTag, +) -> ExternResult { + let agent_pubkey = AgentPubKey::try_from(base_address).map_err(|e| wasm_error!(e))?; + + if action.author != agent_pubkey { + return Ok(ValidateCallbackResult::Invalid( + "Only the owner can embed metadata in their link tags".into(), + )); + } + // The contents of the target_address is unused and irrelevant + + // Check the tag is valid + let _item: MetadataItem = bincode::deserialize(&tag.into_inner()).map_err(|_| { + wasm_error!(WasmErrorInner::Guest( + "Failed to deserialize MetadataItem".into() + )) + })?; + + Ok(ValidateCallbackResult::Valid) +} +pub fn validate_delete_link_user_metadata( + action: DeleteLink, + _original_action: CreateLink, + base_address: AnyLinkableHash, + _target_address: AnyLinkableHash, + _tag: LinkTag, +) -> ExternResult { + let agent_pubkey = AgentPubKey::try_from(base_address).map_err(|e| wasm_error!(e))?; + + if action.author != agent_pubkey { + return Ok(ValidateCallbackResult::Invalid( + "Only the owner can delete their metadata tags".into(), + )); + } + + Ok(ValidateCallbackResult::Valid) +} diff --git a/crates/username_registry_validation/src/username_attestation.rs b/old_crates/username_registry_validation/src/username_attestation.rs similarity index 100% rename from crates/username_registry_validation/src/username_attestation.rs rename to old_crates/username_registry_validation/src/username_attestation.rs diff --git a/old_crates/username_registry_validation/src/wallet_attestation.rs b/old_crates/username_registry_validation/src/wallet_attestation.rs new file mode 100644 index 0000000..5a01a56 --- /dev/null +++ b/old_crates/username_registry_validation/src/wallet_attestation.rs @@ -0,0 +1,109 @@ +use hdi::prelude::*; +use holoom_types::{ + ChainWalletSignature, EvmAddress, EvmSignature, SolanaAddress, SolanaSignature, + WalletAttestation, +}; + +pub fn evm_signing_message( + evm_address: &EvmAddress, + agent: AgentPubKey, + prev_action: ActionHash, +) -> String { + format!( + "Binding wallet:\n{}\n\nTo Holochain public key:\n{}\n\nCommitted after holochain action:\n{}", + evm_address.to_checksum(None), + holo_hash::HoloHashB64::<_>::from(agent), + holo_hash::HoloHashB64::<_>::from(prev_action) + ) +} + +pub fn solana_signing_message( + solana_address: &SolanaAddress, + agent: AgentPubKey, + prev_action: ActionHash, +) -> String { + format!( + "Binding Solana wallet:\n{}\n\nTo Holochain public key:\n{}\n\nCommitted after holochain action:\n{}", + bs58::encode(solana_address.as_bytes()).into_string(), + holo_hash::HoloHashB64::<_>::from(agent), + holo_hash::HoloHashB64::<_>::from(prev_action) + ) +} + +fn verify_evm_signature( + evm_signature: EvmSignature, + evm_address: EvmAddress, + agent: AgentPubKey, + prev_action: ActionHash, +) -> ExternResult { + let message = evm_signing_message(&evm_address, agent, prev_action); + match evm_signature.recover_address_from_msg(message) { + Ok(recovered_address) => { + if recovered_address == evm_address { + Ok(ValidateCallbackResult::Valid) + } else { + Ok(ValidateCallbackResult::Invalid(format!( + "Expected to recover {} from signature, but instead recovered {}", + evm_address.to_checksum(None), + recovered_address.to_checksum(None) + ))) + } + } + Err(_) => Ok(ValidateCallbackResult::Invalid( + "Invalid signature over wallet binding message".into(), + )), + } +} + +fn verify_solana_signature( + solana_signature: SolanaSignature, + solana_address: &SolanaAddress, + agent: AgentPubKey, + prev_action: ActionHash, +) -> ExternResult { + let message = solana_signing_message(solana_address, agent, prev_action); + match solana_address.verify_strict(message.as_bytes(), &solana_signature) { + Ok(()) => Ok(ValidateCallbackResult::Valid), + Err(_) => Ok(ValidateCallbackResult::Invalid( + "Invalid signature over wallet binding message".into(), + )), + } +} + +pub fn validate_create_wallet_attestation( + action: EntryCreationAction, + wallet_attestation: WalletAttestation, +) -> ExternResult { + if action.author() != &wallet_attestation.agent { + return Ok(ValidateCallbackResult::Invalid( + "Wallet cannot by attested by a different user".into(), + )); + } + // Including the previous action hash in the signing message ensures that signature was + // intended for a particular context, i.e. on the user's chain in this particular DHT. + if action.prev_action() != &wallet_attestation.prev_action { + return Ok(ValidateCallbackResult::Invalid( + "Previous action doesn't match".into(), + )); + } + match wallet_attestation.chain_wallet_signature { + ChainWalletSignature::Evm { + evm_address, + evm_signature, + } => verify_evm_signature( + evm_signature, + evm_address, + wallet_attestation.agent, + wallet_attestation.prev_action, + ), + ChainWalletSignature::Solana { + solana_address, + solana_signature, + } => verify_solana_signature( + solana_signature, + &solana_address, + wallet_attestation.agent, + wallet_attestation.prev_action, + ), + } +} diff --git a/scripts/build_dna.sh b/scripts/build_dna.sh index 560d0b8..9b7d54b 100755 --- a/scripts/build_dna.sh +++ b/scripts/build_dna.sh @@ -6,7 +6,8 @@ cd .. RUSTFLAGS='' CARGO_TARGET_DIR=target cargo build \ --release \ --target wasm32-unknown-unknown \ - --package '*_integrity' \ - --package '*_coordinator' + --workspace + # --package 'crates/username_attestation/*' + # --package 'external_attestation' hc dna pack workdir diff --git a/workdir/dna.yaml b/workdir/dna.yaml index 3038f16..24d63c2 100644 --- a/workdir/dna.yaml +++ b/workdir/dna.yaml @@ -7,23 +7,59 @@ integrity: authority_agent: ~ origin_time: 1695664357181911 zomes: - - name: username_registry_integrity + - name: external_attestation_integrity hash: ~ - bundled: "../target/wasm32-unknown-unknown/release/username_registry_integrity.wasm" + bundled: "../target/wasm32-unknown-unknown/release/external_attestation_integrity.wasm" + dependencies: ~ + - name: username_attestation_integrity + hash: ~ + bundled: "../target/wasm32-unknown-unknown/release/username_attestation_integrity.wasm" + dependencies: ~ + - name: wallet_attestation_integrity + hash: ~ + bundled: "../target/wasm32-unknown-unknown/release/wallet_attestation_integrity.wasm" + dependencies: ~ + - name: oracle_document_integrity + hash: ~ + bundled: "../target/wasm32-unknown-unknown/release/oracle_document_integrity.wasm" + dependencies: ~ + - name: holoom_recipe_integrity + hash: ~ + bundled: "../target/wasm32-unknown-unknown/release/holoom_recipe_integrity.wasm" + dependencies: ~ + - name: holoom_recipe_execution_integrity + hash: ~ + bundled: "../target/wasm32-unknown-unknown/release/holoom_recipe_execution_integrity.wasm" dependencies: ~ coordinator: zomes: - - name: username_registry + - name: external_attestation + hash: ~ + bundled: "../target/wasm32-unknown-unknown/release/external_attestation.wasm" + dependencies: + - name: external_attestation_integrity + - name: username_attestation + hash: ~ + bundled: "../target/wasm32-unknown-unknown/release/username_attestation.wasm" + dependencies: + - name: username_attestation_integrity + - name: wallet_attestation hash: ~ - bundled: "../target/wasm32-unknown-unknown/release/username_registry_coordinator.wasm" + bundled: "../target/wasm32-unknown-unknown/release/wallet_attestation.wasm" dependencies: - - name: username_registry_integrity - - name: records + - name: wallet_attestation_integrity + - name: oracle_document hash: ~ - bundled: "../target/wasm32-unknown-unknown/release/records_coordinator.wasm" - - name: signer + bundled: "../target/wasm32-unknown-unknown/release/oracle_document.wasm" + dependencies: + - name: oracle_document_integrity + - name: holoom_recipe hash: ~ - bundled: "../target/wasm32-unknown-unknown/release/signer_coordinator.wasm" - - name: ping + bundled: "../target/wasm32-unknown-unknown/release/holoom_recipe.wasm" + dependencies: + - name: holoom_recipe_integrity + - name: holoom_recipe_execution hash: ~ - bundled: "../target/wasm32-unknown-unknown/release/ping_coordinator.wasm" + bundled: "../target/wasm32-unknown-unknown/release/holoom_recipe_execution.wasm" + dependencies: + - name: holoom_recipe_execution_integrity From f7518c0f7d86beb88c45d080fcc78b980a05e654 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 7 Aug 2024 17:02:51 +0100 Subject: [PATCH 2/5] updates to recipe --- .../src/holoom_recipe_execution.rs | 155 ++++++++++-------- crates/holoom_types/src/recipe.rs | 2 +- crates/oracle_document/coordinator/src/lib.rs | 4 + .../coordinator/src/oracle_document.rs | 18 +- 4 files changed, 108 insertions(+), 71 deletions(-) diff --git a/crates/holoom_recipe_execution/coordinator/src/holoom_recipe_execution.rs b/crates/holoom_recipe_execution/coordinator/src/holoom_recipe_execution.rs index 98361f8..3e682af 100644 --- a/crates/holoom_recipe_execution/coordinator/src/holoom_recipe_execution.rs +++ b/crates/holoom_recipe_execution/coordinator/src/holoom_recipe_execution.rs @@ -43,7 +43,7 @@ pub fn execute_recipe(payload: ExecuteRecipePayload) -> ExternResult { "Incorrect number of arguments".into() ))); } - for (arg, (arg_name, arg_type)) in payload.arguments.iter().zip(recipe.arguments) { + for (arg, (arg_name, arg_type)) in payload.arguments.iter().zip(recipe.arguments.clone()) { let val = match (arg, arg_type) { (RecipeArgument::String { value }, RecipeArgumentType::String) => { Val::str(value.clone()) @@ -60,7 +60,7 @@ pub fn execute_recipe(payload: ExecuteRecipePayload) -> ExternResult { vars.insert(arg_name, val); } - for (out_var_name, instruction) in recipe.instructions { + for (out_var_name, instruction) in recipe.instructions.clone() { if vars.contains_key(&out_var_name) { unreachable!("Bad impl: A valid Recipe doesn't reassign vars"); } @@ -74,52 +74,14 @@ pub fn execute_recipe(payload: ExecuteRecipePayload) -> ExternResult { (val, RecipeInstructionExecution::GetCallerAgentPublicKey) } RecipeInstruction::GetDocsListedByVar { var_name } => { - let list_val = vars - .get(&var_name) - .expect("Bad impl: A valid recipe doesn't use unassigned vars"); - let Val::Arr(item_vals) = list_val else { - return Err(wasm_error!(WasmErrorInner::Guest(format!( - "var '{}' expected to contain array", - &var_name - )))); - }; - let doc_ahs = item_vals - .iter() - .map(|val| { - let Val::Str(identifier) = val else { - return Err(wasm_error!(WasmErrorInner::Guest(format!( - "var '{}' expected to contain array of string elements", - &var_name - )))); - }; - get_latest_oracle_document_ah_for_name( - ExecuteOracleRecipePayload { name:identifier.as_ref().clone(), - trusted:recipe.trusted_authors, - }.into()?)? - .ok_or(wasm_error!(WasmErrorInner::Guest( - format!("No OracleDocument for identifier '{}'", &identifier) - ))) - }) - .collect::>>()?; - let doc_vals = doc_ahs - .iter() - .map(|doc_ah| { - let doc_record = get(doc_ah.clone(), GetOptions::network())?.ok_or( - wasm_error!(WasmErrorInner::Guest("OracleDocument not found".into())), - )?; - let doc: OracleDocument = deserialize_record_entry(doc_record)?; - let val = parse_single_json(&doc.json_data)?; - Ok(val) - }) - .collect::>>()?; - let val = Val::arr(doc_vals); - let instruction_execution = - RecipeInstructionExecution::GetDocsListedByVar { doc_ahs }; + let tuple = get_docs_listed_by_var(&vars, &recipe, &var_name)?; + let val = Val::arr(tuple.0); + let instruction_execution = RecipeInstructionExecution::GetDocsListedByVar { doc_ahs:tuple.1 }; (val, instruction_execution) } RecipeInstruction::GetLatestCallerExternalId => { let mut attestation_records = - get_external_id_attestations_for_agent(SerializedBytes::try_from(agent_info()?.agent_initial_pubkey))?; + get_external_id_attestations_for_agent(SerializedBytes::try_from(agent_info()?.agent_initial_pubkey).unwrap())?; let attestation_record = attestation_records .pop() @@ -148,28 +110,9 @@ pub fn execute_recipe(payload: ExecuteRecipePayload) -> ExternResult { (val, instruction_execution) } RecipeInstruction::GetLatestDocWithIdentifier { var_name } => { - let identifier_val = vars - .get(&var_name) - .expect("Bad impl: A valid recipe doesn't use unassigned vars"); - let Val::Str(identifier) = identifier_val else { - return Err(wasm_error!(WasmErrorInner::Guest(format!( - "var '{}' expected to contain string", - &var_name - )))); - }; - let doc_record = get_latest_oracle_document_for_name( - ExecuteOracleRecipePayload { name:identifier.as_ref().clone(), - trusted:recipe.trusted_authors, - }.into()?)? - .ok_or(wasm_error!(WasmErrorInner::Guest(format!( - "No OracleDocument found for identifier '{}'", - identifier - ))))?; - let doc_ah = doc_record.action_address().clone(); - let doc: OracleDocument = deserialize_record_entry(doc_record)?; - let val = parse_single_json(&doc.json_data)?; - let instruction_execution = - RecipeInstructionExecution::GetLatestDocWithIdentifier { doc_ah }; + let tuple = get_latest_doc_with_identifier(&vars, &recipe, &var_name)?; + let val = tuple.0; + let instruction_execution = RecipeInstructionExecution::GetLatestDocWithIdentifier { doc_ah:tuple.1 }; (val, instruction_execution) } RecipeInstruction::Jq { @@ -220,6 +163,86 @@ pub fn execute_recipe(payload: ExecuteRecipePayload) -> ExternResult { create_recipe_execution(recipe_execution) } +fn get_docs_listed_by_var( + vars: &HashMap, + recipe: &Recipe, + var_name: &str, +) -> ExternResult<(Vec,Vec)> { + let list_val = vars + .get(var_name) + .expect("Bad impl: A valid recipe doesn't use unassigned vars"); + let Val::Arr(item_vals) = list_val else { + return Err(wasm_error!(WasmErrorInner::Guest(format!( + "var '{}' expected to contain array", + var_name + )))); + }; + let doc_ahs = item_vals + .iter() + .map(|val| { + let Val::Str(identifier) = val else { + return Err(wasm_error!(WasmErrorInner::Guest(format!( + "var '{}' expected to contain array of string elements", + var_name + )))); + }; + get_latest_oracle_document_ah_for_name(SerializedBytes::try_from( + ExecuteOracleRecipePayload { + name: identifier.as_ref().clone(), + trusted_authors: recipe.trusted_authors.clone(), + } + ).unwrap())? + .ok_or(wasm_error!(WasmErrorInner::Guest( + format!("No OracleDocument for identifier '{}'", &identifier) + ))) + }) + .collect::>>()?; + let doc_vals = doc_ahs + .iter() + .map(|doc_ah| { + let doc_record = get(doc_ah.clone(), GetOptions::network())?.ok_or( + wasm_error!(WasmErrorInner::Guest("OracleDocument not found".into())), + )?; + let doc: OracleDocument = deserialize_record_entry(doc_record)?; + let val = parse_single_json(&doc.json_data)?; + Ok(val) + }) + .collect::>>()?; + Ok((doc_vals,doc_ahs)) +} + +fn get_latest_doc_with_identifier( + vars: &HashMap, + recipe: &Recipe, + var_name: &str +) -> ExternResult<(Val, ActionHash)> { + let identifier_val = vars + .get(var_name) + .expect("Bad impl: A valid recipe doesn't use unassigned vars"); + let Val::Str(identifier) = identifier_val else { + return Err(wasm_error!(WasmErrorInner::Guest(format!( + "var '{}' expected to contain string", + var_name + )))); + }; + + let doc_record = get_latest_oracle_document_for_name(SerializedBytes::try_from( + ExecuteOracleRecipePayload { + name: identifier.as_ref().clone(), + trusted_authors: recipe.trusted_authors.clone(), + } + ).unwrap())? + .ok_or(wasm_error!(WasmErrorInner::Guest(format!( + "No OracleDocument found for identifier '{}'", + identifier + ))))?; + + let doc_ah = doc_record.action_address().clone(); + let doc: OracleDocument = deserialize_record_entry(doc_record)?; + let val = parse_single_json(&doc.json_data)?; + Ok((val,doc_ah)) + +} fn get_latest_oracle_document_ah_for_name(payload: SerializedBytes) -> ExternResult>{ let call_response = call(CallTargetCell::Local, ZomeName::from("oracle_document"), FunctionName("get_latest_oracle_document_ah_for_name".into()), None, payload)?; diff --git a/crates/holoom_types/src/recipe.rs b/crates/holoom_types/src/recipe.rs index f0fb4a9..b52892e 100644 --- a/crates/holoom_types/src/recipe.rs +++ b/crates/holoom_types/src/recipe.rs @@ -107,5 +107,5 @@ pub struct ExecuteRecipePayload { #[serde(tag = "type")] pub struct ExecuteOracleRecipePayload { pub name: String, - pub trusted: Vec, + pub trusted_authors: Vec, } diff --git a/crates/oracle_document/coordinator/src/lib.rs b/crates/oracle_document/coordinator/src/lib.rs index 04a7fa8..45ad9b6 100644 --- a/crates/oracle_document/coordinator/src/lib.rs +++ b/crates/oracle_document/coordinator/src/lib.rs @@ -13,6 +13,10 @@ pub fn init(_: ()) -> ExternResult { zome_name.clone(), "get_latest_oracle_document_ah_for_name".into(), )); + functions.insert(( + zome_name.clone(), + "get_latest_oracle_document_for_name".into(), + )); } functions.insert((zome_name, "recv_remote_signal".into())); create_cap_grant(CapGrantEntry { diff --git a/crates/oracle_document/coordinator/src/oracle_document.rs b/crates/oracle_document/coordinator/src/oracle_document.rs index 9c7015b..04ad1a1 100644 --- a/crates/oracle_document/coordinator/src/oracle_document.rs +++ b/crates/oracle_document/coordinator/src/oracle_document.rs @@ -1,5 +1,5 @@ use hdk::prelude::*; -use holoom_types::{DocumentRelationTag, OracleDocument}; +use holoom_types::{DocumentRelationTag, ExecuteOracleRecipePayload, OracleDocument}; use oracle_document_integrity::{EntryTypes, LinkTypes}; use shared_utils::hash_identifier; @@ -22,7 +22,12 @@ pub fn create_oracle_document(oracle_document: OracleDocument) -> ExternResult ExternResult> { + get_latest_document_ah_for_name(payload.name, &payload.trusted_authors) +} + +pub fn get_latest_document_ah_for_name( name: String, trusted_authors: &[AgentPubKey], ) -> ExternResult> { @@ -60,11 +65,16 @@ pub fn get_oracle_document_link_ahs_for_name(name: String) -> ExternResult ExternResult> { + get_latest_document_for_name(payload.name, &payload.trusted_authors) +} + +pub fn get_latest_document_for_name( name: String, trusted_authors: &[AgentPubKey], ) -> ExternResult> { - let Some(action_hash) = get_latest_oracle_document_ah_for_name(name, trusted_authors)? else { + let Some(action_hash) = get_latest_document_ah_for_name(name, trusted_authors)? else { return Ok(None); }; get(action_hash, GetOptions::network()) From a2493771cbcc33decdf3dc6274f3d83b4b2780dc Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 7 Aug 2024 23:16:39 +0100 Subject: [PATCH 3/5] added evm_attestation --- Cargo.lock | 24 + Cargo.toml | 7 +- crates/evm_attestation/coordinator/Cargo.toml | 20 + .../coordinator}/src/evm_signing_offer.rs | 4 +- .../evm_attestation/coordinator}/src/lib.rs | 24 +- .../evm_attestation/integrity}/Cargo.toml | 6 +- .../integrity/src/entry_types.rs | 24 + .../src/evm_address_to_signing_offer.rs | 2 +- .../integrity}/src/evm_signing_offer.rs | 2 +- .../evm_attestation/integrity}/src/lib.rs | 7 + .../integrity/src/link_types.rs | 66 +++ .../src/name_to_evm_signing_offer.rs | 0 .../src/holoom_recipe_execution.rs | 6 - crates/holoom_types/src/evm_signing_offer.rs | 16 +- crates/shared_utils/Cargo.toml | 2 +- .../shared_utils/src/chain_info.rs | 6 +- crates/shared_utils/src/helpers.rs | 11 +- crates/shared_utils/src/lib.rs | 4 +- .../lib.rs => crates/shared_utils/src/ping.rs | 0 .../coordinator/Cargo.toml | 1 + .../coordinator}/tests/signer.rs | 6 +- .../integrity/src/entry_types.rs | 1 - flake.nix | 2 +- old_crates/holoom_dna_tests/Cargo.toml | 26 -- old_crates/holoom_dna_tests/src/lib.rs | 141 ------ old_crates/holoom_dna_tests/src/tests/mod.rs | 2 - .../external_id_attestation.rs | 315 ------------- .../src/tests/username_registry/mod.rs | 6 - .../src/tests/username_registry/oracle.rs | 71 --- .../src/tests/username_registry/recipe.rs | 361 --------------- .../tests/username_registry/user_metadata.rs | 63 --- .../username_registry/username_attestation.rs | 422 ------------------ .../username_registry/wallet_attestation.rs | 149 ------- old_crates/holoom_types/Cargo.toml | 15 - .../holoom_types/src/evm_signing_offer.rs | 81 ---- old_crates/holoom_types/src/external_id.rs | 49 -- old_crates/holoom_types/src/lib.rs | 86 ---- old_crates/holoom_types/src/metadata.rs | 27 -- old_crates/holoom_types/src/oracle.rs | 19 - old_crates/holoom_types/src/recipe.rs | 104 ----- old_crates/holoom_types/src/username.rs | 22 - old_crates/holoom_types/src/wallet.rs | 36 -- old_crates/jaq_wrapper/Cargo.toml | 16 - old_crates/jaq_wrapper/src/lib.rs | 147 ------ old_crates/ping_coordinator/Cargo.toml | 12 - old_crates/records_coordinator/Cargo.toml | 12 - old_crates/signer_coordinator/Cargo.toml | 13 - old_crates/signer_coordinator/src/lib.rs | 8 - .../username_registry_coordinator/Cargo.toml | 21 - .../src/external_id_attestation.rs | 200 --------- .../src/oracle_document.rs | 126 ------ .../src/recipe.rs | 13 - .../src/recipe_execution.rs | 219 --------- .../src/user_metadata.rs | 77 ---- .../src/username_attestation.rs | 128 ------ .../src/wallet_attestation.rs | 75 ---- .../src/entry_types.rs | 63 --- .../src/link_types.rs | 187 -------- old_crates/username_registry_utils/Cargo.toml | 18 - old_crates/username_registry_utils/src/lib.rs | 43 -- .../username_registry_validation/Cargo.toml | 21 - .../src/agent_external_id_attestation.rs | 42 -- .../src/agent_username_attestation.rs | 42 -- .../src/agent_wallet_attestation.rs | 52 --- .../src/external_id_attestation.rs | 18 - .../src/external_id_to_attestation.rs | 49 -- .../username_registry_validation/src/lib.rs | 34 -- .../src/name_oracle_document.rs | 41 -- .../src/name_to_recipe.rs | 21 - .../src/oracle_document.rs | 9 - .../src/recipe.rs | 69 --- .../src/recipe_execution.rs | 231 ---------- .../src/relate_oracle_document_name.rs | 39 -- .../src/user_metadata.rs | 44 -- .../src/username_attestation.rs | 92 ---- .../src/wallet_attestation.rs | 109 ----- workdir/dna.yaml | 9 + 77 files changed, 202 insertions(+), 4334 deletions(-) create mode 100644 crates/evm_attestation/coordinator/Cargo.toml rename {old_crates/username_registry_coordinator => crates/evm_attestation/coordinator}/src/evm_signing_offer.rs (98%) rename {old_crates/username_registry_coordinator => crates/evm_attestation/coordinator}/src/lib.rs (62%) rename {old_crates/username_registry_integrity => crates/evm_attestation/integrity}/Cargo.toml (60%) create mode 100644 crates/evm_attestation/integrity/src/entry_types.rs rename {old_crates/username_registry_validation => crates/evm_attestation/integrity}/src/evm_address_to_signing_offer.rs (95%) rename {old_crates/username_registry_validation => crates/evm_attestation/integrity}/src/evm_signing_offer.rs (97%) rename {old_crates/username_registry_integrity => crates/evm_attestation/integrity}/src/lib.rs (96%) create mode 100644 crates/evm_attestation/integrity/src/link_types.rs rename {old_crates/username_registry_validation => crates/evm_attestation/integrity}/src/name_to_evm_signing_offer.rs (100%) rename old_crates/records_coordinator/src/lib.rs => crates/shared_utils/src/chain_info.rs (94%) rename old_crates/ping_coordinator/src/lib.rs => crates/shared_utils/src/ping.rs (100%) rename {old_crates/holoom_dna_tests/src => crates/username_attestation/coordinator}/tests/signer.rs (96%) delete mode 100644 old_crates/holoom_dna_tests/Cargo.toml delete mode 100644 old_crates/holoom_dna_tests/src/lib.rs delete mode 100644 old_crates/holoom_dna_tests/src/tests/mod.rs delete mode 100644 old_crates/holoom_dna_tests/src/tests/username_registry/external_id_attestation.rs delete mode 100644 old_crates/holoom_dna_tests/src/tests/username_registry/mod.rs delete mode 100644 old_crates/holoom_dna_tests/src/tests/username_registry/oracle.rs delete mode 100644 old_crates/holoom_dna_tests/src/tests/username_registry/recipe.rs delete mode 100644 old_crates/holoom_dna_tests/src/tests/username_registry/user_metadata.rs delete mode 100644 old_crates/holoom_dna_tests/src/tests/username_registry/username_attestation.rs delete mode 100644 old_crates/holoom_dna_tests/src/tests/username_registry/wallet_attestation.rs delete mode 100644 old_crates/holoom_types/Cargo.toml delete mode 100644 old_crates/holoom_types/src/evm_signing_offer.rs delete mode 100644 old_crates/holoom_types/src/external_id.rs delete mode 100644 old_crates/holoom_types/src/lib.rs delete mode 100644 old_crates/holoom_types/src/metadata.rs delete mode 100644 old_crates/holoom_types/src/oracle.rs delete mode 100644 old_crates/holoom_types/src/recipe.rs delete mode 100644 old_crates/holoom_types/src/username.rs delete mode 100644 old_crates/holoom_types/src/wallet.rs delete mode 100644 old_crates/jaq_wrapper/Cargo.toml delete mode 100644 old_crates/jaq_wrapper/src/lib.rs delete mode 100644 old_crates/ping_coordinator/Cargo.toml delete mode 100644 old_crates/records_coordinator/Cargo.toml delete mode 100644 old_crates/signer_coordinator/Cargo.toml delete mode 100644 old_crates/signer_coordinator/src/lib.rs delete mode 100644 old_crates/username_registry_coordinator/Cargo.toml delete mode 100644 old_crates/username_registry_coordinator/src/external_id_attestation.rs delete mode 100644 old_crates/username_registry_coordinator/src/oracle_document.rs delete mode 100644 old_crates/username_registry_coordinator/src/recipe.rs delete mode 100644 old_crates/username_registry_coordinator/src/recipe_execution.rs delete mode 100644 old_crates/username_registry_coordinator/src/user_metadata.rs delete mode 100644 old_crates/username_registry_coordinator/src/username_attestation.rs delete mode 100644 old_crates/username_registry_coordinator/src/wallet_attestation.rs delete mode 100644 old_crates/username_registry_integrity/src/entry_types.rs delete mode 100644 old_crates/username_registry_integrity/src/link_types.rs delete mode 100644 old_crates/username_registry_utils/Cargo.toml delete mode 100644 old_crates/username_registry_utils/src/lib.rs delete mode 100644 old_crates/username_registry_validation/Cargo.toml delete mode 100644 old_crates/username_registry_validation/src/agent_external_id_attestation.rs delete mode 100644 old_crates/username_registry_validation/src/agent_username_attestation.rs delete mode 100644 old_crates/username_registry_validation/src/agent_wallet_attestation.rs delete mode 100644 old_crates/username_registry_validation/src/external_id_attestation.rs delete mode 100644 old_crates/username_registry_validation/src/external_id_to_attestation.rs delete mode 100644 old_crates/username_registry_validation/src/lib.rs delete mode 100644 old_crates/username_registry_validation/src/name_oracle_document.rs delete mode 100644 old_crates/username_registry_validation/src/name_to_recipe.rs delete mode 100644 old_crates/username_registry_validation/src/oracle_document.rs delete mode 100644 old_crates/username_registry_validation/src/recipe.rs delete mode 100644 old_crates/username_registry_validation/src/recipe_execution.rs delete mode 100644 old_crates/username_registry_validation/src/relate_oracle_document_name.rs delete mode 100644 old_crates/username_registry_validation/src/user_metadata.rs delete mode 100644 old_crates/username_registry_validation/src/username_attestation.rs delete mode 100644 old_crates/username_registry_validation/src/wallet_attestation.rs diff --git a/Cargo.lock b/Cargo.lock index ddac8e1..69d2563 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2394,6 +2394,28 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "evm_attestation" +version = "0.0.1" +dependencies = [ + "evm_attestation_integrity", + "hdk", + "holoom_types", + "jaq_wrapper", + "serde", + "shared_utils", +] + +[[package]] +name = "evm_attestation_integrity" +version = "0.0.1" +dependencies = [ + "hdi", + "holoom_types", + "serde", + "shared_utils", +] + [[package]] name = "external_attestation" version = "0.0.1" @@ -7531,6 +7553,7 @@ name = "shared_utils" version = "0.0.1" dependencies = [ "hdi", + "hdk", "holoom_types", "serde", ] @@ -8781,6 +8804,7 @@ dependencies = [ "bincode", "hdk", "holochain", + "holochain_keystore", "holoom_types", "serde", "shared_utils", diff --git a/Cargo.toml b/Cargo.toml index 3b6f01d..25f0d6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,8 +35,11 @@ path = "crates/jaq_wrapper" [workspace.dependencies.shared_utils] path = "crates/shared_utils" -[workspace.dependencies.shared_tests] -path = "crates/shared_tests" +[workspace.dependencies.evm_attestation_coordinator] +path = "crates/evm_attestation/coordinator" + +[workspace.dependencies.evm_attestation_integrity] +path = "crates/evm_attestation/integrity" [workspace.dependencies.username_attestation_coordinator] path = "crates/username_attestation/coordinator" diff --git a/crates/evm_attestation/coordinator/Cargo.toml b/crates/evm_attestation/coordinator/Cargo.toml new file mode 100644 index 0000000..c7a1c67 --- /dev/null +++ b/crates/evm_attestation/coordinator/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "evm_attestation" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] +name = "evm_attestation" + +[dependencies] +hdk = { workspace = true } +serde = { workspace = true } +holoom_types = { workspace = true } +shared_utils = { workspace = true } +evm_attestation_integrity = { workspace = true } +jaq_wrapper = { workspace = true } + +#[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] #avoids mio bug +#holochain = { workspace = true, default-features = false, features = ["test_utils"] } +#tokio = "1.38.0" diff --git a/old_crates/username_registry_coordinator/src/evm_signing_offer.rs b/crates/evm_attestation/coordinator/src/evm_signing_offer.rs similarity index 98% rename from old_crates/username_registry_coordinator/src/evm_signing_offer.rs rename to crates/evm_attestation/coordinator/src/evm_signing_offer.rs index 27c29b2..2062b7d 100644 --- a/old_crates/username_registry_coordinator/src/evm_signing_offer.rs +++ b/crates/evm_attestation/coordinator/src/evm_signing_offer.rs @@ -9,8 +9,8 @@ use holoom_types::{ EvmAddress, LocalHoloomSignal, RemoteHoloomSignal, }; use jaq_wrapper::{parse_single_json, Val}; -use username_registry_integrity::{EntryTypes, LinkTypes}; -use username_registry_utils::{deserialize_record_entry, hash_evm_address, hash_identifier}; +use evm_attestation_integrity::{EntryTypes, LinkTypes}; +use shared_utils::{deserialize_record_entry, hash_evm_address, hash_identifier}; #[hdk_extern] fn create_signed_evm_signing_offer(payload: CreateEvmSigningOfferPayload) -> ExternResult { diff --git a/old_crates/username_registry_coordinator/src/lib.rs b/crates/evm_attestation/coordinator/src/lib.rs similarity index 62% rename from old_crates/username_registry_coordinator/src/lib.rs rename to crates/evm_attestation/coordinator/src/lib.rs index 5f2edff..3ee036a 100644 --- a/old_crates/username_registry_coordinator/src/lib.rs +++ b/crates/evm_attestation/coordinator/src/lib.rs @@ -1,14 +1,7 @@ pub mod evm_signing_offer; -pub mod external_id_attestation; -pub mod oracle_document; -pub mod recipe; -pub mod recipe_execution; -pub mod user_metadata; -pub mod username_attestation; -pub mod wallet_attestation; use hdk::prelude::*; use holoom_types::{LocalHoloomSignal, RemoteHoloomSignal}; -use username_registry_utils::get_authority_agent; +use shared_utils::get_authority_agent; #[hdk_extern] pub fn init(_: ()) -> ExternResult { @@ -17,14 +10,8 @@ pub fn init(_: ()) -> ExternResult { let mut functions = BTreeSet::new(); let zome_name = zome_info()?.name; if my_pubkey == authority_agent { - functions.insert((zome_name.clone(), "ingest_signed_username".into())); functions.insert(( - zome_name.clone(), - "ingest_external_id_attestation_request".into(), - )); - functions.insert(( - zome_name.clone(), - "ingest_evm_signature_over_recipe_execution_request".into(), + zome_name.clone(), "ingest_signed_username".into(), )); } functions.insert((zome_name, "recv_remote_signal".into())); @@ -44,12 +31,6 @@ fn recv_remote_signal(signal_io: ExternIO) -> ExternResult<()> { .map_err(|e| wasm_error!(WasmErrorInner::Serialize(e)))?; match remote_holoom_signal { - RemoteHoloomSignal::ExternalIdAttested { request_id, record } => { - emit_signal(LocalHoloomSignal::ExternalIdAttested { request_id, record })? - } - RemoteHoloomSignal::ExternalIdRejected { request_id, reason } => { - emit_signal(LocalHoloomSignal::ExternalIdRejected { request_id, reason })? - } RemoteHoloomSignal::EvmSignatureProvided { request_id, signed_u256_array, @@ -60,6 +41,7 @@ fn recv_remote_signal(signal_io: ExternIO) -> ExternResult<()> { RemoteHoloomSignal::EvmSignatureRequestRejected { request_id, reason } => { emit_signal(LocalHoloomSignal::EvmSignatureRequestRejected { request_id, reason })? } + _=>{} } Ok(()) diff --git a/old_crates/username_registry_integrity/Cargo.toml b/crates/evm_attestation/integrity/Cargo.toml similarity index 60% rename from old_crates/username_registry_integrity/Cargo.toml rename to crates/evm_attestation/integrity/Cargo.toml index a0f9d12..de61bfd 100644 --- a/old_crates/username_registry_integrity/Cargo.toml +++ b/crates/evm_attestation/integrity/Cargo.toml @@ -1,14 +1,14 @@ [package] -name = "username_registry_integrity" +name = "evm_attestation_integrity" version = "0.0.1" edition = "2021" [lib] crate-type = ["cdylib", "rlib"] -name = "username_registry_integrity" +name = "evm_attestation_integrity" [dependencies] hdi = { workspace = true } serde = { workspace = true } holoom_types = { workspace = true } -username_registry_validation = { workspace = true } +shared_utils = { workspace = true } diff --git a/crates/evm_attestation/integrity/src/entry_types.rs b/crates/evm_attestation/integrity/src/entry_types.rs new file mode 100644 index 0000000..2091c45 --- /dev/null +++ b/crates/evm_attestation/integrity/src/entry_types.rs @@ -0,0 +1,24 @@ +use hdi::prelude::*; +use holoom_types::evm_signing_offer::SignedEvmSigningOffer; +use crate::evm_signing_offer::*; + +#[derive(Serialize, Deserialize)] +#[serde(tag = "type")] +#[hdk_entry_types] +#[unit_enum(UnitEntryTypes)] +pub enum EntryTypes { + SignedEvmSigningOffer(SignedEvmSigningOffer), +} + +impl EntryTypes { + pub fn validate_create(self, action: Create) -> ExternResult { + match self { + EntryTypes::SignedEvmSigningOffer(evm_signing_offer) => { + validate_create_signed_evm_signing_offer( + EntryCreationAction::Create(action), + evm_signing_offer, + ) + } + } + } +} diff --git a/old_crates/username_registry_validation/src/evm_address_to_signing_offer.rs b/crates/evm_attestation/integrity/src/evm_address_to_signing_offer.rs similarity index 95% rename from old_crates/username_registry_validation/src/evm_address_to_signing_offer.rs rename to crates/evm_attestation/integrity/src/evm_address_to_signing_offer.rs index d087278..d315b51 100644 --- a/old_crates/username_registry_validation/src/evm_address_to_signing_offer.rs +++ b/crates/evm_attestation/integrity/src/evm_address_to_signing_offer.rs @@ -1,6 +1,6 @@ use hdi::prelude::*; use holoom_types::evm_signing_offer::SignedEvmSigningOffer; -use username_registry_utils::{deserialize_record_entry, hash_evm_address}; +use shared_utils::{deserialize_record_entry, hash_evm_address}; pub fn validate_create_link_evm_address_to_signing_offer( action: CreateLink, diff --git a/old_crates/username_registry_validation/src/evm_signing_offer.rs b/crates/evm_attestation/integrity/src/evm_signing_offer.rs similarity index 97% rename from old_crates/username_registry_validation/src/evm_signing_offer.rs rename to crates/evm_attestation/integrity/src/evm_signing_offer.rs index b43db17..db3b1de 100644 --- a/old_crates/username_registry_validation/src/evm_signing_offer.rs +++ b/crates/evm_attestation/integrity/src/evm_signing_offer.rs @@ -3,7 +3,7 @@ use holoom_types::{ evm_signing_offer::{EvmU256Item, SignedEvmSigningOffer}, recipe::Recipe, }; -use username_registry_utils::deserialize_record_entry; +use shared_utils::deserialize_record_entry; pub fn validate_create_signed_evm_signing_offer( _action: EntryCreationAction, diff --git a/old_crates/username_registry_integrity/src/lib.rs b/crates/evm_attestation/integrity/src/lib.rs similarity index 96% rename from old_crates/username_registry_integrity/src/lib.rs rename to crates/evm_attestation/integrity/src/lib.rs index a3f2fa1..09ff7d8 100644 --- a/old_crates/username_registry_integrity/src/lib.rs +++ b/crates/evm_attestation/integrity/src/lib.rs @@ -3,6 +3,13 @@ pub mod entry_types; pub use entry_types::*; pub mod link_types; pub use link_types::*; +pub mod evm_address_to_signing_offer; +pub use evm_address_to_signing_offer::*; +pub mod evm_signing_offer; +pub use evm_signing_offer::*; +pub mod name_to_evm_signing_offer; +pub use name_to_evm_signing_offer::*; + #[hdk_extern] pub fn genesis_self_check(_data: GenesisSelfCheckData) -> ExternResult { diff --git a/crates/evm_attestation/integrity/src/link_types.rs b/crates/evm_attestation/integrity/src/link_types.rs new file mode 100644 index 0000000..ce29aa0 --- /dev/null +++ b/crates/evm_attestation/integrity/src/link_types.rs @@ -0,0 +1,66 @@ +use hdi::prelude::*; +use crate::evm_address_to_signing_offer::*; +use crate::name_to_evm_signing_offer::*; + +#[derive(Serialize, Deserialize)] +#[hdk_link_types] +pub enum LinkTypes { + NameToSigningOffer, + EvmAddressToSigningOffer, + +} + +impl LinkTypes { + pub fn validate_create( + self, + action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + tag: LinkTag, + ) -> ExternResult { + match self { + LinkTypes::NameToSigningOffer => validate_create_link_name_to_evm_signing_offer( + action, + base_address, + target_address, + tag, + ), + LinkTypes::EvmAddressToSigningOffer => { + validate_create_link_evm_address_to_signing_offer( + action, + base_address, + target_address, + tag, + ) + } + } + } + + pub fn validate_delete( + self, + action: DeleteLink, + original_action: CreateLink, + base_address: AnyLinkableHash, + target_address: AnyLinkableHash, + tag: LinkTag, + ) -> ExternResult { + match self { + LinkTypes::NameToSigningOffer => validate_delete_link_name_to_evm_signing_offer( + action, + original_action, + base_address, + target_address, + tag, + ), + LinkTypes::EvmAddressToSigningOffer => { + validate_delete_link_evm_address_to_signing_offer( + action, + original_action, + base_address, + target_address, + tag, + ) + } + } + } +} diff --git a/old_crates/username_registry_validation/src/name_to_evm_signing_offer.rs b/crates/evm_attestation/integrity/src/name_to_evm_signing_offer.rs similarity index 100% rename from old_crates/username_registry_validation/src/name_to_evm_signing_offer.rs rename to crates/evm_attestation/integrity/src/name_to_evm_signing_offer.rs diff --git a/crates/holoom_recipe_execution/coordinator/src/holoom_recipe_execution.rs b/crates/holoom_recipe_execution/coordinator/src/holoom_recipe_execution.rs index 3e682af..2c63e39 100644 --- a/crates/holoom_recipe_execution/coordinator/src/holoom_recipe_execution.rs +++ b/crates/holoom_recipe_execution/coordinator/src/holoom_recipe_execution.rs @@ -248,9 +248,7 @@ fn get_latest_oracle_document_ah_for_name(payload: SerializedBytes) -> ExternRes let call_response = call(CallTargetCell::Local, ZomeName::from("oracle_document"), FunctionName("get_latest_oracle_document_ah_for_name".into()), None, payload)?; match call_response { ZomeCallResponse::Ok(result) => { // Of type ExternIO, wrapper around byte array - //let posts: Vec = result.decode().map_err(|err| wasm_error!(err))?; let data: Option> = result.decode().map_err(|err| wasm_error!(err))?; - //debug!("{:?}",data.signed_action.into()); return Ok(data) }, ZomeCallResponse::NetworkError(err) => { @@ -267,9 +265,7 @@ fn get_latest_oracle_document_for_name(payload: SerializedBytes) -> ExternResult let call_response = call(CallTargetCell::Local, ZomeName::from("oracle_document"), FunctionName("get_latest_oracle_document_for_name".into()), None, payload)?; match call_response { ZomeCallResponse::Ok(result) => { // Of type ExternIO, wrapper around byte array - //let posts: Vec = result.decode().map_err(|err| wasm_error!(err))?; let data: Option = result.decode().map_err(|err| wasm_error!(err))?; - //debug!("{:?}",data.signed_action.into()); return Ok(data) }, ZomeCallResponse::NetworkError(err) => { @@ -286,9 +282,7 @@ fn get_external_id_attestations_for_agent(payload: SerializedBytes) -> ExternRes let call_response = call(CallTargetCell::Local, ZomeName::from("external_attestation"), FunctionName("get_external_id_attestations_for_agent".into()), None, payload)?; match call_response { ZomeCallResponse::Ok(result) => { // Of type ExternIO, wrapper around byte array - //let posts: Vec = result.decode().map_err(|err| wasm_error!(err))?; let data: Vec = result.decode().map_err(|err| wasm_error!(err))?; - //debug!("{:?}",data.signed_action.into()); return Ok(data) }, ZomeCallResponse::NetworkError(err) => { diff --git a/crates/holoom_types/src/evm_signing_offer.rs b/crates/holoom_types/src/evm_signing_offer.rs index 277e2b6..905e2b2 100644 --- a/crates/holoom_types/src/evm_signing_offer.rs +++ b/crates/holoom_types/src/evm_signing_offer.rs @@ -13,8 +13,7 @@ pub enum EvmU256Item { HoloAgent, } -#[hdk_entry_helper] -#[derive(Clone, PartialEq, TS)] +#[derive(Clone, PartialEq, TS, Serialize, Deserialize, Debug)] #[ts(export)] pub struct EvmSigningOffer { #[ts(type = "ActionHash")] @@ -22,11 +21,22 @@ pub struct EvmSigningOffer { pub u256_items: Vec, } +#[hdk_entry_helper] +#[derive(Clone, PartialEq, TS)] +#[ts(export)] +pub struct SignedEvmSigningOffer { + #[ts(type = "Uint8Array")] + pub signer: EvmAddress, + #[ts(type = "[Uint8Array, Uint8Array, number]")] + pub signature: EvmSignature, + pub offer: EvmSigningOffer, +} + #[derive(Serialize, Deserialize, Debug, TS)] #[ts(export)] pub struct CreateEvmSigningOfferPayload { pub identifier: String, - pub evm_signing_offer: EvmSigningOffer, + pub signed_offer: SignedEvmSigningOffer, } #[derive(Serialize, Deserialize, Debug, TS)] diff --git a/crates/shared_utils/Cargo.toml b/crates/shared_utils/Cargo.toml index a9049fa..8b01bb5 100644 --- a/crates/shared_utils/Cargo.toml +++ b/crates/shared_utils/Cargo.toml @@ -20,5 +20,5 @@ holoom_types = { workspace = true } #[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] #avoids mio bug #holochain = { workspace = true, default-features = false, features = ["test_utils"] } -#hdk = { workspace = true, features = ["encoding", "test_utils"] } +hdk = { workspace = true, features = ["encoding", "test_utils"] } diff --git a/old_crates/records_coordinator/src/lib.rs b/crates/shared_utils/src/chain_info.rs similarity index 94% rename from old_crates/records_coordinator/src/lib.rs rename to crates/shared_utils/src/chain_info.rs index 9613140..807ac6c 100644 --- a/old_crates/records_coordinator/src/lib.rs +++ b/crates/shared_utils/src/chain_info.rs @@ -1,11 +1,11 @@ use hdk::prelude::*; -#[hdk_extern] +//#[hdk_extern] pub fn get_record(action_hash: ActionHash) -> ExternResult> { get(action_hash, GetOptions::network()) } -#[hdk_extern] +//#[hdk_extern] pub fn get_chain_status(agent: AgentPubKey) -> ExternResult { get_agent_activity(agent, ChainQueryFilter::default(), ActivityRequest::Status) } @@ -17,7 +17,7 @@ pub struct GetChainSegmentPayload { pub end: u32, } -#[hdk_extern] +//#[hdk_extern] pub fn get_chain_segment(payload: GetChainSegmentPayload) -> ExternResult { let query = ChainQueryFilter::default() .descending() diff --git a/crates/shared_utils/src/helpers.rs b/crates/shared_utils/src/helpers.rs index d2d032b..764a3ea 100644 --- a/crates/shared_utils/src/helpers.rs +++ b/crates/shared_utils/src/helpers.rs @@ -1,5 +1,5 @@ use hdi::prelude::*; -use holoom_types::HoloomDnaProperties; +use holoom_types::{EvmAddress, HoloomDnaProperties}; pub fn deserialize_record_entry(record: Record) -> ExternResult where @@ -24,6 +24,15 @@ pub fn hash_identifier(identifier: String) -> ExternResult { hash_entry(Entry::App(AppEntryBytes(bytes))) } +pub fn hash_evm_address(evm_address: EvmAddress) -> ExternResult { + #[derive(SerializedBytes, Serialize, Debug, Deserialize)] + struct SerializableEvmAddress(EvmAddress); + + let bytes = SerializedBytes::try_from(SerializableEvmAddress(evm_address)) + .map_err(|err| wasm_error!(err))?; + hash_entry(Entry::App(AppEntryBytes(bytes))) +} + pub fn get_authority_agent() -> ExternResult { let dna_props = HoloomDnaProperties::try_from_dna_properties()?; AgentPubKey::try_from(dna_props.authority_agent).map_err(|_| { diff --git a/crates/shared_utils/src/lib.rs b/crates/shared_utils/src/lib.rs index 0d01fc3..9b1aeb5 100644 --- a/crates/shared_utils/src/lib.rs +++ b/crates/shared_utils/src/lib.rs @@ -1,2 +1,4 @@ pub mod helpers; -pub use helpers::*; \ No newline at end of file +pub use helpers::*; +pub mod chain_info; +pub use chain_info::*; \ No newline at end of file diff --git a/old_crates/ping_coordinator/src/lib.rs b/crates/shared_utils/src/ping.rs similarity index 100% rename from old_crates/ping_coordinator/src/lib.rs rename to crates/shared_utils/src/ping.rs diff --git a/crates/username_attestation/coordinator/Cargo.toml b/crates/username_attestation/coordinator/Cargo.toml index 2f7bcfe..cc4a184 100644 --- a/crates/username_attestation/coordinator/Cargo.toml +++ b/crates/username_attestation/coordinator/Cargo.toml @@ -18,3 +18,4 @@ bincode = { workspace = true } [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] #avoids mio bug holochain = { workspace = true, default-features = false, features = ["test_utils"] } tokio = "1.38.0" +holochain_keystore = { workspace = true } diff --git a/old_crates/holoom_dna_tests/src/tests/signer.rs b/crates/username_attestation/coordinator/tests/signer.rs similarity index 96% rename from old_crates/holoom_dna_tests/src/tests/signer.rs rename to crates/username_attestation/coordinator/tests/signer.rs index be49c3d..a69a3cf 100644 --- a/old_crates/holoom_dna_tests/src/tests/signer.rs +++ b/crates/username_attestation/coordinator/tests/signer.rs @@ -1,9 +1,13 @@ -use crate::holoom_dna_with_authority; use hdk::prelude::fake_agent_pubkey_1; use holochain::{conductor::config::ConductorConfig, prelude::Signature, sweettest::*}; use holochain_keystore::AgentPubKeyExt; use holoom_types::SignableBytes; +mod config; +use config::*; + +#[cfg(test)] + #[tokio::test(flavor = "multi_thread")] async fn sign_message_verify_signature() { let dna = holoom_dna_with_authority(&fake_agent_pubkey_1()).await; diff --git a/crates/username_attestation/integrity/src/entry_types.rs b/crates/username_attestation/integrity/src/entry_types.rs index 50ea9fd..054564e 100644 --- a/crates/username_attestation/integrity/src/entry_types.rs +++ b/crates/username_attestation/integrity/src/entry_types.rs @@ -1,7 +1,6 @@ use hdi::prelude::*; use holoom_types::UsernameAttestation; use crate::username_attestation::*; -//use external_attestation_validation::*; #[derive(Serialize, Deserialize)] #[serde(tag = "type")] diff --git a/flake.nix b/flake.nix index 57662e3..16fa305 100644 --- a/flake.nix +++ b/flake.nix @@ -19,7 +19,7 @@ inputsFrom = [ holonix.devShells.${system}.holochainBinaries ]; packages = with pkgs; [ # add further packages from nixpkgs - # nodejs + nodejs cargo-nextest ]; }; diff --git a/old_crates/holoom_dna_tests/Cargo.toml b/old_crates/holoom_dna_tests/Cargo.toml deleted file mode 100644 index 4bce3ba..0000000 --- a/old_crates/holoom_dna_tests/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "holoom_dna_tests" -version = "0.0.1" -edition = "2021" - -[lib] -crate-type = ["cdylib", "rlib"] -name = "holoom_dna_tests" - -[dependencies] -serde = { workspace = true } -holoom_types = { workspace = true } -hdk = { workspace = true, features = ["encoding", "test_utils"] } -holochain = { workspace = true, default-features = false, features = [ - "test_utils", -] } - - -[dev-dependencies] -username_registry_utils = { workspace = true } -username_registry_validation = { workspace = true } -tokio = "1.38.0" -holochain_keystore = { workspace = true } -ethers-signers = { workspace = true } -ed25519-dalek = { workspace = true } -bs58 = { workspace = true } diff --git a/old_crates/holoom_dna_tests/src/lib.rs b/old_crates/holoom_dna_tests/src/lib.rs deleted file mode 100644 index f17f034..0000000 --- a/old_crates/holoom_dna_tests/src/lib.rs +++ /dev/null @@ -1,141 +0,0 @@ -use std::time::Duration; - -use hdk::prelude::*; -use holochain::{ - conductor::{api::error::ConductorApiResult, config::ConductorConfig}, - prelude::DnaFile, - sweettest::{await_consistency, SweetAgents, SweetCell, SweetConductorBatch, SweetDnaFile}, -}; -use holoom_types::HoloomDnaProperties; - -#[cfg(test)] -mod tests; - -async fn load_dna() -> DnaFile { - // Use prebuilt dna file - let dna_path = std::env::current_dir() - .unwrap() - .join("../../workdir/holoom.dna"); - - SweetDnaFile::from_bundle(&dna_path).await.unwrap() -} - -pub async fn holoom_dna_with_authority(authority_agent: &AgentPubKey) -> DnaFile { - let dna = load_dna().await; - let properties = SerializedBytes::try_from(HoloomDnaProperties { - authority_agent: authority_agent.to_string(), - }) - .unwrap(); - dna.update_modifiers(DnaModifiersOpt { - network_seed: None, - properties: Some(properties), - origin_time: None, - quantum_time: None, - }) -} - -pub struct TestSetup { - pub conductors: SweetConductorBatch, - cells: Vec, -} - -impl TestSetup { - pub async fn new(user_count: usize) -> Self { - // Set up conductors - let mut conductors: SweetConductorBatch = - SweetConductorBatch::from_config(1 + user_count, ConductorConfig::default()).await; - - let authority_agent_pubkey = SweetAgents::one(conductors[0].keystore()).await; - - let dnas = &[holoom_dna_with_authority(&authority_agent_pubkey).await]; - - let authority_app = conductors[0] - .setup_app_for_agent("holoom", authority_agent_pubkey.clone(), dnas) - .await - .unwrap(); - let (authority_cell,) = authority_app.into_tuple(); - let mut cells = Vec::from([authority_cell]); - for i in 1..1 + user_count { - let user_app = conductors[i].setup_app("holoom", dnas).await.unwrap(); - let (user_cell,) = user_app.into_tuple(); - cells.push(user_cell); - } - - TestSetup { conductors, cells } - } - - pub async fn authority_only() -> Self { - Self::new(0).await - } - - pub async fn authority_and_alice() -> Self { - Self::new(1).await - } - - pub async fn authority_and_alice_bob() -> Self { - Self::new(2).await - } - - pub async fn authority_call( - &self, - zome_name: &str, - fn_name: &str, - payload: I, - ) -> ConductorApiResult - where - I: serde::Serialize + std::fmt::Debug, - O: serde::de::DeserializeOwned + std::fmt::Debug, - { - self.conductors[0] - .call_fallible(&self.cells[0].zome(zome_name), fn_name, payload) - .await - } - - pub async fn alice_call( - &self, - zome_name: &str, - fn_name: &str, - payload: I, - ) -> ConductorApiResult - where - I: serde::Serialize + std::fmt::Debug, - O: serde::de::DeserializeOwned + std::fmt::Debug, - { - self.conductors[1] - .call_fallible(&self.cells[1].zome(zome_name), fn_name, payload) - .await - } - - pub async fn bob_call( - &self, - zome_name: &str, - fn_name: &str, - payload: I, - ) -> ConductorApiResult - where - I: serde::Serialize + std::fmt::Debug, - O: serde::de::DeserializeOwned + std::fmt::Debug, - { - self.conductors[2] - .call_fallible(&self.cells[2].zome(zome_name), fn_name, payload) - .await - } - - pub fn authority_pubkey(&self) -> AgentPubKey { - self.cells[0].agent_pubkey().clone() - } - - pub fn alice_pubkey(&self) -> AgentPubKey { - self.cells[1].agent_pubkey().clone() - } - - pub fn bob_pubkey(&self) -> AgentPubKey { - self.cells[1].agent_pubkey().clone() - } - - pub async fn consistency(&self) { - await_consistency(Duration::from_secs(60), self.cells.iter()) - .await - .unwrap(); - } -} diff --git a/old_crates/holoom_dna_tests/src/tests/mod.rs b/old_crates/holoom_dna_tests/src/tests/mod.rs deleted file mode 100644 index 644a0e4..0000000 --- a/old_crates/holoom_dna_tests/src/tests/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod signer; -mod username_registry; diff --git a/old_crates/holoom_dna_tests/src/tests/username_registry/external_id_attestation.rs b/old_crates/holoom_dna_tests/src/tests/username_registry/external_id_attestation.rs deleted file mode 100644 index 7898ca0..0000000 --- a/old_crates/holoom_dna_tests/src/tests/username_registry/external_id_attestation.rs +++ /dev/null @@ -1,315 +0,0 @@ -use hdk::prelude::*; -use holochain::conductor::api::error::ConductorApiError; -use holoom_types::{ConfirmExternalIdRequestPayload, ExternalIdAttestation}; - -use crate::TestSetup; - - -#[tokio::test(flavor = "multi_thread")] -async fn only_authority_can_create_external_id_attestation() { - let setup = TestSetup::authority_and_alice().await; - - // Authority creates a external id Attestation for alice - let _: Record = setup - .authority_call( - "username_registry", - "create_external_id_attestation", - ExternalIdAttestation { - request_id: "1234".into(), - internal_pubkey: setup.alice_pubkey(), - external_id: "4546".into(), - display_name: "alice".into() - }, - ) - .await - .unwrap(); - - // Alice cannot create an external id Attestation - let result: Result = setup - .alice_call( - "username_registry", - "create_external_id_attestation", - ExternalIdAttestation { - request_id: "9876".into(), - internal_pubkey: setup.alice_pubkey(), - external_id: "abcd".into(), - display_name: "alice2".into() - }, - ) - .await; - - assert!(result.is_err()); -} - - - -#[tokio::test(flavor = "multi_thread")] -async fn only_authority_can_confirm_request() { - let setup = TestSetup::authority_and_alice().await; - - let _: Record = setup - .authority_call( - "username_registry", - "confirm_external_id_request", - ConfirmExternalIdRequestPayload { - request_id:"1234".into(), - external_id: "4567".into(), - display_name: "alice".into(), - requestor: setup.alice_pubkey() - }) - .await - .unwrap(); - - let result2: Result = setup - .alice_call( - "username_registry", - "confirm_external_id_request", - ConfirmExternalIdRequestPayload { - request_id:"1234".into(), - external_id: "4567".into(), - display_name: "alice".into(), - requestor: setup.alice_pubkey() - }) - .await; - assert!(result2.is_err()); -} - - -#[tokio::test(flavor = "multi_thread")] -async fn nobody_can_delete_external_id_attestation() { - let setup = TestSetup::authority_and_alice().await; - setup.conductors.exchange_peer_info().await; - - // Authority creates a external_id Attestation - let record: Record = setup - .authority_call( - "username_registry", - "create_external_id_attestation", - ExternalIdAttestation { - request_id: "1234".into(), - internal_pubkey: fake_agent_pubkey_1(), - external_id: "4546".into(), - display_name: "alice".into() - }, - ) - .await - .unwrap(); - - setup.consistency().await; - - // Authority cannot delete a external_id Attestation - let result: Result = setup - .authority_call( - "username_registry", - "delete_external_id_attestation", - record.action_address(), - ) - .await; - - assert!(result.is_err()); - - // Alice cannot delete a external_id Attestation - let result2: Result = setup - .alice_call( - "username_registry", - "delete_external_id_attestation", - record.action_address(), - ) - .await; - - assert!(result2.is_err()); -} - - - -#[tokio::test(flavor = "multi_thread")] -async fn all_can_get_external_id_attestations() { - let setup = TestSetup::authority_and_alice().await; - setup.conductors.exchange_peer_info().await; - - // Authority creates an external_id Attestation - let record: Record = setup - .authority_call( - "username_registry", - "create_external_id_attestation", - ExternalIdAttestation { - request_id: "1234".into(), - internal_pubkey: fake_agent_pubkey_1(), - external_id: "4546".into(), - display_name: "alice".into() - }, - ) - .await - .unwrap(); - - setup.consistency().await; - - // Authority gets the external_id Attestation - let maybe_record: Option = setup - .authority_call( - "username_registry", - "get_external_id_attestation", - record.action_address(), - ) - .await - .unwrap(); - - assert!(maybe_record.is_some()); - - // Alice gets the external_id Attestation - let maybe_record2: Option = setup - .alice_call( - "username_registry", - "get_external_id_attestation", - record.action_address(), - ) - .await - .unwrap(); - - assert!(maybe_record2.is_some()); -} - - -#[tokio::test(flavor = "multi_thread")] -async fn all_can_get_external_id_attestation_for_agent() { - let setup = TestSetup::authority_and_alice().await; - setup.conductors.exchange_peer_info().await; - - // Authority's complete list of attestations initially empty - let all_records1: Vec = setup - .authority_call("username_registry", "get_all_external_id_ahs", ()) - .await - .unwrap(); - assert_eq!(all_records1, vec![]); - - // Authority creates an external_id Attestation - let _: Record = setup - .authority_call( - "username_registry", - "create_external_id_attestation", - ExternalIdAttestation { - request_id: "1234".into(), - internal_pubkey: setup.alice_pubkey(), - external_id: "4546".into(), - display_name: "alice".into() - }, - ) - .await - .unwrap(); - - // Authority gets the external_id Attestation - let maybe_record: Option = setup - .authority_call( - "username_registry", - "get_attestation_for_external_id", - "4546".to_string() - ) - .await - .unwrap(); - let entry = maybe_record - .clone() - .unwrap() - .entry() - .to_app_option::() - .unwrap() - .unwrap(); - - assert_eq!(entry.external_id, "4546"); - assert_eq!(entry.internal_pubkey, setup.alice_pubkey()); - - // Alice gets the external_id Attestation - setup.consistency().await; - - let maybe_vector_record: Vec = setup - .alice_call( - "username_registry", - "get_external_id_attestations_for_agent", - setup.alice_pubkey(), - ) - .await - .unwrap(); - let entry2 = maybe_vector_record.first() - .unwrap() - .entry() - .to_app_option::() - .unwrap() - .unwrap(); - - assert_eq!(entry2.external_id, "4546"); - assert_eq!(entry2.internal_pubkey, setup.alice_pubkey()); - - // Authority can see the attestation in their complete list - let all_records2: Vec = setup - .authority_call("username_registry", "get_all_external_id_ahs", ()) - .await - .unwrap(); - - let first_record: Record = maybe_vector_record.first().unwrap().clone(); - - let search_record: Record = setup - .authority_call("username_registry", "get_external_id_attestation", first_record.action_address()) - .await - .unwrap(); - assert_eq!(all_records2.first().unwrap(), search_record.action_address()); -} - - - -#[tokio::test(flavor = "multi_thread")] -async fn cannot_get_external_id_attestation_for_agent_that_doesnt_exist() { - let setup = TestSetup::authority_only().await; - - // Authority tries to get external_id Attestation - let res: Vec> = setup - .authority_call( - "username_registry", - "get_external_id_attestations_for_agent", - fake_agent_pubkey_1(), - ) - .await - .unwrap(); - - assert!(res.is_empty()); -} - - -//this test anticipates future code changes that change the behaviour -//of allowing another pub key to use the same external id -// commented for now - -/*#[tokio::test(flavor = "multi_thread")] -async fn same_external_id_cannot_be_registered_twice_from_another_user() { - // Set up conductors - let setup = TestSetup::authority_only().await; - - // Authority creates an external id attestation - let _: Record = setup - .authority_call( - "username_registry", - "create_external_id_attestation", - ExternalIdAttestation { - request_id: "1234".into(), - internal_pubkey: fake_agent_pubkey_1(), - external_id: "4546".into(), - display_name: "alice".into() - }, - ) - .await - .unwrap(); - - // Authority creates a UsernameAttestation with an identical username - let result: Result = setup - .authority_call( - "username_registry", - "create_external_id_attestation", - ExternalIdAttestation { - request_id: "1234".into(), - internal_pubkey: fake_agent_pubkey_2(), - external_id: "4546".into(), - display_name: "bob".into() - }, - ) - .await; - - assert!(result.is_err()); -}*/ diff --git a/old_crates/holoom_dna_tests/src/tests/username_registry/mod.rs b/old_crates/holoom_dna_tests/src/tests/username_registry/mod.rs deleted file mode 100644 index 6d00bb4..0000000 --- a/old_crates/holoom_dna_tests/src/tests/username_registry/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod external_id_attestation; -mod oracle; -mod recipe; -mod user_metadata; -mod username_attestation; -mod wallet_attestation; diff --git a/old_crates/holoom_dna_tests/src/tests/username_registry/oracle.rs b/old_crates/holoom_dna_tests/src/tests/username_registry/oracle.rs deleted file mode 100644 index df2f3f3..0000000 --- a/old_crates/holoom_dna_tests/src/tests/username_registry/oracle.rs +++ /dev/null @@ -1,71 +0,0 @@ -use hdk::prelude::*; - -use holochain::conductor::api::error::ConductorApiResult; -use holoom_types::{DocumentRelationTag, OracleDocument}; - -use crate::TestSetup; - -#[tokio::test(flavor = "multi_thread")] -async fn can_fetch_documents_by_relation() { - let setup = TestSetup::authority_only().await; - - let _foo1_record: Record = setup - .authority_call( - "username_registry", - "create_oracle_document", - OracleDocument { - name: "foo/1".into(), - json_data: "{\"type\":\"foo\",\"value\":1}".into(), - }, - ) - .await - .unwrap(); - - let _foo2_record: Record = setup - .authority_call( - "username_registry", - "create_oracle_document", - OracleDocument { - name: "foo/2".into(), - json_data: "{\"type\":\"foo\",\"value\":2}".into(), - }, - ) - .await - .unwrap(); - - let res: ConductorApiResult<()> = setup - .authority_call( - "username_registry", - "relate_oracle_document", - DocumentRelationTag { - name: "foo/1".into(), - relation: "foo".into(), - }, - ) - .await; - assert!(res.is_ok()); - - let res: ConductorApiResult<()> = setup - .authority_call( - "username_registry", - "relate_oracle_document", - DocumentRelationTag { - name: "foo/2".into(), - relation: "foo".into(), - }, - ) - .await; - assert!(res.is_ok()); - - let identifiers: Vec = setup - .authority_call( - "username_registry", - "get_related_oracle_document_names", - String::from("foo"), - ) - .await - .unwrap(); - - let expected_identifiers = vec![String::from("foo/1"), String::from("foo/2")]; - assert_eq!(identifiers, expected_identifiers); -} diff --git a/old_crates/holoom_dna_tests/src/tests/username_registry/recipe.rs b/old_crates/holoom_dna_tests/src/tests/username_registry/recipe.rs deleted file mode 100644 index c4575e4..0000000 --- a/old_crates/holoom_dna_tests/src/tests/username_registry/recipe.rs +++ /dev/null @@ -1,361 +0,0 @@ -use hdk::prelude::*; - -use holochain::conductor::api::error::ConductorApiResult; -use holoom_types::{ - recipe::{ - ExecuteRecipePayload, JqInstructionArgumentNames, Recipe, RecipeArgument, - RecipeArgumentType, RecipeExecution, RecipeInstruction, RecipeInstructionExecution, - }, - ExternalIdAttestation, OracleDocument, -}; -use username_registry_utils::deserialize_record_entry; - -use crate::TestSetup; - -#[tokio::test(flavor = "multi_thread")] -async fn can_execute_basic_recipe() { - let setup = TestSetup::authority_and_alice().await; - setup.conductors.exchange_peer_info().await; - - // Materials: - - // Doc: foo/1234 -> { value: 1, owner: "1234" } - // Doc: foo/5678 -> { value: 4, owner: "5678" } - // Doc: foo -> [foo/1234, foo/5678] - // ExternalId: authority_agent_pub_key -> { id: 1234, display_name: "some-user-1" } - // ExternalId: alice_agent_pub_key -> { id: 5678, display_name: "some-user-2" } - - // Recipe: - // Calculate value share of caller - // { - // "$arguments": [{ name" "greeting", type: "string" }], - // "foo_name_list_name": { inst: "get_doc", var_name: `"foo"` }, - // "foo_name_list": { inst: "get_docs", var_name: `"foo"` }, - // "foos": { inst: "get_docs", var_name: "foo_name_list" }, - // "caller_external_id": { inst: "get_caller_external_id" }, - // "$return": { - // inst: "jq", - // input_vars: ["foos", "caller_external_id", "greeting"], - // program: ` - // .caller_external_id.external_id as $id | - // .foos as $foos | - // "\(.greeting) \(.caller_external_id.display_name)" as $msg | - // [$foos[].value] | add as $total | - // $foos[] | select(.owner==$id) | .value / $total | - // { share: ., msg: $msg } - // ` - // } - // } - - // Expected outputs: - // Authority with greeting: 'Hi' -> { share: 0.2, msg: "Hi some-user-1" } - // Alice with greeting: 'Hello' -> { share: 0.8, msg: "Hello some-user-2" } - - let _foo1_record: Record = setup - .authority_call( - "username_registry", - "create_oracle_document", - OracleDocument { - name: "foo/1234".into(), - json_data: "{\"value\":1,\"owner\":\"1234\"}".into(), - }, - ) - .await - .unwrap(); - - let _foo2_record: Record = setup - .authority_call( - "username_registry", - "create_oracle_document", - OracleDocument { - name: "foo/5678".into(), - json_data: "{\"value\":4,\"owner\":\"5678\"}".into(), - }, - ) - .await - .unwrap(); - - let _foo_name_list_record: Record = setup - .authority_call( - "username_registry", - "create_oracle_document", - OracleDocument { - name: "foo".into(), - json_data: "[\"foo/1234\",\"foo/5678\"]".into(), - }, - ) - .await - .unwrap(); - - let res: ConductorApiResult = setup - .authority_call( - "username_registry", - "create_external_id_attestation", - ExternalIdAttestation { - request_id: "".into(), - internal_pubkey: setup.authority_pubkey(), - external_id: "1234".into(), - display_name: "some-user-1".into(), - }, - ) - .await; - assert!(res.is_ok()); - - let res: ConductorApiResult = setup - .authority_call( - "username_registry", - "create_external_id_attestation", - ExternalIdAttestation { - request_id: "".into(), - internal_pubkey: setup.alice_pubkey(), - external_id: "5678".into(), - display_name: "some-user-2".into(), - }, - ) - .await; - assert!(res.is_ok()); - - let recipe_record: Record = setup - .authority_call( - "username_registry", - "create_recipe", - Recipe { - trusted_authors: vec![setup.authority_pubkey()], - arguments: vec![("greeting".into(),RecipeArgumentType::String)], - instructions: vec![ - ( - "foo_name_list_name".into(), - RecipeInstruction::Constant { - value: "\"foo\"".into(), - }, - ), - ( - "foo_name_list".into(), - RecipeInstruction::GetLatestDocWithIdentifier { - var_name: "foo_name_list_name".into(), - }, - ), - ( - "foos".into(), - RecipeInstruction::GetDocsListedByVar { - var_name: "foo_name_list".into(), - }, - ), - ( - "caller_external_id".into(), - RecipeInstruction::GetLatestCallerExternalId, - ), - ( - "$return".into(), - RecipeInstruction::Jq { - input_var_names: JqInstructionArgumentNames::List{var_names: vec!["foos".into(),"caller_external_id".into(), "greeting".into()]}, - program: ".caller_external_id.external_id as $id | .foos as $foos | \"\\(.greeting) \\(.caller_external_id.display_name)\" as $msg | [$foos[].value] | add as $total | $foos[] | select(.owner==$id) | .value / $total | { share: ., msg: $msg }".into() - } - ) - ], - }, - ) - .await - .unwrap(); - - // Make sure both agents know recipe - setup.consistency().await; - - let authority_execution_record: Record = setup - .authority_call( - "username_registry", - "execute_recipe", - ExecuteRecipePayload { - recipe_ah: recipe_record.action_address().clone(), - arguments: vec![RecipeArgument::String { value: "Hi".into() }], - }, - ) - .await - .unwrap(); - - let authority_execution: RecipeExecution = - deserialize_record_entry(authority_execution_record).unwrap(); - assert_eq!( - authority_execution.output, - String::from("{\"share\":0.2,\"msg\":\"Hi some-user-1\"}") - ); - - let alice_execution_record: Record = setup - .alice_call( - "username_registry", - "execute_recipe", - ExecuteRecipePayload { - recipe_ah: recipe_record.action_address().clone(), - arguments: vec![RecipeArgument::String { - value: "Hello".into(), - }], - }, - ) - .await - .unwrap(); - - let alice_execution: RecipeExecution = - deserialize_record_entry(alice_execution_record).unwrap(); - assert_eq!( - alice_execution.output, - String::from("{\"share\":0.8,\"msg\":\"Hello some-user-2\"}") - ); - - // Alice's untrusted document isn't able to censor the outcome - - let _alice_foo_name_list_record: Record = setup - .alice_call( - "username_registry", - "create_oracle_document", - OracleDocument { - name: "foo".into(), - json_data: "[\"foo/5678\"]".into(), - }, - ) - .await - .unwrap(); - - let alice_execution_record2: Record = setup - .alice_call( - "username_registry", - "execute_recipe", - ExecuteRecipePayload { - recipe_ah: recipe_record.action_address().clone(), - arguments: vec![RecipeArgument::String { - value: "Hello".into(), - }], - }, - ) - .await - .unwrap(); - - let alice_execution2: RecipeExecution = - deserialize_record_entry(alice_execution_record2).unwrap(); - // Result should be unchanged, rather than the dishonestly attempted alteration of: - // { "share": 1, "msg": "Hello some-user-2" } - assert_eq!( - alice_execution2.output, - String::from("{\"share\":0.8,\"msg\":\"Hello some-user-2\"}") - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn cannot_use_untrusted_docs() { - let setup = TestSetup::authority_only().await; - - let single_doc_recipe_record: Record = setup - .authority_call( - "username_registry", - "create_recipe", - Recipe { - trusted_authors: vec![fake_agent_pub_key(0)], - arguments: vec![], - instructions: vec![ - ( - "doc_name".into(), - RecipeInstruction::Constant { - value: "\"foo\"".into(), - }, - ), - ( - "$return".into(), - RecipeInstruction::GetLatestDocWithIdentifier { - var_name: "doc_name".into(), - }, - ), - ], - }, - ) - .await - .unwrap(); - - let doc_record: Record = setup - .authority_call( - "username_registry", - "create_oracle_document", - OracleDocument { - name: "foo".into(), - json_data: "\"suspicious\"".into(), - }, - ) - .await - .unwrap(); - - let result: ConductorApiResult = setup - .authority_call( - "username_registry", - "create_recipe_execution", - RecipeExecution { - recipe_ah: single_doc_recipe_record.action_address().clone(), - arguments: Vec::new(), - instruction_executions: vec![ - RecipeInstructionExecution::Constant, - RecipeInstructionExecution::GetLatestDocWithIdentifier { - doc_ah: doc_record.action_address().clone(), - }, - ], - output: "\"suspicious\"".into(), - }, - ) - .await; - match result { - Ok(_) => { - panic!("Execution should be invalid"); - } - Err(err) => { - assert!(err.to_string().contains("Untrusted author")) - } - } - - let doc_list_recipe_record: Record = setup - .authority_call( - "username_registry", - "create_recipe", - Recipe { - trusted_authors: vec![fake_agent_pub_key(0)], - arguments: vec![], - instructions: vec![ - ( - "doc_names".into(), - RecipeInstruction::Constant { - value: "[\"foo\"]".into(), - }, - ), - ( - "$return".into(), - RecipeInstruction::GetDocsListedByVar { - var_name: "doc_names".into(), - }, - ), - ], - }, - ) - .await - .unwrap(); - - let result: ConductorApiResult = setup - .authority_call( - "username_registry", - "create_recipe_execution", - RecipeExecution { - recipe_ah: doc_list_recipe_record.action_address().clone(), - arguments: Vec::new(), - instruction_executions: vec![ - RecipeInstructionExecution::Constant, - RecipeInstructionExecution::GetDocsListedByVar { - doc_ahs: vec![doc_record.action_address().clone()], - }, - ], - output: "[\"suspicious\"]".into(), - }, - ) - .await; - match result { - Ok(_) => { - panic!("Execution should be invalid"); - } - Err(err) => { - assert!(err.to_string().contains("Untrusted author")) - } - } -} diff --git a/old_crates/holoom_dna_tests/src/tests/username_registry/user_metadata.rs b/old_crates/holoom_dna_tests/src/tests/username_registry/user_metadata.rs deleted file mode 100644 index 2ade9a5..0000000 --- a/old_crates/holoom_dna_tests/src/tests/username_registry/user_metadata.rs +++ /dev/null @@ -1,63 +0,0 @@ -use std::collections::HashMap; - -use holochain::conductor::api::error::ConductorApiError; -use holoom_types::{GetMetadataItemValuePayload, UpdateMetadataItemPayload}; - -use crate::TestSetup; - -#[tokio::test(flavor = "multi_thread")] -async fn users_can_only_update_their_own_metadata() { - let setup = TestSetup::authority_and_alice_bob().await; - setup.conductors.exchange_peer_info().await; - - // Alice starts with no metadata - let initial_metadata: HashMap = setup - .alice_call("username_registry", "get_metadata", setup.alice_pubkey()) - .await - .unwrap(); - assert_eq!(initial_metadata, HashMap::default()); - - // Bob cannot set Alice's metadata - let res1: Result<(), ConductorApiError> = setup - .bob_call( - "username_registry", - "update_metadata_item", - UpdateMetadataItemPayload { - agent_pubkey: setup.alice_pubkey(), - name: "foo".into(), - value: "bar".into(), - }, - ) - .await; - assert!(res1.is_err()); - - // Alice sets an item - let _: () = setup - .alice_call( - "username_registry", - "update_metadata_item", - UpdateMetadataItemPayload { - agent_pubkey: setup.alice_pubkey(), - name: "foo".into(), - value: "bar2".into(), - }, - ) - .await - .unwrap(); - - setup.consistency().await; - - // Bob sees new item - let value1: String = setup - .bob_call( - "username_registry", - "get_metadata_item_value", - GetMetadataItemValuePayload { - agent_pubkey: setup.alice_pubkey(), - name: "foo".into(), - }, - ) - .await - .unwrap(); - assert_eq!(value1, String::from("bar2")); -} diff --git a/old_crates/holoom_dna_tests/src/tests/username_registry/username_attestation.rs b/old_crates/holoom_dna_tests/src/tests/username_registry/username_attestation.rs deleted file mode 100644 index f8dce0f..0000000 --- a/old_crates/holoom_dna_tests/src/tests/username_registry/username_attestation.rs +++ /dev/null @@ -1,422 +0,0 @@ -use hdk::prelude::*; -use holochain::conductor::api::error::ConductorApiError; -use holoom_types::{SignableBytes, SignedUsername, UsernameAttestation}; - -use crate::TestSetup; - -#[tokio::test(flavor = "multi_thread")] -async fn only_authority_can_create_username_attestation() { - let setup = TestSetup::authority_and_alice().await; - - // Authority creates a UsernameAttestation for alice - let _: Record = setup - .authority_call( - "username_registry", - "create_username_attestation", - UsernameAttestation { - username: "a_cool_guy1".into(), - agent: setup.alice_pubkey(), - }, - ) - .await - .unwrap(); - - // Alice cannot create an UsernameAttestation - let result: Result = setup - .alice_call( - "username_registry", - "create_username_attestation", - UsernameAttestation { - username: "a_cool_guy2".into(), - agent: setup.alice_pubkey(), - }, - ) - .await; - - assert!(result.is_err()); -} - -#[tokio::test(flavor = "multi_thread")] -async fn same_username_cannot_be_registered_twice() { - // Set up conductors - let setup = TestSetup::authority_only().await; - - // Authority creates an UsernameAttestation - let _: Record = setup - .authority_call( - "username_registry", - "create_username_attestation", - UsernameAttestation { - username: "a_cool_guy".into(), - agent: fake_agent_pub_key(0), - }, - ) - .await - .unwrap(); - - // Authority creates a UsernameAttestation with an identical username - let result: Result = setup - .authority_call( - "username_registry", - "create_username_attestation", - UsernameAttestation { - username: "a_cool_guy".into(), - agent: fake_agent_pub_key(1), - }, - ) - .await; - - assert!(result.is_err()); - - // Authority creates a UsernameAttestation with a different username - let _: Record = setup - .authority_call( - "username_registry", - "create_username_attestation", - UsernameAttestation { - username: "a_cool_guy2".into(), - agent: fake_agent_pub_key(2), - }, - ) - .await - .unwrap(); -} - -#[tokio::test(flavor = "multi_thread")] -async fn same_agent_cannot_be_registered_twice() { - // Set up conductors - let setup = TestSetup::authority_only().await; - - // Authority creates an UsernameAttestation - let _: Record = setup - .authority_call( - "username_registry", - "create_username_attestation", - UsernameAttestation { - username: "a_cool_guy".into(), - agent: fake_agent_pubkey_1(), - }, - ) - .await - .unwrap(); - - // Authority creates a UsernameAttestation with an identical agent - let result: Result = setup - .authority_call( - "username_registry", - "create_username_attestation", - UsernameAttestation { - username: "a_different_guy".into(), - agent: fake_agent_pubkey_1(), - }, - ) - .await; - - assert!(result.is_err()); - - // Authority creates a UsernameAttestation with a different agent - let _: Record = setup - .authority_call( - "username_registry", - "create_username_attestation", - UsernameAttestation { - username: "a_third_guy".into(), - agent: fake_agent_pubkey_2(), - }, - ) - .await - .unwrap(); -} - -#[tokio::test(flavor = "multi_thread")] -async fn username_must_be_within_character_limit() { - let setup = TestSetup::authority_only().await; - - // Authority creates an username of 5 characters - let result1: Result = setup - .authority_call( - "username_registry", - "create_username_attestation", - UsernameAttestation { - username: "abcde".into(), - agent: fake_agent_pubkey_1(), - }, - ) - .await; - - assert!(result1.is_err()); - - // Alice creates an username of 33 characters - let result2: Result = setup - .authority_call( - "username_registry", - "create_username_attestation", - UsernameAttestation { - username: "abcdeabcdeabcdeabcdeabcdeabcdeabc".into(), - agent: fake_agent_pubkey_1(), - }, - ) - .await; - - assert!(result2.is_err()); - - // Alice creates an username of 15 characters - let result3: Result = setup - .authority_call( - "username_registry", - "create_username_attestation", - UsernameAttestation { - username: "abcdeabcdeabcde".into(), - agent: fake_agent_pubkey_1(), - }, - ) - .await; - - assert!(result3.is_ok()); -} - -#[tokio::test(flavor = "multi_thread")] -async fn nobody_can_delete_username_attestation() { - let setup = TestSetup::authority_and_alice().await; - setup.conductors.exchange_peer_info().await; - - // Authority creates a UsernameAttestation - let record: Record = setup - .authority_call( - "username_registry", - "create_username_attestation", - UsernameAttestation { - username: "asodijsadvjsadlkj".into(), - agent: fake_agent_pubkey_1(), - }, - ) - .await - .unwrap(); - - setup.consistency().await; - - // Authority cannot delete a UsernameAttestation - let result: Result = setup - .authority_call( - "username_registry", - "delete_username_attestation", - record.action_address(), - ) - .await; - - assert!(result.is_err()); - - // Alice cannot delete a UsernameAttestation - let result2: Result = setup - .alice_call( - "username_registry", - "delete_username_attestation", - record.action_address(), - ) - .await; - - assert!(result2.is_err()); -} - -#[tokio::test(flavor = "multi_thread")] -async fn all_can_get_username_attestations() { - let setup = TestSetup::authority_and_alice().await; - setup.conductors.exchange_peer_info().await; - - // Authority creates an UsernameAttestation - let record: Record = setup - .authority_call( - "username_registry", - "create_username_attestation", - UsernameAttestation { - username: "asodijsadvjsadlkj".into(), - agent: fake_agent_pubkey_1(), - }, - ) - .await - .unwrap(); - - setup.consistency().await; - - // Authority gets the UsernameAttestation - let maybe_record: Option = setup - .authority_call( - "username_registry", - "get_username_attestation", - record.action_address(), - ) - .await - .unwrap(); - - assert!(maybe_record.is_some()); - - // Alice gets the UsernameAttestation - let maybe_record2: Option = setup - .alice_call( - "username_registry", - "get_username_attestation", - record.action_address(), - ) - .await - .unwrap(); - - assert!(maybe_record2.is_some()); -} - -#[tokio::test(flavor = "multi_thread")] -async fn all_can_get_username_attestation_for_agent() { - let setup = TestSetup::authority_and_alice().await; - setup.conductors.exchange_peer_info().await; - - // Authority's complete list of attestations initially empty - let all_records1: Vec = setup - .authority_call("username_registry", "get_all_username_attestations", ()) - .await - .unwrap(); - assert_eq!(all_records1, vec![]); - - // Authority creates an UsernameAttestation - let _: Record = setup - .authority_call( - "username_registry", - "create_username_attestation", - UsernameAttestation { - username: "username1".into(), - agent: fake_agent_pubkey_1(), - }, - ) - .await - .unwrap(); - - // Authority gets the UsernameAttestation - let maybe_record: Option = setup - .authority_call( - "username_registry", - "get_username_attestation_for_agent", - fake_agent_pubkey_1(), - ) - .await - .unwrap(); - let entry = maybe_record - .clone() - .unwrap() - .entry() - .to_app_option::() - .unwrap() - .unwrap(); - - assert_eq!(entry.username, "username1"); - assert_eq!(entry.agent, fake_agent_pubkey_1()); - - // Alice gets the UsernameAttestation - setup.consistency().await; - - let maybe_record2: Option = setup - .alice_call( - "username_registry", - "get_username_attestation_for_agent", - fake_agent_pubkey_1(), - ) - .await - .unwrap(); - let entry2 = maybe_record2 - .unwrap() - .entry() - .to_app_option::() - .unwrap() - .unwrap(); - - assert_eq!(entry2.username, "username1"); - assert_eq!(entry2.agent, fake_agent_pubkey_1()); - - // Authority can see the attestation in their complete list - let all_records2: Vec = setup - .authority_call("username_registry", "get_all_username_attestations", ()) - .await - .unwrap(); - assert_eq!(all_records2, vec![maybe_record.unwrap()]); -} - -#[tokio::test(flavor = "multi_thread")] -async fn cannot_get_username_attestation_for_agent_that_doesnt_exist() { - let setup = TestSetup::authority_only().await; - - // Authority tries to get UsernameAttestation - let res: Option = setup - .authority_call( - "username_registry", - "get_username_attestation_for_agent", - fake_agent_pubkey_1(), - ) - .await - .unwrap(); - - assert!(res.is_none()); -} - -#[tokio::test(flavor = "multi_thread")] -async fn can_attest_username_via_remote_call() { - let setup = TestSetup::authority_and_alice().await; - setup.conductors.exchange_peer_info().await; - - // Alice creates a UsernameAttestation - let record: Record = setup - .alice_call( - "username_registry", - "sign_username_to_attest", - "asodijsadvjsadlkj".to_string(), - ) - .await - .unwrap(); - - setup.consistency().await; - - // UsernameAttestation has been created - let result: Result, ConductorApiError> = setup - .authority_call( - "username_registry", - "get_username_attestation", - record.action_address(), - ) - .await; - - let same_record = result - .expect(" get_username_attestation should have succeeded") - .expect("Record should exist"); - assert_eq!(same_record.action_address(), record.action_address()); - let entry = record - .entry() - .to_app_option::() - .unwrap() - .unwrap(); - assert_ne!(entry.agent, setup.authority_pubkey()); - assert_eq!(entry.agent, setup.alice_pubkey()); -} - -#[tokio::test(flavor = "multi_thread")] -async fn authority_wont_ingest_invalid_username_signature() { - let setup = TestSetup::authority_and_alice().await; - setup.conductors.exchange_peer_info().await; - - // Alice signs username - let signature: Signature = setup - .alice_call("signer", "sign_message", SignableBytes("whatever".into())) - .await - .unwrap(); - let invalid_signed_username = SignedUsername { - username: "a_different_name".into(), - signature, - signer: setup.alice_pubkey(), - }; - - // Authority ingests signed username - let result: Result = setup - .authority_call( - "username_registry", - "ingest_signed_username", - invalid_signed_username, - ) - .await; - - assert!(result.is_err()); -} diff --git a/old_crates/holoom_dna_tests/src/tests/username_registry/wallet_attestation.rs b/old_crates/holoom_dna_tests/src/tests/username_registry/wallet_attestation.rs deleted file mode 100644 index fe21c31..0000000 --- a/old_crates/holoom_dna_tests/src/tests/username_registry/wallet_attestation.rs +++ /dev/null @@ -1,149 +0,0 @@ -use hdk::prelude::*; -use holochain::conductor::api::error::ConductorApiResult; -use holoom_types::{ChainWalletSignature, EvmAddress, EvmSignature, WalletAttestation}; -use std::str::FromStr; -use username_registry_validation::{evm_signing_message, solana_signing_message}; - -use crate::TestSetup; - -#[tokio::test(flavor = "multi_thread")] -async fn checks_validity_of_evm_wallet_attestation() { - let setup = TestSetup::authority_and_alice().await; - - // Create WalletAttestation for alice at address 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 - - // First account of seed phrase: test test test test test test test test test test test junk - let signer_private_key = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; - use ethers_signers::{LocalWallet, Signer}; - let signer_wallet = LocalWallet::from_str(signer_private_key).unwrap(); - let wallet_address = signer_wallet.address(); - let wallet_address = EvmAddress::try_from(wallet_address.as_bytes()).unwrap(); - assert_eq!( - wallet_address.to_checksum(None), - String::from("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266") - ); - let message: String = setup - .alice_call( - "username_registry", - "get_evm_wallet_binding_message", - wallet_address, - ) - .await - .unwrap(); - - let signature = signer_wallet.sign_message(message).await.unwrap(); - let signature_bytes = signature.to_vec(); - let signature = EvmSignature::try_from(&signature_bytes[..]).unwrap(); - - let chain_wallet_signature = ChainWalletSignature::Evm { - evm_address: wallet_address, - evm_signature: signature, - }; - - // Genuine attestation should be accepted - let res: ConductorApiResult = setup - .alice_call( - "username_registry", - "attest_wallet_signature", - chain_wallet_signature, - ) - .await; - assert!(res.is_ok()); - - let prev_action = res.unwrap().action_address().clone(); - let malicious_message = - evm_signing_message(&wallet_address, fake_agent_pubkey_1(), prev_action.clone()); - let signature = signer_wallet.sign_message(malicious_message).await.unwrap(); - let signature_bytes = signature.to_vec(); - let signature = EvmSignature::try_from(&signature_bytes[..]).unwrap(); - - let malicious_attestation = WalletAttestation { - chain_wallet_signature: ChainWalletSignature::Evm { - evm_address: wallet_address, - evm_signature: signature, - }, - agent: setup.alice_pubkey(), - prev_action, - }; - - // Malicious attestation should be rejected - let res: ConductorApiResult = setup - .alice_call( - "username_registry", - "create_wallet_attestation", - malicious_attestation, - ) - .await; - assert!(res.is_err()); -} - -#[tokio::test(flavor = "multi_thread")] -async fn checks_validity_of_solana_wallet_attestation() { - let setup = TestSetup::authority_and_alice().await; - - // Create WalletAttestation for alice at address oeYf6KAJkLYhBuR8CiGc6L4D4Xtfepr85fuDgA9kq96 - - // First account of seed phrase: test test test test test test test test test test test junk - let private_key = - "4Cfc4TJ6dsWwLcw8aJ5uhx7UJKPR5VGXTu2iJr5bVRoTDsxzb6qfJrzR5HNhBcwGwsXqGeHzDR3eUWLr7MRnska8"; - let private_key_bytes = bs58::decode(private_key).into_vec().unwrap(); - - use ed25519_dalek::{Signer, SigningKey, SECRET_KEY_LENGTH}; - - let signing_key = SigningKey::try_from(&private_key_bytes[..SECRET_KEY_LENGTH]).unwrap(); - let solana_address = signing_key.verifying_key(); - - assert_eq!( - bs58::encode(solana_address.as_bytes()).into_string(), - String::from("oeYf6KAJkLYhBuR8CiGc6L4D4Xtfepr85fuDgA9kq96") - ); - - let message: String = setup - .alice_call( - "username_registry", - "get_solana_wallet_binding_message", - solana_address, - ) - .await - .unwrap(); - let solana_signature = signing_key.try_sign(message.as_bytes()).unwrap(); - - let chain_wallet_signature = ChainWalletSignature::Solana { - solana_address: Box::new(solana_address), - solana_signature, - }; - - // Genuine attestation should be accepted - let res: ConductorApiResult = setup - .alice_call( - "username_registry", - "attest_wallet_signature", - chain_wallet_signature, - ) - .await; - assert!(res.is_ok()); - - let prev_action = res.unwrap().action_address().clone(); - let malicious_message = - solana_signing_message(&solana_address, fake_agent_pubkey_1(), prev_action.clone()); - let solana_signature = signing_key.try_sign(malicious_message.as_bytes()).unwrap(); - - let malicious_attestation = WalletAttestation { - chain_wallet_signature: ChainWalletSignature::Solana { - solana_address: Box::new(solana_address), - solana_signature, - }, - agent: setup.alice_pubkey(), - prev_action, - }; - - // Genuine attestation should be rejected - let res: ConductorApiResult = setup - .alice_call( - "username_registry", - "create_wallet_attestation", - malicious_attestation, - ) - .await; - assert!(res.is_err()); -} diff --git a/old_crates/holoom_types/Cargo.toml b/old_crates/holoom_types/Cargo.toml deleted file mode 100644 index 83bc085..0000000 --- a/old_crates/holoom_types/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "holoom_types" -version = "0.0.3" -edition = "2021" - -[lib] -crate-type = ["cdylib", "rlib"] -name = "holoom_types" - -[dependencies] -hdi = { workspace = true } -serde = { workspace = true } -alloy-primitives = { workspace = true } -ed25519-dalek = { workspace = true } -ts-rs = "9" diff --git a/old_crates/holoom_types/src/evm_signing_offer.rs b/old_crates/holoom_types/src/evm_signing_offer.rs deleted file mode 100644 index 905e2b2..0000000 --- a/old_crates/holoom_types/src/evm_signing_offer.rs +++ /dev/null @@ -1,81 +0,0 @@ -use hdi::prelude::*; -use serde::{Deserialize, Serialize}; -use ts_rs::TS; - -use crate::{EvmAddress, EvmSignature}; - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, TS)] -#[serde(tag = "type")] -#[ts(export)] -pub enum EvmU256Item { - Uint, - Hex, - HoloAgent, -} - -#[derive(Clone, PartialEq, TS, Serialize, Deserialize, Debug)] -#[ts(export)] -pub struct EvmSigningOffer { - #[ts(type = "ActionHash")] - pub recipe_ah: ActionHash, - pub u256_items: Vec, -} - -#[hdk_entry_helper] -#[derive(Clone, PartialEq, TS)] -#[ts(export)] -pub struct SignedEvmSigningOffer { - #[ts(type = "Uint8Array")] - pub signer: EvmAddress, - #[ts(type = "[Uint8Array, Uint8Array, number]")] - pub signature: EvmSignature, - pub offer: EvmSigningOffer, -} - -#[derive(Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub struct CreateEvmSigningOfferPayload { - pub identifier: String, - pub signed_offer: SignedEvmSigningOffer, -} - -#[derive(Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub struct EvmSignatureOverRecipeExecutionRequest { - pub request_id: String, - #[ts(type = "ActionHash")] - pub recipe_execution_ah: ActionHash, - #[ts(type = "ActionHash")] - pub signing_offer_ah: ActionHash, -} - -#[derive(Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub struct ResolveEvmSignatureOverRecipeExecutionRequestPayload { - pub request_id: String, - #[ts(type = "AgentPubKey")] - pub requestor: AgentPubKey, - pub signed_u256_array: SignedEvmU256Array, -} - -#[derive(Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub struct RejectEvmSignatureOverRecipeExecutionRequestPayload { - pub request_id: String, - #[ts(type = "AgentPubKey")] - pub requestor: AgentPubKey, - pub reason: String, -} - -pub type EvmU256 = alloy_primitives::U256; - -#[derive(Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub struct SignedEvmU256Array { - #[ts(type = "Uint8Array[]")] - pub raw: Vec, - #[ts(type = "[Uint8Array, Uint8Array, number]")] - pub signature: EvmSignature, - #[ts(type = "Uint8Array")] - pub signer: EvmAddress, -} diff --git a/old_crates/holoom_types/src/external_id.rs b/old_crates/holoom_types/src/external_id.rs deleted file mode 100644 index 3eeb4cc..0000000 --- a/old_crates/holoom_types/src/external_id.rs +++ /dev/null @@ -1,49 +0,0 @@ -use hdi::prelude::*; -use serde::{Deserialize, Serialize}; -use ts_rs::TS; - -#[hdk_entry_helper] -#[derive(Clone, PartialEq, TS)] -#[ts(export)] -pub struct ExternalIdAttestation { - pub request_id: String, - #[ts(type = "AgentPubKey")] - pub internal_pubkey: AgentPubKey, - pub external_id: String, - pub display_name: String, -} - -#[derive(Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub struct SendExternalIdAttestationRequestPayload { - pub request_id: String, - pub code_verifier: String, - pub code: String, -} - -#[derive(Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub struct IngestExternalIdAttestationRequestPayload { - pub request_id: String, - pub code_verifier: String, - pub code: String, -} - -#[derive(Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub struct ConfirmExternalIdRequestPayload { - pub request_id: String, - pub external_id: String, - pub display_name: String, - #[ts(type = "AgentPubKey")] - pub requestor: AgentPubKey, -} - -#[derive(Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub struct RejectExternalIdRequestPayload { - pub request_id: String, - #[ts(type = "AgentPubKey")] - pub requestor: AgentPubKey, - pub reason: String, -} diff --git a/old_crates/holoom_types/src/lib.rs b/old_crates/holoom_types/src/lib.rs deleted file mode 100644 index a43508a..0000000 --- a/old_crates/holoom_types/src/lib.rs +++ /dev/null @@ -1,86 +0,0 @@ -use evm_signing_offer::{EvmU256, SignedEvmU256Array}; -use hdi::prelude::*; -use serde::{Deserialize, Serialize}; -use ts_rs::TS; - -pub mod external_id; -pub use external_id::*; -pub mod evm_signing_offer; -pub mod metadata; -pub mod recipe; -pub use metadata::*; -pub mod wallet; -pub use wallet::*; -pub mod username; -pub use username::*; -pub mod oracle; -pub use oracle::*; - -#[derive(Serialize, Deserialize, Debug, TS)] -#[serde(tag = "type")] -#[ts(export)] -pub enum LocalHoloomSignal { - ExternalIdAttestationRequested { - request_id: String, - #[ts(type = "AgentPubKey")] - requestor_pubkey: AgentPubKey, - code_verifier: String, - code: String, - }, - ExternalIdAttested { - request_id: String, - #[ts(type = "Record")] - record: Record, - }, - ExternalIdRejected { - request_id: String, - reason: String, - }, - EvmSignatureRequested { - request_id: String, - #[ts(type = "AgentPubKey")] - requestor_pubkey: AgentPubKey, - #[ts(type = "Uint8Array[]")] - u256_array: Vec, - }, - EvmSignatureProvided { - request_id: String, - signed_u256_array: SignedEvmU256Array, - }, - EvmSignatureRequestRejected { - request_id: String, - reason: String, - }, -} - -#[derive(Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub enum RemoteHoloomSignal { - ExternalIdAttested { - request_id: String, - #[ts(type = "Record")] - record: Record, - }, - ExternalIdRejected { - request_id: String, - reason: String, - }, - EvmSignatureProvided { - request_id: String, - signed_u256_array: SignedEvmU256Array, - }, - EvmSignatureRequestRejected { - request_id: String, - reason: String, - }, -} - -#[derive(Serialize, Deserialize, Debug, Clone, SerializedBytes, TS)] -#[ts(export)] -pub struct SignableBytes(pub Vec); - -#[dna_properties] -#[derive(Clone)] -pub struct HoloomDnaProperties { - pub authority_agent: String, -} diff --git a/old_crates/holoom_types/src/metadata.rs b/old_crates/holoom_types/src/metadata.rs deleted file mode 100644 index 1ee6e4b..0000000 --- a/old_crates/holoom_types/src/metadata.rs +++ /dev/null @@ -1,27 +0,0 @@ -use hdi::prelude::*; -use serde::{Deserialize, Serialize}; -use ts_rs::TS; - -#[derive(Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub struct MetadataItem { - pub name: String, - pub value: String, -} - -#[derive(Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub struct UpdateMetadataItemPayload { - #[ts(type = "AgentPubKey")] - pub agent_pubkey: AgentPubKey, - pub name: String, - pub value: String, -} - -#[derive(Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub struct GetMetadataItemValuePayload { - #[ts(type = "AgentPubKey")] - pub agent_pubkey: AgentPubKey, - pub name: String, -} diff --git a/old_crates/holoom_types/src/oracle.rs b/old_crates/holoom_types/src/oracle.rs deleted file mode 100644 index 7002a2e..0000000 --- a/old_crates/holoom_types/src/oracle.rs +++ /dev/null @@ -1,19 +0,0 @@ -use hdi::prelude::*; -use serde::{Deserialize, Serialize}; -use ts_rs::TS; - -#[hdk_entry_helper] -#[derive(Clone, PartialEq, TS)] -#[ts(export)] -pub struct OracleDocument { - // E.g. organizers/1234/championship-ids - pub name: String, - pub json_data: String, -} - -#[derive(Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub struct DocumentRelationTag { - pub name: String, - pub relation: String, -} diff --git a/old_crates/holoom_types/src/recipe.rs b/old_crates/holoom_types/src/recipe.rs deleted file mode 100644 index e11f2ce..0000000 --- a/old_crates/holoom_types/src/recipe.rs +++ /dev/null @@ -1,104 +0,0 @@ -use hdi::prelude::*; -use serde::{Deserialize, Serialize}; -use ts_rs::TS; - -use crate::EvmAddress; - -#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, TS)] -#[ts(export)] -#[serde(tag = "type")] -pub enum RecipeArgumentType { - String, - EvmAddress, -} - -#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, TS)] -#[ts(export)] -#[serde(tag = "type")] -pub enum JqInstructionArgumentNames { - Single { var_name: String }, - List { var_names: Vec }, -} - -#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, TS)] -#[ts(export)] -#[serde(tag = "type")] -pub enum RecipeInstruction { - Constant { - value: String, - }, - GetLatestDocWithIdentifier { - var_name: String, - }, - Jq { - input_var_names: JqInstructionArgumentNames, - program: String, - }, - GetDocsListedByVar { - var_name: String, - }, - GetLatestCallerExternalId, - GetCallerAgentPublicKey, -} - -#[hdk_entry_helper] -#[derive(Clone, PartialEq, TS)] -#[ts(export)] -pub struct Recipe { - #[ts(type = "AgentPubKey[]")] - pub trusted_authors: Vec, - pub arguments: Vec<(String, RecipeArgumentType)>, - pub instructions: Vec<(String, RecipeInstruction)>, -} - -#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, TS)] -#[ts(export)] -#[serde(tag = "type")] -pub enum RecipeArgument { - String { - value: String, - }, - EvmAddress { - #[ts(type = "Uint8Array")] - value: EvmAddress, - }, -} - -#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub enum RecipeInstructionExecution { - Constant, // In memory - GetLatestDocWithIdentifier { - #[ts(type = "ActionHash")] - doc_ah: ActionHash, - }, - Jq, // In memory - GetDocsListedByVar { - #[ts(type = "ActionHash")] - doc_ahs: Vec, - }, - GetLatestCallerExternalId { - #[ts(type = "ActionHash")] - attestation_ah: ActionHash, - }, - GetCallerAgentPublicKey, // In memory -} - -#[hdk_entry_helper] -#[derive(Clone, PartialEq, TS)] -#[ts(export)] -pub struct RecipeExecution { - #[ts(type = "ActionHash")] - pub recipe_ah: ActionHash, - pub arguments: Vec, - pub instruction_executions: Vec, - pub output: String, -} - -#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub struct ExecuteRecipePayload { - #[ts(type = "ActionHash")] - pub recipe_ah: ActionHash, - pub arguments: Vec, -} diff --git a/old_crates/holoom_types/src/username.rs b/old_crates/holoom_types/src/username.rs deleted file mode 100644 index e638c84..0000000 --- a/old_crates/holoom_types/src/username.rs +++ /dev/null @@ -1,22 +0,0 @@ -use hdi::prelude::*; -use serde::{Deserialize, Serialize}; -use ts_rs::TS; - -#[hdk_entry_helper] -#[derive(Clone, PartialEq, TS)] -#[ts(export)] -pub struct UsernameAttestation { - #[ts(type = "AgentPubKey")] - pub agent: AgentPubKey, - pub username: String, -} - -#[derive(Serialize, Deserialize, Debug, TS)] -#[ts(export)] -pub struct SignedUsername { - pub username: String, - #[ts(type = "Signature")] - pub signature: Signature, - #[ts(type = "AgentPubKey")] - pub signer: AgentPubKey, -} diff --git a/old_crates/holoom_types/src/wallet.rs b/old_crates/holoom_types/src/wallet.rs deleted file mode 100644 index 9495cb7..0000000 --- a/old_crates/holoom_types/src/wallet.rs +++ /dev/null @@ -1,36 +0,0 @@ -use hdi::prelude::*; -use serde::{Deserialize, Serialize}; -use ts_rs::TS; - -pub type EvmAddress = alloy_primitives::Address; -pub type EvmSignature = alloy_primitives::Signature; -pub type SolanaAddress = ed25519_dalek::VerifyingKey; -pub type SolanaSignature = ed25519_dalek::Signature; - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, TS)] -#[ts(export)] -pub enum ChainWalletSignature { - Evm { - #[ts(type = "Uint8Array")] - evm_address: EvmAddress, - #[ts(type = "[Uint8Array, Uint8Array, number]")] - evm_signature: EvmSignature, - }, - Solana { - #[ts(type = "Uint8Array")] - solana_address: Box, - #[ts(type = "number[]")] - solana_signature: SolanaSignature, - }, -} - -#[hdk_entry_helper] -#[derive(Clone, PartialEq, TS)] -#[ts(export)] -pub struct WalletAttestation { - #[ts(type = "AgentPubKey")] - pub agent: AgentPubKey, - pub chain_wallet_signature: ChainWalletSignature, - #[ts(type = "ActionHash")] - pub prev_action: ActionHash, -} diff --git a/old_crates/jaq_wrapper/Cargo.toml b/old_crates/jaq_wrapper/Cargo.toml deleted file mode 100644 index 09354de..0000000 --- a/old_crates/jaq_wrapper/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "jaq_wrapper" -version = "0.0.1" -edition = "2021" - -[lib] -crate-type = ["cdylib", "rlib"] -name = "jaq_wrapper" - -[dependencies] -hdi = { workspace = true } -jaq-interpret = { git = "https://github.com/8e8b2c/jaq", rev = "1870c7c" } -jaq-parse = { git = "https://github.com/8e8b2c/jaq", rev = "1870c7c" } -jaq-core = { git = "https://github.com/8e8b2c/jaq", rev = "1870c7c" } -jaq-std = { git = "https://github.com/8e8b2c/jaq", rev = "1870c7c" } -hifijson = "0.2.0" diff --git a/old_crates/jaq_wrapper/src/lib.rs b/old_crates/jaq_wrapper/src/lib.rs deleted file mode 100644 index 23a0e12..0000000 --- a/old_crates/jaq_wrapper/src/lib.rs +++ /dev/null @@ -1,147 +0,0 @@ -use hdi::prelude::*; -use jaq_interpret::{Ctx, Filter, FilterT, ParseCtx, RcIter}; -use std::io::{self, BufRead}; - -// Re-export Val -pub use jaq_interpret::Val; - -pub enum JqProgramInput { - Single(String), - Slurp(Vec), -} - -pub fn compile_and_run_jq(program_str: &str, input: JqProgramInput) -> ExternResult { - let filter = compile_filter(program_str)?; - let input = input.parse()?; - let output = run_filter(filter, input)?; - Ok(output.to_string()) -} - -impl JqProgramInput { - fn parse(self) -> ExternResult { - match self { - Self::Single(json) => parse_single_json(&json), - Self::Slurp(jsons) => { - let items = jsons - .into_iter() - .map(|json| parse_single_json(&json)) - .collect::>>()?; - Ok(Val::arr(items)) - } - } - } -} - -pub fn compile_filter(program_str: &str) -> ExternResult { - let (maybe_main, errs) = jaq_parse::parse(program_str, jaq_parse::main()); - - if !errs.is_empty() { - return Err(wasm_error!(format!( - "jq program compilation failed with {} error(s)", - errs.len() - ))); - } - let Some(main) = maybe_main else { - return Err(wasm_error!(String::from("no main filter"))); - }; - let mut defs = ParseCtx::new(vec![]); - defs.insert_natives(jaq_core::core()); - defs.insert_defs(jaq_std::std()); - let filter = defs.compile(main); - if !defs.errs.is_empty() { - return Err(wasm_error!(format!( - "jq program compilation failed with {} def error(s)", - defs.errs.len() - ))); - } - Ok(filter) -} - -pub fn run_filter(filter: Filter, input: Val) -> ExternResult { - // Seems jaq is designed to pipe errors forwards, whilst tracking a global reference - hence - // the iterator gubbins. - let vars = vec![]; - let inputs: Vec> = vec![Ok(input)]; - let iter = Box::new(inputs.into_iter()) as Box>; - let iter = RcIter::new(iter); - let ctx = Ctx::new(vars, &iter); - - // The above iterator dance makes it very hard for me to understand how to take just one item. - // As a workaround I use a for loop (which the compiler seems happy with) and then error if - // the loop repeats. - let mut looped_once = false; - let mut output: Option = None; - for input in &iter { - if looped_once { - return Err(wasm_error!(WasmErrorInner::Guest( - "Unexpected continued input".into() - ))); - } - let input = input.map_err(|err| { - wasm_error!(WasmErrorInner::Guest(format!( - "Error in jq program input: {}", - err - ))) - })?; - let mut outputs = filter - .run((ctx.clone(), input)) - .collect::, _>>() - .map_err(|err| { - wasm_error!(WasmErrorInner::Guest(format!( - "jq execution error: {}", - err - ))) - })?; - if outputs.len() > 1 { - return Err(wasm_error!(WasmErrorInner::Guest( - "Unexpected multiple outputs to jq program".into() - ))); - } - if let Some(val) = outputs.pop() { - output = Some(val); - } - looped_once = true; - } - output.ok_or(wasm_error!(WasmErrorInner::Guest( - "jq program produced no output".into() - ))) -} - -pub fn parse_single_json(json: &str) -> ExternResult { - let mut iter = json_read(json.as_bytes()); - let val = iter - .next() - .ok_or(wasm_error!(WasmErrorInner::Guest("No input parsed".into())))? - .map_err(|err| { - wasm_error!(WasmErrorInner::Guest(format!( - "Input parse failed: {}", - err - ))) - })?; - if iter.next().is_some() { - return Err(wasm_error!(WasmErrorInner::Guest( - "Unexpected continuation of input".into() - ))); - } - Ok(val) -} - -fn json_read<'a>(read: impl BufRead + 'a) -> impl Iterator> + 'a { - let mut lexer = hifijson::IterLexer::new(read.bytes()); - core::iter::from_fn(move || { - use hifijson::token::Lex; - let v = Val::parse(lexer.ws_token()?, &mut lexer); - Some(v.map_err(|e| core::mem::take(&mut lexer.error).unwrap_or_else(|| invalid_data(e)))) - }) -} - -fn invalid_data(e: impl std::error::Error + Send + Sync + 'static) -> std::io::Error { - io::Error::new(io::ErrorKind::InvalidData, e) -} - -// Regression test for https://github.com/holochain-open-dev/holoom/issues/59 -#[test] -fn no_undefined_vars() { - let result = compile_filter("$missing"); - assert!(result.is_err()) -} diff --git a/old_crates/ping_coordinator/Cargo.toml b/old_crates/ping_coordinator/Cargo.toml deleted file mode 100644 index 372cf84..0000000 --- a/old_crates/ping_coordinator/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "ping_coordinator" -version = "0.0.1" -edition = "2021" - -[lib] -crate-type = ["cdylib", "rlib"] -name = "ping_coordinator" - -[dependencies] -hdk = { workspace = true } -serde = { workspace = true } diff --git a/old_crates/records_coordinator/Cargo.toml b/old_crates/records_coordinator/Cargo.toml deleted file mode 100644 index d650c9a..0000000 --- a/old_crates/records_coordinator/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "records_coordinator" -version = "0.0.1" -edition = "2021" - -[lib] -crate-type = ["cdylib", "rlib"] -name = "records_coordinator" - -[dependencies] -hdk = { workspace = true } -serde = { workspace = true } diff --git a/old_crates/signer_coordinator/Cargo.toml b/old_crates/signer_coordinator/Cargo.toml deleted file mode 100644 index 7e30a6e..0000000 --- a/old_crates/signer_coordinator/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "signer_coordinator" -version = "0.0.1" -edition = "2021" - -[lib] -crate-type = ["cdylib", "rlib"] -name = "signer_coordinator" - -[dependencies] -hdk = { workspace = true } -serde = { workspace = true } -holoom_types = { workspace = true } diff --git a/old_crates/signer_coordinator/src/lib.rs b/old_crates/signer_coordinator/src/lib.rs deleted file mode 100644 index ef18f8e..0000000 --- a/old_crates/signer_coordinator/src/lib.rs +++ /dev/null @@ -1,8 +0,0 @@ -use hdk::prelude::*; -use holoom_types::SignableBytes; - -/// Sign secret message with agent key as transferable proof that user owns this account -#[hdk_extern] -pub fn sign_message(message: SignableBytes) -> ExternResult { - sign(agent_info()?.agent_initial_pubkey, message) -} diff --git a/old_crates/username_registry_coordinator/Cargo.toml b/old_crates/username_registry_coordinator/Cargo.toml deleted file mode 100644 index 4bcfb8c..0000000 --- a/old_crates/username_registry_coordinator/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "username_registry_coordinator" -version = "0.0.1" -edition = "2021" - -[lib] -crate-type = ["cdylib", "rlib"] -name = "username_registry_coordinator" - -[dependencies] -serde = { workspace = true } -hdk = { workspace = true } -bincode = { workspace = true } -username_registry_integrity = { workspace = true } -holoom_types = { workspace = true } -username_registry_validation = { workspace = true } -username_registry_utils = { workspace = true } -jaq_wrapper = { workspace = true } -indexmap = "2.2.6" -serde_json = { workspace = true } -hex = { workspace = true } diff --git a/old_crates/username_registry_coordinator/src/external_id_attestation.rs b/old_crates/username_registry_coordinator/src/external_id_attestation.rs deleted file mode 100644 index e05072a..0000000 --- a/old_crates/username_registry_coordinator/src/external_id_attestation.rs +++ /dev/null @@ -1,200 +0,0 @@ -use hdk::prelude::*; -use holoom_types::{ - ConfirmExternalIdRequestPayload, ExternalIdAttestation, - IngestExternalIdAttestationRequestPayload, LocalHoloomSignal, RejectExternalIdRequestPayload, - RemoteHoloomSignal, SendExternalIdAttestationRequestPayload, -}; -use username_registry_integrity::{EntryTypes, LinkTypes, UnitEntryTypes}; -use username_registry_utils::{get_authority_agent, hash_identifier}; - -#[hdk_extern] -pub fn send_external_id_attestation_request( - payload: SendExternalIdAttestationRequestPayload, -) -> ExternResult<()> { - let payload = IngestExternalIdAttestationRequestPayload { - request_id: payload.request_id, - code_verifier: payload.code_verifier, - code: payload.code, - }; - - let authority_agent = get_authority_agent()?; - - let zome_name = zome_info()?.name; - let fn_name = FunctionName::from("ingest_external_id_attestation_request"); - let resp = call_remote(authority_agent, zome_name, fn_name, None, payload)?; - match resp { - ZomeCallResponse::Ok(result) => result.decode().map_err(|err| wasm_error!(err)), - ZomeCallResponse::NetworkError(err) => Err(wasm_error!(WasmErrorInner::Guest(format!( - "There was a network error: {:?}", - err - )))), - ZomeCallResponse::Unauthorized(..) => { - Err(wasm_error!(WasmErrorInner::Guest("Unauthorized".into()))) - } - ZomeCallResponse::CountersigningSession(_) => Err(wasm_error!(WasmErrorInner::Guest( - "Unexpected countersigning session".into() - ))), - } -} - -/// Remote called by user seeking attestation -/// -/// Whether or not the request is successful is messaged via a callback -#[hdk_extern] -pub fn ingest_external_id_attestation_request( - payload: IngestExternalIdAttestationRequestPayload, -) -> ExternResult<()> { - let signal = LocalHoloomSignal::ExternalIdAttestationRequested { - request_id: payload.request_id, - requestor_pubkey: call_info()?.provenance, - code_verifier: payload.code_verifier, - code: payload.code, - }; - emit_signal(signal)?; - Ok(()) -} - - -//authority confirms the users request -#[hdk_extern] -pub fn confirm_external_id_request( - payload: ConfirmExternalIdRequestPayload, -) -> ExternResult { - let attestation = ExternalIdAttestation { - request_id: payload.request_id.clone(), - internal_pubkey: payload.requestor.clone(), - external_id: payload.external_id, - display_name: payload.display_name, - }; - let result = create_external_id_attestation(attestation); - let signal = match &result { - Ok(record) => RemoteHoloomSignal::ExternalIdAttested { - request_id: payload.request_id, - record: record.clone(), - }, - Err(err) => RemoteHoloomSignal::ExternalIdRejected { - request_id: payload.request_id, - reason: err.to_string(), - }, - }; - let signal_encoded = ExternIO::encode(signal) - .map_err(|err: SerializedBytesError| wasm_error!(WasmErrorInner::Serialize(err)))?; - let recipients = vec![payload.requestor]; - send_remote_signal(signal_encoded, recipients)?; - - result -} - -#[hdk_extern] -pub fn reject_external_id_request(payload: RejectExternalIdRequestPayload) -> ExternResult<()> { - let signal = RemoteHoloomSignal::ExternalIdRejected { - request_id: payload.request_id, - reason: payload.reason, - }; - let signal_encoded = ExternIO::encode(signal) - .map_err(|err: SerializedBytesError| wasm_error!(WasmErrorInner::Serialize(err)))?; - let recipients = vec![payload.requestor]; - send_remote_signal(signal_encoded, recipients)?; - - Ok(()) -} - -#[hdk_extern] -pub fn create_external_id_attestation(attestation: ExternalIdAttestation) -> ExternResult { - let agent = attestation.internal_pubkey.clone(); - let external_id_hash = hash_identifier(attestation.external_id.clone())?; - let attestation_action_hash = create_entry(EntryTypes::ExternalIdAttestation(attestation))?; - create_link( - agent, - attestation_action_hash.clone(), - LinkTypes::AgentToExternalIdAttestation, - (), - )?; - create_link( - external_id_hash, - attestation_action_hash.clone(), - LinkTypes::ExternalIdToAttestation, - (), - )?; - let record = get(attestation_action_hash, GetOptions::network())?.ok_or(wasm_error!( - WasmErrorInner::Guest(String::from( - "Could not find the newly created ExternalIdAttestation" - )) - ))?; - - Ok(record) -} - -#[hdk_extern] -pub fn get_external_id_attestation(external_id_ah: ActionHash) -> ExternResult> { - get(external_id_ah, GetOptions::network()) -} - -#[hdk_extern] -pub fn get_external_id_attestations_for_agent( - agent_pubkey: AgentPubKey, -) -> ExternResult> { - let mut links = get_links( - GetLinksInputBuilder::try_new(agent_pubkey, LinkTypes::AgentToExternalIdAttestation)? - .build(), - )?; - links.sort_by_key(|link| link.timestamp); - let maybe_records = links - .into_iter() - .map(|link| { - let action_hash = ActionHash::try_from(link.target).map_err(|_| { - wasm_error!(WasmErrorInner::Guest( - "ExternalIdToAttestation link doesn't point at action".into() - )) - })?; - get(action_hash, GetOptions::network()) - }) - .collect::>>()?; - Ok(maybe_records.into_iter().flatten().collect()) -} - - -#[hdk_extern] -pub fn get_attestation_for_external_id(external_id: String) -> ExternResult> { - let base = hash_identifier(external_id)?; - let mut links = get_links( - GetLinksInputBuilder::try_new(base, LinkTypes::ExternalIdToAttestation)?.build(), - )?; - links.sort_by_key(|link| link.timestamp); - let Some(link) = links.pop() else { - return Ok(None); - }; - let action_hash = ActionHash::try_from(link.target).map_err(|_| { - wasm_error!(WasmErrorInner::Guest( - "ExternalIdToAttestation link doesn't point at action".into() - )) - })?; - get(action_hash, GetOptions::network()) -} - -#[hdk_extern] -pub fn get_all_external_id_ahs(_: ()) -> ExternResult> { - if agent_info()?.agent_initial_pubkey != get_authority_agent()? { - return Err(wasm_error!(WasmErrorInner::Guest( - "Only callable by authority agent".into() - ))); - } - let entry_type: EntryType = UnitEntryTypes::ExternalIdAttestation - .try_into() - .expect("ExternalIdAttestation is an entry type"); - let filter = ChainQueryFilter::default() - .entry_type(entry_type) - .include_entries(false); - let ahs = query(filter)? - .into_iter() - .map(|record| record.action_address().to_owned()) - .collect(); - Ok(ahs) -} - -#[hdk_extern] -pub fn delete_external_id_attestation( - original_attestation_hash: ActionHash, -) -> ExternResult { - delete_entry(original_attestation_hash) -} diff --git a/old_crates/username_registry_coordinator/src/oracle_document.rs b/old_crates/username_registry_coordinator/src/oracle_document.rs deleted file mode 100644 index 343da96..0000000 --- a/old_crates/username_registry_coordinator/src/oracle_document.rs +++ /dev/null @@ -1,126 +0,0 @@ -use hdk::prelude::*; -use holoom_types::{DocumentRelationTag, OracleDocument}; -use username_registry_integrity::{EntryTypes, LinkTypes}; -use username_registry_utils::hash_identifier; - -#[hdk_extern] -pub fn create_oracle_document(oracle_document: OracleDocument) -> ExternResult { - let base_address = hash_identifier(oracle_document.name.clone())?; - let link_tag = oracle_document.name.as_bytes().to_vec(); - let oracle_document_ah = create_entry(EntryTypes::OracleDocument(oracle_document))?; - create_link( - base_address, - oracle_document_ah.clone(), - LinkTypes::NameToOracleDocument, - link_tag, - )?; - let record = get(oracle_document_ah, GetOptions::network())?.ok_or(wasm_error!( - WasmErrorInner::Guest(String::from( - "Could not find the newly created OracleDocument" - )) - ))?; - - Ok(record) -} -pub fn get_latest_oracle_document_ah_for_name( - name: String, - trusted_authors: &[AgentPubKey], -) -> ExternResult> { - let base_address = hash_identifier(name)?; - let mut links = get_links( - GetLinksInputBuilder::try_new(base_address, LinkTypes::NameToOracleDocument)?.build(), - )?; - links.sort_by_key(|link| link.timestamp); - let Some(link) = links - .into_iter() - .filter(|link| trusted_authors.contains(&link.author)) - .last() - else { - return Ok(None); - }; - let action_hash = ActionHash::try_from(link.target).map_err(|_| { - wasm_error!(WasmErrorInner::Guest( - "Link target isn't an ActionHash".into() - )) - })?; - Ok(Some(action_hash)) -} - -#[hdk_extern] -pub fn get_oracle_document_link_ahs_for_name(name: String) -> ExternResult> { - let base_address = hash_identifier(name)?; - let mut links = get_links( - GetLinksInputBuilder::try_new(base_address, LinkTypes::NameToOracleDocument)?.build(), - )?; - links.sort_by_key(|link| link.timestamp); - let action_hashes = links - .into_iter() - .filter_map(|link| ActionHash::try_from(link.create_link_hash).ok()) - .collect(); - Ok(action_hashes) -} - -pub fn get_latest_oracle_document_for_name( - name: String, - trusted_authors: &[AgentPubKey], -) -> ExternResult> { - let Some(action_hash) = get_latest_oracle_document_ah_for_name(name, trusted_authors)? else { - return Ok(None); - }; - get(action_hash, GetOptions::network()) -} - -#[hdk_extern] -pub fn relate_oracle_document(relation_tag: DocumentRelationTag) -> ExternResult<()> { - let tag_bytes = - ExternIO::encode(&relation_tag).expect("Couldn't serialize DocumentRelationTag"); - - let base_address = hash_identifier(relation_tag.relation)?; - let target_address = hash_identifier(relation_tag.name.clone())?; - create_link( - base_address, - target_address, - LinkTypes::RelateOracleDocumentName, - tag_bytes.0, - )?; - - Ok(()) -} - -#[hdk_extern] -pub fn get_related_oracle_document_names(relation_name: String) -> ExternResult> { - // BTreeSet ensures order an no repeats - let identifiers: BTreeSet = get_links( - GetLinksInputBuilder::try_new( - hash_identifier(relation_name)?, - LinkTypes::RelateOracleDocumentName, - )? - .build(), - )? - .into_iter() - .map(|link| { - let document_relation: DocumentRelationTag = ExternIO(link.tag.into_inner()) - .decode() - .map_err(|_| wasm_error!(WasmErrorInner::Guest("LinkTag isn't utf8".into())))?; - Ok(document_relation.name) - }) - .collect::>()?; - Ok(identifiers.into_iter().collect()) -} - -#[hdk_extern] -pub fn get_relation_link_ahs(relation_name: String) -> ExternResult> { - let mut links = get_links( - GetLinksInputBuilder::try_new( - hash_identifier(relation_name)?, - LinkTypes::RelateOracleDocumentName, - )? - .build(), - )?; - links.sort_by_key(|link| link.timestamp); - let action_hashes = links - .into_iter() - .filter_map(|link| ActionHash::try_from(link.create_link_hash).ok()) - .collect(); - Ok(action_hashes) -} diff --git a/old_crates/username_registry_coordinator/src/recipe.rs b/old_crates/username_registry_coordinator/src/recipe.rs deleted file mode 100644 index f9b884d..0000000 --- a/old_crates/username_registry_coordinator/src/recipe.rs +++ /dev/null @@ -1,13 +0,0 @@ -use hdk::prelude::*; -use holoom_types::recipe::Recipe; -use username_registry_integrity::EntryTypes; - -#[hdk_extern] -pub fn create_recipe(recipe: Recipe) -> ExternResult { - let recipe_ah = create_entry(EntryTypes::Recipe(recipe))?; - let record = get(recipe_ah, GetOptions::network())?.ok_or(wasm_error!( - WasmErrorInner::Guest(String::from("Could not find the newly created Recipe")) - ))?; - - Ok(record) -} diff --git a/old_crates/username_registry_coordinator/src/recipe_execution.rs b/old_crates/username_registry_coordinator/src/recipe_execution.rs deleted file mode 100644 index b42e347..0000000 --- a/old_crates/username_registry_coordinator/src/recipe_execution.rs +++ /dev/null @@ -1,219 +0,0 @@ -use std::{collections::HashMap, rc::Rc}; - -use hdk::prelude::*; -use holoom_types::{recipe::*, ExternalIdAttestation, OracleDocument}; -use indexmap::IndexMap; -use jaq_wrapper::{compile_filter, parse_single_json, run_filter, Val}; -use username_registry_integrity::EntryTypes; -use username_registry_utils::deserialize_record_entry; - -use crate::{ - external_id_attestation::get_external_id_attestations_for_agent, - oracle_document::{ - get_latest_oracle_document_ah_for_name, get_latest_oracle_document_for_name, - }, -}; - -#[hdk_extern] -pub fn create_recipe_execution(recipe_execution: RecipeExecution) -> ExternResult { - let recipe_execution_ah = create_entry(EntryTypes::RecipeExecution(recipe_execution))?; - let record = get(recipe_execution_ah, GetOptions::network())?.ok_or(wasm_error!( - WasmErrorInner::Guest(String::from( - "Could not find the newly created RecipeExecution" - )) - ))?; - - Ok(record) -} - -#[hdk_extern] -pub fn execute_recipe(payload: ExecuteRecipePayload) -> ExternResult { - let recipe_record = get(payload.recipe_ah.clone(), GetOptions::network())?.ok_or( - wasm_error!(WasmErrorInner::Guest("Recipe not found".into())), - )?; - let recipe: Recipe = deserialize_record_entry(recipe_record)?; - - let mut vars: HashMap = HashMap::default(); - let mut instruction_executions: Vec = Vec::default(); - - if payload.arguments.len() != recipe.arguments.len() { - return Err(wasm_error!(WasmErrorInner::Guest( - "Incorrect number of arguments".into() - ))); - } - for (arg, (arg_name, arg_type)) in payload.arguments.iter().zip(recipe.arguments) { - let val = match (arg, arg_type) { - (RecipeArgument::String { value }, RecipeArgumentType::String) => { - Val::str(value.clone()) - } - (RecipeArgument::EvmAddress { value }, RecipeArgumentType::EvmAddress) => { - Val::str(value.to_string()) - } - _ => { - return Err(wasm_error!(WasmErrorInner::Guest( - "Bad recipe argument".into() - ))) - } - }; - vars.insert(arg_name, val); - } - - for (out_var_name, instruction) in recipe.instructions { - if vars.contains_key(&out_var_name) { - unreachable!("Bad impl: A valid Recipe doesn't reassign vars"); - } - let (val, instruction_execution) = match instruction { - RecipeInstruction::Constant { value } => { - let val = parse_single_json(&value)?; - (val, RecipeInstructionExecution::Constant) - } - RecipeInstruction::GetCallerAgentPublicKey => { - let val = Val::Str(Rc::new(agent_info()?.agent_initial_pubkey.to_string())); - (val, RecipeInstructionExecution::GetCallerAgentPublicKey) - } - RecipeInstruction::GetDocsListedByVar { var_name } => { - let list_val = vars - .get(&var_name) - .expect("Bad impl: A valid recipe doesn't use unassigned vars"); - let Val::Arr(item_vals) = list_val else { - return Err(wasm_error!(WasmErrorInner::Guest(format!( - "var '{}' expected to contain array", - &var_name - )))); - }; - let doc_ahs = item_vals - .iter() - .map(|val| { - let Val::Str(identifier) = val else { - return Err(wasm_error!(WasmErrorInner::Guest(format!( - "var '{}' expected to contain array of string elements", - &var_name - )))); - }; - get_latest_oracle_document_ah_for_name( - identifier.as_ref().clone(), - &recipe.trusted_authors, - )? - .ok_or(wasm_error!(WasmErrorInner::Guest( - format!("No OracleDocument for identifier '{}'", &identifier) - ))) - }) - .collect::>>()?; - let doc_vals = doc_ahs - .iter() - .map(|doc_ah| { - let doc_record = get(doc_ah.clone(), GetOptions::network())?.ok_or( - wasm_error!(WasmErrorInner::Guest("OracleDocument not found".into())), - )?; - let doc: OracleDocument = deserialize_record_entry(doc_record)?; - let val = parse_single_json(&doc.json_data)?; - Ok(val) - }) - .collect::>>()?; - let val = Val::arr(doc_vals); - let instruction_execution = - RecipeInstructionExecution::GetDocsListedByVar { doc_ahs }; - (val, instruction_execution) - } - RecipeInstruction::GetLatestCallerExternalId => { - let mut attestation_records = - get_external_id_attestations_for_agent(agent_info()?.agent_initial_pubkey)?; - let attestation_record = - attestation_records - .pop() - .ok_or(wasm_error!(WasmErrorInner::Guest( - "Agent has no External ID Attestations".into() - )))?; - let attestation_ah = attestation_record.action_address().clone(); - let attestation: ExternalIdAttestation = - deserialize_record_entry(attestation_record)?; - let val = Val::obj(IndexMap::from([ - ( - Rc::new(String::from("agent_pubkey")), - Val::str(attestation.internal_pubkey.to_string()), - ), - ( - Rc::new(String::from("external_id")), - Val::str(attestation.external_id), - ), - ( - Rc::new(String::from("display_name")), - Val::str(attestation.display_name), - ), - ])); - let instruction_execution = - RecipeInstructionExecution::GetLatestCallerExternalId { attestation_ah }; - (val, instruction_execution) - } - RecipeInstruction::GetLatestDocWithIdentifier { var_name } => { - let identifier_val = vars - .get(&var_name) - .expect("Bad impl: A valid recipe doesn't use unassigned vars"); - let Val::Str(identifier) = identifier_val else { - return Err(wasm_error!(WasmErrorInner::Guest(format!( - "var '{}' expected to contain string", - &var_name - )))); - }; - let doc_record = get_latest_oracle_document_for_name( - identifier.as_ref().clone(), - &recipe.trusted_authors, - )? - .ok_or(wasm_error!(WasmErrorInner::Guest(format!( - "No OracleDocument found for identifier '{}'", - identifier - ))))?; - let doc_ah = doc_record.action_address().clone(); - let doc: OracleDocument = deserialize_record_entry(doc_record)?; - let val = parse_single_json(&doc.json_data)?; - let instruction_execution = - RecipeInstructionExecution::GetLatestDocWithIdentifier { doc_ah }; - (val, instruction_execution) - } - RecipeInstruction::Jq { - input_var_names, - program, - } => { - let input_val = match input_var_names { - JqInstructionArgumentNames::Single { var_name } => vars - .get(&var_name) - .expect("Bad impl: A valid recipe doesn't use unassigned vars") - .clone(), - JqInstructionArgumentNames::List { var_names } => { - let map: IndexMap, Val> = var_names - .into_iter() - .map(|var_name| { - let val = vars - .get(&var_name) - .expect("Bad impl: A valid recipe doesn't use unassigned vars") - .clone(); - (Rc::new(var_name), val) - }) - .collect(); - Val::obj(map) - } - }; - let filter = compile_filter(&program)?; - let val = run_filter(filter, input_val)?; - let instruction_execution = RecipeInstructionExecution::Jq; - (val, instruction_execution) - } - }; - vars.insert(out_var_name, val); - instruction_executions.push(instruction_execution) - } - - let return_val = vars - .remove("$return") - .expect("Bad impl: A valid recipe has a $return"); - let output = return_val.to_string(); - - let recipe_execution = RecipeExecution { - recipe_ah: payload.recipe_ah, - arguments: payload.arguments, - instruction_executions, - output, - }; - - create_recipe_execution(recipe_execution) -} diff --git a/old_crates/username_registry_coordinator/src/user_metadata.rs b/old_crates/username_registry_coordinator/src/user_metadata.rs deleted file mode 100644 index e66e53d..0000000 --- a/old_crates/username_registry_coordinator/src/user_metadata.rs +++ /dev/null @@ -1,77 +0,0 @@ -use std::collections::HashMap; - -use hdk::prelude::*; -use holoom_types::{GetMetadataItemValuePayload, MetadataItem, UpdateMetadataItemPayload}; -use username_registry_integrity::*; - -#[hdk_extern] -pub fn update_metadata_item(payload: UpdateMetadataItemPayload) -> ExternResult<()> { - let links = get_links( - GetLinksInputBuilder::try_new(payload.agent_pubkey.clone(), LinkTypes::AgentMetadata)? - .build(), - )?; - for link in links { - let existing_item: MetadataItem = - bincode::deserialize(&link.tag.into_inner()).map_err(|_| { - wasm_error!(WasmErrorInner::Guest( - "Failed to deserialize MetadataItem".into() - )) - })?; - if existing_item.name == payload.name { - // Remove old MetadataItem - delete_link(link.create_link_hash)?; - } - } - let item = MetadataItem { - name: payload.name, - value: payload.value, - }; - let tag_bytes = bincode::serialize(&item).map_err(|_| { - wasm_error!(WasmErrorInner::Guest( - "Failed to serialize MetadataItem".into() - )) - })?; - create_link( - payload.agent_pubkey.clone(), - payload.agent_pubkey, // unused and irrelevant - LinkTypes::AgentMetadata, - LinkTag(tag_bytes), - )?; - Ok(()) -} - -#[hdk_extern] -pub fn get_metadata_item_value( - payload: GetMetadataItemValuePayload, -) -> ExternResult> { - let links = get_links( - GetLinksInputBuilder::try_new(payload.agent_pubkey, LinkTypes::AgentMetadata)?.build(), - )?; - for link in links { - let item: MetadataItem = bincode::deserialize(&link.tag.into_inner()).map_err(|_| { - wasm_error!(WasmErrorInner::Guest( - "Failed to deserialize MetadataItem".into() - )) - })?; - if payload.name == item.name { - return Ok(Some(item.value)); - } - } - Ok(None) -} - -#[hdk_extern] -pub fn get_metadata(agent_pubkey: AgentPubKey) -> ExternResult> { - let links = - get_links(GetLinksInputBuilder::try_new(agent_pubkey, LinkTypes::AgentMetadata)?.build())?; - let mut out = HashMap::default(); - for link in links { - let item: MetadataItem = bincode::deserialize(&link.tag.into_inner()).map_err(|_| { - wasm_error!(WasmErrorInner::Guest( - "Failed to deserialize MetadataItem".into() - )) - })?; - out.insert(item.name, item.value); - } - Ok(out) -} diff --git a/old_crates/username_registry_coordinator/src/username_attestation.rs b/old_crates/username_registry_coordinator/src/username_attestation.rs deleted file mode 100644 index 6e7740e..0000000 --- a/old_crates/username_registry_coordinator/src/username_attestation.rs +++ /dev/null @@ -1,128 +0,0 @@ -use hdk::prelude::*; -use holoom_types::{SignedUsername, UsernameAttestation}; -use username_registry_integrity::*; -use username_registry_utils::get_authority_agent; - -#[hdk_extern] -pub fn create_username_attestation( - username_attestation: UsernameAttestation, -) -> ExternResult { - let username_attestation_hash = create_entry(&EntryTypes::UsernameAttestation( - username_attestation.clone(), - ))?; - create_link( - username_attestation.agent.clone(), - username_attestation_hash.clone(), - LinkTypes::AgentToUsernameAttestations, - (), - )?; - let record = get(username_attestation_hash.clone(), GetOptions::network())?.ok_or( - wasm_error!(WasmErrorInner::Guest(String::from( - "Could not find the newly created UsernameAttestation" - ))), - )?; - Ok(record) -} -#[hdk_extern] -pub fn get_username_attestation( - username_attestation_hash: ActionHash, -) -> ExternResult> { - get(username_attestation_hash, GetOptions::network()) -} -#[hdk_extern] -pub fn delete_username_attestation( - original_username_attestation_hash: ActionHash, -) -> ExternResult { - delete_entry(original_username_attestation_hash) -} -#[hdk_extern] -pub fn get_username_attestation_for_agent(agent: AgentPubKey) -> ExternResult> { - let links = get_links( - GetLinksInputBuilder::try_new(agent, LinkTypes::AgentToUsernameAttestations)?.build(), - )?; - - match links.first() { - Some(l) => get( - ActionHash::try_from(l.clone().target).unwrap(), - GetOptions::network(), - ), - None => Ok(None), - } -} - -#[hdk_extern] -pub fn does_agent_have_username(agent: AgentPubKey) -> ExternResult { - let count = count_links(LinkQuery::new( - agent, - LinkTypes::AgentToUsernameAttestations.try_into_filter()?, - ))?; - - Ok(count > 0) -} - -#[hdk_extern] -pub fn get_all_username_attestations(_: ()) -> ExternResult> { - let my_pubkey = agent_info()?.agent_initial_pubkey; - if my_pubkey != get_authority_agent()? { - return Err(wasm_error!(WasmErrorInner::Host( - "Only callable by authority agent".into() - ))); - } - let username_attestation_type: EntryType = UnitEntryTypes::UsernameAttestation.try_into()?; - let filter = ChainQueryFilter::new() - .include_entries(true) - .entry_type(username_attestation_type); - query(filter) -} - -/// Called by the user who wishes to register a username. Returns a UsernameAttestation Record. -#[hdk_extern] -pub fn sign_username_to_attest(username: String) -> ExternResult { - // TODO: devise scheme akin to signing a nonce - let my_pubkey = agent_info()?.agent_initial_pubkey; - let signature = sign(my_pubkey.clone(), &username)?; - let payload = SignedUsername { - username, - signature, - signer: my_pubkey, - }; - - let authority_agent = get_authority_agent()?; - - let zome_name = zome_info()?.name; - let fn_name = FunctionName::from("ingest_signed_username"); - let resp = call_remote(authority_agent, zome_name, fn_name, None, payload)?; - match resp { - ZomeCallResponse::Ok(result) => result.decode().map_err(|err| wasm_error!(err)), - ZomeCallResponse::NetworkError(err) => Err(wasm_error!(WasmErrorInner::Guest(format!( - "There was a network error: {:?}", - err - )))), - ZomeCallResponse::Unauthorized(..) => { - Err(wasm_error!(WasmErrorInner::Guest("Unauthorized".into()))) - } - ZomeCallResponse::CountersigningSession(_) => Err(wasm_error!(WasmErrorInner::Guest( - "Unexpected countersigning session".into() - ))), - } -} - -/// Remotely invoked on the authority agent. Returns a UsernameAttestation Record. -#[hdk_extern] -pub fn ingest_signed_username(signed_username: SignedUsername) -> ExternResult { - let is_valid = verify_signature( - signed_username.signer.clone(), - signed_username.signature, - signed_username.username.clone(), - )?; - if !is_valid { - return Err(wasm_error!(WasmErrorInner::Host( - "Invalid username signature".into() - ))); - } - let username_attestation = UsernameAttestation { - username: signed_username.username, - agent: signed_username.signer, - }; - create_username_attestation(username_attestation) -} diff --git a/old_crates/username_registry_coordinator/src/wallet_attestation.rs b/old_crates/username_registry_coordinator/src/wallet_attestation.rs deleted file mode 100644 index 1d14d7f..0000000 --- a/old_crates/username_registry_coordinator/src/wallet_attestation.rs +++ /dev/null @@ -1,75 +0,0 @@ -use hdk::prelude::*; -use holoom_types::{ChainWalletSignature, EvmAddress, SolanaAddress, WalletAttestation}; -use username_registry_integrity::*; -use username_registry_validation::{evm_signing_message, solana_signing_message}; - -#[hdk_extern] -pub fn get_evm_wallet_binding_message(evm_address: EvmAddress) -> ExternResult { - let info = agent_info()?; - let message = evm_signing_message(&evm_address, info.agent_initial_pubkey, info.chain_head.0); - Ok(message) -} - -#[hdk_extern] -pub fn get_solana_wallet_binding_message(solana_address: SolanaAddress) -> ExternResult { - let info = agent_info()?; - let message = solana_signing_message( - &solana_address, - info.agent_initial_pubkey, - info.chain_head.0, - ); - Ok(message) -} - -#[hdk_extern] -pub fn attest_wallet_signature( - chain_wallet_signature: ChainWalletSignature, -) -> ExternResult { - let wallet_attestation = WalletAttestation { - agent: agent_info()?.agent_initial_pubkey, - chain_wallet_signature, - prev_action: agent_info()?.chain_head.0, - }; - create_wallet_attestation(wallet_attestation) -} - -#[hdk_extern] -pub fn create_wallet_attestation(wallet_attestation: WalletAttestation) -> ExternResult { - let wallet_attestation_hash = - create_entry(&EntryTypes::WalletAttestation(wallet_attestation.clone()))?; - create_link( - wallet_attestation.agent.clone(), - wallet_attestation_hash.clone(), - LinkTypes::AgentToWalletAttestations, - (), - )?; - let record = get(wallet_attestation_hash.clone(), GetOptions::network())?.ok_or( - wasm_error!(WasmErrorInner::Guest(String::from( - "Could not find the newly created WalletAttestation" - ))), - )?; - Ok(record) -} - -#[hdk_extern] -pub fn get_wallet_attestation(wallet_attestation_hash: ActionHash) -> ExternResult> { - get(wallet_attestation_hash, GetOptions::network()) -} - -#[hdk_extern] -pub fn get_wallet_attestations_for_agent(agent: AgentPubKey) -> ExternResult> { - get_links(GetLinksInputBuilder::try_new(agent, LinkTypes::AgentToWalletAttestations)?.build())? - .into_iter() - .map(|l| { - let record = get( - ActionHash::try_from(l.clone().target).unwrap(), - GetOptions::network(), - )?; - record.ok_or_else(|| { - wasm_error!(WasmErrorInner::Guest( - "Broken Wallet Attestation link".into() - )) - }) - }) - .collect::>>() -} diff --git a/old_crates/username_registry_integrity/src/entry_types.rs b/old_crates/username_registry_integrity/src/entry_types.rs deleted file mode 100644 index f63e87b..0000000 --- a/old_crates/username_registry_integrity/src/entry_types.rs +++ /dev/null @@ -1,63 +0,0 @@ -use hdi::prelude::*; -use holoom_types::{ - evm_signing_offer::SignedEvmSigningOffer, - recipe::{Recipe, RecipeExecution}, - ExternalIdAttestation, OracleDocument, UsernameAttestation, WalletAttestation, -}; -use username_registry_validation::*; - -#[derive(Serialize, Deserialize)] -#[serde(tag = "type")] -#[hdk_entry_types] -#[unit_enum(UnitEntryTypes)] -pub enum EntryTypes { - UsernameAttestation(UsernameAttestation), - WalletAttestation(WalletAttestation), - ExternalIdAttestation(ExternalIdAttestation), - OracleDocument(OracleDocument), - Recipe(Recipe), - RecipeExecution(RecipeExecution), - SignedEvmSigningOffer(SignedEvmSigningOffer), -} - -impl EntryTypes { - pub fn validate_create(self, action: Create) -> ExternResult { - match self { - EntryTypes::UsernameAttestation(username_attestation) => { - validate_create_username_attestation( - EntryCreationAction::Create(action), - username_attestation, - ) - } - EntryTypes::WalletAttestation(wallet_attestation) => { - validate_create_wallet_attestation( - EntryCreationAction::Create(action), - wallet_attestation, - ) - } - EntryTypes::ExternalIdAttestation(external_id_attestation) => { - validate_create_external_id_attestation( - EntryCreationAction::Create(action), - external_id_attestation, - ) - } - EntryTypes::OracleDocument(oracle_document) => validate_create_oracle_document( - EntryCreationAction::Create(action), - oracle_document, - ), - EntryTypes::Recipe(recipe) => { - validate_create_recipe(EntryCreationAction::Create(action), recipe) - } - EntryTypes::RecipeExecution(recipe_execution) => validate_create_recipe_execution( - EntryCreationAction::Create(action), - recipe_execution, - ), - EntryTypes::SignedEvmSigningOffer(evm_signing_offer) => { - validate_create_signed_evm_signing_offer( - EntryCreationAction::Create(action), - evm_signing_offer, - ) - } - } - } -} diff --git a/old_crates/username_registry_integrity/src/link_types.rs b/old_crates/username_registry_integrity/src/link_types.rs deleted file mode 100644 index efe895f..0000000 --- a/old_crates/username_registry_integrity/src/link_types.rs +++ /dev/null @@ -1,187 +0,0 @@ -use hdi::prelude::*; -use username_registry_validation::*; - -#[derive(Serialize, Deserialize)] -#[hdk_link_types] -pub enum LinkTypes { - AgentToUsernameAttestations, - AgentMetadata, - AgentToWalletAttestations, - AgentToExternalIdAttestation, - ExternalIdToAttestation, - NameToOracleDocument, - RelateOracleDocumentName, - NameToRecipe, - NameToSigningOffer, - EvmAddressToSigningOffer, -} - -impl LinkTypes { - pub fn validate_create( - self, - action: CreateLink, - base_address: AnyLinkableHash, - target_address: AnyLinkableHash, - tag: LinkTag, - ) -> ExternResult { - match self { - LinkTypes::AgentToUsernameAttestations => { - validate_create_link_agent_to_username_attestations( - action, - base_address, - target_address, - tag, - ) - } - LinkTypes::AgentMetadata => { - validate_create_link_user_metadata(action, base_address, target_address, tag) - } - LinkTypes::AgentToWalletAttestations => { - validate_create_link_agent_to_wallet_attestations( - action, - base_address, - target_address, - tag, - ) - } - LinkTypes::AgentToExternalIdAttestation => { - validate_create_link_agent_to_external_id_attestations( - action, - base_address, - target_address, - tag, - ) - } - LinkTypes::ExternalIdToAttestation => validate_create_link_external_id_to_attestation( - action, - base_address, - target_address, - tag, - ), - LinkTypes::NameToOracleDocument => validate_create_link_name_to_oracle_document( - action, - base_address, - target_address, - tag, - ), - LinkTypes::RelateOracleDocumentName => { - validate_create_link_relate_oracle_document_name( - action, - base_address, - target_address, - tag, - ) - } - LinkTypes::NameToRecipe => { - validate_create_link_name_to_recipe(action, base_address, target_address, tag) - } - LinkTypes::NameToSigningOffer => validate_create_link_name_to_evm_signing_offer( - action, - base_address, - target_address, - tag, - ), - LinkTypes::EvmAddressToSigningOffer => { - validate_create_link_evm_address_to_signing_offer( - action, - base_address, - target_address, - tag, - ) - } - } - } - - pub fn validate_delete( - self, - action: DeleteLink, - original_action: CreateLink, - base_address: AnyLinkableHash, - target_address: AnyLinkableHash, - tag: LinkTag, - ) -> ExternResult { - match self { - LinkTypes::AgentToUsernameAttestations => { - validate_delete_link_agent_to_username_attestations( - action, - original_action, - base_address, - target_address, - tag, - ) - } - LinkTypes::AgentMetadata => validate_delete_link_user_metadata( - action, - original_action, - base_address, - target_address, - tag, - ), - LinkTypes::AgentToWalletAttestations => { - validate_delete_link_agent_to_wallet_attestations( - action, - original_action, - base_address, - target_address, - tag, - ) - } - LinkTypes::AgentToExternalIdAttestation => { - validate_delete_link_agent_to_external_id_attestations( - action, - original_action, - base_address, - target_address, - tag, - ) - } - LinkTypes::ExternalIdToAttestation => validate_delete_link_external_id_to_attestation( - action, - original_action, - base_address, - target_address, - tag, - ), - LinkTypes::NameToOracleDocument => validate_delete_link_name_to_oracle_document( - action, - original_action, - base_address, - target_address, - tag, - ), - LinkTypes::RelateOracleDocumentName => { - validate_delete_link_relate_oracle_document_name( - action, - original_action, - base_address, - target_address, - tag, - ) - } - - LinkTypes::NameToRecipe => validate_delete_link_name_to_recipe( - action, - original_action, - base_address, - target_address, - tag, - ), - LinkTypes::NameToSigningOffer => validate_delete_link_name_to_evm_signing_offer( - action, - original_action, - base_address, - target_address, - tag, - ), - LinkTypes::EvmAddressToSigningOffer => { - validate_delete_link_evm_address_to_signing_offer( - action, - original_action, - base_address, - target_address, - tag, - ) - } - } - } -} diff --git a/old_crates/username_registry_utils/Cargo.toml b/old_crates/username_registry_utils/Cargo.toml deleted file mode 100644 index 756ca7a..0000000 --- a/old_crates/username_registry_utils/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "username_registry_utils" -version = "0.0.1" -edition = "2021" - -[lib] -crate-type = ["cdylib", "rlib"] -name = "username_registry_utils" - -[dependencies] -hdi = { workspace = true } -holo_hash = { workspace = true } -serde = { workspace = true } -bincode = { workspace = true } -holoom_types = { workspace = true } -ed25519-dalek = { workspace = true } -bs58 = { workspace = true } -jaq_wrapper = { workspace = true } diff --git a/old_crates/username_registry_utils/src/lib.rs b/old_crates/username_registry_utils/src/lib.rs deleted file mode 100644 index 764a3ea..0000000 --- a/old_crates/username_registry_utils/src/lib.rs +++ /dev/null @@ -1,43 +0,0 @@ -use hdi::prelude::*; -use holoom_types::{EvmAddress, HoloomDnaProperties}; - -pub fn deserialize_record_entry(record: Record) -> ExternResult -where - O: TryFrom, -{ - let entry: O = record - .entry() - .to_app_option() - .map_err(|e| wasm_error!(e))? - .ok_or(wasm_error!(WasmErrorInner::Guest( - "Entry not present in Record".into() - )))?; - Ok(entry) -} - -pub fn hash_identifier(identifier: String) -> ExternResult { - #[derive(SerializedBytes, Serialize, Debug, Deserialize)] - struct SerializableIdentifier(String); - - let bytes = SerializedBytes::try_from(SerializableIdentifier(identifier)) - .map_err(|err| wasm_error!(err))?; - hash_entry(Entry::App(AppEntryBytes(bytes))) -} - -pub fn hash_evm_address(evm_address: EvmAddress) -> ExternResult { - #[derive(SerializedBytes, Serialize, Debug, Deserialize)] - struct SerializableEvmAddress(EvmAddress); - - let bytes = SerializedBytes::try_from(SerializableEvmAddress(evm_address)) - .map_err(|err| wasm_error!(err))?; - hash_entry(Entry::App(AppEntryBytes(bytes))) -} - -pub fn get_authority_agent() -> ExternResult { - let dna_props = HoloomDnaProperties::try_from_dna_properties()?; - AgentPubKey::try_from(dna_props.authority_agent).map_err(|_| { - wasm_error!(WasmErrorInner::Guest( - "Failed to deserialize AgentPubKey from dna properties".into() - )) - }) -} diff --git a/old_crates/username_registry_validation/Cargo.toml b/old_crates/username_registry_validation/Cargo.toml deleted file mode 100644 index 87c0252..0000000 --- a/old_crates/username_registry_validation/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "username_registry_validation" -version = "0.0.1" -edition = "2021" - -[lib] -crate-type = ["cdylib", "rlib"] -name = "username_registry_validation" - -[dependencies] -hdi = { workspace = true } -holo_hash = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } -bincode = { workspace = true } -holoom_types = { workspace = true } -ed25519-dalek = { workspace = true } -bs58 = { workspace = true } -jaq_wrapper = { workspace = true } -username_registry_utils = { workspace = true } -indexmap = "2.2.6" diff --git a/old_crates/username_registry_validation/src/agent_external_id_attestation.rs b/old_crates/username_registry_validation/src/agent_external_id_attestation.rs deleted file mode 100644 index 8e23cbc..0000000 --- a/old_crates/username_registry_validation/src/agent_external_id_attestation.rs +++ /dev/null @@ -1,42 +0,0 @@ -use hdi::prelude::*; -use holoom_types::ExternalIdAttestation; -use username_registry_utils::get_authority_agent; - -pub fn validate_create_link_agent_to_external_id_attestations( - action: CreateLink, - _base_address: AnyLinkableHash, - target_address: AnyLinkableHash, - _tag: LinkTag, -) -> ExternResult { - // Only the authority can create link - let authority_agent = get_authority_agent()?; - if action.author != authority_agent { - return Ok(ValidateCallbackResult::Invalid( - "Only the Username Registry Authority can create external ID attestation links".into(), - )); - } - - // Check the entry type for the given action hash - let action_hash = ActionHash::try_from(target_address).map_err(|e| wasm_error!(e))?; - let record = must_get_valid_record(action_hash)?; - let _external_id_attestation: ExternalIdAttestation = record - .entry() - .to_app_option() - .map_err(|e| wasm_error!(e))? - .ok_or(wasm_error!(WasmErrorInner::Guest(String::from( - "Linked action must reference an entry" - ))))?; - - Ok(ValidateCallbackResult::Valid) -} -pub fn validate_delete_link_agent_to_external_id_attestations( - _action: DeleteLink, - _original_action: CreateLink, - _base: AnyLinkableHash, - _target: AnyLinkableHash, - _tag: LinkTag, -) -> ExternResult { - Ok(ValidateCallbackResult::Invalid(String::from( - "External ID Attestation links cannot be deleted", - ))) -} diff --git a/old_crates/username_registry_validation/src/agent_username_attestation.rs b/old_crates/username_registry_validation/src/agent_username_attestation.rs deleted file mode 100644 index 9d023a1..0000000 --- a/old_crates/username_registry_validation/src/agent_username_attestation.rs +++ /dev/null @@ -1,42 +0,0 @@ -use hdi::prelude::*; -use holoom_types::UsernameAttestation; -use username_registry_utils::get_authority_agent; - -pub fn validate_create_link_agent_to_username_attestations( - action: CreateLink, - _base_address: AnyLinkableHash, - target_address: AnyLinkableHash, - _tag: LinkTag, -) -> ExternResult { - // Only the authority can create link - let authority_agent = get_authority_agent()?; - if action.author != authority_agent { - return Ok(ValidateCallbackResult::Invalid( - "Only the Username Registry Authority can create attestation links".into(), - )); - } - - // Check the entry type for the given action hash - let action_hash = ActionHash::try_from(target_address).map_err(|e| wasm_error!(e))?; - let record = must_get_valid_record(action_hash)?; - let _username_attestation: UsernameAttestation = record - .entry() - .to_app_option() - .map_err(|e| wasm_error!(e))? - .ok_or(wasm_error!(WasmErrorInner::Guest(String::from( - "Linked action must reference an entry" - ))))?; - - Ok(ValidateCallbackResult::Valid) -} -pub fn validate_delete_link_agent_to_username_attestations( - _action: DeleteLink, - _original_action: CreateLink, - _base: AnyLinkableHash, - _target: AnyLinkableHash, - _tag: LinkTag, -) -> ExternResult { - Ok(ValidateCallbackResult::Invalid(String::from( - "Username Attestation links cannot be deleted", - ))) -} diff --git a/old_crates/username_registry_validation/src/agent_wallet_attestation.rs b/old_crates/username_registry_validation/src/agent_wallet_attestation.rs deleted file mode 100644 index 6c506ec..0000000 --- a/old_crates/username_registry_validation/src/agent_wallet_attestation.rs +++ /dev/null @@ -1,52 +0,0 @@ -use hdi::prelude::*; -use holoom_types::WalletAttestation; - -pub fn validate_create_link_agent_to_wallet_attestations( - action: CreateLink, - base_address: AnyLinkableHash, - target_address: AnyLinkableHash, - _tag: LinkTag, -) -> ExternResult { - // Check the entry type for the given action hash - let action_hash = ActionHash::try_from(target_address).map_err(|e| wasm_error!(e))?; - let record = must_get_valid_record(action_hash)?; - let wallet_attestation: WalletAttestation = record - .entry() - .to_app_option() - .map_err(|e| wasm_error!(e))? - .ok_or(wasm_error!(WasmErrorInner::Guest(String::from( - "Linked action must reference an entry" - ))))?; - - if action.author != wallet_attestation.agent { - return Ok(ValidateCallbackResult::Invalid( - "Only the owner can create wallet attestation links".into(), - )); - } - let base_address_agent = match AgentPubKey::try_from(base_address) { - Ok(agent) => agent, - Err(_) => { - return Ok(ValidateCallbackResult::Invalid( - "Base address must be an agent".into(), - )); - } - }; - if wallet_attestation.agent != base_address_agent { - return Ok(ValidateCallbackResult::Invalid( - "Link must be from agent in attestation".into(), - )); - } - - Ok(ValidateCallbackResult::Valid) -} -pub fn validate_delete_link_agent_to_wallet_attestations( - _action: DeleteLink, - _original_action: CreateLink, - _base: AnyLinkableHash, - _target: AnyLinkableHash, - _tag: LinkTag, -) -> ExternResult { - Ok(ValidateCallbackResult::Invalid(String::from( - "Wallet Attestation links cannot be deleted", - ))) -} diff --git a/old_crates/username_registry_validation/src/external_id_attestation.rs b/old_crates/username_registry_validation/src/external_id_attestation.rs deleted file mode 100644 index 73bd571..0000000 --- a/old_crates/username_registry_validation/src/external_id_attestation.rs +++ /dev/null @@ -1,18 +0,0 @@ -use hdi::prelude::*; -use holoom_types::ExternalIdAttestation; -use username_registry_utils::get_authority_agent; - -pub fn validate_create_external_id_attestation( - action: EntryCreationAction, - _external_id_attestation: ExternalIdAttestation, -) -> ExternResult { - // Only the authority can publish - let authority_agent = get_authority_agent()?; - if action.author() != &authority_agent { - return Ok(ValidateCallbackResult::Invalid( - "Only the Username Registry Authority can create external ID attestations".into(), - )); - } - - Ok(ValidateCallbackResult::Valid) -} diff --git a/old_crates/username_registry_validation/src/external_id_to_attestation.rs b/old_crates/username_registry_validation/src/external_id_to_attestation.rs deleted file mode 100644 index d9f20e3..0000000 --- a/old_crates/username_registry_validation/src/external_id_to_attestation.rs +++ /dev/null @@ -1,49 +0,0 @@ -use hdi::prelude::*; -use holoom_types::ExternalIdAttestation; -use username_registry_utils::{get_authority_agent, hash_identifier}; - -pub fn validate_create_link_external_id_to_attestation( - action: CreateLink, - base_address: AnyLinkableHash, - target_address: AnyLinkableHash, - _tag: LinkTag, -) -> ExternResult { - // Only the authority can create link - let authority_agent = get_authority_agent()?; - if action.author != authority_agent { - return Ok(ValidateCallbackResult::Invalid( - "Only the Username Registry Authority can create external ID attestation links".into(), - )); - } - - // Check the entry type for the given action hash - let action_hash = ActionHash::try_from(target_address).map_err(|e| wasm_error!(e))?; - let record = must_get_valid_record(action_hash)?; - let external_id_attestation: ExternalIdAttestation = record - .entry() - .to_app_option() - .map_err(|e| wasm_error!(e))? - .ok_or(wasm_error!(WasmErrorInner::Guest(String::from( - "Linked action must reference an entry" - ))))?; - - let expected_base_address = hash_identifier(external_id_attestation.external_id)?; - if AnyLinkableHash::from(expected_base_address) != base_address { - return Ok(ValidateCallbackResult::Invalid( - "ExternalIdToAttestation base_address not derived from external_id".into(), - )); - } - - Ok(ValidateCallbackResult::Valid) -} -pub fn validate_delete_link_external_id_to_attestation( - _action: DeleteLink, - _original_action: CreateLink, - _base: AnyLinkableHash, - _target: AnyLinkableHash, - _tag: LinkTag, -) -> ExternResult { - Ok(ValidateCallbackResult::Invalid(String::from( - "External ID Attestation links cannot be deleted", - ))) -} diff --git a/old_crates/username_registry_validation/src/lib.rs b/old_crates/username_registry_validation/src/lib.rs deleted file mode 100644 index a39669d..0000000 --- a/old_crates/username_registry_validation/src/lib.rs +++ /dev/null @@ -1,34 +0,0 @@ -pub mod username_attestation; -pub use username_attestation::*; -pub mod wallet_attestation; -pub use wallet_attestation::*; -pub mod user_metadata; -pub use user_metadata::*; -pub mod oracle_document; -pub use oracle_document::*; -pub mod agent_username_attestation; -pub use agent_username_attestation::*; -pub mod agent_wallet_attestation; -pub use agent_wallet_attestation::*; -pub mod external_id_attestation; -pub use external_id_attestation::*; -pub mod external_id_to_attestation; -pub use external_id_to_attestation::*; -pub mod agent_external_id_attestation; -pub use agent_external_id_attestation::*; -pub mod name_oracle_document; -pub use name_oracle_document::*; -pub mod recipe; -pub use recipe::*; -pub mod recipe_execution; -pub use recipe_execution::*; -pub mod relate_oracle_document_name; -pub use relate_oracle_document_name::*; -pub mod evm_signing_offer; -pub use evm_signing_offer::*; -pub mod name_to_recipe; -pub use name_to_recipe::*; -pub mod name_to_evm_signing_offer; -pub use name_to_evm_signing_offer::*; -pub mod evm_address_to_signing_offer; -pub use evm_address_to_signing_offer::*; diff --git a/old_crates/username_registry_validation/src/name_oracle_document.rs b/old_crates/username_registry_validation/src/name_oracle_document.rs deleted file mode 100644 index 6436441..0000000 --- a/old_crates/username_registry_validation/src/name_oracle_document.rs +++ /dev/null @@ -1,41 +0,0 @@ -use hdi::prelude::*; -use holoom_types::OracleDocument; -use username_registry_utils::hash_identifier; - -pub fn validate_create_link_name_to_oracle_document( - _action: CreateLink, - base_address: AnyLinkableHash, - target_address: AnyLinkableHash, - _tag: LinkTag, -) -> ExternResult { - // Check the entry type for the given action hash - let action_hash = ActionHash::try_from(target_address).map_err(|e| wasm_error!(e))?; - let record = must_get_valid_record(action_hash)?; - let oracle_document: OracleDocument = record - .entry() - .to_app_option() - .map_err(|e| wasm_error!(e))? - .ok_or(wasm_error!(WasmErrorInner::Guest(String::from( - "Linked action must reference an entry" - ))))?; - - let expected_base_address = hash_identifier(oracle_document.name)?; - if AnyLinkableHash::from(expected_base_address) != base_address { - return Ok(ValidateCallbackResult::Invalid( - "OracleDocument name doesn't hash to base address".into(), - )); - } - - Ok(ValidateCallbackResult::Valid) -} -pub fn validate_delete_link_name_to_oracle_document( - _action: DeleteLink, - _original_action: CreateLink, - _base: AnyLinkableHash, - _target: AnyLinkableHash, - _tag: LinkTag, -) -> ExternResult { - Ok(ValidateCallbackResult::Invalid(String::from( - "OracleDocument links cannot be deleted", - ))) -} diff --git a/old_crates/username_registry_validation/src/name_to_recipe.rs b/old_crates/username_registry_validation/src/name_to_recipe.rs deleted file mode 100644 index 41d8bff..0000000 --- a/old_crates/username_registry_validation/src/name_to_recipe.rs +++ /dev/null @@ -1,21 +0,0 @@ -use hdi::prelude::*; - -pub fn validate_create_link_name_to_recipe( - _action: CreateLink, - _base_address: AnyLinkableHash, - _target_address: AnyLinkableHash, - _tag: LinkTag, -) -> ExternResult { - Ok(ValidateCallbackResult::Valid) -} -pub fn validate_delete_link_name_to_recipe( - _action: DeleteLink, - _original_action: CreateLink, - _base_address: AnyLinkableHash, - _target_address: AnyLinkableHash, - _tag: LinkTag, -) -> ExternResult { - Ok(ValidateCallbackResult::Invalid( - "Cannot delete NameToRecipe links".into(), - )) -} diff --git a/old_crates/username_registry_validation/src/oracle_document.rs b/old_crates/username_registry_validation/src/oracle_document.rs deleted file mode 100644 index f69983f..0000000 --- a/old_crates/username_registry_validation/src/oracle_document.rs +++ /dev/null @@ -1,9 +0,0 @@ -use hdi::prelude::*; -use holoom_types::OracleDocument; - -pub fn validate_create_oracle_document( - _action: EntryCreationAction, - _oracle_document: OracleDocument, -) -> ExternResult { - Ok(ValidateCallbackResult::Valid) -} diff --git a/old_crates/username_registry_validation/src/recipe.rs b/old_crates/username_registry_validation/src/recipe.rs deleted file mode 100644 index 0b0ad5f..0000000 --- a/old_crates/username_registry_validation/src/recipe.rs +++ /dev/null @@ -1,69 +0,0 @@ -use hdi::prelude::*; -use holoom_types::recipe::{JqInstructionArgumentNames, Recipe, RecipeInstruction}; -use jaq_wrapper::compile_filter; - -pub fn validate_create_recipe( - _action: EntryCreationAction, - recipe: Recipe, -) -> ExternResult { - if recipe.trusted_authors.is_empty() { - return Ok(ValidateCallbackResult::Invalid( - "Recipe needs at least 1 trusted author".into(), - )); - } - - match recipe.instructions.last() { - None => { - return Ok(ValidateCallbackResult::Invalid( - "Recipe must contain at least 1 instruction".into(), - )) - } - Some((var_name, _)) => { - if var_name != "$return" { - return Ok(ValidateCallbackResult::Invalid( - "Last instruction must be named '$return'".into(), - )); - } - } - } - - let mut declared_vars_names: HashSet = HashSet::default(); - for (arg_name, _) in recipe.arguments { - declared_vars_names.insert(arg_name); - } - - for (out_var_name, inst) in recipe.instructions { - let var_dependencies = match inst { - RecipeInstruction::Constant { .. } - | RecipeInstruction::GetCallerAgentPublicKey - | RecipeInstruction::GetLatestCallerExternalId => Vec::new(), - RecipeInstruction::GetDocsListedByVar { var_name } => vec![var_name], - RecipeInstruction::GetLatestDocWithIdentifier { var_name } => vec![var_name], - RecipeInstruction::Jq { - input_var_names, - program, - } => { - if compile_filter(&program).is_err() { - return Ok(ValidateCallbackResult::Invalid("Invalid jq program".into())); - } - match input_var_names { - JqInstructionArgumentNames::List { var_names } => var_names, - JqInstructionArgumentNames::Single { var_name } => vec![var_name], - } - } - }; - for dependency in var_dependencies { - if !declared_vars_names.contains(&dependency) { - return Ok(ValidateCallbackResult::Invalid( - "var used before declaration".into(), - )); - } - } - if declared_vars_names.contains(&out_var_name) { - return Ok(ValidateCallbackResult::Invalid("var redeclared".into())); - } - declared_vars_names.insert(out_var_name); - } - - Ok(ValidateCallbackResult::Valid) -} diff --git a/old_crates/username_registry_validation/src/recipe_execution.rs b/old_crates/username_registry_validation/src/recipe_execution.rs deleted file mode 100644 index d0c62cb..0000000 --- a/old_crates/username_registry_validation/src/recipe_execution.rs +++ /dev/null @@ -1,231 +0,0 @@ -use std::{collections::HashMap, rc::Rc}; - -use hdi::prelude::*; -use holoom_types::{ - recipe::{ - JqInstructionArgumentNames, Recipe, RecipeArgument, RecipeArgumentType, RecipeExecution, - RecipeInstruction, RecipeInstructionExecution, - }, - ExternalIdAttestation, OracleDocument, -}; -use indexmap::IndexMap; -use jaq_wrapper::{compile_filter, parse_single_json, run_filter, Val}; -use username_registry_utils::deserialize_record_entry; - -pub fn validate_create_recipe_execution( - action: EntryCreationAction, - recipe_execution: RecipeExecution, -) -> ExternResult { - let recipe_record = must_get_valid_record(recipe_execution.recipe_ah)?; - let recipe: Recipe = deserialize_record_entry(recipe_record)?; - - let mut vars: HashMap = HashMap::default(); - - if recipe_execution.arguments.len() != recipe.arguments.len() { - return Ok(ValidateCallbackResult::Invalid( - "Incorrect number of arguments".into(), - )); - } - - for (arg, (arg_name, arg_type)) in recipe_execution - .arguments - .into_iter() - .zip(recipe.arguments.into_iter()) - { - let val = match (arg, arg_type) { - (RecipeArgument::String { value }, RecipeArgumentType::String) => { - Val::str(value.clone()) - } - (RecipeArgument::EvmAddress { value }, RecipeArgumentType::EvmAddress) => { - Val::str(value.to_string()) - } - _ => { - return Ok(ValidateCallbackResult::Invalid( - "Bad recipe argument".into(), - )) - } - }; - vars.insert(arg_name, val); - } - - if recipe_execution.instruction_executions.len() != recipe.instructions.len() { - return Ok(ValidateCallbackResult::Invalid( - "Incorrect number of instruction executions".into(), - )); - } - - for (instruction_execution, (out_var_name, instruction)) in recipe_execution - .instruction_executions - .into_iter() - .zip(recipe.instructions.into_iter()) - { - if vars.contains_key(&out_var_name) { - unreachable!("Bad impl: A valid Recipe doesn't reassign vars"); - } - - let val = match (instruction_execution, instruction) { - (RecipeInstructionExecution::Constant, RecipeInstruction::Constant { value }) => { - // TODO: validate constant value in validate_create_recipe - parse_single_json(&value)? - } - ( - RecipeInstructionExecution::GetCallerAgentPublicKey, - RecipeInstruction::GetCallerAgentPublicKey, - ) => Val::str(action.author().to_string()), - ( - RecipeInstructionExecution::GetDocsListedByVar { doc_ahs }, - RecipeInstruction::GetDocsListedByVar { var_name }, - ) => { - let list_val = vars - .get(&var_name) - .expect("Bad impl: A valid recipe doesn't use unassigned vars"); - let Val::Arr(item_vals) = list_val else { - return Ok(ValidateCallbackResult::Invalid(format!( - "var '{}' expected to contain array", - &var_name - ))); - }; - let mut expected_names = Vec::new(); - for val in item_vals.iter() { - match val { - Val::Str(identifier) => expected_names.push(identifier.as_ref().clone()), - _ => { - return Ok(ValidateCallbackResult::Invalid(format!( - "var '{}' expected to contain array of string elements", - &var_name - ))) - } - } - } - - let mut docs = Vec::new(); - for doc_ah in doc_ahs { - let doc_record = must_get_valid_record(doc_ah.clone())?; - if !recipe - .trusted_authors - .contains(doc_record.action().author()) - { - return Ok(ValidateCallbackResult::Invalid("Untrusted author".into())); - } - let doc: OracleDocument = deserialize_record_entry(doc_record)?; - docs.push(doc); - } - - let actual_names: Vec = docs.iter().map(|doc| doc.name.clone()).collect(); - if expected_names != actual_names { - return Ok(ValidateCallbackResult::Invalid( - "Listed document name doesn't match".into(), - )); - } - let doc_vals = docs - .iter() - .map(|doc| { - let val = parse_single_json(&doc.json_data)?; - Ok(val) - }) - .collect::>>()?; - Val::arr(doc_vals) - } - ( - RecipeInstructionExecution::GetLatestCallerExternalId { attestation_ah }, - RecipeInstruction::GetLatestCallerExternalId, - ) => { - let attestation_record = must_get_valid_record(attestation_ah)?; - let attestation: ExternalIdAttestation = - deserialize_record_entry(attestation_record)?; - Val::obj(IndexMap::from([ - ( - Rc::new(String::from("agent_pubkey")), - Val::str(attestation.internal_pubkey.to_string()), - ), - ( - Rc::new(String::from("external_id")), - Val::str(attestation.external_id), - ), - ( - Rc::new(String::from("display_name")), - Val::str(attestation.display_name), - ), - ])) - } - ( - RecipeInstructionExecution::GetLatestDocWithIdentifier { doc_ah }, - RecipeInstruction::GetLatestDocWithIdentifier { var_name }, - ) => { - let name_val = vars - .get(&var_name) - .expect("Bad impl: A valid recipe doesn't use unassigned vars"); - let Val::Str(name) = name_val else { - return Ok(ValidateCallbackResult::Invalid(format!( - "var '{}' expected to contain string", - &var_name - ))); - }; - let expected_name = name.as_ref().clone(); - let doc_record = must_get_valid_record(doc_ah)?; - if !recipe - .trusted_authors - .contains(doc_record.action().author()) - { - return Ok(ValidateCallbackResult::Invalid("Untrusted author".into())); - } - let doc: OracleDocument = deserialize_record_entry(doc_record)?; - - if doc.name != expected_name { - return Ok(ValidateCallbackResult::Invalid( - "Specified document name doesn't match".into(), - )); - } - parse_single_json(&doc.json_data)? - } - ( - RecipeInstructionExecution::Jq, - RecipeInstruction::Jq { - input_var_names, - program, - }, - ) => { - let input_val = match input_var_names { - JqInstructionArgumentNames::Single { var_name } => vars - .get(&var_name) - .expect("Bad impl: A valid recipe doesn't use unassigned vars") - .clone(), - JqInstructionArgumentNames::List { var_names } => { - let map: IndexMap, Val> = var_names - .into_iter() - .map(|var_name| { - let val = vars - .get(&var_name) - .expect("Bad impl: A valid recipe doesn't use unassigned vars") - .clone(); - (Rc::new(var_name), val) - }) - .collect(); - Val::obj(map) - } - }; - let filter = compile_filter(&program)?; - run_filter(filter, input_val)? - } - _ => { - return Ok(ValidateCallbackResult::Invalid( - "Bad RecipeInstructionExecution".into(), - )) - } - }; - vars.insert(out_var_name, val); - } - - let return_val = vars - .remove("$return") - .expect("Bad impl: A valid recipe has a $return"); - let output = return_val.to_string(); - - if output != recipe_execution.output { - return Ok(ValidateCallbackResult::Invalid( - "Provided output doesn't match execution's".into(), - )); - } - - Ok(ValidateCallbackResult::Valid) -} diff --git a/old_crates/username_registry_validation/src/relate_oracle_document_name.rs b/old_crates/username_registry_validation/src/relate_oracle_document_name.rs deleted file mode 100644 index 2eeb316..0000000 --- a/old_crates/username_registry_validation/src/relate_oracle_document_name.rs +++ /dev/null @@ -1,39 +0,0 @@ -use hdi::prelude::*; -use holoom_types::DocumentRelationTag; -use username_registry_utils::hash_identifier; - -pub fn validate_create_link_relate_oracle_document_name( - _action: CreateLink, - base_address: AnyLinkableHash, - target_address: AnyLinkableHash, - tag: LinkTag, -) -> ExternResult { - let Ok(document_relation) = ExternIO(tag.into_inner()).decode::() else { - return Ok(ValidateCallbackResult::Invalid( - "Tag must be a DocumentRelationTag".into(), - )); - }; - if base_address != hash_identifier(document_relation.relation)?.into() { - return Ok(ValidateCallbackResult::Invalid( - "Base address must be the hash of the document relation".into(), - )); - } - if target_address != hash_identifier(document_relation.name)?.into() { - return Ok(ValidateCallbackResult::Invalid( - "Target address must be the hash of the target document name".into(), - )); - } - - Ok(ValidateCallbackResult::Valid) -} -pub fn validate_delete_link_relate_oracle_document_name( - _action: DeleteLink, - _original_action: CreateLink, - _base_address: AnyLinkableHash, - _target_address: AnyLinkableHash, - _tag: LinkTag, -) -> ExternResult { - Ok(ValidateCallbackResult::Invalid( - "Cannot delete oracle document relation links".into(), - )) -} diff --git a/old_crates/username_registry_validation/src/user_metadata.rs b/old_crates/username_registry_validation/src/user_metadata.rs deleted file mode 100644 index 06ef711..0000000 --- a/old_crates/username_registry_validation/src/user_metadata.rs +++ /dev/null @@ -1,44 +0,0 @@ -use hdi::prelude::*; -use holoom_types::MetadataItem; - -pub fn validate_create_link_user_metadata( - action: CreateLink, - base_address: AnyLinkableHash, - _target_address: AnyLinkableHash, - tag: LinkTag, -) -> ExternResult { - let agent_pubkey = AgentPubKey::try_from(base_address).map_err(|e| wasm_error!(e))?; - - if action.author != agent_pubkey { - return Ok(ValidateCallbackResult::Invalid( - "Only the owner can embed metadata in their link tags".into(), - )); - } - // The contents of the target_address is unused and irrelevant - - // Check the tag is valid - let _item: MetadataItem = bincode::deserialize(&tag.into_inner()).map_err(|_| { - wasm_error!(WasmErrorInner::Guest( - "Failed to deserialize MetadataItem".into() - )) - })?; - - Ok(ValidateCallbackResult::Valid) -} -pub fn validate_delete_link_user_metadata( - action: DeleteLink, - _original_action: CreateLink, - base_address: AnyLinkableHash, - _target_address: AnyLinkableHash, - _tag: LinkTag, -) -> ExternResult { - let agent_pubkey = AgentPubKey::try_from(base_address).map_err(|e| wasm_error!(e))?; - - if action.author != agent_pubkey { - return Ok(ValidateCallbackResult::Invalid( - "Only the owner can delete their metadata tags".into(), - )); - } - - Ok(ValidateCallbackResult::Valid) -} diff --git a/old_crates/username_registry_validation/src/username_attestation.rs b/old_crates/username_registry_validation/src/username_attestation.rs deleted file mode 100644 index 201b85e..0000000 --- a/old_crates/username_registry_validation/src/username_attestation.rs +++ /dev/null @@ -1,92 +0,0 @@ -use hdi::prelude::*; -use holoom_types::UsernameAttestation; -use username_registry_utils::get_authority_agent; - -pub fn validate_create_username_attestation( - action: EntryCreationAction, - username_attestation: UsernameAttestation, -) -> ExternResult { - // Username length is 6-32 characters - let username_len = username_attestation.username.chars().count(); - if !(6..=32).contains(&username_len) { - return Ok(ValidateCallbackResult::Invalid( - "Username must be between 6-32 characters".into(), - )); - } - - // Only the authority can publish - let authority_agent = get_authority_agent()?; - if action.author() != &authority_agent { - return Ok(ValidateCallbackResult::Invalid( - "Only the Username Registry Authority can create attestations".into(), - )); - } - - let agent_activity = must_get_agent_activity( - authority_agent.clone(), - ChainFilter::new(action.prev_action().clone()).include_cached_entries(), - )?; - let created_usernames: Vec = agent_activity - .into_iter() - .filter_map( - |agent_activity| match agent_activity.action.action().action_type() { - ActionType::Create => agent_activity - .action - .clone() - .action() - .entry_type() - .and_then(|entry_type: &EntryType| match entry_type.clone() { - EntryType::App(app_entry_def) => { - match (app_entry_def.zome_index, app_entry_def.entry_index) { - (ZomeIndex(0), EntryDefIndex(0)) => Some(agent_activity), - _ => None, - } - } - _ => None, - }), - _ => None, - }, - ) - .filter_map(|agent_activity| { - agent_activity - .action - .action() - .entry_data() - .and_then(|(entry_hash, ..)| { - must_get_entry(entry_hash.clone()) - .ok() - .and_then(|entry| UsernameAttestation::try_from(entry.as_content()).ok()) - }) - }) - .collect(); - - // Each username is unique - let identical_usernames_count = created_usernames - .clone() - .into_iter() - .filter(|ua| ua.username == username_attestation.username) - .count(); - - if identical_usernames_count > 0 { - return Ok(ValidateCallbackResult::Invalid(format!( - "Username {:} has already been registered", - username_attestation.username - ))); - } - - // Each agent is unique - let identical_agents_count = created_usernames - .clone() - .iter() - .filter(|ua| ua.agent == username_attestation.agent) - .count(); - - if identical_agents_count > 0 { - return Ok(ValidateCallbackResult::Invalid(format!( - "Agent {:} has already set a Username", - username_attestation.agent - ))); - } - - Ok(ValidateCallbackResult::Valid) -} diff --git a/old_crates/username_registry_validation/src/wallet_attestation.rs b/old_crates/username_registry_validation/src/wallet_attestation.rs deleted file mode 100644 index 5a01a56..0000000 --- a/old_crates/username_registry_validation/src/wallet_attestation.rs +++ /dev/null @@ -1,109 +0,0 @@ -use hdi::prelude::*; -use holoom_types::{ - ChainWalletSignature, EvmAddress, EvmSignature, SolanaAddress, SolanaSignature, - WalletAttestation, -}; - -pub fn evm_signing_message( - evm_address: &EvmAddress, - agent: AgentPubKey, - prev_action: ActionHash, -) -> String { - format!( - "Binding wallet:\n{}\n\nTo Holochain public key:\n{}\n\nCommitted after holochain action:\n{}", - evm_address.to_checksum(None), - holo_hash::HoloHashB64::<_>::from(agent), - holo_hash::HoloHashB64::<_>::from(prev_action) - ) -} - -pub fn solana_signing_message( - solana_address: &SolanaAddress, - agent: AgentPubKey, - prev_action: ActionHash, -) -> String { - format!( - "Binding Solana wallet:\n{}\n\nTo Holochain public key:\n{}\n\nCommitted after holochain action:\n{}", - bs58::encode(solana_address.as_bytes()).into_string(), - holo_hash::HoloHashB64::<_>::from(agent), - holo_hash::HoloHashB64::<_>::from(prev_action) - ) -} - -fn verify_evm_signature( - evm_signature: EvmSignature, - evm_address: EvmAddress, - agent: AgentPubKey, - prev_action: ActionHash, -) -> ExternResult { - let message = evm_signing_message(&evm_address, agent, prev_action); - match evm_signature.recover_address_from_msg(message) { - Ok(recovered_address) => { - if recovered_address == evm_address { - Ok(ValidateCallbackResult::Valid) - } else { - Ok(ValidateCallbackResult::Invalid(format!( - "Expected to recover {} from signature, but instead recovered {}", - evm_address.to_checksum(None), - recovered_address.to_checksum(None) - ))) - } - } - Err(_) => Ok(ValidateCallbackResult::Invalid( - "Invalid signature over wallet binding message".into(), - )), - } -} - -fn verify_solana_signature( - solana_signature: SolanaSignature, - solana_address: &SolanaAddress, - agent: AgentPubKey, - prev_action: ActionHash, -) -> ExternResult { - let message = solana_signing_message(solana_address, agent, prev_action); - match solana_address.verify_strict(message.as_bytes(), &solana_signature) { - Ok(()) => Ok(ValidateCallbackResult::Valid), - Err(_) => Ok(ValidateCallbackResult::Invalid( - "Invalid signature over wallet binding message".into(), - )), - } -} - -pub fn validate_create_wallet_attestation( - action: EntryCreationAction, - wallet_attestation: WalletAttestation, -) -> ExternResult { - if action.author() != &wallet_attestation.agent { - return Ok(ValidateCallbackResult::Invalid( - "Wallet cannot by attested by a different user".into(), - )); - } - // Including the previous action hash in the signing message ensures that signature was - // intended for a particular context, i.e. on the user's chain in this particular DHT. - if action.prev_action() != &wallet_attestation.prev_action { - return Ok(ValidateCallbackResult::Invalid( - "Previous action doesn't match".into(), - )); - } - match wallet_attestation.chain_wallet_signature { - ChainWalletSignature::Evm { - evm_address, - evm_signature, - } => verify_evm_signature( - evm_signature, - evm_address, - wallet_attestation.agent, - wallet_attestation.prev_action, - ), - ChainWalletSignature::Solana { - solana_address, - solana_signature, - } => verify_solana_signature( - solana_signature, - &solana_address, - wallet_attestation.agent, - wallet_attestation.prev_action, - ), - } -} diff --git a/workdir/dna.yaml b/workdir/dna.yaml index 24d63c2..f858934 100644 --- a/workdir/dna.yaml +++ b/workdir/dna.yaml @@ -19,6 +19,10 @@ integrity: hash: ~ bundled: "../target/wasm32-unknown-unknown/release/wallet_attestation_integrity.wasm" dependencies: ~ + - name: evm_attestation_integrity + hash: ~ + bundled: "../target/wasm32-unknown-unknown/release/evm_attestation_integrity.wasm" + dependencies: ~ - name: oracle_document_integrity hash: ~ bundled: "../target/wasm32-unknown-unknown/release/oracle_document_integrity.wasm" @@ -48,6 +52,11 @@ coordinator: bundled: "../target/wasm32-unknown-unknown/release/wallet_attestation.wasm" dependencies: - name: wallet_attestation_integrity + - name: evm_attestation + hash: ~ + bundled: "../target/wasm32-unknown-unknown/release/evm_attestation.wasm" + dependencies: + - name: evm_attestation_integrity - name: oracle_document hash: ~ bundled: "../target/wasm32-unknown-unknown/release/oracle_document.wasm" From 69849b029c0c0ab478d8e3e8df4abd18a7b11450 Mon Sep 17 00:00:00 2001 From: Thomas Date: Fri, 9 Aug 2024 01:10:09 +0100 Subject: [PATCH 4/5] fixes --- Cargo.lock | 67 +++++++++---------- Cargo.toml | 8 +-- .../coordinator}/src/chain_info.rs | 0 .../coordinator/src/lib.rs | 1 + crates/shared_utils/Cargo.toml | 2 +- crates/shared_utils/src/lib.rs | 4 +- flake.nix | 2 +- 7 files changed, 41 insertions(+), 43 deletions(-) rename crates/{shared_utils => external_attestation/coordinator}/src/chain_info.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 69d2563..e6e902a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,9 +140,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a43b18702501396fa9bcdeecd533bc85fac75150d308fc0f6800a01e6234a003" +checksum = "26154390b1d205a4a7ac7352aa2eb4f81f391399d4e2f546fb81a2f8bb383f62" dependencies = [ "arrayvec", "bytes", @@ -1085,9 +1085,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" +checksum = "504bdec147f2cc13c8b57ed9401fd8a147cc66b67ad5cb241394244f2c947549" [[package]] name = "cesu8" @@ -3118,9 +3118,9 @@ dependencies = [ [[package]] name = "hdk_derive" -version = "0.4.0-dev.9" +version = "0.4.0-dev.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a4f51a32c79ec338daaec277c46ecb51f6b5f65517894c43cb012c6864efe" +checksum = "fbfd717793514df9e0c44d698e820e68692792fa38c2d721c97c201e5376476e" dependencies = [ "darling 0.14.4", "heck 0.5.0", @@ -3240,9 +3240,9 @@ dependencies = [ [[package]] name = "holo_hash" -version = "0.4.0-dev.8" +version = "0.4.0-dev.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be7094460e2cbf0f2092fb7158ca5c0aeaa6e225fdcf417f091bb994dc8c919" +checksum = "51425a83caa336a4bd8e6bf4f9b0374ee315fcf4b4c7a103aa2e0c54bb872cad" dependencies = [ "arbitrary", "base64 0.22.1", @@ -3431,9 +3431,9 @@ dependencies = [ [[package]] name = "holochain_integrity_types" -version = "0.4.0-dev.9" +version = "0.4.0-dev.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "048f0ba891006a949a244543954977612b17a0acd7efbeac1914d0e7a119cf8b" +checksum = "12e2d557cc479814090f4724264880ee7ee5e31e5009c98fe23fcc07857ff724" dependencies = [ "arbitrary", "derive_builder 0.20.0", @@ -3574,9 +3574,9 @@ dependencies = [ [[package]] name = "holochain_sqlite" -version = "0.4.0-dev.12" +version = "0.4.0-dev.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451cef8386abbb3b33324bb97988d2722c6cab7d75de977ca4839f6633d14043" +checksum = "31ee6ddf05656b3e85c6d7b0a1c3e31c1099129c8fd571f38034c61e0594e2d1" dependencies = [ "anyhow", "async-trait", @@ -3653,9 +3653,9 @@ dependencies = [ [[package]] name = "holochain_state_types" -version = "0.4.0-dev.9" +version = "0.4.0-dev.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "426e26174cbd8a48c17bb16b99537e13df4eb735f7acdb91c96a7ef0cb41293a" +checksum = "a5c889f7234110e0b2328c454d4d1a57281e7bbfbe1252ac1ac78dc71eab2dc0" dependencies = [ "holo_hash", "holochain_integrity_types", @@ -3842,9 +3842,9 @@ dependencies = [ [[package]] name = "holochain_zome_types" -version = "0.4.0-dev.10" +version = "0.4.0-dev.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9338e9b985d6af6e788aa0036040dc98996ddbc7156a9240dc31d87adf81a9a" +checksum = "71794e55ee4a1d0315e0963c6b5f78a6f97b9ce28de211fed50d37efd284beb2" dependencies = [ "arbitrary", "contrafact", @@ -4133,9 +4133,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" dependencies = [ "bytes", "futures-channel", @@ -4543,9 +4543,9 @@ dependencies = [ [[package]] name = "keccak-asm" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a3633291834c4fbebf8673acbc1b04ec9d151418ff9b8e26dcd79129928758" +checksum = "422fbc7ff2f2f5bdffeb07718e5a5324dca72b0c9293d50df4026652385e3314" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -4553,9 +4553,9 @@ dependencies = [ [[package]] name = "kitsune_p2p" -version = "0.4.0-dev.14" +version = "0.4.0-dev.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91c1ee5d791599a64c14bd476eef8ca6f8767747ffb50bd1720795c58a5a051" +checksum = "058a32524322419b1e8738c0ca886f7d222f12fe6efce045363e051190cce716" dependencies = [ "arrayref", "base64 0.22.1", @@ -5536,9 +5536,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.2" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" dependencies = [ "memchr", ] @@ -6688,9 +6688,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.47" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12bc8d2f72df26a5d3178022df33720fbede0d31d82c7291662eff89836994d" +checksum = "0f86ae463694029097b846d8f99fd5536740602ae00022c0c50c5600720b2f71" dependencies = [ "bytemuck", ] @@ -7013,9 +7013,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" @@ -7521,9 +7521,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" +checksum = "57d79b758b7cb2085612b11a235055e485605a5103faccdd633f35bd7aee69dd" dependencies = [ "cc", "cfg-if 1.0.0", @@ -7553,7 +7553,6 @@ name = "shared_utils" version = "0.0.1" dependencies = [ "hdi", - "hdk", "holoom_types", "serde", ] @@ -8006,15 +8005,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.11.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if 1.0.0", "fastrand 2.1.0", "once_cell", "rustix 0.38.34", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 25f0d6e..c0d4b3d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,12 +14,12 @@ hdk = "=0.4.0-dev.10" holo_hash = { version = "=0.4.0-dev.8", features = ["encoding"] } serde = "1" serde_json = "1" -bincode = "1.3.3" -hex = "0.4.3" +bincode = "1.3" +hex = "0.4" alloy-primitives = { version = "0.6.3", features = ["serde", "k256"] } ed25519-dalek = { version = "2.1.1", features = ["serde"] } -bs58 = "0.5.0" -ethers-signers = "0.6.2" +bs58 = "0.5" +ethers-signers = "0.6" holochain = { version = "=0.4.0-dev.12", default-features = false, features = [ "test_utils", ] } diff --git a/crates/shared_utils/src/chain_info.rs b/crates/external_attestation/coordinator/src/chain_info.rs similarity index 100% rename from crates/shared_utils/src/chain_info.rs rename to crates/external_attestation/coordinator/src/chain_info.rs diff --git a/crates/external_attestation/coordinator/src/lib.rs b/crates/external_attestation/coordinator/src/lib.rs index 96ea26d..b687b23 100644 --- a/crates/external_attestation/coordinator/src/lib.rs +++ b/crates/external_attestation/coordinator/src/lib.rs @@ -1,4 +1,5 @@ pub mod external_attestation; +pub mod chain_info; use hdk::prelude::*; use holoom_types::{LocalHoloomSignal, RemoteHoloomSignal}; diff --git a/crates/shared_utils/Cargo.toml b/crates/shared_utils/Cargo.toml index 8b01bb5..a9049fa 100644 --- a/crates/shared_utils/Cargo.toml +++ b/crates/shared_utils/Cargo.toml @@ -20,5 +20,5 @@ holoom_types = { workspace = true } #[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] #avoids mio bug #holochain = { workspace = true, default-features = false, features = ["test_utils"] } -hdk = { workspace = true, features = ["encoding", "test_utils"] } +#hdk = { workspace = true, features = ["encoding", "test_utils"] } diff --git a/crates/shared_utils/src/lib.rs b/crates/shared_utils/src/lib.rs index 9b1aeb5..0d01fc3 100644 --- a/crates/shared_utils/src/lib.rs +++ b/crates/shared_utils/src/lib.rs @@ -1,4 +1,2 @@ pub mod helpers; -pub use helpers::*; -pub mod chain_info; -pub use chain_info::*; \ No newline at end of file +pub use helpers::*; \ No newline at end of file diff --git a/flake.nix b/flake.nix index 16fa305..57662e3 100644 --- a/flake.nix +++ b/flake.nix @@ -19,7 +19,7 @@ inputsFrom = [ holonix.devShells.${system}.holochainBinaries ]; packages = with pkgs; [ # add further packages from nixpkgs - nodejs + # nodejs cargo-nextest ]; }; From f76b533a414705ffbabc4b64c256016cf2fea84a Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 12 Aug 2024 14:47:31 +0100 Subject: [PATCH 5/5] upgrade to dev16 to mitigate dev12 breakage --- Cargo.lock | 57 ++++++++++++++++++++++++++-------------------------- Cargo.toml | 18 ++++++++--------- package.json | 1 + 3 files changed, 39 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e6e902a..d4e2f39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3057,9 +3057,9 @@ dependencies = [ [[package]] name = "hc_sleuth" -version = "0.4.0-dev.12" +version = "0.4.0-dev.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0337881e0e595f327105cd4a7571e2f08799fee7275d68f2cd67e90c79747eb3" +checksum = "1a1a68c23c82f63682dda91d1d4db792a7ddac4b7ac1a736372761b8360cfb2d" dependencies = [ "aitia", "anyhow", @@ -3080,9 +3080,9 @@ dependencies = [ [[package]] name = "hdi" -version = "0.5.0-dev.9" +version = "0.5.0-dev.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496fab25a7da57d4473ec3afd676c097fa6b1e579e7f97cf7ccfe409b391f079" +checksum = "9dd62de0d29f215642cb2481ec5cdde81233c3fabe97157c8a35118b69dd821d" dependencies = [ "getrandom 0.2.15", "hdk_derive", @@ -3098,9 +3098,9 @@ dependencies = [ [[package]] name = "hdk" -version = "0.4.0-dev.10" +version = "0.4.0-dev.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c64cad926b27bbf72c447f8f8e3b53946458c0987a5b09f40d894aaa2bb143b" +checksum = "5d000c0be9deb5fa8bc111b42fd7085fccf7cc12bf67ae4c8ccf797dca1e866c" dependencies = [ "getrandom 0.2.15", "hdi", @@ -3266,9 +3266,9 @@ dependencies = [ [[package]] name = "holochain" -version = "0.4.0-dev.12" +version = "0.4.0-dev.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5984d6480554d9bd14ae5e3c48fc7ee2852d84d962eca79b1aa94d3881e6823c" +checksum = "9591270c059211089f8749d32242bef545898ec8b8cb0dacdc1b1db33478d700" dependencies = [ "aitia", "anyhow", @@ -3365,9 +3365,9 @@ dependencies = [ [[package]] name = "holochain_cascade" -version = "0.4.0-dev.12" +version = "0.4.0-dev.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e828231e90df7e732d902eef0bc9accf39e086ddb29e652f623aef8e48b8a6c" +checksum = "f33e4a8fe02b3661aa8fdb7a197157f60b338f28ff547b2a124cb60db3f0a3c9" dependencies = [ "async-trait", "fixt", @@ -3392,9 +3392,9 @@ dependencies = [ [[package]] name = "holochain_conductor_api" -version = "0.4.0-dev.12" +version = "0.4.0-dev.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd3aabbd5bc3b2161136016c1572547f665d18f612180a98e24ae7ab5e9f207" +checksum = "f5d756013a108415a71b6b110dd2bd9a91704b8962125cb36ce3040ea44c05ba" dependencies = [ "derive_more", "holo_hash", @@ -3415,9 +3415,9 @@ dependencies = [ [[package]] name = "holochain_conductor_services" -version = "0.3.0-dev.12" +version = "0.3.0-dev.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afbc233d3a4b5a8b5029e358edbd73d79a324ae6832b419f279ea9817d605bae" +checksum = "8638873116ca4fbb0703abfb904bef1c7291505de0109a5a556e069d5ed86a68" dependencies = [ "anyhow", "async-trait", @@ -3453,9 +3453,9 @@ dependencies = [ [[package]] name = "holochain_keystore" -version = "0.4.0-dev.12" +version = "0.4.0-dev.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50203763524fc888d73b449f657fb4c403eaf9e0653029d912e095ecd184ac2a" +checksum = "9a96972e7cdb67e1ed9ca272d17fb537addf0c4262d067475011b464407e2c37" dependencies = [ "base64 0.22.1", "derive_more", @@ -3503,9 +3503,9 @@ dependencies = [ [[package]] name = "holochain_p2p" -version = "0.4.0-dev.12" +version = "0.4.0-dev.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9410a660f06728332b6466282408d86293b3c9139a70d387acfac87a93880e07" +checksum = "701fedea19dd0988f8f24a112bf75b666d5a63b0f50e57eec360e7625421cf95" dependencies = [ "aitia", "async-trait", @@ -3617,9 +3617,9 @@ dependencies = [ [[package]] name = "holochain_state" -version = "0.4.0-dev.12" +version = "0.4.0-dev.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3569950589cded14de212760bd6489b73343012e4d5ac22a723f6a62fa263eb" +checksum = "730cddf56f0c3fd235b1be1f3e7c225558aa49134a40f7aa40d08fc12a0f08ce" dependencies = [ "aitia", "async-recursion", @@ -3627,6 +3627,7 @@ dependencies = [ "chrono", "contrafact", "cron", + "derive_more", "fallible-iterator 0.3.0", "hc_sleuth", "holo_hash", @@ -3664,9 +3665,9 @@ dependencies = [ [[package]] name = "holochain_test_wasm_common" -version = "0.4.0-dev.10" +version = "0.4.0-dev.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681d815fc5028bca1805ca361436be4006d65602a15991a525a8a31c01020909" +checksum = "5edf2524d8270eb118fb8c1ba93edcb42674c7d529d62b1e87ade0b9b2307ea4" dependencies = [ "hdk", "serde", @@ -3692,9 +3693,9 @@ dependencies = [ [[package]] name = "holochain_types" -version = "0.4.0-dev.12" +version = "0.4.0-dev.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac8dd94259b1a620a895e78f454b346f2eeadb09628dab3b8eb59e9241791c2" +checksum = "924da444614b62af53116c61e95a06818eb3be4ae04e490fd080300ddca73214" dependencies = [ "anyhow", "arbitrary", @@ -3764,9 +3765,9 @@ dependencies = [ [[package]] name = "holochain_wasm_test_utils" -version = "0.4.0-dev.12" +version = "0.4.0-dev.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6e3fc495faf5d2ab0d7e8671c8c8d7d70b65cae175437758fc2513993378def" +checksum = "95495106acef20c8ffe32790fc5337dbaf39b36d8a40f669c84ef8dc6a6932a9" dependencies = [ "holochain_types", "holochain_util", @@ -3825,9 +3826,9 @@ dependencies = [ [[package]] name = "holochain_websocket" -version = "0.4.0-dev.12" +version = "0.4.0-dev.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b97be832d7e3d99bc16c925fa14865d45ae3c9cc0027db3b1b3e3ed73e76d7d" +checksum = "0f6b7fbf9a15b3ee68965221b0c25bf908c6f401f0e9f7ba77321655135afc97" dependencies = [ "async-trait", "futures", diff --git a/Cargo.toml b/Cargo.toml index c0d4b3d..1af81ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,22 +9,22 @@ resolver = "2" members = ["crates/*/coordinator","crates/*/integrity"] [workspace.dependencies] -hdi = "=0.5.0-dev.9" -hdk = "=0.4.0-dev.10" -holo_hash = { version = "=0.4.0-dev.8", features = ["encoding"] } +hdi = "=0.5.0-dev.10" +hdk = "=0.4.0-dev.12" +holo_hash = { version = "=0.4.0-dev.9", features = ["encoding"] } serde = "1" serde_json = "1" -bincode = "1.3" -hex = "0.4" +bincode = "1.3.3" +hex = "0.4.3" alloy-primitives = { version = "0.6.3", features = ["serde", "k256"] } ed25519-dalek = { version = "2.1.1", features = ["serde"] } bs58 = "0.5" -ethers-signers = "0.6" -holochain = { version = "=0.4.0-dev.12", default-features = false, features = [ +ethers-signers = "0.6.2" +holochain = { version = "=0.4.0-dev.16", default-features = false, features = [ "test_utils", ] } -holochain_keystore = "=0.4.0-dev.12" -holochain_integrity_types = "0.3" +holochain_keystore = "=0.4.0-dev.15" +#holochain_integrity_types = "0.3" [workspace.dependencies.holoom_types] path = "crates/holoom_types" diff --git a/package.json b/package.json index 8afb230..1bd5790 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "scripts": { "build:dna": "scripts/build_dna.sh", "test:dna": "npm run build:dna && cargo nextest run -j 1", + "test:recipes": "npm run build:dna && cargo nextest run -p holoom_recipe", "build:types": "rimraf crates/holoom_types/bindings && cargo test --package holoom_types && npm run -w @holoom/types build", "build:client": "npm run build -w @holoom/client", "build:authority": "npm run build -w @holoom/authority",