diff --git a/Cargo.lock b/Cargo.lock index 252b58c77..3ae93c733 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,8 +12,8 @@ dependencies = [ "ethabi 8.0.0 (git+https://github.com/samparsky/ethabi?branch=graph-patches)", "ethkey 0.4.0 (git+https://github.com/paritytech/parity-ethereum)", "ethstore 0.2.1 (git+https://github.com/paritytech/parity-ethereum)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-crypto 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "primitives 0.1.0", @@ -31,11 +31,18 @@ dependencies = [ name = "adview-manager" version = "0.1.0" dependencies = [ + "async-std 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "primitives 0.1.0", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -139,45 +146,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "async-std" -version = "1.5.0" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "async-task 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "async-task 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smol 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-futures 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "async-task" -version = "1.3.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "async-trait" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -186,7 +187,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -207,7 +208,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -217,7 +218,7 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -267,7 +268,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "async-trait 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -278,7 +279,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "async-trait 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "bb8 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-postgres 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -344,7 +345,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-padding 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -377,6 +378,18 @@ name = "block-padding" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "blocking" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "waker-fn 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bumpalo" version = "3.2.0" @@ -422,6 +435,11 @@ name = "bytes" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cache-padded" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cc" version = "1.0.41" @@ -437,8 +455,8 @@ name = "chrono" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -487,6 +505,14 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "concurrent-queue" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cache-padded 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "const-random" version = "0.1.8" @@ -516,7 +542,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -635,7 +661,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "data-encoding 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-hack 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -643,9 +669,9 @@ name = "derive_more" version = "0.99.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -669,7 +695,7 @@ name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -698,7 +724,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -845,7 +871,7 @@ dependencies = [ "dir 0.1.2 (git+https://github.com/paritytech/parity-ethereum)", "ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.4.0 (git+https://github.com/paritytech/parity-ethereum)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-crypto 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wordlist 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -894,6 +920,11 @@ dependencies = [ "plain_hasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fastrand" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fixed-hash" version = "0.5.2" @@ -949,30 +980,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-executor 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-executor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-channel" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-core" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -986,59 +1017,58 @@ dependencies = [ [[package]] name = "futures-executor" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-io" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures-macro" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-hack 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-sink" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures-task" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-timer" -version = "2.0.2" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "once_cell 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "futures-util" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-macro 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-hack 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-nested 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1054,7 +1084,7 @@ name = "generic-array" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1062,15 +1092,15 @@ name = "generic-array" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "generic-array" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1080,7 +1110,7 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1108,9 +1138,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1138,7 +1168,7 @@ name = "hermit-abi" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1148,7 +1178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hex" -version = "0.3.2" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1286,16 +1316,16 @@ version = "0.13.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1393,9 +1423,9 @@ name = "impl-trait-for-tuples" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1411,7 +1441,7 @@ name = "iovec" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1439,10 +1469,10 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.36" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "wasm-bindgen 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1512,7 +1542,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.68" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1527,7 +1557,7 @@ dependencies = [ "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1587,7 +1617,7 @@ name = "memchr" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1600,7 +1630,7 @@ name = "memmap" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1687,7 +1717,7 @@ dependencies = [ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1701,7 +1731,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1746,7 +1776,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1763,7 +1793,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1774,26 +1804,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-bigint" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-complex 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1802,18 +1821,17 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-complex" -version = "0.2.4" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1828,37 +1846,37 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-iter" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-rational" -version = "0.2.4" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1870,7 +1888,7 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1906,7 +1924,7 @@ dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1922,7 +1940,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2010,8 +2028,8 @@ name = "parity-util-mem-derive" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2024,6 +2042,11 @@ dependencies = [ "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "parking_lot" version = "0.9.0" @@ -2050,7 +2073,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2064,7 +2087,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2140,9 +2163,9 @@ name = "pin-project-internal" version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2152,7 +2175,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pin-utils" -version = "0.1.0-alpha.4" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2175,7 +2198,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2189,7 +2212,7 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "postgres-protocol 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "postgres-shared 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2277,14 +2300,14 @@ dependencies = [ "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "cid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "fake 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "merkletree 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "postgres-types 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2308,9 +2331,9 @@ name = "proc-macro-hack" version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2328,7 +2351,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.9" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2347,7 +2370,7 @@ name = "quote" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2355,7 +2378,7 @@ name = "rand" version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2365,7 +2388,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2378,7 +2401,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2389,7 +2412,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2407,7 +2430,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2481,7 +2504,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2493,7 +2516,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2554,8 +2577,8 @@ dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-executor 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-executor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2612,13 +2635,13 @@ dependencies = [ "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2633,8 +2656,8 @@ dependencies = [ "tokio 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-futures 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-futures 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)", "web-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2674,7 +2697,7 @@ version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2740,6 +2763,11 @@ name = "scoped-tls" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "scopeguard" version = "0.3.3" @@ -2808,7 +2836,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2829,13 +2857,13 @@ name = "sentry" version = "0.1.0" dependencies = [ "adapter 0.1.0", - "async-std 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "async-std 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "bb8 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "bb8-postgres 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "migrant_lib 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2872,9 +2900,9 @@ name = "serde_derive" version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3038,13 +3066,33 @@ name = "smallvec" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "smol" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "async-task 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blocking 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "concurrent-queue 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fastrand 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "wepoll-sys-stjepang 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "socket2" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3106,10 +3154,10 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.16" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3130,9 +3178,9 @@ name = "synstructure" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3156,7 +3204,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3193,9 +3241,9 @@ name = "thiserror-impl" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3211,7 +3259,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3262,10 +3310,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3356,9 +3404,9 @@ name = "tokio-macros" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3370,7 +3418,7 @@ dependencies = [ "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3499,7 +3547,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3515,7 +3563,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3530,8 +3578,8 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3543,8 +3591,8 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3598,7 +3646,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "typenum" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3706,11 +3754,11 @@ dependencies = [ "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "primitives 0.1.0", "reqwest 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3745,6 +3793,11 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "waker-fn" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "walkdir" version = "2.3.1" @@ -3781,64 +3834,64 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasm-bindgen" -version = "0.2.59" +version = "0.2.67" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.59" +version = "0.2.67" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bumpalo 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.9" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "web-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.59" +version = "0.2.67" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro-support 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro-support 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.59" +version = "0.2.67" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.59" +version = "0.2.67" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3846,8 +3899,8 @@ name = "web-sys" version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "js-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3902,6 +3955,14 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "wepoll-sys-stjepang" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi" version = "0.2.8" @@ -3998,8 +4059,8 @@ dependencies = [ "checksum arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" "checksum ascii 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" -"checksum async-std 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "538ecb01eb64eecd772087e5b6f7540cbc917f047727339a472dafed2185b267" -"checksum async-task 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0ac2c016b079e771204030951c366db398864f5026f84a44dafb0ff20f02085d" +"checksum async-std 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "00d68a33ebc8b57800847d00787307f84a562224a14db069b0acefe4c2abbf5d" +"checksum async-task 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c17772156ef2829aadc587461c7753af20b7e8db1529bc66855add962a3b35d3" "checksum async-trait 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "687c230d85c0a52504709705fc8a53e4a692b83a2184f03dae73e38e1e93a783" "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" @@ -4026,6 +4087,7 @@ dependencies = [ "checksum block-modes 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "31aa8410095e39fdb732909fb5730a48d5bd7c2e3cd76bd1b07b3dbea130c529" "checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" "checksum block-padding 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" +"checksum blocking 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9d17efb70ce4421e351d61aafd90c16a20fb5bfe339fcdc32a86816280e62ce0" "checksum bumpalo 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742" "checksum byte-slice-cast 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" @@ -4034,6 +4096,7 @@ dependencies = [ "checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" +"checksum cache-padded 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" "checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" @@ -4041,6 +4104,7 @@ dependencies = [ "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" +"checksum concurrent-queue 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" "checksum const-random 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "2f1af9ac737b2dd2d577701e59fd09ba34822f6f2ebdb30a7647405d9e55e16a" "checksum const-random-macro 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "25e4c606eb459dd29f7c57b2e0879f2b6f14ee130918c2b78ccb58a9624e6c7a" "checksum constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" @@ -4085,6 +4149,7 @@ dependencies = [ "checksum fallible-iterator 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eb7217124812dc5672b7476d0c2d20cfe9f7c0f1ba0904b674a9762a0212f72e" "checksum fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" "checksum fastmap 0.1.0 (git+https://github.com/paritytech/parity-ethereum)" = "" +"checksum fastrand 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bd3bdaaf0a72155260a1c098989b60db1cbb22d6a628e64f16237aa4da93cc7" "checksum fixed-hash 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3367952ceb191f4ab95dd5685dc163ac539e36202f9fcfd0cb22f9f9c542fefc" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" @@ -4093,20 +4158,19 @@ dependencies = [ "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" -"checksum futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780" -"checksum futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8" -"checksum futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" +"checksum futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613" +"checksum futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5" +"checksum futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum futures-executor 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba" -"checksum futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6" -"checksum futures-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" -"checksum futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6" -"checksum futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" -"checksum futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" -"checksum futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" +"checksum futures-executor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314" +"checksum futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789" +"checksum futures-macro 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" +"checksum futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc" +"checksum futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626" +"checksum futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum generic-array 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "60fb4bb6bba52f78a471264d9a3b7d026cc0af47b22cd2cffbc0b787ca003e63" +"checksum generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" @@ -4115,7 +4179,7 @@ dependencies = [ "checksum hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" "checksum hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8" "checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" -"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +"checksum hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" "checksum hmac 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44f3bdb08579d99d7dc761c0e266f13b5f2ab8c8c703b9fc9ef333cd8f48f55e" "checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" "checksum hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" @@ -4142,7 +4206,7 @@ dependencies = [ "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" "checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" "checksum journaldb 0.2.0 (git+https://github.com/paritytech/parity-ethereum)" = "" -"checksum js-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1cb931d43e71f560c81badb0191596562bafad2be06a3f9025b845c847c60df5" +"checksum js-sys 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)" = "85a7e2c92a4804dd459b86c339278d0fe87cf93757fae222c3fa3ae75458bc73" "checksum jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fe3b688648f1ef5d5072229e2d672ecb92cbff7d1c79bcf3fd5898f3f3df0970" "checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" "checksum keccak-hasher 0.1.1 (git+https://github.com/paritytech/parity-ethereum)" = "" @@ -4151,7 +4215,7 @@ dependencies = [ "checksum kvdb 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03080afe6f42cd996da9f568d6add5d7fb5ee2ea7fb7802d2d2cbd836958fd87" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" +"checksum libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)" = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" "checksum libsecp256k1 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1fc1e2c808481a63dc6da2074752fdd4336a3c8fcc68b83db6f1fd5224ae7962" "checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" @@ -4179,15 +4243,14 @@ dependencies = [ "checksum native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" -"checksum num 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" -"checksum num-bigint 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +"checksum num 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab3e176191bc4faad357e3122c4747aa098ac880e88b168f106386128736cf4a" "checksum num-bigint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b7f3fc75e3697059fb1bc465e3d8cca6cf92f56854f201158b3f9c77d5a3cfa0" -"checksum num-complex 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +"checksum num-complex 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b05ad05bd8977050b171b3f6b48175fea6e0565b7981059b486075e1026a9fb5" "checksum num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2" -"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" -"checksum num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00" -"checksum num-rational 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" -"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +"checksum num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" +"checksum num-iter 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f" +"checksum num-rational 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b4d7360f362cfb50dde8143501e6940b22f644be75a4cc90b2d81968908138" +"checksum num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" "checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" "checksum once_cell 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b" @@ -4203,6 +4266,7 @@ dependencies = [ "checksum parity-util-mem 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9344bc978467339b9ae688f9dcf279d1aaa0ccfc88e9a780c729b765a82d57d5" "checksum parity-util-mem-derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" "checksum parity-wordlist 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f45ab1896c154f80a23f22aa81134b881e18b8fb7ff106abe67ae53a161d54a0" +"checksum parking 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6cb300f271742d4a2a66c01b6b2fa0c83dfebd2e0bf11addb879a3547b4ed87c" "checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" @@ -4217,7 +4281,7 @@ dependencies = [ "checksum pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)" = "ca4433fff2ae79342e497d9f8ee990d174071408f28f726d6d83af93e58e48aa" "checksum pin-project-internal 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)" = "2c0e815c3ee9a031fdf5af21c10aa17c573c9c6a566328d99e3936c34e36461f" "checksum pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" -"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" +"checksum pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" "checksum plain_hasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1e19e6491bdde87c2c43d70f4c194bc8a758f2eb732df00f61e43f7362e3b4cc" "checksum positioned-io 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c405a565f48a728dbb07fa1770e30791b0fa3e6344c1e5615225ce84049354d6" @@ -4231,7 +4295,7 @@ dependencies = [ "checksum proc-macro-hack 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f918f2b601f93baa836c1c2945faef682ba5b6d4828ecb45eeb7cc3c71b811b4" "checksum proc-macro-nested 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" +"checksum proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" "checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" @@ -4275,6 +4339,7 @@ dependencies = [ "checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" "checksum schannel 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "039c25b130bd8c1321ee2d7de7fde2659fa9c2744e4bb29711cfc852ea53cd19" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" +"checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" "checksum scrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "656c79d0e90d0ab28ac86bf3c3d10bfbbac91450d3f190113b4e76d9fec3cfdd" @@ -4307,7 +4372,8 @@ dependencies = [ "checksum slog-term 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "124501187c410b6a46fe8a47a48435ae462fae4e02d03c558d358f40b17308cb" "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" "checksum smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" -"checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" +"checksum smol 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "620cbb3c6e34da57d3a248cda0cd01cd5848164dc062e764e65d06fe3ea7aed5" +"checksum socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" "checksum static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" "checksum stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8131256a5896cabcf5eb04f4d6dacbe1aefda854b0d9896e09cb58829ec5638c" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" @@ -4316,7 +4382,7 @@ dependencies = [ "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -"checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" +"checksum syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" @@ -4361,7 +4427,7 @@ dependencies = [ "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" -"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +"checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" "checksum uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e75a4cdd7b87b28840dba13c483b9a88ee6bbf16ba5c951ee1ecfcf723078e0d" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" @@ -4380,19 +4446,21 @@ dependencies = [ "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum waker-fn 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9571542c2ce85ce642e6b58b3364da2fb53526360dfb7c211add4f5c23105ff7" "checksum walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" "checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" "checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -"checksum wasm-bindgen 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "3557c397ab5a8e347d434782bcd31fc1483d927a6826804cec05cc792ee2519d" -"checksum wasm-bindgen-backend 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "e0da9c9a19850d3af6df1cb9574970b566d617ecfaf36eb0b706b6f3ef9bd2f8" -"checksum wasm-bindgen-futures 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "457414a91863c0ec00090dba537f88ab955d93ca6555862c29b6d860990b8a8a" -"checksum wasm-bindgen-macro 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "0f6fde1d36e75a714b5fe0cffbb78978f222ea6baebb726af13c78869fdb4205" -"checksum wasm-bindgen-macro-support 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "25bda4168030a6412ea8a047e27238cadf56f0e53516e1e83fec0a8b7c786f6d" -"checksum wasm-bindgen-shared 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "fc9f36ad51f25b0219a3d4d13b90eb44cd075dff8b6280cca015775d7acaddd8" +"checksum wasm-bindgen 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "f0563a9a4b071746dd5aedbc3a28c6fe9be4586fb3fbadb67c400d4f53c6b16c" +"checksum wasm-bindgen-backend 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "bc71e4c5efa60fb9e74160e89b93353bc24059999c0ae0fb03affc39770310b0" +"checksum wasm-bindgen-futures 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)" = "95f8d235a77f880bcef268d379810ea6c0af2eacfa90b1ad5af731776e0c4699" +"checksum wasm-bindgen-macro 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "97c57cefa5fa80e2ba15641578b44d36e7a64279bc5ed43c6dbaf329457a2ed2" +"checksum wasm-bindgen-macro-support 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "841a6d1c35c6f596ccea1f82504a192a60378f64b3bb0261904ad8f2f5657556" +"checksum wasm-bindgen-shared 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "93b162580e34310e5931c4b792560108b10fd14d64915d7fff8ff00180e70092" "checksum web-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)" = "721c6263e2c66fd44501cc5efbfa2b7dfa775d13e4ea38c46299646ed1f9c70a" "checksum web3 0.8.0 (git+https://github.com/samparsky/rust-web3)" = "" "checksum websocket 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c9faed2bff8af2ea6b9f8b917d3d00b467583f6781fe3def174a9e33c879703" +"checksum wepoll-sys-stjepang 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd319e971980166b53e17b1026812ad66c6b54063be879eb182342b55284694" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/adapter/Cargo.toml b/adapter/Cargo.toml index 3895e0922..af4fb7af6 100644 --- a/adapter/Cargo.toml +++ b/adapter/Cargo.toml @@ -5,12 +5,12 @@ authors = ["Lachezar Lechev , Omidiora Samuel , - /// Defaulted - pub min_per_impression: BigNum, - /// Defaulted - pub min_targeting_score: MinTargetingScore, - /// Defaulted - pub randomize: bool, - pub publisher_addr: String, - pub whitelisted_token: String, - pub whitelisted_type: Option, - /// Defaulted - pub top_by_price: usize, - /// Defaulted - pub top_by_score: usize, - #[serde(default)] - pub targeting: Vec, + pub market_url: Url, + pub market_slot: IPFS, + pub publisher_addr: ValidatorId, + // All passed tokens must be of the same price and decimals, so that the amounts can be accurately compared + pub whitelisted_tokens: Vec, pub width: Option, pub height: Option, - pub fallback_unit: Option, + pub navigator_language: Option, /// Defaulted pub disabled_video: bool, + pub disabled_sticky: bool, } -impl AdViewManagerOptions { +impl Options { pub fn size(&self) -> Option<(u64, u64)> { self.width .and_then(|width| self.height.map(|height| (width, height))) } } -#[derive(Debug)] -pub struct UnitByPrice { - pub unit: AdUnit, - pub channel_id: ChannelId, - pub validators: SpecValidators, - pub min_targeting_score: MinTargetingScore, - pub min_per_impression: BigNum, -} - -#[derive(Debug)] -pub struct Unit { - pub unit: AdUnit, - pub channel_id: ChannelId, - pub validators: SpecValidators, - pub min_targeting_score: MinTargetingScore, - pub min_per_impression: BigNum, - pub targeting_score: TargetingScore, -} - -impl Unit { - pub fn new(by_price: UnitByPrice, targeting_score: TargetingScore) -> Self { - Self { - unit: by_price.unit, - channel_id: by_price.channel_id, - validators: by_price.validators, - min_targeting_score: by_price.min_targeting_score, - min_per_impression: by_price.min_per_impression, - targeting_score, - } - } -} - -pub fn apply_selection(campaigns: &[Campaign], options: &AdViewManagerOptions) -> Vec { - let eligible = campaigns.iter().filter(|campaign| { - options - .accepted_states - .contains(&campaign.status.status_type) - && campaign - .channel - .spec - .active_from - .map(|datetime| datetime < Utc::now()) - .unwrap_or(true) - && campaign.channel.deposit_asset == options.whitelisted_token - && campaign.channel.spec.min_per_impression >= options.min_per_impression - }); - - let mut units: Vec = eligible - // filter ad_units by whitelisted type, map then to UnitByPrice and flat_map them for each campaing - .flat_map(|campaign| { - campaign - .channel - .spec - .ad_units - .iter() - .filter(|unit| { - options - .whitelisted_type - .as_ref() - .map(|whitelisted_type| { - whitelisted_type != &unit.ad_type - && !(options.disabled_video && is_video(&unit)) - }) - .unwrap_or(false) - }) - .map(move |ad_unit| UnitByPrice { - unit: ad_unit.clone(), - channel_id: campaign.channel.id, - validators: campaign.channel.spec.validators.clone(), - min_targeting_score: ad_unit - .min_targeting_score - .or(campaign.channel.spec.min_targeting_score) - .unwrap_or_else(|| 0.into()), - min_per_impression: campaign.channel.spec.min_per_impression.clone(), - }) - }) - .collect(); - - // Sort - units.sort_by(|b, a| a.min_per_impression.cmp(&b.min_per_impression)); - // Top units - units.truncate(options.top_by_price); - - let mut by_score: Vec = units - .into_iter() - .filter_map(|by_price| { - let targeting_score = - calculate_target_score(&by_price.unit.targeting, &options.targeting); - if targeting_score >= options.min_targeting_score - && targeting_score >= by_price.min_targeting_score - { - Some(Unit::new(by_price, targeting_score)) - } else { - None - } - }) - .collect(); - by_score.sort_by(|a, b| { - a.targeting_score - .partial_cmp(&b.targeting_score) - .expect("Should always be comparable") - }); - by_score.truncate(options.top_by_score); - - by_score -} - -fn is_video(ad_unit: &AdUnit) -> bool { - ad_unit.media_mime.split('/').next() == Some("video") -} - -fn calculate_target_score(a: &[TargetingTag], b: &[TargetingTag]) -> TargetingScore { - a.iter() - .map(|x| -> TargetingScore { - match b.iter().find(|y| y.tag == x.tag) { - Some(b) => (&x.score * &b.score).into(), - None => 0.into(), - } - }) - .sum() +#[derive(Debug, Clone)] +pub struct HistoryEntry { + time: DateTime, + unit_id: IPFS, + campaign_id: ChannelId, + slot_id: IPFS, } #[derive(Serialize)] @@ -175,8 +79,11 @@ fn calculate_target_score(a: &[TargetingTag], b: &[TargetingTag]) -> TargetingSc struct Event { #[serde(rename = "type")] event_type: String, - publisher: String, - ad_unit: String, + publisher: ValidatorId, + ad_unit: IPFS, + ad_slot: IPFS, + #[serde(rename = "ref")] + referrer: String, } #[derive(Serialize)] @@ -184,20 +91,6 @@ struct EventBody { events: Vec, } -fn image_html( - event_body: &str, - on_load: &str, - size: &Option<(u64, u64)>, - image_url: &str, -) -> String { - let size = size - .map(|(width, height)| format!("width=\"{}\" height=\"{}\"", width, height)) - .unwrap_or_else(|| "".to_string()); - - format!("\"AdEx", - image_url = image_url, event_body = event_body, on_load = on_load, size = size) -} - fn normalize_url(url: &str) -> String { if url.starts_with("ipfs://") { url.replacen("ipfs://", IPFS_GATEWAY, 1) @@ -206,8 +99,16 @@ fn normalize_url(url: &str) -> String { } } +fn image_html(on_load: &str, size: &Option<(u64, u64)>, image_url: &str) -> String { + let size = size + .map(|(width, height)| format!("width=\"{}\" height=\"{}\"", width, height)) + .unwrap_or_else(|| "".to_string()); + + format!("\"AdEx", + image_url = image_url, on_load = on_load, size = size) +} + fn video_html( - event_body: &str, on_load: &str, size: &Option<(u64, u64)>, image_url: &str, @@ -217,106 +118,499 @@ fn video_html( .map(|(width, height)| format!("width=\"{}\" height=\"{}\"", width, height)) .unwrap_or_else(|| "".to_string()); - format!("", size = size, event_body = event_body, on_load = on_load, image_url = image_url, media_mime = media_mime) + format!( + "", + size = size, + on_load = on_load, + image_url = image_url, + media_mime = media_mime + ) } -pub fn get_html( - options: &AdViewManagerOptions, - ad_unit: AdUnit, - channel_id: ChannelId, - validators: &SpecValidators, -) -> String { - let ev_body = EventBody { - events: vec![Event { - event_type: "IMPRESSION".into(), - publisher: options.publisher_addr.clone(), - ad_unit: ad_unit.ipfs.clone(), - }], - }; +fn adex_icon() -> &'static str { + r#" + + + + + + + + "# +} - let on_load: String = validators.iter().map(|validator| { - let fetch_opts = "{ method: 'POST', headers: { 'content-type': 'application/json' }, body: this.dataset.eventBody }"; - let fetch_url = format!("{}/channel/{}/events", validator.url, channel_id); +fn is_video(ad_unit: &AdUnit) -> bool { + ad_unit.media_mime.split('/').next() == Some("video") +} - format!("fetch({}, {});", fetch_url, fetch_opts) - }).collect(); +/// Does not copy the JS impl, instead it generates the BigNum from the IPFS CID bytes +fn randomized_sort_pos(ad_unit: &AdUnit, seed: BigNum) -> BigNum { + let bytes = ad_unit.id.0.to_bytes(); - let ev_body = serde_json::to_string(&ev_body).expect("should convert"); + let unit_id = BigNum::from_bytes_be(&bytes); - get_unit_html(&options.size(), ad_unit, &ev_body, &on_load) + let x: BigNum = unit_id.mul(seed).add(BigNum::from(12345)); + + x.mod_floor(&BigNum::from(0x80000000)) } fn get_unit_html( size: &Option<(u64, u64)>, - ad_unit: AdUnit, - event_body: &str, + ad_unit: &AdUnit, + hostname: &str, on_load: &str, + on_click: &str, ) -> String { let image_url = normalize_url(&ad_unit.media_url); let element_html = if is_video(&ad_unit) { - video_html(event_body, on_load, size, &image_url, &ad_unit.media_mime) + video_html(on_load, size, &image_url, &ad_unit.media_mime) } else { - image_html(event_body, on_load, size, &image_url) + image_html(on_load, size, &image_url) }; - let style_size = size - .map(|(width, height)| format!("width: {}; height: {};", width, height)) - .unwrap_or_else(|| "".to_string()); + // @TODO click protection page + let final_target_url = ad_unit.target_url.replace( + "utm_source=adex_PUBHOSTNAME", + &format!("utm_source=AdEx+({hostname})", hostname = hostname), + ); + + let max_min_size = match size { + Some((width, height)) => { + format!( + "max-width: {}px; min-width: {min_width}px; height: {}px;", + width, + height, + // u64 / 2 will floor the result! + min_width = width / 2 + ) + } + None => String::new(), + }; - let adex_icon = " - - - - - - - - "; - - let result = format!(" -
- {element_html} - {adex_icon} -
- ", target_url = ad_unit.target_url, size = style_size, element_html = element_html, adex_icon = adex_icon); - - result + format!("
+ + {element_html} + + {adex_icon} +
", style=max_min_size, adex_icon=adex_icon(), final_target_url=final_target_url, on_click = on_click, element_html=element_html) +} + +pub fn get_unit_html_with_events( + options: &Options, + ad_unit: &AdUnit, + hostname: &str, + channel_id: ChannelId, + validators: &SpecValidators, + no_impression: impl Into, +) -> String { + let get_body = |event_type: &str| EventBody { + events: vec![Event { + event_type: event_type.to_string(), + publisher: options.publisher_addr, + ad_unit: ad_unit.id.clone(), + ad_slot: options.market_slot.clone(), + referrer: "document.referrer".to_string(), + }], + }; + + let get_fetch_code = |event_type: &str| -> String { + let body = serde_json::to_string(&get_body(event_type)) + .expect("It should always serialize EventBody"); + + let fetch_opts = format!("var fetchOpts = {{ method: 'POST', headers: {{ 'content-type': 'application/json' }}, body: {} }};", body); + + let validators: String = validators + .iter() + .map(|validator| { + let fetch_url = format!( + "{}/channel/{}/events?pubAddr={}", + validator.url, channel_id, options.publisher_addr + ); + + format!("fetch('{}', fetchOpts)", fetch_url) + }) + .collect::>() + .join(";"); + + format!("{}{}", fetch_opts, validators) + }; + + let get_timeout_code = |event_type: &str| -> String { + format!( + "setTimeout(function() {{ {code} }}, {timeout})", + code = get_fetch_code(event_type), + timeout = WAIT_FOR_IMPRESSION + ) + }; + + let on_load = if no_impression.into() { + String::new() + } else { + get_timeout_code("IMPRESSION") + }; + + get_unit_html( + &options.size(), + ad_unit, + hostname, + &on_load, + &get_fetch_code("CLICK"), + ) +} + +#[derive(Debug, Error)] +pub enum Error { + #[error("Request to the Market failed: status {status} at url {url}")] + Market { status: StatusCode, url: String }, + #[error(transparent)] + Request(#[from] reqwest::Error), +} + +pub struct Manager { + options: Options, + /// Contains the Entries from Old to New + /// It always trims to HISTORY_LIMIT, removing the oldest (firstly inserted) elements from the History + history: Arc>>, + client: reqwest::Client, + logger: Logger, +} + +impl Manager { + pub fn new( + options: Options, + history: VecDeque, + logger: Logger, + ) -> Result { + let client = reqwest::Client::builder().build()?; + + Ok(Self { + options, + history: Arc::new(RwLock::new(history)), + client, + logger, + }) + } + + pub async fn get_targeting_input( + &self, + mut input: input::Input, + channel_id: ChannelId, + ) -> input::Input { + let seconds_since_campaign_impression = self + .history + .read() + .await + .iter() + .rev() + .find_map(|h| { + if h.campaign_id == channel_id { + let last_impression: chrono::Duration = Utc::now() - h.time; + + u64::try_from(last_impression.num_seconds()).ok() + } else { + None + } + }) + .unwrap_or(u64::MAX); + + input.set_ad_view(input::AdView { + seconds_since_campaign_impression, + has_custom_preferences: false, + // TODO: Check this empty default! + navigator_language: self.options.navigator_language.clone().unwrap_or_default(), + }); + + input + } + + pub async fn get_sticky_ad_unit( + &self, + campaigns: &[Campaign], + hostname: &str, + ) -> Option { + if self.options.disabled_sticky { + return None; + } + + let stickiness_threshold = Utc::now() - *IMPRESSION_STICKINESS_TIME; + let sticky_entry = self + .history + .read() + .await + .iter() + .find(|h| h.time > stickiness_threshold && h.slot_id == self.options.market_slot) + .cloned()?; + + let stick_campaign = campaigns + .iter() + .find(|c| c.channel.id == sticky_entry.campaign_id)?; + + let unit = stick_campaign + .units_with_price + .iter() + .find_map(|u| { + if u.unit.id == sticky_entry.unit_id { + Some(u.unit.clone()) + } else { + None + } + }) + .expect("Something went terribly wrong. Data is corrupted! There should be an AdUnit"); + + let html = get_unit_html_with_events( + &self.options, + &unit, + hostname, + stick_campaign.channel.id, + &stick_campaign.channel.spec.validators, + true, + ); + + Some(StickyAdUnit { + unit, + price: 0.into(), + html, + is_sticky: true, + }) + } + + async fn is_campaign_sticky(&self, campaign_id: ChannelId) -> bool { + if self.options.disabled_sticky { + false + } else { + let stickiness_threshold = Utc::now() - *IMPRESSION_STICKINESS_TIME; + + self.history + .read() + .await + .iter() + .any(|h| h.time > stickiness_threshold && h.campaign_id == campaign_id) + } + } + + pub async fn get_market_demand_resp( + &self, + ) -> Result { + let pub_prefix: String = self.options.publisher_addr.to_hex_non_prefix_string(); + + let deposit_asset = self + .options + .whitelisted_tokens + .iter() + .map(|token| format!("depositAsset={}", token)) + .collect::>() + .join("&"); + + + // Url adds a trailing `/` + let url = format!( + "{}units-for-slot/{}?pubPrefix={}&{}", + self.options.market_url, self.options.market_slot, pub_prefix, deposit_asset + ); + + let market_response = self.client.get(&url).send().await?; + + if market_response.status() != StatusCode::OK { + Err(Error::Market { + status: market_response.status(), + url, + }) + } else { + let units_for_slot_response = market_response.json().await?; + + Ok(units_for_slot_response) + } + } + + pub async fn get_next_ad_unit(&self) -> Result, Error> { + let units_for_slot = self.get_market_demand_resp().await?; + let campaigns = &units_for_slot.campaigns; + let fallback_unit = units_for_slot.fallback_unit; + let targeting_input = input::Getter { + base: units_for_slot.targeting_input_base, + ad_unit: None, + channel: None, + last_approved: None, + deposit_asset: None, + }; + + let hostname = targeting_input + .try_get("adSlot.hostname") + .and_then(Value::try_string) + .unwrap_or_default(); + + // Stickiness is when we keep showing an ad unit for a slot for some time in order to achieve fair impression value + // see https://github.com/AdExNetwork/adex-adview-manager/issues/65 + let sticky_result = self.get_sticky_ad_unit(campaigns, &hostname).await; + if let Some(sticky) = sticky_result { + return Ok(Some(NextAdUnit { + unit: sticky.unit, + price: sticky.price, + accepted_referrers: units_for_slot.accepted_referrers, + html: sticky.html, + })); + } + + // If two or more units result in the same price, apply random selection between them: this is why we need the seed + let mut rng = rand::thread_rng(); + + let random: f64 = rng.gen::() * (0x80000000_u64 as f64 - 1.0); + let seed = BigNum::from(random as u64); + + // Apply targeting, now with adView.* variables, and sort the resulting ad units + let mut units_with_price: Vec<(UnitsWithPrice, ChannelId)> = campaigns + .iter() + .map(|campaign| { + // since we are in a Iterator.map(), we can't use async, so we block + if block_on(self.is_campaign_sticky(campaign.channel.id)) { + return vec![]; + } + let mut campaign_input = targeting_input.clone(); + let campaign_id = campaign.channel.id; + campaign_input.channel = Some(campaign.channel.clone()); + + campaign + .units_with_price + .iter() + .filter(|unit_with_price| { + campaign_input.ad_unit = Some(unit_with_price.unit.clone()); + + let mut output = targeting::Output { + show: true, + boost: 1.0, + price: vec![("IMPRESSION".to_string(), unit_with_price.price.clone())] + .into_iter() + .collect(), + }; + + let on_type_error = |error, rule| error!(&self.logger, "Rule evaluation error for {:?}", campaign_id; "error" => ?error, "rule" => ?rule); + + targeting::eval_with_callback( + &campaign.targeting_rules, + &input::Input::Getter(campaign_input.clone()), + &mut output, + Some(on_type_error) + ); + + output.show + }) + .map(|uwp| (uwp.clone(), campaign_id)) + .collect() + }) + .flatten() + .filter(|x| !(self.options.disabled_video && is_video(&x.0.unit))) + .collect(); + + units_with_price.sort_by(|b, a| match (&a.0.price).cmp(&b.0.price) { + Ordering::Equal => randomized_sort_pos(&a.0.unit, seed.clone()) + .cmp(&randomized_sort_pos(&b.0.unit, seed.clone())), + ordering => ordering, + }); + + // Update history + let auction_winner = units_with_price.get(0); + + if let Some((unit_with_price, campaign_id)) = auction_winner { + let history = self.history.read().await.clone(); + + let new_entry = HistoryEntry { + time: Utc::now(), + unit_id: unit_with_price.unit.id.clone(), + campaign_id: *campaign_id, + slot_id: self.options.market_slot.clone(), + }; + + *self.history.write().await = history + .into_iter() + .chain(std::iter::once(new_entry)) + // Reverse the iterator since we want to remove the oldest history entries + .rev() + .take(HISTORY_LIMIT as usize) + .collect::>() + // Keeps the same order, as the one we've started with! Old => New + .into_iter() + .rev() + .collect(); + } + + // Return the results, with a fallback unit if there is one + if let Some((unit_with_price, campaign_id)) = auction_winner { + let validators = campaigns + .iter() + .find_map(|campaign| { + if &campaign.channel.id == campaign_id { + Some(&campaign.channel.spec.validators) + } else { + None + } + }) + // TODO: Check what should happen here if we don't find the Validator + .unwrap(); + + let html = get_unit_html_with_events( + &self.options, + &unit_with_price.unit, + &hostname, + *campaign_id, + validators, + false, + ); + + Ok(Some(NextAdUnit { + unit: unit_with_price.unit.clone(), + price: unit_with_price.price.clone(), + accepted_referrers: units_for_slot.accepted_referrers, + html, + })) + } else if let Some(fallback_unit) = fallback_unit { + let html = get_unit_html(&self.options.size(), &fallback_unit, &hostname, "", ""); + Ok(Some(NextAdUnit { + unit: fallback_unit, + price: 0.into(), + accepted_referrers: units_for_slot.accepted_referrers, + html, + })) + } else { + Ok(None) + } + } +} + +pub struct NextAdUnit { + pub unit: AdUnit, + pub price: BigNum, + pub accepted_referrers: Vec, + pub html: String, +} + +pub struct StickyAdUnit { + pub unit: AdUnit, + pub price: BigNum, + pub html: String, + pub is_sticky: bool, } #[cfg(test)] mod test { use super::*; - use adex_primitives::ValidatorId; - use std::convert::TryFrom; + use adex_primitives::util::tests::prep_db::DUMMY_IPFS; fn get_ad_unit(media_mime: &str) -> AdUnit { - let owner = ValidatorId::try_from("0xce07CbB7e054514D590a0262C93070D838bFBA2e") - .expect("Should be valid ValidatorId string"); AdUnit { - ipfs: "".to_string(), - ad_type: "".to_string(), + id: DUMMY_IPFS[0].clone(), media_url: "".to_string(), media_mime: media_mime.to_string(), target_url: "".to_string(), - targeting: vec![], - min_targeting_score: None, - tags: vec![], - owner, - created: Utc::now(), - title: None, - description: None, - archived: false, - modified: None, } } @@ -338,4 +632,24 @@ mod test { // Non-IPFS case assert_eq!("http://123".to_string(), normalize_url("http://123")); } + + mod randomized_sort_pos { + + use super::*; + + #[test] + fn test_randomized_position() { + let ad_unit = AdUnit { + id: DUMMY_IPFS[0].clone(), + media_url: "ipfs://QmWWQSuPMS6aXCbZKpEjPHPUZN2NjB3YrhJTHsV4X3vb2t".to_string(), + media_mime: "image/jpeg".to_string(), + target_url: "https://google.com".to_string(), + }; + + let result = randomized_sort_pos(&ad_unit, 5.into()); + + // The seed is responsible for generating different results since the AdUnit IPFS can be the same + assert_eq!(BigNum::from(177_349_401), result); + } + } } diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 290cf2b49..5b4880a04 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -23,16 +23,16 @@ slog-async = "^2.3.0" thiserror = "^1.0" chrono = { version = "0.4", features = ["serde"] } time = "0.1.42" -hex = "0.3.2" # CID & multihash / multibase cid = "0.5" +hex = "0.4" merkletree = "0.10.0" tiny-keccak = "1.5" rust-crypto = "0.2" url = { version = "2.1", features = ["serde"]} # Numbers - BigNum, Numbers, Traits and Derives -num-bigint = { version = "0.2", features = ["serde"] } -num = "0.2.0" +num-bigint = { version = "^0.3", features = ["serde"] } +num = "0.3" num-traits = "0.2" num-derive = "0.2" # Fixtures @@ -43,7 +43,7 @@ postgres-types = { version = "0.1.0", optional = true } bytes = { version = "0.5", optional = true } tokio-postgres = { version = "0.5.1", optional = true, features = ["with-chrono-0_4", "with-serde_json-1"] } # Futures -futures = "0.3.1" +futures = "0.3" async-trait = "0.1.40" # Other lazy_static = "1.4.0" diff --git a/primitives/src/ad_slot.rs b/primitives/src/ad_slot.rs index a327d0610..fd85dc30e 100644 --- a/primitives/src/ad_slot.rs +++ b/primitives/src/ad_slot.rs @@ -1,4 +1,4 @@ -use crate::{targeting::Rule, BigNum, TargetingTag, ValidatorId}; +use crate::{targeting::Rule, BigNum, ValidatorId}; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -21,19 +21,9 @@ pub struct AdSlot { /// see IAB ad unit guidelines and iab_flex_{adUnitName} (see IAB's new ad portfolio and PDF) #[serde(rename = "type")] pub ad_type: String, - /// Array of TargetingTag - #[serde(default)] - pub targeting: Vec, // HashMap for the minimum payment accepted per impression #[serde(default)] pub min_per_impression: Option>, - /// Array of TargetingTag - /// meant for discovery between publishers/advertisers - #[serde(default)] - pub tags: Vec, - #[serde(default)] - pub auto_tags: Vec, - /// Targeting rules #[serde(default)] pub rules: Vec, /// Valid ipfs hash for Ad Unit object. It will be used as fallback data (optional) diff --git a/primitives/src/ad_unit.rs b/primitives/src/ad_unit.rs index 5cc3f8831..a2f38218c 100644 --- a/primitives/src/ad_unit.rs +++ b/primitives/src/ad_unit.rs @@ -1,13 +1,13 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; -use crate::{TargetingTag, ValidatorId}; +use crate::{ValidatorId, IPFS}; -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] #[serde(rename_all = "camelCase")] pub struct AdUnit { /// valid ipfs hash of spec props below - pub ipfs: String, + pub ipfs: IPFS, /// the type of the ad unit /// currently, possible values are: /// legacy_300x250, legacy_250x250, legacy_240x400, legacy_336x280, @@ -24,14 +24,8 @@ pub struct AdUnit { pub media_mime: String, /// Advertised URL pub target_url: String, - /// Array of TargetingTag - pub targeting: Vec, /// Number; minimum targeting score (optional) pub min_targeting_score: Option, - /// Array of TargetingTag (optional) - /// meant for discovery between publishers/advertisers - #[serde(default)] - pub tags: Vec, /// user address from the session pub owner: ValidatorId, /// number, UTC timestamp in milliseconds, used as nonce for escaping duplicated spec ipfs hashes diff --git a/primitives/src/big_num.rs b/primitives/src/big_num.rs index 38cdaa11c..a8863deaf 100644 --- a/primitives/src/big_num.rs +++ b/primitives/src/big_num.rs @@ -44,6 +44,10 @@ impl BigNum { pub fn to_str_radix(&self, radix: u32) -> String { self.0.to_str_radix(radix) } + + pub fn from_bytes_be(buf: &[u8]) -> Self { + Self(BigUint::from_bytes_be(buf)) + } } impl fmt::Debug for BigNum { diff --git a/primitives/src/channel.rs b/primitives/src/channel.rs index 51171c743..51dafc9f0 100644 --- a/primitives/src/channel.rs +++ b/primitives/src/channel.rs @@ -7,9 +7,7 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Deserializer, Serialize}; use serde_hex::{SerHex, StrictPfx}; -use crate::{ - targeting::Rule, AdUnit, BigNum, EventSubmission, TargetingTag, ValidatorDesc, ValidatorId, -}; +use crate::{targeting::Rule, AdUnit, BigNum, EventSubmission, ValidatorDesc, ValidatorId}; use hex::{FromHex, FromHexError}; #[derive(Serialize, Deserialize, PartialEq, Eq, Copy, Clone, Hash)] @@ -76,7 +74,7 @@ impl fmt::Display for ChannelId { } } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] #[serde(rename_all = "camelCase")] pub struct Channel { pub id: ChannelId, @@ -90,13 +88,13 @@ pub struct Channel { pub spec: ChannelSpec, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] pub struct Pricing { pub max: BigNum, pub min: BigNum, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] #[serde(rename_all = "UPPERCASE")] pub struct PricingBounds { #[serde(default, skip_serializing_if = "Option::is_none")] @@ -129,25 +127,21 @@ impl PricingBounds { } } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] #[serde(rename_all = "camelCase")] pub struct ChannelSpec { #[serde(default, skip_serializing_if = "Option::is_none")] pub title: Option, pub validators: SpecValidators, /// Maximum payment per impression + /// **OBSOLETE**, only used if `pricingBounds` is missing an `IMPRESSION` entry pub max_per_impression: BigNum, /// Minimum payment offered per impression + /// **OBSOLETE**, only used if `pricingBounds` is missing an `IMPRESSION` entry pub min_per_impression: BigNum, /// Event pricing bounds #[serde(default, skip_serializing_if = "Option::is_none")] pub pricing_bounds: Option, - /// An array of TargetingTag (optional) - #[serde(default, skip_serializing_if = "Vec::is_empty")] - pub targeting: Vec, - /// Minimum targeting score (optional) - #[serde(default, skip_serializing_if = "Option::is_none")] - pub min_targeting_score: Option, /// EventSubmission object, applies to event submission (POST /channel/:id/events) #[serde(default, skip_serializing_if = "Option::is_none")] pub event_submission: Option, @@ -176,30 +170,9 @@ pub struct ChannelSpec { pub ad_units: Vec, #[serde(default)] pub targeting_rules: Vec, - #[serde(default, skip_serializing_if = "Vec::is_empty")] - pub price_multiplication_rules: Vec, - #[serde(default)] - pub price_dynamic_adjustment: bool, -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -#[serde(rename_all = "camelCase")] -pub struct PriceMultiplicationRules { - #[serde(default, skip_serializing_if = "Option::is_none")] - pub multiplier: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub amount: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub ev_type: Option>, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub publisher: Option>, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub os_type: Option>, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub country: Option>, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] /// A (leader, follower) tuple pub struct SpecValidators(ValidatorDesc, ValidatorDesc); diff --git a/primitives/src/event_submission.rs b/primitives/src/event_submission.rs index 3086242e5..d6205c615 100644 --- a/primitives/src/event_submission.rs +++ b/primitives/src/event_submission.rs @@ -1,13 +1,13 @@ use serde::{Deserialize, Serialize}; use std::time::Duration; -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] pub struct EventSubmission { #[serde(default)] pub allow: Vec, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] #[serde(rename_all = "camelCase")] pub struct Rule { #[serde(default)] @@ -16,7 +16,7 @@ pub struct Rule { pub rate_limit: Option, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] #[serde(rename_all = "camelCase")] pub struct RateLimit { /// "ip", "uid" diff --git a/primitives/src/ipfs.rs b/primitives/src/ipfs.rs index e28b1b431..bceb942ae 100644 --- a/primitives/src/ipfs.rs +++ b/primitives/src/ipfs.rs @@ -5,6 +5,8 @@ use thiserror::Error; const URL_PREFIX: &str = "ipfs://"; +pub use cid::{Cid, Error}; + #[derive(Clone, Serialize, Deserialize, Eq, PartialEq)] #[serde(try_from = "String", into = "String")] pub struct IPFS(pub cid::Cid); @@ -43,6 +45,14 @@ impl TryFrom for IPFS { } } +impl TryFrom<&String> for IPFS { + type Error = cid::Error; + + fn try_from(value: &String) -> Result { + Self::try_from(value.as_str()) + } +} + impl<'a> TryFrom<&'a str> for IPFS { type Error = cid::Error; @@ -163,18 +173,25 @@ impl fmt::Debug for Url { mod test { use super::*; - static TESTS_IPFS_V1: [&str; 4] = [ + // CID V0 + static TESTS_IPFS_V0: [&str; 4] = [ "QmcUVX7fvoLMM93uN2bD3wGTH8MXSxeL8hojYfL2Lhp7mR", "Qmasg8FrbuSQpjFu3kRnZF9beg8rEBFrqgi1uXDRwCbX5f", "QmQnu8zrHsuVvnTJsEgDHYA8c1MmRL7YLiMD8uzDUJKcNq", "QmYYBULc9QDEaDr8HAXvVWHDmFfL2GvyumYRr1g4ERBC96", ]; + // CID V1 + static TESTS_IPFS_V1: [&str; 1] = [ + // V1 of the V0 ipfs: `QmcUVX7fvoLMM93uN2bD3wGTH8MXSxeL8hojYfL2Lhp7mR` + "bafybeif2h3mynaf3ylgdbs6arf6mczqycargt5cqm3rmel3wpjarlswway", + ]; + #[test] fn ipfs_from_string_and_serialize_deserialize() { - for &ipfs_str in TESTS_IPFS_V1.iter() { + let check = |ipfs_str: &str, version: cid::Version| { let ipfs = IPFS::try_from(ipfs_str).expect("should be ok"); - assert_eq!(ipfs.0.version(), cid::Version::V0); + assert_eq!(ipfs.0.version(), version); assert_eq!(ipfs.0.to_string(), ipfs_str); let expected_json = format!("\"{}\"", ipfs); @@ -185,7 +202,21 @@ mod test { ipfs, serde_json::from_str(&actual_json).expect("Should Deserialize") ) + }; + + for &ipfs_str in TESTS_IPFS_V0.iter() { + check(ipfs_str, cid::Version::V0) } + + for &ipfs_str in TESTS_IPFS_V1.iter() { + check(ipfs_str, cid::Version::V1) + } + + // v0 != v1 + assert_ne!( + IPFS::try_from(TESTS_IPFS_V0[0]), + IPFS::try_from(TESTS_IPFS_V1[0]) + ) } #[test] @@ -216,15 +247,20 @@ mod test { } // Invalid cases - // CID V1 - Invalid scheme - valid IPFS + // CID V0 - Invalid scheme - valid IPFS assert_eq!( Err(UrlError::NoPrefix), "https://QmcUVX7fvoLMM93uN2bD3wGTH8MXSxeL8hojYfL2Lhp7mR".parse::() ); - // CID V1 - Invalid scheme - valid IPFS + // CID V0 - Invalid scheme - valid IPFS assert_eq!( Err(UrlError::IPFS(cid::Error::ParsingError)), "ipfs://NotValid".parse::() ); + // CID V1 - Invalid scheme - valid IPFS + assert_eq!( + Err(UrlError::NoPrefix), + "https://bafybeif2h3mynaf3ylgdbs6arf6mczqycargt5cqm3rmel3wpjarlswway".parse::() + ); } } diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index e1295d622..64b31eb2b 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -22,8 +22,16 @@ pub mod targeting_tag; pub mod util { pub mod tests { + use slog::{o, Discard, Drain, Logger}; + pub mod prep_db; pub mod time; + + pub fn discard_logger() -> Logger { + let drain = Discard.fuse(); + + Logger::root(drain, o!()) + } } pub mod logging; diff --git a/primitives/src/sentry.rs b/primitives/src/sentry.rs index 55822e21c..4428dbbe7 100644 --- a/primitives/src/sentry.rs +++ b/primitives/src/sentry.rs @@ -127,6 +127,8 @@ pub struct AggregateEvents { pub struct ChannelListResponse { pub channels: Vec, pub total_pages: u64, + pub total: u64, + pub page: u64, } #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] diff --git a/primitives/src/supermarket.rs b/primitives/src/supermarket.rs index cd710ac83..3f7acd564 100644 --- a/primitives/src/supermarket.rs +++ b/primitives/src/supermarket.rs @@ -1,6 +1,6 @@ use crate::{BalancesMap, Channel}; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct Campaign { pub channel: Channel, pub status: Status, @@ -39,9 +39,14 @@ pub enum Finalized { Exhausted, Withdraw, } + pub mod units_for_slot { pub mod response { - use crate::{targeting::Rule, BigNum, ChannelId, ChannelSpec, SpecValidators, ValidatorId}; + + use crate::{ + targeting::{Map, Rule}, + BigNum, ChannelId, ChannelSpec, SpecValidators, ValidatorId, IPFS, + }; use chrono::{ serde::{ts_milliseconds, ts_milliseconds_option}, DateTime, Utc, @@ -49,24 +54,23 @@ pub mod units_for_slot { use serde::{Deserialize, Serialize}; use url::Url; - #[derive(Debug, Serialize, Deserialize)] + #[derive(Debug, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct Response { - // TODO: This should be Input, however, we only need the fields and not the Global: Channel, Status & BalancesMap - pub targeting_input_base: (), + pub targeting_input_base: Map, pub accepted_referrers: Vec, - pub fallback_unit: AdUnit, + pub fallback_unit: Option, pub campaigns: Vec, } - #[derive(Debug, Serialize, Deserialize)] + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct UnitsWithPrice { pub unit: AdUnit, pub price: BigNum, } - #[derive(Debug, Serialize, Deserialize)] + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct Campaign { #[serde(flatten)] @@ -75,7 +79,7 @@ pub mod units_for_slot { pub units_with_price: Vec, } - #[derive(Debug, Serialize, Deserialize)] + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct Channel { pub id: ChannelId, @@ -97,7 +101,7 @@ pub mod units_for_slot { } } - #[derive(Debug, Serialize, Deserialize)] + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct Spec { #[serde(with = "ts_milliseconds")] @@ -124,11 +128,11 @@ pub mod units_for_slot { } } - #[derive(Debug, Serialize, Deserialize, Clone)] + #[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)] #[serde(rename_all = "camelCase")] pub struct AdUnit { /// Same as `ipfs` - pub id: String, + pub id: IPFS, pub media_url: String, pub media_mime: String, pub target_url: String, diff --git a/primitives/src/targeting.rs b/primitives/src/targeting.rs index 14407476c..d476fdab0 100644 --- a/primitives/src/targeting.rs +++ b/primitives/src/targeting.rs @@ -1,160 +1,551 @@ -use crate::{ - channel::Pricing, supermarket::Status, AdUnit, BalancesMap, BigNum, Channel, ToETHChecksum, - ValidatorId, -}; -use chrono::Utc; -use std::collections::HashMap; +use crate::{channel::Pricing, BigNum, Channel}; pub use eval::*; use serde_json::Number; +use std::collections::HashMap; + +pub use input::{Getter, Input, Map}; mod eval; -#[derive(Debug, Clone)] -pub struct Input { - /// AdView scope, accessible only on the AdView - pub ad_view: Option, - /// Global scope, accessible everywhere - pub global: Global, - /// adSlot scope, accessible on Supermarket and AdView - pub ad_slot: Option, -} +pub mod input { + use super::{get_pricing_bounds, Error, Value}; + use crate::{ + supermarket::units_for_slot::response::{AdUnit as UFSAdUnit, Channel as UFSChannel}, + AdUnit, BalancesMap, ToETHChecksum, ValidatorId, + }; -impl Input { - fn try_get(&self, key: &str) -> Result { - let spec = &self.global.channel.spec; + use chrono::Utc; + use serde::Serialize; + use std::collections::HashMap; + use std::convert::TryFrom; + + pub type Map = HashMap; + + #[derive(Debug, Clone)] + pub struct Getter { + pub base: Map, + pub ad_unit: Option, + pub channel: Option, + pub last_approved: Option, + pub deposit_asset: Option, + } - match key { - // AdView scope, accessible only on the AdView - "adView.secondsSinceCampaignImpression" => self - .ad_view - .as_ref() - .map(|ad_view| Value::Number(ad_view.seconds_since_campaign_impression.into())) - .ok_or(Error::UnknownVariable), - "adView.hasCustomPreferences" => self - .ad_view - .as_ref() - .map(|ad_view| Value::Bool(ad_view.has_custom_preferences)) - .ok_or(Error::UnknownVariable), - "adView.navigatorLanguage" => self - .ad_view - .as_ref() - .map(|ad_view| Value::String(ad_view.navigator_language.clone())) - .ok_or(Error::UnknownVariable), - // Global scope, accessible everywhere - "adSlotId" => Ok(Value::String(self.global.ad_slot_id.clone())), - "adSlotType" => Ok(Value::String(self.global.ad_slot_type.clone())), - "publisherId" => Ok(Value::String(self.global.publisher_id.to_checksum())), - "country" => self - .global - .country - .clone() - .ok_or(Error::UnknownVariable) - .map(Value::String), - "eventType" => Ok(Value::String(self.global.event_type.clone())), - "secondsSinceEpoch" => Ok(Value::Number(self.global.seconds_since_epoch.into())), - "userAgentOS" => self - .global - .user_agent_os - .clone() - .map(Value::String) - .ok_or(Error::UnknownVariable), - "userAgentBrowserFamily" => self - .global - .user_agent_browser_family - .clone() - .map(Value::String) - .ok_or(Error::UnknownVariable), - // Global scope, accessible everywhere, campaign-dependant - "adUnitId" => { - let ipfs = self - .global - .ad_unit - .as_ref() - .map(|ad_unit| ad_unit.ipfs.clone()); - Ok(Value::String(ipfs.unwrap_or_default())) - } - "advertiserId" => { - let creator = self.global.channel.creator.to_hex_prefix_string(); + impl Getter { + /// This method will first check the set properties of Getter (ad_unit, channel, last_approved) + /// if they are set, it will use them, otherwise it will fallback to the base HashMap + /// containing the other keys of the Input + pub fn try_get(&self, key: &str) -> Result { + let channel = self.channel.as_ref(); + let balances_map = self.last_approved.as_ref(); + + // TODO: Replace all `channel.is_some()` & `channel.expect(..)` with `if let`, when it gets stabilized + match key { + "adUnitId" => { + let ipfs = self.ad_unit.as_ref().map(|ad_unit| ad_unit.id.clone()); + Ok(Value::String( + ipfs.map(|ipfs| ipfs.to_string()).unwrap_or_default(), + )) + } - Ok(Value::String(creator)) - } - "campaignId" => Ok(Value::String(self.global.channel.id.to_string())), - "campaignTotalSpent" => Ok(Value::BigNum( - self.global - .balances - .as_ref() - .map(|b| b.values().sum()) - .unwrap_or_default(), - )), - "campaignSecondsActive" => { - let duration = Utc::now() - spec.active_from.unwrap_or(spec.created); + "advertiserId" if channel.is_some() => { + let channel = channel.expect("We did check is_some(), this should never fail!"); - let seconds = duration - .to_std() - .map(|duration| duration.as_secs()) - .unwrap_or(0); + let creator = channel.creator.to_hex_prefix_string(); + Ok(Value::String(creator)) + } - Ok(Value::Number(seconds.into())) - } - "campaignSecondsDuration" => { - let duration = - spec.withdraw_period_start - spec.active_from.unwrap_or(spec.created); - let seconds = duration - .to_std() - .map(|std_duration| std_duration.as_secs()) - .unwrap_or(0); - - Ok(Value::Number(seconds.into())) + "campaignId" if channel.is_some() => { + let channel = channel.expect("We did check is_some(), this should never fail!"); + + Ok(Value::String(channel.id.to_string())) + } + "campaignTotalSpent" => Ok(Value::BigNum( + balances_map.map(|b| b.values().sum()).unwrap_or_default(), + )), + "campaignSecondsActive" if channel.is_some() => { + let spec = &channel + .expect("We did check is_some(), this should never fail!") + .spec; + let duration = Utc::now() - spec.active_from.unwrap_or(spec.created); + + let seconds = duration + .to_std() + .map(|duration| duration.as_secs()) + .unwrap_or(0); + + Ok(Value::Number(seconds.into())) + } + "campaignSecondsDuration" if channel.is_some() => { + let spec = &channel + .expect("We did check is_some(), this should never fail!") + .spec; + + let duration = + spec.withdraw_period_start - spec.active_from.unwrap_or(spec.created); + let seconds = duration + .to_std() + .map(|std_duration| std_duration.as_secs()) + .unwrap_or(0); + + Ok(Value::Number(seconds.into())) + } + "campaignBudget" if channel.is_some() => { + let channel = channel.expect("We did check is_some(), this should never fail!"); + + Ok(Value::BigNum(channel.deposit_amount.clone())) + } + // TODO: Should we be able to get the pricing bounds from Market's Channel/Campaign or directly use the Base? + // Skip the eventMinPrice & eventMaxPrice + // "eventMinPrice" if self.pricing_bounds.is_some() => { + + // let event_type = self + // .base + // .get("eventType") + // .ok_or(Error::UnknownVariable)? + // .clone() + // .try_string()?; + // let min = get_pricing_bounds(todo!(), &event_type).min; + + // Ok(Value::BigNum(min)) + // } + + // "eventMaxPrice" if self.pricing_bounds.is_some() => { + // let event_type = self + // .base + // .get("eventType") + // .ok_or(Error::UnknownVariable)? + // .clone() + // .try_string()?; + + // let max = get_pricing_bounds(todo!(), &event_type).max; + // Ok(Value::BigNum(max)) + // } + "publisherEarnedFromCampaign" if channel.is_some() => { + let publisher_id = + self.base.get("publisherId").ok_or(Error::UnknownVariable)?; + let publisher_id = ValidatorId::try_from(publisher_id.clone()) + .map_err(|_| Error::TypeError)?; + + let earned = balances_map + .and_then(|balances| balances.get(&publisher_id)) + .cloned() + .unwrap_or_default(); + + Ok(Value::BigNum(earned)) + } + // Otherwise we will look into the base HashMap + key => self + .base + .get(key) + .ok_or(Error::UnknownVariable) + .map(Clone::clone), } - "campaignBudget" => Ok(Value::BigNum(self.global.channel.deposit_amount.clone())), - "eventMinPrice" => { - let min = get_pricing_bounds(&self.global.channel, &self.global.event_type).min; - Ok(Value::BigNum(min)) + } + } + + #[derive(Debug)] + pub enum Input { + /// Used for when we deserialize the input and we need to be able to get the same fields as the Source + Getter(Getter), + /// We have the deposit_asset from the Source.global.channel + Source(Box), + } + + impl Input { + /// - For Getter: + /// this method will call the `Getter::try_get()` method with the **currently** set properties + /// of the Getter + /// - For Source: + /// This method will call the `Source::try_get()` as well + pub fn try_get(&self, key: &str) -> Result { + match self { + Input::Getter(getter) => getter.try_get(key), + Input::Source(input) => input.try_get(key), } - "eventMaxPrice" => { - let max = get_pricing_bounds(&self.global.channel, &self.global.event_type).max; - Ok(Value::BigNum(max)) + } + + /// AdView scope, accessible only on the AdView + pub fn set_ad_view(&mut self, ad_view: AdView) { + match self { + Input::Getter(getter) => { + getter.base.insert( + "adView.secondsSinceCampaignImpression".to_string(), + Value::Number(ad_view.seconds_since_campaign_impression.into()), + ); + getter.base.insert( + "adView.hasCustomPreferences".to_string(), + Value::Bool(ad_view.has_custom_preferences), + ); + getter.base.insert( + "adView.navigatorLanguage".to_string(), + Value::String(ad_view.navigator_language), + ); + } + Input::Source(source) => source.ad_view = Some(ad_view), } - "publisherEarnedFromCampaign" => { - let earned = self + } + + pub fn deposit_asset(&self) -> Option { + match self { + Input::Getter(getter) => getter.deposit_asset.clone(), + Input::Source(source) => source .global - .balances + .channel .as_ref() - .and_then(|balances| balances.get(&self.global.publisher_id)) - .cloned() - .unwrap_or_default(); + .map(|c| c.deposit_asset.clone()), + } + } + } - Ok(Value::BigNum(earned)) + #[derive(Debug, Clone, Serialize)] + #[serde(into = "Map")] + pub struct Source { + /// AdView scope, accessible only on the AdView + pub ad_view: Option, + /// Global scope, accessible everywhere + pub global: Global, + /// adSlot scope, accessible on Supermarket and AdView + pub ad_slot: Option, + } + + #[derive(Debug, Clone)] + pub struct AdView { + pub seconds_since_campaign_impression: u64, + pub has_custom_preferences: bool, + pub navigator_language: String, + } + + #[derive(Debug, Clone)] + pub struct Global { + /// Global scope, accessible everywhere + pub ad_slot_id: String, + pub ad_slot_type: String, + pub publisher_id: ValidatorId, + pub country: Option, + pub event_type: String, + pub seconds_since_epoch: u64, + pub user_agent_os: Option, + pub user_agent_browser_family: Option, + /// Global scope, accessible everywhere, campaign-dependant + pub ad_unit: Option, + /// We use the regular full Channel here + pub channel: Option, + pub balances: Option, + } + + #[derive(Debug, Clone)] + pub struct AdSlot { + pub categories: Vec, + pub hostname: String, + pub alexa_rank: Option, + } + + impl From for Map { + fn from(input_source: Source) -> Self { + let mut map = Self::new(); + + let fields = [ + // AdView scope, accessible only on the AdView + "adView.secondsSinceCampaignImpression", + "adView.hasCustomPreferences", + "adView.navigatorLanguage", + // Global scope, accessible everywhere + "adSlotId", + "adSlotType", + "publisherId", + "country", + "eventType", + "secondsSinceEpoch", + "userAgentOS", + "userAgentBrowserFamily", + // Global scope, accessible everywhere, campaign-dependant + "adUnitId", + "advertiserId", + "campaignId", + "campaignTotalSpent", + "campaignSecondsActive", + "campaignSecondsDuration", + "campaignBudget", + "eventMinPrice", + "eventMaxPrice", + "publisherEarnedFromCampaign", + // adSlot scope, accessible on Supermarket and AdView + "adSlot.categories", + "adSlot.hostname", + "adSlot.alexaRank", + ]; + + for field in fields.iter() { + // if there is an Error, it will be `UnknownVariable` and we just skip it + + if let Ok(value) = input_source.try_get(field) { + // we don't care if there is an old value, there shouldn't be one! + map.insert(field.to_string(), value); + } } - // adSlot scope, accessible on Supermarket and AdView - "adSlot.categories" => self - .ad_slot - .as_ref() - .map(|ad_slot| { - let array = ad_slot - .categories - .iter() - .map(|string| Value::String(string.clone())) - .collect(); - Value::Array(array) - }) - .ok_or(Error::UnknownVariable), - "adSlot.hostname" => self - .ad_slot - .as_ref() - .map(|ad_slot| Value::String(ad_slot.hostname.clone())) - .ok_or(Error::UnknownVariable), - "adSlot.alexaRank" => { - let ad_slot = self.ad_slot.as_ref().ok_or(Error::UnknownVariable)?; - let alexa_rank = ad_slot.alexa_rank.ok_or(Error::UnknownVariable)?; - - match serde_json::Number::from_f64(alexa_rank) { - Some(number) => Ok(Value::Number(number)), - None => Err(Error::TypeError), + + map + } + } + + impl Source { + fn try_get(&self, key: &str) -> Result { + match key { + // AdView scope, accessible only on the AdView + "adView.secondsSinceCampaignImpression" => self + .ad_view + .as_ref() + .map(|ad_view| Value::Number(ad_view.seconds_since_campaign_impression.into())) + .ok_or(Error::UnknownVariable), + "adView.hasCustomPreferences" => self + .ad_view + .as_ref() + .map(|ad_view| Value::Bool(ad_view.has_custom_preferences)) + .ok_or(Error::UnknownVariable), + "adView.navigatorLanguage" => self + .ad_view + .as_ref() + .map(|ad_view| Value::String(ad_view.navigator_language.clone())) + .ok_or(Error::UnknownVariable), + // Global scope, accessible everywhere + "adSlotId" => Ok(Value::String(self.global.ad_slot_id.clone())), + "adSlotType" => Ok(Value::String(self.global.ad_slot_type.clone())), + "publisherId" => Ok(Value::String(self.global.publisher_id.to_checksum())), + "country" => self + .global + .country + .clone() + .ok_or(Error::UnknownVariable) + .map(Value::String), + "eventType" => Ok(Value::String(self.global.event_type.clone())), + "secondsSinceEpoch" => Ok(Value::Number(self.global.seconds_since_epoch.into())), + "userAgentOS" => self + .global + .user_agent_os + .clone() + .map(Value::String) + .ok_or(Error::UnknownVariable), + "userAgentBrowserFamily" => self + .global + .user_agent_browser_family + .clone() + .map(Value::String) + .ok_or(Error::UnknownVariable), + // Global scope, accessible everywhere, campaign-dependant + "adUnitId" => { + let ipfs = self + .global + .ad_unit + .as_ref() + .map(|ad_unit| ad_unit.ipfs.to_string()); + + Ok(Value::String(ipfs.unwrap_or_default())) } + "advertiserId" => self + .global + .channel + .as_ref() + .map(|channel| Value::String(channel.creator.to_hex_prefix_string())) + .ok_or(Error::UnknownVariable), + "campaignId" => self + .global + .channel + .as_ref() + .map(|channel| Value::String(channel.id.to_string())) + .ok_or(Error::UnknownVariable), + "campaignTotalSpent" => Ok(Value::BigNum( + self.global + .balances + .as_ref() + .map(|b| b.values().sum()) + .unwrap_or_default(), + )), + "campaignSecondsActive" => self + .global + .channel + .as_ref() + .map(|channel| { + let duration = + Utc::now() - channel.spec.active_from.unwrap_or(channel.spec.created); + + let seconds = duration + .to_std() + .map(|duration| duration.as_secs()) + .unwrap_or(0); + + Value::Number(seconds.into()) + }) + .ok_or(Error::UnknownVariable), + "campaignSecondsDuration" => self + .global + .channel + .as_ref() + .map(|channel| { + let spec = &channel.spec; + let duration = + spec.withdraw_period_start - spec.active_from.unwrap_or(spec.created); + let seconds = duration + .to_std() + .map(|std_duration| std_duration.as_secs()) + .unwrap_or(0); + + Value::Number(seconds.into()) + }) + .ok_or(Error::UnknownVariable), + "campaignBudget" => self + .global + .channel + .as_ref() + .map(|channel| Value::BigNum(channel.deposit_amount.clone())) + .ok_or(Error::UnknownVariable), + "eventMinPrice" => self + .global + .channel + .as_ref() + .map(|channel| { + let min = get_pricing_bounds(channel, &self.global.event_type).min; + Value::BigNum(min) + }) + .ok_or(Error::UnknownVariable), + "eventMaxPrice" => self + .global + .channel + .as_ref() + .map(|channel| { + let max = get_pricing_bounds(channel, &self.global.event_type).max; + + Value::BigNum(max) + }) + .ok_or(Error::UnknownVariable), + "publisherEarnedFromCampaign" => { + let earned = self + .global + .balances + .as_ref() + .and_then(|balances| balances.get(&self.global.publisher_id)) + .cloned() + .unwrap_or_default(); + + Ok(Value::BigNum(earned)) + } + // adSlot scope, accessible on Supermarket and AdView + "adSlot.categories" => self + .ad_slot + .as_ref() + .map(|ad_slot| { + let array = ad_slot + .categories + .iter() + .map(|string| Value::String(string.clone())) + .collect(); + Value::Array(array) + }) + .ok_or(Error::UnknownVariable), + "adSlot.hostname" => self + .ad_slot + .as_ref() + .map(|ad_slot| Value::String(ad_slot.hostname.clone())) + .ok_or(Error::UnknownVariable), + "adSlot.alexaRank" => { + let ad_slot = self.ad_slot.as_ref().ok_or(Error::UnknownVariable)?; + let alexa_rank = ad_slot.alexa_rank.ok_or(Error::UnknownVariable)?; + + match serde_json::Number::from_f64(alexa_rank) { + Some(number) => Ok(Value::Number(number)), + None => Err(Error::TypeError), + } + } + _unknown_field => Err(Error::UnknownVariable), } - _unknown_field => Err(Error::UnknownVariable), + } + } + + #[cfg(test)] + mod test { + use super::*; + use crate::util::tests::prep_db::{DUMMY_CHANNEL, DUMMY_IPFS, IDS}; + use chrono::Utc; + + #[test] + fn test_try_get_of_input() { + let ad_unit = AdUnit { + ipfs: DUMMY_IPFS[0].clone(), + ad_type: "legacy_300x250".to_string(), + media_url: "media_url".to_string(), + media_mime: "media_mime".to_string(), + target_url: "target_url".to_string(), + min_targeting_score: None, + owner: IDS["creator"], + created: Utc::now(), + title: None, + description: None, + archived: false, + modified: None, + }; + let input_balances = BalancesMap::default(); + let mut input = Source { + ad_view: Some(AdView { + seconds_since_campaign_impression: 10, + has_custom_preferences: false, + navigator_language: "bg".to_string(), + }), + global: Global { + ad_slot_id: "ad_slot_id Value".to_string(), + ad_slot_type: "ad_slot_type Value".to_string(), + publisher_id: IDS["leader"], + country: Some("bg".to_string()), + event_type: "IMPRESSION".to_string(), + seconds_since_epoch: 500, + user_agent_os: Some("os".to_string()), + user_agent_browser_family: Some("family".to_string()), + ad_unit: Some(ad_unit), + channel: Some(DUMMY_CHANNEL.clone()), + balances: Some(input_balances), + }, + ad_slot: None, + }; + + let ad_view_seconds_since_show = input + .try_get("adView.secondsSinceCampaignImpression") + .expect("Should get the ad_view.seconds_since_campaign_impression field"); + + let expected_number = serde_json::Number::from(10); + + assert_eq!(Value::Number(expected_number), ad_view_seconds_since_show); + + let ad_slot_id = input + .try_get("adSlotId") + .expect("Should get the global.ad_slot_id field"); + + assert_eq!(Value::String("ad_slot_id Value".to_string()), ad_slot_id); + + let get_unknown = input + .try_get("unknownField") + .expect_err("Should return Error"); + + assert_eq!(Error::UnknownVariable, get_unknown); + + let global_campaign_budget = input + .try_get("campaignBudget") + .expect("Should get the global.campaign_budget field"); + + assert_eq!( + Value::BigNum(DUMMY_CHANNEL.deposit_amount.clone()), + global_campaign_budget + ); + + assert_eq!( + Err(Error::UnknownVariable), + input.try_get("adSlot.alexaRank") + ); + let ad_slot = AdSlot { + categories: vec![], + hostname: "".to_string(), + alexa_rank: Some(20.0), + }; + input.ad_slot = Some(ad_slot); + assert!(input.try_get("adSlot.alexaRank").is_ok()); } } } @@ -181,38 +572,6 @@ pub fn get_pricing_bounds(channel: &Channel, event_type: &str) -> Pricing { }) } -#[derive(Debug, Clone)] -pub struct AdView { - pub seconds_since_campaign_impression: u64, - pub has_custom_preferences: bool, - pub navigator_language: String, -} - -#[derive(Debug, Clone)] -pub struct Global { - /// Global scope, accessible everywhere - pub ad_slot_id: String, - pub ad_slot_type: String, - pub publisher_id: ValidatorId, - pub country: Option, - pub event_type: String, - pub seconds_since_epoch: u64, - pub user_agent_os: Option, - pub user_agent_browser_family: Option, - /// Global scope, accessible everywhere, campaign-dependant - pub ad_unit: Option, - pub channel: Channel, - pub status: Option, - pub balances: Option, -} - -#[derive(Debug, Clone)] -pub struct AdSlot { - pub categories: Vec, - pub hostname: String, - pub alexa_rank: Option, -} - #[derive(Debug)] pub struct Output { /// Whether to show the ad @@ -271,95 +630,6 @@ impl From<&Channel> for Output { #[cfg(test)] mod test { use super::*; - use crate::{ - supermarket::Status, - util::tests::prep_db::{DUMMY_CHANNEL, IDS}, - }; - use chrono::Utc; - - #[test] - fn test_try_get_of_input() { - let ad_unit = AdUnit { - ipfs: "Hash".to_string(), - ad_type: "legacy_300x250".to_string(), - media_url: "media_url".to_string(), - media_mime: "media_mime".to_string(), - target_url: "target_url".to_string(), - targeting: vec![], - min_targeting_score: None, - tags: vec![], - owner: IDS["creator"], - created: Utc::now(), - title: None, - description: None, - archived: false, - modified: None, - }; - let input_balances = BalancesMap::default(); - let mut input = Input { - ad_view: Some(AdView { - seconds_since_campaign_impression: 10, - has_custom_preferences: false, - navigator_language: "bg".to_string(), - }), - global: Global { - ad_slot_id: "ad_slot_id Value".to_string(), - ad_slot_type: "ad_slot_type Value".to_string(), - publisher_id: IDS["leader"], - country: Some("bg".to_string()), - event_type: "IMPRESSION".to_string(), - seconds_since_epoch: 500, - user_agent_os: Some("os".to_string()), - user_agent_browser_family: Some("family".to_string()), - ad_unit: Some(ad_unit), - channel: DUMMY_CHANNEL.clone(), - status: Some(Status::Initializing), - balances: Some(input_balances), - }, - ad_slot: None, - }; - - let ad_view_seconds_since_show = input - .try_get("adView.secondsSinceCampaignImpression") - .expect("Should get the ad_view.seconds_since_campaign_impression field"); - - let expected_number = serde_json::Number::from(10); - - assert_eq!(Value::Number(expected_number), ad_view_seconds_since_show); - - let ad_slot_id = input - .try_get("adSlotId") - .expect("Should get the global.ad_slot_id field"); - - assert_eq!(Value::String("ad_slot_id Value".to_string()), ad_slot_id); - - let get_unknown = input - .try_get("unknownField") - .expect_err("Should return Error"); - - assert_eq!(Error::UnknownVariable, get_unknown); - - let global_campaign_budget = input - .try_get("campaignBudget") - .expect("Should get the global.campaign_budget field"); - - assert_eq!( - Value::BigNum(DUMMY_CHANNEL.deposit_amount.clone()), - global_campaign_budget - ); - - assert_eq!( - Err(Error::UnknownVariable), - input.try_get("adSlot.alexaRank") - ); - let ad_slot = AdSlot { - categories: vec![], - hostname: "".to_string(), - alexa_rank: Some(20.0), - }; - input.ad_slot = Some(ad_slot); - assert!(input.try_get("adSlot.alexaRank").is_ok()); - } #[test] fn test_try_get_of_output() { diff --git a/primitives/src/targeting/eval.rs b/primitives/src/targeting/eval.rs index 25e247642..3e543d851 100644 --- a/primitives/src/targeting/eval.rs +++ b/primitives/src/targeting/eval.rs @@ -10,8 +10,6 @@ use std::{ str::FromStr, }; -pub type Map = serde_json::value::Map; - use super::{Input, Output}; #[cfg(test)] @@ -85,7 +83,7 @@ impl Rule { } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -#[serde(try_from = "SerdeValue")] +#[serde(try_from = "SerdeValue", into = "SerdeValue")] pub enum Value { Bool(bool), Number(Number), @@ -126,6 +124,18 @@ impl TryFrom for Value { } } +impl Into for Value { + fn into(self) -> SerdeValue { + match self { + Value::Bool(bool) => SerdeValue::Bool(bool), + Value::Number(number) => SerdeValue::Number(number), + Value::String(string) => SerdeValue::String(string), + Value::Array(array) => SerdeValue::Array(array.into_iter().map(|value| value.into()).collect()), + Value::BigNum(bignum) => SerdeValue::String(bignum.to_string()) + } + } +} + #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] #[serde(rename_all = "camelCase")] // TODO: https://github.com/AdExNetwork/adex-validator-stack-rust/issues/296 @@ -893,10 +903,13 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result .eval(input, output)? .ok_or(Error::TypeError)? .try_bignum()?; - let deposit_asset = &input.global.channel.deposit_asset; + + // if there is no way to get the deposit_asset, then fail with UnknownVariable + // since we can't calculate the price in USD + let deposit_asset = input.deposit_asset().ok_or(Error::UnknownVariable)?; let divisor = DEPOSIT_ASSETS_MAP - .get(deposit_asset) + .get(&deposit_asset) .ok_or(Error::TypeError)?; let amount_in_usd = amount.div(divisor).to_f64().ok_or(Error::TypeError)?; let amount_as_number = Number::from_f64(amount_in_usd).ok_or(Error::TypeError)?; @@ -961,6 +974,48 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result Ok(value) } +/// Stops (i.e. it short-circuits) evaluating `Rule`s when `Output.show` becomes `false` +pub fn eval_multiple( + rules: &[Rule], + input: &Input, + output: &mut Output, +) -> Vec, (Error, Rule)>> { + let mut results = vec![]; + + for rule in rules { + results.push(rule.eval(input, output).map_err(|err| (err, rule.clone()))); + + if !output.show { + break; + } + } + + results +} + +pub fn eval_with_callback( + rules: &[Rule], + input: &Input, + output: &mut Output, + on_type_error: Option, +) { + for result in eval_multiple(rules, input, output) { + match (result, on_type_error.as_ref()) { + (Ok(_), _) => {} + (Err((Error::UnknownVariable, _)), _) => {} + (Err((Error::TypeError, rule)), Some(on_type_error)) => { + on_type_error(Error::TypeError, rule) + } + // skip any other case, including Error::TypeError if there is no passed function + _ => {} + } + + if !output.show { + return; + } + } +} + enum MathOperator { Division, Multiplication, diff --git a/primitives/src/targeting/eval_test.rs b/primitives/src/targeting/eval_test.rs index 1aee9b18b..5f47dfa2a 100644 --- a/primitives/src/targeting/eval_test.rs +++ b/primitives/src/targeting/eval_test.rs @@ -1,22 +1,19 @@ use super::*; use crate::{ - supermarket::Status, - targeting::{AdView, Global, Input}, - util::tests::prep_db::{DUMMY_CHANNEL, IDS}, + targeting::input, + util::tests::prep_db::{DUMMY_CHANNEL, DUMMY_IPFS, IDS}, AdUnit, BalancesMap, }; use chrono::Utc; -fn get_default_input() -> Input { +fn get_default_input() -> input::Source { let ad_unit = AdUnit { - ipfs: "Hash".to_string(), + ipfs: DUMMY_IPFS[0].clone(), ad_type: "legacy_300x250".to_string(), media_url: "media_url".to_string(), media_mime: "media_mime".to_string(), target_url: "target_url".to_string(), - targeting: vec![], min_targeting_score: None, - tags: vec![], owner: IDS["creator"], created: Utc::now(), title: None, @@ -26,13 +23,13 @@ fn get_default_input() -> Input { }; let input_balances = BalancesMap::default(); - Input { - ad_view: Some(AdView { + input::Source { + ad_view: Some(input::AdView { seconds_since_campaign_impression: 10, has_custom_preferences: false, navigator_language: "bg".to_string(), }), - global: Global { + global: input::Global { ad_slot_id: "ad_slot_id Value".to_string(), ad_slot_type: "ad_slot_type Value".to_string(), publisher_id: IDS["leader"], @@ -42,8 +39,7 @@ fn get_default_input() -> Input { user_agent_os: Some("os".to_string()), user_agent_browser_family: Some("family".to_string()), ad_unit: Some(ad_unit), - channel: DUMMY_CHANNEL.clone(), - status: Some(Status::Initializing), + channel: Some(DUMMY_CHANNEL.clone()), balances: Some(input_balances), }, ad_slot: None, @@ -52,7 +48,6 @@ fn get_default_input() -> Input { mod dsl_test { use super::*; - use crate::targeting::AdSlot; #[test] fn deserialize_intersects_with_get_rule() { @@ -86,12 +81,13 @@ mod dsl_test { /// ``` #[test] fn test_intersects_eval() { - let mut input = get_default_input(); - input.ad_slot = Some(AdSlot { + let mut source = get_default_input(); + source.ad_slot = Some(input::AdSlot { categories: vec!["Bitcoin".to_string(), "Ethereum".to_string()], hostname: Default::default(), alexa_rank: Some(0.0), }); + let input = input::Input::Source(Box::new(source)); let mut output = Output { show: true, @@ -113,12 +109,13 @@ mod dsl_test { result.expect("Should return Non-NULL result!") ); - let mut input = get_default_input(); - input.ad_slot = Some(AdSlot { + let mut source = get_default_input(); + source.ad_slot = Some(input::AdSlot { categories: vec!["Advertisement".to_string(), "Programming".to_string()], hostname: Default::default(), alexa_rank: Some(0.0), }); + let input = input::Input::Source(Box::new(source)); let result = rules.eval(&input, &mut output).expect("Should eval rules"); @@ -130,7 +127,7 @@ mod dsl_test { #[test] fn test_and_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -154,7 +151,8 @@ mod dsl_test { #[test] fn test_if_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); + let mut output = Output { show: true, boost: 1.0, @@ -174,7 +172,7 @@ mod dsl_test { #[test] fn test_bn_eval_from_actual_number_value_string_bignum_or_number() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -201,7 +199,7 @@ mod dsl_test { #[test] fn test_bn_eval_from_actual_incorrect_value() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -241,7 +239,7 @@ mod dsl_test { }), }); - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output::from(&channel); assert_eq!(Some(&BigNum::from(1_000)), output.price.get("IMPRESSION")); @@ -256,7 +254,7 @@ mod dsl_test { #[test] fn test_get_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 42.0, @@ -282,7 +280,7 @@ mod math_functions { #[test] fn test_div_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -327,7 +325,7 @@ mod math_functions { } #[test] fn test_mul_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -370,7 +368,7 @@ mod math_functions { } #[test] fn test_mod_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -413,7 +411,7 @@ mod math_functions { } #[test] fn test_add_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -456,7 +454,7 @@ mod math_functions { } #[test] fn test_sub_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -499,7 +497,7 @@ mod math_functions { } #[test] fn test_min_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -542,7 +540,7 @@ mod math_functions { } #[test] fn test_max_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -585,7 +583,7 @@ mod math_functions { } #[test] fn test_lt_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -628,7 +626,7 @@ mod math_functions { } #[test] fn test_lte_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -671,7 +669,7 @@ mod math_functions { } #[test] fn test_gt_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -714,7 +712,7 @@ mod math_functions { } #[test] fn test_gte_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -757,7 +755,7 @@ mod math_functions { } #[test] fn test_between_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -805,7 +803,7 @@ mod math_functions { } #[test] fn test_muldiv_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -829,7 +827,7 @@ mod control_flow_and_logic { #[test] fn test_if_not_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -848,7 +846,7 @@ mod control_flow_and_logic { } #[test] fn test_if_else() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -876,7 +874,7 @@ mod control_flow_and_logic { } #[test] fn test_or_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -899,7 +897,7 @@ mod control_flow_and_logic { } #[test] fn test_xor_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -922,7 +920,7 @@ mod control_flow_and_logic { } #[test] fn test_not_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -940,7 +938,7 @@ mod control_flow_and_logic { } #[test] fn test_eq_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -1021,7 +1019,7 @@ mod control_flow_and_logic { } #[test] fn test_neq_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -1079,7 +1077,7 @@ mod control_flow_and_logic { } #[test] fn test_only_show_if_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -1095,7 +1093,7 @@ mod control_flow_and_logic { } #[test] fn test_do_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -1115,7 +1113,7 @@ mod string_and_array { use super::*; #[test] fn test_in_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -1155,7 +1153,7 @@ mod string_and_array { } #[test] fn test_nin_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -1195,7 +1193,7 @@ mod string_and_array { } #[test] fn test_at_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -1218,7 +1216,7 @@ mod string_and_array { } #[test] fn test_split_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -1254,7 +1252,7 @@ mod string_and_array { } #[test] fn test_starts_with_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -1295,7 +1293,7 @@ mod string_and_array { } #[test] fn test_ends_with_eval() { - let input = get_default_input(); + let input = input::Input::Source(Box::new(get_default_input())); let mut output = Output { show: true, boost: 1.0, @@ -1332,7 +1330,7 @@ mod string_and_array { #[test] fn test_get_price_in_usd_eval() { - let mut input = get_default_input(); + let source = get_default_input(); let mut output = Output { show: true, @@ -1340,7 +1338,16 @@ mod string_and_array { price: Default::default(), }; for (key, value) in &*DEPOSIT_ASSETS_MAP { - input.global.channel.deposit_asset = key.to_string(); + let mut source = source.clone(); + source + .global + .channel + .as_mut() + .expect("Should have Channel set for this test!") + .deposit_asset = key.to_string(); + + let input = input::Input::Source(Box::new(source)); + let amount_crypto = BigNum::from(100).mul(value); let amount_usd = Some(Value::Number( Number::from_f64(100.0).expect("should create a float"), diff --git a/primitives/src/util/tests/prep_db.rs b/primitives/src/util/tests/prep_db.rs index cd3773464..e647681f7 100644 --- a/primitives/src/util/tests/prep_db.rs +++ b/primitives/src/util/tests/prep_db.rs @@ -1,7 +1,7 @@ use crate::{ channel::{Pricing, PricingBounds}, BigNum, Channel, ChannelId, ChannelSpec, EventSubmission, SpecValidators, ValidatorDesc, - ValidatorId, + ValidatorId, IPFS, }; use chrono::{TimeZone, Utc}; use fake::faker::{Faker, Number}; @@ -73,8 +73,6 @@ lazy_static! { max_per_impression: 10.into(), min_per_impression: 1.into(), targeting_rules: vec![], - targeting: vec![], - min_targeting_score: None, event_submission: Some(EventSubmission { allow: vec![] }), // July 29, 2019 7:00:00 AM created: Utc.timestamp(1_564_383_600, 0), @@ -83,9 +81,18 @@ lazy_static! { withdraw_period_start: Utc.timestamp_millis(4_073_414_400_000), ad_units: vec![], pricing_bounds: Some(PricingBounds {impression: None, click: Some(Pricing { max: 0.into(), min: 0.into()})}), - price_multiplication_rules: Default::default(), - price_dynamic_adjustment: false, }, } }; + + // CID V0 + pub static ref DUMMY_IPFS: [IPFS; 5] = [ + IPFS::try_from("QmcUVX7fvoLMM93uN2bD3wGTH8MXSxeL8hojYfL2Lhp7mR").expect("Valid IPFS V0"), + IPFS::try_from("Qmasg8FrbuSQpjFu3kRnZF9beg8rEBFrqgi1uXDRwCbX5f").expect("Valid IPFS V0"), + IPFS::try_from("QmQnu8zrHsuVvnTJsEgDHYA8c1MmRL7YLiMD8uzDUJKcNq").expect("Valid IPFS V0"), + IPFS::try_from("QmYYBULc9QDEaDr8HAXvVWHDmFfL2GvyumYRr1g4ERBC96").expect("Valid IPFS V0"), + // V1 of the V0 ipfs: `QmcUVX7fvoLMM93uN2bD3wGTH8MXSxeL8hojYfL2Lhp7mR` + IPFS::try_from("bafybeif2h3mynaf3ylgdbs6arf6mczqycargt5cqm3rmel3wpjarlswway").expect("Valid IPFS V1"), + ]; + } diff --git a/primitives/src/validator.rs b/primitives/src/validator.rs index 0618245e6..32ade355c 100644 --- a/primitives/src/validator.rs +++ b/primitives/src/validator.rs @@ -3,7 +3,7 @@ use hex::FromHex; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::fmt; -use crate::{BalancesMap, BigNum, DomainError, ToETHChecksum}; +use crate::{targeting::Value, BalancesMap, BigNum, DomainError, ToETHChecksum}; use std::convert::TryFrom; #[derive(Debug)] @@ -114,6 +114,7 @@ impl TryFrom<&str> for ValidatorId { impl TryFrom<&String> for ValidatorId { type Error = DomainError; + fn try_from(value: &String) -> Result { ValidatorId::try_from(value.as_str()) } @@ -125,7 +126,19 @@ impl fmt::Display for ValidatorId { } } -#[derive(Serialize, Deserialize, Debug, Clone)] +impl TryFrom for ValidatorId { + type Error = DomainError; + + fn try_from(value: Value) -> Result { + let string = value.try_string().map_err(|err| { + DomainError::InvalidArgument(format!("Value is not a string: {}", err)) + })?; + + Self::try_from(&string) + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] #[serde(rename_all = "camelCase")] pub struct ValidatorDesc { pub id: ValidatorId, diff --git a/sentry/Cargo.toml b/sentry/Cargo.toml index 870163b29..3b51fd072 100644 --- a/sentry/Cargo.toml +++ b/sentry/Cargo.toml @@ -12,7 +12,7 @@ async-std = "1.4.0" primitives = { path = "../primitives", features = ["postgres"] } adapter = { version = "0.1", path = "../adapter" } chrono = { version = "0.4", features = ["serde"] } -hex = "0.3.2" +hex = "0.4" # CLI clap = "2.33.0" # Server diff --git a/sentry/src/analytics_recorder.rs b/sentry/src/analytics_recorder.rs index fa57552a5..0e6469e31 100644 --- a/sentry/src/analytics_recorder.rs +++ b/sentry/src/analytics_recorder.rs @@ -34,10 +34,18 @@ pub async fn record( referrer, } => { let divisor = BigNum::from(10u64.pow(18)); - let pay_amount = get_payout(&channel, event, &session) - .div_floor(&divisor) - .to_f64() - .expect("should always have a payout"); + + let pay_amount = match get_payout(&logger, &channel, event, &session) { + Ok(Some((_, payout))) => payout.div_floor(&divisor) + .to_f64() + .expect("Should always have a payout in f64 after division"), + // This should never happen, as the conditions we are checking for in the .filter are the same as getPayout's + Ok(None) => return, + Err(err) => { + error!(&logger, "Getting the payout failed: {}", &err; "module" => "analytics-recorder", "err" => ?err); + return + }, + }; if let Some(ad_unit) = ad_unit { db.zincr( diff --git a/sentry/src/db/channel.rs b/sentry/src/db/channel.rs index 504020767..ab983c610 100644 --- a/sentry/src/db/channel.rs +++ b/sentry/src/db/channel.rs @@ -168,6 +168,8 @@ mod list_channels { Ok(ChannelListResponse { total_pages, + total: total_pages, + page: skip / limit as u64, channels, }) } diff --git a/sentry/src/event_aggregator.rs b/sentry/src/event_aggregator.rs index 3a218f202..72d0ca3ea 100644 --- a/sentry/src/event_aggregator.rs +++ b/sentry/src/event_aggregator.rs @@ -144,7 +144,16 @@ impl EventAggregator { })?; events.iter().for_each(|ev| { - event_reducer::reduce(&record.channel, &mut record.aggregate, ev, &session) + match event_reducer::reduce( + &app.logger, + &record.channel, + &mut record.aggregate, + ev, + &session, + ) { + Ok(_) => {} + Err(err) => error!(&app.logger, "Event Reducer failed"; "error" => ?err ), + } }); // only time we don't have session is during diff --git a/sentry/src/event_reducer.rs b/sentry/src/event_reducer.rs index ccefb1dd1..09782f3e8 100644 --- a/sentry/src/event_reducer.rs +++ b/sentry/src/event_reducer.rs @@ -1,28 +1,38 @@ -use crate::payout::get_payout; -use crate::Session; -use primitives::sentry::{AggregateEvents, Event, EventAggregate}; -use primitives::{BigNum, Channel, ValidatorId}; +use crate::{payout::get_payout, Session}; +use primitives::{ + sentry::{AggregateEvents, Event, EventAggregate}, + BigNum, Channel, ValidatorId, +}; +use slog::Logger; pub(crate) fn reduce( + logger: &Logger, channel: &Channel, initial_aggr: &mut EventAggregate, ev: &Event, session: &Session, -) { +) -> Result<(), Box> { + let event_type = ev.to_string(); match ev { Event::Impression { publisher, .. } => { - let impression = initial_aggr.events.get("IMPRESSION"); - let payout = get_payout(&channel, &ev, session); - let merge = merge_impression_ev(impression, &publisher, &payout); - - initial_aggr.events.insert("IMPRESSION".to_owned(), merge); + let impression = initial_aggr.events.get(&event_type); + let payout = get_payout(logger, &channel, &ev, session)?; + let merge = merge_payable_event( + impression, + payout.unwrap_or_else(|| (*publisher, Default::default())), + ); + + initial_aggr.events.insert(event_type, merge); } Event::Click { publisher, .. } => { - let clicks = initial_aggr.events.get("CLICK"); - let payout = get_payout(&channel, &ev, session); - let merge = merge_impression_ev(clicks, &publisher, &payout); - - initial_aggr.events.insert("CLICK".to_owned(), merge); + let clicks = initial_aggr.events.get(&event_type); + let payout = get_payout(logger, &channel, &ev, session)?; + let merge = merge_payable_event( + clicks, + payout.unwrap_or_else(|| (*publisher, Default::default())), + ); + + initial_aggr.events.insert(event_type, merge); } Event::Close => { let close_event = AggregateEvents { @@ -31,45 +41,51 @@ pub(crate) fn reduce( .into_iter() .collect(), }; - initial_aggr.events.insert("CLOSE".to_owned(), close_event); + initial_aggr.events.insert(event_type, close_event); } _ => {} }; + + Ok(()) } -fn merge_impression_ev( - impression: Option<&AggregateEvents>, - earner: &ValidatorId, - payout: &BigNum, +/// payable_event is either an IMPRESSION or a CLICK +fn merge_payable_event( + payable_event: Option<&AggregateEvents>, + payout: (ValidatorId, BigNum), ) -> AggregateEvents { - let mut impression = impression.map(Clone::clone).unwrap_or_default(); + let mut payable_event = payable_event.cloned().unwrap_or_default(); - let event_count = impression + let event_count = payable_event .event_counts .get_or_insert_with(Default::default) - .entry(*earner) + .entry(payout.0) .or_insert_with(|| 0.into()); *event_count += &1.into(); - let event_payouts = impression + let event_payouts = payable_event .event_payouts - .entry(*earner) + .entry(payout.0) .or_insert_with(|| 0.into()); - *event_payouts += payout; + *event_payouts += &payout.1; - impression + payable_event } #[cfg(test)] mod test { use super::*; use chrono::Utc; - use primitives::util::tests::prep_db::{DUMMY_CHANNEL, IDS}; + use primitives::util::tests::{ + discard_logger, + prep_db::{DUMMY_CHANNEL, IDS}, + }; use primitives::BigNum; #[test] fn test_reduce() { + let logger = discard_logger(); let mut channel: Channel = DUMMY_CHANNEL.clone(); channel.deposit_amount = 100.into(); // make immutable again @@ -95,8 +111,9 @@ mod test { os: None, }; - for _ in 0..101 { - reduce(&channel, &mut event_aggr, &event, &session); + for i in 0..101 { + reduce(&logger, &channel, &mut event_aggr, &event, &session) + .expect(&format!("Should be able to reduce event #{}", i)); } assert_eq!(event_aggr.channel_id, channel.id); diff --git a/sentry/src/payout.rs b/sentry/src/payout.rs index 6d59e414c..c1a742670 100644 --- a/sentry/src/payout.rs +++ b/sentry/src/payout.rs @@ -1,161 +1,140 @@ use crate::Session; -use primitives::channel::PriceMultiplicationRules; -use primitives::sentry::Event; -use primitives::ValidatorId; -use primitives::{BigNum, Channel}; +use chrono::Utc; +use primitives::{ + sentry::Event, + targeting::{eval_with_callback, get_pricing_bounds, input, Error, Output}, + BigNum, Channel, ValidatorId, +}; +use slog::{error, Logger}; +use std::{ + cmp::{max, min}, + convert::TryFrom, +}; + +type Result = std::result::Result, Error>; + +pub fn get_payout(logger: &Logger, channel: &Channel, event: &Event, session: &Session) -> Result { + let event_type = event.to_string(); -pub fn get_payout(channel: &Channel, event: &Event, session: &Session) -> BigNum { match event { - Event::Impression { publisher, .. } | Event::Click { publisher, .. } => { - let (min, max) = price_bounds(&channel, &event); - - if !channel.spec.price_multiplication_rules.is_empty() { - payout( - &channel.spec.price_multiplication_rules, - &event, - &session, - max, - min, - &publisher, - ) - } else { - min - } - } - _ => Default::default(), - } -} - -fn payout( - rules: &[PriceMultiplicationRules], - event: &Event, - session: &Session, - max_price: BigNum, - min_price: BigNum, - publisher: &ValidatorId, -) -> BigNum { - let fixed_amount_rule = rules.iter().find_map(|rule| { - match (match_rule(rule, &event, &session, &publisher), &rule.amount) { - (true, Some(amount)) => Some(amount.clone()), - _ => None, + Event::Impression { + publisher, + ad_unit, + ad_slot, + .. } - }); - - let price_by_rules = match fixed_amount_rule { - Some(amount) => amount, - None => { - let exponent: f64 = 10.0; - // @TODO: Know-issue - `multiplier` and `value` can overflow, should return Error instead - let multiplier: f64 = rules.iter().filter_map(|rule| rule.multiplier).product(); - let value: u64 = (multiplier * exponent.powi(18)) as u64; - let result = min_price * BigNum::from(value); - - result / BigNum::from(10u64.pow(18)) - } - }; - - max_price.min(price_by_rules) -} - -fn match_rule( - rule: &PriceMultiplicationRules, - ev_type: &Event, - session: &Session, - uid: &ValidatorId, -) -> bool { - let ev_type = match &rule.ev_type { - Some(event_types) => event_types.contains(&ev_type.to_string()), - _ => true, - }; - - let publisher = match &rule.publisher { - Some(publishers) => publishers.contains(&uid), - _ => true, - }; - - let os_type = match (&rule.os_type, &session.os) { - (Some(oses), Some(os)) => oses.contains(&os), - (Some(_), None) => false, - _ => true, - }; - - let country = match (&rule.country, &session.country) { - (Some(countries), Some(country)) => countries.contains(&country), - (Some(_), None) => false, - _ => true, - }; + | Event::Click { + publisher, + ad_unit, + ad_slot, + .. + } => { + let targeting_rules = if !channel.targeting_rules.is_empty() { + channel.targeting_rules.clone() + } else { + channel.spec.targeting_rules.clone() + }; - ev_type && publisher && os_type && country -} + let pricing = get_pricing_bounds(&channel, &event_type); -fn price_bounds(channel: &Channel, event: &Event) -> (BigNum, BigNum) { - let pricing_bounds = channel.spec.pricing_bounds.as_ref(); - match (event, pricing_bounds) { - (Event::Impression { .. }, Some(pricing_bounds)) => { - match pricing_bounds.impression.as_ref() { - Some(pricing) => (pricing.min.clone(), pricing.max.clone()), - _ => ( - channel.spec.min_per_impression.clone(), - channel.spec.max_per_impression.clone(), - ), + if targeting_rules.is_empty() { + Ok(Some((*publisher, pricing.min))) + } else { + let ad_unit = ad_unit.as_ref().and_then(|ipfs| { + channel + .spec + .ad_units + .iter() + .find(|u| &u.ipfs.to_string() == ipfs) + }); + + let source = input::Source { + ad_view: None, + global: input::Global { + // TODO: Check this one! + ad_slot_id: ad_slot.clone().unwrap_or_default(), + // TODO: Check this one! + ad_slot_type: ad_unit.map(|u| u.ad_type.clone()).unwrap_or_default(), + publisher_id: *publisher, + country: session.country.clone(), + event_type: event_type.clone(), + // **seconds** means calling `timestamp()` + seconds_since_epoch: u64::try_from(Utc::now().timestamp()).expect( + "The timestamp (i64) should not overflow or underflow the u64!", + ), + user_agent_os: session.os.clone(), + user_agent_browser_family: None, + // TODO: Check this one! + ad_unit: ad_unit.cloned(), + channel: Some(channel.clone()), + balances: None, + }, + // TODO: Check this one as well! + ad_slot: None, + }; + let input = input::Input::Source(Box::new(source)); + + let mut output = Output { + show: true, + boost: 1.0, + price: vec![(event_type.clone(), pricing.min.clone())] + .into_iter() + .collect(), + }; + + let on_type_error = |error, rule| error!(logger, "Rule evaluation error for {:?}", channel.id; "error" => ?error, "rule" => ?rule); + + eval_with_callback(&targeting_rules, &input, &mut output, Some(on_type_error)); + + if output.show { + let price = match output.price.get(&event_type) { + Some(output_price) => { + max(pricing.min, min(pricing.max, output_price.clone())) + } + None => max(pricing.min, pricing.max), + }; + + Ok(Some((*publisher, price))) + } else { + Ok(None) + } } } - (Event::Impression { .. }, None) => ( - channel.spec.min_per_impression.clone(), - channel.spec.max_per_impression.clone(), - ), - (Event::Click { .. }, Some(pricing_bounds)) => match pricing_bounds.click.as_ref() { - Some(pricing) => (pricing.min.clone(), pricing.max.clone()), - _ => (Default::default(), Default::default()), - }, - _ => (Default::default(), Default::default()), + _ => Ok(None), } } #[cfg(test)] -mod tests { +mod test { use super::*; use primitives::channel::{Pricing, PricingBounds}; - use primitives::util::tests::prep_db::{DUMMY_CHANNEL, IDS}; + use primitives::util::tests::{ + discard_logger, + prep_db::{DUMMY_CHANNEL, IDS}, + }; #[test] - fn test_plain_events() { - let mut channel: Channel = DUMMY_CHANNEL.clone(); + fn get_event_payouts_pricing_bounds_impression_event() { + let logger = discard_logger(); + + let mut channel = DUMMY_CHANNEL.clone(); + channel.deposit_amount = 100.into(); + channel.spec.min_per_impression = 8.into(); + channel.spec.max_per_impression = 64.into(); channel.spec.pricing_bounds = Some(PricingBounds { + impression: None, click: Some(Pricing { - min: BigNum::from(23), - max: BigNum::from(100), + min: 23.into(), + max: 100.into(), }), - impression: None, }); - let cases: Vec<(Event, BigNum, String)> = vec![ - ( - Event::Impression { - publisher: IDS["publisher"], - ad_slot: None, - ad_unit: None, - referrer: None, - }, - BigNum::from(1), - "pricingBounds: impression event".to_string(), - ), - ( - Event::Click { - publisher: IDS["publisher"], - ad_slot: None, - ad_unit: None, - referrer: None, - }, - BigNum::from(23), - "pricingBounds: click event".to_string(), - ), - ( - Event::Close {}, - BigNum::from(0), - "pricingBounds: close event".to_string(), - ), - ]; + let event = Event::Impression { + publisher: IDS["leader"], + ad_unit: None, + ad_slot: None, + referrer: None, + }; let session = Session { ip: None, @@ -164,274 +143,73 @@ mod tests { os: None, }; - cases.iter().for_each(|case| { - let (event, expected_result, message) = case; - let payout = get_payout(&channel, &event, &session); - assert!(&payout == expected_result, message.clone()); - }) - } - - #[test] - fn test_fixed_amount_price_rule_event() { - let mut channel: Channel = DUMMY_CHANNEL.clone(); - channel.spec.pricing_bounds = Some(PricingBounds { - click: Some(Pricing { - min: BigNum::from(23), - max: BigNum::from(100), - }), - impression: None, - }); - channel.spec.price_multiplication_rules = vec![PriceMultiplicationRules { - multiplier: None, - amount: Some(BigNum::from(10)), - os_type: None, - ev_type: Some(vec!["CLICK".to_string()]), - publisher: None, - country: Some(vec!["us".to_string()]), - }]; - - let cases: Vec<(Event, BigNum, String)> = vec![ - ( - Event::Impression { - publisher: IDS["publisher"], - ad_slot: None, - ad_unit: None, - referrer: None, - }, - BigNum::from(1), - "fixedAmount: impression".to_string(), - ), - ( - Event::Click { - publisher: IDS["publisher"], - ad_slot: None, - ad_unit: None, - referrer: None, - }, - BigNum::from(10), - "fixedAmount (country, publisher): click".to_string(), - ), - ]; - - let session = Session { - ip: None, - country: Some("us".to_string()), - referrer_header: None, - os: None, - }; + let payout = get_payout(&logger, &channel, &event, &session).expect("Should be OK"); - cases.iter().for_each(|(event, expected_result, message)| { - println!("payout {}", expected_result.to_string()); - let payout = get_payout(&channel, &event, &session); - println!("payout {}", payout.to_string()); - assert!(&payout == expected_result, message.clone()); - }) + let expected_option = Some((IDS["leader"], 8.into())); + assert_eq!(expected_option, payout, "pricingBounds: impression event"); } #[test] - fn test_fixed_amount_exceed_rule_event() { - let mut channel: Channel = DUMMY_CHANNEL.clone(); + fn get_event_payouts_pricing_bounds_click_event() { + let logger = discard_logger(); + let mut channel = DUMMY_CHANNEL.clone(); + channel.deposit_amount = 100.into(); + channel.spec.min_per_impression = 8.into(); + channel.spec.max_per_impression = 64.into(); channel.spec.pricing_bounds = Some(PricingBounds { - click: Some(Pricing { - min: BigNum::from(23), - max: BigNum::from(100), - }), impression: None, - }); - channel.spec.price_multiplication_rules = vec![PriceMultiplicationRules { - multiplier: None, - amount: Some(BigNum::from(1000)), - os_type: None, - ev_type: None, - publisher: None, - country: None, - }]; - - let cases: Vec<(Event, BigNum, String)> = vec![ - ( - Event::Impression { - publisher: IDS["publisher"], - ad_slot: None, - ad_unit: None, - referrer: None, - }, - BigNum::from(10), - "fixedAmount (all): price should not exceed maxPerImpressionPrice".to_string(), - ), - ( - Event::Click { - publisher: IDS["publisher"], - ad_slot: None, - ad_unit: None, - referrer: None, - }, - BigNum::from(100), - "fixedAmount (all): price should not exceed event pricingBound max".to_string(), - ), - ]; - - let session = Session { - ip: None, - country: Some("us".to_string()), - referrer_header: None, - os: None, - }; - - cases.iter().for_each(|case| { - let (event, expected_result, message) = case; - let payout = get_payout(&channel, &event, &session); - assert!(&payout == expected_result, message.clone()); - }) - } - - #[test] - fn test_pick_first_fixed_amount_rule_event() { - let mut channel: Channel = DUMMY_CHANNEL.clone(); - channel.spec.pricing_bounds = Some(PricingBounds { click: Some(Pricing { - min: BigNum::from(23), - max: BigNum::from(100), + min: 23.into(), + max: 100.into(), }), - impression: None, }); - channel.spec.price_multiplication_rules = vec![ - PriceMultiplicationRules { - multiplier: None, - amount: Some(BigNum::from(10)), - os_type: None, - ev_type: Some(vec!["CLICK".to_string()]), - publisher: None, - country: Some(vec!["us".to_string()]), - }, - PriceMultiplicationRules { - multiplier: None, - amount: Some(BigNum::from(12)), - os_type: None, - ev_type: Some(vec!["CLICK".to_string()]), - publisher: Some(vec![IDS["publisher"]]), - country: Some(vec!["us".to_string()]), - }, - ]; - - let session = Session { - ip: None, - country: Some("us".to_string()), - referrer_header: None, - os: None, - }; let event = Event::Click { - publisher: IDS["publisher"], - ad_slot: None, + publisher: IDS["leader"], ad_unit: None, + ad_slot: None, referrer: None, }; - let payout = get_payout(&channel, &event, &session); - assert!( - payout == BigNum::from(10), - "fixedAmount (country, pulisher): should choose first fixedAmount rule" - ); - } - - #[test] - fn test_pick_fixed_amount_rule_over_multiplier_event() { - let mut channel: Channel = DUMMY_CHANNEL.clone(); - channel.spec.pricing_bounds = Some(PricingBounds { - click: Some(Pricing { - min: BigNum::from(23), - max: BigNum::from(100), - }), - impression: None, - }); - channel.spec.price_multiplication_rules = vec![ - PriceMultiplicationRules { - multiplier: Some(1.2), - amount: None, - os_type: Some(vec!["android".to_string()]), - ev_type: Some(vec!["CLICK".to_string()]), - publisher: Some(vec![IDS["publisher"]]), - country: Some(vec!["us".to_string()]), - }, - PriceMultiplicationRules { - multiplier: None, - amount: Some(BigNum::from(12)), - os_type: None, - ev_type: Some(vec!["CLICK".to_string()]), - publisher: Some(vec![IDS["publisher"]]), - country: Some(vec!["us".to_string()]), - }, - ]; - let session = Session { ip: None, - country: Some("us".to_string()), + country: None, referrer_header: None, os: None, }; - let event = Event::Click { - publisher: IDS["publisher"], - ad_slot: None, - ad_unit: None, - referrer: None, - }; + let payout = get_payout(&logger, &channel, &event, &session).expect("Should be OK"); - let payout = get_payout(&channel, &event, &session); - assert!( - payout == BigNum::from(12), - "fixedAmount (country, osType, publisher): choose fixedAmount rule over multiplier if present" - ); + let expected_option = Some((IDS["leader"], 23.into())); + assert_eq!(expected_option, payout, "pricingBounds: click event"); } #[test] - fn test_apply_all_mutliplier_rules() { - let mut channel: Channel = DUMMY_CHANNEL.clone(); - + fn get_event_payouts_pricing_bounds_close_event() { + let logger = discard_logger(); + let mut channel = DUMMY_CHANNEL.clone(); + channel.deposit_amount = 100.into(); + channel.spec.min_per_impression = 8.into(); + channel.spec.max_per_impression = 64.into(); channel.spec.pricing_bounds = Some(PricingBounds { + impression: None, click: Some(Pricing { - min: BigNum::from(100), - max: BigNum::from(1000), + min: 23.into(), + max: 100.into(), }), - impression: None, }); - channel.spec.price_multiplication_rules = vec![ - PriceMultiplicationRules { - multiplier: Some(1.2), - amount: None, - os_type: Some(vec!["android".to_string()]), - ev_type: Some(vec!["CLICK".to_string()]), - publisher: Some(vec![IDS["publisher"]]), - country: Some(vec!["us".to_string()]), - }, - PriceMultiplicationRules { - multiplier: Some(1.2), - amount: None, - os_type: None, - ev_type: None, - publisher: None, - country: None, - }, - ]; + + let event = Event::Close; let session = Session { ip: None, - country: Some("us".to_string()), + country: None, referrer_header: None, os: None, }; - let event = Event::Click { - publisher: IDS["publisher"].clone(), - ad_slot: None, - ad_unit: None, - referrer: None, - }; + let payout = get_payout(&logger, &channel, &event, &session).expect("Should be OK"); - let payout = get_payout(&channel, &event, &session); - assert!( - payout == BigNum::from(144), - "fixedAmount (country, osType, publisher): apply all multiplier rules" - ); + assert_eq!(None, payout, "pricingBounds: click event"); } } diff --git a/validator_worker/Cargo.toml b/validator_worker/Cargo.toml index 55eb88781..94e28d555 100644 --- a/validator_worker/Cargo.toml +++ b/validator_worker/Cargo.toml @@ -13,10 +13,10 @@ path = "src/lib.rs" primitives = { path = "../primitives" } adapter = { version = "0.1", path = "../adapter" } chrono = { version = "0.4", features = ["serde"] } -num = "0.2.0" -num-traits = "0.2.0" +num = "0.3" +num-traits = "0.2" # To/From Hex -hex = "0.3.2" +hex = "0.4" byteorder = "1.3" # Logging slog = { version = "^2.5.2" , features = ["max_level_trace"] }