diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5c064e6 Binary files /dev/null and b/.DS_Store differ diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7547450 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +target +README.md +Dockerfile +target/CACHEDIR.TAG \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 76d6816..3b04444 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -48,17 +48,6 @@ dependencies = [ "opaque-debug", ] -[[package]] -name = "ahash" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom 0.2.12", - "once_cell", - "version_check", -] - [[package]] name = "ahash" version = "0.8.11" @@ -66,6 +55,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", + "getrandom", "once_cell", "version_check", "zerocopy", @@ -73,77 +63,63 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "anstream" -version = "0.6.5" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -151,9 +127,21 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" + +[[package]] +name = "argon2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" +dependencies = [ + "base64ct", + "blake2", + "cpufeatures", + "password-hash 0.5.0", +] [[package]] name = "arrayref" @@ -169,45 +157,54 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-trait" -version = "0.1.79" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.60", ] [[package]] name = "atoi" -version = "1.0.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" dependencies = [ "num-traits", ] +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" -version = "0.7.3" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d09dbe0e490df5da9d69b36dca48a76635288a82f92eca90024883a56202026d" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", "axum-core", "axum-macros", "bytes", "futures-util", - "http 1.0.0", - "http-body 1.0.0", + "http", + "http-body", "http-body-util", - "hyper 1.1.0", + "hyper", "hyper-util", "itoa", "matchit", @@ -220,9 +217,9 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.1", "tokio", - "tower", + "tower 0.5.1", "tower-layer", "tower-service", "tracing", @@ -230,20 +227,43 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.2" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87c8503f93e6d144ee5690907ba22db7ba79ab001a932ab99034f0fe836b3df" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.0.0", - "http-body 1.0.0", + "http", + "http-body", "http-body-util", "mime", "pin-project-lite", "rustversion", - "sync_wrapper", + "sync_wrapper 1.0.1", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-extra" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73c3220b188aea709cf1b6c5f9b01c3bd936bb08bd2b5184a12b35ac8131b1f9" +dependencies = [ + "axum", + "axum-core", + "bytes", + "futures-util", + "headers", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "serde", + "tower 0.5.1", "tower-layer", "tower-service", "tracing", @@ -251,21 +271,20 @@ dependencies = [ [[package]] name = "axum-macros" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a2edad600410b905404c594e2523549f1bcd4bded1e252c8f74524ccce0b867" +checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ - "heck", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.60", ] [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -277,22 +296,22 @@ dependencies = [ ] [[package]] -name = "base64" -version = "0.13.1" +name = "base16ct" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64" -version = "0.21.6" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c79fed4cdb43e993fcdadc7e58a09fd0e3e649c4436fa11da71c9f1f3ee7feb9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" -version = "1.0.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bech32" @@ -300,33 +319,6 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9ff0bbfd639f15c74af777d81383cf53efb7c93613f6cab67c6c11e05bbf8b" -[[package]] -name = "bellperson" -version = "0.24.1" -source = "git+https://github.com/iron-fish/bellperson.git?branch=blstrs#37b9976bcd96986cbdc71ae09fc455015e3dfac0" -dependencies = [ - "bincode", - "blake2s_simd", - "blstrs", - "byteorder", - "crossbeam-channel", - "digest 0.10.7", - "ec-gpu", - "ec-gpu-gen", - "ff", - "group", - "log", - "memmap2", - "pairing", - "rand 0.8.5", - "rand_core 0.6.4", - "rayon", - "rustversion", - "serde", - "sha2 0.10.8", - "thiserror", -] - [[package]] name = "bincode" version = "1.3.3" @@ -338,18 +330,34 @@ dependencies = [ [[package]] name = "bip0039" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0830ae4cc96b0617cc912970c2b17e89456fecbf55e8eed53a956f37ab50c41" +checksum = "e68a5a99c65851e7be249f5cf510c0a136f18c9bca32139576d59bd3f577b043" dependencies = [ - "hmac 0.11.0", - "pbkdf2 0.9.0", - "rand 0.8.5", - "sha2 0.9.9", + "hmac", + "pbkdf2", + "rand", + "sha2 0.10.8", "unicode-normalization", "zeroize", ] +[[package]] +name = "bitcoin-io" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "340e09e8399c7bd8912f495af6aa58bea0c9214773417ffaa8f6460f93aaee56" + +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io", + "hex-conservative", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -358,9 +366,12 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +dependencies = [ + "serde", +] [[package]] name = "bitvec" @@ -374,6 +385,15 @@ dependencies = [ "wyz", ] +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "blake2b_simd" version = "1.0.2" @@ -398,9 +418,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" dependencies = [ "arrayref", "arrayvec", @@ -449,8 +469,19 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3c196a77437e7cc2fb515ce413a6401291578b5afc8ecb29a3c7ab957f05941" dependencies = [ - "ff", - "rand_core 0.6.4", + "ff 0.12.1", + "rand_core", + "subtle", +] + +[[package]] +name = "bls12_381" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7bc6d6292be3a19e6379786dac800f551e5865a5bb51ebbe3064ab80433f403" +dependencies = [ + "ff 0.13.0", + "rand_core", "subtle", ] @@ -475,10 +506,10 @@ checksum = "1ff3694b352ece02eb664a09ffb948ee69b35afa2e6ac444a6b8cb9d515deebd" dependencies = [ "blst", "byte-slice-cast", - "ff", - "group", + "ff 0.12.1", + "group 0.12.1", "pairing", - "rand_core 0.6.4", + "rand_core", "serde", "subtle", ] @@ -494,9 +525,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byte-slice-cast" @@ -512,18 +543,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" [[package]] name = "cfg-if" @@ -581,15 +609,19 @@ dependencies = [ ] [[package]] -name = "chrono" -version = "0.4.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +name = "chain_loader" +version = "0.1.0" dependencies = [ - "android-tzdata", - "iana-time-zone", - "num-traits", - "windows-targets 0.52.0", + "anyhow", + "clap", + "constants", + "db_handler", + "networking", + "oreo_errors", + "serde_json", + "tokio", + "tracing", + "utils", ] [[package]] @@ -614,9 +646,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.14" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e92c5c1a78c62968ec57dbc2440366a2d6e5a23faf829970ff1585dc6b18e2" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -624,9 +656,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.14" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4323769dc8a61e2c39ad7dc26f6f2800524691a44d74fe3d1071a5c24db6370" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", @@ -636,33 +668,39 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.60", ] [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "combine" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", "futures-core", @@ -672,12 +710,28 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "const-crc32-nostd" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808ac43170e95b11dd23d78aa9eaac5bea45776a602955552c4e833f3f0f823d" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "constant_time_eq" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +[[package]] +name = "constants" +version = "0.1.0" + [[package]] name = "core-foundation" version = "0.9.4" @@ -705,9 +759,9 @@ dependencies = [ [[package]] name = "crc" -version = "3.0.1" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ "crc-catalog", ] @@ -720,18 +774,24 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + [[package]] name = "crossbeam-channel" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ "crossbeam-utils", ] @@ -783,58 +843,135 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array 0.14.7", - "rand_core 0.6.4", + "rand_core", "typenum", ] [[package]] -name = "crypto-mac" -version = "0.8.0" +name = "crypto_box" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +checksum = "16182b4f39a82ec8a6851155cc4c0cda3065bb1db33651726a29e1951de0f009" dependencies = [ - "generic-array 0.14.7", + "aead 0.5.2", + "crypto_secretbox", + "curve25519-dalek", + "salsa20", "subtle", + "zeroize", ] [[package]] -name = "crypto-mac" -version = "0.11.1" +name = "crypto_secretbox" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1" dependencies = [ + "aead 0.5.2", + "cipher 0.4.4", "generic-array 0.14.7", + "poly1305 0.8.0", + "salsa20", "subtle", + "zeroize", ] [[package]] -name = "crypto_box" -version = "0.8.2" +name = "csv" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd26c32de5307fd08aac445a75c43472b14559d5dccdfba8022dbcd075838ebc" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" dependencies = [ - "aead 0.5.2", - "chacha20 0.9.1", - "chacha20poly1305 0.10.1", - "salsa20", - "x25519-dalek", - "xsalsa20poly1305", - "zeroize", + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", ] [[package]] name = "curve25519-dalek" -version = "3.2.0" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rustc_version", "subtle", "zeroize", ] +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "db_handler" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "constants", + "futures", + "oreo_errors", + "redis", + "serde", + "serde_json", + "serde_yaml", + "sqlx", + "sqlx-db-tester", + "substring", + "tokio", + "tracing", +] + +[[package]] +name = "debugless-unwrap" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f400d0750c0c069e8493f2256cb4da6f604b6d2eeb69a0ca8863acde352f8400" + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "derive-getters" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74ef43543e701c01ad77d3a5922755c6a1d71b22d942cb8042be4994b380caff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "digest" version = "0.9.0" @@ -851,6 +988,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", + "const-oid", "crypto-common", "subtle", ] @@ -864,15 +1002,6 @@ dependencies = [ "dirs-sys", ] -[[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" @@ -885,29 +1014,96 @@ dependencies = [ ] [[package]] -name = "dotenvy" -version = "0.15.7" +name = "document-features" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" +dependencies = [ + "litrs", +] [[package]] -name = "ec-gpu" -version = "0.2.0" +name = "dotenv" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd63582de2b59ea1aa48d7c1941b5d87618d95484397521b3acdfa0e1e9f5e45" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] -name = "ec-gpu-gen" -version = "0.5.2" +name = "dotenvy" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd09bf9d5313ad60379f70250590bccc10f7a04e2773062ac13255a37022584e" -dependencies = [ +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "dservice" +version = "0.1.0" +dependencies = [ + "anyhow", + "axum", + "bincode", + "bytes", + "clap", + "constants", + "db_handler", + "dotenv", + "futures", + "hex", + "networking", + "oreo_errors", + "priority-queue", + "rayon", + "serde", + "serde_json", + "tokio", + "tokio-util", + "tower 0.4.13", + "tower-http", + "tracing", + "utils", +] + +[[package]] +name = "dworker" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytes", + "clap", + "constants", + "db_handler", + "futures", + "gethostname", + "hex", + "ironfish", + "networking", + "num_cpus", + "oreo_errors", + "rand", + "rayon", + "tokio", + "tokio-util", + "tracing", + "utils", +] + +[[package]] +name = "ec-gpu" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd63582de2b59ea1aa48d7c1941b5d87618d95484397521b3acdfa0e1e9f5e45" + +[[package]] +name = "ec-gpu-gen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd09bf9d5313ad60379f70250590bccc10f7a04e2773062ac13255a37022584e" +dependencies = [ "bitvec", "crossbeam-channel", "ec-gpu", "execute", - "ff", - "group", + "ff 0.12.1", + "group 0.12.1", "hex", "log", "num_cpus", @@ -919,24 +1115,56 @@ dependencies = [ ] [[package]] -name = "either" -version = "1.9.0" +name = "ed25519" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] [[package]] -name = "encoding_rs" -version = "0.8.33" +name = "ed25519-dalek" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ - "cfg-if", + "curve25519-dalek", + "ed25519", + "rand_core", + "serde", + "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "either" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +dependencies = [ + "serde", ] +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "equihash" version = "0.2.0" -source = "git+https://github.com/oreoslabs/librustzcash.git?branch=blstrs#37c35dbcf7fc35fd321d02f9b38be7f1e6f02bce" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab579d7cf78477773b03e80bc2f89702ef02d7112c711d54ca93dcdce68533d5" dependencies = [ "blake2b_simd", "byteorder", @@ -958,6 +1186,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -992,7 +1231,7 @@ checksum = "ce8cd46a041ad005ab9c71263f9a0ff5b529eac0fe4cc9b4a20f4f0765d8cf4b" dependencies = [ "execute-command-tokens", "quote", - "syn 2.0.48", + "syn 2.0.60", ] [[package]] @@ -1004,16 +1243,17 @@ checksum = "69dc321eb6be977f44674620ca3aa21703cb20ffbe560e1ae97da08401ffbcad" [[package]] name = "f4jumble" version = "0.1.0" -source = "git+https://github.com/oreoslabs/librustzcash.git?branch=blstrs#37c35dbcf7fc35fd321d02f9b38be7f1e6f02bce" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a83e8d7fd0c526af4aad893b7c9fe41e2699ed8a776a6c74aecdeafe05afc75" dependencies = [ "blake2b_simd", ] [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "ff" @@ -1022,21 +1262,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" dependencies = [ "bitvec", - "rand_core 0.6.4", + "rand_core", + "subtle", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", "subtle", ] +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "finl_unicode" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" +[[package]] +name = "fish_hash" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cea268879491ea825e57d07604f4080d26acfee3c603077ea3ac1e5ea034313" +dependencies = [ + "blake3", + "tiny-keccak", +] + [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", @@ -1051,6 +1317,17 @@ dependencies = [ "spin 0.9.8", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1095,6 +1372,42 @@ dependencies = [ "num-traits", ] +[[package]] +name = "frost-core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5afd375261c34d31ff24dad068382f4bc3c95010c919d4fb8d483dc3d85c023" +dependencies = [ + "byteorder", + "const-crc32-nostd", + "debugless-unwrap", + "derive-getters", + "document-features", + "hex", + "itertools 0.13.0", + "postcard", + "rand_core", + "serde", + "serdect", + "thiserror", + "thiserror-nostd-notrait", + "visibility", + "zeroize", +] + +[[package]] +name = "frost-rerandomized" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a9d77595060546b53543d96b83dbeacaf3907e40a89763a8bb22124812b0cb6" +dependencies = [ + "derive-getters", + "document-features", + "frost-core", + "hex", + "rand_core", +] + [[package]] name = "funty" version = "2.0.0" @@ -1145,13 +1458,13 @@ dependencies = [ [[package]] name = "futures-intrusive" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" dependencies = [ "futures-core", "lock_api", - "parking_lot 0.11.2", + "parking_lot", ] [[package]] @@ -1168,7 +1481,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.60", ] [[package]] @@ -1209,6 +1522,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1221,28 +1535,25 @@ dependencies = [ ] [[package]] -name = "getrandom" -version = "0.1.16" +name = "gethostname" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" dependencies = [ - "cfg-if", - "js-sys", "libc", - "wasi 0.9.0+wasi-snapshot-preview1", - "wasm-bindgen", + "windows-targets 0.48.5", ] [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] @@ -1264,49 +1575,22 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ - "ff", - "rand 0.8.5", - "rand_core 0.6.4", + "ff 0.12.1", + "rand", + "rand_core", "rand_xorshift", "subtle", ] [[package]] -name = "h2" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b553656127a00601c8ae5590fcfdc118e4083a7924b6cf4ffc1ea4b99dc429d7" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.11", - "indexmap 2.1.0", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "h2" -version = "0.4.1" +name = "group" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "991910e35c615d8cab86b5ab04be67e6ad24d2bf5f4f11fdbbed26da999bbeab" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 1.0.0", - "indexmap 2.1.0", - "slab", - "tokio", - "tokio-util", - "tracing", + "ff 0.13.0", + "rand_core", + "subtle", ] [[package]] @@ -1317,12 +1601,12 @@ checksum = "85e10bf9924da1754e443641c9e7f9f00483749f8fb837fde696ef6ed6e2f079" dependencies = [ "arrayvec", "bitvec", - "ff", - "group", + "ff 0.12.1", + "group 0.12.1", "halo2_proofs", "lazy_static", - "pasta_curves", - "rand 0.8.5", + "pasta_curves 0.4.1", + "rand", "subtle", "uint", ] @@ -1334,27 +1618,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cff771b9a2445cd2545c9ef26d863c290fbb44ae440c825a20eb7156f67a949a" dependencies = [ "blake2b_simd", - "ff", - "group", - "pasta_curves", - "rand_core 0.6.4", + "ff 0.12.1", + "group 0.12.1", + "pasta_curves 0.4.1", + "rand_core", "rayon", "tracing", ] [[package]] -name = "hashbrown" -version = "0.12.3" +name = "hash32" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash 0.8.11", + "ahash", "allocator-api2", ] @@ -1364,7 +1651,45 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.3", + "hashbrown", +] + +[[package]] +name = "headers" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" +dependencies = [ + "base64", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" +dependencies = [ + "http", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version", + "serde", + "spin 0.9.8", + "stable_deref_trait", ] [[package]] @@ -1376,11 +1701,17 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1389,32 +1720,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] -name = "hkdf" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" -dependencies = [ - "hmac 0.12.1", -] - -[[package]] -name = "hmac" -version = "0.8.1" +name = "hex-conservative" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" dependencies = [ - "crypto-mac 0.8.0", - "digest 0.9.0", + "arrayvec", ] [[package]] -name = "hmac" -version = "0.11.0" +name = "hkdf" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ - "crypto-mac 0.11.1", - "digest 0.9.0", + "hmac", ] [[package]] @@ -1437,37 +1757,15 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.11", - "pin-project-lite", -] - [[package]] name = "http-body" version = "1.0.0" @@ -1475,19 +1773,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ "bytes", - "http 1.0.0", + "http", ] [[package]] name = "http-body-util" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" dependencies = [ "bytes", - "futures-util", - "http 1.0.0", - "http-body 1.0.0", + "futures-core", + "http", + "http-body", "pin-project-lite", ] @@ -1505,100 +1803,39 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.28" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", - "futures-core", "futures-util", - "h2 0.3.23", - "http 0.2.11", - "http-body 0.4.6", + "http", + "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2", + "smallvec", "tokio", - "tower-service", - "tracing", - "want", ] [[package]] -name = "hyper" -version = "1.1.0" +name = "hyper-util" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" dependencies = [ "bytes", - "futures-channel", - "futures-util", - "h2 0.4.1", - "http 1.0.0", - "http-body 1.0.0", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.11", - "hyper 0.14.28", - "rustls 0.21.10", - "tokio", - "tokio-rustls 0.24.1", -] - -[[package]] -name = "hyper-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdea9aac0dbe5a9240d68cfd9501e2db94222c6dc06843e06640b9e07f0fdc67" -dependencies = [ - "bytes", - "futures-channel", "futures-util", - "http 1.0.0", - "http-body 1.0.0", - "hyper 1.1.0", + "http", + "http-body", + "hyper", "pin-project-lite", "socket2", "tokio", - "tracing", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", + "tower 0.4.13", + "tower-service", ] [[package]] @@ -1622,22 +1859,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.3" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown", ] [[package]] @@ -1649,109 +1876,194 @@ dependencies = [ "generic-array 0.14.7", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - [[package]] name = "ironfish" version = "0.3.0" -source = "git+https://github.com/oreoslabs/ironfish-optimize.git?branch=feature/support-wasm#c31ee6622fcd65df868e13bef5def6d4a377e91d" +source = "git+https://github.com/iron-fish/ironfish.git?branch=master#6693fe5f913850867c0a3063f41ab4bff9891ab9" dependencies = [ - "bellperson", + "argon2", "blake2b_simd", "blake2s_simd", "blake3", - "blst", "blstrs", "byteorder", - "chacha20poly1305 0.9.1", + "chacha20poly1305 0.10.1", "crypto_box", - "ff", - "group", + "ff 0.12.1", + "fish_hash", + "group 0.12.1", "hex", + "hkdf", + "ironfish-bellperson", + "ironfish-frost", + "ironfish-jubjub", "ironfish_zkp", - "jubjub 0.9.0 (git+https://github.com/oreoslabs/jubjub.git?branch=blstrs)", "lazy_static", - "libc", - "rand 0.8.5", + "rand", "sha2 0.10.8", "tiny-bip39", "xxhash-rust", ] [[package]] -name = "ironfish-server" -version = "0.1.1" +name = "ironfish-bellperson" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2e19b8d7c61fdbdfde5ba86cec85b9facf60b2b5ef9968618c353f8f7f6815" dependencies = [ - "anyhow", - "async-trait", - "axum", - "bellperson", - "blst", + "bincode", + "blake2s_simd", "blstrs", - "clap", - "ff", - "futures", - "getrandom 0.2.12", - "group", - "ironfish", - "ironfish_zkp", - "jubjub 0.9.0 (git+https://github.com/oreoslabs/jubjub.git?branch=blstrs)", - "rand 0.8.5", - "rand_core 0.6.4", + "byteorder", + "crossbeam-channel", + "digest 0.10.7", + "ec-gpu", + "ec-gpu-gen", + "ff 0.12.1", + "group 0.12.1", + "log", + "memmap2", + "pairing", + "rand", + "rand_core", "rayon", - "redis", - "reqwest", + "rustversion", "serde", - "serde_json", - "serde_yaml", - "sqlx", - "sqlx-db-tester", - "substring", + "sha2 0.10.8", "thiserror", - "tokio", - "tower", - "tower-http", +] + +[[package]] +name = "ironfish-frost" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bee779ebf008aa92e1bb90993a47ab730065a8d39f5fa6630cde1ddfcf56a46" +dependencies = [ + "blake3", + "chacha20 0.9.1", + "chacha20poly1305 0.10.1", + "ed25519-dalek", + "ironfish-reddsa", + "rand_chacha", + "rand_core", + "siphasher", + "x25519-dalek", +] + +[[package]] +name = "ironfish-jubjub" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81ee437e98296799ebdff1f62c14c63bbfb65df3e4e19c3913e7c46b9827b148" +dependencies = [ + "bitvec", + "blst", + "blstrs", + "ff 0.12.1", + "group 0.12.1", + "lazy_static", + "rand_core", + "subtle", +] + +[[package]] +name = "ironfish-primitives" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7b213445520fb92462bd4a79274ad9b31c1ce49248f6eaa7ca3a50e8fe413d3" +dependencies = [ + "aes", + "bip0039", + "bitvec", + "blake2b_simd", + "blake2s_simd", + "blstrs", + "byteorder", + "chacha20poly1305 0.9.1", + "equihash", + "ff 0.12.1", + "fpe", + "group 0.12.1", + "hex", + "incrementalmerkletree", + "ironfish-jubjub", + "lazy_static", + "memuse", + "nonempty", + "orchard", + "rand", + "rand_core", + "sha2 0.9.9", + "subtle", + "zcash_address", + "zcash_encoding", + "zcash_note_encryption", +] + +[[package]] +name = "ironfish-proofs" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ea51eb3565333b8c67483a16499452215326df95f92160bd567f16c35f82e29" +dependencies = [ + "blake2b_simd", + "blstrs", + "byteorder", + "directories", + "ff 0.12.1", + "group 0.12.1", + "ironfish-bellperson", + "ironfish-jubjub", + "ironfish-primitives", + "lazy_static", + "rand_core", + "redjubjub", "tracing", - "tracing-subscriber", - "ureq", - "zcash_primitives", +] + +[[package]] +name = "ironfish-reddsa" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb4aecfd3334f0128215ce47f57360d91d68ff9d6fd890e1faca3c79b2bfa28d" +dependencies = [ + "blake2b_simd", + "byteorder", + "frost-rerandomized", + "group 0.13.0", + "hex", + "jubjub 0.10.0", + "pasta_curves 0.5.1", + "rand_core", + "serde", + "thiserror", + "zeroize", ] [[package]] name = "ironfish_zkp" version = "0.2.0" -source = "git+https://github.com/oreoslabs/ironfish-optimize.git?branch=feature/support-wasm#c31ee6622fcd65df868e13bef5def6d4a377e91d" +source = "git+https://github.com/iron-fish/ironfish.git?branch=master#6693fe5f913850867c0a3063f41ab4bff9891ab9" dependencies = [ - "bellperson", "blake2s_simd", - "blst", "blstrs", "byteorder", - "ff", - "getrandom 0.2.12", - "group", - "jubjub 0.9.0 (git+https://github.com/oreoslabs/jubjub.git?branch=blstrs)", + "ff 0.12.1", + "group 0.12.1", + "ironfish-bellperson", + "ironfish-jubjub", + "ironfish-primitives", + "ironfish-proofs", "lazy_static", - "rand 0.8.5", - "rand_core 0.6.4", - "serde", - "zcash_primitives", - "zcash_proofs", + "rand", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.12.1" @@ -1761,17 +2073,26 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1783,25 +2104,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a575df5f985fe1cd5b2b05664ff6accfc46559032b954529fd225a2168d27b0f" dependencies = [ "bitvec", - "bls12_381", - "ff", - "group", - "rand_core 0.6.4", + "bls12_381 0.7.1", + "ff 0.12.1", + "group 0.12.1", + "rand_core", "subtle", ] [[package]] name = "jubjub" -version = "0.9.0" -source = "git+https://github.com/oreoslabs/jubjub.git?branch=blstrs#3f864b418d01bf330cefdad04bfd15362971c34b" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8499f7a74008aafbecb2a2e608a3e13e4dd3e84df198b604451efe93f2de6e61" dependencies = [ "bitvec", - "blst", - "blstrs", - "ff", - "group", - "lazy_static", - "rand_core 0.6.4", + "bls12_381 0.8.0", + "ff 0.13.0", + "group 0.13.0", + "rand_core", "subtle", ] @@ -1810,12 +2130,15 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "libc" -version = "0.2.152" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "libm" @@ -1825,26 +2148,42 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libredox" -version = "0.0.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "libc", - "redox_syscall 0.4.1", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", ] [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "litrs" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1852,9 +2191,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "matchers" @@ -1883,9 +2222,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "memmap2" @@ -1919,21 +2258,21 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.48.0", ] @@ -1955,6 +2294,25 @@ dependencies = [ "tempfile", ] +[[package]] +name = "networking" +version = "0.1.0" +dependencies = [ + "anyhow", + "axum", + "bytes", + "constants", + "db_handler", + "oreo_errors", + "serde", + "serde_json", + "tokio", + "tokio-util", + "tracing", + "ureq", + "uuid", +] + [[package]] name = "nom" version = "7.1.3" @@ -1992,23 +2350,51 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + [[package]] name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", + "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -2038,9 +2424,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" @@ -2048,7 +2434,7 @@ version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "cfg-if", "foreign-types", "libc", @@ -2065,7 +2451,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.60", ] [[package]] @@ -2076,9 +2462,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.101" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -2095,9 +2481,9 @@ dependencies = [ "aes", "bitvec", "blake2b_simd", - "ff", + "ff 0.12.1", "fpe", - "group", + "group 0.12.1", "halo2_gadgets", "halo2_proofs", "hex", @@ -2105,13 +2491,23 @@ dependencies = [ "lazy_static", "memuse", "nonempty", - "pasta_curves", - "rand 0.8.5", + "pasta_curves 0.4.1", + "rand", "reddsa", "serde", "subtle", "tracing", - "zcash_note_encryption 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_note_encryption", +] + +[[package]] +name = "oreo_errors" +version = "0.1.0" +dependencies = [ + "axum", + "serde", + "serde_json", + "thiserror", ] [[package]] @@ -2126,65 +2522,51 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "135590d8bdba2b31346f9cd1fb2a912329f5135e832a4f422942eb6ead8b6b3b" dependencies = [ - "group", -] - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", + "group 0.12.1", ] [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" dependencies = [ "lock_api", - "parking_lot_core 0.9.9", + "parking_lot_core", ] [[package]] name = "parking_lot_core" -version = "0.8.6" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", - "instant", "libc", - "redox_syscall 0.2.16", + "redox_syscall 0.5.1", "smallvec", - "winapi", + "windows-targets 0.52.5", ] [[package]] -name = "parking_lot_core" -version = "0.9.9" +name = "password-hash" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.4.1", - "smallvec", - "windows-targets 0.48.5", + "base64ct", + "rand_core", + "subtle", ] [[package]] name = "password-hash" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" dependencies = [ "base64ct", - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -2195,10 +2577,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cc65faf8e7313b4b1fbaa9f7ca917a0eed499a9663be71477f87993604341d8" dependencies = [ "blake2b_simd", - "ff", - "group", + "ff 0.12.1", + "group 0.12.1", "lazy_static", - "rand 0.8.5", + "rand", + "static_assertions", + "subtle", +] + +[[package]] +name = "pasta_curves" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095" +dependencies = [ + "ff 0.13.0", + "group 0.13.0", + "rand", "static_assertions", "subtle", ] @@ -2211,21 +2606,21 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pbkdf2" -version = "0.4.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "crypto-mac 0.8.0", + "digest 0.10.7", + "password-hash 0.4.2", ] [[package]] -name = "pbkdf2" -version = "0.9.0" +name = "pem-rfc7468" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05894bce6a1ba4be299d0c5f29563e08af2bc18bb7d48313113bed71e904739" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" dependencies = [ - "crypto-mac 0.11.1", - "password-hash", + "base64ct", ] [[package]] @@ -2236,29 +2631,29 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.60", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -2266,6 +2661,27 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.30" @@ -2294,26 +2710,78 @@ dependencies = [ "universal-hash 0.5.1", ] +[[package]] +name = "postcard" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "heapless", + "serde", +] + [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "priority-queue" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "509354d8a769e8d0b567d6821b84495c60213162761a732d68ce87c964bd347f" +dependencies = [ + "autocfg", + "equivalent", + "indexmap", +] + [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] +[[package]] +name = "prover" +version = "0.1.0" +dependencies = [ + "anyhow", + "axum", + "blst", + "blstrs", + "clap", + "constants", + "db_handler", + "getrandom", + "ironfish", + "ironfish-bellperson", + "ironfish_zkp", + "networking", + "oreo_errors", + "rand", + "rand_core", + "rayon", + "serde_json", + "tokio", + "tower 0.4.13", + "tower-http", + "tracing", + "utils", +] + [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -2326,36 +2794,13 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", + "libc", + "rand_chacha", + "rand_core", ] [[package]] @@ -2365,16 +2810,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", + "rand_core", ] [[package]] @@ -2383,16 +2819,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.12", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", + "getrandom", ] [[package]] @@ -2401,14 +2828,14 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ - "rand_core 0.6.4", + "rand_core", ] [[package]] name = "rayon" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -2416,9 +2843,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -2432,10 +2859,10 @@ checksum = "4cc8038c8b7e481bdf688d0585d4897ed0e9e0cee10aa365dde51238c20e4182" dependencies = [ "blake2b_simd", "byteorder", - "group", - "jubjub 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pasta_curves", - "rand_core 0.6.4", + "group 0.12.1", + "jubjub 0.9.0", + "pasta_curves 0.4.1", + "rand_core", "serde", "thiserror", "zeroize", @@ -2443,9 +2870,9 @@ dependencies = [ [[package]] name = "redis" -version = "0.25.2" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d64e978fd98a0e6b105d066ba4889a7301fca65aeac850a877d8797343feeb" +checksum = "6472825949c09872e8f2c50bde59fcefc17748b6be5c90fd67cd8b4daca73bfd" dependencies = [ "async-trait", "bytes", @@ -2473,8 +2900,8 @@ dependencies = [ "blake2b_simd", "byteorder", "digest 0.9.0", - "jubjub 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.6.4", + "jubjub 0.9.0", + "rand_core", "serde", "thiserror", "zeroize", @@ -2482,43 +2909,43 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", ] [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ - "getrandom 0.2.12", + "getrandom", "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.10.2" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", - "regex-syntax 0.8.2", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", ] [[package]] @@ -2532,13 +2959,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -2549,77 +2976,43 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "reqwest" -version = "0.11.23" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" -dependencies = [ - "base64 0.21.6", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.3.23", - "http 0.2.11", - "http-body 0.4.6", - "hyper 0.14.28", - "hyper-rustls", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls 0.21.10", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "system-configuration", - "tokio", - "tokio-rustls 0.24.1", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots 0.25.3", - "winreg", -] +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "ring" -version = "0.16.20" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", + "getrandom", "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", + "spin 0.9.8", + "untrusted", + "windows-sys 0.52.0", ] [[package]] -name = "ring" -version = "0.17.7" +name = "rsa" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" dependencies = [ - "cc", - "getrandom 0.2.12", - "libc", - "spin 0.9.8", - "untrusted 0.9.0", - "windows-sys 0.48.0", + "const-oid", + "digest 0.10.7", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "spki", + "subtle", + "zeroize", ] [[package]] @@ -2635,38 +3028,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] -name = "rustix" -version = "0.38.28" +name = "rustc_version" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "bitflags 2.4.1", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", + "semver", ] [[package]] -name = "rustls" -version = "0.20.9" +name = "rustix" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "log", - "ring 0.16.20", - "sct", - "webpki", + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.21.10" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring 0.17.7", + "ring", "rustls-webpki", "sct", ] @@ -2677,7 +3067,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.6", + "base64", ] [[package]] @@ -2686,21 +3076,21 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "salsa20" @@ -2732,15 +3122,34 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", + "ring", + "untrusted", +] + +[[package]] +name = "secp256k1" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3" +dependencies = [ + "bitcoin_hashes", + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1433bd67156263443f14d603720b082dd3121779323fce20cba2aa07b874bc1b" +dependencies = [ + "cc", ] [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -2751,39 +3160,45 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", ] +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + [[package]] name = "serde" -version = "1.0.195" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.60", ] [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -2792,9 +3207,9 @@ dependencies = [ [[package]] name = "serde_path_to_error" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" dependencies = [ "itoa", "serde", @@ -2814,17 +3229,51 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.30" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1bf28c79a99f70ee1f1d83d10c875d2e70618417fda01ad1785e027579d9d38" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.1.0", + "indexmap", "itoa", "ryu", "serde", "unsafe-libyaml", ] +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "server" +version = "0.1.0" +dependencies = [ + "anyhow", + "axum", + "axum-extra", + "bincode", + "clap", + "constants", + "db_handler", + "dotenv", + "hex", + "networking", + "oreo_errors", + "serde_json", + "sha2 0.10.8", + "tokio", + "tower 0.4.13", + "tower-http", + "tracing", + "utils", +] + [[package]] name = "sha1" version = "0.10.6" @@ -2877,13 +3326,29 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "slab" version = "0.4.9" @@ -2895,18 +3360,18 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2924,122 +3389,243 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "sqlformat" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" dependencies = [ - "itertools", + "itertools 0.12.1", "nom", "unicode_categories", ] [[package]] name = "sqlx" -version = "0.6.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8de3b03a925878ed54a954f621e64bf55a3c1bd29652d0d1a17830405350188" +checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa" dependencies = [ "sqlx-core", "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", ] [[package]] name = "sqlx-core" -version = "0.6.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" +checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6" dependencies = [ - "ahash 0.7.8", + "ahash", "atoi", - "base64 0.13.1", - "bitflags 1.3.2", "byteorder", "bytes", - "chrono", "crc", "crossbeam-queue", - "dirs", - "dotenvy", "either", "event-listener", "futures-channel", "futures-core", "futures-intrusive", + "futures-io", "futures-util", "hashlink", "hex", - "hkdf", - "hmac 0.12.1", - "indexmap 1.9.3", - "itoa", - "libc", + "indexmap", "log", - "md-5", "memchr", "once_cell", "paste", "percent-encoding", - "rand 0.8.5", - "rustls 0.20.9", + "rustls", "rustls-pemfile", "serde", "serde_json", - "sha1", "sha2 0.10.8", "smallvec", "sqlformat", - "sqlx-rt", - "stringprep", "thiserror", + "tokio", "tokio-stream", + "tracing", "url", - "uuid", - "webpki-roots 0.22.6", - "whoami", + "webpki-roots", ] [[package]] name = "sqlx-db-tester" -version = "0.1.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5b4b49682a8a2ddf4d574b2d06add6e68b81d34c07a31529aa87c7b58b028e5" +checksum = "18ec4c9e9c434dceec904013de09c070921bab90c76ff1551cd73663836793bc" dependencies = [ + "anyhow", + "csv", + "itertools 0.12.1", "sqlx", "tokio", "uuid", ] [[package]] -name = "sqlx-macros" -version = "0.6.3" +name = "sqlx-macros" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 1.0.109", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8" +dependencies = [ + "dotenvy", + "either", + "heck 0.4.1", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2 0.10.8", + "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", + "syn 1.0.109", + "tempfile", + "tokio", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" +dependencies = [ + "atoi", + "base64", + "bitflags 2.5.0", + "byteorder", + "bytes", + "crc", + "digest 0.10.7", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array 0.14.7", + "hex", + "hkdf", + "hmac", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand", + "rsa", + "serde", + "sha1", + "sha2 0.10.8", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" +dependencies = [ + "atoi", + "base64", + "bitflags 2.5.0", + "byteorder", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand", + "serde", + "serde_json", + "sha2 0.10.8", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9966e64ae989e7e575b19d7265cb79d7fc3cbbdf179835cb0d716f294c2049c9" +checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa" dependencies = [ - "dotenvy", - "either", - "heck", - "once_cell", - "proc-macro2", - "quote", - "sha2 0.10.8", + "atoi", + "flume 0.11.0", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", "sqlx-core", - "sqlx-rt", - "syn 1.0.109", + "tracing", "url", + "urlencoding", ] [[package]] -name = "sqlx-rt" -version = "0.6.3" +name = "stable_deref_trait" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024" -dependencies = [ - "once_cell", - "tokio", - "tokio-rustls 0.23.4", -] +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "static_assertions" @@ -3060,9 +3646,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "substring" @@ -3092,9 +3678,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -3108,25 +3694,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" +name = "sync_wrapper" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" [[package]] name = "tap" @@ -3136,42 +3707,61 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.9.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.4.1", "rustix", "windows-sys 0.52.0", ] [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "thiserror-nostd-notrait" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8444e638022c44d2a9337031dee8acb732bcc7fbf52ac654edc236b26408b61" +dependencies = [ + "thiserror-nostd-notrait-impl", +] + +[[package]] +name = "thiserror-nostd-notrait-impl" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "585e5ef40a784ce60b49c67d762110688d211d395d39e096be204535cf64590e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.60", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -3188,23 +3778,32 @@ dependencies = [ [[package]] name = "tiny-bip39" -version = "0.8.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d" +checksum = "62cc94d358b5a1e84a5cb9109f559aa3c4d634d2b1b4de3d0fa4adc7c78e2861" dependencies = [ "anyhow", - "hmac 0.8.1", + "hmac", "once_cell", - "pbkdf2 0.4.0", - "rand 0.7.3", + "pbkdf2", + "rand", "rustc-hash", - "sha2 0.9.9", + "sha2 0.10.8", "thiserror", "unicode-normalization", "wasm-bindgen", "zeroize", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -3222,16 +3821,16 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", "libc", "mio", "num_cpus", - "parking_lot 0.12.1", + "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", @@ -3247,7 +3846,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.60", ] [[package]] @@ -3260,27 +3859,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls 0.20.9", - "tokio", - "webpki", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.10", - "tokio", -] - [[package]] name = "tokio-stream" version = "0.1.15" @@ -3294,16 +3872,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -3322,16 +3899,32 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower-http" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09e12e6351354851911bdf8c2b8f2ab15050c567d70a8b9a37ae7b8301a4080d" +checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "bytes", - "http 1.0.0", - "http-body 1.0.0", + "http", + "http-body", "http-body-util", "pin-project-lite", "tower-layer", @@ -3340,15 +3933,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -3370,7 +3963,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.60", ] [[package]] @@ -3413,10 +4006,18 @@ dependencies = [ ] [[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +name = "transfer-tool" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "constants", + "db_handler", + "networking", + "tokio", + "tracing", + "utils", +] [[package]] name = "typenum" @@ -3438,9 +4039,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -3450,9 +4051,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -3495,12 +4096,6 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "untrusted" version = "0.9.0" @@ -3513,16 +4108,16 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" dependencies = [ - "base64 0.21.6", + "base64", "flate2", "log", "once_cell", - "rustls 0.21.10", + "rustls", "rustls-webpki", "serde", "serde_json", "url", - "webpki-roots 0.25.3", + "webpki-roots", ] [[package]] @@ -3536,19 +4131,49 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf8parse" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "utils" +version = "0.1.0" +dependencies = [ + "anyhow", + "secp256k1", + "tokio", + "tracing", + "tracing-subscriber", +] + [[package]] name = "uuid" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ - "getrandom 0.2.12", + "getrandom", + "rand", + "uuid-macro-internal", +] + +[[package]] +name = "uuid-macro-internal" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9881bea7cbe687e36c9ab3b778c36cd0487402e270304e8b1296d5085303c1a2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", ] [[package]] @@ -3570,20 +4195,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] -name = "want" -version = "0.3.1" +name = "visibility" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91" dependencies = [ - "try-lock", + "proc-macro2", + "quote", + "syn 2.0.60", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -3598,9 +4219,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3608,36 +4229,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.60", "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3645,57 +4254,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" - -[[package]] -name = "web-sys" -version = "0.3.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.22.4" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" -dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki", -] +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "webpki-roots" -version = "0.25.3" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "which" @@ -3717,7 +4297,6 @@ checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" dependencies = [ "redox_syscall 0.4.1", "wasite", - "web-sys", ] [[package]] @@ -3742,15 +4321,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.0", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -3766,7 +4336,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.5", ] [[package]] @@ -3786,17 +4356,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -3807,9 +4378,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -3819,9 +4390,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -3831,9 +4402,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -3843,9 +4420,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -3855,9 +4432,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -3867,9 +4444,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -3879,19 +4456,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" - -[[package]] -name = "winreg" -version = "0.50.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "wyz" @@ -3904,33 +4471,19 @@ dependencies = [ [[package]] name = "x25519-dalek" -version = "1.1.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ "curve25519-dalek", - "rand_core 0.5.1", - "zeroize", -] - -[[package]] -name = "xsalsa20poly1305" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02a6dad357567f81cd78ee75f7c61f1b30bb2fe4390be8fb7c69e2ac8dffb6c7" -dependencies = [ - "aead 0.5.2", - "poly1305 0.8.0", - "salsa20", - "subtle", - "zeroize", + "rand_core", ] [[package]] name = "xxhash-rust" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53be06678ed9e83edb1745eb72efc0bbcd7b5c3c35711a860906aed827a13d61" +checksum = "927da81e25be1e1a2901d59b81b37dd2efd1fc9c9345a55007f09bf5a2d3ee03" [[package]] name = "yastl" @@ -3938,14 +4491,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca6c5a4d66c1a9ea261811cf4773c27343de7e5033e1b75ea3f297dc7db3c1a" dependencies = [ - "flume", + "flume 0.10.14", "scopeguard", ] [[package]] name = "zcash_address" version = "0.1.0" -source = "git+https://github.com/oreoslabs/librustzcash.git?branch=blstrs#37c35dbcf7fc35fd321d02f9b38be7f1e6f02bce" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1322a31b757f0087f110cc4a85dc5c6ccf83d0533bac04c4d3d1ce9112cc602" dependencies = [ "bech32", "bs58", @@ -3956,7 +4510,8 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.1.0" -source = "git+https://github.com/oreoslabs/librustzcash.git?branch=blstrs#37c35dbcf7fc35fd321d02f9b38be7f1e6f02bce" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb61ea88eb539bc0ac2068e5da99411dd4978595b3d7ff6a4b1562ddc8e8710" dependencies = [ "byteorder", "nonempty", @@ -3970,94 +4525,28 @@ checksum = "33f84ae538f05a8ac74c82527f06b77045ed9553a0871d9db036166a4c344e3a" dependencies = [ "chacha20 0.8.2", "chacha20poly1305 0.9.1", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "zcash_note_encryption" -version = "0.1.0" -source = "git+https://github.com/oreoslabs/librustzcash.git?branch=blstrs#37c35dbcf7fc35fd321d02f9b38be7f1e6f02bce" -dependencies = [ - "chacha20 0.8.2", - "chacha20poly1305 0.9.1", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "zcash_primitives" -version = "0.7.0" -source = "git+https://github.com/oreoslabs/librustzcash.git?branch=blstrs#37c35dbcf7fc35fd321d02f9b38be7f1e6f02bce" -dependencies = [ - "aes", - "bip0039", - "bitvec", - "blake2b_simd", - "blake2s_simd", - "blst", - "blstrs", - "byteorder", - "chacha20poly1305 0.9.1", - "equihash", - "ff", - "fpe", - "group", - "hex", - "incrementalmerkletree", - "jubjub 0.9.0 (git+https://github.com/oreoslabs/jubjub.git?branch=blstrs)", - "lazy_static", - "memuse", - "nonempty", - "orchard", - "rand 0.8.5", - "rand_core 0.6.4", - "sha2 0.9.9", + "rand_core", "subtle", - "zcash_address", - "zcash_encoding", - "zcash_note_encryption 0.1.0 (git+https://github.com/oreoslabs/librustzcash.git?branch=blstrs)", -] - -[[package]] -name = "zcash_proofs" -version = "0.7.1" -source = "git+https://github.com/oreoslabs/librustzcash.git?branch=blstrs#37c35dbcf7fc35fd321d02f9b38be7f1e6f02bce" -dependencies = [ - "bellperson", - "blake2b_simd", - "blst", - "blstrs", - "byteorder", - "directories", - "ff", - "group", - "jubjub 0.9.0 (git+https://github.com/oreoslabs/jubjub.git?branch=blstrs)", - "lazy_static", - "rand_core 0.6.4", - "redjubjub", - "tracing", - "zcash_primitives", ] [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "087eca3c1eaf8c47b94d02790dd086cd594b912d2043d4de4bfdd466b3befb7c" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "6f4b6c273f496d8fd4eaf18853e6b448760225dc030ff2c485a786859aea6393" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.60", ] [[package]] @@ -4077,5 +4566,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.60", ] diff --git a/Cargo.toml b/Cargo.toml index 34bbd49..142d459 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,45 +1,14 @@ -[package] -name = "ironfish-server" -version = "0.1.1" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -anyhow = "1.0.79" -axum = { version = "0.7.3", features = ["macros"] } -clap = { version = "4.4.13", features = ["derive"] } -redis = { version = "0.25.2", features = ["tokio-comp", "tokio-native-tls-comp"] } -serde = { version = "1.0.195", features = ["derive"] } -serde_json = "1.0.111" -substring = "1.4.5" -thiserror = "1.0.56" -tokio = { version = "1.35.1", features = ["full"] } -tower = { version = "0.4.13", features = ["timeout"] } -tower-http = { version = "0.5.0", features = ["cors"] } -tracing = "0.1.40" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -ureq = { version = "2.9.1", features = ["json"] } -ironfish_rust = { package = "ironfish", git = "https://github.com/oreoslabs/ironfish-optimize.git", branch = "feature/support-wasm"} -# ironfish_rust = { package = "ironfish", path = "../ironfish/ironfish-rust"} -ironfish_zkp = { package = "ironfish_zkp", git = "https://github.com/oreoslabs/ironfish-optimize.git", branch = "feature/support-wasm"} -# ironfish_zkp = { package = "ironfish_zkp", path = "../ironfish/ironfish-zkp"} -blst = "=0.3.10" -blstrs = { version = "0.6.0", features = ["portable"] } -bellperson = { git = "https://github.com/iron-fish/bellperson.git", branch = "blstrs", features = ["groth16"] } -rand = "0.8.5" -getrandom = { version = "0.2", features = ["js"] } -rand_core = { version = "0.6.4", features = ["getrandom"] } -rayon = "1.5" -serde_yaml = "0.9.14" -async-trait = "0.1.79" -sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "postgres"] } -futures = { version = "0.3.30", features = ["futures-executor"] } - -[dev-dependencies] -reqwest = { version = "0.11", default-features = false, features = ["json", "rustls-tls"] } -jubjub = { git = "https://github.com/oreoslabs/jubjub.git", branch = "blstrs" } -zcash_primitives = { git = "https://github.com/oreoslabs/librustzcash.git", branch = "blstrs", package = "zcash_primitives" } -ff = "0.12.0" -group = "0.12.0" -sqlx-db-tester = "0.1.1" +[workspace] +resolver = "2" +members = [ + "crates/networking", + "crates/constants", + "crates/db_handler", + "crates/oreo_errors", + "crates/server", + "crates/utils", + "crates/prover", + "crates/dworker", + "crates/dservice", + "crates/chain_loader", "crates/transfer-tool", +] diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..fe409f3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +# Use the official Rust image as a base +FROM rust:latest AS builder + +# Set the working directory +WORKDIR /app + +RUN mkdir -p /app/build/target + +# Install sqlx-cli +RUN cargo install sqlx-cli + +# Copy the entire workspace +COPY . . + +RUN --mount=type=cache,target=/usr/local/cargo/registry \ + --mount=type=cache,target=/usr/local/cargo/git \ + --mount=type=cache,target=/app/target \ + cargo build --release && \ + cp -r /app/target /app/build + +# Use a minimal base image for the final container +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y \ + libssl3 \ + && rm -rf /var/lib/apt/lists/* + +# Set the working directory +WORKDIR /app + +# Copy the built binaries from the builder stage +COPY --from=builder /app/build/target/release/server /app/server +COPY --from=builder /app/build/target/release/chain_loader /app/chain_loader +COPY --from=builder /app/build/target/release/dservice /app/dservice +COPY --from=builder /app/build/target/release/dworker /app/dworker +COPY --from=builder /app/build/target/release/prover /app/prover + +# Copy the sqlx binary from the builder stage +COPY --from=builder /usr/local/cargo/bin/sqlx /app/sqlx +COPY migrations /app/migrations + + +# Expose necessary ports +EXPOSE 10002 9093 10001 20001 + +# Define the entry point for the container +CMD ["./main"] \ No newline at end of file diff --git a/README.md b/README.md index e9c6870..ed0ca7f 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,50 @@ ## 1. Overview -This repo consists of `server`, `prover` and `migrate`, is the core backend service of `OreoWallet`. +This repo consists of `chain_loader`, `dservice`, `dworker`, `server` and `prover`, is the core service of `OreoWallet`. -### 1.1 Server +### 1.1 crates/server Core service stores imported viewKeys from users and serves as data provider of OreoWallet. -### 1.2 Prover +### 1.2 crates/prover Standalone service to generate zk proof for user transactions, serves as prover of OreoWallet. -### 1.3 Migrate -This feature is useful only if you are running your own data provider since the 1st version of `ironfish-server`. Then you need to migrate redis data to one of new redis struct or postgres db. +### 1.3 crates/dservice +Quickscan server to schedule decryption tasks among all connected dworkers. + +### 1.4 crates/dworker +Decryption worker connects to dservice and handles decryption tasks from dservice. + +### 1.5 crates/chain_loader +A tool to fetch blocks from rpc and save in local db for better performance during dservice getBlocks. ## 2. Guide-level explanation ![basic arch](assets/arch_v2.png) -## 3. Run data provider (Advanced for developer only) - -### 3.1 Install +## Docker -- [Install `postgresql db`](https://www.postgresql.org/download/). -- [Install rust](https://www.rust-lang.org/tools/install). -- Install sqlx-cli with `cargo install sqlx-cli`. - -### 3.2 Init +Build -- If you ran `server` before, you need to migrate data to new struct with `src/bin/migrate`. -- Init postgres db with `sqlx database create` then create table with `sqlx migrate run`, check `migrations` directory for details. +```bash +docker build -t oreowallet . +``` -### 3.3 Run with postgres db +Run node: -- Create a config file for postgres db as `fixtures/postgres-config.yml`. -- Start server with db config, node config above. +```bash +ironfish start -d ~/.ironfish-testnet --rpc.http --rpc.http.port 9092 --rpc.http.host 0.0.0.0 +``` -## 4. Run prover +Run -- Build. -- Run with necessary cli opts. \ No newline at end of file +```bash +DB_USER=postgres \ +DB_PASSWORD=postgres \ +DB_PORT=5444 \ +NODE_HOST=host.docker.internal \ +NODE_PORT=9092 \ +SECRET_KEY=a0882c5ac5e2fa771dde52b2d5639734a4411df14f4748c6f991a96e5dd9f997 \ +PUBLIC_KEY=03221b2a0ebd9d6798aadee2861a5307ced1a33d143f34c571a98ab4fa534b7d3e \ +SERVER_PORT=8080 \ +docker-compose up +``` \ No newline at end of file diff --git a/crates/chain_loader/Cargo.toml b/crates/chain_loader/Cargo.toml new file mode 100644 index 0000000..62cb7c7 --- /dev/null +++ b/crates/chain_loader/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "chain_loader" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.79" +clap = { version = "4.4.13", features = ["derive"] } +tokio = { version = "1.35.1", features = ["full"] } +tracing = "0.1.40" +utils = { path = "../utils" } +networking = { path = "../networking" } +constants = { path = "../constants" } +oreo_errors = { path = "../oreo_errors" } +db_handler = { path = "../db_handler" } +serde_json = "1.0.117" \ No newline at end of file diff --git a/crates/chain_loader/src/lib.rs b/crates/chain_loader/src/lib.rs new file mode 100644 index 0000000..1b2eb96 --- /dev/null +++ b/crates/chain_loader/src/lib.rs @@ -0,0 +1,58 @@ +use std::time::Duration; + +use constants::{LOCAL_BLOCKS_CHECKPOINT, PRIMARY_BATCH}; +use db_handler::{DBHandler, DBTransaction, InnerBlock, Json, PgHandler}; +use networking::{rpc_abi::RpcBlock, rpc_handler::RpcHandler}; +use tokio::time::sleep; +use tracing::info; +use utils::blocks_range; + +pub async fn load_checkpoint(rpc_node: String, db_handler: PgHandler) -> anyhow::Result<()> { + let rpc_handler = RpcHandler::new(rpc_node); + for group in blocks_range(1..LOCAL_BLOCKS_CHECKPOINT + 1, PRIMARY_BATCH) { + if db_handler + .get_blocks(group.start as i64, group.end as i64) + .await + .is_ok() + { + continue; + } + let results = { + loop { + match rpc_handler.get_blocks(group.start, group.end) { + Ok(res) => break res, + Err(_) => {} + } + sleep(Duration::from_secs(3)).await; + } + }; + let blocks: Vec = results + .data + .blocks + .into_iter() + .map(|item| item.block) + .collect(); + let inner_blocks = blocks + .into_iter() + .map(|rpc| InnerBlock { + hash: rpc.hash.clone(), + sequence: rpc.sequence as i64, + transactions: Json( + rpc.transactions + .into_iter() + .map(|tx| DBTransaction { + hash: tx.hash, + serialized_notes: tx.notes.into_iter().map(|n| n.serialized).collect(), + }) + .collect(), + ), + }) + .collect(); + info!( + "save blocks from {} to {} in local db", + group.start, group.end + ); + let _ = db_handler.save_blocks(inner_blocks).await; + } + Ok(()) +} diff --git a/src/bin/server.rs b/crates/chain_loader/src/main.rs similarity index 54% rename from src/bin/server.rs rename to crates/chain_loader/src/main.rs index 4c68346..ad7f57c 100644 --- a/src/bin/server.rs +++ b/crates/chain_loader/src/main.rs @@ -1,21 +1,14 @@ -use std::net::SocketAddr; - use anyhow::Result; +use chain_loader::load_checkpoint; use clap::Parser; -use ironfish_server::{ - config::DbConfig, - db_handler::{DBHandler, PgHandler}, - handle_signals, initialize_logger, run_server, -}; +use db_handler::{DBHandler, DbConfig, PgHandler}; +use utils::{handle_signals, initialize_logger}; #[derive(Parser, Debug, Clone)] -pub struct Command { - /// The ip:port server will listen on - #[clap(short, long, default_value = "0.0.0.0:10001")] - pub listen: SocketAddr, +struct Command { /// The path to db config file - #[clap(short, long)] - pub config: String, + #[clap(long)] + pub dbconfig: String, /// Set your logger level #[clap(short, long, default_value = "0")] pub verbosity: u8, @@ -28,15 +21,14 @@ pub struct Command { async fn main() -> Result<()> { let args = Command::parse(); let Command { - listen, - config, + dbconfig, verbosity, node, } = args; initialize_logger(verbosity); handle_signals().await?; - let db_config = DbConfig::load(config).unwrap(); + let db_config = DbConfig::load(dbconfig).unwrap(); let db_handler = PgHandler::from_config(&db_config); - run_server(listen.into(), node, db_handler).await?; + load_checkpoint(node, db_handler).await?; Ok(()) } diff --git a/crates/constants/Cargo.toml b/crates/constants/Cargo.toml new file mode 100644 index 0000000..06d8173 --- /dev/null +++ b/crates/constants/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "constants" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/constants.rs b/crates/constants/src/lib.rs similarity index 61% rename from src/constants.rs rename to crates/constants/src/lib.rs index a84a98f..f6768d0 100644 --- a/src/constants.rs +++ b/crates/constants/src/lib.rs @@ -1,3 +1,5 @@ +use std::time::Duration; + pub const ACCOUNT_VERSION: u8 = 2; pub const IRON_NATIVE_ASSET: &str = "51f33a2f14f92735e562dc658a5639279ddca3d5079a6d1242b2a588a9cbf44c"; @@ -6,3 +8,8 @@ pub const OREOSRIPTIONS_ENDPOINT: &str = "http://localhost:20001/api"; pub const MAINNET_GENESIS_HASH: &str = "eac623b099b8081d2bde92d43a4a7795385c94e2c0ae4097ef488972e83ff2b3"; pub const MAINNET_GENESIS_SEQUENCE: i64 = 1; +pub const REORG_DEPTH: i64 = 100; +pub const SECONDARY_BATCH: i64 = 10000; +pub const RESCHEDULING_DURATION: Duration = Duration::from_secs(30); +pub const PRIMARY_BATCH: u64 = 100; +pub const LOCAL_BLOCKS_CHECKPOINT: u64 = 797_000; diff --git a/crates/db_handler/Cargo.toml b/crates/db_handler/Cargo.toml new file mode 100644 index 0000000..7c1c794 --- /dev/null +++ b/crates/db_handler/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "db_handler" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.79" +futures = { version = "0.3.30", features = ["futures-executor"] } +serde = { version = "1.0.195", features = ["derive"] } +serde_yaml = "0.9.14" +serde_json = "1.0.111" +async-trait = "0.1.79" +sqlx = { version = "0.7.0", features = ["runtime-tokio-rustls", "postgres"] } +substring = "1.4.5" +tracing = "0.1.40" +oreo_errors = { path = "../oreo_errors" } +constants = { path = "../constants" } +redis = { version = "0.25.2", features = [ + "tokio-comp", + "tokio-native-tls-comp", +] } + +[dev-dependencies] +sqlx-db-tester = "0.4.0" +tokio = { version = "1.35.1", features = ["full"] } diff --git a/fixtures/postgres-config.yml b/crates/db_handler/fixtures/postgres-config.yml similarity index 100% rename from fixtures/postgres-config.yml rename to crates/db_handler/fixtures/postgres-config.yml diff --git a/fixtures/redis-config.yml b/crates/db_handler/fixtures/redis-config.yml similarity index 100% rename from fixtures/redis-config.yml rename to crates/db_handler/fixtures/redis-config.yml diff --git a/src/config/mod.rs b/crates/db_handler/src/config.rs similarity index 100% rename from src/config/mod.rs rename to crates/db_handler/src/config.rs diff --git a/crates/db_handler/src/lib.rs b/crates/db_handler/src/lib.rs new file mode 100644 index 0000000..a2b030e --- /dev/null +++ b/crates/db_handler/src/lib.rs @@ -0,0 +1,77 @@ +mod config; +mod pg_handler; +mod redis_handler; + +pub use config::DbConfig; +pub use pg_handler::*; +pub use redis_handler::*; + +pub use sqlx::types::Json; + +use oreo_errors::OreoError; +use serde::{Deserialize, Serialize}; +use sqlx::FromRow; +use substring::Substring; + +#[async_trait::async_trait] +pub trait DBHandler { + /// Initialize a DB handler + fn from_config(config: &DbConfig) -> Self; + /// Save account in db and return account name + async fn save_account(&self, account: Account, worker_id: u32) -> Result; + /// Get account name from db + async fn get_account(&self, address: String) -> Result; + /// Remove account from db + async fn remove_account(&self, address: String) -> Result; + /// Update account need_scan status + async fn update_scan_status( + &self, + address: String, + new_status: bool, + ) -> Result; + /// Get accounts list which needs scan + async fn get_scan_accounts(&self) -> Result, OreoError>; + /// Save rpc blocks to db + async fn save_blocks(&self, blocks: Vec) -> Result<(), OreoError>; + /// Get compact blocks for dservice + async fn get_blocks(&self, start: i64, end: i64) -> Result, OreoError>; +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, FromRow)] +#[serde(rename_all = "camelCase")] +pub struct Account { + pub name: String, + pub create_head: Option, + pub create_hash: Option, + pub head: i64, + pub hash: String, + pub in_vk: String, + pub out_vk: String, + pub vk: String, + pub address: String, + pub need_scan: bool, +} + +pub fn address_to_name(address: &str) -> String { + address.substring(0, 10).into() +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, FromRow)] +#[sqlx(type_name = "db_transaction")] +pub struct DBTransaction { + pub hash: String, + pub serialized_notes: Vec, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, FromRow)] +pub struct InnerBlock { + pub hash: String, + pub sequence: i64, + pub transactions: Json>, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, FromRow)] +pub struct BonusAddress { + pub address: String, + pub paid: bool, +} diff --git a/crates/db_handler/src/pg_handler.rs b/crates/db_handler/src/pg_handler.rs new file mode 100644 index 0000000..8feab84 --- /dev/null +++ b/crates/db_handler/src/pg_handler.rs @@ -0,0 +1,379 @@ +use std::str::FromStr; + +use futures::executor::block_on; +use oreo_errors::OreoError; +use sqlx::{postgres::PgConnectOptions, ConnectOptions, PgPool, Row}; + +use crate::{BonusAddress, DBTransaction, InnerBlock}; + +use super::{Account, DBHandler}; + +#[derive(Debug, Clone)] +pub struct PgHandler { + pub pool: PgPool, +} + +impl PgHandler { + pub fn new(pool: PgPool) -> Self { + Self { pool } + } + + pub async fn insert(&self, account: Account) -> Result { + let result = sqlx::query( + "INSERT INTO wallet.account (name, create_head, create_hash, head, hash, in_vk, out_vk, vk, address) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING name" + ) + .bind(account.name.clone()) + .bind(account.create_head.clone()) + .bind(account.create_hash.clone()) + .bind(account.head) + .bind(account.hash.clone()) + .bind(account.in_vk.clone()) + .bind(account.out_vk.clone()) + .bind(account.vk.clone()) + .bind(account.address.clone()) + .fetch_one(&self.pool) + .await?.get(0); + Ok(result) + } + + pub async fn get_one(&self, address: String) -> Result { + let result = + sqlx::query_as::<_, Account>("SELECT * FROM wallet.account WHERE address = $1") + .bind(address) + .fetch_one(&self.pool) + .await?; + Ok(result) + } + + pub async fn get_one_by_name(&self, name: String) -> Result { + let result = sqlx::query_as::<_, Account>("SELECT * FROM wallet.account WHERE name = $1") + .bind(name) + .fetch_one(&self.pool) + .await?; + Ok(result) + } + + pub async fn update_one(&self, state: Account) -> Result { + let result = sqlx::query( + "UPDATE wallet.account SET head = $1, hash = $2, create_head = $3, create_hash = $4 WHERE address = $5 RETURNING name", + ) + .bind(state.head) + .bind(state.hash.clone()) + .bind(state.create_head) + .bind(state.create_hash.clone()) + .bind(state.address.clone()) + .fetch_one(&self.pool) + .await? + .get(0); + Ok(result) + } + + pub async fn delete(&self, address: String) -> Result { + let result = sqlx::query("DELETE FROM wallet.account WHERE address = $1 RETURNING name") + .bind(address) + .fetch_one(&self.pool) + .await? + .get(0); + Ok(result) + } + + pub async fn set_scan(&self, address: String, new_status: bool) -> Result { + let result = sqlx::query( + "UPDATE wallet.account SET need_scan = $1 WHERE address = $2 RETURNING name", + ) + .bind(new_status) + .bind(address) + .fetch_one(&self.pool) + .await? + .get(0); + Ok(result) + } + + pub async fn get_many_need_scan(&self) -> Result, sqlx::Error> { + let result = sqlx::query_as("SELECT * FROM wallet.account WHERE need_scan = true") + .fetch_all(&self.pool) + .await?; + Ok(result) + } + + pub async fn insert_compact_block(&self, block: InnerBlock) -> Result { + let result = sqlx::query( + "INSERT INTO wallet.blocks (hash, sequence, transactions) VALUES ($1, $2, $3) RETURNING sequence" + ) + .bind(block.hash.clone()) + .bind(block.sequence) + .bind(block.transactions) + .fetch_one(&self.pool) + .await?.get(0); + Ok(result) + } + + pub async fn get_compact_blocks( + &self, + start: i64, + end: i64, + ) -> Result, sqlx::Error> { + let result = + sqlx::query_as("SELECT * FROM wallet.blocks WHERE sequence >= $1 AND sequence <= $2") + .bind(start) + .bind(end) + .fetch_all(&self.pool) + .await?; + Ok(result) + } + + pub async fn get_compact_transactions( + &self, + block_hash: String, + ) -> Result, sqlx::Error> { + let result = + sqlx::query_as("SELECT hash, serialized_notes FROM wallet.txs WHERE block_hash = $1") + .bind(block_hash) + .fetch_all(&self.pool) + .await?; + Ok(result) + } + + pub async fn insert_first_seen(&self, address: String) -> Result<(), sqlx::Error> { + let result = sqlx::query("INSERT INTO wallet.firstseen (address) VALUES ($1)") + .bind(address) + .fetch_one(&self.pool) + .await? + .get(0); + Ok(result) + } + + pub async fn get_unpaid_addresses(&self) -> Result, sqlx::Error> { + let result = + sqlx::query_as("SELECT address, paid FROM wallet.firstseen WHERE paid = False") + .fetch_all(&self.pool) + .await?; + Ok(result) + } + + pub async fn update_firstseen_status(&self, address: String) -> Result<(), sqlx::Error> { + let result = sqlx::query("UPDATE wallet.firstseen SET paid = $1 WHERE address = $2") + .bind(true) + .bind(address) + .fetch_one(&self.pool) + .await? + .get(0); + Ok(result) + } +} + +#[async_trait::async_trait] +impl DBHandler for PgHandler { + fn from_config(config: &crate::config::DbConfig) -> Self { + let url = config.server_url(); + let options = PgConnectOptions::from_str(&url) + .unwrap() + .disable_statement_logging() + .clone(); + let pool = block_on(async { PgPool::connect_with(options).await.unwrap() }); + Self::new(pool) + } + + async fn save_account(&self, account: Account, _worker_id: u32) -> Result { + let _ = self.insert_first_seen(account.address.clone()).await; + let old_account = self.get_one(account.address.clone()).await; + match old_account { + Ok(_) => Err(OreoError::Duplicate(account.address)), + Err(e) => match e { + sqlx::Error::RowNotFound => { + self.insert(account).await.map_err(|_| OreoError::DBError) + } + _ => Err(OreoError::DBError), + }, + } + } + + async fn get_account(&self, address: String) -> Result { + self.get_one(address.clone()).await.map_err(|e| match e { + sqlx::Error::RowNotFound => OreoError::NoImported(address), + _ => OreoError::DBError, + }) + } + + async fn remove_account(&self, address: String) -> Result { + self.delete(address.clone()).await.map_err(|e| match e { + sqlx::Error::RowNotFound => OreoError::NoImported(address), + _ => OreoError::DBError, + }) + } + + async fn update_scan_status( + &self, + address: String, + new_status: bool, + ) -> Result { + match self.get_one(address.clone()).await { + Ok(account) => self + .set_scan(account.address, new_status) + .await + .map_err(|e| match e { + sqlx::Error::RowNotFound => OreoError::NoImported(address), + _ => OreoError::DBError, + }), + Err(_) => Err(OreoError::NoImported(address)), + } + } + + async fn get_scan_accounts(&self) -> Result, OreoError> { + self.get_many_need_scan() + .await + .map_err(|_| OreoError::DBError) + } + + async fn save_blocks(&self, blocks: Vec) -> Result<(), OreoError> { + let transaction = self.pool.begin().await.unwrap(); + for block in blocks { + let _ = self.insert_compact_block(block).await; + } + transaction.rollback().await.unwrap(); + Ok(()) + } + + async fn get_blocks(&self, start: i64, end: i64) -> Result, OreoError> { + let blocks = self + .get_compact_blocks(start, end) + .await + .map_err(|_| OreoError::DBError)?; + match blocks.len() as i64 == (end - start + 1) { + true => Ok(blocks), + false => Err(OreoError::DBError), + } + } +} + +#[cfg(test)] +mod tests { + use std::path::Path; + + use constants::{MAINNET_GENESIS_HASH, MAINNET_GENESIS_SEQUENCE}; + use sqlx::types::Json; + use sqlx_db_tester::TestPg; + + use crate::{address_to_name, Account, DBHandler, DBTransaction, InnerBlock}; + + use super::PgHandler; + + const VK: &str = "4ae4eb9606ba57b3b17a444100a9ac6453cd67e6fe4c860e63a2e18b1200978ab5ecce68e8639d5016cbe73b0ea9a3c8e906fc881af2e9ccfa7a7b63fb73d555"; + const IN_VK: &str = "4a08bec0ec5a471352f340d737e4b3baec2aec8d0a2e12201d92d8ad71aadd07"; + const OUT_VK: &str = "cee4ff41d7d8da5eedc6493134981eaad7b26a8b0291a4eac9ba95090fa47bf7"; + const ADDRESS: &str = "d63ba13d7c35caf942c64d5139b948b885ec931977a3f248c13e7f3c1bd0aa64"; + + fn get_tdb() -> TestPg { + TestPg::new( + "postgres://postgres:postgres@localhost:5432".to_string(), + Path::new("../../migrations"), + ) + } + + fn get_test_account() -> Account { + Account { + name: address_to_name(ADDRESS), + create_head: None, + create_hash: None, + head: MAINNET_GENESIS_SEQUENCE, + hash: MAINNET_GENESIS_HASH.to_string(), + in_vk: IN_VK.to_string(), + out_vk: OUT_VK.to_string(), + vk: VK.to_string(), + address: ADDRESS.to_string(), + need_scan: false, + } + } + + fn get_test_block() -> InnerBlock { + InnerBlock { + hash: "dd6653ad5ec58e6174586d8a54e6c60731520d0c3b41c2e3266a05965cad0dae".to_string(), + sequence: 10, + transactions: Json(vec![DBTransaction { + hash: "dd6653ad5ec58e6174586d8a54e6c60731520d0c3b41c2e3266a05965cad0da1".to_string(), + serialized_notes: vec!["dd6653ad5ec58e6174586d8a54e6c60731520d0c3b41c2e3266a05965cad0daedd6653ad5ec58e6174586d8a54e6c60731520d0c3b41c2e3266a05965cad0dae1".to_string()], + }, DBTransaction { + hash: "dd6653ad5ec58e6174586d8a54e6c60731520d0c3b41c2e3266a05965cad0d2".to_string(), + serialized_notes: vec!["dd6653ad5ec58e6174586d8a54e6c60731520d0c3b41c2e3266a05965cad0daedd6653ad5ec58e6174586d8a54e6c60731520d0c3b41c2e3266a05965cad0dae2".to_string()], + }]), + } + } + + #[tokio::test] + async fn save_account_should_work_pg() { + let tdb = get_tdb(); + let pool = tdb.get_pool().await; + let pg_handler = PgHandler::new(pool); + let account = get_test_account(); + let saved = pg_handler.save_account(account, 0).await; + assert!(saved.is_ok()); + let saved = saved.unwrap(); + assert_eq!(address_to_name(&ADDRESS.to_string()), saved); + } + + #[tokio::test] + async fn get_account_should_work_pg() { + let tdb = get_tdb(); + let pool = tdb.get_pool().await; + let pg_handler = PgHandler::new(pool); + let account = get_test_account(); + let _ = pg_handler.save_account(account.clone(), 0).await.unwrap(); + let saved = pg_handler.get_account(ADDRESS.to_string()).await; + assert!(saved.is_ok()); + let saved = saved.unwrap(); + assert_eq!(account, saved); + } + + #[tokio::test] + async fn remove_account_should_work_pg() { + let tdb = get_tdb(); + let pool = tdb.get_pool().await; + let pg_handler = PgHandler::new(pool); + let account = get_test_account(); + let saved = pg_handler.save_account(account.clone(), 0).await.unwrap(); + let result = pg_handler.remove_account(ADDRESS.to_string()).await; + assert!(result.is_ok()); + + // run remove once again + let should_error = pg_handler.remove_account(saved).await; + assert!(should_error.is_err()); + } + + #[tokio::test] + async fn save_blocks_should_work_pg() { + let tdb = get_tdb(); + let pool = tdb.get_pool().await; + let pg_handler = PgHandler::new(pool); + let block = get_test_block(); + let result = pg_handler.save_blocks(vec![block]).await; + println!("{:?}", result); + } + + #[tokio::test] + async fn get_blocks_should_work_pg() { + let tdb = get_tdb(); + let pool = tdb.get_pool().await; + let pg_handler = PgHandler::new(pool); + let block = get_test_block(); + let x = pg_handler.save_blocks(vec![block]).await; + println!("saved: {:?}", x); + + let blocks = pg_handler.get_blocks(9, 11).await.unwrap(); + println!("get blocks test: {:?}", blocks); + } + + #[tokio::test] + async fn get_firstseen_should_work_pg() { + let tdb = get_tdb(); + let pool = tdb.get_pool().await; + let pg_handler = PgHandler::new(pool); + let account = get_test_account(); + let saved = pg_handler.save_account(account, 0).await; + assert!(saved.is_ok()); + let unpaid = pg_handler.get_unpaid_addresses().await; + assert!(unpaid.is_ok()); + let unpaid = unpaid.unwrap(); + assert!(unpaid.len() == 1); + println!("{:?}", unpaid); + } +} diff --git a/src/db_handler/redis_handler.rs b/crates/db_handler/src/redis_handler.rs similarity index 88% rename from src/db_handler/redis_handler.rs rename to crates/db_handler/src/redis_handler.rs index 1caecc6..084e5bf 100644 --- a/src/db_handler/redis_handler.rs +++ b/crates/db_handler/src/redis_handler.rs @@ -1,3 +1,4 @@ +use oreo_errors::OreoError; use redis::{ aio::MultiplexedConnection, AsyncCommands, Client, ErrorKind, FromRedisValue, RedisResult, }; @@ -5,8 +6,7 @@ use std::collections::HashMap; use substring::Substring; use tracing::info; -use super::{Account, DBHandler}; -use crate::{config::DbConfig, error::OreoError}; +use crate::{config::DbConfig, Account, DBHandler, InnerBlock}; pub const REDIS_ACCOUNT_KEY: &str = "IRONACCOUNT"; pub const REDIS_ACCOUNT_KEY_V1: &str = "IRONACCOUNTV1"; @@ -129,6 +129,26 @@ impl DBHandler for RedisClient { } } + async fn update_scan_status( + &self, + _address: String, + _new_status: bool, + ) -> Result { + unimplemented!("Redis is deprecated for such feature!") + } + + async fn get_scan_accounts(&self) -> Result, OreoError> { + unimplemented!("Redis is deprecated for such feature!") + } + + async fn save_blocks(&self, _blocks: Vec) -> Result<(), OreoError> { + unimplemented!("Redis is deprecated for such feature!") + } + + async fn get_blocks(&self, _start: i64, _end: i64) -> Result, OreoError> { + unimplemented!("Redis is deprecated for such feature!") + } + fn from_config(config: &DbConfig) -> Self { info!("Redis handler selected"); RedisClient::connect(&config.server_url(), config.default_pool_size).unwrap() @@ -150,14 +170,15 @@ mod tests { // Outgoing View Key cee4ff41d7d8da5eedc6493134981eaad7b26a8b0291a4eac9ba95090fa47bf7 // Address d63ba13d7c35caf942c64d5139b948b885ec931977a3f248c13e7f3c1bd0aa64 + use constants::MAINNET_GENESIS_HASH; + use constants::MAINNET_GENESIS_SEQUENCE; + use oreo_errors::OreoError; + use super::address_to_name; use super::RedisClient; use crate::config::DbConfig; - use crate::constants::MAINNET_GENESIS_HASH; - use crate::constants::MAINNET_GENESIS_SEQUENCE; - use crate::db_handler::Account; - use crate::db_handler::DBHandler; - use crate::error::OreoError; + use crate::Account; + use crate::DBHandler; const VK: &str = "4ae4eb9606ba57b3b17a444100a9ac6453cd67e6fe4c860e63a2e18b1200978ab5ecce68e8639d5016cbe73b0ea9a3c8e906fc881af2e9ccfa7a7b63fb73d555"; const IN_VK: &str = "4a08bec0ec5a471352f340d737e4b3baec2aec8d0a2e12201d92d8ad71aadd07"; @@ -175,6 +196,7 @@ mod tests { out_vk: OUT_VK.to_string(), vk: VK.to_string(), address: ADDRESS.to_string(), + need_scan: false, } } diff --git a/crates/dservice/Cargo.toml b/crates/dservice/Cargo.toml new file mode 100644 index 0000000..7fc862d --- /dev/null +++ b/crates/dservice/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "dservice" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.79" +clap = { version = "4.4.13", features = ["derive"] } +tokio = { version = "1.35.1", features = ["full"] } +rayon = "1.5" +tokio-util = { version = "0.7.3", features = ["codec"] } +bytes = "1" +futures = { version = "0.3.30" } +tracing = "0.1.40" +serde = { version = "1.0.195", features = ["derive"] } +axum = { version = "0.7.3", features = ["macros"] } +serde_json = "1.0.111" +tower = { version = "0.4.13", features = ["timeout"] } +tower-http = { version = "0.5.0", features = ["cors"] } +constants = { path = "../constants" } +oreo_errors = { path = "../oreo_errors" } +db_handler = { path = "../db_handler" } +networking = { path = "../networking" } +utils = { path = "../utils" } +hex = "0.4.3" +priority-queue = "2.0.2" +dotenv = "0.15.0" +bincode = "1.3.3" diff --git a/crates/dservice/src/lib.rs b/crates/dservice/src/lib.rs new file mode 100644 index 0000000..9989bb8 --- /dev/null +++ b/crates/dservice/src/lib.rs @@ -0,0 +1,362 @@ +use std::{ + cmp::{self, Reverse}, + net::SocketAddr, + ops::Deref, + str::FromStr, + sync::Arc, + time::{Duration, Instant}, +}; + +use axum::{ + error_handling::HandleErrorLayer, + extract::{self, State}, + http::StatusCode, + response::IntoResponse, + routing::post, + BoxError, Json, Router, +}; +use constants::{LOCAL_BLOCKS_CHECKPOINT, PRIMARY_BATCH, REORG_DEPTH, RESCHEDULING_DURATION}; +use db_handler::{DBHandler, InnerBlock, PgHandler}; +use manager::{AccountInfo, Manager, SecpKey, ServerMessage, SharedState, TaskInfo}; +use networking::{ + decryption_message::{DecryptionMessage, ScanRequest, SuccessResponse}, + rpc_abi::BlockInfo, + socket_message::codec::DRequest, +}; +use tokio::{net::TcpListener, sync::oneshot, time::sleep}; +use tower::{timeout::TimeoutLayer, ServiceBuilder}; +use tower_http::cors::{Any, CorsLayer}; +use tracing::{debug, error, info}; +use utils::{blocks_range, default_secp, verify, Signature}; + +pub mod manager; +pub mod router; + +pub async fn scheduling_tasks( + scheduler: Arc, + accounts: &Vec, + blocks: Vec, +) -> anyhow::Result<()> { + for account in accounts.iter() { + if let Some(account_info) = scheduler + .account_mappling + .read() + .await + .get(&account.address) + { + debug!( + "start scanning {} blocks for account {:?}", + blocks.len(), + account.address.clone() + ); + for block in blocks.iter() { + if (block.sequence as u64) < account_info.start_block.sequence + || (block.sequence as u64) > account_info.end_block.sequence + { + debug!("skip height {:?}", block.sequence); + continue; + } + let task = DRequest::from_transactions(account, block.transactions.deref().clone()); + let task_id = task.id.clone(); + let _ = scheduler.task_mapping.write().await.insert( + task_id, + TaskInfo { + since: Instant::now(), + sequence: block.sequence, + hash: block.hash.clone(), + address: account.address.clone(), + }, + ); + let mut task_sent = false; + for (k, worker) in scheduler.workers.read().await.iter() { + if worker.status == 1 { + match worker + .router + .send(ServerMessage { + name: Some(k.to_string()), + request: task.clone(), + }) + .await + { + Ok(_) => { + task_sent = true; + break; + } + Err(e) => { + error!("failed to send message to worker, {:?}", e); + } + } + } + } + if task_sent { + continue; + } + let _ = scheduler + .task_queue + .write() + .await + .push(task, Reverse(block.sequence)); + } + } + } + Ok(()) +} + +pub async fn run_dserver( + dlisten: SocketAddr, + restful: SocketAddr, + rpc_server: String, + db_handler: PgHandler, + server: String, + sk_u8: [u8; 32], + pk_u8: [u8; 33], +) -> anyhow::Result<()> { + let secp_key = SecpKey { + sk: sk_u8, + pk: pk_u8, + }; + let shared_resource = Arc::new(SharedState::new(db_handler, &rpc_server, &server, secp_key)); + let manager = Manager::new(shared_resource); + + if let Err(e) = Manager::initialize_networking(manager.clone(), dlisten).await { + error!("init networking server {}", e); + } + + // manager status updater + let status_manager = manager.clone(); + let (router, handler) = oneshot::channel(); + tokio::spawn(async move { + let _ = router.send(()); + loop { + { + info!( + "online workers: {}", + status_manager.workers.read().await.len() + ); + info!( + "pending taskes in queue: {}", + status_manager.task_queue.read().await.len() + ); + info!( + "pending account to scan: {:?}", + status_manager.accounts_to_scan.read().await + ); + } + sleep(Duration::from_secs(60)).await; + } + }); + let _ = handler.await; + + { + info!("warmup, wait for worker to join"); + sleep(Duration::from_secs(60)).await; + } + + // primary task scheduling + let schduler = manager.clone(); + let (router, handler) = oneshot::channel(); + tokio::spawn(async move { + let _ = router.send(()); + loop { + sleep(RESCHEDULING_DURATION).await; + if !schduler.accounts_to_scan.read().await.is_empty() { + if !schduler.account_mappling.read().await.is_empty() { + continue; + } + let mut accounts_should_scan = vec![]; + let mut scan_start = u64::MAX; + let latest = schduler + .shared + .rpc_handler + .get_latest_block() + .unwrap() + .data + .current_block_identifier; + let scan_end = schduler + .shared + .rpc_handler + .get_block(latest.index.parse::().unwrap() - REORG_DEPTH) + .unwrap() + .data + .block; + let scan_end = BlockInfo { + sequence: scan_end.sequence as u64, + hash: scan_end.hash, + }; + while let Some(account) = schduler.accounts_to_scan.write().await.pop() { + if schduler + .account_mappling + .read() + .await + .get(&account.address) + .is_some() + { + continue; + } + let head = account.head.clone().unwrap(); + let _ = schduler.account_mappling.write().await.insert( + account.address.clone(), + AccountInfo::new( + head.clone(), + scan_end.clone(), + account.in_vk.clone(), + account.out_vk.clone(), + ), + ); + scan_start = cmp::min(scan_start, head.sequence); + accounts_should_scan.push(account); + } + if accounts_should_scan.is_empty() { + continue; + } + info!("accounts to scanning, {:?}", accounts_should_scan); + let blocks_to_scan = blocks_range(scan_start..scan_end.sequence + 1, PRIMARY_BATCH); + for group in blocks_to_scan { + let blocks = match group.end <= LOCAL_BLOCKS_CHECKPOINT { + true => schduler + .shared + .db_handler + .get_blocks(group.start as i64, group.end as i64) + .await + .unwrap(), + false => { + let items = schduler + .shared + .rpc_handler + .get_blocks(group.start, group.end) + .unwrap() + .data + .blocks; + items + .into_iter() + .map(|item| item.block.to_inner()) + .collect() + } + }; + + let _ = scheduling_tasks(schduler.clone(), &accounts_should_scan, blocks) + .await + .unwrap(); + // avoid too much memory usage + if group.end % 30000 == 0 { + sleep(Duration::from_secs(1)).await; + } + } + } + } + }); + let _ = handler.await; + + // secondary task scheduling + let secondary = manager.clone(); + let (router, handler) = oneshot::channel(); + tokio::spawn(async move { + let _ = router.send(()); + loop { + for key in secondary + .task_mapping + .read() + .await + .iter() + .filter(|(_k, v)| v.since.elapsed().as_secs() >= 600) + .map(|(k, _)| k.to_string()) + { + info!("rescheduling task: {:?}", key); + match secondary.task_mapping.write().await.remove(&key) { + Some(task_info) => { + let address = task_info.address.to_string(); + let sequence = task_info.sequence; + if let Some(account) = secondary.account_mappling.read().await.get(&address) + { + if let Ok(block) = secondary.shared.rpc_handler.get_block(sequence) { + let block = block.data.block.to_inner(); + let _ = scheduling_tasks( + secondary.clone(), + &vec![ScanRequest { + address: address.clone(), + in_vk: account.in_vk.clone(), + out_vk: account.out_vk.clone(), + head: Some(account.start_block.clone()), + }], + vec![block], + ) + .await + .unwrap(); + } + } + } + None => {} + } + } + sleep(RESCHEDULING_DURATION).await; + } + }); + let _ = handler.await; + + let (router, handler) = oneshot::channel(); + tokio::spawn(async move { + let _ = router.send(()); + let _ = start_rest(manager.clone(), restful).await; + }); + let _ = handler.await; + + std::future::pending::<()>().await; + Ok(()) +} + +pub async fn start_rest(server: Arc, restful: SocketAddr) -> anyhow::Result<()> { + let router = Router::new() + .route("/scanAccount", post(account_scanner_handler)) + .with_state(server) + .layer( + ServiceBuilder::new() + .layer(HandleErrorLayer::new(|_: BoxError| async { + StatusCode::REQUEST_TIMEOUT + })) + .layer(TimeoutLayer::new(Duration::from_secs(60))), + ) + .layer( + CorsLayer::new() + .allow_methods(Any) + .allow_origin(Any) + .allow_headers(Any), + ); + let listener = TcpListener::bind(&restful).await?; + info!("rest server listening on {}", &restful); + axum::serve(listener, router).await?; + Ok(()) +} + +pub async fn account_scanner_handler( + State(manager): State>, + extract::Json(request): extract::Json>, +) -> impl IntoResponse { + info!("new scan request coming: {:?}", request); + let DecryptionMessage { message, signature } = request; + let secp = default_secp(); + let msg = bincode::serialize(&message).unwrap(); + let signature = Signature::from_str(&signature).unwrap(); + if let Ok(x) = verify( + &secp, + &msg[..], + signature.serialize_compact(), + &manager.shared.secp_key.pk, + ) { + if x { + let _ = manager.accounts_to_scan.write().await.push(message); + return Json(SuccessResponse { success: true }); + } + } + Json(SuccessResponse { success: false }) +} + +#[cfg(test)] +mod tests { + use crate::blocks_range; + + #[test] + fn block_range_test() { + let range = blocks_range(1..100, 30); + println!("ranges, {:?}", range); + } +} diff --git a/crates/dservice/src/main.rs b/crates/dservice/src/main.rs new file mode 100644 index 0000000..20ea164 --- /dev/null +++ b/crates/dservice/src/main.rs @@ -0,0 +1,65 @@ +use std::net::SocketAddr; + +use anyhow::Result; +use clap::Parser; +use db_handler::{DBHandler, DbConfig, PgHandler}; +use dotenv::dotenv; +use dservice::run_dserver; +use utils::{handle_signals, initialize_logger}; + +#[derive(Parser, Debug, Clone)] +pub struct Command { + /// The ip:port server will listen on for worker to connect + #[clap(long, default_value = "0.0.0.0:10001")] + pub dlisten: SocketAddr, + /// The ip:port server will listen on for worker to connect + #[clap(long, default_value = "0.0.0.0:20001")] + pub restful: SocketAddr, + /// Set your logger level + #[clap(short, long, default_value = "0")] + pub verbosity: u8, + /// The path to db config file + #[clap(long)] + pub dbconfig: String, + /// The Ironfish rpc node to connect to + #[clap(short, long, default_value = "127.0.0.1:9092")] + pub node: String, + /// The server to connect to + #[clap(short, long, default_value = "127.0.0.1:9093")] + pub server: String, +} + +#[tokio::main] +async fn main() -> Result<()> { + dotenv().ok(); + let sk = std::env::var("SECRET_KEY").expect("SECRET_KEY not provided in env"); + let pk = std::env::var("PUBLIC_KEY").expect("PUBLIC_KEY not provided in env"); + let mut sk_u8 = [0u8; 32]; + let mut pk_u8 = [0u8; 33]; + let _ = hex::decode_to_slice(sk, &mut sk_u8).unwrap(); + let _ = hex::decode_to_slice(pk, &mut pk_u8).unwrap(); + let args = Command::parse(); + let Command { + dlisten, + restful, + verbosity, + dbconfig, + node, + server, + } = args; + initialize_logger(verbosity); + handle_signals().await?; + let db_config = DbConfig::load(dbconfig).unwrap(); + let db_handler = PgHandler::from_config(&db_config); + run_dserver( + dlisten.into(), + restful.into(), + node, + db_handler, + server, + sk_u8, + pk_u8, + ) + .await?; + Ok(()) +} diff --git a/crates/dservice/src/manager.rs b/crates/dservice/src/manager.rs new file mode 100644 index 0000000..59efe19 --- /dev/null +++ b/crates/dservice/src/manager.rs @@ -0,0 +1,350 @@ +use std::{ + cmp::Reverse, + collections::HashMap, + net::SocketAddr, + sync::Arc, + time::{Duration, Instant}, +}; + +use anyhow::Result; +use constants::{MAINNET_GENESIS_HASH, MAINNET_GENESIS_SEQUENCE}; +use db_handler::{DBHandler, PgHandler}; +use futures::{SinkExt, StreamExt}; +use networking::{ + decryption_message::{DecryptionMessage, ScanRequest}, + rpc_abi::{BlockInfo, BlockWithHash, RpcSetAccountHeadRequest, TransactionWithHash}, + rpc_handler::RpcHandler, + server_handler::ServerHandler, + socket_message::codec::{DMessage, DMessageCodec, DRequest, DResponse}, +}; +use priority_queue::PriorityQueue; +use serde::{Deserialize, Serialize}; +use tokio::{ + io::split, + net::{TcpListener, TcpStream}, + sync::{ + mpsc::{self, Sender}, + oneshot, RwLock, + }, + time::timeout, +}; +use tokio_util::codec::{FramedRead, FramedWrite}; +use tracing::{debug, error, info, warn}; +use utils::{default_secp, sign}; + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct ServerMessage { + pub name: Option, + pub request: DRequest, +} + +#[derive(Debug, Clone)] +pub struct ServerWorker { + pub router: Sender, + // 1: Idle; 2: Busy + pub status: u8, +} + +impl ServerWorker { + pub fn new(router: Sender) -> Self { + Self { router, status: 1 } + } +} + +#[derive(Debug, Clone)] +pub struct TaskInfo { + pub since: Instant, + pub sequence: i64, + pub hash: String, + pub address: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AccountInfo { + pub start_block: BlockInfo, + pub end_block: BlockInfo, + pub remaining_task: u64, + pub in_vk: String, + pub out_vk: String, + // mapping from block_hash to transaction list in this block + pub blocks: HashMap>, +} + +impl AccountInfo { + pub fn new( + start_block: BlockInfo, + end_block: BlockInfo, + in_vk: String, + out_vk: String, + ) -> Self { + let remaining_task = end_block.sequence - start_block.sequence + 1; + Self { + start_block, + end_block, + remaining_task, + in_vk, + out_vk, + blocks: HashMap::new(), + } + } +} + +#[derive(Debug, Clone)] +pub struct SecpKey { + pub sk: [u8; 32], + pub pk: [u8; 33], +} + +#[derive(Debug, Clone)] +pub struct SharedState { + pub db_handler: T, + pub rpc_handler: RpcHandler, + pub server_handler: ServerHandler, + pub secp_key: SecpKey, +} + +impl SharedState +where + T: DBHandler, +{ + pub fn new(db_handler: T, endpoint: &str, server: &str, secp_key: SecpKey) -> Self { + Self { + db_handler: db_handler, + rpc_handler: RpcHandler::new(endpoint.into()), + server_handler: ServerHandler::new(server.into()), + secp_key, + } + } +} + +#[derive(Debug, Clone)] +pub struct Manager { + pub workers: Arc>>, + pub task_queue: Arc>>>, + pub task_mapping: Arc>>, + pub account_mappling: Arc>>, + pub shared: Arc>, + pub accounts_to_scan: Arc>>, +} + +impl Manager { + pub fn new(shared: Arc>) -> Arc { + Arc::new(Self { + workers: Arc::new(RwLock::new(HashMap::new())), + task_queue: Arc::new(RwLock::new(PriorityQueue::new())), + task_mapping: Arc::new(RwLock::new(HashMap::new())), + account_mappling: Arc::new(RwLock::new(HashMap::new())), + shared, + accounts_to_scan: Arc::new(RwLock::new(vec![])), + }) + } + + pub async fn initialize_networking(server: Arc, addr: SocketAddr) -> Result<()> { + let (router, handler) = oneshot::channel(); + let listener = TcpListener::bind(&addr).await?; + tokio::spawn(async move { + let _ = router.send(()); + loop { + match listener.accept().await { + Ok((stream, ip)) => { + debug!("new connection from {}", ip); + let _ = Self::handle_stream(stream, server.clone(), ip.to_string()).await; + } + Err(e) => error!("failed to accept connection, {:?}", e), + } + } + }); + let _ = handler.await; + Ok(()) + } + + pub async fn handle_stream(stream: TcpStream, server: Arc, worker: String) -> Result<()> { + let (tx, mut rx) = mpsc::channel::(1024); + let mut worker_name = worker; + let (r, w) = split(stream); + let mut outbound_w = FramedWrite::new(w, DMessageCodec::default()); + let mut outbound_r = FramedRead::new(r, DMessageCodec::default()); + + let worker_server = server.clone(); + let (router, handler) = oneshot::channel(); + tokio::spawn(async move { + let _ = router.send(()); + while let Some(message) = rx.recv().await { + let ServerMessage { name, request } = message; + match name { + Some(name) => { + let _ = worker_server + .workers + .write() + .await + .get_mut(&name) + .unwrap() + .status = 2; + } + None => {} + } + let send_future = outbound_w.send(DMessage::DRequest(request)); + if let Err(error) = timeout(Duration::from_secs(3), send_future).await { + error!("send message to worker timeout: {}", error); + } + } + }); + let _ = handler.await; + + let mut timer = tokio::time::interval(Duration::from_secs(300)); + let _ = timer.tick().await; + let (router, handler) = oneshot::channel(); + let worker_server = server.clone(); + tokio::spawn(async move { + let _ = router.send(()); + loop { + tokio::select! { + _ = timer.tick() => { + debug!("no message from worker {} for 5 mins, exit", worker_name); + let _ = worker_server.workers.write().await.remove(&worker_name).unwrap(); + break; + }, + result = outbound_r.next() => { + debug!("new message from outboud_reader {:?} of worker {}", result, worker_name); + match result { + Some(Ok(message)) => { + timer.reset(); + match message { + DMessage::RegisterWorker(register) => { + debug!("heart beat info {:?}", register); + match worker_name == register.name { + true => {}, + false => { + let worker = ServerWorker::new(tx.clone()); + worker_name = register.name; + debug!("new worker: {}", worker_name.clone()); + let _ = worker_server.workers.write().await.insert(worker_name.clone(), worker); + let data = worker_server.task_queue.write().await.pop(); + match data { + Some((task, _)) => { + let _ = tx.send(ServerMessage { name: Some(worker_name.clone()), request: task }).await.unwrap(); + }, + None => {}, + } + } + } + }, + DMessage::DRequest(_) => { + error!("invalid message from worker, should never happen"); + let _ = worker_server.workers.write().await.remove(&worker_name).unwrap(); + break; + }, + DMessage::DResponse(response) => { + debug!("new response from worker {}", response.id); + let data = worker_server.task_queue.write().await.pop(); + match data { + Some((task, _)) => { + let _ = tx.send(ServerMessage { name: None, request: task }).await.unwrap(); + }, + None => worker_server.workers.write().await.get_mut(&worker_name).unwrap().status = 1, + } + let _ = worker_server.update_account(response).await; + }, + } + }, + _ => { + warn!("unknown message"); + let _ = worker_server.workers.write().await.remove(&worker_name).unwrap(); + break; + }, + } + } + } + } + error!("worker {} main loop exit", worker_name); + }); + let _ = handler.await; + Ok(()) + } + + pub async fn update_account(&self, response: DResponse) -> Result<()> { + let address = response.address.clone(); + let task_id = response.id.clone(); + let mut update_account = false; + let mut latest_scanned_block = BlockInfo { + hash: MAINNET_GENESIS_HASH.to_string(), + sequence: MAINNET_GENESIS_SEQUENCE as u64, + }; + match self.account_mappling.write().await.get_mut(&address) { + Some(account) => { + if let Some(task_info) = self.task_mapping.read().await.get(&task_id) { + let block_hash = task_info.hash.to_string(); + if !response.data.is_empty() { + info!("account info: {:?}", account); + info!("new available block {} for account {}", block_hash, address); + account.blocks.insert( + block_hash, + response + .data + .into_iter() + .map(|hash| TransactionWithHash { hash }) + .collect(), + ); + } + account.remaining_task -= 1; + if account.remaining_task % 5000 == 0 { + update_account = true; + } + if task_info.sequence > latest_scanned_block.sequence as i64 { + latest_scanned_block = BlockInfo { + hash: task_info.hash.clone(), + sequence: task_info.sequence as u64, + }; + } + } + } + None => { + error!("bad response whose request account doesn't exist, should never happen") + } + } + if update_account { + let account_info = self + .account_mappling + .read() + .await + .get(&address) + .unwrap() + .clone(); + let set_account_head_request = RpcSetAccountHeadRequest { + account: address.clone(), + start: account_info.start_block.hash.to_string(), + end: latest_scanned_block.hash.clone(), + scan_complete: account_info.remaining_task == 0, + blocks: account_info + .blocks + .iter() + .map(|(k, v)| BlockWithHash { + hash: k.to_string(), + transactions: v.clone(), + }) + .collect(), + }; + let msg = bincode::serialize(&set_account_head_request).unwrap(); + let secp = default_secp(); + let signature = sign(&secp, &msg[..], &self.shared.secp_key.sk) + .unwrap() + .to_string(); + let request = DecryptionMessage { + message: set_account_head_request, + signature, + }; + match self.shared.server_handler.submit_scan_response(request) { + Ok(msg) => { + if msg.success && account_info.end_block.hash == latest_scanned_block.hash { + let _ = self.account_mappling.write().await.remove(&address); + } + } + Err(e) => error!("failed to submit decryption response to server, {:?}", e), + } + } + let _ = self.task_mapping.write().await.remove(&task_id); + Ok(()) + } +} diff --git a/crates/dservice/src/router.rs b/crates/dservice/src/router.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/dservice/src/router.rs @@ -0,0 +1 @@ + diff --git a/crates/dworker/Cargo.toml b/crates/dworker/Cargo.toml new file mode 100644 index 0000000..0e8585e --- /dev/null +++ b/crates/dworker/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "dworker" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +ironfish_rust = { package = "ironfish", git = "https://github.com/iron-fish/ironfish.git", branch = "master" } +anyhow = "1.0.79" +clap = { version = "4.4.13", features = ["derive"] } +tokio = { version = "1.35.1", features = ["full"] } +rayon = "1.5" +tokio-util = { version = "0.7.3", features = ["codec"] } +bytes = "1" +futures = { version = "0.3.30" } +tracing = "0.1.40" +constants = { path = "../constants" } +oreo_errors = { path = "../oreo_errors" } +db_handler = { path = "../db_handler" } +networking = { path = "../networking" } +utils = { path = "../utils" } +hex = "0.4.3" +num_cpus = "1.16.0" +gethostname = "0.4.3" +rand = "0.8.5" diff --git a/crates/dworker/src/lib.rs b/crates/dworker/src/lib.rs new file mode 100644 index 0000000..c9aba22 --- /dev/null +++ b/crates/dworker/src/lib.rs @@ -0,0 +1,206 @@ +use std::collections::HashSet; +use std::{net::SocketAddr, sync::Arc, time::Duration}; + +use anyhow::anyhow; +use futures::{SinkExt, StreamExt}; +use ironfish_rust::{IncomingViewKey, MerkleNote, OutgoingViewKey}; +use networking::socket_message::codec::{ + DMessage, DMessageCodec, DRequest, DResponse, RegisterWorker, SingleRequest, +}; +use rayon::prelude::*; +use rayon::{iter::IntoParallelIterator, ThreadPool}; +use tokio::time::timeout; +use tokio::{ + io::split, + net::TcpStream, + sync::{mpsc, oneshot}, + time::sleep, +}; +use tokio_util::codec::{FramedRead, FramedWrite}; +use tracing::{debug, error}; + +pub async fn decrypt(worker_pool: Arc, request: DRequest) -> DResponse { + let DRequest { + id, + address, + incoming_view_key, + outgoing_view_key, + decrypt_for_spender, + data, + } = request; + let mut target_hash = vec![]; + let in_vk = IncomingViewKey::from_hex(&incoming_view_key); + let out_vk = OutgoingViewKey::from_hex(&outgoing_view_key); + if in_vk.is_err() || out_vk.is_err() { + return DResponse { + id, + data: target_hash, + address, + }; + } + let in_vk = in_vk.unwrap(); + let out_vk = out_vk.unwrap(); + target_hash = worker_pool.install(move || { + let decrypted: HashSet> = data + .into_par_iter() + .map(|data| { + let SingleRequest { + serialized_note, + tx_hash, + } = data; + for note in serialized_note { + let raw = hex::decode(note); + match raw { + Ok(raw) => { + let note_enc = MerkleNote::read(&raw[..]); + if let Ok(note_enc) = note_enc { + if let Ok(received_note) = note_enc.decrypt_note_for_owner(&in_vk) { + if received_note.value() != 0 { + return Some(tx_hash); + } + } + + if decrypt_for_spender { + if let Ok(spend_note) = + note_enc.decrypt_note_for_spender(&out_vk) + { + if spend_note.value() != 0 { + return Some(tx_hash); + } + } + } + } + } + Err(_) => {} + } + } + return None; + }) + .collect(); + decrypted.into_iter().flatten().collect() + }); + DResponse { + id, + data: target_hash, + address, + } +} + +pub async fn handle_connection( + worker_pool: Arc, + stream: TcpStream, + worker_name: String, +) -> anyhow::Result<()> { + debug!("connected to scheduler"); + let (r, w) = split(stream); + let mut socket_w_handler = FramedWrite::new(w, DMessageCodec::default()); + let mut socket_r_handler = FramedRead::new(r, DMessageCodec::default()); + let (tx, mut rx) = mpsc::channel::(1024); + + // send to scheduler loop + let (router, handler) = oneshot::channel(); + tokio::spawn(async move { + let _ = router.send(()); + while let Some(message) = rx.recv().await { + debug!("write message to scheduler {:?}", message); + match message { + DMessage::DResponse(response) => { + if let Err(e) = socket_w_handler.send(DMessage::DResponse(response)).await { + error!("failed to send DResponse message, {:?}", e); + return; + } + } + DMessage::RegisterWorker(register) => { + if let Err(e) = socket_w_handler + .send(DMessage::RegisterWorker(register)) + .await + { + error!("failed to send RegisterWorker message, {:?}", e); + return; + } + } + _ => error!("invalid message to send"), + } + } + }); + let _ = handler.await; + + // receive task handler loop + let task_tx = tx.clone(); + let (router, handler) = oneshot::channel(); + tokio::spawn(async move { + let _ = router.send(()); + while let Some(Ok(message)) = socket_r_handler.next().await { + match message { + DMessage::DRequest(request) => { + debug!("new task from scheduler: {}", request.id.clone()); + let response = decrypt(worker_pool.clone(), request).await; + if let Err(e) = task_tx.send(DMessage::DResponse(response)).await { + error!("failed to send response to write channel, {}", e); + } + } + _ => { + error!("invalid message"); + break; + } + } + } + }); + let _ = handler.await; + + let heart_beat_tx = tx.clone(); + let (router, handler) = oneshot::channel(); + tokio::spawn(async move { + let _ = router.send(()); + loop { + let _ = heart_beat_tx + .send(DMessage::RegisterWorker(RegisterWorker { + name: worker_name.clone(), + })) + .await + .unwrap(); + sleep(Duration::from_secs(30)).await; + } + }); + let _ = handler.await; + Ok(()) +} + +pub async fn reconnect_tcp(addr: SocketAddr) -> anyhow::Result { + match timeout(Duration::from_secs(3), TcpStream::connect(addr)).await { + Ok(Ok(stream)) => Ok(stream), + _ => Err(anyhow!("failed to connect to dservice")), + } +} + +pub async fn start_worker(addr: SocketAddr, name: String) -> anyhow::Result<()> { + let thread_pool = rayon::ThreadPoolBuilder::new() + .num_threads(num_cpus::get()) + .build() + .unwrap(); + let worker = Arc::new(thread_pool); + let (router, handler) = oneshot::channel(); + tokio::spawn(async move { + let _ = router.send(()); + loop { + let stream = loop { + if let Ok(stream) = reconnect_tcp(addr.clone()).await { + break stream; + } + error!("can't connect to dservice, reconnect after 30 seconds"); + sleep(Duration::from_secs(30)).await; + }; + + if handle_connection(worker.clone(), stream, name.clone()) + .await + .is_err() + { + error!("failed to init networking"); + break; + } + } + }); + let _ = handler.await; + std::future::pending::<()>().await; + Ok(()) +} diff --git a/crates/dworker/src/main.rs b/crates/dworker/src/main.rs new file mode 100644 index 0000000..74312e2 --- /dev/null +++ b/crates/dworker/src/main.rs @@ -0,0 +1,44 @@ +use anyhow::Result; +use clap::Parser; +use dworker::start_worker; +use rand::Rng; +use std::net::SocketAddr; +use tracing::info; +use utils::{handle_signals, initialize_logger}; + +#[derive(Parser, Debug)] +#[command(version, about)] +struct Cli { + /// scheduler to connect to + #[arg(short, long)] + address: SocketAddr, + /// worker name + #[arg(short, long)] + name: Option, + /// Set your logger level + #[clap(short, long, default_value = "0")] + pub verbosity: u8, +} + +#[tokio::main] +async fn main() -> Result<()> { + let mut args = Cli::parse(); + initialize_logger(args.verbosity); + handle_signals().await?; + if args.name.is_none() { + args.name = Some( + format!( + "dworker-{:?}-{}", + gethostname::gethostname(), + rand::thread_rng().gen::() + ) + .into(), + ); + } + info!( + "Start connecting to scheduler: {:?} with name {:?}", + args.address, args.name + ); + start_worker(args.address, args.name.unwrap()).await?; + Ok(()) +} diff --git a/crates/networking/.gitignore b/crates/networking/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/crates/networking/.gitignore @@ -0,0 +1 @@ +/target diff --git a/crates/networking/Cargo.toml b/crates/networking/Cargo.toml new file mode 100644 index 0000000..a0a496c --- /dev/null +++ b/crates/networking/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "networking" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde = { version = "1.0.199", features = ["derive"] } +serde_json = "1.0.111" +constants = { path = "../constants" } +oreo_errors = { path = "../oreo_errors" } +db_handler = { path = "../db_handler" } +anyhow = "1.0.82" +ureq = { version = "2.9.1", features = ["json"] } +axum = "0.7.3" +tracing = "0.1.40" +tokio-util = { version = "0.7.3", features = ["codec"] } +bytes = "1" +uuid = { version = "1.8.0", features = [ + "v4", # Lets you generate random UUIDs + "fast-rng", # Use a faster (but still sufficiently random) RNG + "macro-diagnostics", # Enable better diagnostics for compile-time UUIDs +] } + +[dev-dependencies] +tokio = { version = "1.35.1", features = ["full"] } diff --git a/crates/networking/src/decryption_message.rs b/crates/networking/src/decryption_message.rs new file mode 100644 index 0000000..a0aad89 --- /dev/null +++ b/crates/networking/src/decryption_message.rs @@ -0,0 +1,24 @@ +use serde::{Deserialize, Serialize}; + +use crate::rpc_abi::BlockInfo; +pub use crate::rpc_abi::RpcSetAccountHeadRequest as ScanResponse; + +#[derive(Debug, Deserialize, Serialize)] +pub struct DecryptionMessage { + pub message: T, + pub signature: String, +} + +#[derive(Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct ScanRequest { + pub in_vk: String, + pub out_vk: String, + pub address: String, + pub head: Option, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct SuccessResponse { + pub success: bool, +} diff --git a/crates/networking/src/lib.rs b/crates/networking/src/lib.rs new file mode 100644 index 0000000..e8c0eb9 --- /dev/null +++ b/crates/networking/src/lib.rs @@ -0,0 +1,40 @@ +pub mod decryption_message; +pub mod orescriptions; +pub mod rpc_abi; +pub mod rpc_handler; +pub mod server_handler; +pub mod socket_message; +pub mod stream; +pub mod web_abi; + +use db_handler::{DBTransaction, InnerBlock, Json}; +use rpc_abi::RpcBlock; +pub use ureq; + +impl RpcBlock { + pub fn to_inner(self) -> InnerBlock { + let RpcBlock { + hash, + sequence, + previous_block_hash: _, + transactions, + } = self; + InnerBlock { + hash, + sequence: sequence as i64, + transactions: Json( + transactions + .into_iter() + .map(|tx| DBTransaction { + hash: tx.hash, + serialized_notes: tx + .notes + .into_iter() + .map(|note| note.serialized) + .collect(), + }) + .collect(), + ), + } + } +} diff --git a/src/orescriptions/mod.rs b/crates/networking/src/orescriptions.rs similarity index 92% rename from src/orescriptions/mod.rs rename to crates/networking/src/orescriptions.rs index d4e57b1..c3c822f 100644 --- a/src/orescriptions/mod.rs +++ b/crates/networking/src/orescriptions.rs @@ -1,14 +1,13 @@ +use constants::{IRON_NATIVE_ASSET, OREOSRIPTIONS_ENDPOINT, OREOS_VALUE}; use serde::{Deserialize, Serialize}; -use crate::{ - constants::{IRON_NATIVE_ASSET, OREOSRIPTIONS_ENDPOINT, OREOS_VALUE}, - rpc_handler::abi::AssetBalance, -}; +use crate::rpc_abi::AssetBalance; #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Ores { pub asset_id: String, + pub mint_height: u32, pub tick: String, pub tick_index: u32, pub data: String, diff --git a/src/rpc_handler/abi.rs b/crates/networking/src/rpc_abi.rs similarity index 61% rename from src/rpc_handler/abi.rs rename to crates/networking/src/rpc_abi.rs index ccaf1cb..8686f91 100644 --- a/src/rpc_handler/abi.rs +++ b/crates/networking/src/rpc_abi.rs @@ -1,12 +1,9 @@ use axum::{response::IntoResponse, Json}; +use constants::IRON_NATIVE_ASSET; use serde::{Deserialize, Serialize}; -use serde_json::json; +use ureq::json; -use crate::{ - constants::{IRON_NATIVE_ASSET, MAINNET_GENESIS_HASH, MAINNET_GENESIS_SEQUENCE}, - db_handler::address_to_name, - orescriptions::{get_ores, is_ores_local, Ores}, -}; +use crate::orescriptions::{get_ores, is_ores_local, Ores}; #[derive(Debug, Deserialize, Serialize)] pub struct RpcResponse { @@ -14,6 +11,11 @@ pub struct RpcResponse { pub data: T, } +#[derive(Debug, Deserialize, Serialize)] +pub struct RpcResponseStream { + pub data: T +} + impl IntoResponse for RpcResponse { fn into_response(self) -> axum::response::Response { Json(json!({"code": 200, "data": self.data})).into_response() @@ -21,63 +23,98 @@ impl IntoResponse for RpcResponse { } #[derive(Debug, Deserialize, Serialize, Clone)] -pub struct CreateAccountOpt { +pub struct BlockInfo { pub hash: String, pub sequence: u64, } #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -pub struct ImportAccountReq { +pub struct RpcImportAccountRequest { pub version: u8, pub name: String, pub view_key: String, pub incoming_view_key: String, pub outgoing_view_key: String, pub public_address: String, - pub created_at: Option, + pub created_at: Option, + pub spending_key: Option, } #[derive(Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct ExportAccountRep { +pub struct RpcImportAccountResponse { + pub name: String, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct RpcExportAccountResponse { pub account: String, } -impl ImportAccountReq { - pub fn to_account(&self) -> crate::db_handler::Account { - let (create_head, create_hash) = match &self.created_at { - Some(creat) => (Some(creat.sequence as i64), Some(creat.hash.clone())), - None => (None, None), - }; - crate::db_handler::Account { - address: self.public_address.clone(), - name: address_to_name(&self.public_address), - create_head, - create_hash: create_hash.clone(), - head: create_head.unwrap_or(MAINNET_GENESIS_SEQUENCE), - hash: create_hash.unwrap_or(MAINNET_GENESIS_HASH.to_string()), - in_vk: self.incoming_view_key.clone(), - out_vk: self.outgoing_view_key.clone(), - vk: self.view_key.clone(), - } - } +#[derive(Debug, Deserialize, Serialize)] +pub struct RpcRemoveAccountRequest { + pub account: String, + pub confirm: Option, + pub wait: Option, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct RpcRemoveAccountResponse { + pub removed: bool, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct RpcGetAccountStatusRequest { + pub account: String, } #[derive(Debug, Deserialize, Serialize)] -pub struct ImportAccountRep { +pub struct AccountStatus { pub name: String, + pub head: Option, } #[derive(Debug, Deserialize, Serialize)] -pub struct RemoveAccountReq { +pub struct RpcGetAccountStatusResponse { + pub account: AccountStatus, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct RpcSetScanningRequest { pub account: String, - pub confirm: Option, - pub wait: Option, + pub enabled: bool, +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct TransactionWithHash { + pub hash: String, +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct BlockWithHash { + pub hash: String, + pub transactions: Vec, +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct RpcSetAccountHeadRequest { + pub account: String, + pub start: String, + pub end: String, + pub blocks: Vec, + pub scan_complete: bool, } #[derive(Debug, Deserialize, Serialize)] -pub struct GetBalancesReq { +#[serde(rename_all = "camelCase")] +pub struct RpcResetAccountRequest { + pub account: String, + pub reset_created_at: Option, + pub reset_scanning_enabled: Option, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct RpcGetBalancesRequest { pub account: String, pub confirmations: Option, } @@ -101,12 +138,12 @@ pub struct AssetBalance { } #[derive(Debug, Deserialize, Serialize)] -pub struct GetBalancesRep { +pub struct RpcGetBalancesResponse { pub account: String, pub balances: Vec, } -impl GetBalancesRep { +impl RpcGetBalancesResponse { pub fn verified_asset(base: Self) -> Self { Self { balances: base @@ -144,15 +181,18 @@ pub struct OutPut { pub public_address: String, pub amount: String, pub memo: Option, + pub memo_hex: Option, pub asset_id: Option, } impl OutPut { pub fn from(base: OutPut) -> Self { let memo = Some(base.memo.unwrap_or("".into())); + let memo_hex = Some(base.memo_hex.unwrap_or("".into())); let asset_id = Some(base.asset_id.unwrap_or(IRON_NATIVE_ASSET.into())); Self { memo, + memo_hex, asset_id, ..base } @@ -177,7 +217,7 @@ pub struct BurnAsset { #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -pub struct CreateTxReq { +pub struct RpcCreateTxRequest { pub account: String, pub fee: Option, pub expiration_delta: Option, @@ -187,30 +227,29 @@ pub struct CreateTxReq { } #[derive(Debug, Deserialize, Serialize)] -pub struct CreateTxRep { +pub struct RpcCreateTxResponse { pub transaction: String, } #[derive(Debug, Deserialize, Serialize)] -pub struct BroadcastTxReq { +pub struct RpcAddTxRequest { pub transaction: String, } #[derive(Debug, Deserialize, Serialize)] -pub struct BroadcastTxRep { +pub struct RpcAddTxResponse { pub hash: String, pub accepted: bool, - pub broadcasted: bool, } #[derive(Debug, Deserialize, Serialize)] -pub struct GetTransactionsReq { +pub struct RpcGetTransactionsRequest { pub account: String, pub limit: Option, pub reverse: Option, } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, Clone)] #[serde(rename_all = "camelCase")] pub struct TransactionStatus { pub hash: String, @@ -223,19 +262,18 @@ pub struct TransactionStatus { } #[derive(Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct GetTransactionsRep { +pub struct RpcGetTransactionsResponse { pub transactions: Vec, } #[derive(Debug, Deserialize, Serialize)] -pub struct GetAccountTransactionReq { +pub struct RpcGetAccountTransactionRequest { pub account: String, pub hash: String, pub notes: Option, } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, Clone)] #[serde(rename_all = "camelCase")] pub struct AssetBalanceDelta { pub asset_id: String, @@ -265,37 +303,83 @@ pub struct TransactionWithNotes { } #[derive(Debug, Deserialize, Serialize)] -pub struct GetAccountTransactionRep { +pub struct RpcGetAccountTransactionResponse { pub account: String, pub transaction: Option, } #[derive(Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct RpcAsset { - pub id: String, - pub name: String, - pub metadata: String, - pub verification: String, +pub struct RpcGetBlockRequest { + pub sequence: i64, + pub serialized: Option, } #[derive(Debug, Deserialize, Serialize)] -pub struct GetNoteWitnessReq { - pub index: u32, - pub confirmations: Option, +pub struct BlockIdentifier { + pub index: String, + pub hash: String, } #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -pub struct AuthPath { - pub side: String, - pub hash_of_sibling: String, +pub struct RpcGetLatestBlockResponse { + pub current_block_identifier: BlockIdentifier, + pub genesis_block_identifier: BlockIdentifier, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct RpcEncryptedNote { + pub hash: String, + pub serialized: String, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct RpcTransaction { + pub hash: String, + pub notes: Vec, } #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -pub struct GetNoteWitnessRep { - pub tree_size: u32, - pub root_hash: String, - pub auth_path: Vec, +pub struct RpcBlock { + pub hash: String, + pub sequence: u32, + pub previous_block_hash: String, + pub transactions: Vec, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct RpcGetBlockResponse { + pub block: RpcBlock, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct RpcGetBlocksRequest { + pub start: u64, + pub end: u64, + pub serialized: bool, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct BlockItem { + pub block: RpcBlock, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct RpcGetBlocksResponse { + pub blocks: Vec, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct SendTransactionRequest { + pub account: String, + pub fee: String, + pub expiration_delta: u32, + pub outputs: Vec, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct SendTransactionResponse { + pub account: String, + pub hash: String, } diff --git a/crates/networking/src/rpc_handler/handler.rs b/crates/networking/src/rpc_handler/handler.rs new file mode 100644 index 0000000..7c4190b --- /dev/null +++ b/crates/networking/src/rpc_handler/handler.rs @@ -0,0 +1,299 @@ +use std::{fmt::Debug, time::Duration}; + +use oreo_errors::OreoError; +use serde::Deserialize; +use serde_json::json; +use tracing::debug; +use ureq::{Agent, AgentBuilder, Error, Response}; + +use crate::{ + rpc_abi::{ + RpcAddTxRequest, RpcAddTxResponse, RpcCreateTxRequest, RpcCreateTxResponse, + RpcExportAccountResponse, RpcGetAccountStatusRequest, RpcGetAccountStatusResponse, + RpcGetAccountTransactionRequest, RpcGetAccountTransactionResponse, RpcGetBalancesRequest, + RpcGetBalancesResponse, RpcGetBlockRequest, RpcGetBlockResponse, RpcGetBlocksRequest, + RpcGetBlocksResponse, RpcGetLatestBlockResponse, RpcGetTransactionsRequest, + RpcGetTransactionsResponse, RpcImportAccountRequest, RpcImportAccountResponse, + RpcRemoveAccountRequest, RpcRemoveAccountResponse, RpcResetAccountRequest, RpcResponse, + RpcSetAccountHeadRequest, RpcSetScanningRequest, SendTransactionRequest, + SendTransactionResponse, TransactionStatus, + }, + rpc_handler::RpcError, stream::ResponseExt, +}; + +#[derive(Debug, Clone)] +pub struct RpcHandler { + pub endpoint: String, + pub agent: Agent, +} + +impl RpcHandler { + pub fn new(endpoint: String) -> Self { + Self { + endpoint, + agent: AgentBuilder::new() + .timeout_read(Duration::from_secs(5)) + .timeout_write(Duration::from_secs(5)) + .build(), + } + } + + pub fn import_account( + &self, + request: RpcImportAccountRequest, + ) -> Result, OreoError> { + let path = format!("http://{}/wallet/importAccount", self.endpoint); + let account_str = serde_json::to_string(&request).map_err(|_|OreoError::InternalRpcError("JSON serialization failed".to_string()))?; + let resp = self + .agent + .clone() + .post(&path) + .send_json(ureq::json!({"account": account_str})); + handle_response(resp) + } + + pub fn export_account( + &self, + account: String, + ) -> Result, OreoError> { + let path = format!("http://{}/wallet/exportAccount", self.endpoint); + let resp = self + .agent + .clone() + .post(&path) + .send_json(json!({"account": account, "format": "JSON".to_string()})); + handle_response(resp) + } + + pub fn remove_account( + &self, + request: RpcRemoveAccountRequest, + ) -> Result, OreoError> { + debug!("req: {:?}", request); + let path = format!("http://{}/wallet/removeAccount", self.endpoint); + let resp = self + .agent + .clone() + .post(&path) + .send_json(&request) + .map(|res| match res.status() { + 200 => Response::new(200, "OK", "{\"status\":200,\"data\":{\"removed\":true}}") + .unwrap(), + _ => res, + }); + handle_response(resp) + } + + pub fn get_account_status( + &self, + request: RpcGetAccountStatusRequest, + ) -> Result, OreoError> { + let path = format!("http://{}/wallet/getAccountStatus", self.endpoint); + let resp = self.agent.clone().post(&path).send_json(&request); + handle_response(resp) + } + + pub fn set_scanning( + &self, + request: RpcSetScanningRequest, + ) -> Result>, OreoError> { + let path = format!("http://{}/wallet/setScanning", self.endpoint); + let resp = self.agent.clone().post(&path).send_json(&request); + handle_response(resp) + } + + pub fn set_account_head( + &self, + request: RpcSetAccountHeadRequest, + ) -> Result>, OreoError> { + let path = format!("http://{}/wallet/setAccountHead", self.endpoint); + let resp = self.agent.clone().post(&path).send_json(&request); + handle_response(resp) + } + + pub fn reset_account( + &self, + request: RpcResetAccountRequest, + ) -> Result>, OreoError> { + let path = format!("http://{}/wallet/resetAccount", self.endpoint); + let resp = self.agent.clone().post(&path).send_json(&request); + handle_response(resp) + } + + pub fn get_balances( + &self, + request: RpcGetBalancesRequest, + ) -> Result, OreoError> { + let path = format!("http://{}/wallet/getBalances", self.endpoint); + let resp = self.agent.clone().post(&path).send_json(&request); + handle_response(resp) + } + + pub fn get_account_transaction( + &self, + request: RpcGetAccountTransactionRequest, + ) -> Result, OreoError> { + let path = format!("http://{}/wallet/getAccountTransaction", self.endpoint); + let resp = self.agent.clone().post(&path).send_json(&request); + handle_response(resp) + } + + pub fn get_transactions( + &self, + request: RpcGetTransactionsRequest, + ) -> Result, OreoError> { + let path = format!("http://{}/wallet/getAccountTransactions", self.endpoint); + let resp = self.agent.clone().post(&path).send_json(&request); + + match resp { + Ok(response) => { + let transactions: Result, OreoError> = response + .into_stream::() + .collect(); + + Ok(RpcResponse { + status: 200, + data: RpcGetTransactionsResponse { + transactions: transactions?, + }, + }) + } + Err(e) => Err(OreoError::InternalRpcError(e.to_string())), + } + } + + pub fn create_transaction( + &self, + request: RpcCreateTxRequest, + ) -> Result, OreoError> { + let path = format!("http://{}/wallet/createTransaction", self.endpoint); + let resp = self.agent.clone().post(&path).send_json(&request); + handle_response(resp) + } + + pub fn add_transaction( + &self, + request: RpcAddTxRequest, + ) -> Result, OreoError> { + let path = format!("http://{}/wallet/addTransaction", self.endpoint); + let resp = self.agent.clone().post(&path).send_json(&request); + handle_response(resp) + } + + pub fn get_latest_block(&self) -> Result, OreoError> { + let path = format!("http://{}/chain/getChainInfo", self.endpoint); + let resp = self.agent.clone().get(&path).call(); + handle_response(resp) + } + + pub fn get_block(&self, sequence: i64) -> Result, OreoError> { + let path = format!("http://{}/chain/getBlock", self.endpoint); + let resp = self + .agent + .clone() + .post(&path) + .send_json(RpcGetBlockRequest { + sequence, + serialized: Some(true), + }); + handle_response(resp) + } + + pub fn get_blocks( + &self, + start: u64, + end: u64, + ) -> Result, OreoError> { + let path = format!("http://{}/chain/getBlocks", self.endpoint); + let resp = self + .agent + .clone() + .post(&path) + .send_json(RpcGetBlocksRequest { start, end, serialized: true }); + handle_response(resp) + } + + pub fn send_transaction( + &self, + request: SendTransactionRequest, + ) -> Result, OreoError> { + let path = format!("http://{}/wallet/sendTransaction", self.endpoint); + let resp = self.agent.clone().post(&path).send_json(request); + handle_response(resp) + } +} + +pub fn handle_response Deserialize<'a>>( + resp: Result, +) -> Result, OreoError> { + let res = match resp { + Ok(response) => match response.into_json::>() { + Ok(data) => Ok(data), + Err(e) => Err(RpcError { + code: "Unknown".into(), + status: 606, + message: e.to_string(), + }), + }, + Err(ureq::Error::Status(_code, response)) => match response.into_json::() { + Ok(data) => Err(data), + Err(e) => Err(RpcError { + code: "Unknown".into(), + status: 606, + message: e.to_string(), + }), + }, + Err(e) => Err(RpcError { + code: "Unknown".into(), + status: 606, + message: e.to_string(), + }), + }; + debug!("Handle rpc response: {:?}", res); + match res { + Ok(data) => Ok(data), + Err(e) => Err(OreoError::try_from(e).unwrap()), + } +} + +#[cfg(test)] +mod tests { + use crate::rpc_abi::{RpcResetAccountRequest, RpcSetScanningRequest}; + + use super::RpcHandler; + + #[test] + pub fn get_block_should_work() { + let rpc_handler = RpcHandler::new("127.0.0.1:8021".into()); + let block = rpc_handler.get_latest_block().unwrap().data; + println!("{:?}", block); + } + + #[test] + pub fn get_blocks_should_work() { + let rpc_handler = RpcHandler::new("127.0.0.1:8021".into()); + let blocks = rpc_handler.get_blocks(3, 12).unwrap().data; + println!("{:?}", blocks.blocks); + } + + #[test] + pub fn set_scanning_should_work() { + let rpc_handler = RpcHandler::new("127.0.0.1:8021".into()); + let result = rpc_handler.set_scanning(RpcSetScanningRequest { + account: "test".to_string(), + enabled: false, + }); + assert!(result.is_ok()); + } + + #[test] + pub fn reset_account_should_work() { + let rpc_handler = RpcHandler::new("127.0.0.1:8021".into()); + let result = rpc_handler.reset_account(RpcResetAccountRequest { + account: "test".to_string(), + reset_created_at: Some(false), + reset_scanning_enabled: Some(false), + }); + assert!(result.is_ok()); + } +} diff --git a/src/rpc_handler/mod.rs b/crates/networking/src/rpc_handler/mod.rs similarity index 75% rename from src/rpc_handler/mod.rs rename to crates/networking/src/rpc_handler/mod.rs index abd069d..8a9cf01 100644 --- a/src/rpc_handler/mod.rs +++ b/crates/networking/src/rpc_handler/mod.rs @@ -1,11 +1,10 @@ -pub mod abi; +use oreo_errors::OreoError; +use serde::{Deserialize, Serialize}; + mod handler; pub use handler::*; - -use serde::{Deserialize, Serialize}; - -use crate::error::OreoError; +use tracing::error; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct RpcError { @@ -24,7 +23,10 @@ impl TryFrom for OreoError { // Should never happen return Ok(OreoError::Duplicate("0x00".to_string())); } - _ => Ok(OreoError::InternalRpcError), + _ => { + error!("Rpc error: {:?}", value); + return Ok(OreoError::InternalRpcError(value.message)); + } } } } diff --git a/crates/networking/src/server_handler.rs b/crates/networking/src/server_handler.rs new file mode 100644 index 0000000..0108bfc --- /dev/null +++ b/crates/networking/src/server_handler.rs @@ -0,0 +1,58 @@ +use std::{fmt::Debug, time::Duration}; + +use oreo_errors::OreoError; +use serde::Deserialize; +use tracing::debug; +use ureq::{Agent, AgentBuilder, Error, Response}; + +use crate::decryption_message::{DecryptionMessage, ScanRequest, ScanResponse, SuccessResponse}; + +#[derive(Debug, Clone)] +pub struct ServerHandler { + pub endpoint: String, + pub agent: Agent, +} + +impl ServerHandler { + pub fn new(endpoint: String) -> Self { + Self { + endpoint, + agent: AgentBuilder::new() + .timeout_read(Duration::from_secs(5)) + .timeout_write(Duration::from_secs(5)) + .build(), + } + } + + pub fn submit_scan_request( + &self, + request: DecryptionMessage, + ) -> Result { + let path = format!("http://{}/scanAccount", self.endpoint); + let resp = self.agent.clone().post(&path).send_json(&request); + handle_response(resp) + } + + pub fn submit_scan_response( + &self, + request: DecryptionMessage, + ) -> Result { + let path = format!("http://{}/updateScan", self.endpoint); + let resp = self.agent.clone().post(&path).send_json(&request); + handle_response(resp) + } +} + +fn handle_response Deserialize<'a>>( + resp: Result, +) -> Result { + let res = match resp { + Ok(response) => match response.into_json::() { + Ok(data) => Ok(data), + Err(_) => Err(OreoError::DServerError), + }, + _ => Err(OreoError::DServerError), + }; + debug!("Handle rpc response: {:?}", res); + res +} diff --git a/crates/networking/src/socket_message/codec.rs b/crates/networking/src/socket_message/codec.rs new file mode 100644 index 0000000..5c31f65 --- /dev/null +++ b/crates/networking/src/socket_message/codec.rs @@ -0,0 +1,122 @@ +use anyhow::Result; +use bytes::{BufMut, BytesMut}; +use db_handler::{Account, DBTransaction}; +use serde::{Deserialize, Serialize}; +use std::io::Write; +use tokio_util::codec::{Decoder, Encoder}; +use uuid::Uuid; + +use crate::decryption_message::ScanRequest; + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub struct RegisterWorker { + pub name: String, +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Hash, Eq)] +#[serde(rename_all = "camelCase")] +pub struct SingleRequest { + pub serialized_note: Vec, + pub tx_hash: String, +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Hash, Eq)] +#[serde(rename_all = "camelCase")] +pub struct DRequest { + pub id: String, + pub address: String, + pub incoming_view_key: String, + pub outgoing_view_key: String, + pub decrypt_for_spender: bool, + pub data: Vec, +} + +impl DRequest { + pub fn new(account: &Account, transaction: DBTransaction) -> Self { + let tx_hash = transaction.hash; + let serializeds = transaction.serialized_notes; + let data = SingleRequest { + tx_hash, + serialized_note: serializeds, + }; + Self { + id: Uuid::new_v4().to_string(), + address: account.address.clone(), + incoming_view_key: account.in_vk.clone(), + outgoing_view_key: account.out_vk.clone(), + decrypt_for_spender: true, + data: vec![data], + } + } + + pub fn from_transactions(account: &ScanRequest, transactions: Vec) -> Self { + let data = transactions + .into_iter() + .map(|tx| SingleRequest { + tx_hash: tx.hash.to_string(), + serialized_note: tx.serialized_notes, + }) + .collect(); + Self { + id: Uuid::new_v4().to_string(), + address: account.address.clone(), + incoming_view_key: account.in_vk.clone(), + outgoing_view_key: account.out_vk.clone(), + decrypt_for_spender: true, + data, + } + } +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub struct DResponse { + pub address: String, + pub id: String, + pub data: Vec, +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] +pub enum DMessage { + RegisterWorker(RegisterWorker), + DRequest(DRequest), + DResponse(DResponse), +} + +#[derive(Default)] +pub struct DMessageCodec { + cursor: usize, +} + +impl Encoder for DMessageCodec { + type Error = anyhow::Error; + fn encode(&mut self, message: DMessage, dst: &mut BytesMut) -> Result<(), Self::Error> { + let json_string = serde_json::to_string(&message).unwrap(); + dst.writer().write_all(json_string.as_bytes())?; + dst.writer().write_all("\n".as_bytes())?; + Ok(()) + } +} + +impl Decoder for DMessageCodec { + type Error = anyhow::Error; + type Item = DMessage; + + fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error> { + let mut i = self.cursor; + while i < src.len() { + if src[i] == 10u8 { + self.cursor = 0; + let mut data = src.split_to(i + 1); + unsafe { + data.set_len(i); + } + src.reserve(100); + let message = serde_json::from_slice(&data[..])?; + return Ok(Some(message)); + } + i += 1; + } + self.cursor = i; + Ok(None) + } +} diff --git a/crates/networking/src/socket_message/mod.rs b/crates/networking/src/socket_message/mod.rs new file mode 100644 index 0000000..7142de5 --- /dev/null +++ b/crates/networking/src/socket_message/mod.rs @@ -0,0 +1 @@ +pub mod codec; diff --git a/crates/networking/src/stream.rs b/crates/networking/src/stream.rs new file mode 100644 index 0000000..cdc8b5f --- /dev/null +++ b/crates/networking/src/stream.rs @@ -0,0 +1,162 @@ +use std::io::{BufRead, BufReader, Read}; +use std::marker::PhantomData; + +use oreo_errors::OreoError; +use serde::de::DeserializeOwned; +use serde::{Deserialize, Serialize}; +use ureq::Response; + +use crate::rpc_abi::RpcResponseStream; + +pub struct StreamReader { + reader: BufReader, + _marker: PhantomData, +} + +#[derive(Deserialize, Serialize)] +#[serde(untagged)] +enum ResponseItem { + Data(RpcResponseStream), + Status { status: u16 }, +} + +impl StreamReader where T: DeserializeOwned, R: Read { + pub fn new(reader: R) -> Self { + Self { + reader: BufReader::new(reader), + _marker: PhantomData, + } + } + + fn read_item(&mut self) -> Result>, OreoError> { + let mut item = Vec::new(); + loop { + let bytes_read = self.reader.read_until(b'\x0c', &mut item) + .map_err(|e| OreoError::RpcStreamError(e.to_string()))?; + if bytes_read == 0 { + break; + } + if item.last() == Some(&b'\x0c') { + item.pop(); + break; + } + } + match item.len() { + 0 => Ok(None), + _ => Ok(Some(item)) + } + } + + + /// Parses a chunk of data into a `ResponseItem`. + fn parse_item(&self, chunk: &[u8]) -> Result, OreoError> { + match serde_json::from_slice::>(chunk) { + Ok(ResponseItem::Data(item)) => Ok(Some(item.data)), + Ok(ResponseItem::Status { status: 200 }) => Ok(None), + Ok(ResponseItem::Status { status }) => Err(OreoError::RpcStreamError(format!("Received error status: {}", status))), + Err(e) => { + let err_str = format!("Failed to parse JSON object: {:?}", e); + Err(OreoError::RpcStreamError(err_str)) + } + } + } +} + +impl Iterator for StreamReader +where + T: DeserializeOwned, + R: Read, +{ + type Item = Result; + + fn next(&mut self) -> Option { + match self.read_item() { + Ok(Some(chunk)) => match self.parse_item(&chunk) { + Ok(Some(data)) => Some(Ok(data)), + Ok(None) => None, // End of stream + Err(e) => Some(Err(e)), + }, + Ok(None) => None, // EOF reached + Err(e) => Some(Err(e)), + } + } +} + +pub trait ResponseExt { + fn into_stream(self) -> StreamReader>; +} + +impl ResponseExt for Response { + fn into_stream(self) -> StreamReader> { + let reader = self.into_reader(); + StreamReader::new(Box::new(reader)) + } +} + +#[cfg(test)] +mod tests { + use crate::rpc_abi::TransactionStatus; + + use super::*; + + #[test] + fn test_stream_reader_with_status() { + // Prepare some test data. + let transaction_status = TransactionStatus { + hash: "cde4c2a5bc7cb6cbad93a414ff76176e07412fbd48f2f3d1ee8f7fc1238626a5".to_string(), + fee: "1".to_string(), + r#type: "type".to_string(), + status: "status".to_string(), + block_sequence: Some(1), + timestamp: 1, + asset_balance_deltas: Vec::new(), + }; + let item1: RpcResponseStream = RpcResponseStream { data: transaction_status.clone() }; + let response1 = ResponseItem::Data(item1); + + let status = ResponseItem::::Status { status: 200 }; + + let json1 = serde_json::to_string(&response1).unwrap(); + let json_status = serde_json::to_string(&status).unwrap(); + + // Add \x0c separators + let data = format!("{}\x0c{}\x0c", json1, json_status); + + let reader = StreamReader::::new(data.as_bytes()); + let items: Vec<_> = reader.collect(); + let returned_status = items[0].as_ref().unwrap(); + assert_eq!(returned_status.hash, transaction_status.hash); + assert_eq!(returned_status.fee, transaction_status.fee); + assert_eq!(returned_status.r#type, transaction_status.r#type); + assert_eq!(returned_status.status, transaction_status.status); + assert_eq!(returned_status.block_sequence, transaction_status.block_sequence); + assert_eq!(returned_status.timestamp, transaction_status.timestamp); + assert_eq!(returned_status.asset_balance_deltas.len(), transaction_status.asset_balance_deltas.len()); + } + + #[test] + fn test_stream_reader_with_error_status() { + // Prepare some test data. + let item1 = RpcResponseStream { data: 42u32 }; + let response1 = ResponseItem::Data(item1); + + let status = ResponseItem::::Status { status: 500 }; + + let json1 = serde_json::to_string(&response1).unwrap(); + let json_status = serde_json::to_string(&status).unwrap(); + + // Add \x0c separators + let data = format!("{}\x0c{}\x0c", json1, json_status); + + let reader = StreamReader::::new(data.as_bytes()); + let items: Vec<_> = reader.collect(); + + assert_eq!(items.len(), 2); + assert_eq!(items[0], Ok(42u32)); + + match &items[1] { + Err(OreoError::RpcStreamError(msg)) => assert!(msg.contains("Received error status: 500")), + _ => panic!("Expected error with status code 500"), + } + } + } \ No newline at end of file diff --git a/src/web_handlers/abi.rs b/crates/networking/src/web_abi.rs similarity index 52% rename from src/web_handlers/abi.rs rename to crates/networking/src/web_abi.rs index 6ee6863..4eba0a2 100644 --- a/src/web_handlers/abi.rs +++ b/crates/networking/src/web_abi.rs @@ -1,27 +1,29 @@ +use constants::MAINNET_GENESIS_SEQUENCE; +use db_handler::{address_to_name, Account}; +use oreo_errors::OreoError; use serde::{Deserialize, Serialize}; -use crate::{ - constants::{MAINNET_GENESIS_HASH, MAINNET_GENESIS_SEQUENCE}, - db_handler::{address_to_name, Account}, - error::OreoError, - rpc_handler::abi::{ - AssetBalanceDelta, CreateAccountOpt, GetAccountTransactionRep, RpcNote, - TransactionWithNotes, - }, +use crate::rpc_abi::{ + AssetBalanceDelta, BlockInfo, RpcGetAccountTransactionResponse, RpcNote, TransactionWithNotes, }; #[derive(Debug, Deserialize, Serialize, Clone)] #[serde(rename_all = "camelCase")] -pub struct ImportAccountReq { +pub struct ImportAccountRequest { pub view_key: String, pub incoming_view_key: String, pub outgoing_view_key: String, pub public_address: String, - pub created_at: Option, + pub created_at: Option, } -impl ImportAccountReq { - pub fn to_account(&self) -> Account { +#[derive(Debug, Deserialize, Serialize)] +pub struct ImportAccountResponse { + pub name: String, +} + +impl ImportAccountRequest { + pub fn to_account(&self, genesis_hash: String) -> Account { let (create_head, create_hash) = match &self.created_at { Some(creat) => (Some(creat.sequence as i64), Some(creat.hash.clone())), None => (None, None), @@ -32,73 +34,15 @@ impl ImportAccountReq { create_head, create_hash: create_hash.clone(), head: create_head.unwrap_or(MAINNET_GENESIS_SEQUENCE), - hash: create_hash.unwrap_or(MAINNET_GENESIS_HASH.to_string()), + hash: create_hash.unwrap_or(genesis_hash), in_vk: self.incoming_view_key.clone(), out_vk: self.outgoing_view_key.clone(), vk: self.view_key.clone(), + need_scan: false, } } } -#[derive(Debug, Deserialize, Serialize)] -pub struct ImportAccountRep { - pub name: String, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct RemoveAccountReq { - pub account: String, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct RemoveAccountRep { - pub removed: bool, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct GenerateProofReq { - pub spend_circuits: Vec>, - pub output_circuits: Vec>, - pub mint_asset_circuits: Vec>, -} - -#[derive(Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct GenerateProofRep { - pub spend_proofs: Vec>, - pub output_proofs: Vec>, - pub mint_asset_proofs: Vec>, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct GetAccountStatusReq { - pub account: String, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct AccountStatus { - pub name: String, - pub head: Option, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct GetAccountStatusRep { - pub account: AccountStatus, -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct BlockIdentifier { - pub index: String, - pub hash: String, -} - -#[derive(Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct GetLatestBlockRep { - pub current_block_identifier: BlockIdentifier, -} - #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct TransactionDetail { @@ -117,8 +61,6 @@ pub struct TransactionDetail { impl TransactionDetail { pub fn from(tx: TransactionWithNotes) -> Result { - // we handle send/receive transactions only now - // todo: miner transaction let TransactionWithNotes { hash, fee, @@ -129,20 +71,11 @@ impl TransactionDetail { asset_balance_deltas, notes, } = tx; - let mut notes = notes.unwrap(); - let note = match notes - .iter() - .filter(|asset| asset.owner != asset.sender) - .collect::>() - .len() - { - 0 => notes.pop(), - _ => notes - .into_iter() - .filter(|asset| asset.owner != asset.sender) - .collect::>() - .pop(), - }; + let notes = notes.unwrap(); + let note = notes.iter() + .find(|asset| asset.owner != asset.sender) + .or_else(|| notes.iter().find(|note| !note.memo.is_empty())) + .or_else(|| notes.first()); match note { Some(RpcNote { value, @@ -162,31 +95,46 @@ impl TransactionDetail { memo: Some(memo.into()), value: value.into(), }), - None => Err(OreoError::InternalRpcError), + None => Err(OreoError::InternalRpcError("No note found".into())), } } } #[derive(Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct GetTransactionDetail { +pub struct GetTransactionDetailResponse { pub account: String, pub transaction: TransactionDetail, } -impl GetTransactionDetail { - pub fn from_rpc_data(data: GetAccountTransactionRep) -> Result { - if data.transaction.is_none() { - return Err(OreoError::TransactionNotFound); - } - let tx = data.transaction.unwrap(); - let transaction_detail = TransactionDetail::from(tx); - match transaction_detail { - Ok(detail) => Ok(Self { +impl GetTransactionDetailResponse { + pub fn from_rpc_data(data: RpcGetAccountTransactionResponse) -> Result { + match data.transaction { + Some(tx) => TransactionDetail::from(tx).map(|x| Self { account: data.account, - transaction: detail, + transaction: x, }), - Err(e) => Err(e), + None => Err(OreoError::TransactionNotFound), } } } + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct GenerateProofRequest { + pub spend_circuits: Vec>, + pub output_circuits: Vec>, + pub mint_asset_circuits: Vec>, +} + +#[derive(Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GenerateProofResponse { + pub spend_proofs: Vec>, + pub output_proofs: Vec>, + pub mint_asset_proofs: Vec>, +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct RescanAccountResponse { + pub success: bool, +} diff --git a/crates/oreo_errors/Cargo.toml b/crates/oreo_errors/Cargo.toml new file mode 100644 index 0000000..be7605b --- /dev/null +++ b/crates/oreo_errors/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "oreo_errors" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +axum = "0.7.3" +serde = { version = "1.0.195", features = ["derive"] } +serde_json = "1.0.111" +thiserror = "1.0.56" diff --git a/src/error.rs b/crates/oreo_errors/src/lib.rs similarity index 83% rename from src/error.rs rename to crates/oreo_errors/src/lib.rs index 0d7a331..f436385 100644 --- a/src/error.rs +++ b/crates/oreo_errors/src/lib.rs @@ -20,7 +20,7 @@ pub enum OreoError { #[error("Internal db error")] DBError, #[error("Internal Ironfish rpc error")] - InternalRpcError, + InternalRpcError(String), #[error("The `{0}` spend circuit can not generate proof")] GenerateSpendProofFailed(u32), #[error("The `{0}` output circuit can not generate proof")] @@ -37,6 +37,12 @@ pub enum OreoError { SeralizeError(String), #[error("Failed to parse data `{0}`")] ParseError(String), + #[error("Decryption server error")] + DServerError, + #[error("Unauthorized")] + Unauthorized, + #[error("RPC stream error")] + RpcStreamError(String), } impl IntoResponse for OreoError { @@ -47,7 +53,7 @@ impl IntoResponse for OreoError { OreoError::NoImported(_) => (StatusCode::from_u16(602).unwrap(), self.to_string()), OreoError::Scanning(_) => (StatusCode::from_u16(603).unwrap(), self.to_string()), OreoError::Syncing => (StatusCode::from_u16(604).unwrap(), self.to_string()), - OreoError::InternalRpcError => (StatusCode::from_u16(605).unwrap(), self.to_string()), + OreoError::InternalRpcError(_) => (StatusCode::from_u16(605).unwrap(), self.to_string()), OreoError::GenerateSpendProofFailed(_) => { (StatusCode::from_u16(606).unwrap(), self.to_string()) } @@ -64,6 +70,9 @@ impl IntoResponse for OreoError { } OreoError::SeralizeError(_) => (StatusCode::from_u16(612).unwrap(), self.to_string()), OreoError::ParseError(_) => (StatusCode::from_u16(613).unwrap(), self.to_string()), + OreoError::DServerError => (StatusCode::from_u16(614).unwrap(), self.to_string()), + OreoError::Unauthorized => (StatusCode::UNAUTHORIZED, self.to_string()), + OreoError::RpcStreamError(_) => (StatusCode::from_u16(615).unwrap(), self.to_string()), }; Json(json!({"code": status_code.as_u16(), "error": err_msg})).into_response() } diff --git a/crates/prover/Cargo.toml b/crates/prover/Cargo.toml new file mode 100644 index 0000000..6a4c1ac --- /dev/null +++ b/crates/prover/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "prover" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.79" +axum = { version = "0.7.3", features = ["macros"] } +clap = { version = "4.4.13", features = ["derive"] } +serde_json = "1.0.111" +tokio = { version = "1.35.1", features = ["full"] } +tower = { version = "0.4.13", features = ["timeout"] } +tower-http = { version = "0.5.0", features = ["cors"] } +tracing = "0.1.40" +utils = { path = "../utils" } +constants = { path = "../constants" } +oreo_errors = { path = "../oreo_errors" } +db_handler = { path = "../db_handler" } +networking = { path = "../networking" } +ironfish_rust = { package = "ironfish", git = "https://github.com/iron-fish/ironfish.git", branch = "master" } +ironfish_zkp = { package = "ironfish_zkp", git = "https://github.com/iron-fish/ironfish.git", branch = "master" } +ironfish-bellperson = { version = "0.1.0", features = ["groth16"] } +blst = "=0.3.10" +blstrs = { version = "0.6.0", features = ["portable"] } +rand = "0.8.5" +getrandom = { version = "0.2", features = ["js"] } +rand_core = { version = "0.6.4", features = ["getrandom"] } +rayon = "1.5" diff --git a/src/web_handlers/proof.rs b/crates/prover/src/handlers.rs similarity index 91% rename from src/web_handlers/proof.rs rename to crates/prover/src/handlers.rs index 36da708..ddc0171 100644 --- a/src/web_handlers/proof.rs +++ b/crates/prover/src/handlers.rs @@ -1,20 +1,18 @@ use std::sync::{Arc, Mutex}; use axum::{extract, response::IntoResponse, Json}; -use bellperson::groth16; +use ironfish_bellperson::groth16; use ironfish_rust::sapling_bls12::SAPLING; use ironfish_zkp::proofs::{MintAsset, Output, Spend}; +use networking::web_abi::{GenerateProofRequest, GenerateProofResponse}; +use oreo_errors::OreoError; use rand::thread_rng; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; use serde_json::json; use tracing::{error, info}; -use crate::error::OreoError; - -use super::abi::{GenerateProofRep, GenerateProofReq}; - pub async fn generate_proof_handler( - extract::Json(request): extract::Json, + extract::Json(request): extract::Json, ) -> impl IntoResponse { info!("calling generate_proof_handler"); let failed_index = Arc::new(Mutex::new(0u32)); @@ -117,7 +115,7 @@ pub async fn generate_proof_handler( return OreoError::GenerateMintAssetProofFailed(idx - 1).into_response(); } - let proof = GenerateProofRep { + let proof = GenerateProofResponse { spend_proofs, output_proofs, mint_asset_proofs, @@ -125,3 +123,7 @@ pub async fn generate_proof_handler( Json(json!({"code": 200, "data": proof})).into_response() } + +pub async fn health_check_handler() -> impl IntoResponse { + Json(json!({"code": 200, "data": "Hello prover!"})).into_response() +} diff --git a/crates/prover/src/lib.rs b/crates/prover/src/lib.rs new file mode 100644 index 0000000..3a0efb3 --- /dev/null +++ b/crates/prover/src/lib.rs @@ -0,0 +1,45 @@ +use std::{net::SocketAddr, time::Duration}; + +use axum::{ + error_handling::HandleErrorLayer, + http::StatusCode, + response::IntoResponse, + routing::{get, post}, + BoxError, Router, +}; +use tokio::net::TcpListener; +use tower::{timeout::TimeoutLayer, ServiceBuilder}; +use tower_http::cors::{Any, CorsLayer}; +use tracing::info; + +use crate::handlers::{generate_proof_handler, health_check_handler}; + +pub mod handlers; + +pub async fn run_prover(listen: SocketAddr) -> anyhow::Result<()> { + let router = Router::new() + .route("/generateProofs", post(generate_proof_handler)) + .route("/healthCheck", get(health_check_handler)) + .layer( + ServiceBuilder::new() + .layer(HandleErrorLayer::new(|_: BoxError| async { + StatusCode::REQUEST_TIMEOUT + })) + .layer(TimeoutLayer::new(Duration::from_secs(30))), + ) + .layer( + CorsLayer::new() + .allow_methods(Any) + .allow_origin(Any) + .allow_headers(Any), + ); + let listener = TcpListener::bind(&listen).await?; + let app = router.fallback(handler_404); + info!("Prover listening on {}", listen); + axum::serve(listener, app).await?; + Ok(()) +} + +async fn handler_404() -> impl IntoResponse { + (StatusCode::NOT_FOUND, "Not Found") +} diff --git a/src/bin/prover.rs b/crates/prover/src/main.rs similarity index 89% rename from src/bin/prover.rs rename to crates/prover/src/main.rs index 103e230..9d5b91e 100644 --- a/src/bin/prover.rs +++ b/crates/prover/src/main.rs @@ -2,7 +2,8 @@ use std::net::SocketAddr; use anyhow::Result; use clap::Parser; -use ironfish_server::{handle_signals, initialize_logger, run_prover}; +use prover::run_prover; +use utils::{handle_signals, initialize_logger}; #[derive(Parser, Debug, Clone)] pub struct Command { diff --git a/crates/server/Cargo.toml b/crates/server/Cargo.toml new file mode 100644 index 0000000..a15efdd --- /dev/null +++ b/crates/server/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "server" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.79" +axum = { version = "0.7.3", features = ["macros"] } +axum-extra = { version = "0.9.4", features = ["typed-header"]} +clap = { version = "4.4.13", features = ["derive"] } +tokio = { version = "1.35.1", features = ["full"] } +tower = { version = "0.4.13", features = ["timeout"] } +tower-http = { version = "0.5.0", features = ["cors"] } +tracing = "0.1.40" +utils = { path = "../utils" } +networking = { path = "../networking" } +constants = { path = "../constants" } +oreo_errors = { path = "../oreo_errors" } +db_handler = { path = "../db_handler" } +serde_json = "1.0.117" +dotenv = "0.15.0" +bincode = "1.3.3" +hex = "0.4.3" +sha2 = "0.10.8" diff --git a/crates/server/src/handlers.rs b/crates/server/src/handlers.rs new file mode 100644 index 0000000..22166e8 --- /dev/null +++ b/crates/server/src/handlers.rs @@ -0,0 +1,447 @@ +use std::{str::FromStr, sync::Arc}; + +use axum::{ + extract::{self, State}, + response::IntoResponse, + Json, +}; +use constants::{ACCOUNT_VERSION, MAINNET_GENESIS_SEQUENCE}; +use db_handler::DBHandler; +use networking::{ + decryption_message::{DecryptionMessage, ScanRequest, ScanResponse, SuccessResponse}, + rpc_abi::{ + BlockInfo, OutPut, RpcAddTxRequest, RpcCreateTxRequest, RpcGetAccountStatusRequest, + RpcGetAccountTransactionRequest, RpcGetBalancesRequest, RpcGetBalancesResponse, + RpcGetTransactionsRequest, RpcImportAccountRequest, RpcImportAccountResponse, + RpcRemoveAccountRequest, RpcResetAccountRequest, RpcResponse, RpcSetScanningRequest, + }, + web_abi::{GetTransactionDetailResponse, ImportAccountRequest, RescanAccountResponse}, +}; +use oreo_errors::OreoError; +use serde_json::json; +use tracing::error; +use utils::{default_secp, sign, verify, Signature}; + +use crate::SharedState; + +pub async fn import_account_handler( + State(shared): State>>, + extract::Json(import): extract::Json, +) -> impl IntoResponse { + let account_name = shared + .db_handler + .save_account(import.clone().to_account(shared.genesis_hash.clone()), 0) + .await; + if let Err(e) = account_name { + return e.into_response(); + } + let account_name = account_name.unwrap(); + let ImportAccountRequest { + view_key, + incoming_view_key, + outgoing_view_key, + public_address, + created_at, + } = import; + let rpc_data = RpcImportAccountRequest { + view_key, + incoming_view_key: incoming_view_key.clone(), + outgoing_view_key: outgoing_view_key.clone(), + public_address: public_address.clone(), + spending_key: None, + version: ACCOUNT_VERSION, + name: account_name.clone(), + created_at, + }; + match shared.rpc_handler.import_account(rpc_data) { + Ok(_) => { + let latest = shared.rpc_handler.get_latest_block().unwrap(); + let latest_height = latest + .data + .current_block_identifier + .index + .parse::() + .unwrap(); + shared + .rpc_handler + .get_account_status(RpcGetAccountStatusRequest { + account: account_name.clone(), + }) + .map(|x| { + let head = x.data.account.head.unwrap_or(BlockInfo { + hash: shared.genesis_hash.clone(), + sequence: MAINNET_GENESIS_SEQUENCE as u64, + }); + if latest_height - head.sequence > 1000 { + let _ = shared.rpc_handler.set_scanning(RpcSetScanningRequest { + account: account_name.clone(), + enabled: false, + }); + let _ = shared.rpc_handler.reset_account(RpcResetAccountRequest { + account: account_name.clone(), + reset_scanning_enabled: Some(false), + reset_created_at: Some(false), + }); + let scan_request = ScanRequest { + address: public_address.clone(), + in_vk: incoming_view_key.clone(), + out_vk: outgoing_view_key.clone(), + head: Some(head), + }; + let msg = bincode::serialize(&scan_request).unwrap(); + let signature = sign(&default_secp(), &msg[..], &shared.secp.sk) + .unwrap() + .to_string(); + let _ = shared.scan_handler.submit_scan_request(DecryptionMessage { + message: scan_request, + signature, + }); + } + RpcResponse { + status: 200, + data: RpcImportAccountResponse { + name: account_name.clone(), + }, + } + }) + .into_response() + } + Err(e) => e.into_response(), + } +} + +pub async fn remove_account_handler( + State(shared): State>>, + extract::Json(remove_account): extract::Json, +) -> impl IntoResponse { + let db_account = shared + .db_handler + .get_account(remove_account.account.clone()) + .await; + if let Err(e) = db_account { + return e.into_response(); + } + let result = shared.rpc_handler.remove_account(RpcRemoveAccountRequest { + account: db_account.unwrap().name, + confirm: Some(true), + wait: Some(true), + }); + match result { + Ok(response) => { + if let Err(e) = shared + .db_handler + .remove_account(remove_account.account.clone()) + .await + { + return e.into_response(); + } + response.into_response() + } + Err(e) => e.into_response(), + } +} + +pub async fn account_status_handler( + State(shared): State>>, + extract::Json(account): extract::Json, +) -> impl IntoResponse { + let db_account = shared.db_handler.get_account(account.account.clone()).await; + if let Err(e) = db_account { + return e.into_response(); + } + let result = shared + .rpc_handler + .get_account_status(RpcGetAccountStatusRequest { + account: db_account.unwrap().name, + }); + match result { + Ok(mut result) => { + match result.data.account.head { + Some(_) => {} + None => { + result.data.account.head = Some(BlockInfo { + hash: shared.genesis_hash.clone(), + sequence: MAINNET_GENESIS_SEQUENCE as u64, + }) + } + } + Ok(result) + } + Err(e) => Err(e), + } + .into_response() +} + +pub async fn rescan_account_handler( + State(shared): State>>, + extract::Json(account): extract::Json, +) -> impl IntoResponse { + let db_account = shared.db_handler.get_account(account.account.clone()).await; + if let Err(e) = db_account { + return e.into_response(); + } + let account = db_account.unwrap(); + let _ = shared.rpc_handler.set_scanning(RpcSetScanningRequest { + account: account.name.clone(), + enabled: false, + }); + let _ = shared.rpc_handler.reset_account(RpcResetAccountRequest { + account: account.name.clone(), + reset_scanning_enabled: Some(false), + reset_created_at: Some(false), + }); + let _ = shared + .db_handler + .update_scan_status(account.address.clone(), true) + .await; + if let Ok(status) = shared + .rpc_handler + .get_account_status(RpcGetAccountStatusRequest { + account: account.name.clone(), + }) + { + let head = BlockInfo { + hash: account.create_hash.unwrap_or(shared.genesis_hash.clone()), + sequence: account.create_head.unwrap_or(MAINNET_GENESIS_SEQUENCE) as u64, + }; + let scan_request = ScanRequest { + address: account.address.clone(), + in_vk: account.in_vk.clone(), + out_vk: account.out_vk.clone(), + head: Some(head), + }; + let msg = bincode::serialize(&scan_request).unwrap(); + let signature = sign(&default_secp(), &msg[..], &shared.secp.sk) + .unwrap() + .to_string(); + let _ = shared.scan_handler.submit_scan_request(DecryptionMessage { + message: scan_request, + signature, + }); + } + RpcResponse { + status: 200, + data: RescanAccountResponse { success: true }, + } + .into_response() +} + +pub async fn update_scan_status_handler( + State(shared): State>>, + extract::Json(response): extract::Json>, +) -> impl IntoResponse { + let DecryptionMessage { + mut message, + signature, + } = response; + let secp = default_secp(); + let msg = bincode::serialize(&message).unwrap(); + let signature = Signature::from_str(&signature).unwrap(); + if let Ok(x) = verify( + &secp, + &msg[..], + signature.serialize_compact(), + &shared.secp.pk, + ) { + if x { + let db_account = shared.db_handler.get_account(message.account.clone()).await; + if let Err(e) = db_account { + return e.into_response(); + } + let account = db_account.unwrap(); + let reset_created_at = account.create_head.is_none() || account.create_head.unwrap() == 1; + let reset = shared.rpc_handler.reset_account(RpcResetAccountRequest { + account: account.name.clone(), + reset_scanning_enabled: Some(false), + reset_created_at: Some(reset_created_at), + }); + if let Err(e) = reset { + return e.into_response(); + } + message.account = account.name.clone(); + let resp = shared.rpc_handler.set_account_head(message.clone()); + + if resp.is_err() { + error!("Failed to update account head: {:?}", resp.unwrap_err()); + } + if message.scan_complete { + let _ = shared.rpc_handler.set_scanning(RpcSetScanningRequest { + account: account.name.clone(), + enabled: true, + }); + let _ = shared + .db_handler + .update_scan_status(account.address, false) + .await; + } + return Json(SuccessResponse { success: true }).into_response(); + } + } + Json(SuccessResponse { success: false }).into_response() +} + +pub async fn get_balances_handler( + State(shared): State>>, + extract::Json(get_balance): extract::Json, +) -> impl IntoResponse { + let db_account = shared + .db_handler + .get_account(get_balance.account.clone()) + .await; + if let Err(e) = db_account { + return e.into_response(); + } + let resp = shared.rpc_handler.get_balances(RpcGetBalancesRequest { + account: db_account.unwrap().name, + confirmations: Some(get_balance.confirmations.unwrap_or(10)), + }); + match resp { + Ok(res) => { + let response = RpcResponse { + status: 200, + data: RpcGetBalancesResponse::verified_asset(res.data), + }; + response.into_response() + } + Err(e) => e.into_response(), + } +} + +pub async fn get_ores_handler( + State(shared): State>>, + extract::Json(get_balance): extract::Json, +) -> impl IntoResponse { + let db_account = shared + .db_handler + .get_account(get_balance.account.clone()) + .await; + if let Err(e) = db_account { + return e.into_response(); + } + let resp = shared.rpc_handler.get_balances(RpcGetBalancesRequest { + account: db_account.unwrap().name, + confirmations: Some(get_balance.confirmations.unwrap_or(10)), + }); + match resp { + Ok(res) => { + let response = RpcResponse { + status: 200, + data: RpcGetBalancesResponse::ores(res.data).await, + }; + response.into_response() + } + Err(e) => e.into_response(), + } +} + +pub async fn get_transaction_handler( + State(shared): State>>, + extract::Json(account): extract::Json, +) -> impl IntoResponse { + let db_account = shared.db_handler.get_account(account.account.clone()).await; + if let Err(e) = db_account { + return e.into_response(); + } + let rpc_transaction = + shared + .rpc_handler + .get_account_transaction(RpcGetAccountTransactionRequest { + account: db_account.unwrap().name, + hash: account.hash, + notes: Some(true), + }); + match rpc_transaction { + Ok(RpcResponse { data, status: _ }) => { + let transaction_detail = GetTransactionDetailResponse::from_rpc_data(data); + match transaction_detail { + Ok(detail) => RpcResponse { + status: 200, + data: detail, + } + .into_response(), + Err(e) => e.into_response(), + } + } + Err(e) => e.into_response(), + } +} + +pub async fn get_transactions_handler( + State(shared): State>>, + extract::Json(get_transactions): extract::Json, +) -> impl IntoResponse { + let db_account = shared + .db_handler + .get_account(get_transactions.account.clone()) + .await; + if let Err(e) = db_account { + return e.into_response(); + } + shared + .rpc_handler + .get_transactions(RpcGetTransactionsRequest { + account: db_account.unwrap().name, + limit: Some(get_transactions.limit.unwrap_or(6)), + reverse: Some(true), + }) + .into_response() +} + +pub async fn create_transaction_handler( + State(shared): State>>, + extract::Json(create_transaction): extract::Json, +) -> impl IntoResponse { + let db_account = shared + .db_handler + .get_account(create_transaction.account.clone()) + .await; + if let Err(e) = db_account { + return e.into_response(); + } + let outputs: Vec = create_transaction + .outputs + .unwrap_or(vec![]) + .iter() + .map(|output| OutPut::from(output.clone())) + .collect(); + let mut mints = vec![]; + for item in create_transaction.mints.unwrap_or(vec![]).into_iter() { + if item.asset_id.is_none() && item.name.is_none() { + return OreoError::BadMintRequest.into_response(); + } else { + mints.push(item); + } + } + let burns = create_transaction.burns.unwrap_or(vec![]); + shared + .rpc_handler + .create_transaction(RpcCreateTxRequest { + account: db_account.unwrap().name, + outputs: Some(outputs), + fee: Some(create_transaction.fee.unwrap_or("1".into())), + expiration_delta: Some(create_transaction.expiration_delta.unwrap_or(30)), + mints: Some(mints), + burns: Some(burns), + }) + .into_response() +} + +pub async fn add_transaction_handler( + State(shared): State>>, + extract::Json(broadcast_transaction): extract::Json, +) -> impl IntoResponse { + shared + .rpc_handler + .add_transaction(broadcast_transaction) + .into_response() +} + +pub async fn latest_block_handler( + State(shared): State>>, +) -> impl IntoResponse { + shared.rpc_handler.get_latest_block().into_response() +} + +pub async fn health_check_handler() -> impl IntoResponse { + Json(json!({"code": 200, "data": "Hello prover!"})).into_response() +} diff --git a/crates/server/src/lib.rs b/crates/server/src/lib.rs new file mode 100644 index 0000000..4e6c7ed --- /dev/null +++ b/crates/server/src/lib.rs @@ -0,0 +1,159 @@ +use std::{env, net::SocketAddr, sync::Arc, time::Duration}; +use axum_extra::{headers::{authorization::Basic, Authorization}, TypedHeader}; +use sha2::{Sha256, Digest}; +use std::str; + +use anyhow::Result; +use axum::{ + body::Body, error_handling::HandleErrorLayer, extract::State, http::{Request, StatusCode}, middleware::{from_fn_with_state, Next}, response::IntoResponse, routing::{get, post}, BoxError, Router +}; +use db_handler::{DBHandler, PgHandler}; +use networking::{rpc_handler::RpcHandler, server_handler::ServerHandler}; +use tokio::net::TcpListener; +use tower::{timeout::TimeoutLayer, ServiceBuilder}; +use tower_http::cors::{Any, CorsLayer}; +use tracing::info; + +use crate::handlers::{ + account_status_handler, add_transaction_handler, create_transaction_handler, + get_balances_handler, get_ores_handler, get_transaction_handler, get_transactions_handler, + health_check_handler, import_account_handler, latest_block_handler, remove_account_handler, + rescan_account_handler, update_scan_status_handler, +}; + +mod handlers; + +#[derive(Debug, Clone)] +pub struct SecpKey { + pub sk: [u8; 32], + pub pk: [u8; 33], +} + +#[derive(Debug, Clone)] +pub struct SharedState { + pub db_handler: T, + pub rpc_handler: RpcHandler, + pub scan_handler: ServerHandler, + pub secp: SecpKey, + pub genesis_hash: String, +} + +impl SharedState +where + T: DBHandler, +{ + pub fn new(db_handler: T, endpoint: &str, scan: &str, secp: SecpKey, genesis_hash: String) -> Self { + Self { + db_handler: db_handler, + rpc_handler: RpcHandler::new(endpoint.into()), + scan_handler: ServerHandler::new(scan.into()), + secp, + genesis_hash, + } + } +} + +// Authentication middleware function +pub async fn auth( + State(shared_state): State>>, + TypedHeader(Authorization(basic)): TypedHeader>, + req: Request, + next: Next +) -> impl IntoResponse + where + T: DBHandler + Send + Sync + 'static, +{ + match shared_state.db_handler.get_account(basic.username().to_string()).await { + Ok(account) => { + let bytes = hex::decode(account.vk).map_err(|_| (StatusCode::UNAUTHORIZED, "Invalid token"))?; + let token = Sha256::digest(bytes); + let token_hex = hex::encode(token); + if token_hex != basic.password() { + return Err((StatusCode::UNAUTHORIZED, "Invalid token")); + } + return Ok(next.run(req).await); + } + Err(_) => { + // Token is invalid + return Err((StatusCode::UNAUTHORIZED, "Invalid token")); + } + } +} + +pub async fn run_server( + listen: SocketAddr, + rpc_server: String, + db_handler: PgHandler, + scan: String, + sk_u8: [u8; 32], + pk_u8: [u8; 33], +) -> Result<()> { + let genesis_hash; + { + let temp_handler: RpcHandler = RpcHandler::new(rpc_server.clone().into()); + let latest_block_response = temp_handler.get_latest_block()?.data; + genesis_hash = latest_block_response.genesis_block_identifier.hash; + } + info!("Genesis hash: {}", genesis_hash); + let shared_resource = Arc::new(SharedState::new( + db_handler, + &rpc_server, + &scan, + SecpKey { + sk: sk_u8, + pk: pk_u8, + }, + genesis_hash, + )); + let auth_middleware = from_fn_with_state(shared_resource.clone(), auth); + + let no_auth_router = Router::new() + .route("/import", post(import_account_handler)) + .with_state(shared_resource.clone()); + + let mut auth_router = Router::new() + .route("/remove", post(remove_account_handler)) + .route("/getBalances", post(get_balances_handler)) + .route("/getTransaction", post(get_transaction_handler)) + .route("/getTransactions", post(get_transactions_handler)) + .route("/createTx", post(create_transaction_handler)) + .route("/broadcastTx", post(add_transaction_handler)) // TODO: Remove after front end updates to addTx + .route("/addTx", post(add_transaction_handler)) + .route("/accountStatus", post(account_status_handler)) + .route("/latestBlock", get(latest_block_handler)) + .route("/ores", post(get_ores_handler)) + .route("/rescan", post(rescan_account_handler)) + .route("/healthCheck", get(health_check_handler)) + .route("/updateScan", post(update_scan_status_handler)) + .with_state(shared_resource.clone()); + + if env::var("ENABLE_AUTH").unwrap_or_else(|_| "false".to_string()) == "true" { + auth_router = auth_router.layer(auth_middleware); + } + + let router = no_auth_router + .merge(auth_router) + .layer( + ServiceBuilder::new() + .layer(HandleErrorLayer::new(|_: BoxError| async { + StatusCode::REQUEST_TIMEOUT + })) + .layer(TimeoutLayer::new(Duration::from_secs(30))), + ) + .layer( + CorsLayer::new() + .allow_methods(Any) + .allow_origin(Any) + .allow_headers(Any), + ); + + let listener = TcpListener::bind(&listen).await?; + let app = router.fallback(handler_404); + info!("Server listening on {}", listen); + axum::serve(listener, app).await?; + Ok(()) +} + +async fn handler_404() -> impl IntoResponse { + (StatusCode::NOT_FOUND, "Not Found") +} diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs new file mode 100644 index 0000000..8488b97 --- /dev/null +++ b/crates/server/src/main.rs @@ -0,0 +1,52 @@ +use std::net::SocketAddr; + +use anyhow::Result; +use clap::Parser; +use db_handler::{DBHandler, DbConfig, PgHandler}; +use dotenv::dotenv; +use server::run_server; +use utils::{handle_signals, initialize_logger}; + +#[derive(Parser, Debug, Clone)] +pub struct Command { + /// The ip:port server will listen on for restful api + #[clap(long, default_value = "0.0.0.0:10001")] + pub listen: SocketAddr, + /// The path to db config file + #[clap(long)] + pub dbconfig: String, + /// Set your logger level + #[clap(short, long, default_value = "0")] + pub verbosity: u8, + /// The Ironfish rpc node to connect to + #[clap(short, long, default_value = "127.0.0.1:9092")] + pub node: String, + /// The scan server to connect to + #[clap(long, default_value = "127.0.0.1:9093")] + pub scan: String, +} + +#[tokio::main] +async fn main() -> Result<()> { + dotenv().ok(); + let sk = std::env::var("SECRET_KEY").expect("SECRET_KEY not provided in env"); + let pk = std::env::var("PUBLIC_KEY").expect("PUBLIC_KEY not provided in env"); + let mut sk_u8 = [0u8; 32]; + let mut pk_u8 = [0u8; 33]; + let _ = hex::decode_to_slice(sk, &mut sk_u8).unwrap(); + let _ = hex::decode_to_slice(pk, &mut pk_u8).unwrap(); + let args = Command::parse(); + let Command { + listen, + dbconfig, + verbosity, + node, + scan, + } = args; + initialize_logger(verbosity); + handle_signals().await?; + let db_config = DbConfig::load(dbconfig).unwrap(); + let db_handler = PgHandler::from_config(&db_config); + run_server(listen.into(), node, db_handler, scan, sk_u8, pk_u8).await?; + Ok(()) +} diff --git a/crates/transfer-tool/Cargo.toml b/crates/transfer-tool/Cargo.toml new file mode 100644 index 0000000..c277e7d --- /dev/null +++ b/crates/transfer-tool/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "transfer-tool" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.79" +clap = { version = "4.4.13", features = ["derive"] } +tokio = { version = "1.35.1", features = ["full"] } +tracing = "0.1.40" +utils = { path = "../utils" } +networking = { path = "../networking" } +db_handler = { path = "../db_handler" } +constants = { path = "../constants" } diff --git a/crates/transfer-tool/src/main.rs b/crates/transfer-tool/src/main.rs new file mode 100644 index 0000000..eb8f9c2 --- /dev/null +++ b/crates/transfer-tool/src/main.rs @@ -0,0 +1,89 @@ +use anyhow::Result; +use clap::Parser; +use constants::IRON_NATIVE_ASSET; +use db_handler::{DBHandler, DbConfig, PgHandler}; +use networking::{ + rpc_abi::{OutPut, SendTransactionRequest}, + rpc_handler::RpcHandler, +}; +use tracing::info; +use utils::{handle_signals, initialize_logger}; +#[derive(Parser, Debug, Clone)] +pub struct Command { + /// The path to db config file + #[clap(long)] + pub dbconfig: String, + /// Set your logger level + #[clap(short, long, default_value = "0")] + pub verbosity: u8, + /// The Ironfish rpc node to connect to + #[clap(short, long, default_value = "127.0.0.1:9092")] + pub node: String, + /// The account used to transfer from + #[clap(long)] + pub account: String, + /// The bonus amount + #[clap(long)] + pub bonus: String, +} + +#[tokio::main] +async fn main() -> Result<()> { + let cli = Command::parse(); + let Command { + dbconfig, + verbosity, + node, + account, + bonus, + } = cli; + initialize_logger(verbosity); + handle_signals().await?; + let db_config = DbConfig::load(dbconfig).unwrap(); + let db_handler = PgHandler::from_config(&db_config); + let rpc_handler = RpcHandler::new(node); + match db_handler.get_unpaid_addresses().await { + Ok(accounts) => { + info!("bonus accounts: {:?}", accounts); + let mut outputs = vec![]; + for account in accounts.iter() { + if account.paid { + continue; + } + outputs.push(OutPut { + public_address: account.address.clone(), + amount: bonus.clone(), + memo: Some("OreoWallet-Bonus".to_string()), + memo_hex: Some("".into()), + asset_id: Some(IRON_NATIVE_ASSET.to_string()), + }); + } + if outputs.is_empty() { + info!("no new bonus address"); + return Ok(()); + } + let send_request = SendTransactionRequest { + account: account.clone(), + fee: "10".to_string(), + expiration_delta: 30, + outputs, + }; + let result = rpc_handler.send_transaction(send_request); + match result { + Ok(result) => { + info!("transaction sent, {}", result.data.hash); + for account in accounts.iter() { + let _ = db_handler + .update_firstseen_status(account.address.clone()) + .await; + } + } + Err(e) => { + tracing::error!("failed to send transaction, {:?}", e); + } + } + } + Err(e) => tracing::error!("failed to get accounts, {:?}", e), + } + Ok(()) +} diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml new file mode 100644 index 0000000..a18ee74 --- /dev/null +++ b/crates/utils/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "utils" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.79" +secp256k1 = { version = "0.29.0", features = ["hashes-std"] } +tokio = { version = "1.35.1", features = ["full"] } +tracing = "0.1.40" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs new file mode 100644 index 0000000..e2b1558 --- /dev/null +++ b/crates/utils/src/lib.rs @@ -0,0 +1,85 @@ +use std::{cmp, ops::Range, time::Duration}; + +use secp256k1::{ + ecdsa, + hashes::{sha256, Hash}, + All, Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification, +}; +use tokio::sync::oneshot; +use tracing::{info, warn}; +use tracing_subscriber::EnvFilter; + +pub use secp256k1::ecdsa::Signature; + +pub async fn handle_signals() -> anyhow::Result<()> { + let (router, handler) = oneshot::channel(); + tokio::spawn(async move { + let _ = router.send(()); + match tokio::signal::ctrl_c().await { + Ok(()) => { + info!("Shutdowning..."); + tokio::time::sleep(Duration::from_millis(5000)).await; + info!("Goodbye"); + std::process::exit(0); + } + Err(error) => warn!("tokio::signal::ctrl_c encountered an error: {}", error), + } + }); + let _ = handler.await; + info!("Signal handler installed"); + Ok(()) +} + +pub fn initialize_logger(verbosity: u8) { + match verbosity { + 0 => std::env::set_var("RUST_LOG", "info"), + 1 => std::env::set_var("RUST_LOG", "debug"), + 2 | 3 | 4 => std::env::set_var("RUST_LOG", "trace"), + _ => std::env::set_var("RUST_LOG", "info"), + }; + tracing_subscriber::fmt() + .with_env_filter( + EnvFilter::from_default_env().add_directive("ironfish-server=info".parse().unwrap()), + ) + .init(); +} + +pub fn blocks_range(blocks: Range, batch: u64) -> Vec> { + let end = blocks.end; + let mut result = vec![]; + for block in blocks.step_by(batch as usize) { + let start = block; + let end = cmp::min(start + batch - 1, end); + result.push(start..end) + } + result +} + +pub fn verify( + secp: &Secp256k1, + msg: &[u8], + sig: [u8; 64], + pubkey: &[u8; 33], +) -> Result { + let msg = sha256::Hash::hash(msg); + let msg = Message::from_digest_slice(msg.as_ref())?; + let sig = ecdsa::Signature::from_compact(&sig)?; + let pubkey = PublicKey::from_slice(pubkey)?; + + Ok(secp.verify_ecdsa(&msg, &sig, &pubkey).is_ok()) +} + +pub fn sign( + secp: &Secp256k1, + msg: &[u8], + seckey: &[u8; 32], +) -> Result { + let msg = sha256::Hash::hash(msg); + let msg = Message::from_digest_slice(msg.as_ref())?; + let seckey = SecretKey::from_slice(seckey)?; + Ok(secp.sign_ecdsa(&msg, &seckey)) +} + +pub fn default_secp() -> Secp256k1 { + Secp256k1::new() +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ea759f5 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,181 @@ +version: '2.4' +services: + dbconfig: + image: alpine:latest + volumes: + - conf:/app/conf # Mount the config directory on the host to the container + command: | + /bin/sh -c "echo 'host: postgres + port: 5432 + user: ${DB_USER} + password: ${DB_PASSWORD} + dbname: oreowallet + default_pool_size: 200 + protocol: \"postgres\"' > /app/conf/dbconfig" + + postgres: + image: postgres:latest + environment: + POSTGRES_USER: ${DB_USER} + POSTGRES_PASSWORD: ${DB_PASSWORD} + POSTGRES_DB: oreowallet + ports: + - "${DB_PORT}:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + networks: + - oreowallet_network + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"] + interval: 10s + timeout: 5s + retries: 5 + + migration: + build: . + image: "oreowallet" + command: /bin/sh -c "./sqlx database create && ./sqlx migrate run" + environment: + - DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@postgres:5432/oreowallet + networks: + - oreowallet_network + depends_on: + - postgres + - dbconfig + logging: + driver: "json-file" + options: + max-file: "4" + max-size: "25m" + + chainloader: + build: . + restart: always + image: "oreowallet" + command: ./chain_loader --dbconfig /app/conf/dbconfig --node ${NODE_HOST}:${NODE_PORT} --verbosity ${VERBOSITY:-0} + volumes: + - conf:/app/conf + depends_on: + - migration + networks: + - oreowallet_network + ulimits: + core: + hard: 0 + soft: 0 + logging: + driver: "json-file" + options: + max-file: "4" + max-size: "25m" + + prover: + build: . + restart: always + image: "oreowallet" + command: ./prover --verbosity ${VERBOSITY:-0} + ports: + - "10002:10002" + depends_on: + - migration + - chainloader + networks: + - oreowallet_network + ulimits: + core: + hard: 0 + soft: 0 + logging: + driver: "json-file" + options: + max-file: "4" + max-size: "25m" + + server: + build: . + restart: always + image: "oreowallet" + environment: + - SECRET_KEY=${SECRET_KEY} + - PUBLIC_KEY=${PUBLIC_KEY} + - ENABLE_AUTH=${ENABLE_AUTH:-false} + command: | + ./server --listen 0.0.0.0:${SERVER_PORT} --dbconfig /app/conf/dbconfig --node ${NODE_HOST}:${NODE_PORT} --scan dservice:20001 --verbosity ${VERBOSITY:-0} + ports: + - "${SERVER_PORT}:${SERVER_PORT}" + volumes: + - conf:/app/conf + depends_on: + - migration + - chainloader + networks: + - oreowallet_network + ulimits: + core: + hard: 0 + soft: 0 + logging: + driver: "json-file" + options: + max-file: "4" + max-size: "25m" + + dservice: + build: . + restart: always + image: "oreowallet" + environment: + - SECRET_KEY=${SECRET_KEY} + - PUBLIC_KEY=${PUBLIC_KEY} + command: ./dservice --dbconfig /app/conf/dbconfig --node ${NODE_HOST}:${NODE_PORT} --server server:${SERVER_PORT} --verbosity ${VERBOSITY:-0} + ports: + - "10001:10001" + - "20001:20001" + volumes: + - conf:/app/conf + depends_on: + - migration + - chainloader + networks: + oreowallet_network: + ipv4_address: 172.19.0.10 + ulimits: + core: + hard: 0 + soft: 0 + logging: + driver: "json-file" + options: + max-file: "4" + max-size: "25m" + + dworker: + build: . + restart: always + image: "oreowallet" + command: ./dworker --address 172.19.0.10:10001 --verbosity ${VERBOSITY:-0} + depends_on: + - migration + - chainloader + networks: + - oreowallet_network + ulimits: + core: + hard: 0 + soft: 0 + logging: + driver: "json-file" + options: + max-file: "4" + max-size: "25m" + +networks: + oreowallet_network: + driver: bridge + ipam: + config: + - subnet: 172.19.0.0/16 + +volumes: + postgres_data: + conf: \ No newline at end of file diff --git a/migrations/20240417022519_cachetable.down.sql b/migrations/20240417022519_cachetable.down.sql new file mode 100644 index 0000000..ed183bf --- /dev/null +++ b/migrations/20240417022519_cachetable.down.sql @@ -0,0 +1 @@ +DROP TABLE wallet.primarychain; diff --git a/migrations/20240417022519_cachetable.up.sql b/migrations/20240417022519_cachetable.up.sql new file mode 100644 index 0000000..5834d8c --- /dev/null +++ b/migrations/20240417022519_cachetable.up.sql @@ -0,0 +1,5 @@ +CREATE TABLE wallet.primarychain ( + address CHAR(64) NOT NULL, + hash CHAR(64) NOT NULL, + sequence BIGINT NOT NULL +); \ No newline at end of file diff --git a/migrations/20240507125825_needscan.down.sql b/migrations/20240507125825_needscan.down.sql new file mode 100644 index 0000000..bcaa00f --- /dev/null +++ b/migrations/20240507125825_needscan.down.sql @@ -0,0 +1,2 @@ +ALTER TABLE + wallet.account DROP COLUMN need_scan CASCADE; \ No newline at end of file diff --git a/migrations/20240507125825_needscan.up.sql b/migrations/20240507125825_needscan.up.sql new file mode 100644 index 0000000..72974c8 --- /dev/null +++ b/migrations/20240507125825_needscan.up.sql @@ -0,0 +1,4 @@ +ALTER TABLE + wallet.account +ADD + COLUMN need_scan boolean DEFAULT false; \ No newline at end of file diff --git a/migrations/20240507164837_dropprimary.down.sql b/migrations/20240507164837_dropprimary.down.sql new file mode 100644 index 0000000..d2f607c --- /dev/null +++ b/migrations/20240507164837_dropprimary.down.sql @@ -0,0 +1 @@ +-- Add down migration script here diff --git a/migrations/20240507164837_dropprimary.up.sql b/migrations/20240507164837_dropprimary.up.sql new file mode 100644 index 0000000..a0bb6ee --- /dev/null +++ b/migrations/20240507164837_dropprimary.up.sql @@ -0,0 +1 @@ +DROP TABLE wallet.primarychain; \ No newline at end of file diff --git a/migrations/20240611004802_localblocks.down.sql b/migrations/20240611004802_localblocks.down.sql new file mode 100644 index 0000000..f08a5d3 --- /dev/null +++ b/migrations/20240611004802_localblocks.down.sql @@ -0,0 +1,2 @@ +-- Add down migration script here +DROP TABLE wallet.blocks; \ No newline at end of file diff --git a/migrations/20240611004802_localblocks.up.sql b/migrations/20240611004802_localblocks.up.sql new file mode 100644 index 0000000..3e277cc --- /dev/null +++ b/migrations/20240611004802_localblocks.up.sql @@ -0,0 +1,7 @@ +-- Add up migration script here +CREATE TABLE wallet.blocks ( + hash CHAR(64) NOT NULL, + sequence BIGINT NOT NULL, + transactions JSON, + CONSTRAINT block_pkey PRIMARY KEY (sequence) +); \ No newline at end of file diff --git a/migrations/20240805163224_firstseen.down.sql b/migrations/20240805163224_firstseen.down.sql new file mode 100644 index 0000000..0f87352 --- /dev/null +++ b/migrations/20240805163224_firstseen.down.sql @@ -0,0 +1,2 @@ +-- Add down migration script here +DROP TABLE wallet.firstseen; \ No newline at end of file diff --git a/migrations/20240805163224_firstseen.up.sql b/migrations/20240805163224_firstseen.up.sql new file mode 100644 index 0000000..6499ca5 --- /dev/null +++ b/migrations/20240805163224_firstseen.up.sql @@ -0,0 +1,6 @@ +-- Add up migration script here +CREATE TABLE wallet.firstseen ( + address CHAR(64) NOT NULL, + paid boolean DEFAULT false, + CONSTRAINT seen_pkey PRIMARY KEY (address) +); \ No newline at end of file diff --git a/src/bin/migrate.rs b/src/bin/migrate.rs deleted file mode 100644 index 7a5058f..0000000 --- a/src/bin/migrate.rs +++ /dev/null @@ -1,74 +0,0 @@ -use anyhow::Result; -use clap::Parser; -use ironfish_server::{ - config::DbConfig, - db_handler::{DBHandler, PgHandler, RedisClient, REDIS_ACCOUNT_KEY}, - handle_signals, initialize_logger, - rpc_handler::{abi::ImportAccountReq, RpcHandler}, -}; - -#[derive(Parser, Debug, Clone)] -pub struct Command { - /// The path to source db config file (redis) - #[clap(short, long)] - pub config: String, - /// Set your logger level - #[clap(short, long, default_value = "0")] - pub verbosity: u8, - /// The Ironfish rpc node to connect to - #[clap(short, long, default_value = "127.0.0.1:9092")] - pub node: String, - /// Destination db name, redis or postgres - #[clap(long, default_value = "redis")] - pub dname: String, - /// Destination db config file - #[clap(long)] - pub dconfig: String, -} - -#[tokio::main] -async fn main() -> Result<()> { - let args = Command::parse(); - let Command { - config, - verbosity, - node, - dname, - dconfig, - } = args; - initialize_logger(verbosity); - handle_signals().await?; - let db_config = DbConfig::load(config).unwrap(); - let redis_handler = RedisClient::from_config(&db_config); - let rpc_handler = RpcHandler::new(node.into()); - let accounts_v0 = redis_handler.hgetall(REDIS_ACCOUNT_KEY).await.unwrap(); - match dname.as_str() { - "redis" => { - for (_, name) in accounts_v0.into_iter() { - if let Ok(imported) = rpc_handler.export_account(name).await { - let account = imported.data.account; - let account: ImportAccountReq = serde_json::from_str(&account).unwrap(); - let _ = redis_handler - .save_account(account.to_account(), 0) - .await - .unwrap(); - } - } - } - "postgres" => { - let pg_handler = PgHandler::from_config(&DbConfig::load(dconfig).unwrap()); - for (_, name) in accounts_v0.into_iter() { - if let Ok(imported) = rpc_handler.export_account(name).await { - let account = imported.data.account; - let account: ImportAccountReq = serde_json::from_str(&account).unwrap(); - let _ = pg_handler - .save_account(account.to_account(), 0) - .await - .unwrap(); - } - } - } - _ => unimplemented!(), - } - Ok(()) -} diff --git a/src/db_handler/mod.rs b/src/db_handler/mod.rs deleted file mode 100644 index 8719c87..0000000 --- a/src/db_handler/mod.rs +++ /dev/null @@ -1,36 +0,0 @@ -mod pg_handler; -mod redis_handler; - -pub use pg_handler::*; -pub use redis_handler::*; - -use serde::{Deserialize, Serialize}; -use sqlx::FromRow; - -use crate::{config::DbConfig, error::OreoError}; - -#[async_trait::async_trait] -pub trait DBHandler { - /// Initialize a DB handler - fn from_config(config: &DbConfig) -> Self; - /// Save account in db and return account name - async fn save_account(&self, account: Account, worker_id: u32) -> Result; - /// Get account name from db - async fn get_account(&self, address: String) -> Result; - /// Remove account from db - async fn remove_account(&self, address: String) -> Result; -} - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, FromRow)] -#[serde(rename_all = "camelCase")] -pub struct Account { - pub name: String, - pub create_head: Option, - pub create_hash: Option, - pub head: i64, - pub hash: String, - pub in_vk: String, - pub out_vk: String, - pub vk: String, - pub address: String, -} diff --git a/src/db_handler/pg_handler.rs b/src/db_handler/pg_handler.rs deleted file mode 100644 index 9bc6716..0000000 --- a/src/db_handler/pg_handler.rs +++ /dev/null @@ -1,183 +0,0 @@ -use futures::executor::block_on; -use sqlx::{postgres::PgPoolOptions, PgPool, Row}; - -use crate::error::OreoError; - -use super::{Account, DBHandler}; - -#[derive(Debug, Clone)] -pub struct PgHandler { - pub pool: PgPool, -} - -impl PgHandler { - pub fn new(pool: PgPool) -> Self { - Self { pool } - } - - pub async fn insert(&self, account: Account) -> Result { - let result = sqlx::query( - "INSERT INTO wallet.account (name, create_head, create_hash, head, hash, in_vk, out_vk, vk, address) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING address" - ) - .bind(account.name.clone()) - .bind(account.create_head.clone()) - .bind(account.create_hash.clone()) - .bind(account.head) - .bind(account.hash.clone()) - .bind(account.in_vk.clone()) - .bind(account.out_vk.clone()) - .bind(account.vk.clone()) - .bind(account.address.clone()) - .fetch_one(&self.pool) - .await?.get(0); - Ok(result) - } - - pub async fn get_one(&self, address: String) -> Result { - let result = - sqlx::query_as::<_, Account>("SELECT * FROM wallet.account WHERE address = $1") - .bind(address) - .fetch_one(&self.pool) - .await?; - Ok(result) - } - - pub async fn update_one(&self, state: Account) -> Result { - let result = sqlx::query( - "UPDATE wallet.account SET head = $1, hash = $2 WHERE address = $3 RETURNING address", - ) - .bind(state.head) - .bind(state.hash.clone()) - .bind(state.address.clone()) - .fetch_one(&self.pool) - .await? - .get(0); - Ok(result) - } - - pub async fn delete(&self, address: String) -> Result { - let result = sqlx::query("DELETE FROM wallet.account WHERE address = $1 RETURNING address") - .bind(address) - .fetch_one(&self.pool) - .await? - .get(0); - Ok(result) - } -} - -#[async_trait::async_trait] -impl DBHandler for PgHandler { - fn from_config(config: &crate::config::DbConfig) -> Self { - let url = config.server_url(); - let pool = block_on(async { - PgPoolOptions::default() - .max_connections(config.default_pool_size) - .connect(&url) - .await - .unwrap() - }); - Self::new(pool) - } - - async fn save_account(&self, account: Account, _worker_id: u32) -> Result { - let old_account = self.get_one(account.address.clone()).await; - match old_account { - Ok(_) => Err(OreoError::Duplicate(account.address)), - Err(e) => match e { - sqlx::Error::RowNotFound => { - self.insert(account).await.map_err(|_| OreoError::DBError) - } - _ => Err(OreoError::DBError), - }, - } - } - - async fn get_account(&self, address: String) -> Result { - self.get_one(address.clone()).await.map_err(|e| match e { - sqlx::Error::RowNotFound => OreoError::NoImported(address), - _ => OreoError::DBError, - }) - } - - async fn remove_account(&self, address: String) -> Result { - self.delete(address.clone()).await.map_err(|e| match e { - sqlx::Error::RowNotFound => OreoError::NoImported(address), - _ => OreoError::DBError, - }) - } -} - -#[cfg(test)] -mod tests { - use sqlx_db_tester::TestDb; - - use crate::{ - constants::{MAINNET_GENESIS_HASH, MAINNET_GENESIS_SEQUENCE}, - db_handler::{address_to_name, Account, DBHandler}, - }; - - use super::PgHandler; - - const VK: &str = "4ae4eb9606ba57b3b17a444100a9ac6453cd67e6fe4c860e63a2e18b1200978ab5ecce68e8639d5016cbe73b0ea9a3c8e906fc881af2e9ccfa7a7b63fb73d555"; - const IN_VK: &str = "4a08bec0ec5a471352f340d737e4b3baec2aec8d0a2e12201d92d8ad71aadd07"; - const OUT_VK: &str = "cee4ff41d7d8da5eedc6493134981eaad7b26a8b0291a4eac9ba95090fa47bf7"; - const ADDRESS: &str = "d63ba13d7c35caf942c64d5139b948b885ec931977a3f248c13e7f3c1bd0aa64"; - - fn get_tdb() -> TestDb { - TestDb::new("localhost", 5432, "postgres", "postgres", "./migrations") - } - - fn get_test_account() -> Account { - Account { - name: address_to_name(ADDRESS), - create_head: None, - create_hash: None, - head: MAINNET_GENESIS_SEQUENCE, - hash: MAINNET_GENESIS_HASH.to_string(), - in_vk: IN_VK.to_string(), - out_vk: OUT_VK.to_string(), - vk: VK.to_string(), - address: ADDRESS.to_string(), - } - } - - #[tokio::test] - async fn save_account_should_work_pg() { - let tdb = get_tdb(); - let pool = tdb.get_pool().await; - let pg_handler = PgHandler::new(pool); - let account = get_test_account(); - let saved = pg_handler.save_account(account, 0).await; - assert!(saved.is_ok()); - let saved = saved.unwrap(); - assert_eq!(ADDRESS.to_string(), saved); - } - - #[tokio::test] - async fn get_account_should_work_pg() { - let tdb = get_tdb(); - let pool = tdb.get_pool().await; - let pg_handler = PgHandler::new(pool); - let account = get_test_account(); - let saved = pg_handler.save_account(account.clone(), 0).await.unwrap(); - let saved = pg_handler.get_account(saved).await; - assert!(saved.is_ok()); - let saved = saved.unwrap(); - assert_eq!(account, saved); - } - - #[tokio::test] - async fn remove_account_should_work_pg() { - let tdb = get_tdb(); - let pool = tdb.get_pool().await; - let pg_handler = PgHandler::new(pool); - let account = get_test_account(); - let saved = pg_handler.save_account(account.clone(), 0).await.unwrap(); - let result = pg_handler.remove_account(saved.clone()).await; - assert!(result.is_ok()); - - // run remove once again - let should_error = pg_handler.remove_account(saved).await; - assert!(should_error.is_err()); - } -} diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 380ce46..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,380 +0,0 @@ -use std::{net::SocketAddr, time::Duration}; - -use anyhow::Result; -use axum::{ - error_handling::HandleErrorLayer, - http::StatusCode, - routing::{get, post}, - BoxError, Router, -}; -use db_handler::{DBHandler, PgHandler}; -use rpc_handler::RpcHandler; -use tokio::{net::TcpListener, sync::oneshot}; -use tower::{timeout::TimeoutLayer, ServiceBuilder}; -use tower_http::cors::{Any, CorsLayer}; -use tracing::{info, warn}; -use tracing_subscriber::EnvFilter; - -use crate::web_handlers::{ - account_status_handler, account_transaction_handler, broadcast_transaction_handler, - create_transaction_handler, generate_proof_handler, get_balances_handler, get_ores_handler, - get_transactions_handler, import_vk_handler, latest_block_handler, remove_account_handler, -}; - -pub mod config; -pub mod constants; -pub mod db_handler; -pub mod error; -pub mod orescriptions; -pub mod rpc_handler; -pub mod web_handlers; - -#[derive(Debug, Clone)] -pub struct SharedState { - pub db_handler: T, - pub rpc_handler: RpcHandler, -} - -impl SharedState -where - T: DBHandler, -{ - pub fn new(db_handler: T, endpoint: &str) -> Self { - Self { - db_handler: db_handler, - rpc_handler: RpcHandler::new(endpoint.into()), - } - } -} - -pub async fn run_server( - listen: SocketAddr, - rpc_server: String, - db_handler: PgHandler, -) -> Result<()> { - let shared_state = SharedState::new(db_handler, &rpc_server); - let router = Router::new() - .route("/import", post(import_vk_handler)) - .route("/remove", post(remove_account_handler)) - .route("/getBalances", post(get_balances_handler)) - .route("/getTransaction", post(account_transaction_handler)) - .route("/getTransactions", post(get_transactions_handler)) - .route("/createTx", post(create_transaction_handler)) - .route("/broadcastTx", post(broadcast_transaction_handler)) - .route("/accountStatus", post(account_status_handler)) - .route("/latestBlock", get(latest_block_handler)) - .route("/ores", post(get_ores_handler)) - .with_state(shared_state) - .layer( - ServiceBuilder::new() - .layer(HandleErrorLayer::new(|_: BoxError| async { - StatusCode::REQUEST_TIMEOUT - })) - .layer(TimeoutLayer::new(Duration::from_secs(30))), - ) - .layer( - CorsLayer::new() - .allow_methods(Any) - .allow_origin(Any) - .allow_headers(Any), - ); - - let listener = TcpListener::bind(&listen).await?; - info!("Server listening on {}", listen); - axum::serve(listener, router).await?; - Ok(()) -} - -pub async fn run_prover(listen: SocketAddr) -> Result<()> { - let router = Router::new() - .route("/generateProofs", post(generate_proof_handler)) - .layer( - ServiceBuilder::new() - .layer(HandleErrorLayer::new(|_: BoxError| async { - StatusCode::REQUEST_TIMEOUT - })) - .layer(TimeoutLayer::new(Duration::from_secs(30))), - ) - .layer( - CorsLayer::new() - .allow_methods(Any) - .allow_origin(Any) - .allow_headers(Any), - ); - let listener = TcpListener::bind(&listen).await?; - info!("Prover listening on {}", listen); - axum::serve(listener, router).await?; - Ok(()) -} - -pub fn initialize_logger(verbosity: u8) { - match verbosity { - 0 => std::env::set_var("RUST_LOG", "info"), - 1 => std::env::set_var("RUST_LOG", "debug"), - 2 | 3 | 4 => std::env::set_var("RUST_LOG", "trace"), - _ => std::env::set_var("RUST_LOG", "info"), - }; - tracing_subscriber::fmt() - .with_env_filter( - EnvFilter::from_default_env().add_directive("ironfish-server=info".parse().unwrap()), - ) - .init(); -} - -pub async fn handle_signals() -> anyhow::Result<()> { - let (router, handler) = oneshot::channel(); - tokio::spawn(async move { - let _ = router.send(()); - match tokio::signal::ctrl_c().await { - Ok(()) => { - info!("Shutdowning..."); - tokio::time::sleep(Duration::from_millis(5000)).await; - info!("Goodbye"); - std::process::exit(0); - } - Err(error) => warn!("tokio::signal::ctrl_c encountered an error: {}", error), - } - }); - let _ = handler.await; - info!("Signal handler installed"); - Ok(()) -} - -#[cfg(test)] -mod tests { - use axum::response::IntoResponse; - use bellperson::groth16::Proof; - use blstrs::Bls12; - use ff::{Field, PrimeField, PrimeFieldBits}; - use group::{Curve, Group}; - use ironfish_zkp::constants::PUBLIC_KEY_GENERATOR; - use ironfish_zkp::proofs::{MintAsset, Output}; - use ironfish_zkp::util::{asset_hash_to_point, commitment_full_point}; - use ironfish_zkp::{primitives::ValueCommitment, proofs::Spend}; - use rand::Rng; - use rand::{rngs::StdRng, RngCore, SeedableRng}; - use zcash_primitives::constants::VALUE_COMMITMENT_VALUE_GENERATOR; - use zcash_primitives::sapling::{pedersen_hash, Note, ProofGenerationKey, Rseed}; - - use crate::error::OreoError; - use crate::web_handlers::abi::{GenerateProofRep, GenerateProofReq}; - - fn build_spend() -> Spend { - let mut rng = StdRng::seed_from_u64(0); - let tree_depth = 32; - - let value_commitment = ValueCommitment { - value: rng.next_u64(), - randomness: jubjub::Fr::random(&mut rng), - asset_generator: (*VALUE_COMMITMENT_VALUE_GENERATOR).into(), - }; - - let proof_generation_key = ProofGenerationKey { - ak: jubjub::SubgroupPoint::random(&mut rng), - nsk: jubjub::Fr::random(&mut rng), - }; - - let viewing_key = proof_generation_key.to_viewing_key(); - - let payment_address = *PUBLIC_KEY_GENERATOR * viewing_key.ivk().0; - let commitment_randomness = jubjub::Fr::random(&mut rng); - let auth_path = - vec![Some((blstrs::Scalar::random(&mut rng), rng.next_u32() % 2 != 0)); tree_depth]; - let ar = jubjub::Fr::random(&mut rng); - - let note = Note { - value: value_commitment.value, - g_d: *PUBLIC_KEY_GENERATOR, - pk_d: payment_address, - rseed: Rseed::BeforeZip212(commitment_randomness), - }; - - let commitment = commitment_full_point( - value_commitment.asset_generator, - value_commitment.value, - payment_address, - note.rcm(), - payment_address, - ); - let cmu = jubjub::ExtendedPoint::from(commitment).to_affine().get_u(); - - let mut cur = cmu; - - for (i, val) in auth_path.clone().into_iter().enumerate() { - let (uncle, b) = val.unwrap(); - - let mut lhs = cur; - let mut rhs = uncle; - - if b { - ::std::mem::swap(&mut lhs, &mut rhs); - } - - let lhs = lhs.to_le_bits(); - let rhs = rhs.to_le_bits(); - - cur = jubjub::ExtendedPoint::from(pedersen_hash::pedersen_hash( - pedersen_hash::Personalization::MerkleTree(i), - lhs.iter() - .by_vals() - .take(blstrs::Scalar::NUM_BITS as usize) - .chain(rhs.iter().by_vals().take(blstrs::Scalar::NUM_BITS as usize)), - )) - .to_affine() - .get_u(); - } - - Spend { - value_commitment: Some(value_commitment.clone()), - proof_generation_key: Some(proof_generation_key.clone()), - payment_address: Some(payment_address), - commitment_randomness: Some(commitment_randomness), - ar: Some(ar), - auth_path: auth_path.clone(), - anchor: Some(cur), - sender_address: Some(payment_address), - } - } - - fn build_output() -> Output { - let mut rng = StdRng::seed_from_u64(0); - let mut asset_id = [0u8; 32]; - let asset_generator = loop { - rng.fill(&mut asset_id[..]); - - if let Some(point) = asset_hash_to_point(&asset_id) { - break point; - } - }; - let value_commitment_randomness = jubjub::Fr::random(&mut rng); - let note_commitment_randomness = jubjub::Fr::random(&mut rng); - let value_commitment = ValueCommitment { - value: rng.next_u64(), - randomness: value_commitment_randomness, - asset_generator, - }; - - let nsk = jubjub::Fr::random(&mut rng); - let ak = jubjub::SubgroupPoint::random(&mut rng); - let esk = jubjub::Fr::random(&mut rng); - let ar = jubjub::Fr::random(&mut rng); - - let proof_generation_key = ProofGenerationKey { ak, nsk }; - - let viewing_key = proof_generation_key.to_viewing_key(); - - let payment_address = *PUBLIC_KEY_GENERATOR * viewing_key.ivk().0; - - Output { - value_commitment: Some(value_commitment.clone()), - payment_address: Some(payment_address), - commitment_randomness: Some(note_commitment_randomness), - esk: Some(esk), - asset_id, - proof_generation_key: Some(proof_generation_key.clone()), - ar: Some(ar), - } - } - - fn build_mint_asset() -> MintAsset { - let mut rng = StdRng::seed_from_u64(0); - let proof_generation_key = ProofGenerationKey { - ak: jubjub::SubgroupPoint::random(&mut rng), - nsk: jubjub::Fr::random(&mut rng), - }; - - let public_key_randomness = jubjub::Fr::random(&mut rng); - - MintAsset { - proof_generation_key: Some(proof_generation_key), - public_key_randomness: Some(public_key_randomness), - } - } - - #[tokio::test] - async fn generate_proofs_works() { - let client = reqwest::Client::new(); - let spend = build_spend(); - let output = build_output(); - let mint_asset = build_mint_asset(); - let mut spend_bytes = vec![]; - spend.write(&mut spend_bytes).unwrap(); - let mut output_bytes = vec![]; - output.write(&mut output_bytes).unwrap(); - let mut mint_asset_bytes = vec![]; - mint_asset.write(&mut mint_asset_bytes).unwrap(); - let body = GenerateProofReq { - spend_circuits: vec![spend_bytes], - output_circuits: vec![output_bytes], - mint_asset_circuits: vec![mint_asset_bytes], - }; - let response = client - .post("http://127.0.0.1:10001/generate_proofs") - .header("Content-Type", "application/json") - .json(&body) - .send() - .await - .expect("failed to generate proofs"); - assert!(response.status().is_success()); - let rep: GenerateProofRep = response.json().await.unwrap(); - if let Some(proof) = rep.spend_proofs.first() { - let proof: Proof = Proof::read(&proof[..]).unwrap(); - println!("response first spend proof {:?}", proof); - } - if let Some(proof) = rep.output_proofs.first() { - let proof: Proof = Proof::read(&proof[..]).unwrap(); - println!("response first output proof {:?}", proof); - } - if let Some(proof) = rep.mint_asset_proofs.first() { - let proof: Proof = Proof::read(&proof[..]).unwrap(); - println!("response first mint asset proof {:?}", proof); - } - } - - #[tokio::test] - async fn generate_proofs_failed() { - let client = reqwest::Client::new(); - let spend = build_spend(); - let spend2 = build_spend(); - let output = build_output(); - let mint_asset = build_mint_asset(); - let mut spend_bytes = vec![]; - spend.write(&mut spend_bytes).unwrap(); - let mut spend2_bytes = vec![]; - spend2.write(&mut spend2_bytes).unwrap(); - let mut output_bytes = vec![]; - output.write(&mut output_bytes).unwrap(); - let mut mint_asset_bytes = vec![]; - mint_asset.write(&mut mint_asset_bytes).unwrap(); - - // make spend2 circuit fail to generate a proof - spend2_bytes.truncate(100); - - let body = GenerateProofReq { - spend_circuits: vec![spend_bytes, spend2_bytes], - output_circuits: vec![output_bytes], - mint_asset_circuits: vec![mint_asset_bytes], - }; - let response = client - .post("http://127.0.0.1:10001/generate_proofs") - .header("Content-Type", "application/json") - .json(&body) - .send() - .await - .expect("failed to generate proofs"); - - let status1 = response.status(); - assert!(status1.is_success()); - - let error = response.json::().await.unwrap(); - let error_msg = error.to_string(); - assert_eq!( - error_msg, - OreoError::GenerateSpendProofFailed(1).to_string() - ); - - let response = error.into_response(); - let status = response.status(); - assert_eq!(status.as_u16(), 900); - } -} diff --git a/src/rpc_handler/handler.rs b/src/rpc_handler/handler.rs deleted file mode 100644 index 14ed914..0000000 --- a/src/rpc_handler/handler.rs +++ /dev/null @@ -1,188 +0,0 @@ -use std::{fmt::Debug, time::Duration}; - -use serde::Deserialize; -use serde_json::json; -use tracing::debug; -use ureq::{Agent, AgentBuilder, Error, Response}; - -use crate::{ - error::OreoError, - web_handlers::abi::{ - GetAccountStatusRep, GetAccountStatusReq, GetLatestBlockRep, RemoveAccountRep, - }, -}; - -use super::{abi::*, RpcError}; - -#[derive(Debug, Clone)] -pub struct RpcHandler { - pub endpoint: String, - pub agent: Agent, -} - -impl RpcHandler { - pub fn new(endpoint: String) -> Self { - Self { - endpoint, - agent: AgentBuilder::new() - .timeout_read(Duration::from_secs(5)) - .timeout_write(Duration::from_secs(5)) - .build(), - } - } - - pub async fn import_view_only( - &self, - req: ImportAccountReq, - ) -> Result, OreoError> { - let path = format!("http://{}/wallet/importAccount", self.endpoint); - let resp = self - .agent - .clone() - .post(&path) - .send_json(ureq::json!({"account": req})); - handle_response(resp) - } - - pub async fn remove_account( - &self, - req: RemoveAccountReq, - ) -> Result, OreoError> { - debug!("req: {:?}", req); - let path = format!("http://{}/wallet/removeAccount", self.endpoint); - let resp = self - .agent - .clone() - .post(&path) - .send_json(&req) - .map(|res| match res.status() { - 200 => Response::new(200, "OK", "{\"status\":200,\"data\":{\"removed\":true}}") - .unwrap(), - _ => res, - }); - handle_response(resp) - } - - pub async fn get_balance( - &self, - req: GetBalancesReq, - ) -> Result, OreoError> { - let path = format!("http://{}/wallet/getBalances", self.endpoint); - let resp = self.agent.clone().post(&path).send_json(&req); - handle_response(resp) - } - - pub async fn get_transactions( - &self, - req: GetTransactionsReq, - ) -> Result, OreoError> { - let path = format!("http://{}/wallet/getAccountTransactions", self.endpoint); - let resp = self.agent.clone().post(&path).send_json(&req); - handle_response(resp) - } - - pub async fn create_transaction( - &self, - req: CreateTxReq, - ) -> Result, OreoError> { - let path = format!("http://{}/wallet/createTransaction", self.endpoint); - let resp = self.agent.clone().post(&path).send_json(&req); - handle_response(resp) - } - - pub async fn broadcast_transaction( - &self, - req: BroadcastTxReq, - ) -> Result, OreoError> { - let path = format!("http://{}/chain/broadcastTransaction", self.endpoint); - let resp = self.agent.clone().post(&path).send_json(&req); - handle_response(resp) - } - - pub async fn get_account_status( - &self, - req: GetAccountStatusReq, - ) -> Result, OreoError> { - let path = format!("http://{}/wallet/getAccountStatus", self.endpoint); - let resp = self.agent.clone().post(&path).send_json(&req); - handle_response(resp) - } - - pub async fn get_latest_block(&self) -> Result, OreoError> { - let path = format!("http://{}/chain/getChainInfo", self.endpoint); - let resp = self.agent.clone().get(&path).call(); - handle_response(resp) - } - - pub async fn get_account_transaction( - &self, - req: GetAccountTransactionReq, - ) -> Result, OreoError> { - let path = format!("http://{}/wallet/getAccountTransaction", self.endpoint); - let resp = self.agent.clone().post(&path).send_json(&req); - handle_response(resp) - } - - pub async fn get_asset(&self, id: String) -> Result, OreoError> { - let path = format!("http://{}/chain/getAsset", self.endpoint); - let resp = self.agent.clone().post(&path).send_json(&json!({ - "id": id - })); - handle_response(resp) - } - - pub async fn get_note_witness( - &self, - req: GetNoteWitnessReq, - ) -> Result, OreoError> { - let path = format!("http://{}/chain/getNoteWitness", self.endpoint); - let resp = self.agent.clone().post(&path).send_json(req); - handle_response(resp) - } - - pub async fn export_account( - &self, - account: String, - ) -> Result, OreoError> { - let path = format!("http://{}/wallet/exportAccount", self.endpoint); - let resp = self - .agent - .clone() - .post(&path) - .send_json(json!({"account": account, "format": "JSON".to_string()})); - handle_response(resp) - } -} - -pub fn handle_response Deserialize<'a>>( - resp: Result, -) -> Result, OreoError> { - let res = match resp { - Ok(response) => match response.into_json::>() { - Ok(data) => Ok(data), - Err(e) => Err(RpcError { - code: "Unknown".into(), - status: 606, - message: e.to_string(), - }), - }, - Err(ureq::Error::Status(_code, response)) => match response.into_json::() { - Ok(data) => Err(data), - Err(e) => Err(RpcError { - code: "Unknown".into(), - status: 606, - message: e.to_string(), - }), - }, - Err(e) => Err(RpcError { - code: "Unknown".into(), - status: 606, - message: e.to_string(), - }), - }; - debug!("Handle rpc response: {:?}", res); - match res { - Ok(data) => Ok(data), - Err(e) => Err(OreoError::try_from(e).unwrap()), - } -} diff --git a/src/web_handlers/account.rs b/src/web_handlers/account.rs deleted file mode 100644 index 3c8aeee..0000000 --- a/src/web_handlers/account.rs +++ /dev/null @@ -1,285 +0,0 @@ -use axum::{ - extract::{self, State}, - response::IntoResponse, -}; - -use crate::{ - constants::ACCOUNT_VERSION, - db_handler::DBHandler, - error::OreoError, - rpc_handler::abi::{ - BroadcastTxReq, CreateTxReq, GetAccountTransactionReq, GetBalancesRep, GetBalancesReq, - GetNoteWitnessReq, GetTransactionsReq, ImportAccountReq as RpcImportReq, OutPut, - RemoveAccountReq as RpcRemoveAccountReq, RpcResponse, - }, - SharedState, -}; - -use super::abi::{GetAccountStatusReq, GetTransactionDetail, ImportAccountReq, RemoveAccountReq}; - -pub async fn import_vk_handler( - State(shared): State>, - extract::Json(import): extract::Json, -) -> impl IntoResponse { - let account_name = shared - .db_handler - .save_account(import.clone().to_account(), 0) - .await; - if let Err(e) = account_name { - return e.into_response(); - } - let ImportAccountReq { - view_key, - incoming_view_key, - outgoing_view_key, - public_address, - created_at, - } = import; - let rpc_data = RpcImportReq { - view_key, - incoming_view_key, - outgoing_view_key, - public_address, - version: ACCOUNT_VERSION, - name: account_name.unwrap(), - created_at, - }; - shared - .rpc_handler - .import_view_only(rpc_data) - .await - .into_response() -} - -pub async fn remove_account_handler( - State(shared): State>, - extract::Json(remove_account): extract::Json, -) -> impl IntoResponse { - let db_account = shared - .db_handler - .get_account(remove_account.account.clone()) - .await; - if let Err(e) = db_account { - return e.into_response(); - } - let result = shared - .rpc_handler - .remove_account(RpcRemoveAccountReq { - account: db_account.unwrap().name, - confirm: Some(true), - wait: Some(true), - }) - .await; - match result { - Ok(response) => { - if let Err(e) = shared - .db_handler - .remove_account(remove_account.account.clone()) - .await - { - return e.into_response(); - } - response.into_response() - } - Err(e) => e.into_response(), - } -} - -pub async fn get_balances_handler( - State(shared): State>, - extract::Json(get_balance): extract::Json, -) -> impl IntoResponse { - let db_account = shared - .db_handler - .get_account(get_balance.account.clone()) - .await; - if let Err(e) = db_account { - return e.into_response(); - } - let resp = shared - .rpc_handler - .get_balance(GetBalancesReq { - account: db_account.unwrap().name, - confirmations: Some(get_balance.confirmations.unwrap_or(10)), - }) - .await; - match resp { - Ok(res) => { - let response = RpcResponse { - status: 200, - data: GetBalancesRep::verified_asset(res.data), - }; - response.into_response() - } - Err(e) => e.into_response(), - } -} - -pub async fn get_ores_handler( - State(shared): State>, - extract::Json(get_balance): extract::Json, -) -> impl IntoResponse { - let db_account = shared - .db_handler - .get_account(get_balance.account.clone()) - .await; - if let Err(e) = db_account { - return e.into_response(); - } - let resp = shared - .rpc_handler - .get_balance(GetBalancesReq { - account: db_account.unwrap().name, - confirmations: Some(get_balance.confirmations.unwrap_or(10)), - }) - .await; - match resp { - Ok(res) => { - let response = RpcResponse { - status: 200, - data: GetBalancesRep::ores(res.data).await, - }; - response.into_response() - } - Err(e) => e.into_response(), - } -} - -pub async fn get_transactions_handler( - State(shared): State>, - extract::Json(get_transactions): extract::Json, -) -> impl IntoResponse { - let db_account = shared - .db_handler - .get_account(get_transactions.account.clone()) - .await; - if let Err(e) = db_account { - return e.into_response(); - } - shared - .rpc_handler - .get_transactions(GetTransactionsReq { - account: db_account.unwrap().name, - limit: Some(get_transactions.limit.unwrap_or(6)), - reverse: Some(true), - }) - .await - .into_response() -} - -pub async fn create_transaction_handler( - State(shared): State>, - extract::Json(create_transaction): extract::Json, -) -> impl IntoResponse { - let db_account = shared - .db_handler - .get_account(create_transaction.account.clone()) - .await; - if let Err(e) = db_account { - return e.into_response(); - } - let outputs: Vec = create_transaction - .outputs - .unwrap_or(vec![]) - .iter() - .map(|output| OutPut::from(output.clone())) - .collect(); - let mut mints = vec![]; - for item in create_transaction.mints.unwrap_or(vec![]).into_iter() { - if item.asset_id.is_none() && item.name.is_none() { - return OreoError::BadMintRequest.into_response(); - } else { - mints.push(item); - } - } - let burns = create_transaction.burns.unwrap_or(vec![]); - shared - .rpc_handler - .create_transaction(CreateTxReq { - account: db_account.unwrap().name, - outputs: Some(outputs), - fee: Some(create_transaction.fee.unwrap_or("1".into())), - expiration_delta: Some(create_transaction.expiration_delta.unwrap_or(30)), - mints: Some(mints), - burns: Some(burns), - }) - .await - .into_response() -} - -pub async fn broadcast_transaction_handler( - State(shared): State>, - extract::Json(broadcast_transaction): extract::Json, -) -> impl IntoResponse { - shared - .rpc_handler - .broadcast_transaction(broadcast_transaction) - .await - .into_response() -} - -pub async fn account_status_handler( - State(shared): State>, - extract::Json(account): extract::Json, -) -> impl IntoResponse { - let db_account = shared.db_handler.get_account(account.account.clone()).await; - if let Err(e) = db_account { - return e.into_response(); - } - shared - .rpc_handler - .get_account_status(GetAccountStatusReq { - account: db_account.unwrap().name, - }) - .await - .into_response() -} - -pub async fn latest_block_handler( - State(shared): State>, -) -> impl IntoResponse { - shared.rpc_handler.get_latest_block().await.into_response() -} - -pub async fn note_witness_handler( - State(shared): State>, - extract::Json(req): extract::Json, -) -> impl IntoResponse { - shared - .rpc_handler - .get_note_witness(req) - .await - .into_response() -} - -pub async fn account_transaction_handler( - State(shared): State>, - extract::Json(account): extract::Json, -) -> impl IntoResponse { - let db_account = shared.db_handler.get_account(account.account.clone()).await; - if let Err(e) = db_account { - return e.into_response(); - } - let rpc_transaction = shared - .rpc_handler - .get_account_transaction(GetAccountTransactionReq { - account: db_account.unwrap().name, - hash: account.hash, - notes: Some(true), - }) - .await; - match rpc_transaction { - Ok(RpcResponse { data, status: _ }) => { - let transaction_detail = GetTransactionDetail::from_rpc_data(data); - match transaction_detail { - Ok(detail) => RpcResponse { - status: 200, - data: detail, - } - .into_response(), - Err(e) => e.into_response(), - } - } - Err(e) => e.into_response(), - } -} diff --git a/src/web_handlers/mod.rs b/src/web_handlers/mod.rs deleted file mode 100644 index fad8e08..0000000 --- a/src/web_handlers/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod abi; -mod account; -mod proof; - -pub use account::*; -pub use proof::*;