Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b402aa891a | |||
| 1b7267ec18 |
@@ -17,9 +17,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: install yarn in root
|
||||
run: cd ../.. yarn install
|
||||
|
||||
- name: Install npm
|
||||
run: npm install
|
||||
|
||||
|
||||
Generated
+208
-236
@@ -661,22 +661,6 @@ dependencies = [
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-tungstenite"
|
||||
version = "0.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1e9efbe14612da0a19fb983059a0b621e9cf6225d7018ecab4f9988215540dc"
|
||||
dependencies = [
|
||||
"futures-io",
|
||||
"futures-util",
|
||||
"log",
|
||||
"pin-project-lite 0.2.13",
|
||||
"rustls-native-certs",
|
||||
"tokio",
|
||||
"tokio-rustls 0.24.1",
|
||||
"tungstenite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asynchronous-codec"
|
||||
version = "0.6.2"
|
||||
@@ -690,6 +674,15 @@ dependencies = [
|
||||
"pin-project-lite 0.2.13",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atoi"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atoi"
|
||||
version = "1.0.0"
|
||||
@@ -1559,26 +1552,6 @@ version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
|
||||
|
||||
[[package]]
|
||||
name = "const_format"
|
||||
version = "0.2.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673"
|
||||
dependencies = [
|
||||
"const_format_proc_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const_format_proc_macros"
|
||||
version = "0.2.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.3.0"
|
||||
@@ -1649,16 +1622,6 @@ dependencies = [
|
||||
"tendermint-proto",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmos-sdk-proto"
|
||||
version = "0.20.0"
|
||||
source = "git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features#41ed4631e146268b0300033c8bbb993d79a49f58"
|
||||
dependencies = [
|
||||
"prost 0.12.1",
|
||||
"prost-types 0.12.1",
|
||||
"tendermint-proto",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmrs"
|
||||
version = "0.15.0"
|
||||
@@ -1666,26 +1629,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47126f5364df9387b9d8559dcef62e99010e1d4098f39eb3f7ee4b5c254e40ea"
|
||||
dependencies = [
|
||||
"bip32",
|
||||
"cosmos-sdk-proto 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ecdsa 0.16.8",
|
||||
"eyre",
|
||||
"k256",
|
||||
"rand_core 0.6.4",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"signature 2.1.0",
|
||||
"subtle-encoding",
|
||||
"tendermint",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmrs"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features#41ed4631e146268b0300033c8bbb993d79a49f58"
|
||||
dependencies = [
|
||||
"bip32",
|
||||
"cosmos-sdk-proto 0.20.0 (git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features)",
|
||||
"cosmos-sdk-proto",
|
||||
"ecdsa 0.16.8",
|
||||
"eyre",
|
||||
"k256",
|
||||
@@ -1803,15 +1747,30 @@ dependencies = [
|
||||
"toml 0.5.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23"
|
||||
dependencies = [
|
||||
"crc-catalog 1.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "3.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe"
|
||||
dependencies = [
|
||||
"crc-catalog",
|
||||
"crc-catalog 2.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc-catalog"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403"
|
||||
|
||||
[[package]]
|
||||
name = "crc-catalog"
|
||||
version = "2.2.0"
|
||||
@@ -2241,16 +2200,6 @@ dependencies = [
|
||||
"darling_macro 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
|
||||
dependencies = [
|
||||
"darling_core 0.20.3",
|
||||
"darling_macro 0.20.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.13.4"
|
||||
@@ -2279,20 +2228,6 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.13.4"
|
||||
@@ -2315,17 +2250,6 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
|
||||
dependencies = [
|
||||
"darling_core 0.20.3",
|
||||
"quote",
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "5.5.3"
|
||||
@@ -2640,6 +2564,12 @@ version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||
|
||||
[[package]]
|
||||
name = "dotenv"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
|
||||
|
||||
[[package]]
|
||||
name = "dotenvy"
|
||||
version = "0.15.7"
|
||||
@@ -2835,6 +2765,26 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum-iterator"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45a0ac4aeb3a18f92eaf09c6bb9b3ac30ff61ca95514fc58cbead1c9a6bf5401"
|
||||
dependencies = [
|
||||
"enum-iterator-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum-iterator-derive"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eecf8589574ce9b895052fa12d69af7a233f99e6107f5cb8dd1044f2a17bfdcb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.7.1"
|
||||
@@ -3031,9 +2981,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "eyre"
|
||||
version = "0.6.11"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799"
|
||||
checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb"
|
||||
dependencies = [
|
||||
"indenter",
|
||||
"once_cell",
|
||||
@@ -5914,15 +5864,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-api"
|
||||
version = "1.1.34"
|
||||
@@ -5991,7 +5932,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"sqlx 0.6.3",
|
||||
"tap",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
@@ -6009,7 +5950,7 @@ name = "nym-api-requests"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bs58 0.4.0",
|
||||
"cosmrs 0.15.0 (git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features)",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"getset",
|
||||
"nym-coconut-interface",
|
||||
@@ -6067,7 +6008,7 @@ name = "nym-bity-integration"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cosmrs 0.15.0 (git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features)",
|
||||
"cosmrs",
|
||||
"eyre",
|
||||
"k256",
|
||||
"nym-cli-commands",
|
||||
@@ -6112,7 +6053,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"clap 4.4.7",
|
||||
"comfy-table",
|
||||
"cosmrs 0.15.0 (git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features)",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"cw-utils",
|
||||
"handlebars",
|
||||
@@ -6219,7 +6160,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.8",
|
||||
"sqlx",
|
||||
"sqlx 0.6.3",
|
||||
"tap",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
@@ -6309,8 +6250,6 @@ dependencies = [
|
||||
"cosmwasm-schema",
|
||||
"cosmwasm-std",
|
||||
"cw-utils",
|
||||
"cw2",
|
||||
"cw4",
|
||||
"nym-contracts-common",
|
||||
"nym-multisig-contract-common",
|
||||
]
|
||||
@@ -6358,7 +6297,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"log",
|
||||
"sqlx",
|
||||
"sqlx 0.5.13",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
@@ -6383,7 +6322,7 @@ name = "nym-credentials"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bls12_381",
|
||||
"cosmrs 0.15.0 (git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features)",
|
||||
"cosmrs",
|
||||
"log",
|
||||
"nym-api-requests",
|
||||
"nym-coconut-interface",
|
||||
@@ -6545,7 +6484,7 @@ dependencies = [
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"sqlx 0.5.13",
|
||||
"subtle-encoding",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
@@ -6742,6 +6681,7 @@ dependencies = [
|
||||
"nym-types",
|
||||
"nym-validator-client",
|
||||
"opentelemetry",
|
||||
"pretty_env_logger",
|
||||
"rand 0.7.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -6866,7 +6806,7 @@ dependencies = [
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"sqlx 0.6.3",
|
||||
"tap",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
@@ -6887,7 +6827,7 @@ dependencies = [
|
||||
"pretty_env_logger",
|
||||
"rocket",
|
||||
"serde",
|
||||
"sqlx",
|
||||
"sqlx 0.5.13",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
@@ -7395,7 +7335,7 @@ dependencies = [
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"sqlx 0.5.13",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
@@ -7470,7 +7410,7 @@ name = "nym-types"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"base64 0.21.4",
|
||||
"cosmrs 0.15.0 (git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features)",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"eyre",
|
||||
"hmac 0.12.1",
|
||||
@@ -7504,7 +7444,7 @@ dependencies = [
|
||||
"bip32",
|
||||
"bip39",
|
||||
"colored",
|
||||
"cosmrs 0.15.0 (git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features)",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"cw-controllers",
|
||||
"cw-utils",
|
||||
@@ -7546,40 +7486,6 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-validator-rewarder"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bip39",
|
||||
"clap 4.4.7",
|
||||
"cosmwasm-std",
|
||||
"futures",
|
||||
"humantime 2.1.0",
|
||||
"humantime-serde",
|
||||
"nym-bin-common",
|
||||
"nym-coconut",
|
||||
"nym-coconut-bandwidth-contract-common",
|
||||
"nym-coconut-dkg-common",
|
||||
"nym-config",
|
||||
"nym-credentials",
|
||||
"nym-crypto",
|
||||
"nym-network-defaults",
|
||||
"nym-task",
|
||||
"nym-validator-client",
|
||||
"nyxd-scraper",
|
||||
"serde",
|
||||
"serde_with",
|
||||
"sha2 0.10.8",
|
||||
"sqlx",
|
||||
"thiserror",
|
||||
"time",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"url",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-vesting-contract-common"
|
||||
version = "0.7.0"
|
||||
@@ -7598,7 +7504,7 @@ dependencies = [
|
||||
name = "nym-wallet-types"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"cosmrs 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"hex-literal",
|
||||
"nym-config",
|
||||
@@ -7676,28 +7582,6 @@ dependencies = [
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nyxd-scraper"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"const_format",
|
||||
"cosmrs 0.15.0 (git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features)",
|
||||
"eyre",
|
||||
"futures",
|
||||
"nym-bin-common",
|
||||
"sha2 0.10.8",
|
||||
"sqlx",
|
||||
"tendermint",
|
||||
"tendermint-rpc",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.32.1"
|
||||
@@ -7763,9 +7647,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.62"
|
||||
version = "0.10.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671"
|
||||
checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"cfg-if",
|
||||
@@ -7804,9 +7688,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.98"
|
||||
version = "0.9.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7"
|
||||
checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@@ -9906,35 +9790,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23"
|
||||
dependencies = [
|
||||
"base64 0.21.4",
|
||||
"chrono",
|
||||
"hex",
|
||||
"indexmap 1.9.3",
|
||||
"indexmap 2.0.2",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with_macros",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788"
|
||||
dependencies = [
|
||||
"darling 0.20.3",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.25"
|
||||
@@ -10253,6 +10108,17 @@ dependencies = [
|
||||
"der 0.7.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlformat"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4"
|
||||
dependencies = [
|
||||
"itertools 0.10.5",
|
||||
"nom",
|
||||
"unicode_categories",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlformat"
|
||||
version = "0.2.2"
|
||||
@@ -10264,14 +10130,70 @@ dependencies = [
|
||||
"unicode_categories",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlx"
|
||||
version = "0.5.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "551873805652ba0d912fec5bbb0f8b4cdd96baf8e2ebf5970e5671092966019b"
|
||||
dependencies = [
|
||||
"sqlx-core 0.5.13",
|
||||
"sqlx-macros 0.5.13",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlx"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8de3b03a925878ed54a954f621e64bf55a3c1bd29652d0d1a17830405350188"
|
||||
dependencies = [
|
||||
"sqlx-core",
|
||||
"sqlx-macros",
|
||||
"sqlx-core 0.6.3",
|
||||
"sqlx-macros 0.6.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-core"
|
||||
version = "0.5.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e48c61941ccf5ddcada342cd59e3e5173b007c509e1e8e990dafc830294d9dc5"
|
||||
dependencies = [
|
||||
"ahash 0.7.6",
|
||||
"atoi 0.4.0",
|
||||
"bitflags 1.3.2",
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"crc 2.1.0",
|
||||
"crossbeam-queue",
|
||||
"either",
|
||||
"event-listener",
|
||||
"flume",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-intrusive",
|
||||
"futures-util",
|
||||
"hashlink 0.7.0",
|
||||
"hex",
|
||||
"indexmap 1.9.3",
|
||||
"itoa",
|
||||
"libc",
|
||||
"libsqlite3-sys",
|
||||
"log",
|
||||
"memchr",
|
||||
"once_cell",
|
||||
"paste",
|
||||
"percent-encoding",
|
||||
"rustls 0.19.1",
|
||||
"sha2 0.10.8",
|
||||
"smallvec",
|
||||
"sqlformat 0.1.8",
|
||||
"sqlx-rt 0.5.13",
|
||||
"stringprep",
|
||||
"thiserror",
|
||||
"tokio-stream",
|
||||
"url",
|
||||
"webpki 0.21.4",
|
||||
"webpki-roots 0.21.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10281,12 +10203,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029"
|
||||
dependencies = [
|
||||
"ahash 0.7.6",
|
||||
"atoi",
|
||||
"atoi 1.0.0",
|
||||
"bitflags 1.3.2",
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"crc",
|
||||
"crc 3.0.1",
|
||||
"crossbeam-queue",
|
||||
"dotenvy",
|
||||
"either",
|
||||
@@ -10312,16 +10234,34 @@ dependencies = [
|
||||
"rustls-pemfile",
|
||||
"sha2 0.10.8",
|
||||
"smallvec",
|
||||
"sqlformat",
|
||||
"sqlx-rt",
|
||||
"sqlformat 0.2.2",
|
||||
"sqlx-rt 0.6.3",
|
||||
"stringprep",
|
||||
"thiserror",
|
||||
"time",
|
||||
"tokio-stream",
|
||||
"url",
|
||||
"webpki-roots 0.22.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-macros"
|
||||
version = "0.5.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc0fba2b0cae21fc00fe6046f8baa4c7fcb49e379f0f592b04696607f69ed2e1"
|
||||
dependencies = [
|
||||
"dotenv",
|
||||
"either",
|
||||
"heck 0.4.1",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"sha2 0.10.8",
|
||||
"sqlx-core 0.5.13",
|
||||
"sqlx-rt 0.5.13",
|
||||
"syn 1.0.109",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-macros"
|
||||
version = "0.6.3"
|
||||
@@ -10335,12 +10275,23 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"sha2 0.10.8",
|
||||
"sqlx-core",
|
||||
"sqlx-rt",
|
||||
"sqlx-core 0.6.3",
|
||||
"sqlx-rt 0.6.3",
|
||||
"syn 1.0.109",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-rt"
|
||||
version = "0.5.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4db708cd3e459078f85f39f96a00960bd841f66ee2a669e90bf36907f5a79aae"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"tokio",
|
||||
"tokio-rustls 0.22.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-rt"
|
||||
version = "0.6.3"
|
||||
@@ -10473,7 +10424,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7e94b1ec00bad60e6410e058b52f1c66de3dc5fe4d62d09b3e52bb7d3b73e25"
|
||||
dependencies = [
|
||||
"base64 0.13.1",
|
||||
"crc",
|
||||
"crc 3.0.1",
|
||||
"lazy_static",
|
||||
"md-5",
|
||||
"rand 0.8.5",
|
||||
@@ -10707,7 +10658,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfbf0a4753b46a190f367337e0163d0b552a2674a6bac54e74f9f2cdcde2969b"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"async-tungstenite",
|
||||
"bytes",
|
||||
"flex-error",
|
||||
"futures",
|
||||
@@ -10819,8 +10769,6 @@ dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"num_threads",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
@@ -10918,6 +10866,17 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6"
|
||||
dependencies = [
|
||||
"rustls 0.19.1",
|
||||
"tokio",
|
||||
"webpki 0.21.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.23.4"
|
||||
@@ -11453,7 +11412,6 @@ dependencies = [
|
||||
"log",
|
||||
"native-tls",
|
||||
"rand 0.8.5",
|
||||
"rustls 0.21.7",
|
||||
"sha1",
|
||||
"thiserror",
|
||||
"url",
|
||||
@@ -11771,13 +11729,18 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "vergen"
|
||||
version = "8.2.6"
|
||||
version = "7.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1290fd64cc4e7d3c9b07d7f333ce0ce0007253e32870e632624835cc80b83939"
|
||||
checksum = "447f9238a4553957277b3ee09d80babeae0811f1b3baefb093de1c0448437a37"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cfg-if",
|
||||
"enum-iterator",
|
||||
"getset",
|
||||
"git2",
|
||||
"rustc_version 0.4.0",
|
||||
"rustversion",
|
||||
"thiserror",
|
||||
"time",
|
||||
]
|
||||
|
||||
@@ -12063,6 +12026,15 @@ dependencies = [
|
||||
"untrusted 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940"
|
||||
dependencies = [
|
||||
"webpki 0.21.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.22.6"
|
||||
@@ -12182,7 +12154,7 @@ checksum = "465a03cc11e9a7d7b4f9f99870558fe37a102b65b93f8045392fef7c67b39e80"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"async-trait",
|
||||
"crc",
|
||||
"crc 3.0.1",
|
||||
"log",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
@@ -12233,7 +12205,7 @@ dependencies = [
|
||||
"arc-swap",
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"crc",
|
||||
"crc 3.0.1",
|
||||
"log",
|
||||
"rand 0.8.5",
|
||||
"thiserror",
|
||||
|
||||
+2
-9
@@ -67,7 +67,6 @@ members = [
|
||||
"common/nymsphinx/params",
|
||||
"common/nymsphinx/routing",
|
||||
"common/nymsphinx/types",
|
||||
"common/nyxd-scraper",
|
||||
"common/pemstore",
|
||||
"common/socks5-client-core",
|
||||
"common/socks5/proxy-helpers",
|
||||
@@ -102,7 +101,6 @@ members = [
|
||||
"nym-node",
|
||||
"nym-node/nym-node-requests",
|
||||
"nym-outfox",
|
||||
"nym-validator-rewarder",
|
||||
"tools/internal/ssl-inject",
|
||||
"tools/internal/sdk-version-bump",
|
||||
"tools/nym-cli",
|
||||
@@ -125,7 +123,6 @@ default-members = [
|
||||
"nym-api",
|
||||
"tools/nymvisor",
|
||||
"explorer-api",
|
||||
"nym-validator-rewarder",
|
||||
]
|
||||
|
||||
exclude = ["explorer", "contracts", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "nym-vpn/ui/src-tauri", "cpu-cycles"]
|
||||
@@ -162,7 +159,6 @@ reqwest = "0.11.22"
|
||||
schemars = "0.8.1"
|
||||
serde = "1.0.152"
|
||||
serde_json = "1.0.91"
|
||||
sqlx = "0.6.3"
|
||||
tap = "1.0.1"
|
||||
time = "0.3.30"
|
||||
thiserror = "1.0.48"
|
||||
@@ -203,12 +199,9 @@ cw-controllers = { version = "=1.1.0" }
|
||||
|
||||
# cosmrs-related
|
||||
bip32 = "0.5.1"
|
||||
|
||||
# temporarily using a fork again (yay.) because we need staking and slashing support
|
||||
cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch ="nym-temp/all-validator-features" }
|
||||
#cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch = "nym-temp/all-validator-features" } # unfortuntely we need a fork by yours truly to get the staking support
|
||||
tendermint = "0.34" # same version as used by cosmrs
|
||||
cosmrs = "=0.15.0"
|
||||
tendermint-rpc = "0.34" # same version as used by cosmrs
|
||||
tendermint = "0.34" # same version as used by cosmrs
|
||||
prost = "0.12"
|
||||
|
||||
# wasm-related dependencies
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background: #333;
|
||||
color: white;
|
||||
}
|
||||
a {
|
||||
color: skyblue;
|
||||
}
|
||||
}
|
||||
.container {
|
||||
font-family: sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.intro {
|
||||
text-align: center;
|
||||
}
|
||||
.licenses-list {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.license-used-by {
|
||||
margin-top: -10px;
|
||||
}
|
||||
.license-text {
|
||||
max-height: 200px;
|
||||
overflow-y: scroll;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main class="container">
|
||||
<div class="intro">
|
||||
<h1>Third Party Licenses</h1>
|
||||
<p>This page lists the licenses of the projects used in cargo-about.</p>
|
||||
</div>
|
||||
|
||||
<h2>Overview of licenses:</h2>
|
||||
<ul class="licenses-overview">
|
||||
{{#each overview}}
|
||||
<li><a href="#{{id}}">{{name}}</a> ({{count}})</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
||||
<h2>All license text:</h2>
|
||||
<ul class="licenses-list">
|
||||
{{#each licenses}}
|
||||
<li class="license">
|
||||
<h3 id="{{id}}">{{name}}</h3>
|
||||
<h4>Used by:</h4>
|
||||
<ul class="license-used-by">
|
||||
{{#each used_by}}
|
||||
<li><a href="{{#if crate.repository}} {{crate.repository}} {{else}} https://crates.io/crates/{{crate.name}} {{/if}}">{{crate.name}} {{crate.version}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
<pre class="license-text">{{text}}</pre>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
private = { ignore = true }
|
||||
|
||||
accepted = [
|
||||
"0BSD",
|
||||
"Apache-2.0",
|
||||
"BSD-2-Clause",
|
||||
"BSD-3-Clause",
|
||||
"CC0-1.0",
|
||||
"ISC",
|
||||
"MIT",
|
||||
"MPL-2.0",
|
||||
"Unicode-DFS-2016",
|
||||
"OpenSSL",
|
||||
]
|
||||
|
||||
workarounds = [
|
||||
"ring",
|
||||
"rustls",
|
||||
]
|
||||
@@ -5,7 +5,6 @@ authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej St
|
||||
description = "Implementation of the Nym Client"
|
||||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -1667,9 +1667,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.4",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
|
||||
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
|
||||
"version": "1.14.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
|
||||
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -5800,9 +5800,9 @@
|
||||
}
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.15.4",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
|
||||
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
|
||||
"version": "1.14.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
|
||||
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==",
|
||||
"dev": true
|
||||
},
|
||||
"forwarded": {
|
||||
|
||||
@@ -3,7 +3,6 @@ name = "nym-client-websocket-requests"
|
||||
version = "0.1.0"
|
||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
clap = { workspace = true, features = ["cargo", "derive"] }
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
module.exports = {
|
||||
ConfigHandler: require('./config/configHandler.ts'),
|
||||
RestClient: require('./restClient/RestClient.ts')
|
||||
};
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "async-file-watcher"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "nym-bandwidth-controller"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -35,10 +35,9 @@ opentelemetry = { version = "0.19.0", optional = true, features = ["rt-tokio"] }
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
vergen = { version = "=8.2.6", default-features = false, features = [
|
||||
vergen = { version = "=7.4.3", default-features = false, features = [
|
||||
"build",
|
||||
"git",
|
||||
"gitcl",
|
||||
"rustc",
|
||||
"cargo",
|
||||
] }
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use vergen::EmitBuilder;
|
||||
use vergen::{vergen, Config};
|
||||
|
||||
fn main() {
|
||||
EmitBuilder::builder()
|
||||
.all_build()
|
||||
.all_git()
|
||||
.all_rustc()
|
||||
.all_cargo()
|
||||
.emit()
|
||||
.expect("failed to extract build metadata");
|
||||
let mut config = Config::default();
|
||||
if std::env::var("DOCS_RS").is_ok() {
|
||||
// If we don't have access to git information, such as in a docs.rs build, don't error
|
||||
*config.git_mut().skip_if_error_mut() = true;
|
||||
}
|
||||
vergen(config).expect("failed to extract build metadata");
|
||||
}
|
||||
|
||||
@@ -40,9 +40,9 @@ pub struct BinaryBuildInformation {
|
||||
/// Provides the rustc channel that was used for the build, for example `nightly`.
|
||||
pub rustc_channel: &'static str,
|
||||
|
||||
// VERGEN_CARGO_DEBUG
|
||||
/// Provides the cargo debug mode that was used for the build.
|
||||
pub cargo_debug: &'static str,
|
||||
// VERGEN_CARGO_PROFILE
|
||||
/// Provides the cargo profile that was used for the build, for example `debug`.
|
||||
pub cargo_profile: &'static str,
|
||||
}
|
||||
|
||||
impl BinaryBuildInformation {
|
||||
@@ -57,7 +57,7 @@ impl BinaryBuildInformation {
|
||||
commit_branch: env!("VERGEN_GIT_BRANCH"),
|
||||
rustc_version: env!("VERGEN_RUSTC_SEMVER"),
|
||||
rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
|
||||
cargo_debug: env!("VERGEN_CARGO_DEBUG"),
|
||||
cargo_profile: env!("VERGEN_CARGO_PROFILE"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ impl BinaryBuildInformation {
|
||||
commit_branch: self.commit_branch.to_owned(),
|
||||
rustc_version: self.rustc_version.to_owned(),
|
||||
rustc_channel: self.rustc_channel.to_owned(),
|
||||
cargo_debug: self.cargo_debug.to_owned(),
|
||||
cargo_profile: self.cargo_profile.to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,9 +115,9 @@ pub struct BinaryBuildInformationOwned {
|
||||
/// Provides the rustc channel that was used for the build, for example `nightly`.
|
||||
pub rustc_channel: String,
|
||||
|
||||
// VERGEN_CARGO_DEBUG
|
||||
/// Provides the cargo debug mode that was used for the build.
|
||||
pub cargo_debug: String,
|
||||
// VERGEN_CARGO_PROFILE
|
||||
/// Provides the cargo profile that was used for the build, for example `debug`.
|
||||
pub cargo_profile: String,
|
||||
}
|
||||
|
||||
impl Display for BinaryBuildInformationOwned {
|
||||
@@ -151,8 +151,8 @@ impl Display for BinaryBuildInformationOwned {
|
||||
self.rustc_version,
|
||||
"rustc Channel:",
|
||||
self.rustc_channel,
|
||||
"cargo Debug:",
|
||||
self.cargo_debug,
|
||||
"cargo Profile:",
|
||||
self.cargo_profile,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ version = "1.1.15"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.66"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -59,7 +58,7 @@ features = ["time"]
|
||||
version = "0.20.1"
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx]
|
||||
workspace = true
|
||||
version = "0.6.2"
|
||||
features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"]
|
||||
optional = true
|
||||
|
||||
@@ -90,7 +89,7 @@ tempfile = "3.1.0"
|
||||
|
||||
[build-dependencies]
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
|
||||
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
|
||||
sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
pub use wasmtimer::{std::Instant, tokio::*};
|
||||
|
||||
@@ -3,7 +3,6 @@ name = "nym-gateway-client"
|
||||
version = "0.1.0"
|
||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ name = "nym-mixnet-client"
|
||||
version = "0.1.0"
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ version = "0.1.0"
|
||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -42,14 +42,6 @@ pub struct Config {
|
||||
nyxd_config: nyxd::Config,
|
||||
}
|
||||
|
||||
impl TryFrom<NymNetworkDetails> for Config {
|
||||
type Error = ValidatorClientError;
|
||||
|
||||
fn try_from(value: NymNetworkDetails) -> Result<Self, Self::Error> {
|
||||
Config::try_from_nym_network_details(&value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn try_from_nym_network_details(
|
||||
details: &NymNetworkDetails,
|
||||
|
||||
@@ -5,24 +5,21 @@ use crate::nym_api::error::NymAPIError;
|
||||
use crate::nym_api::routes::{CORE_STATUS_COUNT, SINCE_ARG};
|
||||
use async_trait::async_trait;
|
||||
use http_api_client::{ApiClient, NO_PARAMS};
|
||||
pub use nym_api_requests::{
|
||||
coconut::{
|
||||
models::{
|
||||
EpochCredentialsResponse, IssuedCredential, IssuedCredentialBody,
|
||||
IssuedCredentialResponse, IssuedCredentialsResponse,
|
||||
},
|
||||
BlindSignRequestBody, BlindedSignatureResponse, CredentialsRequestBody,
|
||||
VerifyCredentialBody, VerifyCredentialResponse,
|
||||
},
|
||||
models::{
|
||||
ComputeRewardEstParam, DescribedGateway, GatewayBondAnnotated, GatewayCoreStatusResponse,
|
||||
GatewayStatusReportResponse, GatewayUptimeHistoryResponse, InclusionProbabilityResponse,
|
||||
MixNodeBondAnnotated, MixnodeCoreStatusResponse, MixnodeStatusReportResponse,
|
||||
MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RewardEstimationResponse,
|
||||
StakeSaturationResponse, UptimeResponse,
|
||||
},
|
||||
use nym_api_requests::coconut::models::{
|
||||
EpochCredentialsResponse, IssuedCredentialResponse, IssuedCredentialsResponse,
|
||||
};
|
||||
pub use nym_coconut_dkg_common::types::EpochId;
|
||||
use nym_api_requests::coconut::{
|
||||
BlindSignRequestBody, BlindedSignatureResponse, CredentialsRequestBody, VerifyCredentialBody,
|
||||
VerifyCredentialResponse,
|
||||
};
|
||||
use nym_api_requests::models::{
|
||||
ComputeRewardEstParam, DescribedGateway, GatewayBondAnnotated, GatewayCoreStatusResponse,
|
||||
GatewayStatusReportResponse, GatewayUptimeHistoryResponse, InclusionProbabilityResponse,
|
||||
MixNodeBondAnnotated, MixnodeCoreStatusResponse, MixnodeStatusReportResponse,
|
||||
MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RewardEstimationResponse,
|
||||
StakeSaturationResponse, UptimeResponse,
|
||||
};
|
||||
use nym_coconut_dkg_common::types::EpochId;
|
||||
use nym_mixnet_contract_common::mixnode::MixNodeDetails;
|
||||
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId};
|
||||
use nym_name_service_common::response::NamesListResponse;
|
||||
|
||||
@@ -8,8 +8,6 @@ use cosmwasm_std::{Fraction, Uint128};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::ops::Div;
|
||||
use std::str::FromStr;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, Default, Debug, PartialEq, Eq)]
|
||||
pub struct MismatchedDenoms;
|
||||
@@ -128,37 +126,6 @@ impl From<CosmWasmCoin> for Coin {
|
||||
}
|
||||
}
|
||||
|
||||
// unfortunately cosmwasm didn't re-export this correct so we just redefine its
|
||||
#[derive(Error, Debug, PartialEq, Eq)]
|
||||
pub enum CoinFromStrError {
|
||||
#[error("Missing denominator")]
|
||||
MissingDenom,
|
||||
#[error("Missing amount or non-digit characters in amount")]
|
||||
MissingAmount,
|
||||
#[error("Invalid amount: {0}")]
|
||||
InvalidAmount(#[from] std::num::ParseIntError),
|
||||
}
|
||||
|
||||
impl FromStr for Coin {
|
||||
type Err = CoinFromStrError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let pos = s
|
||||
.find(|c: char| !c.is_ascii_digit())
|
||||
.ok_or(CoinFromStrError::MissingDenom)?;
|
||||
let (amount, denom) = s.split_at(pos);
|
||||
|
||||
if amount.is_empty() {
|
||||
return Err(CoinFromStrError::MissingAmount);
|
||||
}
|
||||
|
||||
Ok(Coin {
|
||||
amount: amount.parse::<u128>()?,
|
||||
denom: denom.to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CoinConverter {
|
||||
type Target;
|
||||
|
||||
|
||||
@@ -7,18 +7,12 @@ use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::CosmWasmClient;
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::AccountId;
|
||||
use nym_coconut_dkg_common::{
|
||||
dealer::{
|
||||
DealerDetailsResponse, DealingResponse, DealingStatusResponse, PagedDealerResponse,
|
||||
PagedDealingsResponse,
|
||||
},
|
||||
msg::QueryMsg as DkgQueryMsg,
|
||||
types::{
|
||||
DealerDetails, DealingIndex, Epoch, EpochId, InitialReplacementData,
|
||||
PartialContractDealing, State,
|
||||
},
|
||||
verification_key::{ContractVKShare, PagedVKSharesResponse},
|
||||
use nym_coconut_dkg_common::dealer::{
|
||||
ContractDealing, DealerDetailsResponse, PagedDealerResponse, PagedDealingsResponse,
|
||||
};
|
||||
use nym_coconut_dkg_common::msg::QueryMsg as DkgQueryMsg;
|
||||
use nym_coconut_dkg_common::types::{DealerDetails, Epoch, EpochId, InitialReplacementData};
|
||||
use nym_coconut_dkg_common::verification_key::{ContractVKShare, PagedVKSharesResponse};
|
||||
use serde::Deserialize;
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
@@ -28,16 +22,10 @@ pub trait DkgQueryClient {
|
||||
where
|
||||
for<'a> T: Deserialize<'a>;
|
||||
|
||||
async fn get_state(&self) -> Result<State, NyxdError> {
|
||||
let request = DkgQueryMsg::GetState {};
|
||||
self.query_dkg_contract(request).await
|
||||
}
|
||||
|
||||
async fn get_current_epoch(&self) -> Result<Epoch, NyxdError> {
|
||||
let request = DkgQueryMsg::GetCurrentEpochState {};
|
||||
self.query_dkg_contract(request).await
|
||||
}
|
||||
|
||||
async fn get_current_epoch_threshold(&self) -> Result<Option<u64>, NyxdError> {
|
||||
let request = DkgQueryMsg::GetCurrentEpochThreshold {};
|
||||
self.query_dkg_contract(request).await
|
||||
@@ -76,46 +64,14 @@ pub trait DkgQueryClient {
|
||||
self.query_dkg_contract(request).await
|
||||
}
|
||||
|
||||
async fn get_dealing_status(
|
||||
async fn get_dealings_paged(
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
dealing_index: DealingIndex,
|
||||
) -> Result<DealingStatusResponse, NyxdError> {
|
||||
let request = DkgQueryMsg::GetDealingStatus {
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealing_index,
|
||||
};
|
||||
|
||||
self.query_dkg_contract(request).await
|
||||
}
|
||||
|
||||
async fn get_dealing(
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
dealing_index: DealingIndex,
|
||||
) -> Result<DealingResponse, NyxdError> {
|
||||
let request = DkgQueryMsg::GetDealing {
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealing_index,
|
||||
};
|
||||
|
||||
self.query_dkg_contract(request).await
|
||||
}
|
||||
|
||||
async fn get_dealer_dealings_paged(
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
dealer: &str,
|
||||
start_after: Option<DealingIndex>,
|
||||
idx: u64,
|
||||
start_after: Option<String>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<PagedDealingsResponse, NyxdError> {
|
||||
let request = DkgQueryMsg::GetDealings {
|
||||
epoch_id,
|
||||
dealer: dealer.to_string(),
|
||||
let request = DkgQueryMsg::GetDealing {
|
||||
idx,
|
||||
limit,
|
||||
start_after,
|
||||
};
|
||||
@@ -135,11 +91,6 @@ pub trait DkgQueryClient {
|
||||
};
|
||||
self.query_dkg_contract(request).await
|
||||
}
|
||||
|
||||
async fn get_contract_cw2_version(&self) -> Result<cw2::ContractVersion, NyxdError> {
|
||||
self.query_dkg_contract(DkgQueryMsg::GetCW2ContractVersion {})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
// extension trait to the query client to deal with the paged queries
|
||||
@@ -155,12 +106,8 @@ pub trait PagedDkgQueryClient: DkgQueryClient {
|
||||
collect_paged!(self, get_past_dealers_paged, dealers)
|
||||
}
|
||||
|
||||
async fn get_all_dealer_dealings(
|
||||
&self,
|
||||
epoch_id: EpochId,
|
||||
dealer: &str,
|
||||
) -> Result<Vec<PartialContractDealing>, NyxdError> {
|
||||
collect_paged!(self, get_dealer_dealings_paged, dealings, epoch_id, dealer)
|
||||
async fn get_all_epoch_dealings(&self, idx: u64) -> Result<Vec<ContractDealing>, NyxdError> {
|
||||
collect_paged!(self, get_dealings_paged, dealings, idx)
|
||||
}
|
||||
|
||||
async fn get_all_verification_key_shares(
|
||||
@@ -204,7 +151,6 @@ mod tests {
|
||||
msg: DkgQueryMsg,
|
||||
) {
|
||||
match msg {
|
||||
DkgQueryMsg::GetState {} => client.get_state().ignore(),
|
||||
DkgQueryMsg::GetCurrentEpochState {} => client.get_current_epoch().ignore(),
|
||||
DkgQueryMsg::GetCurrentEpochThreshold {} => {
|
||||
client.get_current_epoch_threshold().ignore()
|
||||
@@ -219,26 +165,11 @@ mod tests {
|
||||
DkgQueryMsg::GetPastDealers { limit, start_after } => {
|
||||
client.get_past_dealers_paged(start_after, limit).ignore()
|
||||
}
|
||||
DkgQueryMsg::GetDealingStatus {
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealing_index,
|
||||
} => client
|
||||
.get_dealing_status(epoch_id, dealer, dealing_index)
|
||||
.ignore(),
|
||||
DkgQueryMsg::GetDealing {
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealing_index,
|
||||
} => client.get_dealing(epoch_id, dealer, dealing_index).ignore(),
|
||||
DkgQueryMsg::GetDealings {
|
||||
epoch_id,
|
||||
dealer,
|
||||
idx,
|
||||
limit,
|
||||
start_after,
|
||||
} => client
|
||||
.get_dealer_dealings_paged(epoch_id, &dealer, limit, start_after)
|
||||
.ignore(),
|
||||
} => client.get_dealings_paged(idx, start_after, limit).ignore(),
|
||||
DkgQueryMsg::GetVerificationKeys {
|
||||
epoch_id,
|
||||
limit,
|
||||
@@ -246,7 +177,6 @@ mod tests {
|
||||
} => client
|
||||
.get_vk_shares_paged(epoch_id, start_after, limit)
|
||||
.ignore(),
|
||||
DkgQueryMsg::GetCW2ContractVersion {} => client.get_contract_cw2_version().ignore(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+13
-16
@@ -10,9 +10,9 @@ use async_trait::async_trait;
|
||||
use cosmrs::AccountId;
|
||||
use cosmwasm_std::Addr;
|
||||
use nym_coconut_dkg_common::msg::ExecuteMsg as DkgExecuteMsg;
|
||||
use nym_coconut_dkg_common::types::{EncodedBTEPublicKeyWithProof, PartialContractDealing};
|
||||
use nym_coconut_dkg_common::types::EncodedBTEPublicKeyWithProof;
|
||||
use nym_coconut_dkg_common::verification_key::VerificationKeyShare;
|
||||
use nym_contracts_common::IdentityKey;
|
||||
use nym_contracts_common::dealings::ContractSafeBytes;
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
@@ -42,14 +42,12 @@ pub trait DkgSigningClient {
|
||||
async fn register_dealer(
|
||||
&self,
|
||||
bte_key: EncodedBTEPublicKeyWithProof,
|
||||
identity_key: IdentityKey,
|
||||
announce_address: String,
|
||||
resharing: bool,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
let req = DkgExecuteMsg::RegisterDealer {
|
||||
bte_key_with_proof: bte_key,
|
||||
identity_key,
|
||||
announce_address,
|
||||
resharing,
|
||||
};
|
||||
@@ -60,11 +58,14 @@ pub trait DkgSigningClient {
|
||||
|
||||
async fn submit_dealing_bytes(
|
||||
&self,
|
||||
dealing: PartialContractDealing,
|
||||
dealing_bytes: ContractSafeBytes,
|
||||
resharing: bool,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
let req = DkgExecuteMsg::CommitDealing { dealing, resharing };
|
||||
let req = DkgExecuteMsg::CommitDealing {
|
||||
dealing_bytes,
|
||||
resharing,
|
||||
};
|
||||
|
||||
self.execute_dkg_contract(fee, req, "dealing commitment".to_string(), vec![])
|
||||
.await
|
||||
@@ -147,20 +148,16 @@ mod tests {
|
||||
match msg {
|
||||
DkgExecuteMsg::RegisterDealer {
|
||||
bte_key_with_proof,
|
||||
identity_key,
|
||||
announce_address,
|
||||
resharing,
|
||||
} => client
|
||||
.register_dealer(
|
||||
bte_key_with_proof,
|
||||
identity_key,
|
||||
announce_address,
|
||||
resharing,
|
||||
None,
|
||||
)
|
||||
.register_dealer(bte_key_with_proof, announce_address, resharing, None)
|
||||
.ignore(),
|
||||
DkgExecuteMsg::CommitDealing { dealing, resharing } => client
|
||||
.submit_dealing_bytes(dealing, resharing, None)
|
||||
DkgExecuteMsg::CommitDealing {
|
||||
dealing_bytes,
|
||||
resharing,
|
||||
} => client
|
||||
.submit_dealing_bytes(dealing_bytes, resharing, None)
|
||||
.ignore(),
|
||||
DkgExecuteMsg::CommitVerificationKeyShare { share, resharing } => client
|
||||
.submit_verification_key_share(share, resharing, None)
|
||||
|
||||
+4
-4
@@ -52,6 +52,10 @@ use wasmtimer::tokio::sleep;
|
||||
pub const DEFAULT_BROADCAST_POLLING_RATE: Duration = Duration::from_secs(4);
|
||||
pub const DEFAULT_BROADCAST_TIMEOUT: Duration = Duration::from_secs(60);
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
#[async_trait]
|
||||
impl CosmWasmClient for cosmrs::rpc::HttpClient {}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait CosmWasmClient: TendermintRpcClient {
|
||||
@@ -518,7 +522,3 @@ pub trait CosmWasmClient: TendermintRpcClient {
|
||||
res.try_into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
impl<T> CosmWasmClient for T where T: TendermintRpcClient {}
|
||||
|
||||
+1
-1
@@ -425,7 +425,7 @@ where
|
||||
amount: amount.into_iter().map(Into::into).collect(),
|
||||
}
|
||||
.to_any()
|
||||
.map_err(|_| NyxdError::SerializationError("MsgSend".to_owned()))
|
||||
.map_err(|_| NyxdError::SerializationError("MsgExecuteContract".to_owned()))
|
||||
})
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::nyxd::cosmwasm_client::client_traits::SigningCosmWasmClient;
|
||||
use crate::nyxd::cosmwasm_client::client_traits::{CosmWasmClient, SigningCosmWasmClient};
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::{Config, GasPrice, Hash, Height};
|
||||
use crate::rpc::TendermintRpcClient;
|
||||
@@ -26,7 +26,6 @@ use cosmrs::rpc::{HttpClient, HttpClientUrl};
|
||||
pub mod client_traits;
|
||||
mod helpers;
|
||||
pub mod logs;
|
||||
pub mod module_traits;
|
||||
pub mod types;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -330,6 +329,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C, S> CosmWasmClient for MaybeSigningClient<C, S>
|
||||
where
|
||||
C: TendermintRpcClient + Send + Sync,
|
||||
S: Send + Sync,
|
||||
{
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C, S> SigningCosmWasmClient for MaybeSigningClient<C, S>
|
||||
where
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod slashing;
|
||||
pub mod staking;
|
||||
|
||||
pub use staking::query::StakingQueryClient;
|
||||
// pub use slashing::query
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod query;
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod query;
|
||||
|
||||
pub use cosmrs::staking::{
|
||||
QueryHistoricalInfoResponse, QueryValidatorResponse, QueryValidatorsResponse, Validator,
|
||||
};
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::{QueryHistoricalInfoResponse, QueryValidatorResponse, QueryValidatorsResponse};
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::{CosmWasmClient, PageRequest};
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::proto::cosmos::staking::v1beta1::{
|
||||
QueryHistoricalInfoRequest as ProtoQueryHistoricalInfoRequest,
|
||||
QueryHistoricalInfoResponse as ProtoQueryHistoricalInfoResponse,
|
||||
QueryValidatorRequest as ProtoQueryValidatorRequest,
|
||||
QueryValidatorResponse as ProtoQueryValidatorResponse,
|
||||
QueryValidatorsRequest as ProtoQueryValidatorsRequest,
|
||||
QueryValidatorsResponse as ProtoQueryValidatorsResponse,
|
||||
};
|
||||
use cosmrs::staking::{QueryHistoricalInfoRequest, QueryValidatorRequest, QueryValidatorsRequest};
|
||||
use cosmrs::AccountId;
|
||||
|
||||
// TODO: change trait restriction from `CosmWasmClient` to `TendermintRpcClient`
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait StakingQueryClient: CosmWasmClient {
|
||||
async fn historical_info(&self, height: i64) -> Result<QueryHistoricalInfoResponse, NyxdError> {
|
||||
let path = Some("/cosmos.staking.v1beta1.Query/HistoricalInfo".to_owned());
|
||||
|
||||
let req = QueryHistoricalInfoRequest { height };
|
||||
|
||||
let res = self
|
||||
.make_abci_query::<ProtoQueryHistoricalInfoRequest, ProtoQueryHistoricalInfoResponse>(
|
||||
path,
|
||||
req.into(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(res.try_into()?)
|
||||
}
|
||||
|
||||
async fn validator(
|
||||
&self,
|
||||
validator_addr: AccountId,
|
||||
) -> Result<QueryValidatorResponse, NyxdError> {
|
||||
let path = Some("/cosmos.staking.v1beta1.Query/Validator".to_owned());
|
||||
|
||||
let req = QueryValidatorRequest { validator_addr };
|
||||
|
||||
let res = self
|
||||
.make_abci_query::<ProtoQueryValidatorRequest, ProtoQueryValidatorResponse>(
|
||||
path,
|
||||
req.into(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(res.try_into()?)
|
||||
}
|
||||
|
||||
async fn validators(
|
||||
&self,
|
||||
status: String,
|
||||
pagination: Option<PageRequest>,
|
||||
) -> Result<QueryValidatorsResponse, NyxdError> {
|
||||
let path = Some("/cosmos.staking.v1beta1.Query/Validators".to_owned());
|
||||
|
||||
let req = QueryValidatorsRequest { status, pagination };
|
||||
|
||||
let res = self
|
||||
.make_abci_query::<ProtoQueryValidatorsRequest, ProtoQueryValidatorsResponse>(
|
||||
path,
|
||||
req.into(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(res.try_into()?)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
impl<T> StakingQueryClient for T where T: CosmWasmClient {}
|
||||
@@ -11,7 +11,7 @@ pub mod gas_price;
|
||||
|
||||
pub type GasAdjustment = f32;
|
||||
|
||||
pub const DEFAULT_SIMULATED_GAS_MULTIPLIER: GasAdjustment = 1.5;
|
||||
pub const DEFAULT_SIMULATED_GAS_MULTIPLIER: GasAdjustment = 2.0;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AutoFeeGrant {
|
||||
|
||||
@@ -29,30 +29,23 @@ use tendermint_rpc::endpoint::*;
|
||||
use tendermint_rpc::{Error as TendermintRpcError, Order};
|
||||
use url::Url;
|
||||
|
||||
pub use crate::nyxd::{
|
||||
cosmwasm_client::{
|
||||
client_traits::{CosmWasmClient, SigningCosmWasmClient},
|
||||
module_traits::{self, StakingQueryClient},
|
||||
},
|
||||
fee::Fee,
|
||||
};
|
||||
pub use crate::nyxd::cosmwasm_client::client_traits::{CosmWasmClient, SigningCosmWasmClient};
|
||||
pub use crate::nyxd::fee::Fee;
|
||||
pub use crate::rpc::TendermintRpcClient;
|
||||
pub use coin::Coin;
|
||||
pub use cosmrs::{
|
||||
bank::MsgSend,
|
||||
bip32,
|
||||
crypto::PublicKey,
|
||||
query::{PageRequest, PageResponse},
|
||||
tendermint::{
|
||||
abci::{response::DeliverTx, types::ExecTxResult, Event, EventAttribute},
|
||||
block::Height,
|
||||
hash::{self, Algorithm, Hash},
|
||||
validator::Info as TendermintValidatorInfo,
|
||||
Time as TendermintTime,
|
||||
},
|
||||
tx::{self, Msg},
|
||||
AccountId, Any, Coin as CosmosCoin, Denom, Gas,
|
||||
pub use cosmrs::bank::MsgSend;
|
||||
pub use cosmrs::tendermint::abci::{
|
||||
response::DeliverTx, types::ExecTxResult, Event, EventAttribute,
|
||||
};
|
||||
pub use cosmrs::tendermint::block::Height;
|
||||
pub use cosmrs::tendermint::hash::{self, Algorithm, Hash};
|
||||
pub use cosmrs::tendermint::validator::Info as TendermintValidatorInfo;
|
||||
pub use cosmrs::tendermint::Time as TendermintTime;
|
||||
pub use cosmrs::tx::Msg;
|
||||
pub use cosmrs::tx::{self};
|
||||
pub use cosmrs::Coin as CosmosCoin;
|
||||
pub use cosmrs::Gas;
|
||||
pub use cosmrs::{bip32, AccountId, Denom};
|
||||
pub use cosmwasm_std::Coin as CosmWasmCoin;
|
||||
pub use cw2;
|
||||
pub use cw3;
|
||||
@@ -62,8 +55,9 @@ pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment};
|
||||
pub use tendermint_rpc::{
|
||||
endpoint::{tx::Response as TxResponse, validators::Response as ValidatorResponse},
|
||||
query::Query,
|
||||
Paging, Request, Response, SimpleRequest,
|
||||
Paging,
|
||||
};
|
||||
pub use tendermint_rpc::{Request, Response, SimpleRequest};
|
||||
|
||||
#[cfg(feature = "http-client")]
|
||||
use crate::http_client;
|
||||
@@ -103,14 +97,6 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<NymNetworkDetails> for Config {
|
||||
type Error = NyxdError;
|
||||
|
||||
fn try_from(value: NymNetworkDetails) -> Result<Self, Self::Error> {
|
||||
Config::try_from_nym_network_details(&value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NyxdClient<C, S = NoSigner> {
|
||||
client: MaybeSigningClient<C, S>,
|
||||
@@ -742,7 +728,7 @@ where
|
||||
where
|
||||
H: Into<Height> + Send,
|
||||
{
|
||||
TendermintRpcClient::validators(&self.client, height, paging).await
|
||||
self.client.validators(height, paging).await
|
||||
}
|
||||
|
||||
async fn latest_consensus_params(
|
||||
@@ -817,6 +803,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C, S> CosmWasmClient for NyxdClient<C, S>
|
||||
where
|
||||
C: TendermintRpcClient + Send + Sync,
|
||||
S: Send + Sync,
|
||||
{
|
||||
}
|
||||
|
||||
impl<C, S> OfflineSigner for NyxdClient<C, S>
|
||||
where
|
||||
S: OfflineSigner,
|
||||
|
||||
@@ -3,7 +3,6 @@ name = "nym-coconut-interface"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "Crutch library until there is proper SerDe support for coconut structs"
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
bs58 = "0.4.0"
|
||||
|
||||
@@ -3,7 +3,6 @@ name = "nym-cli-commands"
|
||||
version = "1.0.0"
|
||||
authors.workspace = true
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
|
||||
@@ -6,7 +6,7 @@ use log::{debug, info};
|
||||
use std::str::FromStr;
|
||||
|
||||
use nym_coconut_dkg_common::msg::InstantiateMsg;
|
||||
use nym_coconut_dkg_common::types::{TimeConfiguration, DEFAULT_DEALINGS};
|
||||
use nym_coconut_dkg_common::types::TimeConfiguration;
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
@@ -93,7 +93,6 @@ pub async fn generate(args: Args) {
|
||||
multisig_addr: multisig_addr.to_string(),
|
||||
time_configuration: Some(time_configuration),
|
||||
mix_denom,
|
||||
key_size: DEFAULT_DEALINGS as u32,
|
||||
};
|
||||
|
||||
debug!("instantiate_msg: {:?}", instantiate_msg);
|
||||
|
||||
@@ -3,7 +3,6 @@ name = "nym-config"
|
||||
version = "0.1.0"
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -18,4 +17,4 @@ url = { workspace = true }
|
||||
nym-network-defaults = { path = "../network-defaults" }
|
||||
|
||||
[features]
|
||||
default = ["dirs"]
|
||||
default = ["dirs"]
|
||||
@@ -73,7 +73,7 @@ where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let path = path.as_ref();
|
||||
log::info!("saving config file to {}", path.display());
|
||||
log::debug!("trying to save config file to {}", path.display());
|
||||
|
||||
if let Some(parent) = path.parent() {
|
||||
create_dir_all(parent)?;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "nym-coconut-bandwidth-contract-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -13,4 +12,4 @@ cw2 = { workspace = true, optional = true }
|
||||
nym-multisig-contract-common = { path = "../multisig-contract" }
|
||||
|
||||
[features]
|
||||
schema = ["cw2"]
|
||||
schema = ["cw2"]
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "nym-coconut-dkg-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -10,11 +9,9 @@ license.workspace = true
|
||||
cosmwasm-schema = { workspace = true }
|
||||
cosmwasm-std = { workspace = true }
|
||||
cw-utils = { workspace = true }
|
||||
cw2 = { workspace = true }
|
||||
cw4 = { workspace = true }
|
||||
|
||||
contracts-common = { path = "../contracts-common", package = "nym-contracts-common" }
|
||||
nym-multisig-contract-common = { path = "../multisig-contract" }
|
||||
|
||||
[features]
|
||||
schema = []
|
||||
schema = []
|
||||
@@ -1,10 +1,7 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::types::{
|
||||
ContractDealing, DealingIndex, EncodedBTEPublicKeyWithProof, EpochId, NodeIndex,
|
||||
PartialContractDealing,
|
||||
};
|
||||
use crate::types::{ContractSafeBytes, EncodedBTEPublicKeyWithProof, NodeIndex};
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::Addr;
|
||||
|
||||
@@ -12,7 +9,6 @@ use cosmwasm_std::Addr;
|
||||
pub struct DealerDetails {
|
||||
pub address: Addr,
|
||||
pub bte_public_key_with_proof: EncodedBTEPublicKeyWithProof,
|
||||
pub ed25519_identity: String,
|
||||
pub announce_address: String,
|
||||
pub assigned_index: NodeIndex,
|
||||
}
|
||||
@@ -70,50 +66,35 @@ impl PagedDealerResponse {
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct DealingResponse {
|
||||
pub epoch_id: EpochId,
|
||||
|
||||
pub struct ContractDealing {
|
||||
pub dealing: ContractSafeBytes,
|
||||
pub dealer: Addr,
|
||||
|
||||
pub dealing_index: DealingIndex,
|
||||
|
||||
pub dealing: Option<ContractDealing>,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct DealingStatusResponse {
|
||||
pub epoch_id: EpochId,
|
||||
|
||||
pub dealer: Addr,
|
||||
|
||||
pub dealing_index: DealingIndex,
|
||||
|
||||
pub dealing_submitted: bool,
|
||||
impl ContractDealing {
|
||||
pub fn new(dealing: ContractSafeBytes, dealer: Addr) -> Self {
|
||||
ContractDealing { dealing, dealer }
|
||||
}
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct PagedDealingsResponse {
|
||||
pub epoch_id: EpochId,
|
||||
|
||||
pub dealer: Addr,
|
||||
|
||||
pub dealings: Vec<PartialContractDealing>,
|
||||
pub dealings: Vec<ContractDealing>,
|
||||
pub per_page: usize,
|
||||
|
||||
/// Field indicating paging information for the following queries if the caller wishes to get further entries.
|
||||
pub start_next_after: Option<DealingIndex>,
|
||||
pub start_next_after: Option<Addr>,
|
||||
}
|
||||
|
||||
impl PagedDealingsResponse {
|
||||
pub fn new(
|
||||
epoch_id: EpochId,
|
||||
dealer: Addr,
|
||||
dealings: Vec<PartialContractDealing>,
|
||||
start_next_after: Option<DealingIndex>,
|
||||
dealings: Vec<ContractDealing>,
|
||||
per_page: usize,
|
||||
start_next_after: Option<Addr>,
|
||||
) -> Self {
|
||||
PagedDealingsResponse {
|
||||
epoch_id,
|
||||
dealer,
|
||||
dealings,
|
||||
per_page,
|
||||
start_next_after,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::types::{
|
||||
DealingIndex, EncodedBTEPublicKeyWithProof, EpochId, PartialContractDealing, TimeConfiguration,
|
||||
};
|
||||
use crate::types::{ContractSafeBytes, EncodedBTEPublicKeyWithProof, EpochId, TimeConfiguration};
|
||||
use crate::verification_key::VerificationKeyShare;
|
||||
use cosmwasm_schema::cw_serde;
|
||||
use cosmwasm_std::Addr;
|
||||
|
||||
#[cfg(feature = "schema")]
|
||||
use crate::{
|
||||
dealer::{
|
||||
DealerDetailsResponse, DealingResponse, DealingStatusResponse, PagedDealerResponse,
|
||||
PagedDealingsResponse,
|
||||
},
|
||||
types::{Epoch, InitialReplacementData, State},
|
||||
dealer::{DealerDetailsResponse, PagedDealerResponse, PagedDealingsResponse},
|
||||
types::{Epoch, InitialReplacementData},
|
||||
verification_key::PagedVKSharesResponse,
|
||||
};
|
||||
use contracts_common::IdentityKey;
|
||||
#[cfg(feature = "schema")]
|
||||
use cosmwasm_schema::QueryResponses;
|
||||
|
||||
@@ -27,22 +21,18 @@ pub struct InstantiateMsg {
|
||||
pub multisig_addr: String,
|
||||
pub time_configuration: Option<TimeConfiguration>,
|
||||
pub mix_denom: String,
|
||||
|
||||
/// Specifies the number of elements in the derived keys
|
||||
pub key_size: u32,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub enum ExecuteMsg {
|
||||
RegisterDealer {
|
||||
bte_key_with_proof: EncodedBTEPublicKeyWithProof,
|
||||
identity_key: IdentityKey,
|
||||
announce_address: String,
|
||||
resharing: bool,
|
||||
},
|
||||
|
||||
CommitDealing {
|
||||
dealing: PartialContractDealing,
|
||||
dealing_bytes: ContractSafeBytes,
|
||||
resharing: bool,
|
||||
},
|
||||
|
||||
@@ -65,9 +55,6 @@ pub enum ExecuteMsg {
|
||||
#[cw_serde]
|
||||
#[cfg_attr(feature = "schema", derive(QueryResponses))]
|
||||
pub enum QueryMsg {
|
||||
#[cfg_attr(feature = "schema", returns(State))]
|
||||
GetState {},
|
||||
|
||||
#[cfg_attr(feature = "schema", returns(Epoch))]
|
||||
GetCurrentEpochState {},
|
||||
|
||||
@@ -92,26 +79,11 @@ pub enum QueryMsg {
|
||||
start_after: Option<String>,
|
||||
},
|
||||
|
||||
#[cfg_attr(feature = "schema", returns(DealingStatusResponse))]
|
||||
GetDealingStatus {
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
dealing_index: DealingIndex,
|
||||
},
|
||||
|
||||
#[cfg_attr(feature = "schema", returns(DealingResponse))]
|
||||
GetDealing {
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
dealing_index: DealingIndex,
|
||||
},
|
||||
|
||||
#[cfg_attr(feature = "schema", returns(PagedDealingsResponse))]
|
||||
GetDealings {
|
||||
epoch_id: EpochId,
|
||||
dealer: String,
|
||||
GetDealing {
|
||||
idx: u64,
|
||||
limit: Option<u32>,
|
||||
start_after: Option<DealingIndex>,
|
||||
start_after: Option<String>,
|
||||
},
|
||||
|
||||
#[cfg_attr(feature = "schema", returns(PagedVKSharesResponse))]
|
||||
@@ -120,11 +92,6 @@ pub enum QueryMsg {
|
||||
limit: Option<u32>,
|
||||
start_after: Option<String>,
|
||||
},
|
||||
|
||||
/// Gets the stored contract version information that's required by the CW2 spec interface for migrations.
|
||||
#[serde(rename = "get_cw2_contract_version")]
|
||||
#[cfg_attr(feature = "schema", returns(cw2::ContractVersion))]
|
||||
GetCW2ContractVersion {},
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
|
||||
@@ -8,38 +8,14 @@ use std::str::FromStr;
|
||||
pub use crate::dealer::{DealerDetails, PagedDealerResponse};
|
||||
pub use contracts_common::dealings::ContractSafeBytes;
|
||||
pub use cosmwasm_std::{Addr, Coin, Timestamp};
|
||||
pub use cw4::Cw4Contract;
|
||||
|
||||
pub type EncodedBTEPublicKeyWithProof = String;
|
||||
pub type EncodedBTEPublicKeyWithProofRef<'a> = &'a str;
|
||||
pub type NodeIndex = u64;
|
||||
pub type EpochId = u64;
|
||||
pub type DealingIndex = u32;
|
||||
pub type ContractDealing = ContractSafeBytes;
|
||||
|
||||
// 2 public attributes, 2 private attributes, 1 fixed for coconut credential
|
||||
pub const DEFAULT_DEALINGS: usize = 2 + 2 + 1;
|
||||
|
||||
#[cw_serde]
|
||||
pub struct PartialContractDealing {
|
||||
pub index: DealingIndex,
|
||||
pub data: ContractDealing,
|
||||
}
|
||||
|
||||
impl PartialContractDealing {
|
||||
pub fn new(index: DealingIndex, data: ContractDealing) -> Self {
|
||||
PartialContractDealing { index, data }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(DealingIndex, ContractDealing)> for PartialContractDealing {
|
||||
fn from(value: (DealingIndex, ContractDealing)) -> Self {
|
||||
PartialContractDealing {
|
||||
index: value.0,
|
||||
data: value.1,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub const TOTAL_DEALINGS: usize = 2 + 2 + 1;
|
||||
|
||||
#[cw_serde]
|
||||
pub struct InitialReplacementData {
|
||||
@@ -97,16 +73,6 @@ impl Default for TimeConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
pub struct State {
|
||||
pub mix_denom: String,
|
||||
pub multisig_addr: Addr,
|
||||
pub group_addr: Cw4Contract,
|
||||
|
||||
/// Specifies the number of elements in the derived keys
|
||||
pub key_size: u32,
|
||||
}
|
||||
|
||||
#[cw_serde]
|
||||
#[derive(Copy, Default)]
|
||||
pub struct Epoch {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "nym-ephemera-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -14,4 +13,4 @@ cw-utils = { workspace = true }
|
||||
contracts-common = { path = "../contracts-common", package = "nym-contracts-common" }
|
||||
|
||||
[features]
|
||||
schema = []
|
||||
schema = []
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "nym-group-contract-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "nym-multisig-contract-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "nym-name-service-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -17,4 +16,4 @@ serde = { workspace = true, features = ["derive"] }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
[features]
|
||||
schema = ["cw2"]
|
||||
schema = ["cw2"]
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "nym-service-provider-directory-common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -16,4 +15,4 @@ nym-contracts-common = { path = "../contracts-common", version = "0.5.0" }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
[features]
|
||||
schema = ["cw2"]
|
||||
schema = ["cw2"]
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "nym-credential-storage"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -14,14 +13,14 @@ thiserror = { workspace = true }
|
||||
tokio = { version = "1.24.1", features = ["sync"]}
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx]
|
||||
workspace = true
|
||||
version = "0.5"
|
||||
features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"]
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
|
||||
workspace = true
|
||||
version = "1.24.1"
|
||||
features = [ "rt-multi-thread", "net", "signal", "fs" ]
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
|
||||
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
|
||||
tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] }
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "nym-credential-utils"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "nym-credentials"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ name = "nym-dkg"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
resolver = "2"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ use std::collections::HashMap;
|
||||
use std::ops::Neg;
|
||||
use zeroize::Zeroize;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(test, derive(PartialEq, Eq))]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(Clone, PartialEq, Eq))]
|
||||
pub struct Ciphertexts {
|
||||
pub rr: [G1Projective; NUM_CHUNKS],
|
||||
pub ss: [G1Projective; NUM_CHUNKS],
|
||||
|
||||
@@ -67,8 +67,8 @@ impl<'a> Instance<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(test, derive(PartialEq, Eq))]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(Clone, PartialEq, Eq))]
|
||||
pub struct ProofOfChunking {
|
||||
y0: G1Projective,
|
||||
bb: Vec<G1Projective>,
|
||||
|
||||
@@ -76,8 +76,8 @@ impl<'a> Instance<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(test, derive(PartialEq, Eq))]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(Clone, PartialEq, Eq))]
|
||||
pub struct ProofOfSecretSharing {
|
||||
ff: G1Projective,
|
||||
aa: G2Projective,
|
||||
|
||||
@@ -82,7 +82,7 @@ impl RecoveredVerificationKeys {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq, Eq))]
|
||||
pub struct Dealing {
|
||||
pub public_coefficients: PublicCoefficients,
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "nym-execute"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
@@ -81,15 +81,6 @@ ExitPolicy accept6 *6:119
|
||||
ExitPolicy accept *4:120
|
||||
ExitPolicy reject6 [FC00::]/7:*
|
||||
|
||||
# Portless
|
||||
ExitPolicy accept *:0
|
||||
ExitPolicy accept *4:0
|
||||
ExitPolicy accept *6:0
|
||||
|
||||
ExitPolicy reject *:0
|
||||
ExitPolicy reject *4:0
|
||||
ExitPolicy reject *6:0
|
||||
|
||||
#ExitPolicy accept *:8080 #and another comment here
|
||||
|
||||
ExitPolicy reject FE80:0000:0000:0000:0202:B3FF:FE1E:8329:*
|
||||
@@ -193,60 +184,6 @@ ExitPolicy reject *:*
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy accept *:0
|
||||
expected.push(
|
||||
Accept,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::Star,
|
||||
ports: PortRange::new_zero(),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy accept *4:0
|
||||
expected.push(
|
||||
Accept,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::V4Star,
|
||||
ports: PortRange::new_zero(),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy accept *6:0
|
||||
expected.push(
|
||||
Accept,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::V6Star,
|
||||
ports: PortRange::new_zero(),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy reject *:0
|
||||
expected.push(
|
||||
Reject,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::Star,
|
||||
ports: PortRange::new_zero(),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy reject *4:0
|
||||
expected.push(
|
||||
Reject,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::V4Star,
|
||||
ports: PortRange::new_zero(),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy reject *6:0
|
||||
expected.push(
|
||||
Reject,
|
||||
AddressPortPattern {
|
||||
ip_pattern: IpPattern::V6Star,
|
||||
ports: PortRange::new_zero(),
|
||||
},
|
||||
);
|
||||
|
||||
// ExitPolicy FE80:0000:0000:0000:0202:B3FF:FE1E:8329:*
|
||||
expected.push(
|
||||
Reject,
|
||||
|
||||
@@ -264,13 +264,7 @@ mod stringified_ip_pattern {
|
||||
impl AddressPortPattern {
|
||||
/// Return true iff this pattern matches a given address and port.
|
||||
pub fn matches(&self, addr: &IpAddr, port: u16) -> bool {
|
||||
// For backward compatibility, we treat port 0 as a wildcard until all gateways have
|
||||
// upgraded, at which point we can add *:0 to the policy list.
|
||||
if port == 0 {
|
||||
self.ip_pattern.matches(addr)
|
||||
} else {
|
||||
self.ip_pattern.matches(addr) && self.ports.contains(port)
|
||||
}
|
||||
self.ip_pattern.matches(addr) && self.ports.contains(port)
|
||||
}
|
||||
|
||||
/// As matches, but accept a SocketAddr.
|
||||
@@ -401,9 +395,19 @@ fn parse_addr(s: &str) -> Result<IpAddr, PolicyError> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Helper: try to parse a port making sure it's non-zero
|
||||
fn parse_port(s: &str) -> Result<u16, PolicyError> {
|
||||
s.parse::<u16>()
|
||||
.map_err(|_| PolicyError::InvalidPort { raw: s.to_string() })
|
||||
let port = s
|
||||
.parse::<u16>()
|
||||
.map_err(|_| PolicyError::InvalidPort { raw: s.to_string() })?;
|
||||
|
||||
if port == 0 {
|
||||
Err(PolicyError::InvalidPort {
|
||||
raw: port.to_string(),
|
||||
})
|
||||
} else {
|
||||
Ok(port)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for IpPattern {
|
||||
@@ -490,10 +494,6 @@ impl PortRange {
|
||||
PortRange::new_unchecked(1, 65535)
|
||||
}
|
||||
|
||||
pub fn new_zero() -> Self {
|
||||
PortRange { start: 0, end: 0 }
|
||||
}
|
||||
|
||||
/// Create a new PortRange.
|
||||
///
|
||||
/// The Portrange contains all ports between `start` and `end` inclusive.
|
||||
@@ -574,7 +574,6 @@ mod test {
|
||||
|
||||
check("marzipan:80");
|
||||
check("1.2.3.4:90-80");
|
||||
check("1.2.3.4:0-80");
|
||||
check("1.2.3.4/100:8888");
|
||||
check("[1.2.3.4]/16:80");
|
||||
check("[::1]/130:8888");
|
||||
@@ -613,22 +612,6 @@ mod test {
|
||||
|
||||
check("0.0.0.0/0:*", &["127.0.0.1:80"], &["[f00b::]:80"]);
|
||||
check("[::]/0:*", &["[f00b::]:80"], &["127.0.0.1:80"]);
|
||||
|
||||
check(
|
||||
"*:0",
|
||||
&["1.2.3.4:0", "[::1]:0", "9.0.0.0:0"],
|
||||
&["1.2.3.4:443", "[::1]:500", "9.0.0.0:80", "[::1]:80"],
|
||||
);
|
||||
check(
|
||||
"*4:0",
|
||||
&["1.2.3.4:0", "9.0.0.0:0"],
|
||||
&["1.2.3.4:443", "9.0.0.0:80", "[::1]:0", "[::1]:80"],
|
||||
);
|
||||
check(
|
||||
"*6:0",
|
||||
&["[::1]:0"],
|
||||
&["[::1]:80", "1.2.3.4:0", "1.2.3.4:443"],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -637,7 +620,6 @@ mod test {
|
||||
policy.push(AddressPolicyAction::Accept, "*:443".parse()?);
|
||||
policy.push(AddressPolicyAction::Accept, "[::1]:80".parse()?);
|
||||
policy.push(AddressPolicyAction::Reject, "*:80".parse()?);
|
||||
policy.push(AddressPolicyAction::Accept, "*:0".parse()?);
|
||||
|
||||
let policy = policy; // drop mut
|
||||
assert!(policy
|
||||
@@ -658,9 +640,6 @@ mod test {
|
||||
assert!(policy
|
||||
.allows_sockaddr(&"127.0.0.1:66".parse().unwrap())
|
||||
.is_none());
|
||||
assert!(policy
|
||||
.allows_sockaddr(&"127.0.0.1:0".parse().unwrap())
|
||||
.unwrap());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -693,6 +672,7 @@ mod test {
|
||||
assert_eq!("*".parse::<PortRange>().unwrap(), PortRange::new_all());
|
||||
|
||||
assert!("hello".parse::<PortRange>().is_err());
|
||||
assert!("0".parse::<PortRange>().is_err());
|
||||
assert!("65536".parse::<PortRange>().is_err());
|
||||
assert!("65537".parse::<PortRange>().is_err());
|
||||
assert!("1-2-3".parse::<PortRange>().is_err());
|
||||
@@ -700,9 +680,6 @@ mod test {
|
||||
assert!("1-".parse::<PortRange>().is_err());
|
||||
assert!("-2".parse::<PortRange>().is_err());
|
||||
assert!("-".parse::<PortRange>().is_err());
|
||||
|
||||
assert_eq!("0".parse::<PortRange>().unwrap(), PortRange::new_zero(),);
|
||||
assert!("0-1".parse::<PortRange>().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "ledger"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -11,4 +10,4 @@ bip32 = "0.5.1"
|
||||
k256 = { workspace = true }
|
||||
ledger-transport = "0.10.0"
|
||||
ledger-transport-hid = "0.10.0"
|
||||
thiserror = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
@@ -3,7 +3,6 @@ name = "nym-mixnode-common"
|
||||
version = "0.1.0"
|
||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -111,7 +111,6 @@ impl NymNetworkDetails {
|
||||
.with_additional_validator_endpoint(ValidatorDetails::new(
|
||||
var(var_names::NYXD).expect("nyxd validator not set"),
|
||||
Some(var(var_names::NYM_API).expect("nym api not set")),
|
||||
get_optional_env(var_names::NYXD_WEBSOCKET),
|
||||
))
|
||||
.with_mixnet_contract(Some(
|
||||
var(var_names::MIXNET_CONTRACT_ADDRESS).expect("mixnet contract not set"),
|
||||
@@ -341,9 +340,6 @@ impl DenomDetailsOwned {
|
||||
pub struct ValidatorDetails {
|
||||
// it is assumed those values are always valid since they're being provided in our defaults file
|
||||
pub nyxd_url: String,
|
||||
//
|
||||
pub websocket_url: Option<String>,
|
||||
|
||||
// Right now api_url is optional as we are not running the api reliably on all validators
|
||||
// however, later on it should be a mandatory field
|
||||
pub api_url: Option<String>,
|
||||
@@ -351,10 +347,9 @@ pub struct ValidatorDetails {
|
||||
}
|
||||
|
||||
impl ValidatorDetails {
|
||||
pub fn new<S: Into<String>>(nyxd_url: S, api_url: Option<S>, websocket_url: Option<S>) -> Self {
|
||||
pub fn new<S: Into<String>>(nyxd_url: S, api_url: Option<S>) -> Self {
|
||||
ValidatorDetails {
|
||||
nyxd_url: nyxd_url.into(),
|
||||
websocket_url: websocket_url.map(Into::into),
|
||||
api_url: api_url.map(Into::into),
|
||||
}
|
||||
}
|
||||
@@ -362,7 +357,6 @@ impl ValidatorDetails {
|
||||
pub fn new_nyxd_only<S: Into<String>>(nyxd_url: S) -> Self {
|
||||
ValidatorDetails {
|
||||
nyxd_url: nyxd_url.into(),
|
||||
websocket_url: None,
|
||||
api_url: None,
|
||||
}
|
||||
}
|
||||
@@ -378,12 +372,6 @@ impl ValidatorDetails {
|
||||
.as_ref()
|
||||
.map(|url| url.parse().expect("the provided api url is invalid!"))
|
||||
}
|
||||
|
||||
pub fn websocket_url(&self) -> Option<Url> {
|
||||
self.websocket_url
|
||||
.as_ref()
|
||||
.map(|url| url.parse().expect("the provided websocket url is invalid!"))
|
||||
}
|
||||
}
|
||||
|
||||
fn fix_deprecated_environmental_variables() {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
use crate::var_names;
|
||||
use crate::{DenomDetails, ValidatorDetails};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub const NETWORK_NAME: &str = "mainnet";
|
||||
|
||||
@@ -26,7 +25,6 @@ pub const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772
|
||||
pub const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "https://mainnet-stats.nymte.ch:8090/";
|
||||
pub const NYXD_URL: &str = "https://rpc.nymtech.net";
|
||||
pub const NYM_API: &str = "https://validator.nymtech.net/api/";
|
||||
pub const NYXD_WS: &str = "wss://rpc.nymtech.net/websocket";
|
||||
pub const EXPLORER_API: &str = "https://explorer.nymtech.net/api/";
|
||||
|
||||
// I'm making clippy mad on purpose, because that url HAS TO be updated and deployed before merging
|
||||
@@ -34,11 +32,7 @@ pub const EXIT_POLICY_URL: &str =
|
||||
"https://nymtech.net/.wellknown/network-requester/exit-policy.txt";
|
||||
|
||||
pub(crate) fn validators() -> Vec<ValidatorDetails> {
|
||||
vec![ValidatorDetails::new(
|
||||
NYXD_URL,
|
||||
Some(NYM_API),
|
||||
Some(NYXD_WS),
|
||||
)]
|
||||
vec![ValidatorDetails::new(NYXD_URL, Some(NYM_API))]
|
||||
}
|
||||
|
||||
const DEFAULT_SUFFIX: &str = "_MAINNET_DEFAULT";
|
||||
@@ -66,12 +60,6 @@ pub fn read_var_if_not_default(var: &str) -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_parsed_var_if_not_default<T: FromStr>(var: &str) -> Option<Result<T, T::Err>> {
|
||||
read_var_if_not_default(var)
|
||||
.as_deref()
|
||||
.map(FromStr::from_str)
|
||||
}
|
||||
|
||||
pub fn export_to_env() {
|
||||
set_var_to_default(var_names::CONFIGURED, "true");
|
||||
set_var_to_default(var_names::NETWORK_NAME, NETWORK_NAME);
|
||||
@@ -116,7 +104,6 @@ pub fn export_to_env() {
|
||||
);
|
||||
set_var_to_default(var_names::NYXD, NYXD_URL);
|
||||
set_var_to_default(var_names::NYM_API, NYM_API);
|
||||
set_var_to_default(var_names::NYXD_WEBSOCKET, NYXD_WS);
|
||||
set_var_to_default(var_names::EXPLORER_API, EXPLORER_API);
|
||||
set_var_to_default(var_names::EXIT_POLICY_URL, EXIT_POLICY_URL);
|
||||
}
|
||||
@@ -165,7 +152,6 @@ pub fn export_to_env_if_not_set() {
|
||||
);
|
||||
set_var_conditionally_to_default(var_names::NYXD, NYXD_URL);
|
||||
set_var_conditionally_to_default(var_names::NYM_API, NYM_API);
|
||||
set_var_conditionally_to_default(var_names::NYXD_WEBSOCKET, NYXD_WS);
|
||||
set_var_conditionally_to_default(var_names::EXPLORER_API, EXPLORER_API);
|
||||
set_var_conditionally_to_default(var_names::EXIT_POLICY_URL, EXIT_POLICY_URL);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ pub const SERVICE_PROVIDER_DIRECTORY_CONTRACT_ADDRESS: &str =
|
||||
pub const NAME_SERVICE_CONTRACT_ADDRESS: &str = "NAME_SERVICE_CONTRACT_ADDRESS";
|
||||
pub const NYXD: &str = "NYXD";
|
||||
pub const NYM_API: &str = "NYM_API";
|
||||
pub const NYXD_WEBSOCKET: &str = "NYXD_WS";
|
||||
pub const EXPLORER_API: &str = "EXPLORER_API";
|
||||
pub const EXIT_POLICY_URL: &str = "EXIT_POLICY";
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "nym-node-tester-utils"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ name = "nym-nonexhaustive-delayqueue"
|
||||
version = "0.1.0"
|
||||
authors = ["Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ name = "nym-coconut"
|
||||
version = "0.5.0"
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>", "Ania Piotrowska <ania@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -255,7 +255,7 @@ fn bench_coconut(c: &mut Criterion) {
|
||||
b.iter(|| {
|
||||
verify_partial_blind_signature(
|
||||
¶ms,
|
||||
blind_sign_request.get_private_attributes_pedersen_commitments(),
|
||||
&blind_sign_request,
|
||||
&public_attributes,
|
||||
random_blind_signature,
|
||||
partial_verification_key,
|
||||
|
||||
@@ -43,5 +43,3 @@ mod utils;
|
||||
pub type Attribute = bls12_381::Scalar;
|
||||
pub type PrivateAttribute = Attribute;
|
||||
pub type PublicAttribute = Attribute;
|
||||
|
||||
pub use bls12_381::G1Projective;
|
||||
|
||||
@@ -362,12 +362,12 @@ pub fn blind_sign(
|
||||
/// The function returns `true` if the partial blind signature is valid, and `false` otherwise.
|
||||
pub fn verify_partial_blind_signature(
|
||||
params: &Parameters,
|
||||
private_attribute_commitments: &[G1Projective],
|
||||
blind_sign_request: &BlindSignRequest,
|
||||
public_attributes: &[&Attribute],
|
||||
blind_sig: &BlindedSignature,
|
||||
partial_verification_key: &VerificationKey,
|
||||
) -> bool {
|
||||
let num_private_attributes = private_attribute_commitments.len();
|
||||
let num_private_attributes = blind_sign_request.private_attributes_commitments.len();
|
||||
if num_private_attributes + public_attributes.len() > partial_verification_key.beta_g2.len() {
|
||||
return false;
|
||||
}
|
||||
@@ -388,7 +388,8 @@ pub fn verify_partial_blind_signature(
|
||||
];
|
||||
|
||||
// for each private attribute, add (cm_i, beta_i) to the miller terms
|
||||
for (private_attr_commit, beta_g2) in private_attribute_commitments
|
||||
for (private_attr_commit, beta_g2) in blind_sign_request
|
||||
.private_attributes_commitments
|
||||
.iter()
|
||||
.zip(&partial_verification_key.beta_g2)
|
||||
{
|
||||
@@ -421,7 +422,7 @@ pub fn verify_partial_blind_signature(
|
||||
// is equivalent to checking e(a, b) • e(c, d)^{-1} == id
|
||||
// and thus to e(a, b) • e(c^{-1}, d) == id
|
||||
//
|
||||
// compute e(c^{-1}, g2) • e(s, alpha) • e(cm_0, beta_0) • e(cm_i, beta_i) • (s^pub_0, beta_{i+1}) (s^pub_j, beta_{i + j})
|
||||
// compute e(c^1, g2) • e(s, alpha) • e(cm_0, beta_0) • e(cm_i, beta_i) • (s^pub_0, beta_{i+1}) (s^pub_j, beta_{i + j})
|
||||
multi_miller_loop(&terms_refs)
|
||||
.final_exponentiation()
|
||||
.is_identity()
|
||||
@@ -518,7 +519,7 @@ mod tests {
|
||||
|
||||
assert!(verify_partial_blind_signature(
|
||||
¶ms,
|
||||
&request.private_attributes_commitments,
|
||||
&request,
|
||||
&public_attributes,
|
||||
&blind_sig,
|
||||
validator_keypair.verification_key()
|
||||
@@ -538,7 +539,7 @@ mod tests {
|
||||
|
||||
assert!(verify_partial_blind_signature(
|
||||
¶ms,
|
||||
&request.private_attributes_commitments,
|
||||
&request,
|
||||
&[],
|
||||
&blind_sig,
|
||||
validator_keypair.verification_key()
|
||||
@@ -567,7 +568,7 @@ mod tests {
|
||||
// this assertion should fail, as we try to verify with a wrong validator key
|
||||
assert!(!verify_partial_blind_signature(
|
||||
¶ms,
|
||||
&request.private_attributes_commitments,
|
||||
&request,
|
||||
&public_attributes,
|
||||
&blind_sig,
|
||||
validator2_keypair.verification_key()
|
||||
|
||||
@@ -108,17 +108,6 @@ pub fn transpose_matrix<T: Debug>(matrix: Vec<Vec<T>>) -> Vec<Vec<T>> {
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! random_scalars_refs {
|
||||
( $x: ident, $params: expr, $n: expr ) => {
|
||||
let _vec = $params.n_random_scalars($n);
|
||||
#[allow(clippy::map_identity)]
|
||||
let $x = _vec.iter().collect::<Vec<_>>();
|
||||
};
|
||||
}
|
||||
|
||||
pub use random_scalars_refs;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
@@ -181,3 +170,14 @@ pub mod tests {
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! random_scalars_refs {
|
||||
( $x: ident, $params: expr, $n: expr ) => {
|
||||
let _vec = $params.n_random_scalars($n);
|
||||
#[allow(clippy::map_identity)]
|
||||
let $x = _vec.iter().collect::<Vec<_>>();
|
||||
};
|
||||
}
|
||||
|
||||
pub use random_scalars_refs;
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
[package]
|
||||
name = "nyxd-scraper"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
documentation.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
async-trait.workspace = true
|
||||
const_format = "0.2.32"
|
||||
cosmrs.workspace = true
|
||||
eyre = "0.6.9"
|
||||
futures.workspace = true
|
||||
sha2 = "0.10.8"
|
||||
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate", "time"] }
|
||||
tendermint.workspace = true
|
||||
tendermint-rpc = { workspace = true, features = ["websocket-client", "http-client"] }
|
||||
thiserror.workspace = true
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
tokio-stream = "0.1.14"
|
||||
tokio-util = { version = "0.7.10", features = ["rt"]}
|
||||
tracing.workspace = true
|
||||
url.workspace = true
|
||||
|
||||
|
||||
# TEMP
|
||||
nym-bin-common = { path = "../bin-common", features = ["basic_tracing"]}
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
|
||||
@@ -1,28 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
use sqlx::{Connection, SqliteConnection};
|
||||
use std::env;
|
||||
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
let database_path = format!("{out_dir}/scraper-example.sqlite");
|
||||
|
||||
let mut conn = SqliteConnection::connect(&format!("sqlite://{database_path}?mode=rwc"))
|
||||
.await
|
||||
.expect("Failed to create SQLx database connection");
|
||||
|
||||
sqlx::migrate!("./sql_migrations")
|
||||
.run(&mut conn)
|
||||
.await
|
||||
.expect("Failed to perform SQLx migrations");
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
println!("cargo:rustc-env=DATABASE_URL=sqlite://{}", &database_path);
|
||||
|
||||
#[cfg(target_family = "windows")]
|
||||
// for some strange reason we need to add a leading `/` to the windows path even though it's
|
||||
// not a valid windows path... but hey, it works...
|
||||
println!("cargo:rustc-env=DATABASE_URL=sqlite:///{}", &database_path);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
CREATE TABLE METADATA
|
||||
(
|
||||
id INTEGER PRIMARY KEY CHECK (id = 0),
|
||||
last_processed_height INTEGER NOT NULL
|
||||
);
|
||||
@@ -1,76 +0,0 @@
|
||||
CREATE TABLE validator
|
||||
(
|
||||
consensus_address TEXT NOT NULL PRIMARY KEY, /* Validator consensus address */
|
||||
consensus_pubkey TEXT NOT NULL UNIQUE /* Validator consensus public key */
|
||||
);
|
||||
|
||||
CREATE TABLE pre_commit
|
||||
(
|
||||
validator_address TEXT NOT NULL REFERENCES validator (consensus_address),
|
||||
height BIGINT NOT NULL,
|
||||
timestamp TIMESTAMP WITHOUT TIME ZONE NOT NULL,
|
||||
voting_power BIGINT NOT NULL,
|
||||
proposer_priority BIGINT NOT NULL,
|
||||
UNIQUE (validator_address, timestamp)
|
||||
);
|
||||
CREATE INDEX pre_commit_validator_address_index ON pre_commit (validator_address);
|
||||
CREATE INDEX pre_commit_height_index ON pre_commit (height);
|
||||
|
||||
CREATE TABLE block
|
||||
(
|
||||
height BIGINT UNIQUE PRIMARY KEY,
|
||||
hash TEXT NOT NULL UNIQUE,
|
||||
num_txs INTEGER DEFAULT 0,
|
||||
total_gas BIGINT DEFAULT 0,
|
||||
proposer_address TEXT REFERENCES validator (consensus_address),
|
||||
timestamp TIMESTAMP WITHOUT TIME ZONE NOT NULL
|
||||
);
|
||||
CREATE INDEX block_height_index ON block (height);
|
||||
CREATE INDEX block_hash_index ON block (hash);
|
||||
CREATE INDEX block_proposer_address_index ON block (proposer_address);
|
||||
|
||||
-- no JSONB in sqlite (yet) : )
|
||||
CREATE TABLE "transaction"
|
||||
(
|
||||
hash TEXT UNIQUE NOT NULL,
|
||||
height BIGINT NOT NULL REFERENCES block (height),
|
||||
"index" INTEGER NOT NULL,
|
||||
success BOOLEAN NOT NULL,
|
||||
|
||||
/* Body */
|
||||
num_messages INTEGER NOT NULL,
|
||||
-- messages JSONB NOT NULL,-- DEFAULT '[]'::JSONB,
|
||||
memo TEXT,
|
||||
-- signatures TEXT[] NOT NULL,
|
||||
|
||||
/* AuthInfo */
|
||||
-- signer_infos JSONB NOT NULL,-- DEFAULT '[]'::JSONB,
|
||||
-- fee JSONB NOT NULL,-- DEFAULT '{}'::JSONB,
|
||||
|
||||
/* Tx response */
|
||||
gas_wanted BIGINT DEFAULT 0,
|
||||
gas_used BIGINT DEFAULT 0,
|
||||
raw_log TEXT
|
||||
-- logs JSONB
|
||||
);
|
||||
CREATE INDEX transaction_hash_index ON "transaction" (hash);
|
||||
CREATE INDEX transaction_height_index ON "transaction" (height);
|
||||
|
||||
CREATE TABLE message
|
||||
(
|
||||
transaction_hash TEXT NOT NULL REFERENCES "transaction" (hash),
|
||||
"index" BIGINT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
-- value JSONB NOT NULL,
|
||||
-- involved_accounts_addresses TEXT[] NOT NULL,
|
||||
|
||||
height BIGINT NOT NULL,
|
||||
CONSTRAINT unique_message_per_tx UNIQUE (transaction_hash, "index")
|
||||
);
|
||||
CREATE INDEX message_transaction_hash_index ON message (transaction_hash);
|
||||
CREATE INDEX message_type_index ON message (type);
|
||||
|
||||
CREATE TABLE pruning
|
||||
(
|
||||
last_pruned_height BIGINT NOT NULL
|
||||
);
|
||||
@@ -1,65 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::block_processor::MAX_RANGE_SIZE;
|
||||
use std::cmp::min;
|
||||
use std::collections::VecDeque;
|
||||
use std::ops::Range;
|
||||
|
||||
pub(crate) fn split_request_range(request_range: Range<u32>) -> VecDeque<Range<u32>> {
|
||||
let mut requests = VecDeque::new();
|
||||
|
||||
let mut start = request_range.start;
|
||||
let mut end = min(request_range.end, start + MAX_RANGE_SIZE as u32);
|
||||
|
||||
loop {
|
||||
requests.push_back(start..end);
|
||||
start = min(start + MAX_RANGE_SIZE as u32, request_range.end);
|
||||
end = min(end + MAX_RANGE_SIZE as u32, request_range.end);
|
||||
|
||||
if start == end {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
requests
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn splitting_request_range() {
|
||||
let range = 0..100;
|
||||
let mut expected = VecDeque::new();
|
||||
expected.push_back(0..30);
|
||||
expected.push_back(30..60);
|
||||
expected.push_back(60..90);
|
||||
expected.push_back(90..100);
|
||||
assert_eq!(expected, split_request_range(range));
|
||||
|
||||
let range = 0..30;
|
||||
let mut expected = VecDeque::new();
|
||||
expected.push_back(0..30);
|
||||
assert_eq!(expected, split_request_range(range));
|
||||
|
||||
let range = 0..60;
|
||||
let mut expected = VecDeque::new();
|
||||
expected.push_back(0..30);
|
||||
expected.push_back(30..60);
|
||||
assert_eq!(expected, split_request_range(range));
|
||||
|
||||
let range = 0..5;
|
||||
let mut expected = VecDeque::new();
|
||||
expected.push_back(0..5);
|
||||
assert_eq!(expected, split_request_range(range));
|
||||
|
||||
let range = 123..200;
|
||||
let mut expected = VecDeque::new();
|
||||
expected.push_back(123..153);
|
||||
expected.push_back(153..183);
|
||||
expected.push_back(183..200);
|
||||
assert_eq!(expected, split_request_range(range));
|
||||
}
|
||||
}
|
||||
@@ -1,332 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::block_processor::helpers::split_request_range;
|
||||
use crate::block_processor::types::BlockToProcess;
|
||||
use crate::block_requester::BlockRequest;
|
||||
use crate::error::ScraperError;
|
||||
use crate::modules::{BlockModule, MsgModule, TxModule};
|
||||
use crate::rpc_client::RpcClient;
|
||||
use crate::storage::{persist_block, ScraperStorage};
|
||||
use futures::StreamExt;
|
||||
use std::collections::{BTreeMap, HashSet, VecDeque};
|
||||
use std::ops::{Add, Range};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tokio::sync::mpsc::{Sender, UnboundedReceiver};
|
||||
use tokio::sync::Notify;
|
||||
use tokio::time::{interval_at, Instant};
|
||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tracing::{debug, error, info, warn};
|
||||
|
||||
mod helpers;
|
||||
pub(crate) mod types;
|
||||
|
||||
const MISSING_BLOCKS_CHECK_INTERVAL: Duration = Duration::from_secs(30);
|
||||
const MAX_MISSING_BLOCKS_DELAY: Duration = Duration::from_secs(15);
|
||||
const MAX_RANGE_SIZE: usize = 30;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct PendingSync {
|
||||
request_in_flight: HashSet<u32>,
|
||||
queued_requests: VecDeque<Range<u32>>,
|
||||
}
|
||||
|
||||
impl PendingSync {
|
||||
fn is_empty(&self) -> bool {
|
||||
self.request_in_flight.is_empty() && self.queued_requests.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BlockProcessor {
|
||||
cancel: CancellationToken,
|
||||
synced: Arc<Notify>,
|
||||
last_processed_height: u32,
|
||||
last_processed_at: Instant,
|
||||
pending_sync: PendingSync,
|
||||
queued_blocks: BTreeMap<u32, BlockToProcess>,
|
||||
|
||||
rpc_client: RpcClient,
|
||||
incoming: UnboundedReceiverStream<BlockToProcess>,
|
||||
block_requester: Sender<BlockRequest>,
|
||||
storage: ScraperStorage,
|
||||
|
||||
// future work: rather than sending each msg to every msg module,
|
||||
// let them subscribe based on `type_url` inside the message itself
|
||||
// (like "/cosmwasm.wasm.v1.MsgExecuteContract")
|
||||
block_modules: Vec<Box<dyn BlockModule + Send>>,
|
||||
tx_modules: Vec<Box<dyn TxModule + Send>>,
|
||||
msg_modules: Vec<Box<dyn MsgModule + Send>>,
|
||||
}
|
||||
|
||||
impl BlockProcessor {
|
||||
pub async fn new(
|
||||
cancel: CancellationToken,
|
||||
synced: Arc<Notify>,
|
||||
incoming: UnboundedReceiver<BlockToProcess>,
|
||||
block_requester: Sender<BlockRequest>,
|
||||
storage: ScraperStorage,
|
||||
rpc_client: RpcClient,
|
||||
) -> Result<Self, ScraperError> {
|
||||
let last_processed = storage.get_last_processed_height().await?;
|
||||
|
||||
Ok(BlockProcessor {
|
||||
cancel,
|
||||
synced,
|
||||
last_processed_height: last_processed.try_into().unwrap_or_default(),
|
||||
last_processed_at: Instant::now(),
|
||||
pending_sync: Default::default(),
|
||||
queued_blocks: Default::default(),
|
||||
rpc_client,
|
||||
incoming: incoming.into(),
|
||||
block_requester,
|
||||
storage,
|
||||
block_modules: vec![],
|
||||
tx_modules: vec![],
|
||||
msg_modules: vec![],
|
||||
})
|
||||
}
|
||||
|
||||
async fn process_block(&mut self, block: BlockToProcess) -> Result<(), ScraperError> {
|
||||
info!("processing block at height {}", block.height);
|
||||
|
||||
let full_info = self.rpc_client.try_get_full_details(block).await?;
|
||||
|
||||
debug!(
|
||||
"this block has {} transaction(s)",
|
||||
full_info.transactions.len()
|
||||
);
|
||||
for tx in &full_info.transactions {
|
||||
debug!("{} has {} message(s)", tx.hash, tx.tx.body.messages.len());
|
||||
for (index, msg) in tx.tx.body.messages.iter().enumerate() {
|
||||
debug!("{index}: {:?}", msg.type_url)
|
||||
}
|
||||
}
|
||||
|
||||
// process the entire block as a transaction so that if anything fails,
|
||||
// we won't end up with a corrupted storage.
|
||||
let mut tx = self.storage.begin_processing_tx().await?;
|
||||
|
||||
persist_block(&full_info, &mut tx).await?;
|
||||
|
||||
// let the modules do whatever they want
|
||||
// the ones wanting the full block:
|
||||
for block_module in &mut self.block_modules {
|
||||
block_module.handle_block(&full_info, &mut tx).await?;
|
||||
}
|
||||
|
||||
// the ones wanting transactions:
|
||||
for block_tx in full_info.transactions {
|
||||
for tx_module in &mut self.tx_modules {
|
||||
tx_module.handle_tx(&block_tx, &mut tx).await?;
|
||||
}
|
||||
// the ones concerned with individual messages
|
||||
for (index, msg) in block_tx.tx.body.messages.iter().enumerate() {
|
||||
for msg_module in &mut self.msg_modules {
|
||||
msg_module
|
||||
.handle_msg(index, msg, &block_tx, &mut tx)
|
||||
.await?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tx.commit()
|
||||
.await
|
||||
.map_err(|source| ScraperError::StorageTxCommitFailure { source })?;
|
||||
|
||||
self.last_processed_height = full_info.block.header.height.value() as u32;
|
||||
self.last_processed_at = Instant::now();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_block_modules(&mut self, modules: Vec<Box<dyn BlockModule + Send>>) {
|
||||
self.block_modules = modules;
|
||||
}
|
||||
|
||||
pub fn set_tx_modules(&mut self, modules: Vec<Box<dyn TxModule + Send>>) {
|
||||
self.tx_modules = modules;
|
||||
}
|
||||
|
||||
pub fn set_msg_modules(&mut self, modules: Vec<Box<dyn MsgModule + Send>>) {
|
||||
self.msg_modules = modules;
|
||||
}
|
||||
|
||||
async fn maybe_request_missing_blocks(&mut self) -> Result<(), ScraperError> {
|
||||
// we're still processing, so we're good
|
||||
if self.last_processed_at.elapsed() < MAX_MISSING_BLOCKS_DELAY {
|
||||
debug!("no need to request missing blocks");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if self.try_request_pending().await {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// TODO: properly fill in the gaps later with BlockRequest::Specific,
|
||||
let request_range = if let Some((next_available, _)) = self.queued_blocks.first_key_value()
|
||||
{
|
||||
self.last_processed_height + 1..*next_available
|
||||
} else {
|
||||
let current_height = self.rpc_client.current_block_height().await? as u32;
|
||||
self.last_processed_height + 1..current_height + 1
|
||||
};
|
||||
|
||||
self.request_missing_blocks(request_range).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn request_missing_blocks(
|
||||
&mut self,
|
||||
request_range: Range<u32>,
|
||||
) -> Result<(), ScraperError> {
|
||||
let request_range = if request_range.len() > MAX_RANGE_SIZE {
|
||||
let mut split = split_request_range(request_range);
|
||||
|
||||
// SAFETY: we know that after the split of a non-empty range we have AT LEAST one value
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let first = split.pop_front().unwrap();
|
||||
self.pending_sync.queued_requests = split;
|
||||
self.pending_sync.request_in_flight = first.clone().collect();
|
||||
|
||||
first
|
||||
} else {
|
||||
request_range
|
||||
};
|
||||
|
||||
self.send_blocks_request(request_range).await
|
||||
}
|
||||
|
||||
// technically we're not mutating self here,
|
||||
// but we need it to help the compiler figure out the future is `Send`
|
||||
async fn send_blocks_request(&mut self, request_range: Range<u32>) -> Result<(), ScraperError> {
|
||||
debug!("requesting missing blocks: {request_range:?}");
|
||||
|
||||
self.block_requester
|
||||
.send(BlockRequest::Range(request_range))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn next_incoming(&mut self, block: BlockToProcess) {
|
||||
let height = block.height;
|
||||
|
||||
self.pending_sync.request_in_flight.remove(&height);
|
||||
|
||||
if self.last_processed_height == 0 {
|
||||
// this is the first time we've started up the process
|
||||
debug!("setting up initial processing height");
|
||||
self.last_processed_height = height - 1
|
||||
}
|
||||
|
||||
if height <= self.last_processed_height {
|
||||
warn!("we have already processed block for height {height}");
|
||||
return;
|
||||
}
|
||||
|
||||
if self.last_processed_height + 1 != height {
|
||||
if self.queued_blocks.insert(height, block).is_some() {
|
||||
warn!("we have already queued up block for height {height}");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if let Err(err) = self.process_block(block).await {
|
||||
error!("failed to process block at height {height}: {err}");
|
||||
return;
|
||||
}
|
||||
|
||||
// process as much as we can from the queue
|
||||
let mut next = height + 1;
|
||||
while let Some(next_block) = self.queued_blocks.remove(&next) {
|
||||
if let Err(err) = self.process_block(next_block).await {
|
||||
error!("failed to process queued-up block at height {next}: {err}")
|
||||
}
|
||||
next += 1;
|
||||
}
|
||||
|
||||
self.try_request_pending().await;
|
||||
|
||||
if self.pending_sync.is_empty() {
|
||||
self.synced.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
async fn try_request_pending(&mut self) -> bool {
|
||||
if self.pending_sync.request_in_flight.is_empty() {
|
||||
if let Some(next_sync) = self.pending_sync.queued_requests.pop_front() {
|
||||
debug!(
|
||||
"current request range has been resolved. requesting another bunch of blocks"
|
||||
);
|
||||
if let Err(err) = self.send_blocks_request(next_sync.clone()).await {
|
||||
error!("failed to request resync blocks: {err}");
|
||||
self.pending_sync.queued_requests.push_front(next_sync);
|
||||
} else {
|
||||
self.pending_sync.request_in_flight = next_sync.collect()
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
// technically we're not mutating self here,
|
||||
// but we need it to help the compiler figure out the future is `Send`
|
||||
async fn startup_resync(&mut self) -> Result<(), ScraperError> {
|
||||
assert!(self.pending_sync.is_empty());
|
||||
|
||||
let latest_block = self.rpc_client.current_block_height().await? as u32;
|
||||
if latest_block > self.last_processed_height && self.last_processed_height != 0 {
|
||||
let request_range = self.last_processed_height + 1..latest_block + 1;
|
||||
info!("we need to request {request_range:?} to resync");
|
||||
self.request_missing_blocks(request_range).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn run(&mut self) {
|
||||
info!("starting processing loop");
|
||||
|
||||
// sure, we could be more efficient and reset it on every processed block,
|
||||
// but the overhead is so minimal that it doesn't matter
|
||||
let mut missing_check_interval = interval_at(
|
||||
Instant::now().add(MISSING_BLOCKS_CHECK_INTERVAL),
|
||||
MISSING_BLOCKS_CHECK_INTERVAL,
|
||||
);
|
||||
|
||||
if let Err(err) = self.startup_resync().await {
|
||||
error!("failed to perform startup sync: {err}");
|
||||
self.cancel.cancel();
|
||||
return;
|
||||
};
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = self.cancel.cancelled() => {
|
||||
info!("received cancellation token");
|
||||
break
|
||||
}
|
||||
_ = missing_check_interval.tick() => {
|
||||
if let Err(err) = self.maybe_request_missing_blocks().await {
|
||||
error!("failed to request missing blocks: {err}")
|
||||
}
|
||||
}
|
||||
block = self.incoming.next() => {
|
||||
match block {
|
||||
Some(block) => self.next_incoming(block).await,
|
||||
None => {
|
||||
warn!("stopped receiving new blocks");
|
||||
self.cancel.cancel();
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::ScraperError;
|
||||
use crate::helpers;
|
||||
use tendermint::{abci, block, tx, Block, Hash};
|
||||
use tendermint_rpc::endpoint::{block as block_endpoint, block_results, validators};
|
||||
use tendermint_rpc::event::{Event, EventData};
|
||||
|
||||
// just get all everything out of tx::Response, but parse raw `tx` bytes
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ParsedTransactionResponse {
|
||||
/// The hash of the transaction.
|
||||
///
|
||||
/// Deserialized from a hex-encoded string (there is a discrepancy between
|
||||
/// the format used for the request and the format used for the response in
|
||||
/// the Tendermint RPC).
|
||||
pub hash: Hash,
|
||||
|
||||
pub height: block::Height,
|
||||
|
||||
pub index: u32,
|
||||
|
||||
pub tx_result: abci::types::ExecTxResult,
|
||||
|
||||
pub tx: cosmrs::tx::Tx,
|
||||
|
||||
pub proof: Option<tx::Proof>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FullBlockInformation {
|
||||
/// Basic block information, including its signers.
|
||||
pub block: Block,
|
||||
|
||||
/// All of the emitted events alongside any tx results.
|
||||
pub results: block_results::Response,
|
||||
|
||||
/// Validator set for this particular block
|
||||
pub validators: validators::Response,
|
||||
|
||||
/// Transaction results from this particular block
|
||||
pub transactions: Vec<ParsedTransactionResponse>,
|
||||
}
|
||||
|
||||
impl FullBlockInformation {
|
||||
pub fn ensure_proposer(&self) -> Result<(), ScraperError> {
|
||||
let block_proposer = self.block.header.proposer_address;
|
||||
if !self
|
||||
.validators
|
||||
.validators
|
||||
.iter()
|
||||
.any(|v| v.address == block_proposer)
|
||||
{
|
||||
let proposer = helpers::validator_consensus_address(block_proposer)?;
|
||||
return Err(ScraperError::BlockProposerNotInValidatorSet {
|
||||
height: self.block.header.height.value() as u32,
|
||||
proposer: proposer.to_string(),
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct BlockToProcess {
|
||||
pub(crate) height: u32,
|
||||
pub(crate) block: Block,
|
||||
}
|
||||
|
||||
impl From<Block> for BlockToProcess {
|
||||
fn from(block: Block) -> Self {
|
||||
BlockToProcess {
|
||||
height: block.header.height.value() as u32,
|
||||
block,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Event> for BlockToProcess {
|
||||
type Error = ScraperError;
|
||||
|
||||
fn try_from(event: Event) -> Result<Self, Self::Error> {
|
||||
let query = event.query.clone();
|
||||
|
||||
// TODO: we're losing `result_begin_block` and `result_end_block` here but maybe that's fine?
|
||||
let maybe_block = match event.data {
|
||||
// we don't care about `NewBlock` until CometBFT 0.38, i.e. until we upgrade to wasmd 0.50
|
||||
EventData::NewBlock { .. } => {
|
||||
return Err(ScraperError::InvalidSubscriptionEvent {
|
||||
query,
|
||||
kind: "NewBlock".to_string(),
|
||||
})
|
||||
}
|
||||
EventData::LegacyNewBlock { block, .. } => block,
|
||||
EventData::Tx { .. } => {
|
||||
return Err(ScraperError::InvalidSubscriptionEvent {
|
||||
query,
|
||||
kind: "Tx".to_string(),
|
||||
})
|
||||
}
|
||||
EventData::GenericJsonEvent(_) => {
|
||||
return Err(ScraperError::InvalidSubscriptionEvent {
|
||||
query,
|
||||
kind: "GenericJsonEvent".to_string(),
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
let Some(block) = maybe_block else {
|
||||
return Err(ScraperError::EmptyBlockData { query });
|
||||
};
|
||||
|
||||
Ok((*block).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<block_endpoint::Response> for BlockToProcess {
|
||||
fn from(value: block_endpoint::Response) -> Self {
|
||||
value.block.into()
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::block_processor::types::BlockToProcess;
|
||||
use crate::error::ScraperError;
|
||||
use crate::rpc_client::RpcClient;
|
||||
use futures::StreamExt;
|
||||
use std::ops::Range;
|
||||
use tokio::sync::mpsc::{Receiver, UnboundedSender};
|
||||
use tokio_stream::wrappers::ReceiverStream;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tracing::{error, info, instrument, warn};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BlockRequest {
|
||||
Range(Range<u32>),
|
||||
|
||||
// UNIMPLEMENTED:
|
||||
#[allow(dead_code)]
|
||||
Specific(Vec<u32>),
|
||||
}
|
||||
|
||||
pub(crate) struct BlockRequester {
|
||||
cancel: CancellationToken,
|
||||
rpc_client: RpcClient,
|
||||
requests: ReceiverStream<BlockRequest>,
|
||||
blocks: UnboundedSender<BlockToProcess>,
|
||||
}
|
||||
|
||||
impl BlockRequester {
|
||||
pub(crate) fn new(
|
||||
cancel: CancellationToken,
|
||||
rpc_client: RpcClient,
|
||||
requests: Receiver<BlockRequest>,
|
||||
blocks: UnboundedSender<BlockToProcess>,
|
||||
) -> Self {
|
||||
BlockRequester {
|
||||
cancel,
|
||||
rpc_client,
|
||||
requests: requests.into(),
|
||||
blocks,
|
||||
}
|
||||
}
|
||||
|
||||
async fn request_and_send(&self, height: u32) -> Result<(), ScraperError> {
|
||||
let block = self.rpc_client.get_basic_block_details(height).await?;
|
||||
self.blocks.send(block.into())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn request_blocks<I: IntoIterator<Item = u32>>(&self, heights: I) {
|
||||
futures::stream::iter(heights)
|
||||
.for_each_concurrent(4, |height| async move {
|
||||
if let Err(err) = self.request_and_send(height).await {
|
||||
error!("failed to request block data: {err}")
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(skip(self))]
|
||||
async fn handle_blocks_request(&self, request: BlockRequest) {
|
||||
info!("received request for missed blocks");
|
||||
|
||||
match request {
|
||||
BlockRequest::Range(range) => self.request_blocks(range).await,
|
||||
BlockRequest::Specific(heights) => self.request_blocks(heights).await,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn run(&mut self) {
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = self.cancel.cancelled() => {
|
||||
info!("received cancellation token");
|
||||
break
|
||||
}
|
||||
maybe_request = self.requests.next() => {
|
||||
match maybe_request {
|
||||
Some(request) => self.handle_blocks_request(request).await,
|
||||
None => {
|
||||
warn!("stopped receiving new requests");
|
||||
self.cancel.cancel();
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use const_format::concatcp;
|
||||
|
||||
// TODO: make those configurable via 'NymNetworkDetails'
|
||||
|
||||
// BECH32_PREFIX defines the main SDK Bech32 prefix of an account's address
|
||||
pub const BECH32_PREFIX: &str = "n";
|
||||
|
||||
// ACCOUNT_PREFIX is the prefix for account keys
|
||||
pub const ACCOUNT_PREFIX: &str = "acc";
|
||||
// VALIDATOR_PREFIX is the prefix for validator keys
|
||||
pub const VALIDATOR_PREFIX: &str = "val";
|
||||
// CONSENSUS_PREFIX is the prefix for consensus keys
|
||||
pub const CONSENSUS_PREFIX: &str = "cons";
|
||||
// PUBKEY_PREFIX is the prefix for public keys
|
||||
pub const PUBKEY_PREFIX: &str = "pub";
|
||||
// OPERATOR_PREFIX is the prefix for operator keys
|
||||
pub const OPERATOR_PREFIX: &str = "oper";
|
||||
// ADDRESS_PREFIX is the prefix for addresses
|
||||
pub const ADDRESS_PREFIX: &str = "addr";
|
||||
|
||||
// BECH32_ACCOUNT_ADDRESS_PREFIX defines the Bech32 prefix of an account's address
|
||||
pub const BECH32_ACCOUNT_ADDRESS_PREFIX: &str = BECH32_PREFIX;
|
||||
// BECH32_ACCOUNT_PUBKEY_PREFIX defines the Bech32 prefix of an account's public key
|
||||
pub const BECH32_ACCOUNT_PUBKEY_PREFIX: &str = concatcp!(BECH32_PREFIX, PUBKEY_PREFIX);
|
||||
// BECH32_VALIDATOR_ADDRESS_PREFIX defines the Bech32 prefix of a validator's operator address
|
||||
pub const BECH32_VALIDATOR_ADDRESS_PREFIX: &str =
|
||||
concatcp!(BECH32_PREFIX, VALIDATOR_PREFIX, OPERATOR_PREFIX);
|
||||
// BECH32_VALIDATOR_PUBKEY_PREFIX defines the Bech32 prefix of a validator's operator public key
|
||||
pub const BECH32_VALIDATOR_PUBKEY_PREFIX: &str = concatcp!(
|
||||
BECH32_PREFIX,
|
||||
VALIDATOR_PREFIX,
|
||||
OPERATOR_PREFIX,
|
||||
PUBKEY_PREFIX
|
||||
);
|
||||
// BECH32_CONSENSUS_ADDRESS_PREFIX defines the Bech32 prefix of a consensus node address
|
||||
pub const BECH32_CONSENSUS_ADDRESS_PREFIX: &str =
|
||||
concatcp!(BECH32_PREFIX, VALIDATOR_PREFIX, CONSENSUS_PREFIX);
|
||||
// BECH32_CONESNSUS_PUBKEY_PREFIX defines the Bech32 prefix of a consensus node public key
|
||||
pub const BECH32_CONESNSUS_PUBKEY_PREFIX: &str = concatcp!(
|
||||
BECH32_PREFIX,
|
||||
VALIDATOR_PREFIX,
|
||||
CONSENSUS_PREFIX,
|
||||
PUBKEY_PREFIX
|
||||
);
|
||||
@@ -1,131 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use tendermint::Hash;
|
||||
use thiserror::Error;
|
||||
use tokio::sync::mpsc::error::SendError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ScraperError {
|
||||
#[error("experienced internal database error: {0}")]
|
||||
InternalDatabaseError(#[from] sqlx::Error),
|
||||
|
||||
#[error("failed to perform startup SQL migration: {0}")]
|
||||
StartupMigrationFailure(#[from] sqlx::migrate::MigrateError),
|
||||
|
||||
#[error("can't add any modules to the scraper as it's already running")]
|
||||
ScraperAlreadyRunning,
|
||||
|
||||
#[error("failed to establish websocket connection to {url}: {source}")]
|
||||
WebSocketConnectionFailure {
|
||||
url: String,
|
||||
#[source]
|
||||
source: tendermint_rpc::Error,
|
||||
},
|
||||
|
||||
#[error("failed to establish rpc connection to {url}: {source}")]
|
||||
HttpConnectionFailure {
|
||||
url: String,
|
||||
#[source]
|
||||
source: tendermint_rpc::Error,
|
||||
},
|
||||
|
||||
#[error("failed to create chain subscription: {source}")]
|
||||
ChainSubscriptionFailure {
|
||||
#[source]
|
||||
source: tendermint_rpc::Error,
|
||||
},
|
||||
|
||||
#[error("could not obtain basic block information at height: {height}: {source}")]
|
||||
BlockQueryFailure {
|
||||
height: u32,
|
||||
#[source]
|
||||
source: tendermint_rpc::Error,
|
||||
},
|
||||
|
||||
#[error("could not obtain block results information at height: {height}: {source}")]
|
||||
BlockResultsQueryFailure {
|
||||
height: u32,
|
||||
#[source]
|
||||
source: tendermint_rpc::Error,
|
||||
},
|
||||
|
||||
#[error("could not obtain validators information at height: {height}: {source}")]
|
||||
ValidatorsQueryFailure {
|
||||
height: u32,
|
||||
#[source]
|
||||
source: tendermint_rpc::Error,
|
||||
},
|
||||
|
||||
#[error("could not obtain tx results for tx: {hash}: {source}")]
|
||||
TxResultsQueryFailure {
|
||||
hash: Hash,
|
||||
#[source]
|
||||
source: tendermint_rpc::Error,
|
||||
},
|
||||
|
||||
#[error("could not obtain current abci info: {source}")]
|
||||
AbciInfoQueryFailure {
|
||||
#[source]
|
||||
source: tendermint_rpc::Error,
|
||||
},
|
||||
|
||||
#[error("could not parse tx {hash}: {source}")]
|
||||
TxParseFailure {
|
||||
hash: Hash,
|
||||
#[source]
|
||||
source: cosmrs::ErrorReport,
|
||||
},
|
||||
|
||||
#[error("received an invalid chain subscription event of kind {kind} while we were waiting for new block data (query: '{query}')")]
|
||||
InvalidSubscriptionEvent { query: String, kind: String },
|
||||
|
||||
#[error("received block data was empty (query: '{query}')")]
|
||||
EmptyBlockData { query: String },
|
||||
|
||||
#[error("reached maximum number of allowed errors for subscription events")]
|
||||
MaximumSubscriptionFailures,
|
||||
|
||||
#[error("failed to begin storage tx: {source}")]
|
||||
StorageTxBeginFailure {
|
||||
#[source]
|
||||
source: sqlx::Error,
|
||||
},
|
||||
|
||||
#[error("failed to commit storage tx: {source}")]
|
||||
StorageTxCommitFailure {
|
||||
#[source]
|
||||
source: sqlx::Error,
|
||||
},
|
||||
|
||||
#[error("failed to send on a closed channel")]
|
||||
ClosedChannelError,
|
||||
|
||||
#[error("failed to parse validator's address: {source}")]
|
||||
MalformedValidatorAddress {
|
||||
#[source]
|
||||
source: eyre::Report,
|
||||
},
|
||||
|
||||
#[error("failed to parse validator's address: {source}")]
|
||||
MalformedValidatorPubkey {
|
||||
#[source]
|
||||
source: eyre::Report,
|
||||
},
|
||||
|
||||
#[error(
|
||||
"could not find the block proposer ('{proposer}') for height {height} in the validator set"
|
||||
)]
|
||||
BlockProposerNotInValidatorSet { height: u32, proposer: String },
|
||||
|
||||
#[error(
|
||||
"could not find validator information for {address}; the validator has signed a commit"
|
||||
)]
|
||||
MissingValidatorInfoCommitted { address: String },
|
||||
}
|
||||
|
||||
impl<T> From<SendError<T>> for ScraperError {
|
||||
fn from(_: SendError<T>) -> Self {
|
||||
ScraperError::ClosedChannelError
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::block_processor::types::ParsedTransactionResponse;
|
||||
use crate::constants::{BECH32_CONESNSUS_PUBKEY_PREFIX, BECH32_CONSENSUS_ADDRESS_PREFIX};
|
||||
use crate::error::ScraperError;
|
||||
use cosmrs::AccountId;
|
||||
use sha2::{Digest, Sha256};
|
||||
use tendermint::{account, PublicKey};
|
||||
use tendermint::{validator, Hash};
|
||||
use tendermint_rpc::endpoint::validators;
|
||||
|
||||
pub(crate) fn tx_hash<M: AsRef<[u8]>>(raw_tx: M) -> Hash {
|
||||
Hash::Sha256(Sha256::digest(raw_tx).into())
|
||||
}
|
||||
|
||||
pub(crate) fn validator_pubkey_to_bech32(pubkey: PublicKey) -> Result<AccountId, ScraperError> {
|
||||
// TODO: this one seem to attach additional prefix to they pubkeys, is that what we want instead maybe?
|
||||
// Ok(pubkey.to_bech32(BECH32_CONESNSUS_PUBKEY_PREFIX))
|
||||
AccountId::new(BECH32_CONESNSUS_PUBKEY_PREFIX, &pubkey.to_bytes())
|
||||
.map_err(|source| ScraperError::MalformedValidatorPubkey { source })
|
||||
}
|
||||
|
||||
pub(crate) fn validator_consensus_address(id: account::Id) -> Result<AccountId, ScraperError> {
|
||||
AccountId::new(BECH32_CONSENSUS_ADDRESS_PREFIX, id.as_ref())
|
||||
.map_err(|source| ScraperError::MalformedValidatorAddress { source })
|
||||
}
|
||||
|
||||
pub(crate) fn tx_gas_sum(txs: &[ParsedTransactionResponse]) -> i64 {
|
||||
txs.iter().map(|tx| tx.tx_result.gas_used).sum()
|
||||
}
|
||||
|
||||
pub(crate) fn validator_info(
|
||||
id: account::Id,
|
||||
validators: &validators::Response,
|
||||
) -> Result<&validator::Info, ScraperError> {
|
||||
match validators.validators.iter().find(|v| v.address == id) {
|
||||
Some(info) => Ok(info),
|
||||
None => {
|
||||
let addr = validator_consensus_address(id)?;
|
||||
Err(ScraperError::MissingValidatorInfoCommitted {
|
||||
address: addr.to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#![warn(clippy::expect_used)]
|
||||
#![warn(clippy::unwrap_used)]
|
||||
|
||||
pub(crate) mod block_processor;
|
||||
pub(crate) mod block_requester;
|
||||
pub mod constants;
|
||||
pub mod error;
|
||||
pub(crate) mod helpers;
|
||||
pub mod modules;
|
||||
pub(crate) mod rpc_client;
|
||||
pub(crate) mod scraper;
|
||||
pub mod storage;
|
||||
|
||||
pub use modules::{BlockModule, MsgModule, TxModule};
|
||||
pub use scraper::{Config, NyxdScraper};
|
||||
pub use storage::models;
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::block_processor::types::FullBlockInformation;
|
||||
use crate::error::ScraperError;
|
||||
use crate::storage::StorageTransaction;
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[async_trait]
|
||||
pub trait BlockModule {
|
||||
async fn handle_block(
|
||||
&mut self,
|
||||
block: &FullBlockInformation,
|
||||
storage_tx: &mut StorageTransaction,
|
||||
) -> Result<(), ScraperError>;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
mod block_module;
|
||||
mod msg_module;
|
||||
mod tx_module;
|
||||
|
||||
pub use block_module::BlockModule;
|
||||
pub use msg_module::MsgModule;
|
||||
pub use tx_module::TxModule;
|
||||
@@ -1,19 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::block_processor::types::ParsedTransactionResponse;
|
||||
use crate::error::ScraperError;
|
||||
use crate::storage::StorageTransaction;
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::Any;
|
||||
|
||||
#[async_trait]
|
||||
pub trait MsgModule {
|
||||
async fn handle_msg(
|
||||
&mut self,
|
||||
index: usize,
|
||||
msg: &Any,
|
||||
tx: &ParsedTransactionResponse,
|
||||
storage_tx: &mut StorageTransaction,
|
||||
) -> Result<(), ScraperError>;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::block_processor::types::ParsedTransactionResponse;
|
||||
use crate::error::ScraperError;
|
||||
use crate::storage::StorageTransaction;
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[async_trait]
|
||||
pub trait TxModule {
|
||||
async fn handle_tx(
|
||||
&mut self,
|
||||
tx: &ParsedTransactionResponse,
|
||||
storage_tx: &mut StorageTransaction,
|
||||
) -> Result<(), ScraperError>;
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::block_processor::types::{
|
||||
BlockToProcess, FullBlockInformation, ParsedTransactionResponse,
|
||||
};
|
||||
use crate::error::ScraperError;
|
||||
use crate::helpers::tx_hash;
|
||||
use futures::future::join3;
|
||||
use futures::StreamExt;
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::Arc;
|
||||
use tendermint::Hash;
|
||||
use tendermint_rpc::endpoint::{block, block_results, tx, validators};
|
||||
use tendermint_rpc::{Client, HttpClient, Paging};
|
||||
use tokio::sync::Mutex;
|
||||
use tracing::{debug, instrument};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RpcClient {
|
||||
// right now I don't care about anything nym specific, so a simple http client is sufficient,
|
||||
// once this is inadequate, we can switch to a NyxdClient
|
||||
inner: Arc<HttpClient>,
|
||||
}
|
||||
|
||||
impl RpcClient {
|
||||
pub fn new(url: &Url) -> Result<Self, ScraperError> {
|
||||
let http_client = HttpClient::new(url.as_str()).map_err(|source| {
|
||||
ScraperError::HttpConnectionFailure {
|
||||
url: url.to_string(),
|
||||
source,
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(RpcClient {
|
||||
inner: Arc::new(http_client),
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(skip(self, block), fields(height = block.height))]
|
||||
pub async fn try_get_full_details(
|
||||
&self,
|
||||
block: BlockToProcess,
|
||||
) -> Result<FullBlockInformation, ScraperError> {
|
||||
debug!("getting complete block details");
|
||||
let height = block.height;
|
||||
|
||||
// make all the http requests concurrently
|
||||
let (results, validators, raw_transactions) = join3(
|
||||
self.get_block_results(height),
|
||||
self.get_validators_details(height),
|
||||
self.get_transaction_results(&block.block.data),
|
||||
)
|
||||
.await;
|
||||
|
||||
let raw_transactions = raw_transactions?;
|
||||
let mut transactions = Vec::with_capacity(raw_transactions.len());
|
||||
for tx in raw_transactions {
|
||||
transactions.push(ParsedTransactionResponse {
|
||||
hash: tx.hash,
|
||||
height: tx.height,
|
||||
index: tx.index,
|
||||
tx_result: tx.tx_result,
|
||||
tx: cosmrs::Tx::from_bytes(&tx.tx).map_err(|source| {
|
||||
ScraperError::TxParseFailure {
|
||||
hash: tx.hash,
|
||||
source,
|
||||
}
|
||||
})?,
|
||||
proof: tx.proof,
|
||||
})
|
||||
}
|
||||
|
||||
Ok(FullBlockInformation {
|
||||
block: block.block,
|
||||
results: results?,
|
||||
validators: validators?,
|
||||
transactions,
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(skip(self), err(Display))]
|
||||
pub async fn get_basic_block_details(
|
||||
&self,
|
||||
height: u32,
|
||||
) -> Result<block::Response, ScraperError> {
|
||||
debug!("getting basic block details");
|
||||
|
||||
self.inner
|
||||
.block(height)
|
||||
.await
|
||||
.map_err(|source| ScraperError::BlockQueryFailure { height, source })
|
||||
}
|
||||
|
||||
#[instrument(skip(self), err(Display))]
|
||||
pub async fn get_block_results(
|
||||
&self,
|
||||
height: u32,
|
||||
) -> Result<block_results::Response, ScraperError> {
|
||||
debug!("getting block results");
|
||||
|
||||
self.inner
|
||||
.block_results(height)
|
||||
.await
|
||||
.map_err(|source| ScraperError::BlockResultsQueryFailure { height, source })
|
||||
}
|
||||
|
||||
pub(crate) async fn current_block_height(&self) -> Result<u64, ScraperError> {
|
||||
debug!("getting current block height");
|
||||
|
||||
let info = self
|
||||
.inner
|
||||
.abci_info()
|
||||
.await
|
||||
.map_err(|source| ScraperError::AbciInfoQueryFailure { source })?;
|
||||
Ok(info.last_block_height.value())
|
||||
}
|
||||
|
||||
async fn get_transaction_results(
|
||||
&self,
|
||||
raw: &[Vec<u8>],
|
||||
) -> Result<Vec<tx::Response>, ScraperError> {
|
||||
let ordered_results = Arc::new(Mutex::new(BTreeMap::new()));
|
||||
|
||||
// "Data is just a wrapper for a list of transactions, where transactions are arbitrary byte arrays"
|
||||
// source: https://github.com/tendermint/spec/blob/d46cd7f573a2c6a2399fcab2cde981330aa63f37/spec/core/data_structures.md#data
|
||||
//
|
||||
// I hate that zip as much as you, dear reader, but for some reason the compiler didn't let me remove the `move`
|
||||
futures::stream::iter(
|
||||
raw.iter()
|
||||
.map(tx_hash)
|
||||
.enumerate()
|
||||
.zip(std::iter::repeat(ordered_results.clone())),
|
||||
)
|
||||
.for_each_concurrent(4, |((id, tx_hash), ordered_results)| async move {
|
||||
let res = self.get_transaction_result(tx_hash).await;
|
||||
ordered_results.lock().await.insert(id, res);
|
||||
})
|
||||
.await;
|
||||
|
||||
// safety the futures have completed so we MUST have the only arc reference
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let inner = Arc::into_inner(ordered_results).unwrap().into_inner();
|
||||
|
||||
// BTreeMap is ordered by its keys so we're guaranteed to get txs in correct order
|
||||
inner.into_values().collect()
|
||||
}
|
||||
|
||||
#[instrument(skip(self, tx_hash), fields(tx_hash = %tx_hash), err(Display))]
|
||||
async fn get_transaction_result(&self, tx_hash: Hash) -> Result<tx::Response, ScraperError> {
|
||||
debug!("getting tx results");
|
||||
|
||||
self.inner
|
||||
.tx(tx_hash, false)
|
||||
.await
|
||||
.map_err(|source| ScraperError::TxResultsQueryFailure {
|
||||
hash: tx_hash,
|
||||
source,
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument(skip(self))]
|
||||
pub async fn get_validators_details(
|
||||
&self,
|
||||
height: u32,
|
||||
) -> Result<validators::Response, ScraperError> {
|
||||
debug!("getting validators set");
|
||||
|
||||
self.inner
|
||||
.validators(height, Paging::All)
|
||||
.await
|
||||
.map_err(|source| ScraperError::ValidatorsQueryFailure { height, source })
|
||||
}
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::block_processor::BlockProcessor;
|
||||
use crate::block_requester::BlockRequester;
|
||||
use crate::error::ScraperError;
|
||||
use crate::modules::{BlockModule, MsgModule, TxModule};
|
||||
use crate::rpc_client::RpcClient;
|
||||
use crate::scraper::subscriber::{run_websocket_driver, ChainSubscriber};
|
||||
use crate::storage::ScraperStorage;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use tendermint_rpc::WebSocketClientDriver;
|
||||
use tokio::sync::mpsc::{channel, unbounded_channel};
|
||||
use tokio::sync::Notify;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tokio_util::task::TaskTracker;
|
||||
use tracing::info;
|
||||
use url::Url;
|
||||
|
||||
mod subscriber;
|
||||
|
||||
pub struct Config {
|
||||
/// Url to the websocket endpoint of a validator, for example `wss://rpc.nymtech.net/websocket`
|
||||
pub websocket_url: Url,
|
||||
|
||||
/// Url to the rpc endpoint of a validator, for example `https://rpc.nymtech.net/`
|
||||
pub rpc_url: Url,
|
||||
|
||||
pub database_path: PathBuf,
|
||||
}
|
||||
|
||||
pub struct NyxdScraperBuilder {
|
||||
config: Config,
|
||||
|
||||
block_modules: Vec<Box<dyn BlockModule + Send>>,
|
||||
tx_modules: Vec<Box<dyn TxModule + Send>>,
|
||||
msg_modules: Vec<Box<dyn MsgModule + Send>>,
|
||||
}
|
||||
|
||||
impl NyxdScraperBuilder {
|
||||
pub async fn build_and_start(self) -> Result<NyxdScraper, ScraperError> {
|
||||
let scraper = NyxdScraper::new(self.config).await?;
|
||||
|
||||
let (processing_tx, processing_rx) = unbounded_channel();
|
||||
let (req_tx, req_rx) = channel(5);
|
||||
|
||||
let rpc_client = RpcClient::new(&scraper.config.rpc_url)?;
|
||||
|
||||
// create the tasks
|
||||
let block_requester = BlockRequester::new(
|
||||
scraper.cancel_token.clone(),
|
||||
rpc_client.clone(),
|
||||
req_rx,
|
||||
processing_tx.clone(),
|
||||
);
|
||||
let mut block_processor = BlockProcessor::new(
|
||||
scraper.cancel_token.clone(),
|
||||
scraper.startup_sync.clone(),
|
||||
processing_rx,
|
||||
req_tx,
|
||||
scraper.storage.clone(),
|
||||
rpc_client,
|
||||
)
|
||||
.await?;
|
||||
block_processor.set_block_modules(self.block_modules);
|
||||
block_processor.set_tx_modules(self.tx_modules);
|
||||
block_processor.set_msg_modules(self.msg_modules);
|
||||
|
||||
let mut chain_subscriber = ChainSubscriber::new(
|
||||
&scraper.config.websocket_url,
|
||||
scraper.cancel_token.clone(),
|
||||
processing_tx,
|
||||
)
|
||||
.await?;
|
||||
let ws_driver = chain_subscriber.ws_driver();
|
||||
|
||||
scraper.start_tasks(
|
||||
block_requester,
|
||||
block_processor,
|
||||
chain_subscriber,
|
||||
ws_driver,
|
||||
);
|
||||
|
||||
Ok(scraper)
|
||||
}
|
||||
|
||||
pub fn new(config: Config) -> Self {
|
||||
NyxdScraperBuilder {
|
||||
config,
|
||||
block_modules: vec![],
|
||||
tx_modules: vec![],
|
||||
msg_modules: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_block_module<M: BlockModule + Send + 'static>(mut self, module: M) -> Self {
|
||||
self.block_modules.push(Box::new(module));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_tx_module<M: TxModule + Send + 'static>(mut self, module: M) -> Self {
|
||||
self.tx_modules.push(Box::new(module));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_msg_module<M: MsgModule + Send + 'static>(mut self, module: M) -> Self {
|
||||
self.msg_modules.push(Box::new(module));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NyxdScraper {
|
||||
config: Config,
|
||||
|
||||
task_tracker: TaskTracker,
|
||||
cancel_token: CancellationToken,
|
||||
startup_sync: Arc<Notify>,
|
||||
pub storage: ScraperStorage,
|
||||
}
|
||||
|
||||
impl NyxdScraper {
|
||||
pub fn builder(config: Config) -> NyxdScraperBuilder {
|
||||
NyxdScraperBuilder::new(config)
|
||||
}
|
||||
|
||||
pub async fn new(config: Config) -> Result<Self, ScraperError> {
|
||||
let storage = ScraperStorage::init(&config.database_path).await?;
|
||||
|
||||
Ok(NyxdScraper {
|
||||
config,
|
||||
task_tracker: TaskTracker::new(),
|
||||
cancel_token: CancellationToken::new(),
|
||||
startup_sync: Arc::new(Default::default()),
|
||||
storage,
|
||||
})
|
||||
}
|
||||
|
||||
fn start_tasks(
|
||||
&self,
|
||||
mut block_requester: BlockRequester,
|
||||
mut block_processor: BlockProcessor,
|
||||
mut chain_subscriber: ChainSubscriber,
|
||||
ws_driver: WebSocketClientDriver,
|
||||
) {
|
||||
self.task_tracker
|
||||
.spawn(async move { block_requester.run().await });
|
||||
self.task_tracker
|
||||
.spawn(async move { block_processor.run().await });
|
||||
self.task_tracker
|
||||
.spawn(async move { chain_subscriber.run().await });
|
||||
self.task_tracker
|
||||
.spawn(run_websocket_driver(ws_driver, self.cancel_token.clone()));
|
||||
self.task_tracker.close();
|
||||
}
|
||||
|
||||
pub async fn start(&self) -> Result<(), ScraperError> {
|
||||
let (processing_tx, processing_rx) = unbounded_channel();
|
||||
let (req_tx, req_rx) = channel(5);
|
||||
|
||||
let rpc_client = RpcClient::new(&self.config.rpc_url)?;
|
||||
|
||||
// create the tasks
|
||||
let block_requester = BlockRequester::new(
|
||||
self.cancel_token.clone(),
|
||||
rpc_client.clone(),
|
||||
req_rx,
|
||||
processing_tx.clone(),
|
||||
);
|
||||
let block_processor = BlockProcessor::new(
|
||||
self.cancel_token.clone(),
|
||||
self.startup_sync.clone(),
|
||||
processing_rx,
|
||||
req_tx,
|
||||
self.storage.clone(),
|
||||
rpc_client,
|
||||
)
|
||||
.await?;
|
||||
let mut chain_subscriber = ChainSubscriber::new(
|
||||
&self.config.websocket_url,
|
||||
self.cancel_token.clone(),
|
||||
processing_tx,
|
||||
)
|
||||
.await?;
|
||||
let ws_driver = chain_subscriber.ws_driver();
|
||||
|
||||
// spawn them
|
||||
self.start_tasks(
|
||||
block_requester,
|
||||
block_processor,
|
||||
chain_subscriber,
|
||||
ws_driver,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn wait_for_startup_sync(&self) {
|
||||
info!("awaiting startup chain sync");
|
||||
self.startup_sync.notified().await
|
||||
}
|
||||
|
||||
pub async fn stop(self) {
|
||||
info!("stopping the chain scrapper");
|
||||
assert!(self.task_tracker.is_closed());
|
||||
|
||||
self.cancel_token.cancel();
|
||||
self.task_tracker.wait().await
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::block_processor::types::BlockToProcess;
|
||||
use crate::error::ScraperError;
|
||||
use tendermint_rpc::event::Event;
|
||||
use tendermint_rpc::query::EventType;
|
||||
use tendermint_rpc::{SubscriptionClient, WebSocketClient, WebSocketClientDriver};
|
||||
use tokio::sync::mpsc::UnboundedSender;
|
||||
use tokio_stream::StreamExt;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tracing::{error, info, warn};
|
||||
use url::Url;
|
||||
|
||||
const MAX_FAILURES: usize = 10;
|
||||
|
||||
pub struct ChainSubscriber {
|
||||
cancel: CancellationToken,
|
||||
block_sender: UnboundedSender<BlockToProcess>,
|
||||
|
||||
websocket_client: WebSocketClient,
|
||||
websocket_driver: Option<WebSocketClientDriver>,
|
||||
}
|
||||
|
||||
impl ChainSubscriber {
|
||||
pub async fn new(
|
||||
websocket_endpoint: &Url,
|
||||
cancel: CancellationToken,
|
||||
block_sender: UnboundedSender<BlockToProcess>,
|
||||
) -> Result<Self, ScraperError> {
|
||||
// sure, we could have just used websocket client entirely, but let's keep the logic for
|
||||
// getting current blocks and historical blocks completely separate with the dual connection
|
||||
let (client, driver) = WebSocketClient::new(websocket_endpoint.as_str())
|
||||
.await
|
||||
.map_err(|source| ScraperError::WebSocketConnectionFailure {
|
||||
url: websocket_endpoint.to_string(),
|
||||
source,
|
||||
})?;
|
||||
|
||||
Ok(ChainSubscriber {
|
||||
cancel,
|
||||
block_sender,
|
||||
websocket_client: client,
|
||||
websocket_driver: Some(driver),
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_new_event(&mut self, event: Event) -> Result<(), ScraperError> {
|
||||
if let Err(err) = self.block_sender.send(event.try_into()?) {
|
||||
// this error has nothing to do with the websocket or chain
|
||||
error!("failed to send block for processing: {err} - are we shutting down?")
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn run(&mut self) -> Result<(), ScraperError> {
|
||||
let _drop_guard = self.cancel.clone().drop_guard();
|
||||
|
||||
info!("creating chain subscription");
|
||||
let mut subs = self
|
||||
.websocket_client
|
||||
.subscribe(EventType::NewBlock.into())
|
||||
.await
|
||||
.map_err(|source| ScraperError::ChainSubscriptionFailure { source })?;
|
||||
|
||||
let mut failures = 0;
|
||||
|
||||
info!("starting processing loop");
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = self.cancel.cancelled() => {
|
||||
info!("received cancellation token");
|
||||
break
|
||||
}
|
||||
maybe_event = subs.next() => {
|
||||
let Some(maybe_event) = maybe_event else {
|
||||
warn!("stopped receiving new events");
|
||||
break;
|
||||
};
|
||||
match maybe_event {
|
||||
Ok(event) => {
|
||||
if let Err(err) = self.handle_new_event(event) {
|
||||
error!("failed to process received block: {err}");
|
||||
failures += 1
|
||||
} else {
|
||||
failures = 0;
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
error!("failed to receive a valid subscription event: {err}");
|
||||
failures += 1
|
||||
}
|
||||
}
|
||||
if failures >= MAX_FAILURES {
|
||||
// note: the drop_guard will get dropped and thus cause a shutdown
|
||||
return Err(ScraperError::MaximumSubscriptionFailures);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn ws_driver(&mut self) -> WebSocketClientDriver {
|
||||
#[allow(clippy::expect_used)]
|
||||
self.websocket_driver
|
||||
.take()
|
||||
.expect("websocket driver has already been started!")
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run_websocket_driver(driver: WebSocketClientDriver, cancel: CancellationToken) {
|
||||
info!("starting websocket driver");
|
||||
tokio::select! {
|
||||
_ = cancel.cancelled() => {
|
||||
info!("received cancellation token")
|
||||
}
|
||||
res = driver.run() => {
|
||||
match res {
|
||||
Ok(_) => info!("our websocket driver has finished execution"),
|
||||
Err(err) => {
|
||||
// TODO: in the future just attempt to reconnect
|
||||
error!("our websocket driver has errored out: {err}")
|
||||
}
|
||||
}
|
||||
cancel.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
@@ -1,352 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::storage::models::{CommitSignature, Validator};
|
||||
use sqlx::types::time::OffsetDateTime;
|
||||
use sqlx::{Executor, Sqlite};
|
||||
use tracing::{instrument, trace};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct StorageManager {
|
||||
pub(crate) connection_pool: sqlx::SqlitePool,
|
||||
}
|
||||
|
||||
impl StorageManager {
|
||||
pub(crate) async fn set_initial_metadata(&self) -> Result<(), sqlx::Error> {
|
||||
if sqlx::query("SELECT * from metadata")
|
||||
.fetch_optional(&self.connection_pool)
|
||||
.await?
|
||||
.is_none()
|
||||
{
|
||||
sqlx::query("INSERT INTO metadata (id, last_processed_height) VALUES (0, 0)")
|
||||
.execute(&self.connection_pool)
|
||||
.await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn get_first_block_height_after(
|
||||
&self,
|
||||
time: OffsetDateTime,
|
||||
) -> Result<Option<i64>, sqlx::Error> {
|
||||
let maybe_record = sqlx::query!(
|
||||
r#"
|
||||
SELECT height
|
||||
FROM block
|
||||
WHERE timestamp > ?
|
||||
ORDER BY timestamp
|
||||
LIMIT 1
|
||||
"#,
|
||||
time
|
||||
)
|
||||
.fetch_optional(&self.connection_pool)
|
||||
.await?;
|
||||
|
||||
if let Some(row) = maybe_record {
|
||||
Ok(row.height)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn get_last_block_height_before(
|
||||
&self,
|
||||
time: OffsetDateTime,
|
||||
) -> Result<Option<i64>, sqlx::Error> {
|
||||
let maybe_record = sqlx::query!(
|
||||
r#"
|
||||
SELECT height
|
||||
FROM block
|
||||
WHERE timestamp < ?
|
||||
ORDER BY timestamp DESC
|
||||
LIMIT 1
|
||||
"#,
|
||||
time
|
||||
)
|
||||
.fetch_optional(&self.connection_pool)
|
||||
.await?;
|
||||
|
||||
if let Some(row) = maybe_record {
|
||||
Ok(row.height)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn get_signed_between(
|
||||
&self,
|
||||
consensus_address: &str,
|
||||
start_height: i64,
|
||||
end_height: i64,
|
||||
) -> Result<i32, sqlx::Error> {
|
||||
let count = sqlx::query!(
|
||||
r#"
|
||||
SELECT COUNT(*) as count FROM pre_commit
|
||||
WHERE
|
||||
validator_address == ?
|
||||
AND height >= ?
|
||||
AND height <= ?
|
||||
"#,
|
||||
consensus_address,
|
||||
start_height,
|
||||
end_height
|
||||
)
|
||||
.fetch_one(&self.connection_pool)
|
||||
.await?
|
||||
.count;
|
||||
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
pub(crate) async fn get_precommit(
|
||||
&self,
|
||||
consensus_address: &str,
|
||||
height: i64,
|
||||
) -> Result<Option<CommitSignature>, sqlx::Error> {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
SELECT * FROM pre_commit
|
||||
WHERE validator_address = ?
|
||||
AND height = ?
|
||||
"#,
|
||||
)
|
||||
.bind(consensus_address)
|
||||
.bind(height)
|
||||
.fetch_optional(&self.connection_pool)
|
||||
.await
|
||||
}
|
||||
|
||||
pub(crate) async fn get_block_validators(
|
||||
&self,
|
||||
height: i64,
|
||||
) -> Result<Vec<Validator>, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
Validator,
|
||||
r#"
|
||||
SELECT * FROM validator
|
||||
WHERE EXISTS (
|
||||
SELECT 1 FROM pre_commit
|
||||
WHERE height == ?
|
||||
AND pre_commit.validator_address = validator.consensus_address
|
||||
)
|
||||
"#,
|
||||
height
|
||||
)
|
||||
.fetch_all(&self.connection_pool)
|
||||
.await
|
||||
}
|
||||
|
||||
pub(crate) async fn get_validators(&self) -> Result<Vec<Validator>, sqlx::Error> {
|
||||
sqlx::query_as("SELECT * FROM validator")
|
||||
.fetch_all(&self.connection_pool)
|
||||
.await
|
||||
}
|
||||
|
||||
pub(crate) async fn get_last_processed_height(&self) -> Result<i64, sqlx::Error> {
|
||||
let maybe_record = sqlx::query!(
|
||||
r#"
|
||||
SELECT last_processed_height FROM metadata
|
||||
"#
|
||||
)
|
||||
.fetch_optional(&self.connection_pool)
|
||||
.await?;
|
||||
|
||||
if let Some(row) = maybe_record {
|
||||
Ok(row.last_processed_height)
|
||||
} else {
|
||||
Ok(-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make those generic over executor so that they could be performed over connection pool and a tx
|
||||
|
||||
#[instrument(skip(executor))]
|
||||
pub(crate) async fn insert_validator<'a, E>(
|
||||
consensus_address: String,
|
||||
consensus_pubkey: String,
|
||||
executor: E,
|
||||
) -> Result<(), sqlx::Error>
|
||||
where
|
||||
E: Executor<'a, Database = Sqlite>,
|
||||
{
|
||||
trace!("insert validator");
|
||||
|
||||
sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO validator (consensus_address, consensus_pubkey)
|
||||
VALUES (?, ?)
|
||||
ON CONFLICT DO NOTHING
|
||||
"#,
|
||||
consensus_address,
|
||||
consensus_pubkey
|
||||
)
|
||||
.execute(executor)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(skip(executor))]
|
||||
pub(crate) async fn insert_block<'a, E>(
|
||||
height: i64,
|
||||
hash: String,
|
||||
num_txs: u32,
|
||||
total_gas: i64,
|
||||
proposer_address: String,
|
||||
timestamp: OffsetDateTime,
|
||||
executor: E,
|
||||
) -> Result<(), sqlx::Error>
|
||||
where
|
||||
E: Executor<'a, Database = Sqlite>,
|
||||
{
|
||||
trace!("insert block");
|
||||
|
||||
sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO block (height, hash, num_txs, total_gas, proposer_address, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT DO NOTHING
|
||||
"#,
|
||||
height,
|
||||
hash,
|
||||
num_txs,
|
||||
total_gas,
|
||||
proposer_address,
|
||||
timestamp
|
||||
)
|
||||
.execute(executor)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(skip(executor))]
|
||||
pub(crate) async fn insert_precommit<'a, E>(
|
||||
validator_address: String,
|
||||
height: i64,
|
||||
timestamp: OffsetDateTime,
|
||||
voting_power: i64,
|
||||
proposer_priority: i64,
|
||||
executor: E,
|
||||
) -> Result<(), sqlx::Error>
|
||||
where
|
||||
E: Executor<'a, Database = Sqlite>,
|
||||
{
|
||||
trace!("insert precommit");
|
||||
|
||||
sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO pre_commit (validator_address, height, timestamp, voting_power, proposer_priority)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON CONFLICT (validator_address, timestamp) DO NOTHING
|
||||
"#,
|
||||
validator_address,
|
||||
height,
|
||||
timestamp,
|
||||
voting_power,
|
||||
proposer_priority
|
||||
)
|
||||
.execute(executor)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(skip(executor))]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) async fn insert_transaction<'a, E>(
|
||||
hash: String,
|
||||
height: i64,
|
||||
index: i64,
|
||||
success: bool,
|
||||
messages: i64,
|
||||
memo: String,
|
||||
gas_wanted: i64,
|
||||
gas_used: i64,
|
||||
raw_log: String,
|
||||
executor: E,
|
||||
) -> Result<(), sqlx::Error>
|
||||
where
|
||||
E: Executor<'a, Database = Sqlite>,
|
||||
{
|
||||
trace!("insert transaction");
|
||||
|
||||
sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO "transaction" (hash, height, "index", success, num_messages, memo, gas_wanted, gas_used, raw_log)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT (hash) DO UPDATE
|
||||
SET height = excluded.height,
|
||||
"index" = excluded."index",
|
||||
success = excluded.success,
|
||||
num_messages = excluded.num_messages,
|
||||
memo = excluded.memo,
|
||||
gas_wanted = excluded.gas_wanted,
|
||||
gas_used = excluded.gas_used,
|
||||
raw_log = excluded.raw_log
|
||||
"#,
|
||||
hash,
|
||||
height,
|
||||
index,
|
||||
success,
|
||||
messages,
|
||||
memo,
|
||||
gas_wanted,
|
||||
gas_used,
|
||||
raw_log,
|
||||
)
|
||||
.execute(executor)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(skip(executor))]
|
||||
pub(crate) async fn insert_message<'a, E>(
|
||||
transaction_hash: String,
|
||||
index: i64,
|
||||
typ: String,
|
||||
height: i64,
|
||||
executor: E,
|
||||
) -> Result<(), sqlx::Error>
|
||||
where
|
||||
E: Executor<'a, Database = Sqlite>,
|
||||
{
|
||||
trace!("insert message");
|
||||
|
||||
sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO message (transaction_hash, "index", type, height)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT (transaction_hash, "index") DO UPDATE
|
||||
SET height = excluded.height,
|
||||
type = excluded.type
|
||||
"#,
|
||||
transaction_hash,
|
||||
index,
|
||||
typ,
|
||||
height
|
||||
)
|
||||
.execute(executor)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(skip(executor))]
|
||||
pub(crate) async fn update_last_processed<'a, E>(
|
||||
height: i64,
|
||||
executor: E,
|
||||
) -> Result<(), sqlx::Error>
|
||||
where
|
||||
E: Executor<'a, Database = Sqlite>,
|
||||
{
|
||||
trace!("update_last_processed");
|
||||
|
||||
sqlx::query!("UPDATE metadata SET last_processed_height = ?", height)
|
||||
.execute(executor)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::block_processor::types::{FullBlockInformation, ParsedTransactionResponse};
|
||||
use crate::error::ScraperError;
|
||||
use crate::storage::manager::{
|
||||
insert_block, insert_message, insert_precommit, insert_transaction, insert_validator,
|
||||
update_last_processed, StorageManager,
|
||||
};
|
||||
use crate::storage::models::{CommitSignature, Validator};
|
||||
use sqlx::types::time::OffsetDateTime;
|
||||
use sqlx::{ConnectOptions, Sqlite, Transaction};
|
||||
use std::fmt::Debug;
|
||||
use std::path::Path;
|
||||
use tendermint::block::{Commit, CommitSig};
|
||||
use tendermint::Block;
|
||||
use tendermint_rpc::endpoint::validators;
|
||||
use tracing::{debug, error, info, instrument, trace, warn};
|
||||
|
||||
mod helpers;
|
||||
mod manager;
|
||||
pub mod models;
|
||||
|
||||
pub type StorageTransaction = Transaction<'static, Sqlite>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ScraperStorage {
|
||||
pub(crate) manager: StorageManager,
|
||||
}
|
||||
|
||||
impl ScraperStorage {
|
||||
#[instrument]
|
||||
pub async fn init<P: AsRef<Path> + Debug>(database_path: P) -> Result<Self, ScraperError> {
|
||||
let mut opts = sqlx::sqlite::SqliteConnectOptions::new()
|
||||
.filename(database_path)
|
||||
.create_if_missing(true);
|
||||
|
||||
// TODO: do we want auto_vacuum ?
|
||||
|
||||
opts.disable_statement_logging();
|
||||
|
||||
let connection_pool = match sqlx::SqlitePool::connect_with(opts).await {
|
||||
Ok(db) => db,
|
||||
Err(err) => {
|
||||
error!("Failed to connect to SQLx database: {err}");
|
||||
return Err(err.into());
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(err) = sqlx::migrate!("./sql_migrations")
|
||||
.run(&connection_pool)
|
||||
.await
|
||||
{
|
||||
error!("Failed to initialize SQLx database: {err}");
|
||||
return Err(err.into());
|
||||
}
|
||||
|
||||
info!("Database migration finished!");
|
||||
|
||||
let manager = StorageManager { connection_pool };
|
||||
manager.set_initial_metadata().await?;
|
||||
|
||||
let storage = ScraperStorage { manager };
|
||||
|
||||
Ok(storage)
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub async fn begin_processing_tx(&self) -> Result<StorageTransaction, ScraperError> {
|
||||
debug!("starting storage tx");
|
||||
self.manager
|
||||
.connection_pool
|
||||
.begin()
|
||||
.await
|
||||
.map_err(|source| ScraperError::StorageTxBeginFailure { source })
|
||||
}
|
||||
|
||||
pub async fn get_first_block_height_after(
|
||||
&self,
|
||||
time: OffsetDateTime,
|
||||
) -> Result<Option<i64>, ScraperError> {
|
||||
Ok(self.manager.get_first_block_height_after(time).await?)
|
||||
}
|
||||
|
||||
pub async fn get_last_block_height_before(
|
||||
&self,
|
||||
time: OffsetDateTime,
|
||||
) -> Result<Option<i64>, ScraperError> {
|
||||
Ok(self.manager.get_last_block_height_before(time).await?)
|
||||
}
|
||||
|
||||
pub async fn get_blocks_between(
|
||||
&self,
|
||||
start_time: OffsetDateTime,
|
||||
end_time: OffsetDateTime,
|
||||
) -> Result<i64, ScraperError> {
|
||||
let Some(block_start) = self.get_first_block_height_after(start_time).await? else {
|
||||
return Ok(0);
|
||||
};
|
||||
let Some(block_end) = self.get_last_block_height_before(end_time).await? else {
|
||||
return Ok(0);
|
||||
};
|
||||
|
||||
Ok(block_end - block_start)
|
||||
}
|
||||
|
||||
pub async fn get_signed_between(
|
||||
&self,
|
||||
consensus_address: &str,
|
||||
start_height: i64,
|
||||
end_height: i64,
|
||||
) -> Result<i32, ScraperError> {
|
||||
Ok(self
|
||||
.manager
|
||||
.get_signed_between(consensus_address, start_height, end_height)
|
||||
.await?)
|
||||
}
|
||||
|
||||
pub async fn get_signed_between_times(
|
||||
&self,
|
||||
consensus_address: &str,
|
||||
start_time: OffsetDateTime,
|
||||
end_time: OffsetDateTime,
|
||||
) -> Result<i32, ScraperError> {
|
||||
let Some(block_start) = self.get_first_block_height_after(start_time).await? else {
|
||||
return Ok(0);
|
||||
};
|
||||
let Some(block_end) = self.get_last_block_height_before(end_time).await? else {
|
||||
return Ok(0);
|
||||
};
|
||||
|
||||
self.get_signed_between(consensus_address, block_start, block_end)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_precommit(
|
||||
&self,
|
||||
consensus_address: &str,
|
||||
height: i64,
|
||||
) -> Result<Option<CommitSignature>, ScraperError> {
|
||||
Ok(self
|
||||
.manager
|
||||
.get_precommit(consensus_address, height)
|
||||
.await?)
|
||||
}
|
||||
|
||||
pub async fn get_block_signers(&self, height: i64) -> Result<Vec<Validator>, ScraperError> {
|
||||
Ok(self.manager.get_block_validators(height).await?)
|
||||
}
|
||||
|
||||
pub async fn get_all_known_validators(&self) -> Result<Vec<Validator>, ScraperError> {
|
||||
Ok(self.manager.get_validators().await?)
|
||||
}
|
||||
|
||||
pub async fn get_last_processed_height(&self) -> Result<i64, ScraperError> {
|
||||
Ok(self.manager.get_last_processed_height().await?)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn persist_block(
|
||||
block: &FullBlockInformation,
|
||||
tx: &mut StorageTransaction,
|
||||
) -> Result<(), ScraperError> {
|
||||
let total_gas = crate::helpers::tx_gas_sum(&block.transactions);
|
||||
|
||||
// SANITY CHECK: make sure the block proposer is present in the validator set
|
||||
block.ensure_proposer()?;
|
||||
|
||||
// persist validators
|
||||
persist_validators(&block.validators, tx).await?;
|
||||
|
||||
// persist block data
|
||||
persist_block_data(&block.block, total_gas, tx).await?;
|
||||
|
||||
// persist commits
|
||||
if let Some(commit) = &block.block.last_commit {
|
||||
persist_commits(commit, &block.validators, tx).await?;
|
||||
} else {
|
||||
warn!("no commits for block {}", block.block.header.height)
|
||||
}
|
||||
|
||||
// persist txs
|
||||
persist_txs(&block.transactions, tx).await?;
|
||||
|
||||
// persist messages (inside the transactions)
|
||||
persist_messages(&block.transactions, tx).await?;
|
||||
|
||||
update_last_processed(block.block.header.height.into(), tx).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn persist_validators(
|
||||
validators: &validators::Response,
|
||||
tx: &mut StorageTransaction,
|
||||
) -> Result<(), ScraperError> {
|
||||
debug!("persisting {} validators", validators.total);
|
||||
for validator in &validators.validators {
|
||||
let consensus_address = crate::helpers::validator_consensus_address(validator.address)?;
|
||||
let consensus_pubkey = crate::helpers::validator_pubkey_to_bech32(validator.pub_key)?;
|
||||
|
||||
insert_validator(
|
||||
consensus_address.to_string(),
|
||||
consensus_pubkey.to_string(),
|
||||
&mut *tx,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn persist_block_data(
|
||||
block: &Block,
|
||||
total_gas: i64,
|
||||
tx: &mut StorageTransaction,
|
||||
) -> Result<(), ScraperError> {
|
||||
let proposer_address =
|
||||
crate::helpers::validator_consensus_address(block.header.proposer_address)?.to_string();
|
||||
|
||||
insert_block(
|
||||
block.header.height.into(),
|
||||
block.header.hash().to_string(),
|
||||
block.data.len() as u32,
|
||||
total_gas,
|
||||
proposer_address,
|
||||
block.header.time.into(),
|
||||
tx,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn persist_commits(
|
||||
commits: &Commit,
|
||||
validators: &validators::Response,
|
||||
tx: &mut StorageTransaction,
|
||||
) -> Result<(), ScraperError> {
|
||||
debug!("persisting up to {} commits", commits.signatures.len());
|
||||
let height: i64 = commits.height.into();
|
||||
|
||||
for commit_sig in &commits.signatures {
|
||||
let (validator_id, timestamp, signature) = match commit_sig {
|
||||
CommitSig::BlockIdFlagAbsent => {
|
||||
trace!("absent signature");
|
||||
continue;
|
||||
}
|
||||
CommitSig::BlockIdFlagCommit {
|
||||
validator_address,
|
||||
timestamp,
|
||||
signature,
|
||||
} => (validator_address, timestamp, signature),
|
||||
CommitSig::BlockIdFlagNil {
|
||||
validator_address,
|
||||
timestamp,
|
||||
signature,
|
||||
} => (validator_address, timestamp, signature),
|
||||
};
|
||||
|
||||
let validator = crate::helpers::validator_info(*validator_id, validators)?;
|
||||
let validator_address = crate::helpers::validator_consensus_address(*validator_id)?;
|
||||
|
||||
if signature.is_none() {
|
||||
warn!("empty signature for {validator_address} at height {height}");
|
||||
continue;
|
||||
}
|
||||
|
||||
insert_precommit(
|
||||
validator_address.to_string(),
|
||||
height,
|
||||
(*timestamp).into(),
|
||||
validator.power.into(),
|
||||
validator.proposer_priority.value(),
|
||||
&mut *tx,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn persist_txs(
|
||||
txs: &[ParsedTransactionResponse],
|
||||
tx: &mut StorageTransaction,
|
||||
) -> Result<(), ScraperError> {
|
||||
debug!("persisting {} txs", txs.len());
|
||||
|
||||
for chain_tx in txs {
|
||||
insert_transaction(
|
||||
chain_tx.hash.to_string(),
|
||||
chain_tx.height.into(),
|
||||
chain_tx.index as i64,
|
||||
chain_tx.tx_result.code.is_ok(),
|
||||
chain_tx.tx.body.messages.len() as i64,
|
||||
chain_tx.tx.body.memo.clone(),
|
||||
chain_tx.tx_result.gas_wanted,
|
||||
chain_tx.tx_result.gas_used,
|
||||
chain_tx.tx_result.log.clone(),
|
||||
&mut *tx,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn persist_messages(
|
||||
txs: &[ParsedTransactionResponse],
|
||||
tx: &mut StorageTransaction,
|
||||
) -> Result<(), ScraperError> {
|
||||
debug!("persisting messages");
|
||||
|
||||
for chain_tx in txs {
|
||||
for (index, msg) in chain_tx.tx.body.messages.iter().enumerate() {
|
||||
insert_message(
|
||||
chain_tx.hash.to_string(),
|
||||
index as i64,
|
||||
msg.type_url.clone(),
|
||||
chain_tx.height.into(),
|
||||
&mut *tx,
|
||||
)
|
||||
.await?
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use sqlx::types::time::OffsetDateTime;
|
||||
use sqlx::FromRow;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash, FromRow)]
|
||||
pub struct Validator {
|
||||
pub consensus_address: String,
|
||||
pub consensus_pubkey: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, FromRow)]
|
||||
pub struct Block {
|
||||
pub height: i64,
|
||||
pub hash: String,
|
||||
pub num_txs: u32,
|
||||
pub total_gas: i64,
|
||||
pub proposer_address: String,
|
||||
pub timestamp: OffsetDateTime,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, FromRow)]
|
||||
pub struct CommitSignature {
|
||||
pub height: i64,
|
||||
pub validator_address: String,
|
||||
pub voting_power: i64,
|
||||
pub proposer_priority: i64,
|
||||
pub timestamp: OffsetDateTime,
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "nym-socks5-client-core"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ name = "nym-ordered-buffer"
|
||||
version = "0.1.0"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ name = "nym-socks5-proxy-helpers"
|
||||
version = "0.1.0"
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ name = "nym-socks5-requests"
|
||||
version = "0.1.0"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
|
||||
edition = "2021"
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user