Merge upstream changes
This commit is contained in:
commit
07f0e38a40
|
@ -69,9 +69,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.0"
|
||||
version = "0.6.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bff2cf94a3dbe2d57cbd56485e1bd7436455058034d6c2d47be51d4e5e4bc6ab"
|
||||
checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
|
@ -102,17 +102,17 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.0"
|
||||
version = "3.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0238ca56c96dfa37bdf7c373c8886dd591322500aceeeccdb2216fe06dc2f796"
|
||||
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -147,9 +147,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.6"
|
||||
version = "0.21.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c79fed4cdb43e993fcdadc7e58a09fd0e3e649c4436fa11da71c9f1f3ee7feb9"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
|
@ -219,9 +219,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.31"
|
||||
version = "0.4.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
|
||||
checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
|
@ -229,7 +229,7 @@ dependencies = [
|
|||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -244,9 +244,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.14"
|
||||
version = "4.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33e92c5c1a78c62968ec57dbc2440366a2d6e5a23faf829970ff1585dc6b18e2"
|
||||
checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
@ -254,21 +254,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.4.14"
|
||||
version = "4.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4323769dc8a61e2c39ad7dc26f6f2800524691a44d74fe3d1071a5c24db6370"
|
||||
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
"strsim 0.11.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.4.7"
|
||||
version = "4.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
|
||||
checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
|
@ -278,9 +278,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.6.0"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
|
@ -445,7 +445,7 @@ dependencies = [
|
|||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"strsim 0.10.0",
|
||||
"syn",
|
||||
]
|
||||
|
||||
|
@ -544,7 +544,7 @@ checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
|
|||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -617,9 +617,9 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
|||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
|
||||
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
|
@ -632,9 +632,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
|
||||
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
|
@ -642,15 +642,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
|
||||
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
|
||||
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
|
@ -659,15 +659,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
|
||||
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
|
||||
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -676,21 +676,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
|
||||
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
|
||||
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
|
||||
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
|
@ -984,9 +984,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
|||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.66"
|
||||
version = "0.3.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
|
||||
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
@ -1131,6 +1131,7 @@ dependencies = [
|
|||
name = "lox_utils"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"lox-library",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -1187,7 +1188,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
|
|||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1243,6 +1244,12 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
|
@ -1405,7 +1412,7 @@ dependencies = [
|
|||
"libc",
|
||||
"redox_syscall 0.3.5",
|
||||
"smallvec",
|
||||
"windows-targets",
|
||||
"windows-targets 0.48.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1498,9 +1505,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "prometheus-client"
|
||||
version = "0.22.0"
|
||||
version = "0.22.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "510c4f1c9d81d556458f94c98f857748130ea9737bbd6053da497503b26ea63c"
|
||||
checksum = "c1ca959da22a332509f2a73ae9e5f23f9dcfc31fd3a54d71f159495bd5909baa"
|
||||
dependencies = [
|
||||
"dtoa",
|
||||
"itoa",
|
||||
|
@ -1821,7 +1828,7 @@ dependencies = [
|
|||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1836,7 +1843,7 @@ version = "0.1.22"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1876,18 +1883,18 @@ checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.195"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
|
||||
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.195"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
|
||||
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1896,9 +1903,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.108"
|
||||
version = "1.0.113"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
|
||||
checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
|
@ -1919,9 +1926,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.5.0"
|
||||
version = "3.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f58c3a1b3e418f61c25b2aeb43fc6c95eaa252b8cecdda67f401943e9e08d33f"
|
||||
checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"chrono",
|
||||
|
@ -1929,6 +1936,7 @@ dependencies = [
|
|||
"indexmap 1.9.3",
|
||||
"indexmap 2.0.0",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"serde_with_macros",
|
||||
"time",
|
||||
|
@ -1936,9 +1944,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "3.5.0"
|
||||
version = "3.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2068b437a31fc68f25dd7edc296b078f04b45145c199d8eed9866e45f1ff274"
|
||||
checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
|
@ -2050,6 +2058,12 @@ version = "0.10.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.5.0"
|
||||
|
@ -2077,23 +2091,23 @@ dependencies = [
|
|||
"fastrand",
|
||||
"redox_syscall 0.3.5",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.56"
|
||||
version = "1.0.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
|
||||
checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.56"
|
||||
version = "1.0.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
|
||||
checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -2102,12 +2116,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.31"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e"
|
||||
checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"num-conv",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
|
@ -2122,10 +2137,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
|||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.16"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f"
|
||||
checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
|
@ -2161,7 +2177,7 @@ dependencies = [
|
|||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2331,9 +2347,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.89"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
|
||||
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
|
@ -2341,9 +2357,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.89"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
|
||||
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
|
@ -2368,9 +2384,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.89"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
|
||||
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
@ -2378,9 +2394,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.89"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
|
||||
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -2391,9 +2407,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.89"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
|
||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-streams"
|
||||
|
@ -2446,7 +2462,7 @@ version = "0.48.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.48.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2455,7 +2471,16 @@ version = "0.48.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.48.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2464,13 +2489,28 @@ version = "0.48.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_aarch64_gnullvm 0.48.0",
|
||||
"windows_aarch64_msvc 0.48.0",
|
||||
"windows_i686_gnu 0.48.0",
|
||||
"windows_i686_msvc 0.48.0",
|
||||
"windows_x86_64_gnu 0.48.0",
|
||||
"windows_x86_64_gnullvm 0.48.0",
|
||||
"windows_x86_64_msvc 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.0",
|
||||
"windows_aarch64_msvc 0.52.0",
|
||||
"windows_i686_gnu 0.52.0",
|
||||
"windows_i686_msvc 0.52.0",
|
||||
"windows_x86_64_gnu 0.52.0",
|
||||
"windows_x86_64_gnullvm 0.52.0",
|
||||
"windows_x86_64_msvc 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2479,42 +2519,84 @@ version = "0.48.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.10.1"
|
||||
|
|
|
@ -16,25 +16,25 @@ readme = "README.md"
|
|||
|
||||
[dependencies]
|
||||
julianday = "1.2.0"
|
||||
base64 = "0.21.6"
|
||||
base64 = "0.21.7"
|
||||
hyper = { version = "0.14.28", features = ["deprecated", "backports","server"] }
|
||||
hex_fmt = "0.3"
|
||||
futures = "0.3.29"
|
||||
time = "0.3.31"
|
||||
futures = "0.3.30"
|
||||
time = "0.3.34"
|
||||
tokio = { version = "1", features = ["full", "macros", "signal"] }
|
||||
rand = "0.8.5"
|
||||
reqwest = { version = "0.11", features = ["json", "stream"]}
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_with = "3.5.0"
|
||||
serde_with = "3.7.0"
|
||||
lox-zkp = { git = "https://gitlab.torproject.org/onyinyang/lox-zkp", version = "0.8.0" }
|
||||
lox-library = { path = "../lox-library", version = "0.1.0"}
|
||||
lox_utils = { path = "../lox-utils", version = "0.1.0"}
|
||||
rdsys_backend = { path = "../rdsys-backend-api", version = "0.2"}
|
||||
clap = { version = "4.4.14", features = ["derive"] }
|
||||
serde_json = "1.0.108"
|
||||
clap = { version = "4.5.2", features = ["derive"] }
|
||||
serde_json = "1.0.113"
|
||||
prometheus = "0.13.3"
|
||||
sled = "0.34.7"
|
||||
prometheus-client = "0.22.0"
|
||||
prometheus-client = "0.22.2"
|
||||
thiserror = "1"
|
||||
curve25519-dalek = { version = "4", default-features = false, features = ["serde", "rand_core", "digest"] }
|
||||
troll-patrol = { git = "https://git-crysp.uwaterloo.ca/vvecna/troll-patrol", version = "0.1.0" }
|
||||
|
@ -42,5 +42,5 @@ array-bytes = "6.2.0"
|
|||
sha1 = "0.10"
|
||||
|
||||
[dependencies.chrono]
|
||||
version = "0.4.31"
|
||||
version = "0.4.34"
|
||||
features = ["serde"]
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -125,11 +125,14 @@ impl LoxServerContext {
|
|||
for bridge in blocked {
|
||||
let res = self.mark_blocked(bridge);
|
||||
if res {
|
||||
println!("BridgeLine {:?} successfully marked unreachable", bridge);
|
||||
println!(
|
||||
"Blocked BridgeLine {:?} successfully marked unreachable",
|
||||
bridge
|
||||
);
|
||||
self.metrics.blocked_bridges.inc();
|
||||
} else {
|
||||
println!(
|
||||
"BridgeLine {:?} NOT marked unreachable, not found in bridgetable!",
|
||||
"Blocked BridgeLine {:?} NOT marked unreachable, not found in bridgetable!",
|
||||
bridge.uid_fingerprint
|
||||
);
|
||||
}
|
||||
|
@ -139,20 +142,22 @@ impl LoxServerContext {
|
|||
let res = self.update_bridge(bridge);
|
||||
if res {
|
||||
println!(
|
||||
"BridgeLine {:?} successfully updated.",
|
||||
"Grace period BridgeLine {:?} successfully updated.",
|
||||
bridge.uid_fingerprint
|
||||
);
|
||||
accounted_for_bridges.push(bridge.uid_fingerprint);
|
||||
self.metrics.existing_or_updated_bridges.inc();
|
||||
} else {
|
||||
println!("Grace period BridgeLine: {:?} not found in Lox's Bridgetable. Wait until it is working to update/add it!", bridge.uid_fingerprint);
|
||||
}
|
||||
}
|
||||
// Next, handle the failing bridges. If resource last passed tests >=ACCEPTED_HOURS_OF_FAILURE ago,
|
||||
// Next, handle the failing bridges. If resource last passed tests >= ACCEPTED_HOURS_OF_FAILURE ago,
|
||||
// it should be replaced with a working resource and be removed from the bridgetable.
|
||||
for bridge in failing {
|
||||
let res = self.replace_with_new(bridge);
|
||||
if res == lox_library::ReplaceSuccess::Replaced {
|
||||
println!(
|
||||
"BridgeLine {:?} successfully replaced.",
|
||||
"Failing BridgeLine {:?} successfully replaced.",
|
||||
bridge.uid_fingerprint
|
||||
);
|
||||
accounted_for_bridges.push(bridge.uid_fingerprint);
|
||||
|
@ -161,10 +166,9 @@ impl LoxServerContext {
|
|||
// Add the bridge to the list of to_be_replaced bridges in the Lox context and try
|
||||
// again to replace at the next update (nothing changes in the Lox Authority)
|
||||
println!(
|
||||
"BridgeLine {:?} NOT replaced, saved for next update!",
|
||||
"Failing BridgeLine {:?} NOT replaced, saved for next update!",
|
||||
bridge.uid_fingerprint
|
||||
);
|
||||
self.new_to_be_replaced_bridge(bridge);
|
||||
self.metrics.existing_or_updated_bridges.inc();
|
||||
accounted_for_bridges.push(bridge.uid_fingerprint);
|
||||
} else {
|
||||
|
@ -174,7 +178,7 @@ impl LoxServerContext {
|
|||
"ReplaceSuccess incorrectly set"
|
||||
);
|
||||
println!(
|
||||
"BridgeLine {:?} no longer in bridge table.",
|
||||
"Failing BridgeLine {:?} not found in bridge table.",
|
||||
bridge.uid_fingerprint
|
||||
);
|
||||
}
|
||||
|
@ -212,11 +216,9 @@ impl LoxServerContext {
|
|||
self.metrics.removed_bridges.inc();
|
||||
}
|
||||
lox_library::ReplaceSuccess::NotReplaced => {
|
||||
// Add the bridge to the list of to_be_replaced bridges in the Lox context and try
|
||||
// again to replace at the next update (nothing changes in the Lox Authority)
|
||||
// Try again to replace at the next update (nothing changes in the Lox Authority)
|
||||
println!("BridgeLine {:?} not found in rdsys update NOT replaced, saved for next update!",
|
||||
bridgeline.uid_fingerprint);
|
||||
self.new_to_be_replaced_bridge(bridgeline);
|
||||
self.metrics.existing_or_updated_bridges.inc();
|
||||
}
|
||||
lox_library::ReplaceSuccess::NotFound => println!(
|
||||
|
@ -267,17 +269,6 @@ impl LoxServerContext {
|
|||
return_bridges
|
||||
}
|
||||
|
||||
pub fn remove_single_bridge(&self) {
|
||||
let mut extra_bridges = self.extra_bridges.lock().unwrap();
|
||||
let length = extra_bridges.len();
|
||||
_ = extra_bridges.remove(length - 1)
|
||||
}
|
||||
|
||||
pub fn new_to_be_replaced_bridge(&self, bridge: BridgeLine) {
|
||||
let mut to_be_replaced_bridges = self.to_be_replaced_bridges.lock().unwrap();
|
||||
to_be_replaced_bridges.push(bridge);
|
||||
}
|
||||
|
||||
// Add extra_bridges to the Lox bridge table as open invitation bridges
|
||||
// TODO: Add some consideration for whether or not bridges should be sorted as
|
||||
// open invitation buckets or hot spare buckets
|
||||
|
@ -322,13 +313,14 @@ impl LoxServerContext {
|
|||
// available bridges or from a spare bucket
|
||||
pub fn replace_with_new(&self, bridgeline: BridgeLine) -> lox_library::ReplaceSuccess {
|
||||
let mut ba_obj = self.ba.lock().unwrap();
|
||||
let eb_obj = self.extra_bridges.lock().unwrap();
|
||||
let available_bridge = eb_obj.last();
|
||||
let mut eb_obj = self.extra_bridges.lock().unwrap();
|
||||
let available_bridge = eb_obj.pop();
|
||||
let result = ba_obj.bridge_replace(&bridgeline, available_bridge);
|
||||
// .last() doesn't actually remove the object so we still have to do that if the bridge was
|
||||
// replaced with an available bridge
|
||||
if result == lox_library::ReplaceSuccess::Replaced && eb_obj.len() > 0 {
|
||||
self.remove_single_bridge();
|
||||
if result != lox_library::ReplaceSuccess::Replaced {
|
||||
if let Some(bridge) = available_bridge {
|
||||
// If available bridge wasn't removed, return it
|
||||
eb_obj.push(bridge);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
|
|
@ -2,7 +2,15 @@ use chrono::{Duration, Utc};
|
|||
use lox_library::bridge_table::{BridgeLine, BRIDGE_INFO_BYTES, MAX_BRIDGES_PER_BUCKET};
|
||||
use rdsys_backend::proto::Resource;
|
||||
|
||||
pub const ACCEPTED_HOURS_OF_FAILURE: i64 = 3;
|
||||
/// Since the last passed time for a working > non-working resource
|
||||
/// may be older than the current time by rdsys' expiry time (currently 18 hours): https://gitlab.torproject.org/tpo/anti-censorship/rdsys/-/blob/main/pkg/usecases/resources/bridges.go?ref_type=heads#L176
|
||||
/// the distributor must use that time to decide on the ACCEPTED_HOURS_OF_FAILURE
|
||||
pub const RDSYS_EXPIRY: i64 = 18;
|
||||
|
||||
/// This value must correspond with rdsys' expiry time
|
||||
/// and decide on an acceptable grace period for resources that aren't working
|
||||
/// but may come back (and so shouldn't be replaced)
|
||||
pub const ACCEPTED_HOURS_OF_FAILURE: i64 = 3 + RDSYS_EXPIRY;
|
||||
|
||||
// Parse each resource from rdsys into a Bridgeline as expected by the Lox Bridgetable and return
|
||||
// Bridgelines as two vectors, those that are marked as blocked in a specified region (indicated in the config file)
|
||||
|
@ -130,6 +138,8 @@ mod tests {
|
|||
|
||||
use chrono::{Duration, Utc};
|
||||
|
||||
use crate::resource_parser::ACCEPTED_HOURS_OF_FAILURE;
|
||||
|
||||
use super::sort_for_parsing;
|
||||
|
||||
pub fn make_resource(
|
||||
|
@ -179,7 +189,7 @@ mod tests {
|
|||
"123.456.789.100".to_owned(),
|
||||
3002,
|
||||
"BE84A97D02130470A1C77839954392BA979F7EE1".to_owned(),
|
||||
2,
|
||||
ACCEPTED_HOURS_OF_FAILURE-1,
|
||||
);
|
||||
let resource_two = make_resource(
|
||||
"https".to_owned(),
|
||||
|
@ -193,7 +203,7 @@ mod tests {
|
|||
"123.222.333.444".to_owned(),
|
||||
6002,
|
||||
"C56B9EF202130470A1C77839954392BA979F7FF9".to_owned(),
|
||||
5,
|
||||
ACCEPTED_HOURS_OF_FAILURE+2,
|
||||
);
|
||||
let resource_three = make_resource(
|
||||
"scramblesuit".to_owned(),
|
||||
|
@ -207,7 +217,7 @@ mod tests {
|
|||
"443.288.222.100".to_owned(),
|
||||
3042,
|
||||
"5E3A8BD902130470A1C77839954392BA979F7B46".to_owned(),
|
||||
4,
|
||||
ACCEPTED_HOURS_OF_FAILURE+1,
|
||||
);
|
||||
let resource_four = make_resource(
|
||||
"https".to_owned(),
|
||||
|
@ -221,7 +231,7 @@ mod tests {
|
|||
"555.444.212.100".to_owned(),
|
||||
8022,
|
||||
"FF024DC302130470A1C77839954392BA979F7AE2".to_owned(),
|
||||
3,
|
||||
ACCEPTED_HOURS_OF_FAILURE,
|
||||
);
|
||||
let resource_five = make_resource(
|
||||
"https".to_owned(),
|
||||
|
@ -249,7 +259,7 @@ mod tests {
|
|||
"434.777.212.100".to_owned(),
|
||||
10112,
|
||||
"7B4DE04A22130470A1C77839954392BA979F7AE2".to_owned(),
|
||||
1,
|
||||
0,
|
||||
);
|
||||
let resource_seven = make_resource(
|
||||
"https".to_owned(),
|
||||
|
|
|
@ -19,18 +19,18 @@ ed25519-dalek = { version = "2", features = ["serde", "rand_core"] }
|
|||
bincode = "1"
|
||||
chrono = "0.4"
|
||||
rand = { version = "0.8", features = ["std_rng"]}
|
||||
serde = "1.0.195"
|
||||
serde_with = {version = "3.5.0", features = ["json"]}
|
||||
serde = "1.0.197"
|
||||
serde_with = {version = "3.7.0", features = ["json"]}
|
||||
sha2 = "0.10"
|
||||
statistical = "1.0.0"
|
||||
lazy_static = "1"
|
||||
hex_fmt = "0.3"
|
||||
aes-gcm = { version = "0.10", features =["aes"]}
|
||||
base64 = "0.21"
|
||||
time = "0.3.31"
|
||||
time = "0.3.34"
|
||||
prometheus = "0.13.3"
|
||||
subtle = "2.5"
|
||||
thiserror = "1.0.56"
|
||||
thiserror = "1.0.57"
|
||||
lox-zkp = { git = "https://gitlab.torproject.org/onyinyang/lox-zkp", version = "0.8.0" }
|
||||
|
||||
[features]
|
||||
|
|
|
@ -94,6 +94,12 @@ pub enum OpenInvitationError {
|
|||
NoBridgesAvailable,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum BridgeTableError {
|
||||
#[error("The bucket corresponding to key {0} was not in the bridge table")]
|
||||
MissingBucket(u32),
|
||||
}
|
||||
|
||||
/// Private Key of the Issuer
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct IssuerPrivKey {
|
||||
|
@ -156,6 +162,7 @@ pub struct BridgeDb {
|
|||
pub pubkey: VerifyingKey,
|
||||
/// The set of open-invitation buckets
|
||||
openinv_buckets: HashSet<u32>,
|
||||
/// The set of open invitation buckets that have been distributed
|
||||
distributed_buckets: Vec<u32>,
|
||||
#[serde(skip)]
|
||||
today: DateTime<Utc>,
|
||||
|
@ -229,14 +236,14 @@ impl BridgeDb {
|
|||
self.today = Utc::now();
|
||||
self.daily_bridges_distributed = 0;
|
||||
}
|
||||
if self.openinv_buckets.is_empty() {
|
||||
return Err(OpenInvitationError::NoBridgesAvailable);
|
||||
}
|
||||
if self.daily_bridges_distributed < MAX_DAILY_BRIDGES {
|
||||
if self.current_k < OPENINV_K && !self.distributed_buckets.is_empty() {
|
||||
bucket_num = *self.distributed_buckets.last().unwrap();
|
||||
self.current_k += 1;
|
||||
} else {
|
||||
if self.openinv_buckets.is_empty() {
|
||||
return Err(OpenInvitationError::NoBridgesAvailable);
|
||||
}
|
||||
// Choose a random bucket number (from the set of open
|
||||
// invitation buckets) and serialize it
|
||||
let openinv_vec: Vec<&u32> = self.openinv_buckets.iter().collect();
|
||||
|
@ -509,121 +516,82 @@ impl BridgeAuth {
|
|||
res
|
||||
}
|
||||
|
||||
// Repurpose a bucket of spares into unallocated bridges
|
||||
pub fn dissolve_spare_bucket(&mut self, key: u32) -> Result<(), BridgeTableError> {
|
||||
self.bridge_table.spares.remove(&key);
|
||||
// Get the actual bridges from the spare bucket
|
||||
let spare_bucket = self
|
||||
.bridge_table
|
||||
.buckets
|
||||
.remove(&key)
|
||||
.ok_or(BridgeTableError::MissingBucket(key))?;
|
||||
for bridge in spare_bucket.iter() {
|
||||
self.bridge_table.unallocated_bridges.push(*bridge);
|
||||
// Mark bucket as unreachable while it is unallocated
|
||||
self.bridge_table.reachable.remove(bridge);
|
||||
}
|
||||
self.bridge_table.keys.remove(&key);
|
||||
self.bridge_table.recycleable_keys.push(key);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Attempt to remove a bridge that is failing tests and replace it with a bridge from
|
||||
/// available_bridge or from a spare bucket
|
||||
pub fn bridge_replace(
|
||||
&mut self,
|
||||
bridge: &BridgeLine,
|
||||
available_bridge: Option<&BridgeLine>,
|
||||
available_bridge: Option<BridgeLine>,
|
||||
) -> ReplaceSuccess {
|
||||
let mut res = ReplaceSuccess::NotFound;
|
||||
let reachable_bridges = &self.bridge_table.reachable.clone();
|
||||
match reachable_bridges.get(bridge) {
|
||||
Some(positions) => {
|
||||
if let Some(replacement) = available_bridge {
|
||||
for (bucketnum, offset) in positions.iter() {
|
||||
let mut bridgelines = match self.bridge_table.buckets.get(bucketnum) {
|
||||
Some(bridgelines) => *bridgelines,
|
||||
None => return ReplaceSuccess::NotFound,
|
||||
};
|
||||
assert!(bridgelines[*offset] == *bridge);
|
||||
bridgelines[*offset] = *replacement;
|
||||
self.bridge_table.buckets.insert(*bucketnum, bridgelines);
|
||||
// Remove the bridge from the reachable bridges and add new bridge
|
||||
self.bridge_table
|
||||
.reachable
|
||||
.insert(*replacement, positions.clone());
|
||||
// Remove the bridge from the bucket
|
||||
self.bridge_table.reachable.remove(bridge);
|
||||
}
|
||||
res = ReplaceSuccess::Replaced
|
||||
} else if !self.bridge_table.unallocated_bridges.is_empty() {
|
||||
let replacement = &self.bridge_table.unallocated_bridges.pop().unwrap();
|
||||
for (bucketnum, offset) in positions.iter() {
|
||||
let mut bridgelines = match self.bridge_table.buckets.get(bucketnum) {
|
||||
Some(bridgelines) => *bridgelines,
|
||||
// This should not happen if the rest of the function is correct, we can assume unwrap will succeed
|
||||
None => return ReplaceSuccess::NotReplaced,
|
||||
};
|
||||
assert!(bridgelines[*offset] == *bridge);
|
||||
bridgelines[*offset] = *replacement;
|
||||
self.bridge_table.buckets.insert(*bucketnum, bridgelines);
|
||||
self.bridge_table
|
||||
.reachable
|
||||
.insert(*replacement, positions.clone());
|
||||
// Remove the bridge from the bucket
|
||||
self.bridge_table.reachable.remove(bridge);
|
||||
}
|
||||
res = ReplaceSuccess::Replaced
|
||||
} else if !self.bridge_table.spares.is_empty() {
|
||||
// First get the bucketnums for the replacement bridge in case it is a spare
|
||||
let mut bucketnums: Vec<u32> = Vec::new();
|
||||
for (bucketnum, _) in positions.iter() {
|
||||
bucketnums.push(*bucketnum);
|
||||
}
|
||||
// Get the first spare and remove it from the spares set.
|
||||
let mut spare = *self.bridge_table.spares.iter().next().unwrap();
|
||||
// Check that the first spare in the list of spares is not the one to be replaced
|
||||
if bucketnums.contains(&spare) {
|
||||
// If it is, take the last spare instead
|
||||
spare = *self.bridge_table.spares.iter().last().unwrap();
|
||||
// If this is the same bucketnum, there is only one spare bucket with the bridge
|
||||
// to be replaced in it, so don't replace it.
|
||||
if bucketnums.contains(&spare) {
|
||||
res = ReplaceSuccess::NotReplaced;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
self.bridge_table.spares.remove(&spare);
|
||||
self.bridge_table.recycleable_keys.push(spare);
|
||||
// Get the actual bridges from the spare bucket
|
||||
let spare_bucket = match self.bridge_table.buckets.remove(&spare) {
|
||||
Some(spare_bucket) => spare_bucket,
|
||||
// This should not happen if the rest of the functions are correct, we can assume unwrap will succeed
|
||||
None => return ReplaceSuccess::NotReplaced,
|
||||
};
|
||||
// Remove the spare bucket uid from the keys map
|
||||
self.bridge_table.keys.remove(&spare);
|
||||
let mut replacement: &BridgeLine = &BridgeLine::default();
|
||||
// Make the first spare the replacement bridge, add the others to the set of
|
||||
// unallocated_bridges
|
||||
for spare_bridge in spare_bucket.iter() {
|
||||
if replacement.port > 0 {
|
||||
self.bridge_table.unallocated_bridges.push(*spare_bridge);
|
||||
// Mark bucket as unreachable while it is unallocated
|
||||
self.bridge_table.reachable.remove(spare_bridge);
|
||||
} else {
|
||||
replacement = spare_bridge;
|
||||
}
|
||||
}
|
||||
for (bucketnum, offset) in positions.iter() {
|
||||
let mut bridgelines = match self.bridge_table.buckets.get(bucketnum) {
|
||||
Some(bridgelines) => *bridgelines,
|
||||
None => return ReplaceSuccess::NotReplaced,
|
||||
};
|
||||
assert!(bridgelines[*offset] == *bridge);
|
||||
bridgelines[*offset] = *replacement;
|
||||
self.bridge_table.buckets.insert(*bucketnum, bridgelines);
|
||||
self.bridge_table
|
||||
.reachable
|
||||
.insert(*replacement, positions.clone());
|
||||
// Remove the bridge from the bucket
|
||||
self.bridge_table.reachable.remove(bridge);
|
||||
}
|
||||
res = ReplaceSuccess::Replaced
|
||||
} else {
|
||||
println!("No available bridges");
|
||||
// If there are no available bridges that can be assigned here, the only thing
|
||||
// that can be done is return an indication that updating the gone bridge
|
||||
// didn't work.
|
||||
// In this case, we do not mark the bridge as unreachable or remove it from the
|
||||
// reachable bridges so that we can still find it when a new bridge does become available
|
||||
res = ReplaceSuccess::NotReplaced
|
||||
}
|
||||
}
|
||||
None => return res,
|
||||
let Some(positions) = reachable_bridges.get(bridge) else {
|
||||
return ReplaceSuccess::NotFound;
|
||||
};
|
||||
res
|
||||
// select replacement:
|
||||
// - first try the given bridge
|
||||
// - second try to pick one from the set of available bridges
|
||||
// - third dissolve a spare bucket to create more available bridges
|
||||
let Some(replacement) = available_bridge.or_else(|| {
|
||||
self.bridge_table.unallocated_bridges.pop().or_else(|| {
|
||||
let Some(spare) = self
|
||||
.bridge_table
|
||||
.spares
|
||||
.iter()
|
||||
// in case bridge is a spare, avoid replacing it with itself
|
||||
.find(|x| !positions.iter().any(|(bucketnum, _)| &bucketnum == x))
|
||||
.cloned()
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
let Ok(_) = self.dissolve_spare_bucket(spare) else {
|
||||
return None;
|
||||
};
|
||||
self.bridge_table.unallocated_bridges.pop()
|
||||
})
|
||||
}) else {
|
||||
// If there are no available bridges that can be assigned here, the only thing
|
||||
// that can be done is return an indication that updating the gone bridge
|
||||
// didn't work.
|
||||
// In this case, we do not mark the bridge as unreachable or remove it from the
|
||||
// reachable bridges so that we can still find it when a new bridge does become available
|
||||
println!("No available bridges");
|
||||
return ReplaceSuccess::NotReplaced;
|
||||
};
|
||||
for (bucketnum, offset) in positions.iter() {
|
||||
let mut bridgelines = match self.bridge_table.buckets.get(bucketnum) {
|
||||
Some(bridgelines) => *bridgelines,
|
||||
None => return ReplaceSuccess::NotFound,
|
||||
};
|
||||
assert!(bridgelines[*offset] == *bridge);
|
||||
bridgelines[*offset] = replacement;
|
||||
self.bridge_table.buckets.insert(*bucketnum, bridgelines);
|
||||
// Remove the bridge from the reachable bridges and add new bridge
|
||||
self.bridge_table
|
||||
.reachable
|
||||
.insert(replacement, positions.clone());
|
||||
// Remove the bridge from the bucket
|
||||
self.bridge_table.reachable.remove(bridge);
|
||||
}
|
||||
ReplaceSuccess::Replaced
|
||||
}
|
||||
|
||||
/// Mark a bridge as blocked
|
||||
|
@ -1012,6 +980,7 @@ pub fn pt_dbl(P: &RistrettoPoint) -> RistrettoPoint {
|
|||
pub mod proto {
|
||||
pub mod blockage_migration;
|
||||
pub mod check_blockage;
|
||||
pub mod errors;
|
||||
pub mod issue_invite;
|
||||
pub mod level_up;
|
||||
pub mod migration;
|
||||
|
|
|
@ -52,6 +52,8 @@ use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
|||
use super::check_blockage::MIN_TRUST_LEVEL;
|
||||
use super::level_up::LEVEL_INVITATIONS;
|
||||
|
||||
use super::errors::CredentialError;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Request {
|
||||
// Fields for blind showing the Lox credential
|
||||
|
@ -182,7 +184,7 @@ pub fn request(
|
|||
migration_cred: &cred::Migration,
|
||||
lox_pub: &IssuerPubKey,
|
||||
migration_pub: &IssuerPubKey,
|
||||
) -> Result<(Request, State), ProofError> {
|
||||
) -> Result<(Request, State), CredentialError> {
|
||||
let A: &RistrettoPoint = &CMZ_A;
|
||||
let B: &RistrettoPoint = &CMZ_B;
|
||||
let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
|
||||
|
@ -192,16 +194,24 @@ pub fn request(
|
|||
// ids match and the Lox credential bucket matches the Migration
|
||||
// credential from_bucket
|
||||
if lox_cred.id != migration_cred.lox_id || lox_cred.bucket != migration_cred.from_bucket {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::CredentialMismatch);
|
||||
}
|
||||
|
||||
// The trust level must be at least MIN_TRUST_LEVEL
|
||||
let level: u32 = match scalar_u32(&lox_cred.trust_level) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if level < MIN_TRUST_LEVEL {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
format!("level {:?} not in range", level),
|
||||
));
|
||||
}
|
||||
|
||||
// Blind showing the Lox credential
|
||||
|
|
|
@ -49,6 +49,8 @@ use super::super::scalar_u32;
|
|||
use super::super::{BridgeAuth, IssuerPubKey};
|
||||
use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
||||
|
||||
use super::errors::CredentialError;
|
||||
|
||||
/// The minimum trust level a Lox credential must have to be allowed to
|
||||
/// perform this protocol.
|
||||
pub const MIN_TRUST_LEVEL: u32 = 3;
|
||||
|
@ -122,7 +124,7 @@ define_proof! {
|
|||
pub fn request(
|
||||
lox_cred: &cred::Lox,
|
||||
lox_pub: &IssuerPubKey,
|
||||
) -> Result<(Request, State), ProofError> {
|
||||
) -> Result<(Request, State), CredentialError> {
|
||||
let A: &RistrettoPoint = &CMZ_A;
|
||||
let B: &RistrettoPoint = &CMZ_B;
|
||||
let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
|
||||
|
@ -132,10 +134,18 @@ pub fn request(
|
|||
// that trust_level >= MIN_TRUST_LEVEL
|
||||
let level: u32 = match scalar_u32(&lox_cred.trust_level) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if level < MIN_TRUST_LEVEL {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
format!("level {:?} not in range", level),
|
||||
));
|
||||
}
|
||||
|
||||
// Blind showing the Lox credential
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
use thiserror::Error;
|
||||
|
||||
/// This error is thrown if the number of buckets/keys in the bridge table
|
||||
/// exceeds u32 MAX.It is unlikely this error will ever occur.
|
||||
#[derive(Error, Debug)]
|
||||
pub enum CredentialError {
|
||||
#[error("time threshold for operation will not be met for {0} more days")]
|
||||
TimeThresholdNotMet(u32),
|
||||
#[error("credential has expired")]
|
||||
CredentialExpired,
|
||||
#[error("invalid field {0}: {1}")]
|
||||
InvalidField(String, String),
|
||||
#[error("exceeded blockages threshold")]
|
||||
ExceededBlockagesThreshold,
|
||||
#[error("credential has no available invitations")]
|
||||
NoInvitationsRemaining,
|
||||
#[error("supplied credentials do not match")]
|
||||
CredentialMismatch,
|
||||
}
|
|
@ -62,6 +62,8 @@ use super::super::scalar_u32;
|
|||
use super::super::{BridgeAuth, IssuerPubKey};
|
||||
use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
||||
|
||||
use super::errors::CredentialError;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Request {
|
||||
// Fields for blind showing the Lox credential
|
||||
|
@ -261,7 +263,7 @@ pub fn request(
|
|||
lox_pub: &IssuerPubKey,
|
||||
reach_pub: &IssuerPubKey,
|
||||
today: u32,
|
||||
) -> Result<(Request, State), ProofError> {
|
||||
) -> Result<(Request, State), CredentialError> {
|
||||
let A: &RistrettoPoint = &CMZ_A;
|
||||
let B: &RistrettoPoint = &CMZ_B;
|
||||
let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
|
||||
|
@ -270,20 +272,28 @@ pub fn request(
|
|||
// Ensure the credential can be correctly shown: it must be the case
|
||||
// that invites_remaining not be 0
|
||||
if lox_cred.invites_remaining == Scalar::ZERO {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::NoInvitationsRemaining);
|
||||
}
|
||||
// The buckets in the Lox and Bucket Reachability credentials have
|
||||
// to match
|
||||
if lox_cred.bucket != reach_cred.bucket {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::CredentialMismatch);
|
||||
}
|
||||
// The Bucket Reachability credential has to be dated today
|
||||
let reach_date: u32 = match scalar_u32(&reach_cred.date) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("date"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if reach_date != today {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("date"),
|
||||
String::from("reachability credential must be generated today"),
|
||||
));
|
||||
}
|
||||
// The new invites_remaining
|
||||
let new_invites_remaining = lox_cred.invites_remaining - Scalar::ONE;
|
||||
|
|
|
@ -55,6 +55,8 @@ use super::super::{pt_dbl, scalar_dbl, scalar_u32};
|
|||
use super::super::{BridgeAuth, IssuerPubKey};
|
||||
use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
||||
|
||||
use super::errors::CredentialError;
|
||||
|
||||
/// The maximum trust level in the system. A user can run this level
|
||||
/// upgrade protocol when they're already at the max level; they will
|
||||
/// get a fresh invites_remaining batch, and reset their level_since
|
||||
|
@ -272,7 +274,7 @@ pub fn request(
|
|||
lox_pub: &IssuerPubKey,
|
||||
reach_pub: &IssuerPubKey,
|
||||
today: u32,
|
||||
) -> Result<(Request, State), ProofError> {
|
||||
) -> Result<(Request, State), CredentialError> {
|
||||
let A: &RistrettoPoint = &CMZ_A;
|
||||
let B: &RistrettoPoint = &CMZ_B;
|
||||
let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
|
||||
|
@ -282,50 +284,83 @@ pub fn request(
|
|||
// that level_since + LEVEL_INTERVAL[level] <= today.
|
||||
let level_since: u32 = match scalar_u32(&lox_cred.level_since) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("level_since"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
// The trust level has to be at least 1
|
||||
let trust_level: u32 = match scalar_u32(&lox_cred.trust_level) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if trust_level < 1 || (trust_level as usize) > MAX_LEVEL {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
format!("level {:?} not in range", trust_level),
|
||||
));
|
||||
}
|
||||
// The trust level has to be no higher than the highest level
|
||||
let level_interval: u32 = match LEVEL_INTERVAL.get(trust_level as usize) {
|
||||
Some(&v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
format!("level {:?} not in range", trust_level),
|
||||
))
|
||||
}
|
||||
};
|
||||
if level_since + level_interval > today {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::TimeThresholdNotMet(
|
||||
level_since + level_interval - today,
|
||||
));
|
||||
}
|
||||
// The credential can't be _too_ old
|
||||
let diffdays = today - (level_since + level_interval);
|
||||
if diffdays > 511 {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::CredentialExpired);
|
||||
}
|
||||
// The current number of blockages
|
||||
let blockages: u32 = match scalar_u32(&lox_cred.blockages) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("blockages"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if blockages > MAX_BLOCKAGES[trust_level as usize] {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::ExceededBlockagesThreshold);
|
||||
}
|
||||
let blockage_diff = MAX_BLOCKAGES[trust_level as usize] - blockages;
|
||||
// The buckets in the Lox and Bucket Reachability credentials have
|
||||
// to match
|
||||
if lox_cred.bucket != reach_cred.bucket {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::CredentialMismatch);
|
||||
}
|
||||
// The Bucket Reachability credential has to be dated today
|
||||
let reach_date: u32 = match scalar_u32(&reach_cred.date) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("date"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if reach_date != today {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("date"),
|
||||
String::from("reachability credential must be generated today"),
|
||||
));
|
||||
}
|
||||
// The new trust level
|
||||
let new_level = if (trust_level as usize) < MAX_LEVEL {
|
||||
|
|
|
@ -46,6 +46,8 @@ use super::super::dup_filter::SeenType;
|
|||
use super::super::{BridgeAuth, IssuerPubKey};
|
||||
use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
||||
|
||||
use super::errors::CredentialError;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Request {
|
||||
// Fields for blind showing the Lox credential
|
||||
|
@ -153,7 +155,7 @@ pub fn request(
|
|||
migration_cred: &cred::Migration,
|
||||
lox_pub: &IssuerPubKey,
|
||||
migration_pub: &IssuerPubKey,
|
||||
) -> Result<(Request, State), ProofError> {
|
||||
) -> Result<(Request, State), CredentialError> {
|
||||
let A: &RistrettoPoint = &CMZ_A;
|
||||
let B: &RistrettoPoint = &CMZ_B;
|
||||
let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
|
||||
|
@ -163,13 +165,16 @@ pub fn request(
|
|||
// ids match and the Lox credential bucket matches the Migration
|
||||
// credential from_bucket
|
||||
if lox_cred.id != migration_cred.lox_id || lox_cred.bucket != migration_cred.from_bucket {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::CredentialMismatch);
|
||||
}
|
||||
|
||||
// This protocol only allows migrating from trust level 0 to trust
|
||||
// level 1
|
||||
if lox_cred.trust_level != Scalar::ZERO {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
String::from("must be zero"),
|
||||
));
|
||||
}
|
||||
|
||||
// Blind showing the Lox credential
|
||||
|
|
|
@ -38,6 +38,8 @@ use super::super::{pt_dbl, scalar_dbl, scalar_u32};
|
|||
use super::super::{BridgeAuth, IssuerPubKey};
|
||||
use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
||||
|
||||
use super::errors::CredentialError;
|
||||
|
||||
/// Invitations must be used within this many days of being issued.
|
||||
/// Note that if you change this number to be larger than 15, you must
|
||||
/// also add bits to the zero knowledge proof.
|
||||
|
@ -174,7 +176,7 @@ pub fn request(
|
|||
inv_cred: &cred::Invitation,
|
||||
invitation_pub: &IssuerPubKey,
|
||||
today: u32,
|
||||
) -> Result<(Request, State), ProofError> {
|
||||
) -> Result<(Request, State), CredentialError> {
|
||||
let A: &RistrettoPoint = &CMZ_A;
|
||||
let B: &RistrettoPoint = &CMZ_B;
|
||||
let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
|
||||
|
@ -184,16 +186,24 @@ pub fn request(
|
|||
// that date + INVITATION_EXPIRY >= today.
|
||||
let date: u32 = match scalar_u32(&inv_cred.date) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("date"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if date + INVITATION_EXPIRY < today {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::CredentialExpired);
|
||||
}
|
||||
let diffdays = date + INVITATION_EXPIRY - today;
|
||||
// If diffdays > 15, then since INVITATION_EXPIRY <= 15, then date
|
||||
// must be in the future. Reject.
|
||||
if diffdays > 15 {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("date"),
|
||||
String::from("credential was created in the future"),
|
||||
));
|
||||
}
|
||||
|
||||
// Blind showing the Invitation credential
|
||||
|
|
|
@ -48,6 +48,8 @@ use super::super::{pt_dbl, scalar_dbl, scalar_u32};
|
|||
use super::super::{BridgeAuth, IssuerPubKey};
|
||||
use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
||||
|
||||
use super::errors::CredentialError;
|
||||
|
||||
/// The minimum number of days a user has to be at trust level 0
|
||||
/// (untrusted) with their (single) bridge unblocked before they can
|
||||
/// move to level 1.
|
||||
|
@ -164,7 +166,7 @@ pub fn request(
|
|||
lox_cred: &cred::Lox,
|
||||
lox_pub: &IssuerPubKey,
|
||||
today: u32,
|
||||
) -> Result<(Request, State), ProofError> {
|
||||
) -> Result<(Request, State), CredentialError> {
|
||||
let A: &RistrettoPoint = &CMZ_A;
|
||||
let B: &RistrettoPoint = &CMZ_B;
|
||||
let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
|
||||
|
@ -174,14 +176,21 @@ pub fn request(
|
|||
// that level_since + UNTRUSTED_INTERVAL <= today.
|
||||
let level_since: u32 = match scalar_u32(&lox_cred.level_since) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("level_since"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if level_since + UNTRUSTED_INTERVAL > today {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::TimeThresholdNotMet(
|
||||
level_since + UNTRUSTED_INTERVAL - today,
|
||||
));
|
||||
}
|
||||
let diffdays = today - (level_since + UNTRUSTED_INTERVAL);
|
||||
if diffdays > 511 {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::CredentialExpired);
|
||||
}
|
||||
|
||||
// Blind showing the Lox credential
|
||||
|
|
|
@ -1091,21 +1091,21 @@ fn test_bridge_replace() {
|
|||
match case {
|
||||
"not found" => {
|
||||
// Case zero: bridge to be replaced is not in the bridgetable
|
||||
let random_bridgeline = &BridgeLine::random();
|
||||
let random_bridgeline = BridgeLine::random();
|
||||
assert!(
|
||||
!th.ba.bridge_table.reachable.contains_key(random_bridgeline),
|
||||
!th.ba.bridge_table.reachable.contains_key(&random_bridgeline),
|
||||
"Random bridgeline happens to be in the bridge_table (and should not be)"
|
||||
);
|
||||
assert!(
|
||||
th.ba
|
||||
.bridge_replace(random_bridgeline, Some(random_bridgeline))
|
||||
.bridge_replace(&random_bridgeline, Some(random_bridgeline))
|
||||
== ReplaceSuccess::NotFound,
|
||||
"Bridge should be marked as NotFound"
|
||||
);
|
||||
}
|
||||
"available" => {
|
||||
// Case one: available_bridge != null
|
||||
let random_bridgeline = &BridgeLine::random();
|
||||
let random_bridgeline = BridgeLine::random();
|
||||
let unallocated_bridgeline = &BridgeLine::random();
|
||||
th.ba
|
||||
.bridge_table
|
||||
|
@ -1115,7 +1115,7 @@ fn test_bridge_replace() {
|
|||
th.ba
|
||||
.bridge_table
|
||||
.reachable
|
||||
.get(random_bridgeline)
|
||||
.get(&random_bridgeline)
|
||||
.is_none(),
|
||||
"Random bridge already in table"
|
||||
);
|
||||
|
@ -1129,7 +1129,7 @@ fn test_bridge_replace() {
|
|||
th.ba
|
||||
.bridge_table
|
||||
.reachable
|
||||
.get(random_bridgeline)
|
||||
.get(&random_bridgeline)
|
||||
.is_some(),
|
||||
"Replacement bridge not added to reachable bridges"
|
||||
);
|
||||
|
|
|
@ -12,10 +12,11 @@ categories = ["rust-patterns"]
|
|||
repository = "https://gitlab.torproject.org/tpo/anti-censorship/lox.git/"
|
||||
|
||||
[dependencies]
|
||||
chrono = { version = "0.4.34", features = ["serde", "clock"] }
|
||||
lox-library = {path = "../lox-library", version = "0.1.0"}
|
||||
serde = "1"
|
||||
serde_json = "1.0.108"
|
||||
serde_with = "3.5.0"
|
||||
serde_json = "1.0.113"
|
||||
serde_with = "3.7.0"
|
||||
|
||||
|
||||
[features]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
use lox_library::bridge_table::{
|
||||
from_scalar, BridgeLine, BridgeTable, EncryptedBucket, MAX_BRIDGES_PER_BUCKET,
|
||||
};
|
||||
|
@ -92,6 +93,14 @@ pub const LOX_SYSTEM_INFO: LoxSystemInfo = LoxSystemInfo {
|
|||
min_blockage_migration_trust_level: check_blockage::MIN_TRUST_LEVEL,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct LoxNextUnlock {
|
||||
pub trust_level_unlock_date: DateTime<Utc>,
|
||||
pub invitation_unlock_date: DateTime<Utc>,
|
||||
pub num_invitations_unlocked: u32,
|
||||
pub blockage_migration_unlock_date: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct EncBridgeTable {
|
||||
|
|
|
@ -21,14 +21,14 @@ lazy_static = "1.4.0"
|
|||
lox-library = { path = "../lox-library", version = "0.1.0" }
|
||||
lox_utils = { path = "../lox-utils", version = "0.1.0" }
|
||||
wasm-bindgen = "0.2"
|
||||
time = "0.3.31"
|
||||
serde_json = "1.0.108"
|
||||
time = "0.3.34"
|
||||
serde_json = "1.0.113"
|
||||
|
||||
console_error_panic_hook = "0.1.7"
|
||||
js-sys = "0.3.66"
|
||||
js-sys = "0.3.69"
|
||||
rand = { version = "0.7", features = ["wasm-bindgen"] }
|
||||
lox-zkp = { git = "https://gitlab.torproject.org/onyinyang/lox-zkp", version = "0.8.0" }
|
||||
|
||||
[dependencies.chrono]
|
||||
version = "0.4.31"
|
||||
version = "0.4.34"
|
||||
features = ["serde", "wasmbind"]
|
||||
|
|
|
@ -16,7 +16,7 @@ import init, {
|
|||
handle_check_blockage,
|
||||
blockage_migration,
|
||||
handle_blockage_migration,
|
||||
set_panic_hook, get_last_upgrade_time, get_trust_level, get_invites_remaining, get_issued_invite_expiry, get_received_invite_expiry, get_bridgelines_from_bucket} from "./pkg/lox_wasm.js";
|
||||
set_panic_hook, get_last_upgrade_time, get_trust_level, get_invites_remaining, get_next_unlock, get_received_invite_expiry, get_bridgelines_from_bucket} from "./pkg/lox_wasm.js";
|
||||
let pubkeys = await simple_request("/pubkeys");
|
||||
console.log("Got pubkeys: " + pubkeys);
|
||||
let constants = await simple_request("/constants");
|
||||
|
@ -42,10 +42,12 @@ let open_lox_cred = await init().then(() => {
|
|||
});
|
||||
return cred;
|
||||
});
|
||||
|
||||
let unlock_info = get_next_unlock(constants, open_lox_cred);
|
||||
console.log("Unlock info: "+unlock_info);
|
||||
get_last_upgrade_time(open_lox_cred);
|
||||
get_trust_level(open_lox_cred);
|
||||
get_invites_remaining(open_lox_cred);
|
||||
|
||||
let encrypted_table = await simple_request("/reachability");
|
||||
let info_five = get_bridgelines_from_bucket(open_lox_cred, encrypted_table);
|
||||
console.log("Bridgelines available: "+info_five);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use chrono::Utc;
|
||||
use chrono::{DateTime, NaiveDateTime, NaiveTime, Utc};
|
||||
use julianday::JulianDay;
|
||||
use lox_library::cred::{Invitation, Migration};
|
||||
use lox_library::proto::{
|
||||
|
@ -793,11 +793,92 @@ pub fn get_bridgelines_from_bucket(
|
|||
pub fn invitation_is_trusted(unspecified_invitation_str: String) -> Result<bool, JsValue> {
|
||||
match serde_json::from_str::<Invitation>(&unspecified_invitation_str) {
|
||||
Ok(_) => Ok(true),
|
||||
Err(_) => {
|
||||
match serde_json::from_str::<lox_utils::Invite>(&unspecified_invitation_str){
|
||||
Ok(_) => Ok(false),
|
||||
Err(e) => Err(JsValue::from(e.to_string())),
|
||||
}
|
||||
}
|
||||
Err(_) => match serde_json::from_str::<lox_utils::Invite>(&unspecified_invitation_str) {
|
||||
Ok(_) => Ok(false),
|
||||
Err(e) => Err(JsValue::from(e.to_string())),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn get_next_unlock(constants_str: String, lox_cred_str: String) -> Result<String, JsValue> {
|
||||
let constants: lox_utils::LoxSystemInfo = match serde_json::from_str(&constants_str) {
|
||||
Ok(constants) => constants,
|
||||
Err(e) => return Err(JsValue::from(e.to_string())),
|
||||
};
|
||||
let lox_cred: lox_utils::LoxCredential = match serde_json::from_str(&lox_cred_str) {
|
||||
Ok(lox_cred) => lox_cred,
|
||||
Err(e) => return Err(JsValue::from(e.to_string())),
|
||||
};
|
||||
let trust_level = scalar_u32(&lox_cred.lox_credential.trust_level).unwrap();
|
||||
let (days_to_next_level, mut invitations_at_next_level) = match trust_level as usize {
|
||||
// If the credential is at trust level 0, we use the untrusted interval from the
|
||||
// trust promotion protocol to calculate the date of the next level update
|
||||
0 => (constants.untrusted_interval, 0),
|
||||
|
||||
// Otherwise, we usethe invitation and upgrade dates from the level up protocol constants
|
||||
_ => (
|
||||
constants.level_interval[trust_level as usize],
|
||||
constants.level_invitations[trust_level as usize],
|
||||
),
|
||||
};
|
||||
let mut days_to_invite_inc = days_to_next_level;
|
||||
// If there are no invitations at the next trust level upgrade
|
||||
// i.e., if the credential is at level 0, calculate the time until they will
|
||||
// unlock invitations
|
||||
if invitations_at_next_level == 0 {
|
||||
days_to_invite_inc =
|
||||
days_to_next_level + constants.level_interval[trust_level as usize + 1];
|
||||
invitations_at_next_level = constants.level_invitations[trust_level as usize + 1];
|
||||
}
|
||||
let days_to_blockage_migration_unlock =
|
||||
match trust_level < constants.min_blockage_migration_trust_level {
|
||||
// If the credential is greater than the minimum level that enables
|
||||
// migrating after a blockage, the time to unlock is 0, otherwise we
|
||||
// add the time to upgrade until that level
|
||||
true => {
|
||||
let mut blockage_days = days_to_next_level;
|
||||
let mut count = 1;
|
||||
while trust_level + count < constants.min_blockage_migration_trust_level {
|
||||
blockage_days += constants.level_interval[trust_level as usize + count as usize];
|
||||
count += 1;
|
||||
}
|
||||
blockage_days
|
||||
}
|
||||
false => 0,
|
||||
};
|
||||
let day_of_level_unlock =
|
||||
(scalar_u32(&lox_cred.lox_credential.level_since).unwrap() + days_to_next_level) as i32;
|
||||
let level_unlock_date = JulianDay::new(day_of_level_unlock).to_date();
|
||||
let day_of_invite_unlock =
|
||||
(scalar_u32(&lox_cred.lox_credential.level_since).unwrap() + days_to_invite_inc) as i32;
|
||||
let invite_unlock_date = JulianDay::new(day_of_invite_unlock).to_date();
|
||||
let day_of_blockage_migration_unlock = (scalar_u32(&lox_cred.lox_credential.level_since).unwrap() + days_to_blockage_migration_unlock) as i32;
|
||||
let blockage_migration_unlock_date =
|
||||
JulianDay::new(day_of_blockage_migration_unlock as i32).to_date();
|
||||
let next_unlock: lox_utils::LoxNextUnlock = lox_utils::LoxNextUnlock {
|
||||
trust_level_unlock_date: DateTime::<Utc>::from_naive_utc_and_offset(
|
||||
NaiveDateTime::new(level_unlock_date, NaiveTime::from_hms_opt(0, 0, 0).unwrap()),
|
||||
Utc,
|
||||
),
|
||||
invitation_unlock_date: DateTime::<Utc>::from_naive_utc_and_offset(
|
||||
NaiveDateTime::new(
|
||||
invite_unlock_date,
|
||||
NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
|
||||
),
|
||||
Utc,
|
||||
),
|
||||
num_invitations_unlocked: invitations_at_next_level,
|
||||
blockage_migration_unlock_date: DateTime::<Utc>::from_naive_utc_and_offset(
|
||||
NaiveDateTime::new(
|
||||
blockage_migration_unlock_date,
|
||||
NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
|
||||
),
|
||||
Utc,
|
||||
),
|
||||
};
|
||||
match serde_json::to_string(&next_unlock) {
|
||||
Ok(next_unlock) => Ok(next_unlock),
|
||||
Err(e) => Err(JsValue::from(e.to_string())),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,6 @@ sha1 = "0.10.6"
|
|||
tokio = { version = "1", features = ["full", "macros"] }
|
||||
reqwest = { version = "0.11", features = ["json", "stream"]}
|
||||
tokio-stream = "0.1.14"
|
||||
futures = "0.3.29"
|
||||
futures = "0.3.30"
|
||||
tokio-util = "0.7.10"
|
||||
chrono = { version = "0.4.31", features = ["serde", "clock"] }
|
||||
chrono = { version = "0.4.34", features = ["serde", "clock"] }
|
||||
|
|
Loading…
Reference in New Issue