Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
048199e30b | ||
|
|
414e83f696 | ||
|
|
225c8f762e | ||
|
|
887fc28ab2 | ||
|
|
294d3b99c3 | ||
|
|
53990672ae | ||
|
|
9c1b21cbfe | ||
|
|
2f63417646 | ||
|
|
3b25160852 | ||
|
|
34ad549cde | ||
|
|
f8b1fe5035 | ||
|
|
f2001dc34a | ||
|
|
b593001229 | ||
|
|
5913b9f87a | ||
|
|
77f35f9f43 | ||
|
|
9e06cc9482 | ||
|
|
e66fa4ac42 | ||
|
|
99e117f620 | ||
|
|
8250e00f05 | ||
|
|
c9f87ec563 | ||
|
|
ceaa01e8b4 |
Generated
+279
-133
@@ -2,6 +2,12 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
@@ -23,10 +29,15 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "async-trait"
|
||||||
version = "0.5.2"
|
version = "0.1.52"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
@@ -60,20 +71,14 @@ version = "0.13.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bitcoin_hashes"
|
|
||||||
version = "0.9.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7ce18265ec2324ad075345d5814fbeed4f41f0a660055dc78840b74d19b874b1"
|
|
||||||
dependencies = [
|
|
||||||
"serde 1.0.136",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitcoin_hashes"
|
name = "bitcoin_hashes"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "006cc91e1a1d99819bc5b8214be3555c1f0611b169f527a1fdc54ed1f2b745b0"
|
checksum = "006cc91e1a1d99819bc5b8214be3555c1f0611b169f527a1fdc54ed1f2b745b0"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
@@ -83,11 +88,32 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.9.0"
|
version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
|
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"block-padding",
|
||||||
|
"byte-tools",
|
||||||
|
"byteorder",
|
||||||
|
"generic-array 0.12.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array 0.14.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-padding"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
|
||||||
|
dependencies = [
|
||||||
|
"byte-tools",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -96,6 +122,12 @@ version = "3.9.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
|
checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byte-tools"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
@@ -110,9 +142,9 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.72"
|
version = "1.0.73"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
|
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@@ -131,15 +163,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "config"
|
name = "config"
|
||||||
version = "0.11.0"
|
version = "0.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b1b9d958c2b1368a663f05538fc1b5975adce1e19f435acceae987aceeeb369"
|
checksum = "54ad70579325f1a38ea4c13412b82241c5900700a69785d73e2736bd65a33f86"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"json5",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"nom",
|
"nom",
|
||||||
|
"pathdiff",
|
||||||
|
"ron",
|
||||||
"rust-ini",
|
"rust-ini",
|
||||||
"serde 1.0.136",
|
"serde",
|
||||||
"serde-hjson",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"toml",
|
"toml",
|
||||||
"yaml-rust",
|
"yaml-rust",
|
||||||
@@ -180,6 +215,16 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array 0.14.5",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dashmap"
|
name = "dashmap"
|
||||||
version = "5.1.0"
|
version = "5.1.0"
|
||||||
@@ -193,11 +238,30 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.9.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
|
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"generic-array 0.12.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer 0.10.2",
|
||||||
|
"crypto-common",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dlv-list"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68df3f2b690c1b86e65ef7830956aededf3cb0a16f898f79b9a6f421a7b6211b"
|
||||||
|
dependencies = [
|
||||||
|
"rand 0.8.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -213,6 +277,12 @@ dependencies = [
|
|||||||
"termcolor",
|
"termcolor",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fake-simd"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fallible-iterator"
|
name = "fallible-iterator"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@@ -366,6 +436,15 @@ dependencies = [
|
|||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.12.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.5"
|
version = "0.14.5"
|
||||||
@@ -378,9 +457,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.4"
|
version = "0.2.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
|
checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -400,7 +479,7 @@ dependencies = [
|
|||||||
"nonzero_ext",
|
"nonzero_ext",
|
||||||
"parking_lot 0.12.0",
|
"parking_lot 0.12.0",
|
||||||
"quanta",
|
"quanta",
|
||||||
"rand 0.8.4",
|
"rand 0.8.5",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -423,13 +502,22 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
||||||
|
dependencies = [
|
||||||
|
"ahash 0.4.7",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash 0.7.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -438,7 +526,7 @@ version = "0.7.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf"
|
checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown",
|
"hashbrown 0.11.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -551,7 +639,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 1.1.0",
|
"autocfg 1.1.0",
|
||||||
"hashbrown",
|
"hashbrown 0.11.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -578,30 +666,28 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "json5"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"pest_derive",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lexical-core"
|
|
||||||
version = "0.7.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
|
|
||||||
dependencies = [
|
|
||||||
"arrayvec",
|
|
||||||
"bitflags",
|
|
||||||
"cfg-if",
|
|
||||||
"ryu",
|
|
||||||
"static_assertions",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.117"
|
version = "0.2.119"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c"
|
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsqlite3-sys"
|
name = "libsqlite3-sys"
|
||||||
@@ -646,6 +732,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "maplit"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matches"
|
name = "matches"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
@@ -659,10 +751,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "minimal-lexical"
|
||||||
version = "0.7.14"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
@@ -706,12 +804,12 @@ checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "5.1.2"
|
version = "7.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
|
checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lexical-core",
|
|
||||||
"memchr",
|
"memchr",
|
||||||
|
"minimal-lexical",
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -723,9 +821,9 @@ checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-rs-relay"
|
name = "nostr-rs-relay"
|
||||||
version = "0.5.0"
|
version = "0.5.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitcoin_hashes 0.9.7",
|
"bitcoin_hashes",
|
||||||
"config",
|
"config",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"futures",
|
"futures",
|
||||||
@@ -741,10 +839,10 @@ dependencies = [
|
|||||||
"parse_duration",
|
"parse_duration",
|
||||||
"r2d2",
|
"r2d2",
|
||||||
"r2d2_sqlite",
|
"r2d2_sqlite",
|
||||||
"rand 0.8.4",
|
"rand 0.8.5",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
"secp256k1",
|
"secp256k1",
|
||||||
"serde 1.0.136",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
@@ -773,7 +871,7 @@ dependencies = [
|
|||||||
"num-integer",
|
"num-integer",
|
||||||
"num-iter",
|
"num-iter",
|
||||||
"num-rational",
|
"num-rational",
|
||||||
"num-traits 0.2.14",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -784,7 +882,7 @@ checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 1.1.0",
|
"autocfg 1.1.0",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits 0.2.14",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -794,7 +892,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95"
|
checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 1.1.0",
|
"autocfg 1.1.0",
|
||||||
"num-traits 0.2.14",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -804,7 +902,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 1.1.0",
|
"autocfg 1.1.0",
|
||||||
"num-traits 0.2.14",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -815,7 +913,7 @@ checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 1.1.0",
|
"autocfg 1.1.0",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits 0.2.14",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -827,16 +925,7 @@ dependencies = [
|
|||||||
"autocfg 1.1.0",
|
"autocfg 1.1.0",
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits 0.2.14",
|
"num-traits",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-traits"
|
|
||||||
version = "0.1.43"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
|
||||||
dependencies = [
|
|
||||||
"num-traits 0.2.14",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -866,9 +955,9 @@ checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opaque-debug"
|
name = "opaque-debug"
|
||||||
version = "0.3.0"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl"
|
name = "openssl"
|
||||||
@@ -903,6 +992,16 @@ dependencies = [
|
|||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ordered-multimap"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1c672c7ad9ec066e428c00eb917124a06f08db19e2584de982cc34b1f4c12485"
|
||||||
|
dependencies = [
|
||||||
|
"dlv-list",
|
||||||
|
"hashbrown 0.9.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
@@ -962,12 +1061,61 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pathdiff"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest"
|
||||||
|
version = "2.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
|
||||||
|
dependencies = [
|
||||||
|
"ucd-trie",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest_derive"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"pest_generator",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest_generator"
|
||||||
|
version = "2.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
|
||||||
|
dependencies = [
|
||||||
|
"pest",
|
||||||
|
"pest_meta",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pest_meta"
|
||||||
|
version = "2.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
|
||||||
|
dependencies = [
|
||||||
|
"maplit",
|
||||||
|
"pest",
|
||||||
|
"sha-1 0.8.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
@@ -1057,7 +1205,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"rand_chacha 0.1.1",
|
"rand_chacha 0.1.1",
|
||||||
"rand_core 0.4.2",
|
"rand_core 0.4.2",
|
||||||
"rand_hc 0.1.0",
|
"rand_hc",
|
||||||
"rand_isaac",
|
"rand_isaac",
|
||||||
"rand_jitter",
|
"rand_jitter",
|
||||||
"rand_os",
|
"rand_os",
|
||||||
@@ -1068,14 +1216,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.4"
|
version = "0.8.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"rand_chacha 0.3.1",
|
"rand_chacha 0.3.1",
|
||||||
"rand_core 0.6.3",
|
"rand_core 0.6.3",
|
||||||
"rand_hc 0.3.1",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1131,15 +1278,6 @@ dependencies = [
|
|||||||
"rand_core 0.3.1",
|
"rand_core 0.3.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_hc"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.6.3",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_isaac"
|
name = "rand_isaac"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@@ -1246,6 +1384,17 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ron"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b861ecaade43ac97886a512b360d01d66be9f41f3c61088b42cedf92e03d678"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"bitflags",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rusqlite"
|
name = "rusqlite"
|
||||||
version = "0.26.3"
|
version = "0.26.3"
|
||||||
@@ -1263,9 +1412,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rust-ini"
|
name = "rust-ini"
|
||||||
version = "0.13.0"
|
version = "0.17.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2"
|
checksum = "63471c4aa97a1cf8332a5f97709a79a4234698de6a1f5087faf66f2dae810e22"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"ordered-multimap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
@@ -1300,14 +1453,14 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "secp256k1"
|
name = "secp256k1"
|
||||||
version = "0.21.2"
|
version = "0.21.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab7883017d5b21f011ef8040ea9c6c7ac90834c0df26a69e4c0b06276151f125"
|
checksum = "9c42e6f1735c5f00f51e43e28d6634141f2bcad10931b2609ddd74a86d751260"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitcoin_hashes 0.10.0",
|
"bitcoin_hashes",
|
||||||
"rand 0.6.5",
|
"rand 0.6.5",
|
||||||
"secp256k1-sys",
|
"secp256k1-sys",
|
||||||
"serde 1.0.136",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1342,12 +1495,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde"
|
|
||||||
version = "0.8.23"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.136"
|
version = "1.0.136"
|
||||||
@@ -1357,18 +1504,6 @@ dependencies = [
|
|||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde-hjson"
|
|
||||||
version = "0.9.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8"
|
|
||||||
dependencies = [
|
|
||||||
"lazy_static",
|
|
||||||
"num-traits 0.1.43",
|
|
||||||
"regex",
|
|
||||||
"serde 0.8.23",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.136"
|
version = "1.0.136"
|
||||||
@@ -1389,20 +1524,30 @@ dependencies = [
|
|||||||
"indexmap",
|
"indexmap",
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde 1.0.136",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha-1"
|
name = "sha-1"
|
||||||
version = "0.9.8"
|
version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6"
|
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer 0.7.3",
|
||||||
|
"digest 0.8.1",
|
||||||
|
"fake-simd",
|
||||||
|
"opaque-debug",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha-1"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
"digest",
|
"digest 0.10.3",
|
||||||
"opaque-debug",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1436,12 +1581,6 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "static_assertions"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.86"
|
version = "1.0.86"
|
||||||
@@ -1513,9 +1652,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.16.1"
|
version = "1.17.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a"
|
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1523,9 +1662,10 @@ dependencies = [
|
|||||||
"mio",
|
"mio",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"parking_lot 0.11.2",
|
"parking_lot 0.12.0",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
@@ -1553,9 +1693,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-tungstenite"
|
name = "tokio-tungstenite"
|
||||||
version = "0.16.1"
|
version = "0.17.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e80b39df6afcc12cdf752398ade96a6b9e99c903dfdc36e53ad10b9c366bca72"
|
checksum = "06cda1232a49558c46f8a504d5b93101d42c0bf7f911f12a105ba48168f821ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"log",
|
"log",
|
||||||
@@ -1583,7 +1723,7 @@ version = "0.5.8"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde 1.0.136",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1594,9 +1734,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.30"
|
version = "0.1.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2d8d93354fe2a8e50d5953f5ae2e47a3fc2ef03292e7ea46e3cc38f549525fb9"
|
checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
@@ -1620,9 +1760,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tungstenite"
|
name = "tungstenite"
|
||||||
version = "0.16.0"
|
version = "0.17.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ad3713a14ae247f22a728a0456a545df14acf3867f905adff84be99e23b3ad1"
|
checksum = "d96a2dea40e7570482f28eb57afbe42d97551905da6a9400acc5c328d24004f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
@@ -1630,8 +1770,8 @@ dependencies = [
|
|||||||
"http",
|
"http",
|
||||||
"httparse",
|
"httparse",
|
||||||
"log",
|
"log",
|
||||||
"rand 0.8.4",
|
"rand 0.8.5",
|
||||||
"sha-1",
|
"sha-1 0.10.0",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"url",
|
"url",
|
||||||
"utf-8",
|
"utf-8",
|
||||||
@@ -1643,6 +1783,12 @@ version = "1.15.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ucd-trie"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
|
|||||||
+5
-5
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nostr-rs-relay"
|
name = "nostr-rs-relay"
|
||||||
version = "0.5.0"
|
version = "0.5.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@@ -9,12 +9,12 @@ env_logger = "^0.9"
|
|||||||
tokio = { version = "^1.16", features = ["full"] }
|
tokio = { version = "^1.16", features = ["full"] }
|
||||||
futures = "^0.3"
|
futures = "^0.3"
|
||||||
futures-util = "^0.3"
|
futures-util = "^0.3"
|
||||||
tokio-tungstenite = "^0.16"
|
tokio-tungstenite = "^0.17"
|
||||||
tungstenite = "^0.16"
|
tungstenite = "^0.17"
|
||||||
thiserror = "^1"
|
thiserror = "^1"
|
||||||
uuid = { version = "^0.8", features = ["v4"] }
|
uuid = { version = "^0.8", features = ["v4"] }
|
||||||
config = { version = "0.11", features = ["toml"] }
|
config = { version = "^0.12", features = ["toml"] }
|
||||||
bitcoin_hashes = { version = "^0.9", features = ["serde"] }
|
bitcoin_hashes = { version = "^0.10", features = ["serde"] }
|
||||||
secp256k1 = {version = "^0.21", features = ["rand", "rand-std", "serde", "bitcoin_hashes"] }
|
secp256k1 = {version = "^0.21", features = ["rand", "rand-std", "serde", "bitcoin_hashes"] }
|
||||||
serde = { version = "^1.0", features = ["derive"] }
|
serde = { version = "^1.0", features = ["derive"] }
|
||||||
serde_json = {version = "^1.0", features = ["preserve_order"]}
|
serde_json = {version = "^1.0", features = ["preserve_order"]}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ NIPs with a relay-specific implementation are listed here.
|
|||||||
- [x] NIP-01: Id/Author prefix search (_experimental_)
|
- [x] NIP-01: Id/Author prefix search (_experimental_)
|
||||||
- [x] NIP-02: Hide old contact list events
|
- [x] NIP-02: Hide old contact list events
|
||||||
- [ ] NIP-03: OpenTimestamps
|
- [ ] NIP-03: OpenTimestamps
|
||||||
- [ ] NIP-05: Mapping Nostr keys to DNS identifiers
|
- [x] NIP-05: Mapping Nostr keys to DNS identifiers
|
||||||
- [ ] NIP-09: Event deletion
|
- [ ] NIP-09: Event deletion
|
||||||
- [x] NIP-11: Relay information document
|
- [x] NIP-11: Relay information document
|
||||||
- [x] NIP-12: Generic tag search (_experimental_)
|
- [x] NIP-12: Generic tag search (_experimental_)
|
||||||
|
|||||||
+2
-2
@@ -63,8 +63,8 @@ reject_future_seconds = 1800
|
|||||||
#broadcast_buffer = 16384
|
#broadcast_buffer = 16384
|
||||||
|
|
||||||
# Event persistence buffer size, in number of events. This provides
|
# Event persistence buffer size, in number of events. This provides
|
||||||
# backpressure to senders if writes are slow. Defaults to 16.
|
# backpressure to senders if writes are slow.
|
||||||
#event_persist_buffer = 16
|
#event_persist_buffer = 4096
|
||||||
|
|
||||||
[authorization]
|
[authorization]
|
||||||
# Pubkey addresses in this array are whitelisted for event publishing.
|
# Pubkey addresses in this array are whitelisted for event publishing.
|
||||||
|
|||||||
+13
-10
@@ -1,4 +1,5 @@
|
|||||||
//! Configuration file and settings management
|
//! Configuration file and settings management
|
||||||
|
use config::{Config, ConfigError, File};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use log::*;
|
use log::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -138,27 +139,29 @@ pub struct Settings {
|
|||||||
|
|
||||||
impl Settings {
|
impl Settings {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let d = Self::default();
|
let default_settings = Self::default();
|
||||||
// attempt to construct settings with file
|
// attempt to construct settings with file
|
||||||
// Self::new_from_default(&d).unwrap_or(d)
|
let from_file = Self::new_from_default(&default_settings);
|
||||||
let from_file = Self::new_from_default(&d);
|
|
||||||
match from_file {
|
match from_file {
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("Error reading config file ({:?})", e);
|
warn!("Error reading config file ({:?})", e);
|
||||||
d
|
default_settings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_from_default(default: &Settings) -> Result<Self, config::ConfigError> {
|
fn new_from_default(default: &Settings) -> Result<Self, ConfigError> {
|
||||||
let config: config::Config = config::Config::new();
|
let builder = Config::builder();
|
||||||
let mut settings: Settings = config
|
let config: Config = builder
|
||||||
// use defaults
|
// use defaults
|
||||||
.with_merged(config::Config::try_from(default).unwrap())?
|
.add_source(Config::try_from(default)?)
|
||||||
// override with file contents
|
// override with file contents
|
||||||
.with_merged(config::File::with_name("config"))?
|
.add_source(File::with_name("config"))
|
||||||
.try_into()?;
|
.build()?
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
|
let mut settings: Settings = config.try_deserialize()?;
|
||||||
// ensure connection pool size is logical
|
// ensure connection pool size is logical
|
||||||
if settings.database.min_conn > settings.database.max_conn {
|
if settings.database.min_conn > settings.database.max_conn {
|
||||||
panic!(
|
panic!(
|
||||||
|
|||||||
@@ -27,6 +27,13 @@ use tokio::task;
|
|||||||
|
|
||||||
pub type SqlitePool = r2d2::Pool<r2d2_sqlite::SqliteConnectionManager>;
|
pub type SqlitePool = r2d2::Pool<r2d2_sqlite::SqliteConnectionManager>;
|
||||||
pub type PooledConnection = r2d2::PooledConnection<r2d2_sqlite::SqliteConnectionManager>;
|
pub type PooledConnection = r2d2::PooledConnection<r2d2_sqlite::SqliteConnectionManager>;
|
||||||
|
|
||||||
|
/// Events submitted from a client, with a return channel for notices
|
||||||
|
pub struct SubmittedEvent {
|
||||||
|
pub event: Event,
|
||||||
|
pub notice_tx: tokio::sync::mpsc::Sender<String>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Database file
|
/// Database file
|
||||||
pub const DB_FILE: &str = "nostr.db";
|
pub const DB_FILE: &str = "nostr.db";
|
||||||
|
|
||||||
@@ -76,7 +83,7 @@ pub fn build_conn(flags: OpenFlags) -> Result<Connection> {
|
|||||||
|
|
||||||
/// Spawn a database writer that persists events to the SQLite store.
|
/// Spawn a database writer that persists events to the SQLite store.
|
||||||
pub async fn db_writer(
|
pub async fn db_writer(
|
||||||
mut event_rx: tokio::sync::mpsc::Receiver<Event>,
|
mut event_rx: tokio::sync::mpsc::Receiver<SubmittedEvent>,
|
||||||
bcast_tx: tokio::sync::broadcast::Sender<Event>,
|
bcast_tx: tokio::sync::broadcast::Sender<Event>,
|
||||||
metadata_tx: tokio::sync::broadcast::Sender<Event>,
|
metadata_tx: tokio::sync::broadcast::Sender<Event>,
|
||||||
mut shutdown: tokio::sync::broadcast::Receiver<()>,
|
mut shutdown: tokio::sync::broadcast::Receiver<()>,
|
||||||
@@ -131,18 +138,20 @@ pub async fn db_writer(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let mut event_write = false;
|
let mut event_write = false;
|
||||||
let event = next_event.unwrap();
|
let subm_event = next_event.unwrap();
|
||||||
|
let event = subm_event.event;
|
||||||
|
let notice_tx = subm_event.notice_tx;
|
||||||
// check if this event is authorized.
|
// check if this event is authorized.
|
||||||
if let Some(allowed_addrs) = whitelist {
|
if let Some(allowed_addrs) = whitelist {
|
||||||
debug!("Checking against pubkey whitelist");
|
|
||||||
// if the event address is not in allowed_addrs.
|
// if the event address is not in allowed_addrs.
|
||||||
if !allowed_addrs.contains(&event.pubkey) {
|
if !allowed_addrs.contains(&event.pubkey) {
|
||||||
info!(
|
info!(
|
||||||
"Rejecting event {}, unauthorized author",
|
"Rejecting event {}, unauthorized author",
|
||||||
event.get_event_id_prefix()
|
event.get_event_id_prefix()
|
||||||
);
|
);
|
||||||
// TODO: define a channel that can send NOTICEs back to the client.
|
notice_tx
|
||||||
|
.try_send("pubkey is not allowed to publish to this relay".to_owned())
|
||||||
|
.ok();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,6 +180,12 @@ pub async fn db_writer(
|
|||||||
uv.name.to_string(),
|
uv.name.to_string(),
|
||||||
event.get_author_prefix()
|
event.get_author_prefix()
|
||||||
);
|
);
|
||||||
|
notice_tx
|
||||||
|
.try_send(
|
||||||
|
"NIP-05 verification is no longer valid (expired/wrong domain)"
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,6 +194,9 @@ pub async fn db_writer(
|
|||||||
"no verification records found for pubkey: {:?}",
|
"no verification records found for pubkey: {:?}",
|
||||||
event.get_author_prefix()
|
event.get_author_prefix()
|
||||||
);
|
);
|
||||||
|
notice_tx
|
||||||
|
.try_send("NIP-05 verification needed to publish events".to_owned())
|
||||||
|
.ok();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -207,6 +225,12 @@ pub async fn db_writer(
|
|||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!("event insert failed: {:?}", err);
|
warn!("event insert failed: {:?}", err);
|
||||||
|
notice_tx
|
||||||
|
.try_send(
|
||||||
|
"relay experienced an error trying to publish the latest event"
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -479,7 +503,7 @@ fn query_from_sub(sub: &Subscription) -> (String, Vec<Box<dyn ToSql>>) {
|
|||||||
/// query is immediately aborted.
|
/// query is immediately aborted.
|
||||||
pub async fn db_query(
|
pub async fn db_query(
|
||||||
sub: Subscription,
|
sub: Subscription,
|
||||||
conn: PooledConnection,
|
pool: SqlitePool,
|
||||||
query_tx: tokio::sync::mpsc::Sender<QueryResult>,
|
query_tx: tokio::sync::mpsc::Sender<QueryResult>,
|
||||||
mut abandon_query_rx: tokio::sync::oneshot::Receiver<()>,
|
mut abandon_query_rx: tokio::sync::oneshot::Receiver<()>,
|
||||||
) {
|
) {
|
||||||
@@ -489,11 +513,22 @@ pub async fn db_query(
|
|||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
// generate SQL query
|
// generate SQL query
|
||||||
let (q, p) = query_from_sub(&sub);
|
let (q, p) = query_from_sub(&sub);
|
||||||
|
debug!("SQL generated in {:?}", start.elapsed());
|
||||||
|
// show pool stats
|
||||||
|
debug!("DB pool stats: {:?}", pool.state());
|
||||||
|
let start = Instant::now();
|
||||||
|
if let Ok(conn) = pool.get() {
|
||||||
// execute the query. Don't cache, since queries vary so much.
|
// execute the query. Don't cache, since queries vary so much.
|
||||||
let mut stmt = conn.prepare(&q)?;
|
let mut stmt = conn.prepare(&q)?;
|
||||||
let mut event_rows = stmt.query(rusqlite::params_from_iter(p))?;
|
let mut event_rows = stmt.query(rusqlite::params_from_iter(p))?;
|
||||||
|
let mut first_result = true;
|
||||||
while let Some(row) = event_rows.next()? {
|
while let Some(row) = event_rows.next()? {
|
||||||
// check if this is still active (we could do this every N rows)
|
if first_result {
|
||||||
|
debug!("time to first result: {:?}", start.elapsed());
|
||||||
|
first_result = false;
|
||||||
|
}
|
||||||
|
// check if this is still active
|
||||||
|
// TODO: check every N rows
|
||||||
if abandon_query_rx.try_recv().is_ok() {
|
if abandon_query_rx.try_recv().is_ok() {
|
||||||
debug!("query aborted");
|
debug!("query aborted");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -512,6 +547,9 @@ pub async fn db_query(
|
|||||||
row_count,
|
row_count,
|
||||||
start.elapsed()
|
start.elapsed()
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
warn!("Could not get a database connection for querying");
|
||||||
|
}
|
||||||
let ok: Result<()> = Ok(());
|
let ok: Result<()> = Ok(());
|
||||||
ok
|
ok
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -148,6 +148,8 @@ impl Event {
|
|||||||
// ** [0, pubkey-hex-string, created-at-num, kind-num, tags-array-of-arrays, content-string]
|
// ** [0, pubkey-hex-string, created-at-num, kind-num, tags-array-of-arrays, content-string]
|
||||||
// * serialize with no spaces/newlines
|
// * serialize with no spaces/newlines
|
||||||
let c_opt = self.to_canonical();
|
let c_opt = self.to_canonical();
|
||||||
|
debug!("Canonical: {:?}", &c_opt);
|
||||||
|
debug!("Canonical: {}", c_opt.as_ref().unwrap());
|
||||||
if c_opt.is_none() {
|
if c_opt.is_none() {
|
||||||
debug!("event could not be canonicalized");
|
debug!("event could not be canonicalized");
|
||||||
return false;
|
return false;
|
||||||
@@ -156,6 +158,7 @@ impl Event {
|
|||||||
// * compute the sha256sum.
|
// * compute the sha256sum.
|
||||||
let digest: sha256::Hash = sha256::Hash::hash(c.as_bytes());
|
let digest: sha256::Hash = sha256::Hash::hash(c.as_bytes());
|
||||||
let hex_digest = format!("{:x}", digest);
|
let hex_digest = format!("{:x}", digest);
|
||||||
|
debug!("hex is: {}", hex_digest);
|
||||||
// * ensure the id matches the computed sha256sum.
|
// * ensure the id matches the computed sha256sum.
|
||||||
if self.id != hex_digest {
|
if self.id != hex_digest {
|
||||||
debug!("event id does not match digest");
|
debug!("event id does not match digest");
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ pub fn hex_range(s: &str) -> Option<HexSearch> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::error::Result;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn hex_range_exact() -> Result<()> {
|
fn hex_range_exact() -> Result<()> {
|
||||||
|
|||||||
+1
-2
@@ -2,12 +2,11 @@ pub mod close;
|
|||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod conn;
|
pub mod conn;
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod schema;
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod hexrange;
|
pub mod hexrange;
|
||||||
pub mod info;
|
pub mod info;
|
||||||
pub mod nip05;
|
pub mod nip05;
|
||||||
pub mod protostream;
|
pub mod schema;
|
||||||
pub mod subscription;
|
pub mod subscription;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|||||||
+146
-45
@@ -9,27 +9,33 @@ use hyper::{
|
|||||||
};
|
};
|
||||||
use log::*;
|
use log::*;
|
||||||
use nostr_rs_relay::close::Close;
|
use nostr_rs_relay::close::Close;
|
||||||
|
use nostr_rs_relay::close::CloseCmd;
|
||||||
use nostr_rs_relay::config;
|
use nostr_rs_relay::config;
|
||||||
use nostr_rs_relay::conn;
|
use nostr_rs_relay::conn;
|
||||||
use nostr_rs_relay::db;
|
use nostr_rs_relay::db;
|
||||||
|
use nostr_rs_relay::db::SubmittedEvent;
|
||||||
use nostr_rs_relay::error::{Error, Result};
|
use nostr_rs_relay::error::{Error, Result};
|
||||||
use nostr_rs_relay::event::Event;
|
use nostr_rs_relay::event::Event;
|
||||||
|
use nostr_rs_relay::event::EventCmd;
|
||||||
use nostr_rs_relay::info::RelayInfo;
|
use nostr_rs_relay::info::RelayInfo;
|
||||||
use nostr_rs_relay::nip05;
|
use nostr_rs_relay::nip05;
|
||||||
use nostr_rs_relay::protostream;
|
use nostr_rs_relay::subscription::Subscription;
|
||||||
use nostr_rs_relay::protostream::NostrMessage::*;
|
use serde::{Deserialize, Serialize};
|
||||||
use nostr_rs_relay::protostream::NostrResponse::*;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::time::Instant;
|
||||||
use tokio::runtime::Builder;
|
use tokio::runtime::Builder;
|
||||||
use tokio::sync::broadcast::{self, Receiver, Sender};
|
use tokio::sync::broadcast::{self, Receiver, Sender};
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tokio::sync::oneshot;
|
use tokio::sync::oneshot;
|
||||||
use tokio_tungstenite::WebSocketStream;
|
use tokio_tungstenite::WebSocketStream;
|
||||||
|
use tungstenite::error::Error as WsError;
|
||||||
use tungstenite::handshake;
|
use tungstenite::handshake;
|
||||||
|
use tungstenite::protocol::Message;
|
||||||
use tungstenite::protocol::WebSocketConfig;
|
use tungstenite::protocol::WebSocketConfig;
|
||||||
|
|
||||||
/// Return a requested DB name from command line arguments.
|
/// Return a requested DB name from command line arguments.
|
||||||
@@ -46,7 +52,7 @@ async fn handle_web_request(
|
|||||||
pool: db::SqlitePool,
|
pool: db::SqlitePool,
|
||||||
remote_addr: SocketAddr,
|
remote_addr: SocketAddr,
|
||||||
broadcast: Sender<Event>,
|
broadcast: Sender<Event>,
|
||||||
event_tx: tokio::sync::mpsc::Sender<Event>,
|
event_tx: tokio::sync::mpsc::Sender<SubmittedEvent>,
|
||||||
shutdown: Receiver<()>,
|
shutdown: Receiver<()>,
|
||||||
) -> Result<Response<Body>, Infallible> {
|
) -> Result<Response<Body>, Infallible> {
|
||||||
match (
|
match (
|
||||||
@@ -227,7 +233,8 @@ fn main() -> Result<(), Error> {
|
|||||||
let (bcast_tx, _) = broadcast::channel::<Event>(settings.limits.broadcast_buffer);
|
let (bcast_tx, _) = broadcast::channel::<Event>(settings.limits.broadcast_buffer);
|
||||||
// validated events that need to be persisted are sent to the
|
// validated events that need to be persisted are sent to the
|
||||||
// database on via this channel.
|
// database on via this channel.
|
||||||
let (event_tx, event_rx) = mpsc::channel::<Event>(settings.limits.event_persist_buffer);
|
let (event_tx, event_rx) =
|
||||||
|
mpsc::channel::<SubmittedEvent>(settings.limits.event_persist_buffer);
|
||||||
// establish a channel for letting all threads now about a
|
// establish a channel for letting all threads now about a
|
||||||
// requested server shutdown.
|
// requested server shutdown.
|
||||||
let (invoke_shutdown, shutdown_listen) = broadcast::channel::<()>(1);
|
let (invoke_shutdown, shutdown_listen) = broadcast::channel::<()>(1);
|
||||||
@@ -312,32 +319,79 @@ fn main() -> Result<(), Error> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Nostr protocol messages from a client
|
||||||
|
#[derive(Deserialize, Serialize, Clone, PartialEq, Debug)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum NostrMessage {
|
||||||
|
/// An `EVENT` message
|
||||||
|
EventMsg(EventCmd),
|
||||||
|
/// A `REQ` message
|
||||||
|
SubMsg(Subscription),
|
||||||
|
/// A `CLOSE` message
|
||||||
|
CloseMsg(CloseCmd),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert Message to NostrMessage
|
||||||
|
fn convert_to_msg(msg: String) -> Result<NostrMessage> {
|
||||||
|
let config = config::SETTINGS.read().unwrap();
|
||||||
|
let parsed_res: Result<NostrMessage> = serde_json::from_str(&msg).map_err(|e| e.into());
|
||||||
|
match parsed_res {
|
||||||
|
Ok(m) => {
|
||||||
|
if let NostrMessage::EventMsg(_) = m {
|
||||||
|
if let Some(max_size) = config.limits.max_event_bytes {
|
||||||
|
// check length, ensure that some max size is set.
|
||||||
|
if msg.len() > max_size && max_size > 0 {
|
||||||
|
return Err(Error::EventMaxLengthError(msg.len()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(m)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
debug!("proto parse error: {:?}", e);
|
||||||
|
debug!("parse error on message: {}", msg.trim());
|
||||||
|
Err(Error::ProtoParseError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Handle new client connections. This runs through an event loop
|
/// Handle new client connections. This runs through an event loop
|
||||||
/// for all client communication.
|
/// for all client communication.
|
||||||
async fn nostr_server(
|
async fn nostr_server(
|
||||||
pool: db::SqlitePool,
|
pool: db::SqlitePool,
|
||||||
ws_stream: WebSocketStream<Upgraded>,
|
mut ws_stream: WebSocketStream<Upgraded>,
|
||||||
broadcast: Sender<Event>,
|
broadcast: Sender<Event>,
|
||||||
event_tx: tokio::sync::mpsc::Sender<Event>,
|
event_tx: mpsc::Sender<SubmittedEvent>,
|
||||||
mut shutdown: Receiver<()>,
|
mut shutdown: Receiver<()>,
|
||||||
) {
|
) {
|
||||||
// get a broadcast channel for clients to communicate on
|
// get a broadcast channel for clients to communicate on
|
||||||
let mut bcast_rx = broadcast.subscribe();
|
let mut bcast_rx = broadcast.subscribe();
|
||||||
// upgrade the TCP connection to WebSocket
|
|
||||||
//let conn = tokio_tungstenite::accept_async_with_config(stream, Some(config)).await;
|
|
||||||
//let ws_stream = conn.expect("websocket handshake error");
|
|
||||||
// wrap websocket into a stream & sink of Nostr protocol messages
|
|
||||||
let mut nostr_stream = protostream::wrap_ws_in_nostr(ws_stream);
|
|
||||||
// Track internal client state
|
// Track internal client state
|
||||||
let mut conn = conn::ClientConn::new();
|
let mut conn = conn::ClientConn::new();
|
||||||
let cid = conn.get_client_prefix();
|
let cid = conn.get_client_prefix();
|
||||||
// Create a channel for receiving query results from the database.
|
// Create a channel for receiving query results from the database.
|
||||||
// we will send out the tx handle to any query we generate.
|
// we will send out the tx handle to any query we generate.
|
||||||
let (query_tx, mut query_rx) = mpsc::channel::<db::QueryResult>(256);
|
let (query_tx, mut query_rx) = mpsc::channel::<db::QueryResult>(256);
|
||||||
|
// Create channel for receiving NOTICEs
|
||||||
|
let (notice_tx, mut notice_rx) = mpsc::channel::<String>(32);
|
||||||
|
|
||||||
|
// last time this client sent data (message, ping, etc.)
|
||||||
|
let mut last_message_time = Instant::now();
|
||||||
|
|
||||||
|
// ping interval (every 5 minutes)
|
||||||
|
let default_ping_dur = Duration::from_secs(300);
|
||||||
|
|
||||||
|
// disconnect after 20 minutes without a ping response or event.
|
||||||
|
let max_quiet_time = Duration::from_secs(60 * 20);
|
||||||
|
|
||||||
|
let start = tokio::time::Instant::now() + default_ping_dur;
|
||||||
|
let mut ping_interval = tokio::time::interval_at(start, default_ping_dur);
|
||||||
|
|
||||||
// maintain a hashmap of a oneshot channel for active subscriptions.
|
// maintain a hashmap of a oneshot channel for active subscriptions.
|
||||||
// when these subscriptions are cancelled, make a message
|
// when these subscriptions are cancelled, make a message
|
||||||
// available to the executing query so it knows to stop.
|
// available to the executing query so it knows to stop.
|
||||||
let mut running_queries: HashMap<String, oneshot::Sender<()>> = HashMap::new();
|
let mut running_queries: HashMap<String, oneshot::Sender<()>> = HashMap::new();
|
||||||
|
|
||||||
// for stats, keep track of how many events the client published,
|
// for stats, keep track of how many events the client published,
|
||||||
// and how many it received from queries.
|
// and how many it received from queries.
|
||||||
let mut client_published_event_count: usize = 0;
|
let mut client_published_event_count: usize = 0;
|
||||||
@@ -349,11 +403,27 @@ async fn nostr_server(
|
|||||||
// server shutting down, exit loop
|
// server shutting down, exit loop
|
||||||
break;
|
break;
|
||||||
},
|
},
|
||||||
|
_ = ping_interval.tick() => {
|
||||||
|
// check how long since we talked to client
|
||||||
|
// if it has been too long, disconnect
|
||||||
|
if last_message_time.elapsed() > max_quiet_time {
|
||||||
|
debug!("ending connection due to lack of client ping response");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Send a ping
|
||||||
|
ws_stream.send(Message::Ping(Vec::new())).await.ok();
|
||||||
|
},
|
||||||
|
Some(notice_msg) = notice_rx.recv() => {
|
||||||
|
let n = notice_msg.to_string().replace("\"", "");
|
||||||
|
ws_stream.send(Message::Text(format!("[\"NOTICE\",\"{}\"]", n))).await.ok();
|
||||||
|
},
|
||||||
Some(query_result) = query_rx.recv() => {
|
Some(query_result) = query_rx.recv() => {
|
||||||
// database informed us of a query result we asked for
|
// database informed us of a query result we asked for
|
||||||
let res = EventRes(query_result.sub_id,query_result.event);
|
|
||||||
client_received_event_count += 1;
|
client_received_event_count += 1;
|
||||||
nostr_stream.send(res).await.ok();
|
// send a result
|
||||||
|
let subesc = query_result.sub_id.replace("\"", "");
|
||||||
|
let send_str = format!("[\"EVENT\",\"{}\",{}]", subesc, &query_result.event);
|
||||||
|
ws_stream.send(Message::Text(send_str)).await.ok();
|
||||||
},
|
},
|
||||||
// TODO: consider logging the LaggedRecv error
|
// TODO: consider logging the LaggedRecv error
|
||||||
Ok(global_event) = bcast_rx.recv() => {
|
Ok(global_event) = bcast_rx.recv() => {
|
||||||
@@ -368,17 +438,55 @@ async fn nostr_server(
|
|||||||
cid, s,
|
cid, s,
|
||||||
global_event.get_event_id_prefix());
|
global_event.get_event_id_prefix());
|
||||||
// create an event response and send it
|
// create an event response and send it
|
||||||
let res = EventRes(s.to_owned(),event_str);
|
let subesc = s.replace("\"", "");
|
||||||
nostr_stream.send(res).await.ok();
|
ws_stream.send(Message::Text(format!("[\"EVENT\",\"{}\",{}]", subesc, event_str))).await.ok();
|
||||||
|
//nostr_stream.send(res).await.ok();
|
||||||
} else {
|
} else {
|
||||||
warn!("could not serialize event {:?}", global_event.get_event_id_prefix());
|
warn!("could not serialize event {:?}", global_event.get_event_id_prefix());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// check if this client has a subscription
|
ws_next = ws_stream.next() => {
|
||||||
proto_next = nostr_stream.next() => {
|
// update most recent message time for client
|
||||||
match proto_next {
|
last_message_time = Instant::now();
|
||||||
Some(Ok(EventMsg(ec))) => {
|
// Consume text messages from the client, parse into Nostr messages.
|
||||||
|
let nostr_msg = match ws_next {
|
||||||
|
Some(Ok(Message::Text(m))) => {
|
||||||
|
convert_to_msg(m)
|
||||||
|
},
|
||||||
|
Some(Ok(Message::Binary(_))) => {
|
||||||
|
ws_stream.send(Message::Text(format!("[\"NOTICE\",\"{}\"]", "binary messages are not accepted"))).await.ok();
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
Some(Ok(Message::Ping(_))) | Some(Ok(Message::Pong(_))) => {
|
||||||
|
// get a ping/pong, ignore. tungstenite will
|
||||||
|
// send responses automatically.
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
None |
|
||||||
|
Some(Ok(Message::Close(_))) |
|
||||||
|
Some(Err(WsError::AlreadyClosed)) |
|
||||||
|
Some(Err(WsError::ConnectionClosed)) |
|
||||||
|
Some(Err(WsError::Protocol(tungstenite::error::ProtocolError::ResetWithoutClosingHandshake)))
|
||||||
|
=> {
|
||||||
|
debug!("websocket close from client: {:?}",cid);
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
Some(Err(WsError::Io(e))) => {
|
||||||
|
// IO errors are considered fatal
|
||||||
|
warn!("IO error (client: {:?}): {:?}", cid, e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
x => {
|
||||||
|
// default condition on error is to close the client connection
|
||||||
|
info!("unknown error (client: {:?}): {:?} (closing conn)", cid, x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// convert ws_next into proto_next
|
||||||
|
match nostr_msg {
|
||||||
|
Ok(NostrMessage::EventMsg(ec)) => {
|
||||||
// An EventCmd needs to be validated to be converted into an Event
|
// An EventCmd needs to be validated to be converted into an Event
|
||||||
// handle each type of message
|
// handle each type of message
|
||||||
let parsed : Result<Event> = Result::<Event>::from(ec);
|
let parsed : Result<Event> = Result::<Event>::from(ec);
|
||||||
@@ -386,23 +494,18 @@ async fn nostr_server(
|
|||||||
Ok(e) => {
|
Ok(e) => {
|
||||||
let id_prefix:String = e.id.chars().take(8).collect();
|
let id_prefix:String = e.id.chars().take(8).collect();
|
||||||
debug!("successfully parsed/validated event: {:?} from client: {:?}", id_prefix, cid);
|
debug!("successfully parsed/validated event: {:?} from client: {:?}", id_prefix, cid);
|
||||||
// TODO: consider moving some/all
|
// Write this to the database.
|
||||||
// authorization checks here, instead
|
let submit_event = SubmittedEvent { event: e.clone(), notice_tx: notice_tx.clone() };
|
||||||
// of the DB module, so we can send a
|
event_tx.send(submit_event).await.ok();
|
||||||
// proper NOTICE back to the client if
|
|
||||||
// they are unable to write.
|
|
||||||
|
|
||||||
// Write this to the database
|
|
||||||
event_tx.send(e.clone()).await.ok();
|
|
||||||
client_published_event_count += 1;
|
client_published_event_count += 1;
|
||||||
},
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
info!("client {:?} sent an invalid event", cid);
|
info!("client {:?} sent an invalid event", cid);
|
||||||
nostr_stream.send(NoticeRes("event was invalid".to_owned())).await.ok();
|
ws_stream.send(Message::Text(format!("[\"NOTICE\",\"{}\"]", "event was invalid"))).await.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(Ok(SubMsg(s))) => {
|
Ok(NostrMessage::SubMsg(s)) => {
|
||||||
debug!("client {} requesting a subscription", cid);
|
debug!("client {} requesting a subscription", cid);
|
||||||
// subscription handling consists of:
|
// subscription handling consists of:
|
||||||
// * registering the subscription so future events can be matched
|
// * registering the subscription so future events can be matched
|
||||||
@@ -416,18 +519,16 @@ async fn nostr_server(
|
|||||||
previous_query.send(()).ok();
|
previous_query.send(()).ok();
|
||||||
}
|
}
|
||||||
// start a database query
|
// start a database query
|
||||||
// show pool stats
|
db::db_query(s, pool.clone(), query_tx.clone(), abandon_query_rx).await;
|
||||||
debug!("DB pool stats: {:?}", pool.state());
|
|
||||||
db::db_query(s, pool.get().expect("could not get connection"), query_tx.clone(), abandon_query_rx).await;
|
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
info!("Subscription error: {}", e);
|
info!("Subscription error: {}", e);
|
||||||
nostr_stream.send(NoticeRes(format!("{}",e))).await.ok();
|
let s = e.to_string().replace("\"", "");
|
||||||
|
ws_stream.send(Message::Text(format!("[\"NOTICE\",\"{}\"]", s))).await.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(Ok(CloseMsg(cc))) => {
|
Ok(NostrMessage::CloseMsg(cc)) => {
|
||||||
// closing a request simply removes the subscription.
|
// closing a request simply removes the subscription.
|
||||||
let parsed : Result<Close> = Result::<Close>::from(cc);
|
let parsed : Result<Close> = Result::<Close>::from(cc);
|
||||||
match parsed {
|
match parsed {
|
||||||
@@ -444,23 +545,23 @@ async fn nostr_server(
|
|||||||
},
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
info!("invalid command ignored");
|
info!("invalid command ignored");
|
||||||
|
ws_stream.send(Message::Text(format!("[\"NOTICE\",\"{}\"]", "could not parse command"))).await.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
Err(Error::ConnError) => {
|
||||||
debug!("normal websocket close from client: {:?}",cid);
|
|
||||||
break;
|
|
||||||
},
|
|
||||||
Some(Err(Error::ConnError)) => {
|
|
||||||
debug!("got connection close/error, disconnecting client: {:?}",cid);
|
debug!("got connection close/error, disconnecting client: {:?}",cid);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Some(Err(Error::EventMaxLengthError(s))) => {
|
Err(Error::EventMaxLengthError(s)) => {
|
||||||
info!("client {:?} sent event larger ({} bytes) than max size", cid, s);
|
info!("client {:?} sent event larger ({} bytes) than max size", cid, s);
|
||||||
nostr_stream.send(NoticeRes("event exceeded max size".to_owned())).await.ok();
|
ws_stream.send(Message::Text(format!("[\"NOTICE\",\"{}\"]", "event exceeded max size"))).await.ok();
|
||||||
},
|
},
|
||||||
Some(Err(e)) => {
|
Err(Error::ProtoParseError) => {
|
||||||
|
info!("client {:?} sent event that could not be parsed", cid);
|
||||||
|
ws_stream.send(Message::Text(format!("[\"NOTICE\",\"{}\"]", "could not parse command"))).await.ok();
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
info!("got non-fatal error from client: {:?}, error: {:?}", cid, e);
|
info!("got non-fatal error from client: {:?}, error: {:?}", cid, e);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,141 +0,0 @@
|
|||||||
//! Nostr protocol layered over WebSocket
|
|
||||||
use crate::close::CloseCmd;
|
|
||||||
use crate::config;
|
|
||||||
use crate::error::{Error, Result};
|
|
||||||
use crate::event::EventCmd;
|
|
||||||
use crate::subscription::Subscription;
|
|
||||||
use core::pin::Pin;
|
|
||||||
use futures::sink::Sink;
|
|
||||||
use futures::stream::Stream;
|
|
||||||
use futures::task::Context;
|
|
||||||
use futures::task::Poll;
|
|
||||||
use hyper::upgrade::Upgraded;
|
|
||||||
use log::*;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use tokio_tungstenite::WebSocketStream;
|
|
||||||
use tungstenite::error::Error as WsError;
|
|
||||||
use tungstenite::protocol::Message;
|
|
||||||
|
|
||||||
/// Nostr protocol messages from a client
|
|
||||||
#[derive(Deserialize, Serialize, Clone, PartialEq, Debug)]
|
|
||||||
#[serde(untagged)]
|
|
||||||
pub enum NostrMessage {
|
|
||||||
/// An `EVENT` message
|
|
||||||
EventMsg(EventCmd),
|
|
||||||
/// A `REQ` message
|
|
||||||
SubMsg(Subscription),
|
|
||||||
/// A `CLOSE` message
|
|
||||||
CloseMsg(CloseCmd),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Nostr protocol messages from a relay/server
|
|
||||||
#[derive(Deserialize, Serialize, Clone, PartialEq, Debug)]
|
|
||||||
pub enum NostrResponse {
|
|
||||||
/// A `NOTICE` response
|
|
||||||
NoticeRes(String),
|
|
||||||
/// An `EVENT` response, composed of the subscription identifier,
|
|
||||||
/// and serialized event JSON
|
|
||||||
EventRes(String, String),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A Nostr protocol stream is layered on top of a Websocket stream.
|
|
||||||
pub struct NostrStream {
|
|
||||||
ws_stream: WebSocketStream<Upgraded>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given a websocket, return a protocol stream wrapper.
|
|
||||||
pub fn wrap_ws_in_nostr(ws: WebSocketStream<Upgraded>) -> NostrStream {
|
|
||||||
NostrStream { ws_stream: ws }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implement the [`Stream`] interface to produce Nostr messages.
|
|
||||||
impl Stream for NostrStream {
|
|
||||||
type Item = Result<NostrMessage>;
|
|
||||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
|
||||||
// get the configuration
|
|
||||||
/// Convert Message to NostrMessage
|
|
||||||
fn convert(msg: String) -> Result<NostrMessage> {
|
|
||||||
let config = config::SETTINGS.read().unwrap();
|
|
||||||
let parsed_res: Result<NostrMessage> = serde_json::from_str(&msg).map_err(|e| e.into());
|
|
||||||
match parsed_res {
|
|
||||||
Ok(m) => {
|
|
||||||
if let NostrMessage::EventMsg(_) = m {
|
|
||||||
if let Some(max_size) = config.limits.max_event_bytes {
|
|
||||||
// check length, ensure that some max size is set.
|
|
||||||
if msg.len() > max_size && max_size > 0 {
|
|
||||||
return Err(Error::EventMaxLengthError(msg.len()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(m)
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
debug!("proto parse error: {:?}", e);
|
|
||||||
debug!("parse error on message: {}", msg.trim());
|
|
||||||
Err(Error::ProtoParseError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match Pin::new(&mut self.ws_stream).poll_next(cx) {
|
|
||||||
Poll::Pending => Poll::Pending,
|
|
||||||
Poll::Ready(None) => Poll::Ready(None),
|
|
||||||
Poll::Ready(Some(v)) => match v {
|
|
||||||
Ok(Message::Text(vs)) => Poll::Ready(Some(convert(vs))),
|
|
||||||
Ok(Message::Ping(x)) => {
|
|
||||||
debug!("client ping ({:?})", x);
|
|
||||||
//Pin::new(&mut self.ws_stream).start_send(Message::Pong(x));
|
|
||||||
// TODO: restructure this so that Pongs work
|
|
||||||
//Pin::new(&mut self.ws_stream).write_pending();
|
|
||||||
//info!("sent pong");
|
|
||||||
Poll::Pending
|
|
||||||
}
|
|
||||||
Ok(Message::Binary(_)) => Poll::Ready(Some(Err(Error::ProtoParseError))),
|
|
||||||
Ok(Message::Pong(_)) => Poll::Pending,
|
|
||||||
Ok(Message::Close(_)) => Poll::Ready(None),
|
|
||||||
Err(WsError::AlreadyClosed) | Err(WsError::ConnectionClosed) => Poll::Ready(None),
|
|
||||||
Err(_) => Poll::Ready(Some(Err(Error::ConnError))),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implement the [`Sink`] interface to produce Nostr responses.
|
|
||||||
impl Sink<NostrResponse> for NostrStream {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
|
||||||
// map the error type
|
|
||||||
match Pin::new(&mut self.ws_stream).poll_ready(cx) {
|
|
||||||
Poll::Ready(Ok(())) => Poll::Ready(Ok(())),
|
|
||||||
Poll::Ready(Err(_)) => Poll::Ready(Err(Error::ConnWriteError)),
|
|
||||||
Poll::Pending => Poll::Pending,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn start_send(mut self: Pin<&mut Self>, item: NostrResponse) -> Result<(), Self::Error> {
|
|
||||||
// TODO: do real escaping for these - at least on NOTICE,
|
|
||||||
// which surely has some problems if arbitrary text is sent.
|
|
||||||
let send_str = match item {
|
|
||||||
NostrResponse::NoticeRes(msg) => {
|
|
||||||
let s = msg.replace("\"", "");
|
|
||||||
format!("[\"NOTICE\",\"{}\"]", s)
|
|
||||||
}
|
|
||||||
NostrResponse::EventRes(sub, eventstr) => {
|
|
||||||
let subesc = sub.replace("\"", "");
|
|
||||||
format!("[\"EVENT\",\"{}\",{}]", subesc, eventstr)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
match Pin::new(&mut self.ws_stream).start_send(Message::Text(send_str)) {
|
|
||||||
Ok(()) => Ok(()),
|
|
||||||
Err(_) => Err(Error::ConnWriteError),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
|
||||||
Poll::Ready(Ok(()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
|
||||||
Poll::Ready(Ok(()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -214,6 +214,7 @@ impl ReqFilter {
|
|||||||
// self.id.as_ref().map(|v| v == &event.id).unwrap_or(true)
|
// self.id.as_ref().map(|v| v == &event.id).unwrap_or(true)
|
||||||
self.ids_match(event)
|
self.ids_match(event)
|
||||||
&& self.since.map(|t| event.created_at > t).unwrap_or(true)
|
&& self.since.map(|t| event.created_at > t).unwrap_or(true)
|
||||||
|
&& self.until.map(|t| event.created_at < t).unwrap_or(true)
|
||||||
&& self.kind_match(event.kind)
|
&& self.kind_match(event.kind)
|
||||||
&& self.authors_match(event)
|
&& self.authors_match(event)
|
||||||
&& self.tag_match(event)
|
&& self.tag_match(event)
|
||||||
@@ -321,6 +322,50 @@ mod tests {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn interest_until() -> Result<()> {
|
||||||
|
// subscription with a filter for ID and time
|
||||||
|
let s: Subscription =
|
||||||
|
serde_json::from_str(r#"["REQ","xyz",{"ids": ["abc"], "until": 1000}]"#)?;
|
||||||
|
let e = Event {
|
||||||
|
id: "abc".to_owned(),
|
||||||
|
pubkey: "".to_owned(),
|
||||||
|
created_at: 50,
|
||||||
|
kind: 0,
|
||||||
|
tags: Vec::new(),
|
||||||
|
content: "".to_owned(),
|
||||||
|
sig: "".to_owned(),
|
||||||
|
tagidx: None,
|
||||||
|
};
|
||||||
|
assert!(s.interested_in_event(&e));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn interest_range() -> Result<()> {
|
||||||
|
// subscription with a filter for ID and time
|
||||||
|
let s_in: Subscription =
|
||||||
|
serde_json::from_str(r#"["REQ","xyz",{"ids": ["abc"], "since": 100, "until": 200}]"#)?;
|
||||||
|
let s_before: Subscription =
|
||||||
|
serde_json::from_str(r#"["REQ","xyz",{"ids": ["abc"], "since": 100, "until": 140}]"#)?;
|
||||||
|
let s_after: Subscription =
|
||||||
|
serde_json::from_str(r#"["REQ","xyz",{"ids": ["abc"], "since": 160, "until": 200}]"#)?;
|
||||||
|
let e = Event {
|
||||||
|
id: "abc".to_owned(),
|
||||||
|
pubkey: "".to_owned(),
|
||||||
|
created_at: 150,
|
||||||
|
kind: 0,
|
||||||
|
tags: Vec::new(),
|
||||||
|
content: "".to_owned(),
|
||||||
|
sig: "".to_owned(),
|
||||||
|
tagidx: None,
|
||||||
|
};
|
||||||
|
assert!(s_in.interested_in_event(&e));
|
||||||
|
assert!(!s_before.interested_in_event(&e));
|
||||||
|
assert!(!s_after.interested_in_event(&e));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn interest_time_and_id() -> Result<()> {
|
fn interest_time_and_id() -> Result<()> {
|
||||||
// subscription with a filter for ID and time
|
// subscription with a filter for ID and time
|
||||||
|
|||||||
Reference in New Issue
Block a user