From fd088144d1f2511fc6f3309b84125763dfe04a22 Mon Sep 17 00:00:00 2001 From: zajko Date: Wed, 9 Aug 2023 15:45:34 +0200 Subject: [PATCH] Adding swagger endpoints and open API endpoint documentation. The openapi schema should be available under http://localhost:/api-doc.json, the swagger ui should be available under http://localhost:/swagger-ui. Added mechanism to transform json schemas from schemars so we can use them i openapi. (#167) --- Cargo.lock | 820 ++++++++++++------ Cargo.toml | 2 +- sidecar/Cargo.toml | 10 +- sidecar/src/main.rs | 3 +- sidecar/src/rest_server.rs | 7 +- sidecar/src/rest_server/filters.rs | 112 ++- sidecar/src/rest_server/openapi.rs | 191 ++++ .../openapi/schema_transformation_visitor.rs | 204 +++++ sidecar/src/types/database.rs | 3 +- sidecar/src/types/sse_events.rs | 24 +- types/Cargo.toml | 4 +- types/src/block.rs | 81 +- types/src/deploy.rs | 28 +- types/src/digest.rs | 3 +- types/src/executable_deploy_item.rs | 4 +- types/src/lib.rs | 6 +- 16 files changed, 1193 insertions(+), 309 deletions(-) create mode 100644 sidecar/src/rest_server/openapi.rs create mode 100644 sidecar/src/rest_server/openapi/schema_transformation_visitor.rs diff --git a/Cargo.lock b/Cargo.lock index c5e16780..19339de6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" @@ -26,7 +35,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if", + "getrandom", "once_cell", + "serde", "version_check", ] @@ -56,9 +67,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56fc6cf8dc8c4158eed8649f9b8b0ea1518eb62b544fe9490d66fa0b349eafe9" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] name = "ansi-str" @@ -130,9 +141,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" [[package]] name = "arrayvec" @@ -171,20 +182,20 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", - "syn 2.0.22", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.27", ] [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", - "syn 2.0.22", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.27", ] [[package]] @@ -196,23 +207,27 @@ dependencies = [ "num-traits", ] -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base16" version = "0.2.1" @@ -252,6 +267,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + [[package]] name = "bitvec" version = "0.18.5" @@ -382,13 +403,16 @@ dependencies = [ "hex_fmt", "http", "hyper", + "indexmap 2.0.0", "itertools", + "jsonschema", "once_cell", "portpicker", "pretty_assertions", "rand 0.8.5", "regex", "reqwest", + "schemars", "sea-query", "serde", "serde_json", @@ -403,6 +427,8 @@ dependencies = [ "tower", "tracing", "tracing-subscriber", + "utoipa", + "utoipa-swagger-ui", "warp", "wheelbuf", ] @@ -411,6 +437,7 @@ dependencies = [ name = "casper-event-types" version = "0.1.0" dependencies = [ + "base16", "blake2", "casper-types", "hex-buffer-serde", @@ -421,6 +448,7 @@ dependencies = [ "serde", "serde_json", "thiserror", + "utoipa", ] [[package]] @@ -431,7 +459,7 @@ checksum = "0e40fa172ff619ae56b2d3c6feb3e941a07fc64c0c73b913621ab0b2808cad80" dependencies = [ "base16", "base64 0.13.1", - "bitflags", + "bitflags 1.3.2", "blake2", "derp", "ed25519-dalek", @@ -451,6 +479,7 @@ dependencies = [ "proptest-derive", "rand 0.8.5", "rand_pcg", + "schemars", "serde", "serde_bytes", "serde_json", @@ -474,9 +503,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.3.8" +version = "4.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9394150f5b4273a1763355bd1c2ec54cc5a2593f790587bcd6b2c947cfa9211" +checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" dependencies = [ "clap_builder", "clap_derive", @@ -485,27 +514,26 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.8" +version = "4.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a78fbdd3cc2914ddf37ba444114bc7765bbdcb55ec9cbe6fa054f0137400717" +checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" dependencies = [ "anstream", "anstyle", - "bitflags", "clap_lex", "strsim", ] [[package]] name = "clap_derive" -version = "4.3.2" +version = "4.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.63", - "quote 1.0.28", - "syn 2.0.22", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.27", ] [[package]] @@ -522,13 +550,13 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "colored" -version = "2.0.0" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" dependencies = [ - "atty", + "is-terminal", "lazy_static", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -549,9 +577,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -635,16 +663,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "ctor" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" -dependencies = [ - "quote 1.0.28", - "syn 1.0.109", -] - [[package]] name = "curve25519-dalek" version = "3.2.1" @@ -664,8 +682,8 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", + "proc-macro2 1.0.66", + "quote 1.0.32", "syn 1.0.109", ] @@ -703,12 +721,38 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "dotenvy" version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dyn-clone" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "304e6508efa593091e97a9abbc10f90aa7ca635b6d2784feff3c89d41dd12272" + [[package]] name = "ecdsa" version = "0.10.2" @@ -744,9 +788,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "elliptic-curve" @@ -776,9 +820,9 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" @@ -819,14 +863,21 @@ dependencies = [ ] [[package]] -name = "fastrand" -version = "1.9.0" +name = "fancy-regex" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" dependencies = [ - "instant", + "bit-set", + "regex", ] +[[package]] +name = "fastrand" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + [[package]] name = "ff" version = "0.8.0" @@ -890,6 +941,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fraction" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3027ae1df8d41b4bed2241c8fdad4acc1e7af60c8e17743534b545e77182d678" +dependencies = [ + "lazy_static", + "num", +] + [[package]] name = "funty" version = "1.1.0" @@ -961,9 +1022,9 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", - "syn 2.0.22", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.27", ] [[package]] @@ -1013,10 +1074,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + [[package]] name = "group" version = "0.8.0" @@ -1030,9 +1099,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" dependencies = [ "bytes", "fnv", @@ -1079,7 +1148,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" dependencies = [ "base64 0.13.1", - "bitflags", + "bitflags 1.3.2", "bytes", "headers-core", "http", @@ -1117,27 +1186,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "hex" @@ -1213,9 +1264,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.26" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes", "futures-channel", @@ -1266,6 +1317,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", + "serde", ] [[package]] @@ -1276,6 +1328,7 @@ checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" dependencies = [ "equivalent", "hashbrown 0.14.0", + "serde", ] [[package]] @@ -1293,29 +1346,37 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi", "libc", "windows-sys 0.48.0", ] [[package]] name = "ipnet" -version = "2.7.2" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" [[package]] name = "is-terminal" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", - "rustix 0.37.20", + "hermit-abi", + "rustix 0.38.4", "windows-sys 0.48.0", ] +[[package]] +name = "iso8601" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924e5d73ea28f59011fec52a0d12185d496a9b075d360657aed2a5707f701153" +dependencies = [ + "nom", +] + [[package]] name = "itertools" version = "0.10.5" @@ -1327,9 +1388,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "js-sys" @@ -1340,6 +1401,36 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonschema" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a071f4f7efc9a9118dfb627a0a94ef247986e1ab8606a4c806ae2b3aa3b6978" +dependencies = [ + "ahash 0.8.3", + "anyhow", + "base64 0.21.2", + "bytecount", + "clap", + "fancy-regex", + "fraction", + "getrandom", + "iso8601", + "itoa", + "memchr", + "num-cmp", + "once_cell", + "parking_lot 0.12.1", + "percent-encoding", + "regex", + "reqwest", + "serde", + "serde_json", + "time", + "url", + "uuid", +] + [[package]] name = "k256" version = "0.7.3" @@ -1389,9 +1480,9 @@ checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" [[package]] name = "lock_api" @@ -1515,9 +1606,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" dependencies = [ "num-bigint", "num-complex", @@ -1538,6 +1629,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-cmp" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63335b2e2c34fae2fb0aa2cecfd9f0832a1e24b3b32ecec612c3426d46dc8aaa" + [[package]] name = "num-complex" version = "0.4.3" @@ -1553,8 +1650,8 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", + "proc-macro2 1.0.66", + "quote 1.0.32", "syn 1.0.109", ] @@ -1593,9 +1690,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", "libm", @@ -1603,14 +1700,23 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi", "libc", ] +[[package]] +name = "object" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -1629,7 +1735,7 @@ version = "0.10.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "foreign-types", "libc", @@ -1644,9 +1750,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", - "syn 2.0.22", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.27", ] [[package]] @@ -1667,15 +1773,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "output_vt100" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" -dependencies = [ - "winapi", -] - [[package]] name = "overload" version = "0.1.1" @@ -1740,14 +1837,14 @@ dependencies = [ "libc", "redox_syscall 0.3.5", "smallvec", - "windows-targets 0.48.0", + "windows-targets 0.48.1", ] [[package]] name = "paste" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pem" @@ -1768,29 +1865,29 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", - "syn 2.0.22", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.27", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" [[package]] name = "pin-utils" @@ -1821,13 +1918,11 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "pretty_assertions" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" +checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" dependencies = [ - "ctor", "diff", - "output_vt100", "yansi", ] @@ -1838,8 +1933,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.63", - "quote 1.0.28", + "proc-macro2 1.0.66", + "quote 1.0.32", "syn 1.0.109", "version_check", ] @@ -1850,8 +1945,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", + "proc-macro2 1.0.66", + "quote 1.0.32", "version_check", ] @@ -1866,9 +1961,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] @@ -1879,11 +1974,11 @@ version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1de8dacb0873f77e6aefc6d71e044761fcc68060290f5b1089fcdf84626bb69" dependencies = [ - "bitflags", + "bitflags 1.3.2", "byteorder", "hex", "lazy_static", - "rustix 0.36.14", + "rustix 0.36.15", ] [[package]] @@ -1910,7 +2005,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" dependencies = [ "bit-set", - "bitflags", + "bitflags 1.3.2", "byteorder", "lazy_static", "num-traits", @@ -1957,11 +2052,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.66", ] [[package]] @@ -2060,7 +2155,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -2069,18 +2164,41 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall 0.2.16", + "thiserror", ] [[package]] name = "regex" -version = "1.8.4" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax 0.7.4", +] + +[[package]] +name = "regex-automata" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.2", + "regex-syntax 0.7.4", ] [[package]] @@ -2091,9 +2209,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "reqwest" @@ -2134,13 +2252,54 @@ dependencies = [ "winreg", ] +[[package]] +name = "rust-embed" +version = "6.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a36224c3276f8c4ebc8c20f158eca7ca4359c8db89991c4925132aaaf6702661" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "6.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49b94b81e5b2c284684141a2fb9e2a31be90638caf040bf9afbc5a0416afe1ac" +dependencies = [ + "proc-macro2 1.0.66", + "quote 1.0.32", + "rust-embed-utils", + "shellexpand", + "syn 2.0.27", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "7.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d38ff6bf570dc3bb7100fce9f7b60c33fa71d80e88da3f2580df4ff2bdded74" +dependencies = [ + "sha2 0.10.7", + "walkdir", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustix" -version = "0.36.14" +version = "0.36.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e4d67015953998ad0eb82887a0eb0129e18a7e2f3b7b0f6c422fddcd503d62" +checksum = "c37f1bd5ef1b5422177b7646cba67430579cfe2ace80f284fee876bca52ad941" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", @@ -2150,32 +2309,31 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.20" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" +checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" dependencies = [ - "bitflags", + "bitflags 2.3.3", "errno", - "io-lifetimes", "libc", - "linux-raw-sys 0.3.8", + "linux-raw-sys 0.4.3", "windows-sys 0.48.0", ] [[package]] name = "rustls-pemfile" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ "base64 0.21.2", ] [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "rusty-fork" @@ -2191,17 +2349,51 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "same-file" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "schemars" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b82485a532ef0af18878ad4281f73e58161cdba1db7918176e9294f0ca5498a5" +dependencies = [ + "dyn-clone", + "indexmap 1.9.3", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "791c2c848cff1abaeae34fef7e70da5f93171d9eea81ce0fe969a1df627a61a8" dependencies = [ - "windows-sys 0.42.0", + "proc-macro2 1.0.66", + "quote 1.0.32", + "serde_derive_internals", + "syn 1.0.109", ] [[package]] @@ -2212,9 +2404,9 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sea-query" @@ -2232,19 +2424,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34cdc022b4f606353fe5dc85b09713a04e433323b70163e81513b141c6ae6eb5" dependencies = [ "heck 0.3.3", - "proc-macro2 1.0.63", - "quote 1.0.28", + "proc-macro2 1.0.66", + "quote 1.0.32", "syn 1.0.109", "thiserror", ] [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -2253,9 +2445,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -2263,38 +2455,49 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.164" +version = "1.0.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "5d25439cd7397d044e2748a6fe2432b5e85db703d6d097bd014b3c0ad1ebff0b" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.9" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" +checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "b23f7ade6f110613c0d63858ddb8b94c1041f550eab58a16b371bdf2c9c80ab4" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", - "syn 2.0.22", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.27", +] + +[[package]] +name = "serde_derive_internals" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dbab34ca63057a1f15280bdf3c39f2b1eb1b54c17e98360e511637aef7418c6" +dependencies = [ + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 1.0.109", ] [[package]] name = "serde_json" -version = "1.0.99" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b" dependencies = [ "indexmap 2.0.0", "itoa", @@ -2358,6 +2561,15 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shellexpand" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4" +dependencies = [ + "dirs", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -2388,9 +2600,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "socket2" @@ -2440,7 +2652,7 @@ checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" dependencies = [ "ahash 0.7.6", "atoi", - "bitflags", + "bitflags 1.3.2", "byteorder", "bytes", "crc", @@ -2485,8 +2697,8 @@ dependencies = [ "either", "heck 0.4.1", "once_cell", - "proc-macro2 1.0.63", - "quote 1.0.28", + "proc-macro2 1.0.66", + "quote 1.0.32", "sha2 0.10.7", "sqlx-core", "sqlx-rt", @@ -2514,9 +2726,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stringprep" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +checksum = "db3737bde7edce97102e0e2b15365bf7a20bfdb5f60f4f9e8d7004258a51a8da" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -2544,8 +2756,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.63", - "quote 1.0.28", + "proc-macro2 1.0.66", + "quote 1.0.32", "rustversion", "syn 1.0.109", ] @@ -2573,19 +2785,19 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", + "proc-macro2 1.0.66", + "quote 1.0.32", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.22" +version = "2.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" +checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", + "proc-macro2 1.0.66", + "quote 1.0.32", "unicode-ident", ] @@ -2609,43 +2821,42 @@ checksum = "beca1b4eaceb4f2755df858b88d9b9315b7ccfd1ffd0d7a48a52602301f01a57" dependencies = [ "heck 0.4.1", "proc-macro-error", - "proc-macro2 1.0.63", - "quote 1.0.28", + "proc-macro2 1.0.66", + "quote 1.0.32", "syn 1.0.109", ] [[package]] name = "tempfile" -version = "3.6.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998" dependencies = [ - "autocfg", "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix 0.37.20", + "rustix 0.38.4", "windows-sys 0.48.0", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", - "syn 2.0.22", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.27", ] [[package]] @@ -2678,6 +2889,32 @@ dependencies = [ "tikv-jemalloc-sys", ] +[[package]] +name = "time" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" +dependencies = [ + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" + +[[package]] +name = "time-macros" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" +dependencies = [ + "time-core", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -2695,11 +2932,12 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.2" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", "libc", "mio", @@ -2718,9 +2956,9 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", - "syn 2.0.22", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.27", ] [[package]] @@ -2827,9 +3065,9 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", - "syn 2.0.22", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.27", ] [[package]] @@ -2933,9 +3171,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" @@ -2999,6 +3237,48 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "utoipa" +version = "3.4.3" +source = "git+https://github.com/juhaku/utoipa?rev=cea4c50112c6cc0883767a43ff611db367cd13b5#cea4c50112c6cc0883767a43ff611db367cd13b5" +dependencies = [ + "indexmap 2.0.0", + "serde", + "serde_json", + "utoipa-gen", +] + +[[package]] +name = "utoipa-gen" +version = "3.4.4" +source = "git+https://github.com/juhaku/utoipa?rev=cea4c50112c6cc0883767a43ff611db367cd13b5#cea4c50112c6cc0883767a43ff611db367cd13b5" +dependencies = [ + "proc-macro-error", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.27", +] + +[[package]] +name = "utoipa-swagger-ui" +version = "3.1.4" +source = "git+https://github.com/juhaku/utoipa?rev=cea4c50112c6cc0883767a43ff611db367cd13b5#cea4c50112c6cc0883767a43ff611db367cd13b5" +dependencies = [ + "mime_guess", + "regex", + "rust-embed", + "serde", + "serde_json", + "utoipa", + "zip", +] + +[[package]] +name = "uuid" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" + [[package]] name = "valuable" version = "0.1.0" @@ -3034,8 +3314,8 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", + "proc-macro2 1.0.66", + "quote 1.0.32", ] [[package]] @@ -3047,6 +3327,16 @@ dependencies = [ "libc", ] +[[package]] +name = "walkdir" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -3113,9 +3403,9 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.63", - "quote 1.0.28", - "syn 2.0.22", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.27", "wasm-bindgen-shared", ] @@ -3137,7 +3427,7 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ - "quote 1.0.28", + "quote 1.0.32", "wasm-bindgen-macro-support", ] @@ -3147,9 +3437,9 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", - "syn 2.0.22", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.27", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3206,25 +3496,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "winapi-util" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] [[package]] -name = "windows-sys" -version = "0.42.0" +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" @@ -3241,7 +3525,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.1", ] [[package]] @@ -3261,9 +3545,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ "windows_aarch64_gnullvm 0.48.0", "windows_aarch64_msvc 0.48.0", @@ -3394,7 +3678,19 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.63", - "quote 1.0.28", - "syn 2.0.22", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.27", +] + +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "byteorder", + "crc32fast", + "crossbeam-utils", + "flate2", ] diff --git a/Cargo.toml b/Cargo.toml index a176bcad..2c458a8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,4 +3,4 @@ members = [ "sidecar", "listener", "types" -] \ No newline at end of file +] diff --git a/sidecar/Cargo.toml b/sidecar/Cargo.toml index a68e13ce..c8b69c47 100644 --- a/sidecar/Cargo.toml +++ b/sidecar/Cargo.toml @@ -11,7 +11,7 @@ async-trait = "0.1.56" bytes = "1.2.0" casper-event-listener = { path = "../listener", version = "0.1.0" } casper-event-types = { path = "../types", version = "0.1.0" } -casper-types = { version = "2.0.0", features = ["std"] } +casper-types = { version = "2.0.0", features = ["std", "json-schema"] } clap = { version = "4.0.32", features = ["derive"] } derive-new = "0.5.9" eventsource-stream = "0.2.3" @@ -20,12 +20,15 @@ hex = "0.4.3" hex_fmt = "0.3.0" http = "0.2.1" hyper = "0.14.4" +indexmap = "2.0.0" itertools = "0.10.3" +jsonschema = "0.17.1" rand = "0.8.3" regex = "1.6.0" reqwest = "0.11.11" +schemars = "0.8.5" sea-query = "0.26.3" -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0", features = ["derive", "rc"] } serde_json = "1.0" sqlx = { version = "0.6", features = ["runtime-tokio-native-tls", "any", "sqlite"] } thiserror = "1" @@ -35,6 +38,9 @@ toml = "0.5.8" tower = { version = "0.4.13", features = ["buffer", "limit", "make", "timeout"] } tracing = "0.1" tracing-subscriber = "0.3" +#Utoipa reference should be updated and pointed to cargo once 3.4.4 is released +utoipa = { git = "https://github.com/juhaku/utoipa", rev = "cea4c50112c6cc0883767a43ff611db367cd13b5", features = ["rc_schema"]} +utoipa-swagger-ui = { git = "https://github.com/juhaku/utoipa", rev = "cea4c50112c6cc0883767a43ff611db367cd13b5"} warp = { version = "0.3.3", features = ["compression"] } wheelbuf = "0.2.0" diff --git a/sidecar/src/main.rs b/sidecar/src/main.rs index 1ae9b60d..74d825b5 100644 --- a/sidecar/src/main.rs +++ b/sidecar/src/main.rs @@ -8,7 +8,7 @@ mod integration_tests_version_switch; mod migration_manager; #[cfg(test)] mod performance_tests; -mod rest_server; +pub mod rest_server; mod sql; mod sqlite_database; #[cfg(test)] @@ -172,7 +172,6 @@ async fn run(config: Config) -> Result<(), Error> { Ok(()) } }); - // This channel allows SseData to be sent from multiple connected nodes to the single EventStreamServer. let (outbound_sse_data_sender, mut outbound_sse_data_receiver) = mpsc_channel(config.outbound_channel_size.unwrap_or(DEFAULT_CHANNEL_SIZE)); diff --git a/sidecar/src/rest_server.rs b/sidecar/src/rest_server.rs index b52ed600..385ca761 100644 --- a/sidecar/src/rest_server.rs +++ b/sidecar/src/rest_server.rs @@ -1,6 +1,7 @@ mod errors; -mod filters; +pub mod filters; mod handlers; +mod openapi; #[cfg(test)] mod tests; @@ -10,6 +11,7 @@ use std::time::Duration; use anyhow::Error; use hyper::Server; use tower::{buffer::Buffer, make::Shared, ServiceBuilder}; +use warp::Filter; use crate::{ sqlite_database::SqliteDatabase, types::config::RestServerConfig, utils::resolve_address, @@ -22,13 +24,12 @@ pub async fn run_server( sqlite_database: SqliteDatabase, ) -> Result<(), Error> { let api = filters::combined_filters(sqlite_database); - let address = format!("{}:{}", BIND_ALL_INTERFACES, config.port); let socket_address = resolve_address(&address)?; let listener = TcpListener::bind(socket_address)?; - let warp_service = warp::service(api); + let warp_service = warp::service(api.with(warp::cors().allow_any_origin())); let tower_service = ServiceBuilder::new() .concurrency_limit(config.max_concurrent_requests as usize) .rate_limit( diff --git a/sidecar/src/rest_server/filters.rs b/sidecar/src/rest_server/filters.rs index f644ee49..e10435e7 100644 --- a/sidecar/src/rest_server/filters.rs +++ b/sidecar/src/rest_server/filters.rs @@ -1,4 +1,4 @@ -use super::{errors::handle_rejection, handlers}; +use super::{errors::handle_rejection, handlers, openapi::build_open_api_filters}; use crate::{ types::database::DatabaseReader, utils::{root_filter, InvalidPath}, @@ -20,6 +20,7 @@ pub(super) fn combined_filters( .or(faults_by_public_key(db.clone())) .or(faults_by_era(db.clone())) .or(finality_signatures_by_block(db)) + .or(build_open_api_filters()) .recover(handle_rejection) } @@ -62,7 +63,14 @@ fn deploy_filters( /// Return: data about the latest block. /// Path URL: block /// Example: curl http://127.0.0.1:18888/block -fn latest_block( +#[utoipa::path( + get, + path = "/block", + responses( + (status = 200, description = "latest stored block", body = BlockAdded) + ) +)] +pub fn latest_block( db: Db, ) -> impl Filter + Clone { warp::path!("block") @@ -76,6 +84,16 @@ fn latest_block( /// Return: data about the block specified. /// Path URL: block/ /// Example: curl http://127.0.0.1:18888/block/c0292d8408e9d83d1aaceadfbeb25dc38cda36bcb91c3d403a0deb594dc3d63f +#[utoipa::path( + get, + path = "/block/{block_hash}", + params( + ("block_hash" = String, Path, description = "Base64 encoded block hash of requested block") + ), + responses( + (status = 200, description = "fetch latest stored block", body = BlockAdded) + ) +)] fn block_by_hash( db: Db, ) -> impl Filter + Clone { @@ -90,6 +108,16 @@ fn block_by_hash( /// Return: data about the block requested. /// Path URL: block/ /// Example: curl http://127.0.0.1:18888/block/630151 +#[utoipa::path( + get, + path = "/block/{height}", + params( + ("height" = u32, Path, description = "Height of the requested block") + ), + responses( + (status = 200, description = "fetch latest stored block", body = BlockAdded) + ) +)] fn block_by_height( db: Db, ) -> impl Filter + Clone { @@ -105,6 +133,16 @@ fn block_by_height( /// Return: data about the deploy specified. /// Path URL: deploy/ /// Example: curl http://127.0.0.1:18888/deploy/f01544d37354c5f9b2c4956826d32f8e44198f94fb6752e87f422fe3071ab58a +#[utoipa::path( + get, + path = "/deploy/{deploy_hash}", + params( + ("deploy_hash" = String, Path, description = "Base64 encoded deploy hash of requested deploy") + ), + responses( + (status = 200, description = "fetch aggregate data for deploy events", body = DeployAggregate) + ) +)] fn deploy_by_hash( db: Db, ) -> impl Filter + Clone { @@ -119,6 +157,16 @@ fn deploy_by_hash( /// Return: data about the accepted deploy. /// Path URL: deploy/accepted/ /// Example: curl http://127.0.0.1:18888/deploy/accepted/f01544d37354c5f9b2c4956826d32f8e44198f94fb6752e87f422fe3071ab58a +#[utoipa::path( + get, + path = "/deploy/accepted/{deploy_hash}", + params( + ("deploy_hash" = String, Path, description = "Base64 encoded deploy hash of requested deploy accepted") + ), + responses( + (status = 200, description = "fetch stored deploy", body = DeployAccepted) + ) +)] fn deploy_accepted_by_hash( db: Db, ) -> impl Filter + Clone { @@ -128,6 +176,16 @@ fn deploy_accepted_by_hash( .and_then(handlers::get_deploy_accepted_by_hash) } +#[utoipa::path( + get, + path = "/deploy/expired/{deploy_hash}", + params( + ("deploy_hash" = String, Path, description = "Base64 encoded deploy hash of requested deploy expired") + ), + responses( + (status = 200, description = "fetch stored deploy", body = DeployExpired) + ) +)] /// Return information about a deploy that expired given its deploy hash. /// Input: the database with data to be filtered. /// Return: data about the expired deploy. @@ -142,6 +200,16 @@ fn deploy_expired_by_hash( .and_then(handlers::get_deploy_expired_by_hash) } +#[utoipa::path( + get, + path = "/deploy/processed/{deploy_hash}", + params( + ("deploy_hash" = String, Path, description = "Base64 encoded deploy hash of requested deploy processed") + ), + responses( + (status = 200, description = "fetch stored deploy", body = DeployProcessed) + ) +)] /// Return information about a deploy that was processed given its deploy hash. /// Input: the database with data to be filtered. /// Return: data about the processed deploy. @@ -156,6 +224,16 @@ fn deploy_processed_by_hash( .and_then(handlers::get_deploy_processed_by_hash) } +#[utoipa::path( + get, + path = "/faults/{public_key}", + params( + ("public_key" = String, Path, description = "Base64 encoded validator's public key") + ), + responses( + (status = 200, description = "faults associated with a validator's public key", body = [Fault]) + ) +)] /// Return the faults associated with a validator's public key. /// Input: the database with data to be filtered. /// Return: faults caused by the validator specified. @@ -170,6 +248,16 @@ fn faults_by_public_key( .and_then(handlers::get_faults_by_public_key) } +#[utoipa::path( + get, + path = "/faults/{era}", + params( + ("era" = String, Path, description = "Era identifier") + ), + responses( + (status = 200, description = "faults associated with an era ", body = [Fault]) + ) +)] /// Return the faults associated with an era given a valid era identifier. /// Input: the database with data to be filtered. /// Return: fault information for a given era. @@ -184,6 +272,16 @@ fn faults_by_era( .and_then(handlers::get_faults_by_era) } +#[utoipa::path( + get, + path = "/signatures/{block_hash}", + params( + ("block_hash" = String, Path, description = "Base64 encoded block hash of requested block") + ), + responses( + (status = 200, description = "finality signatures in a block", body = [FinalitySignature]) + ) +)] /// Return the finality signatures in a block given its block hash. /// Input: the database with data to be filtered. /// Return: the finality signatures for the block specified. @@ -198,6 +296,16 @@ fn finality_signatures_by_block( .and_then(handlers::get_finality_signatures_by_block) } +#[utoipa::path( + get, + path = "/step/{era_id}", + params( + ("era_id" = String, Path, description = "Era id") + ), + responses( + (status = 200, description = "step event emitted at the end of an era", body = Step) + ) +)] /// Return the step event emitted at the end of an era, given a valid era identifier. /// Input: the database with data to be filtered. /// Return: the step event for a given era. diff --git a/sidecar/src/rest_server/openapi.rs b/sidecar/src/rest_server/openapi.rs new file mode 100644 index 00000000..b76f0ee7 --- /dev/null +++ b/sidecar/src/rest_server/openapi.rs @@ -0,0 +1,191 @@ +mod schema_transformation_visitor; +use crate::types::{ + database::DeployAggregate, + sse_events::{BlockAdded, DeployAccepted, DeployExpired, DeployProcessed, Fault, Step}, +}; +use casper_event_types::{ + block::json_compatibility::{ + JsonBlockBody, JsonBlockHeader, JsonEraEnd, JsonEraReport, JsonProof, Reward, + ValidatorWeight, + }, + deploy::{Approval, DeployHeader}, + BlockHash, Deploy, DeployHash, Digest, ExecutableDeployItem, FinalitySignature, JsonBlock, +}; +use casper_types::{ + ContractHash, ContractPackageHash, ContractVersion, ExecutionEffect, ExecutionResult, + RuntimeArgs, +}; +use http::Uri; +use schemars::{schema::SchemaObject, schema_for, visit::Visitor}; +use serde::{Deserialize, Serialize}; +use std::{collections::HashMap, sync::Arc}; +use utoipa::{ + openapi::{Components, Contact, RefOr, Schema}, + Modify, OpenApi, +}; +use utoipa_swagger_ui::Config; +use warp::{ + hyper::{Response, StatusCode}, + path::{FullPath, Tail}, + Filter, Rejection, Reply, +}; + +use self::schema_transformation_visitor::SchemaTransformationVisitor; + +#[derive(OpenApi)] +#[openapi( + modifiers(&AuthorsModification), + paths(crate::rest_server::filters::latest_block, + crate::rest_server::filters::block_by_hash, + crate::rest_server::filters::block_by_height, + crate::rest_server::filters::deploy_by_hash, + crate::rest_server::filters::deploy_accepted_by_hash, + crate::rest_server::filters::deploy_expired_by_hash, + crate::rest_server::filters::deploy_processed_by_hash, + crate::rest_server::filters::faults_by_public_key, + crate::rest_server::filters::faults_by_era, + crate::rest_server::filters::finality_signatures_by_block, + crate::rest_server::filters::step_by_era, + + + ), + components( + schemas(Step, FinalitySignature, Fault, DeployExpired, Deploy, DeployHeader, ExecutableDeployItem, Approval, DeployAggregate, DeployAccepted, DeployProcessed, BlockAdded, JsonBlock, BlockHash, JsonEraEnd, JsonEraReport, JsonBlockBody, JsonBlockHeader, JsonProof, Digest, DeployHash, ValidatorWeight, Reward) + ), + tags( + (name = "event-sidecar", description = "Event-sidecar rest API") + ) + )] +struct ApiDoc; + +struct AuthorsModification; + +impl Modify for AuthorsModification { + fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) { + let mut contact = Contact::new(); + contact.name = Some("Sidecar team".to_string()); + contact.url = Some("https://github.com/CasperLabs/event-sidecar".to_string()); + openapi.info.contact = Some(contact); + } +} + +fn extend_open_api_with_schemars_schemas( + components: &mut Components, + names_and_schemas: Vec<(String, schemars::schema::RootSchema)>, +) { + for (name, schema) in names_and_schemas { + let (execution_result, additional_components) = force_produce_utoipa_schemas(schema); + components.schemas.insert(name, execution_result); + for (key, value) in additional_components.into_iter() { + components.schemas.insert(key, value); + } + } +} + +pub fn build_open_api_filters( +) -> impl Filter + Clone { + let mut doc = ApiDoc::openapi(); + let mut components = doc.components.unwrap(); + extend_open_api_with_schemars_schemas( + &mut components, + vec![ + ("ExecutionResult".to_string(), schema_for!(ExecutionResult)), + ("RuntimeArgs".to_string(), schema_for!(RuntimeArgs)), + ("ContractHash".to_string(), schema_for!(ContractHash)), + ( + "ContractPackageHash".to_string(), + schema_for!(ContractPackageHash), + ), + ("ContractVersion".to_string(), schema_for!(ContractVersion)), + ("ExecutionEffect".to_string(), schema_for!(ExecutionEffect)), + ], + ); + doc.components = Some(components); + let api_doc = warp::path("api-doc.json") + .and(warp::get()) + .map(move || warp::reply::json(&doc)); + let config = Arc::new(Config::from("/api-doc.json")); + let swagger_ui = warp::path("swagger-ui") + .and(warp::get()) + .and(warp::path::full()) + .and(warp::path::tail()) + .and(warp::any().map(move || config.clone())) + .and_then(serve_swagger); + api_doc.or(swagger_ui) +} + +fn force_produce_utoipa_schemas( + mut root_schema: schemars::schema::RootSchema, +) -> (RefOr, HashMap>) { + let mut visitor = SchemaTransformationVisitor { + skip_additional_properties: true, + }; + visitor.visit_root_schema(&mut root_schema); + + let schema_wrapper = RefOr::from(rebuild_schema_object( + "RootSchema".to_string(), + root_schema.schema, + )); + let mut rebuilt_schema_objects = HashMap::new(); + for (key, value) in root_schema.definitions.into_iter() { + rebuilt_schema_objects.insert( + key.clone(), + RefOr::from(rebuild_schema_object(key, value.into_object())), + ); + } + (schema_wrapper, rebuilt_schema_objects) +} + +fn rebuild_schema_object( + key: String, + schemars_schema_obj: SchemaObject, +) -> utoipa::openapi::Schema { + let schema_str = serde_json::to_string(&schemars_schema_obj).unwrap(); + match serde_json::from_str::(&schema_str) { + Ok(x) => x, + Err(e) => { + panic!( + "Failed handling schema for type {}. Err: {}\n\n\n{}", + key, e, schema_str + ); + } + } +} + +async fn serve_swagger( + full_path: FullPath, + tail: Tail, + config: Arc>, +) -> Result, Rejection> { + if full_path.as_str() == "/swagger-ui" { + return Ok(Box::new(warp::redirect::found(Uri::from_static( + "/swagger-ui/", + )))); + } + + let path = tail.as_str(); + match utoipa_swagger_ui::serve(path, config) { + Ok(file) => { + if let Some(file) = file { + Ok(Box::new( + Response::builder() + .header("Content-Type", file.content_type) + .body(file.bytes), + )) + } else { + Ok(Box::new(StatusCode::NOT_FOUND)) + } + } + Err(error) => Ok(Box::new( + Response::builder() + .status(StatusCode::INTERNAL_SERVER_ERROR) + .body(error.to_string()), + )), + } +} + +#[derive(Deserialize, Serialize)] +struct ApiError { + code: u16, + message: String, +} diff --git a/sidecar/src/rest_server/openapi/schema_transformation_visitor.rs b/sidecar/src/rest_server/openapi/schema_transformation_visitor.rs new file mode 100644 index 00000000..756e04c5 --- /dev/null +++ b/sidecar/src/rest_server/openapi/schema_transformation_visitor.rs @@ -0,0 +1,204 @@ +use schemars::{ + schema::{InstanceType, SchemaObject, SubschemaValidation}, + visit::{visit_schema_object, Visitor}, +}; +use serde_json::json; + +/// Implementation of schemars Visitor trait. It's purpose is to transform schema that comes from schemars so it can be deserialized as utoipas entity schema. +/// Utoipa uses OpenApi style schemas, which isn't 100% compatible with the more general json schema. +/// The main transformations are: +/// * adding `"type": "value"` to object schemas that have not `type` field. Object schemas without `type` field are legal in json schema, but utoipa doesn't work with that (whenever an object schema doesn't specify `type` it uses the generic `value`) +/// * changing references from "#/definitions" to "#/components/schemas" +/// * replacing `"type": "nullable"` with `"type": "object"` and property `"nullable": true` -> again, utoipa doesn't support `"type": "null"` +/// * replacing validators with array types, like `"type": ["object","string"]` with "anyOf" +/// * replacing bool validators with schema object ones +pub struct SchemaTransformationVisitor { + /// When set to `true`, a schema's `additionalProperties` property will not be changed from a boolean. + pub skip_additional_properties: bool, +} + +impl Visitor for SchemaTransformationVisitor { + fn visit_schema(&mut self, schema: &mut schemars::schema::Schema) { + if let schemars::schema::Schema::Bool(b) = *schema { + let mut object_schema: SchemaObject = schemars::schema::Schema::Bool(b).into_object(); + // The following is a hack for utoipa - utoipa doesn't accept schemas that don't have any "type" field. + // For a generic schema that doesn't put restraints on the type of the field utoipa uses a special "type": "value" which is, + // AFAIK, non-standard + object_schema + .extensions + .insert("type".to_string(), json!("value")); + *schema = object_schema.into() + } + schemars::visit::visit_schema(self, schema); + } + + fn visit_schema_object(&mut self, schema: &mut SchemaObject) { + if let Some(r) = &schema.reference { + // Schemars produces RootSchemas with "\"$ref\": \"#/definitions/(...)\"". Utoipas open api + // endpoint schema expects reference definitions as "\"$ref\": \"#/components/schemas/(...)\"" + let utoipa_reference = r.replace("#/definitions", "#/components/schemas"); + schema.reference = Some(utoipa_reference); + } + //The following code does two things: + // * utoipa doesn't support "type": "null" -> we need to get rid of that + // * utoipa doesn't support "type": [] -> we need to destructure it to a "one_of" requirement + let instance_type = schema.instance_type.clone(); + if schema.instance_type.is_some() { + let instance_or_object = instance_type.unwrap(); + match instance_or_object { + schemars::schema::SingleOrVec::Single(_) if schema.has_type(InstanceType::Null) => { + force_schema_into_opean_api_nullable(schema); + } + schemars::schema::SingleOrVec::Single(_) => { + //type here is not null, we don't need to do anything to it + } + schemars::schema::SingleOrVec::Vec(types) => { + //OpenApi schemas don't support multiple types definitions, we need to change it to a collection of "anyOf" + let mut new_schema = SchemaObject::default(); + let mut subschema_validation = SubschemaValidation::default(); + let mut vals: Vec = vec![]; + for t in types.iter() { + let mut single_type_schema = schema.clone(); + if *t == InstanceType::Null { + force_schema_into_opean_api_nullable(&mut single_type_schema); + } else { + single_type_schema.instance_type = + Some(schemars::schema::SingleOrVec::Single(Box::new(*t))) + } + vals.push(schemars::schema::Schema::Object(single_type_schema)); + } + subschema_validation.any_of = Some(vals); + *new_schema.subschemas() = subschema_validation; + *schema = new_schema; + } + } + } + + if self.skip_additional_properties { + // We need to make sure that the `additionalProperties` property doesn't get changed into a SchemaObject + if let Some(obj) = &mut schema.object { + if let Some(ap) = &obj.additional_properties { + if let schemars::schema::Schema::Bool(_) = ap.as_ref() { + let additional_properties = obj.additional_properties.take(); + visit_schema_object(self, schema); + schema.object().additional_properties = additional_properties; + return; + } + } + } + } + visit_schema_object(self, schema); + } +} + +fn force_schema_into_opean_api_nullable(schema: &mut SchemaObject) { + schema.instance_type = Some(schemars::schema::SingleOrVec::Single(Box::new( + InstanceType::Object, + ))); + // OpenApi schema doesn't support type "null" - it uses property `"nullable": true` instead + schema + .extensions + .insert("nullable".to_string(), json!(true)); + // The following two lines make sure that the resulting json schema will allow value `null` but not allow empty object `{}` + schema.object().additional_properties = Some(Box::new(schemars::schema::Schema::Bool(false))); + schema.object().properties.clear(); + schema.object().min_properties = Some(1); +} + +#[cfg(test)] +mod tests { + use super::SchemaTransformationVisitor; + use schemars::{schema::Schema, visit::Visitor}; + + #[test] + fn should_change_bool_requirement_into_schema_object() { + let json_schema = r#"{ + "$id": "https://example.com/person.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "firstName": true + }, + "additionalProperties": true + }"#; + let mut visitor = SchemaTransformationVisitor { + skip_additional_properties: false, + }; + let transformed = transform_schema(json_schema, &mut visitor); + let expected = "{\n \"$id\": \"https://example.com/person.schema.json\",\n \"type\": \"object\",\n \"properties\": {\n \"firstName\": {\n \"type\": \"value\"\n }\n },\n \"additionalProperties\": {\n \"type\": \"value\"\n },\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\"\n}".to_string(); + assert_eq!(transformed, expected); + } + + #[test] + fn should_not_change_additional_properties_if_flag_is_set() { + let json_schema = r#"{ + "$id": "https://example.com/person.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "additionalProperties": true + }"#; + let mut visitor = SchemaTransformationVisitor { + skip_additional_properties: true, + }; + let transformed = transform_schema(json_schema, &mut visitor); + let expected = "{\n \"$id\": \"https://example.com/person.schema.json\",\n \"type\": \"object\",\n \"additionalProperties\": true,\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\"\n}".to_string(); + assert_eq!(transformed, expected); + } + + #[test] + fn should_change_multiple_types_in_object_to_any_of() { + let json_schema = r#"{ + "$id": "https://example.com/person.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": ["string", "number", "object"], + "properties": { + "x": {"type": "string"} + }, + "required": ["x"], + "additionalProperties": true + }"#; + let mut visitor = SchemaTransformationVisitor { + skip_additional_properties: true, + }; + let transformed = transform_schema(json_schema, &mut visitor); + let expected = "{\n \"anyOf\": [\n {\n \"$id\": \"https://example.com/person.schema.json\",\n \"type\": \"string\",\n \"required\": [\n \"x\"\n ],\n \"properties\": {\n \"x\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": true,\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\"\n },\n {\n \"$id\": \"https://example.com/person.schema.json\",\n \"type\": \"number\",\n \"required\": [\n \"x\"\n ],\n \"properties\": {\n \"x\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": true,\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\"\n },\n {\n \"$id\": \"https://example.com/person.schema.json\",\n \"type\": \"object\",\n \"required\": [\n \"x\"\n ],\n \"properties\": {\n \"x\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": true,\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\"\n }\n ]\n}".to_string(); + assert_eq!(transformed, expected); + } + + #[test] + fn should_change_null_type_into_nullable() { + let json_schema = r#"{ + "$id": "https://example.com/person.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "null" + }"#; + let mut visitor = SchemaTransformationVisitor { + skip_additional_properties: true, + }; + let transformed = transform_schema(json_schema, &mut visitor); + let expected = "{\n \"$id\": \"https://example.com/person.schema.json\",\n \"type\": \"object\",\n \"minProperties\": 1,\n \"additionalProperties\": false,\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"nullable\": true\n}".to_string(); + assert_eq!(transformed, expected); + } + + #[test] + fn should_change_null_type_into_nullable_if_multiple_types() { + let json_schema = r#"{ + "$id": "https://example.com/person.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": ["null", "object"], + "properties": {"x": true} + }"#; + let mut visitor = SchemaTransformationVisitor { + skip_additional_properties: true, + }; + let transformed = transform_schema(json_schema, &mut visitor); + let expected = "{\n \"anyOf\": [\n {\n \"$id\": \"https://example.com/person.schema.json\",\n \"type\": \"object\",\n \"minProperties\": 1,\n \"additionalProperties\": false,\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"nullable\": true\n },\n {\n \"$id\": \"https://example.com/person.schema.json\",\n \"type\": \"object\",\n \"properties\": {\n \"x\": {\n \"type\": \"value\"\n }\n },\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\"\n }\n ]\n}".to_string(); + assert_eq!(transformed, expected); + } + + fn transform_schema(schema: &str, visitor: &mut SchemaTransformationVisitor) -> String { + let mut obj = serde_json::from_str::(schema).unwrap(); + visitor.visit_schema(&mut obj); + serde_json::to_string_pretty(&obj).unwrap() + } +} diff --git a/sidecar/src/types/database.rs b/sidecar/src/types/database.rs index 5fb5d8ec..d5bd97bc 100644 --- a/sidecar/src/types/database.rs +++ b/sidecar/src/types/database.rs @@ -9,6 +9,7 @@ use async_trait::async_trait; use casper_event_types::FinalitySignature as FinSig; use serde::{Deserialize, Serialize}; use std::sync::Arc; +use utoipa::ToSchema; /// Describes a reference for the writing interface of an 'Event Store' database. /// There is a one-to-one relationship between each method and each event that can be received from the node. @@ -265,7 +266,7 @@ pub enum DatabaseReadError { Unhandled(anyhow::Error), } -#[derive(Debug, Deserialize, Serialize, Clone)] +#[derive(Debug, Deserialize, Serialize, Clone, ToSchema)] pub struct DeployAggregate { pub(crate) deploy_hash: String, pub(crate) deploy_accepted: Option, diff --git a/sidecar/src/types/sse_events.rs b/sidecar/src/types/sse_events.rs index b9b0532a..5e63a769 100644 --- a/sidecar/src/types/sse_events.rs +++ b/sidecar/src/types/sse_events.rs @@ -15,6 +15,7 @@ use std::{ fmt::{Display, Formatter}, sync::Arc, }; +use utoipa::ToSchema; /// The version of this node's API server. This event will always be the first sent to a new /// client, and will have no associated event ID provided. @@ -22,7 +23,7 @@ use std::{ pub struct ApiVersion(ProtocolVersion); /// The given block has been added to the linear chain and stored locally. -#[derive(Clone, Debug, Serialize, Deserialize, new)] +#[derive(Clone, Debug, Serialize, Deserialize, new, ToSchema)] pub struct BlockAdded { block_hash: BlockHash, block: Box, @@ -50,9 +51,8 @@ impl BlockAdded { } /// The given deploy has been newly-accepted by this node. -#[derive(Clone, Debug, Serialize, Deserialize, new)] +#[derive(Clone, Debug, Serialize, Deserialize, new, ToSchema)] pub struct DeployAccepted { - #[serde(flatten)] // It's an Arc to not create multiple copies of the same deploy for multiple subscribers. deploy: Arc, } @@ -76,11 +76,14 @@ impl DeployAccepted { } /// The given deploy has been executed, committed and forms part of the given block. -#[derive(Clone, Debug, Serialize, Deserialize, new)] +#[derive(Clone, Debug, Serialize, Deserialize, new, ToSchema)] pub struct DeployProcessed { deploy_hash: Box, + #[schema(value_type = String)] account: Box, + #[schema(value_type = String)] timestamp: Timestamp, + #[schema(value_type = String)] ttl: TimeDiff, dependencies: Vec, block_hash: Box, @@ -108,7 +111,7 @@ impl DeployProcessed { } /// The given deploy has expired. -#[derive(Clone, Debug, Serialize, Deserialize, new)] +#[derive(Clone, Debug, Serialize, Deserialize, new, ToSchema)] pub struct DeployExpired { deploy_hash: DeployHash, } @@ -127,10 +130,14 @@ impl DeployExpired { } /// Generic representation of validator's fault in an era. -#[derive(Clone, Debug, Serialize, Deserialize, new)] +#[derive(Clone, Debug, Serialize, Deserialize, new, ToSchema)] pub struct Fault { + #[schema(value_type = u64)] pub era_id: EraId, + /// "Hex-encoded cryptographic public key, including the algorithm tag prefix." + #[schema(value_type = String)] pub public_key: PublicKey, + #[schema(value_type = String)] pub timestamp: Timestamp, } @@ -179,9 +186,12 @@ impl FinalitySignature { } /// The execution effects produced by a `StepRequest`. -#[derive(Clone, Debug, Serialize, Deserialize, new)] +#[derive(Clone, Debug, Serialize, Deserialize, new, ToSchema)] pub struct Step { + #[schema(value_type = u64)] pub era_id: EraId, + #[schema(value_type = ExecutionEffect)] + //This technically is not amorphic, but this field is potentially > 30MB of size. By not parsing it we make the process of intaking these messages much quicker and less memory consuming execution_effect: Box, } diff --git a/types/Cargo.toml b/types/Cargo.toml index d5cb770c..037a1136 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +base16 = "0.2.1" blake2 = { version = "0.9.0", optional = true } casper-types = { version = "2.0.0", features = ["std"] } hex-buffer-serde = "0.3.0" @@ -12,8 +13,9 @@ lazy_static = "1.4.0" prometheus = { version = "0.13.3", features = ["process"]} rand = { version = "0.8.5", optional = true } serde = { version = "1", features = ["derive", "rc"] } -serde_json = {version = "1.0", features = ["raw_value"]} +serde_json = { version = "1.0", default-features = false, features = ["alloc", "raw_value"] } thiserror = "1.0.39" +utoipa = { git = "https://github.com/juhaku/utoipa", rev = "cea4c50112c6cc0883767a43ff611db367cd13b5", features = ["rc_schema"]} [features] sse-data-testing = ["blake2", "casper-types/testing", "rand"] diff --git a/types/src/block.rs b/types/src/block.rs index 3dd70287..54edd0a8 100644 --- a/types/src/block.rs +++ b/types/src/block.rs @@ -5,21 +5,32 @@ use std::{ iter, }; -#[cfg(feature = "sse-data-testing")] -use rand::Rng; -use serde::{Deserialize, Serialize}; - use casper_types::{ bytesrepr, EraId, ProtocolVersion, PublicKey, SecretKey, Signature, Timestamp, U512, }; #[cfg(feature = "sse-data-testing")] use casper_types::{bytesrepr::ToBytes, crypto, testing::TestRng}; +#[cfg(feature = "sse-data-testing")] +use rand::Rng; +use serde::{Deserialize, Serialize}; +use utoipa::ToSchema; use crate::{DeployHash, Digest}; /// A cryptographic hash identifying a [`Block`]. #[derive( - Copy, Clone, Default, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, + Copy, + Clone, + Default, + Ord, + PartialOrd, + Eq, + PartialEq, + Hash, + Serialize, + Deserialize, + Debug, + ToSchema, )] #[serde(deny_unknown_fields)] pub struct BlockHash(Digest); @@ -57,10 +68,13 @@ impl ToBytes for BlockHash { } } -#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug)] +#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, ToSchema)] pub struct EraReport { + #[schema(value_type = Vec)] equivocators: Vec, + #[schema(value_type = Map)] rewards: BTreeMap, + #[schema(value_type = Vec)] inactive_validators: Vec, } @@ -106,7 +120,7 @@ impl ToBytes for EraEnd { } /// The header portion of a [`Block`]. -#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug)] +#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, ToSchema)] pub struct BlockHeader { parent_hash: BlockHash, state_root_hash: Digest, @@ -114,9 +128,13 @@ pub struct BlockHeader { random_bit: bool, accumulated_seed: Digest, era_end: Option, + #[schema(value_type = String)] timestamp: Timestamp, + #[schema(value_type = u64)] era_id: EraId, height: u64, + /// The protocol version. + #[schema(value_type = String)] protocol_version: ProtocolVersion, } @@ -151,8 +169,10 @@ impl ToBytes for BlockHeader { } } -#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug)] +#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, ToSchema)] pub struct BlockBody { + /// "Hex-encoded cryptographic public key, including the algorithm tag prefix." + #[schema(value_type = String)] proposer: PublicKey, deploy_hashes: Vec, transfer_hashes: Vec, @@ -275,11 +295,15 @@ impl Block { } } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, ToSchema)] pub struct FinalitySignature { block_hash: BlockHash, + #[schema(value_type = u64)] era_id: EraId, + #[schema(value_type = String)] signature: Signature, + /// "Hex-encoded cryptographic public key, including the algorithm tag prefix." + #[schema(value_type = String)] public_key: PublicKey, } @@ -326,27 +350,36 @@ impl FinalitySignature { pub mod json_compatibility { use super::*; use casper_types::PublicKey; + use utoipa::ToSchema; - #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, ToSchema)] #[serde(deny_unknown_fields)] - struct Reward { + pub struct Reward { + /// "Hex-encoded cryptographic public key, including the algorithm tag prefix." + #[schema(value_type = String)] validator: PublicKey, + #[schema(value_type = String)] amount: u64, } - #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, ToSchema)] #[serde(deny_unknown_fields)] - struct ValidatorWeight { + pub struct ValidatorWeight { + /// "Hex-encoded cryptographic public key, including the algorithm tag prefix." + #[schema(value_type = String)] validator: PublicKey, + #[schema(value_type = String)] weight: U512, } /// Equivocation and reward information to be included in the terminal block. - #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, ToSchema)] #[serde(deny_unknown_fields)] - struct JsonEraReport { + pub struct JsonEraReport { + #[schema(value_type = Vec)] equivocators: Vec, rewards: Vec, + #[schema(value_type = Vec)] inactive_validators: Vec, } @@ -381,7 +414,7 @@ pub mod json_compatibility { } } - #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, ToSchema)] #[serde(deny_unknown_fields)] pub struct JsonEraEnd { era_report: JsonEraReport, @@ -424,7 +457,7 @@ pub mod json_compatibility { } /// JSON representation of a block header. - #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, ToSchema)] #[serde(deny_unknown_fields)] pub struct JsonBlockHeader { /// The parent hash. @@ -440,12 +473,15 @@ pub mod json_compatibility { /// The era end. pub era_end: Option, /// The block timestamp. + #[schema(value_type = String)] pub timestamp: Timestamp, /// The block era id. + #[schema(value_type = u64)] pub era_id: EraId, /// The block height. pub height: u64, /// The protocol version. + #[schema(value_type = String)] pub protocol_version: ProtocolVersion, } @@ -484,9 +520,11 @@ pub mod json_compatibility { } /// A JSON-friendly representation of `Body` - #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, ToSchema)] #[serde(deny_unknown_fields)] pub struct JsonBlockBody { + /// "Hex-encoded cryptographic public key, including the algorithm tag prefix." + #[schema(value_type = String)] proposer: PublicKey, deploy_hashes: Vec, transfer_hashes: Vec, @@ -513,7 +551,7 @@ pub mod json_compatibility { } /// A JSON-friendly representation of `Block`. - #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, ToSchema)] #[serde(deny_unknown_fields)] pub struct JsonBlock { /// `BlockHash` @@ -584,10 +622,13 @@ pub mod json_compatibility { } /// A JSON-friendly representation of a proof, i.e. a block's finality signature. - #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] + #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, ToSchema)] #[serde(deny_unknown_fields)] pub struct JsonProof { + /// "Hex-encoded cryptographic public key, including the algorithm tag prefix." + #[schema(value_type = String)] public_key: PublicKey, + #[schema(value_type = String)] signature: Signature, } diff --git a/types/src/deploy.rs b/types/src/deploy.rs index 1a739d0e..148fbeb1 100644 --- a/types/src/deploy.rs +++ b/types/src/deploy.rs @@ -15,12 +15,24 @@ use casper_types::{ bytesrepr::{self}, runtime_args, PublicKey, RuntimeArgs, SecretKey, Signature, TimeDiff, Timestamp, U512, }; +use utoipa::ToSchema; use crate::{Digest, ExecutableDeployItem}; /// A cryptographic hash uniquely identifying a [`Deploy`]. #[derive( - Copy, Clone, Default, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, + Copy, + Clone, + Default, + Ord, + PartialOrd, + Eq, + PartialEq, + Hash, + Serialize, + Deserialize, + Debug, + ToSchema, )] #[serde(deny_unknown_fields)] pub struct DeployHash(Digest); @@ -55,11 +67,15 @@ impl ToBytes for DeployHash { } /// The header portion of a [`Deploy`]. -#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug)] +#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, ToSchema)] #[serde(deny_unknown_fields)] pub struct DeployHeader { + /// "Hex-encoded cryptographic public key, including the algorithm tag prefix." + #[schema(value_type = String)] account: PublicKey, + #[schema(value_type = String)] timestamp: Timestamp, + #[schema(value_type = String)] ttl: TimeDiff, gas_price: u64, body_hash: Digest, @@ -140,10 +156,13 @@ impl ToBytes for DeployHeader { } /// The signature of a deploy and the public key of the signer. -#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug)] +#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, ToSchema)] #[serde(deny_unknown_fields)] pub struct Approval { + /// "Hex-encoded cryptographic public key, including the algorithm tag prefix." + #[schema(value_type = String)] signer: PublicKey, + #[schema(value_type = String)] signature: Signature, } @@ -157,13 +176,14 @@ impl Approval { } /// A signed item sent to the network used to request execution of Wasm. -#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug)] +#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, ToSchema)] #[serde(deny_unknown_fields)] pub struct Deploy { hash: DeployHash, header: DeployHeader, payment: ExecutableDeployItem, session: ExecutableDeployItem, + #[schema(value_type = Vec)] approvals: BTreeSet, } diff --git a/types/src/digest.rs b/types/src/digest.rs index 947e05f9..c76675bd 100644 --- a/types/src/digest.rs +++ b/types/src/digest.rs @@ -16,9 +16,10 @@ use serde::{de::Error as SerdeError, Deserialize, Deserializer, Serialize, Seria #[cfg(feature = "sse-data-testing")] use casper_types::bytesrepr::{self, ToBytes}; use casper_types::{checksummed_hex, testing::TestRng}; +use utoipa::ToSchema; /// The output of the hash function. -#[derive(Copy, Clone, Default, Ord, PartialOrd, Eq, PartialEq, Hash)] +#[derive(Copy, Clone, Default, Ord, PartialOrd, Eq, PartialEq, Hash, ToSchema)] pub struct Digest([u8; Digest::LENGTH]); impl Digest { diff --git a/types/src/executable_deploy_item.rs b/types/src/executable_deploy_item.rs index a07752ec..dbc9eda1 100644 --- a/types/src/executable_deploy_item.rs +++ b/types/src/executable_deploy_item.rs @@ -12,6 +12,7 @@ use casper_types::{ system::auction::ARG_AMOUNT, CLValue, ContractHash, ContractPackageHash, ContractVersion, RuntimeArgs, U512, }; +use utoipa::ToSchema; #[cfg(feature = "sse-data-testing")] const TAG_LENGTH: usize = 1; @@ -31,13 +32,14 @@ const TRANSFER_TAG: u8 = 5; const MAX_PAYMENT_AMOUNT: u64 = 2_500_000_000; /// The payment or session code of a [`Deploy`]. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Debug)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Debug, ToSchema)] #[serde(deny_unknown_fields)] pub enum ExecutableDeployItem { /// Raw bytes of compiled Wasm code, which must include a `call` entry point, and the arguments /// to call at runtime. ModuleBytes { /// The compiled Wasm bytes. + #[schema(value_type = String)] module_bytes: Bytes, /// The arguments to be passed to the entry point at runtime. args: RuntimeArgs, diff --git a/types/src/lib.rs b/types/src/lib.rs index cc11e0a2..3a39d60f 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -1,7 +1,9 @@ #[macro_use] extern crate lazy_static; -mod block; -mod deploy; +#[cfg_attr(not(test), macro_use)] +extern crate alloc; +pub mod block; +pub mod deploy; mod digest; mod executable_deploy_item; mod filter;