From ad4fb7dbc5983f4c8dd128fb04e7863d673a243f Mon Sep 17 00:00:00 2001 From: Andreas Dzialocha Date: Thu, 27 Jan 2022 17:00:49 +0100 Subject: [PATCH] Add u64 support (#54) * Use u64 branch of p2panda-rs for now * Rewrite sqlx types to use strings instead of p2panda types * Correct hash size and replace BIGINT with VARCHAR * Update p2panda-rs API * Return seq_num and log_id as strings in JSON * Make return values consistent, also for queryEntries * Add entry to CHANGELOG.md * Typos * Revert p2panda-rs dependency to main branch Co-authored-by: Vincent Ahrend --- CHANGELOG.md | 17 +- Cargo.lock | 244 +++++++++++------- aquadoggo/Cargo.toml | 3 +- .../20201229215646_create-entries.sql | 10 +- .../migrations/20201230002752_create-logs.sql | 11 +- .../20211127170238_instance-logs.sql | 19 -- aquadoggo/src/db/models/entry.rs | 103 ++++++-- aquadoggo/src/db/models/log.rs | 53 ++-- aquadoggo/src/db/models/mod.rs | 2 +- aquadoggo/src/errors.rs | 10 +- aquadoggo/src/rpc/methods/entry_args.rs | 14 +- aquadoggo/src/rpc/methods/publish_entry.rs | 29 +-- aquadoggo/src/rpc/response.rs | 17 +- 13 files changed, 338 insertions(+), 194 deletions(-) delete mode 100644 aquadoggo/migrations/20211127170238_instance-logs.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index 960c92258..142df6697 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,20 +9,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- **Breaking change**: Replace schema logs with document logs, changing the behavior the `nextEntryArgs` and `publishEntry` RPC methods, invalidating and deleting all previously published entries [#44](https://github.com/p2panda/aquadoggo/pull/44) -- **Breaking change**: Rename `Message` to `Operation` everywhere [#48](https://github.com/p2panda/aquadoggo/pull/48) -- **Breaking change**: Make JSON RPC methods compatible with new document logs flow [#47](https://github.com/p2panda/aquadoggo/pull/47) +- Replace schema logs with document logs, changing the behavior the `nextEntryArgs` and `publishEntry` RPC methods, invalidating and deleting all previously published entries [#44](https://github.com/p2panda/aquadoggo/pull/44) +- Rename `Message` to `Operation` everywhere [#48](https://github.com/p2panda/aquadoggo/pull/48) +- Make JSON RPC methods compatible with new document logs flow [#47](https://github.com/p2panda/aquadoggo/pull/47) - Nicer looking `README.md` for crate [#42](https://github.com/p2panda/aquadoggo/42) +- Support u64 integers [#54](https://github.com/p2panda/aquadoggo/pull/54) ## [0.1.0] Released on 2021-10-25: :package: [`crate`](https://crates.io/crates/aquadoggo/0.1.0) and 2021-10-26: 🐳 [`docker`](https://hub.docker.com/layers/p2panda/aquadoggo/v0.1.0/images/sha256-be4ba99ce47517dc99e42feda70dd452356190b5f86fcffea44b1bce1d4d315e?context=explore) -### Changed - -- Use p2panda-rs 0.2.1 with fixed linter setting [#41](https://github.com/p2panda/aquadoggo/41) -- Use `tide` for HTTP server and `jsonrpc-v2` for JSON RPC [#29](https://github.com/p2panda/aquadoggo/29) - ### Added - `panda_queryEntries` RPC method [#23](https://github.com/p2panda/aquadoggo/pull/23) @@ -33,5 +29,10 @@ Released on 2021-10-25: :package: [`crate`](https://crates.io/crates/aquadoggo/0 - Server configuration via environment variables [#7](https://github.com/p2panda/aquadoggo/pull/7) - JSON RPC HTTP and WebSocket API server via [#5](https://github.com/p2panda/aquadoggo/pull/5) +### Changed + +- Use p2panda-rs 0.2.1 with fixed linter setting [#41](https://github.com/p2panda/aquadoggo/41) +- Use `tide` for HTTP server and `jsonrpc-v2` for JSON RPC [#29](https://github.com/p2panda/aquadoggo/29) + [Unreleased]: https://github.com/p2panda/aquadoggo/compare/v0.1.0...HEAD [0.1.0]: https://github.com/p2panda/aquadoggo/releases/tag/v0.1.0 diff --git a/Cargo.lock b/Cargo.lock index 6362ead57..cc6c1fc42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -165,6 +165,19 @@ dependencies = [ "structopt", ] +[[package]] +name = "aquamarine" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96e14cb2a51c8b45d26a4219981985c7350fc05eacb7b5b2939bceb2ffefdf3e" +dependencies = [ + "itertools 0.9.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "arrayref" version = "0.3.6" @@ -519,6 +532,12 @@ dependencies = [ "base64 0.13.0", ] +[[package]] +name = "base64ct" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6b4d9b1225d28d360ec6a231d65af1fd99a2a095154c8040689617290569c5c" + [[package]] name = "bincode" version = "1.3.3" @@ -648,7 +667,7 @@ dependencies = [ "console_error_panic_hook", "crossterm", "hexf-parse", - "itertools", + "itertools 0.10.3", "lexical-core", "regex", "regex-syntax", @@ -710,6 +729,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "ciborium" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" + +[[package]] +name = "ciborium-ll" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "cipher" version = "0.2.5" @@ -1039,6 +1085,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" dependencies = [ "const-oid", + "crypto-bigint", ] [[package]] @@ -1061,9 +1108,9 @@ dependencies = [ [[package]] name = "dirs" -version = "3.0.2" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" dependencies = [ "dirs-sys", ] @@ -1256,6 +1303,18 @@ dependencies = [ "subtle", ] +[[package]] +name = "flume" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24c3fd473b3a903a62609e413ed7538f99e10b665ecb502b5e481a95283f8ab4" +dependencies = [ + "futures-core", + "futures-sink", + "pin-project", + "spin 0.9.2", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1289,9 +1348,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" +checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" dependencies = [ "futures-core", "futures-sink", @@ -1299,15 +1358,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" +checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" [[package]] name = "futures-executor" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c" +checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" dependencies = [ "futures-core", "futures-task", @@ -1327,9 +1386,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" +checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" [[package]] name = "futures-lite" @@ -1348,12 +1407,10 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" +checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" dependencies = [ - "autocfg 1.0.1", - "proc-macro-hack", "proc-macro2", "quote", "syn", @@ -1361,23 +1418,22 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" +checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" [[package]] name = "futures-task" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" +checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" [[package]] name = "futures-util" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" +checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" dependencies = [ - "autocfg 1.0.1", "futures-channel", "futures-core", "futures-io", @@ -1387,8 +1443,6 @@ dependencies = [ "memchr", "pin-project-lite 0.2.7", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] @@ -1754,6 +1808,15 @@ dependencies = [ "ghost", ] +[[package]] +name = "itertools" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.10.3" @@ -1820,7 +1883,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ - "spin", + "spin 0.5.2", ] [[package]] @@ -1850,9 +1913,9 @@ checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" [[package]] name = "libsqlite3-sys" -version = "0.22.2" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290b64917f8b0cb885d9de0f9959fe1f775d7fa12f1da2db9001c1c8ab60f89d" +checksum = "d2cafc7c74096c336d9d27145f7ebd4f4b6f95ba16aa5a282387267e6925cb58" dependencies = [ "cc", "pkg-config", @@ -2024,17 +2087,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-bigint" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" -dependencies = [ - "autocfg 1.0.1", - "num-integer", - "num-traits", -] - [[package]] name = "num-bigint-dig" version = "0.7.0" @@ -2151,11 +2203,13 @@ dependencies = [ [[package]] name = "p2panda-rs" version = "0.2.1" -source = "git+https://github.com/p2panda/p2panda?branch=main#86170126bcca0363e02058072749e85aae5bf784" +source = "git+https://github.com/p2panda/p2panda?branch=main#566df75892c4f8d91918354996a6cb98984e9ad9" dependencies = [ + "aquamarine", "arrayvec 0.5.2", "bamboo-rs-core-ed25519-yasmf", "cddl", + "ciborium", "console_error_panic_hook", "ed25519", "ed25519-dalek", @@ -2167,10 +2221,9 @@ dependencies = [ "rand 0.7.3", "rust_crypto", "serde", - "serde_cbor", + "serde-wasm-bindgen", "serde_json", "serde_repr", - "sqlx", "thiserror", "tls_codec", "wasm-bindgen", @@ -2218,14 +2271,12 @@ dependencies = [ ] [[package]] -name = "pem" -version = "0.8.3" +name = "pem-rfc7468" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb" +checksum = "84e93a3b1cc0510b03020f33f21e62acdde3dcaef432edc95bea377fbd4c2cd4" dependencies = [ - "base64 0.13.0", - "once_cell", - "regex", + "base64ct", ] [[package]] @@ -2272,6 +2323,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "116bee8279d783c0cf370efa1a94632f2108e5ef0bb32df31f051647810a4e2c" +dependencies = [ + "der", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "pkcs8" version = "0.7.6" @@ -2279,7 +2341,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447" dependencies = [ "der", + "pem-rfc7468", + "pkcs1", "spki", + "zeroize", ] [[package]] @@ -2371,26 +2436,20 @@ version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" - [[package]] name = "proc-macro2" -version = "1.0.34" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.10" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" dependencies = [ "proc-macro2", ] @@ -2546,7 +2605,7 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", + "spin 0.5.2", "untrusted", "web-sys", "winapi", @@ -2560,9 +2619,9 @@ checksum = "56770675ebc04927ded3e60633437841581c285dc6236109ea25fbf3beb7b59e" [[package]] name = "rsa" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0aeddcca1082112a6eeb43bf25fd7820b066aaf6eaef776e19d0a1febe38fe" +checksum = "e05c2603e2823634ab331437001b411b9ed11660fbc4066f3908c84a9439260d" dependencies = [ "byteorder", "digest", @@ -2571,9 +2630,9 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "pem", + "pkcs1", + "pkcs8", "rand 0.8.4", - "simple_asn1", "subtle", "zeroize", ] @@ -2667,6 +2726,18 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5cefe81e058ce25d1acbd79160e110d2eb4b9459024d46818d7553e4be6ff7e" +dependencies = [ + "fnv", + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_bytes" version = "0.11.5" @@ -2823,18 +2894,6 @@ dependencies = [ "event-listener", ] -[[package]] -name = "simple_asn1" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb4ea60fb301dc81dfc113df680571045d375ab7345d171c5dc7d7e13107a80" -dependencies = [ - "chrono", - "num-bigint 0.4.3", - "num-traits", - "thiserror", -] - [[package]] name = "slab" version = "0.4.5" @@ -2884,6 +2943,15 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" +dependencies = [ + "lock_api", +] + [[package]] name = "spki" version = "0.4.1" @@ -2899,16 +2967,16 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" dependencies = [ - "itertools", + "itertools 0.10.3", "nom", "unicode_categories", ] [[package]] name = "sqlx" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7911b0031a0247af40095838002999c7a52fba29d9739e93326e71a5a1bc9d43" +checksum = "692749de69603d81e016212199d73a2e14ee20e2def7d7914919e8db5d4d48b9" dependencies = [ "sqlx-core", "sqlx-macros", @@ -2916,9 +2984,9 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aec89bfaca8f7737439bad16d52b07f1ccd0730520d3bf6ae9d069fe4b641fb1" +checksum = "518be6f6fff5ca76f985d434f9c37f3662af279642acf730388f271dff7b9016" dependencies = [ "ahash", "atoi", @@ -2934,8 +3002,10 @@ dependencies = [ "dirs", "either", "encoding_rs", + "flume", "futures-channel", "futures-core", + "futures-executor", "futures-intrusive", "futures-util", "generic-array", @@ -2943,13 +3013,13 @@ dependencies = [ "hex", "hmac 0.11.0", "indexmap", - "itoa 0.4.8", + "itoa 1.0.1", "libc", "libsqlite3-sys", "log", "md-5", "memchr", - "num-bigint 0.3.3", + "num-bigint", "once_cell", "parking_lot", "percent-encoding", @@ -2975,9 +3045,9 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "584866c833511b1a152e87a7ee20dee2739746f60c858b3c5209150bc4b466f5" +checksum = "38e45140529cf1f90a5e1c2e561500ca345821a1c513652c8f486bbf07407cc8" dependencies = [ "dotenv", "either", @@ -2994,9 +3064,9 @@ dependencies = [ [[package]] name = "sqlx-rt" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d1bd069de53442e7a320f525a6d4deb8bb0621ac7a55f7eccbc2b58b57f43d0" +checksum = "8061cbaa91ee75041514f67a09398c65a64efed72c90151ecd47593bad53da99" dependencies = [ "async-rustls", "async-std", @@ -3152,9 +3222,9 @@ checksum = "45f6ee7c7b87caf59549e9fe45d6a69c75c8019e79e212a835c5da0e92f0ba08" [[package]] name = "syn" -version = "1.0.82" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +checksum = "ecb2e6da8ee5eb9a61068762a32fa9619cc591ceb055b3687f4cd4051ec2e06b" dependencies = [ "proc-macro2", "quote", diff --git a/aquadoggo/Cargo.toml b/aquadoggo/Cargo.toml index ca434ebf0..49186ef6f 100644 --- a/aquadoggo/Cargo.toml +++ b/aquadoggo/Cargo.toml @@ -29,8 +29,7 @@ jsonrpc-v2 = { version = "0.10.1", features = [ ], default-features = false } log = "0.4.14" openssl-probe = "0.1.4" -# @TODO: Move this back to crate as soon as upcoming changes have been published -p2panda-rs = { git = "https://github.com/p2panda/p2panda", branch = "main", features = ["db-sqlx"] } +p2panda-rs = { git = "https://github.com/p2panda/p2panda", branch = "main" } rand = "0.8.4" serde = { version = "1.0.130", features = ["derive"] } serde_json = "1.0.67" diff --git a/aquadoggo/migrations/20201229215646_create-entries.sql b/aquadoggo/migrations/20201229215646_create-entries.sql index 958f2403e..741494fff 100644 --- a/aquadoggo/migrations/20201229215646_create-entries.sql +++ b/aquadoggo/migrations/20201229215646_create-entries.sql @@ -3,10 +3,12 @@ CREATE TABLE IF NOT EXISTS entries ( author VARCHAR(64) NOT NULL, entry_bytes TEXT NOT NULL, - entry_hash VARCHAR(132) NOT NULL UNIQUE, - log_id BIGINT NOT NULL, + entry_hash VARCHAR(68) NOT NULL UNIQUE, + -- Store u64 integer as 20 character string + log_id VARCHAR(20) NOT NULL, payload_bytes TEXT, - payload_hash VARCHAR(132) NOT NULL, - seq_num BIGINT NOT NULL, + payload_hash VARCHAR(68) NOT NULL, + -- Store u64 integer as 20 character string + seq_num VARCHAR(20) NOT NULL, PRIMARY KEY (author, log_id, seq_num) ); diff --git a/aquadoggo/migrations/20201230002752_create-logs.sql b/aquadoggo/migrations/20201230002752_create-logs.sql index faf39b330..d404a62b0 100644 --- a/aquadoggo/migrations/20201230002752_create-logs.sql +++ b/aquadoggo/migrations/20201230002752_create-logs.sql @@ -2,7 +2,12 @@ CREATE TABLE IF NOT EXISTS logs ( author VARCHAR(64) NOT NULL, - log_id BIGINT NOT NULL, - schema VARCHAR(132) NOT NULL, - PRIMARY KEY (author, schema, log_id) + document VARCHAR(68) NOT NULL, + -- Store u64 integer as 20 character string + log_id VARCHAR(20) NOT NULL, + schema VARCHAR(68) NOT NULL, + PRIMARY KEY (author, document, log_id) ); + +-- Create an index for querying by schema +CREATE INDEX idx_logs_schema ON logs (author, log_id, schema); diff --git a/aquadoggo/migrations/20211127170238_instance-logs.sql b/aquadoggo/migrations/20211127170238_instance-logs.sql deleted file mode 100644 index 914e2f926..000000000 --- a/aquadoggo/migrations/20211127170238_instance-logs.sql +++ /dev/null @@ -1,19 +0,0 @@ --- SPDX-License-Identifier: AGPL-3.0-or-later - --- The change from schema logs to document logs invalidates all entries so --- all logs and entries are deleted. The logs table is also dropped because its --- primary key changes. - -DROP TABLE logs; -DELETE FROM entries; - -CREATE TABLE logs ( - author VARCHAR(64) NOT NULL, - log_id BIGINT NOT NULL, - document VARCHAR(132) NOT NULL, - schema VARCHAR(132) NOT NULL, - PRIMARY KEY (author, document, log_id) -); - --- Create an index for querying by schema -CREATE INDEX idx_logs_schema ON logs (author, log_id, schema); diff --git a/aquadoggo/src/db/models/entry.rs b/aquadoggo/src/db/models/entry.rs index 668905019..fa556f1e1 100644 --- a/aquadoggo/src/db/models/entry.rs +++ b/aquadoggo/src/db/models/entry.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: AGPL-3.0-or-later +use std::convert::TryFrom; + use p2panda_rs::entry::{EntrySigned, LogId, SeqNum}; use p2panda_rs::hash::Hash; use p2panda_rs::identity::Author; @@ -11,6 +13,41 @@ use sqlx::{query, query_as, FromRow}; use crate::db::Pool; use crate::errors::Result; +/// Struct representing the actual SQL row of `Entry`. +/// +/// We store the u64 integer values of `log_id` and `seq_num` as strings since not all database +/// backend support large numbers. +#[derive(FromRow, Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct EntryRow { + /// Public key of the author. + pub author: String, + + /// Actual Bamboo entry data. + pub entry_bytes: String, + + /// Hash of Bamboo entry data. + pub entry_hash: String, + + /// Used log for this entry. + pub log_id: String, + + /// Payload of entry, can be deleted. + pub payload_bytes: Option, + + /// Hash of payload data. + pub payload_hash: String, + + /// Sequence number of this entry. + pub seq_num: String, +} + +impl AsRef for EntryRow { + fn as_ref(&self) -> &Self { + self + } +} + /// Entry of an append-only log based on Bamboo specification. It describes the actual data in the /// p2p network and is shared between nodes. /// @@ -22,7 +59,7 @@ use crate::errors::Result; /// payload can be deleted without affecting the data structures integrity. All other fields like /// `author`, `payload_hash` etc. can be retrieved from `entry_bytes` but are separately stored in /// the database for faster querying. -#[derive(FromRow, Debug, Serialize)] +#[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct Entry { /// Public key of the author. @@ -74,13 +111,13 @@ impl Entry { ($1, $2, $3, $4, $5, $6, $7) ", ) - .bind(author) - .bind(entry_bytes) - .bind(entry_hash) - .bind(log_id) - .bind(payload_bytes) - .bind(payload_hash) - .bind(seq_num) + .bind(author.as_str()) + .bind(entry_bytes.as_str()) + .bind(entry_hash.as_str()) + .bind(log_id.as_u64().to_string()) + .bind(payload_bytes.as_str()) + .bind(payload_hash.as_str()) + .bind(seq_num.as_u64().to_string()) .execute(pool) .await? .rows_affected(); @@ -90,7 +127,7 @@ impl Entry { /// Returns the latest Bamboo entry of an author's log. pub async fn latest(pool: &Pool, author: &Author, log_id: &LogId) -> Result> { - let latest_entry = query_as::<_, Entry>( + let row = query_as::<_, EntryRow>( " SELECT author, @@ -111,17 +148,25 @@ impl Entry { 1 ", ) - .bind(author) - .bind(log_id) + .bind(author.as_str()) + .bind(log_id.as_u64().to_string()) .fetch_optional(pool) .await?; - Ok(latest_entry) + // Convert internal `EntryRow` to `Entry` with correct types + let entry = row.map(|entry| Self::try_from(&entry).expect("Corrupt values found in entry")); + + Ok(entry) } /// Return vector of all entries of a given schema - pub async fn by_schema(pool: &Pool, schema: &Hash) -> Result> { - let entries = query_as::<_, Entry>( + // @TODO: This currently returns `EntryRow`, a better API would return `Entry` instead as it is + // properly typed and `EntryRow` is only meant as an intermediate struct to deal with + // databases. Here we still return `EntryRow` for the `queryEntries` RPC response (we want + // `seq_num` and `log_id` to be strings). This should be changed as soon as we move over using + // a GraphQL API. + pub async fn by_schema(pool: &Pool, schema: &Hash) -> Result> { + let entries = query_as::<_, EntryRow>( " SELECT entries.author, @@ -140,7 +185,7 @@ impl Entry { logs.schema = $1 ", ) - .bind(schema) + .bind(schema.as_str()) .fetch_all(pool) .await?; @@ -154,7 +199,7 @@ impl Entry { log_id: &LogId, seq_num: &SeqNum, ) -> Result> { - let entry = query_as::<_, Entry>( + let row = query_as::<_, EntryRow>( " SELECT author, @@ -172,16 +217,36 @@ impl Entry { AND seq_num = $3 ", ) - .bind(author) - .bind(log_id) - .bind(seq_num) + .bind(author.as_str()) + .bind(log_id.as_u64().to_string()) + .bind(seq_num.as_u64().to_string()) .fetch_optional(pool) .await?; + // Convert internal `EntryRow` to `Entry` with correct types + let entry = row.map(|entry| Self::try_from(&entry).expect("Corrupt values found in entry")); + Ok(entry) } } +/// Convert SQL row representation `EntryRow` to typed `Entry` one. +impl TryFrom<&EntryRow> for Entry { + type Error = crate::errors::Error; + + fn try_from(row: &EntryRow) -> std::result::Result { + Ok(Self { + author: Author::try_from(row.author.as_ref())?, + entry_bytes: row.entry_bytes.clone(), + entry_hash: row.entry_hash.parse()?, + log_id: row.log_id.parse()?, + payload_bytes: row.payload_bytes.clone(), + payload_hash: row.payload_hash.parse()?, + seq_num: row.seq_num.parse()?, + }) + } +} + #[cfg(test)] mod tests { use p2panda_rs::entry::LogId; diff --git a/aquadoggo/src/db/models/log.rs b/aquadoggo/src/db/models/log.rs index e19dc8f3e..70712ff09 100644 --- a/aquadoggo/src/db/models/log.rs +++ b/aquadoggo/src/db/models/log.rs @@ -3,7 +3,7 @@ use p2panda_rs::entry::LogId; use p2panda_rs::hash::Hash; use p2panda_rs::identity::Author; -use sqlx::{query, query_as, FromRow}; +use sqlx::{query, query_scalar, FromRow}; use crate::db::Pool; use crate::errors::Result; @@ -12,19 +12,22 @@ use crate::errors::Result; /// /// This serves as an indexing layer on top of the lower-level bamboo entries. The node updates /// this data according to what it sees in the newly incoming entries. +/// +/// We store the u64 integer values of `log_id` as a string here since not all database backends +/// support large numbers. #[derive(FromRow, Debug)] pub struct Log { /// Public key of the author. - author: Author, + author: String, /// Log id used for this document. - log_id: LogId, + log_id: String, /// Hash that identifies the document this log is for. - document: Hash, + document: String, /// Schema hash used by author. - schema: Hash, + schema: String, } impl Log { @@ -46,10 +49,10 @@ impl Log { ($1, $2, $3, $4) ", ) - .bind(author) - .bind(log_id) - .bind(document) - .bind(schema) + .bind(author.as_str()) + .bind(log_id.as_u64().to_string()) + .bind(document.as_str()) + .bind(schema.as_str()) .execute(pool) .await? .rows_affected(); @@ -60,7 +63,7 @@ impl Log { /// Determines the next unused log_id of an author. pub async fn next_log_id(pool: &Pool, author: &Author) -> Result { // Get all log ids from this author - let log_ids: Vec = query_as::<_, LogId>( + let mut result: Vec = query_scalar( " SELECT log_id @@ -72,11 +75,17 @@ impl Log { log_id ASC ", ) - .bind(author) + .bind(author.as_str()) .fetch_all(pool) .await?; - // Find next unused schema log_id by comparing the sequence of known log ids with an + // Convert all strings representing u64 integers to `LogId` instances + let log_ids: Vec = result + .iter_mut() + .map(|str| str.parse().expect("Corrupt u64 integer found in database")) + .collect(); + + // Find next unused document log by comparing the sequence of known log ids with an // sequence of subsequent log ids until we find a gap. let mut next_log_id = LogId::default(); @@ -99,7 +108,7 @@ impl Log { /// log has already been registered for a document and author and returns its regarding log id /// or None. pub async fn get(pool: &Pool, author: &Author, document_id: &Hash) -> Result> { - let result = query_as::<_, LogId>( + let result: Option = query_scalar( " SELECT log_id @@ -110,12 +119,15 @@ impl Log { AND document = $2 ", ) - .bind(author) - .bind(document_id) + .bind(author.as_str()) + .bind(document_id.as_str()) .fetch_optional(pool) .await?; - Ok(result) + // Wrap u64 inside of `LogId` instance + let log_id = result.map(|str| str.parse().expect("Corrupt u64 integer found in database")); + + Ok(log_id) } /// Returns registered or possible log id for a document. @@ -148,7 +160,7 @@ impl Log { /// by this document and author. This method returns that document id by looking up the log /// that the entry was stored in. pub async fn get_document_by_entry(pool: &Pool, entry_hash: &Hash) -> Result> { - let result = query_as::<_, Hash>( + let result: Option = query_scalar( " SELECT logs.document @@ -161,11 +173,14 @@ impl Log { entries.entry_hash = $1 ", ) - .bind(entry_hash) + .bind(entry_hash.as_str()) .fetch_optional(pool) .await?; - Ok(result) + // Unwrap here since we already validated the hash + let hash = result.map(|str| Hash::new(&str).expect("Corrupt hash found in database")); + + Ok(hash) } } diff --git a/aquadoggo/src/db/models/mod.rs b/aquadoggo/src/db/models/mod.rs index 10c1b041a..ca2c40db8 100644 --- a/aquadoggo/src/db/models/mod.rs +++ b/aquadoggo/src/db/models/mod.rs @@ -4,4 +4,4 @@ mod entry; mod log; pub use self::log::Log; -pub use entry::Entry; +pub use entry::{Entry, EntryRow}; diff --git a/aquadoggo/src/errors.rs b/aquadoggo/src/errors.rs index 6877e5d32..3693070df 100644 --- a/aquadoggo/src/errors.rs +++ b/aquadoggo/src/errors.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: AGPL-3.0-or-later -use p2panda_rs::entry::{EntryError, EntrySignedError}; +use p2panda_rs::entry::{EntryError, EntrySignedError, LogIdError, SeqNumError}; use p2panda_rs::hash::HashError; use p2panda_rs::identity::AuthorError; use p2panda_rs::operation::{OperationEncodedError, OperationError}; @@ -35,6 +35,14 @@ pub enum Error { #[error(transparent)] OperationEncodedValidation(#[from] OperationEncodedError), + /// Error returned from validating p2panda-rs `LogId` data types. + #[error(transparent)] + LogIdValidation(#[from] LogIdError), + + /// Error returned from validating p2panda-rs `SeqNum` data types. + #[error(transparent)] + SeqNumValidation(#[from] SeqNumError), + /// Error returned from validating Bamboo entries. #[error(transparent)] BambooValidation(#[from] bamboo_rs_core_ed25519_yasmf::verify::Error), diff --git a/aquadoggo/src/rpc/methods/entry_args.rs b/aquadoggo/src/rpc/methods/entry_args.rs index bc013a409..8699aa66f 100644 --- a/aquadoggo/src/rpc/methods/entry_args.rs +++ b/aquadoggo/src/rpc/methods/entry_args.rs @@ -53,16 +53,16 @@ pub async fn get_entry_args( Ok(EntryArgsResponse { entry_hash_backlink: Some(entry_backlink.entry_hash), entry_hash_skiplink, - seq_num: entry_backlink.seq_num.next().unwrap(), - log_id, + seq_num: entry_backlink.seq_num.next().unwrap().as_u64().to_string(), + log_id: log_id.as_u64().to_string(), }) } // No entry was given yet, we can assume this is the beginning of the log None => Ok(EntryArgsResponse { entry_hash_backlink: None, entry_hash_skiplink: None, - seq_num: SeqNum::default(), - log_id, + seq_num: SeqNum::default().as_u64().to_string(), + log_id: log_id.as_u64().to_string(), }), } } @@ -76,7 +76,7 @@ pub async fn determine_skiplink(pool: Pool, entry: &Entry) -> Result { - Operation::new_update( - schema.clone(), - document_id.clone(), - vec![backlink.unwrap().hash()], - fields, - ) - .unwrap() + Some(_) => { + Operation::new_update(schema.clone(), vec![backlink.unwrap().hash()], fields) + .unwrap() } None => Operation::new_create(schema.clone(), fields).unwrap(), }; @@ -264,13 +259,13 @@ mod tests { r#"{{ "entryHashBacklink": "{}", "entryHashSkiplink": {}, - "logId": {}, - "seqNum": {} + "logId": "{}", + "seqNum": "{}" }}"#, entry_encoded.hash().as_str(), skiplink_str, - expect_log_id.as_i64(), - expect_seq_num.as_i64(), + expect_log_id.as_u64(), + expect_seq_num.as_u64(), )); assert_eq!(handle_http(&app, request).await, response); diff --git a/aquadoggo/src/rpc/response.rs b/aquadoggo/src/rpc/response.rs index bdae63569..3ccdfa030 100644 --- a/aquadoggo/src/rpc/response.rs +++ b/aquadoggo/src/rpc/response.rs @@ -2,32 +2,35 @@ use serde::Serialize; -use crate::db::models::Entry; -use p2panda_rs::entry::{LogId, SeqNum}; +use crate::db::models::EntryRow; use p2panda_rs::hash::Hash; /// Response body of `panda_getEntryArguments`. +/// +/// `seq_num` and `log_id` are returned as strings to be able to represent large integers in JSON. #[derive(Serialize, Debug)] #[serde(rename_all = "camelCase")] pub struct EntryArgsResponse { pub entry_hash_backlink: Option, pub entry_hash_skiplink: Option, - pub seq_num: SeqNum, - pub log_id: LogId, + pub seq_num: String, + pub log_id: String, } /// Response body of `panda_publishEntry`. +/// +/// `seq_num` and `log_id` are returned as strings to be able to represent large integers in JSON. #[derive(Serialize, Debug)] #[serde(rename_all = "camelCase")] pub struct PublishEntryResponse { pub entry_hash_backlink: Option, pub entry_hash_skiplink: Option, - pub seq_num: SeqNum, - pub log_id: LogId, + pub seq_num: String, + pub log_id: String, } #[derive(Serialize, Debug)] #[serde(rename_all = "camelCase")] pub struct QueryEntriesResponse { - pub entries: Vec, + pub entries: Vec, }