From c08d75ed49178fcea6cd278c643757af8aaf0307 Mon Sep 17 00:00:00 2001 From: serejkaaa512 <5125402@mail.ru> Date: Wed, 22 Nov 2023 15:32:40 +0300 Subject: [PATCH 1/3] core: add keystore naive impl --- Cargo.lock | 246 ++++++++++++++++++++++++++---------- core/Cargo.toml | 10 +- core/src/keystore/mod.rs | 125 ++++++++++++++++++ core/src/keystore/models.rs | 53 ++++++++ core/src/keystore/utils.rs | 29 +++++ core/src/lib.rs | 2 + 6 files changed, 394 insertions(+), 71 deletions(-) create mode 100644 core/src/keystore/mod.rs create mode 100644 core/src/keystore/models.rs create mode 100644 core/src/keystore/utils.rs diff --git a/Cargo.lock b/Cargo.lock index be80f1e42..6f98a906d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.8.7" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f" dependencies = [ "cfg-if", "getrandom", @@ -112,7 +112,7 @@ dependencies = [ "argh_shared", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -223,7 +223,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -238,6 +238,15 @@ version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -249,9 +258,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "a3b1be7772ee4501dba05acbe66bb1e8760f6a6c474a36035631638e4415f130" [[package]] name = "bytecount" @@ -259,6 +268,12 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.5.0" @@ -290,9 +305,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" +checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" dependencies = [ "serde", ] @@ -320,11 +335,10 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730" dependencies = [ - "jobserver", "libc", ] @@ -385,7 +399,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -488,7 +502,20 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", +] + +[[package]] +name = "curve25519-dalek-ng" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core", + "subtle-ng", + "zeroize", ] [[package]] @@ -543,13 +570,22 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", + "block-buffer 0.10.4", "crypto-common", ] @@ -561,7 +597,16 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", +] + +[[package]] +name = "ed25519" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "signature 1.6.4", ] [[package]] @@ -571,7 +616,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", - "signature", + "signature 2.2.0", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "git+https://github.com/broxus/ed25519-dalek.git#e5d68fd1490a7f6a0d473c6c1b1acef868960471" +dependencies = [ + "curve25519-dalek-ng", + "ed25519 1.5.3", + "rand", + "serde", + "sha2 0.9.9", + "zeroize", ] [[package]] @@ -603,7 +661,7 @@ dependencies = [ "generic-array", "hex", "rand", - "sha2", + "sha2 0.10.8", "tl-proto", ] @@ -633,7 +691,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -710,9 +768,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" +checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" [[package]] name = "hex" @@ -732,15 +790,6 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" -[[package]] -name = "jobserver" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" -dependencies = [ - "libc", -] - [[package]] name = "js-sys" version = "0.3.68" @@ -827,6 +876,9 @@ name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +dependencies = [ + "serde", +] [[package]] name = "lz4-sys" @@ -989,6 +1041,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "overload" version = "0.1.1" @@ -1065,7 +1123,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -1076,7 +1134,7 @@ checksum = "d0934d6907f148c22a3acbda520c7eed243ad7487a30f51f6ce52b58b7077a8a" dependencies = [ "once_cell", "pest", - "sha2", + "sha2 0.10.8", ] [[package]] @@ -1103,9 +1161,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "platforms" @@ -1132,7 +1190,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" dependencies = [ "proc-macro2", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -1347,16 +1405,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin 0.9.8", "untrusted 0.9.0", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1419,7 +1478,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring 0.17.7", + "ring 0.17.8", "rustls-webpki", "sct", ] @@ -1430,7 +1489,7 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.7", + "ring 0.17.8", "untrusted 0.9.0", ] @@ -1442,9 +1501,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[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 = "same-file" @@ -1467,50 +1526,63 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.7", + "ring 0.17.8", "untrusted 0.9.0", ] [[package]] name = "semver" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] name = "serde_json" -version = "1.0.113" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", "serde", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha2" version = "0.10.8" @@ -1519,7 +1591,7 @@ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.7", ] [[package]] @@ -1537,6 +1609,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" + [[package]] name = "signature" version = "2.2.0" @@ -1620,6 +1698,12 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "subtle-ng" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" + [[package]] name = "syn" version = "1.0.109" @@ -1633,9 +1717,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" dependencies = [ "proc-macro2", "quote", @@ -1674,29 +1758,29 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[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", @@ -1765,8 +1849,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3418163db528cc2324ed7bc9d52aa3ca7a8f73d685f8b21b319d2a08ee4b36d3" dependencies = [ "bytes", - "digest", - "sha2", + "digest 0.10.7", + "sha2 0.10.8", "smallvec", "thiserror", "tl-proto-proc", @@ -1781,7 +1865,7 @@ dependencies = [ "proc-macro2", "quote", "rustc-hash", - "syn 2.0.48", + "syn 2.0.50", "tl-scheme", ] @@ -1823,7 +1907,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -1871,7 +1955,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -1974,6 +2058,14 @@ dependencies = [ name = "tycho-core" version = "0.0.1" dependencies = [ + "anyhow", + "dashmap", + "ed25519-dalek", + "hex", + "log", + "rand", + "serde", + "serde_json", "tycho-network", "tycho-storage", "tycho-util", @@ -1990,7 +2082,7 @@ dependencies = [ "bytes", "castaway", "dashmap", - "ed25519", + "ed25519 2.2.3", "everscale-crypto", "futures-util", "hex", @@ -2167,7 +2259,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", "wasm-bindgen-shared", ] @@ -2189,7 +2281,7 @@ checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2428,7 +2520,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.50", ] [[package]] @@ -2436,6 +2528,20 @@ name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.50", +] [[package]] name = "zstd-sys" diff --git a/core/Cargo.toml b/core/Cargo.toml index d9fab0eff..d930a13be 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -6,6 +6,14 @@ description = "Basic functionality of peer." [dependencies] # crates.io deps +anyhow = "1.0.70" +dashmap = "5.4.0" +ed25519-dalek = { git = "https://github.com/broxus/ed25519-dalek.git" } +hex = "0.4" +rand = "0.8" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +log = { version = "0.4", features = ["std", "serde"] } # local deps tycho-network = { path = "../network", version = "=0.0.1" } @@ -13,4 +21,4 @@ tycho-storage = { path = "../storage", version = "=0.0.1" } tycho-util = { path = "../util", version = "=0.0.1" } [lints] -workspace= true \ No newline at end of file +workspace= true diff --git a/core/src/keystore/mod.rs b/core/src/keystore/mod.rs new file mode 100644 index 000000000..0ab75e24e --- /dev/null +++ b/core/src/keystore/mod.rs @@ -0,0 +1,125 @@ +use std::fs::File; +use std::io::Seek; +use std::io::Write; +use std::path::Path; +use std::sync::Arc; + +use anyhow::{Context, Result}; +use dashmap::DashMap; +use ed25519_dalek::{Keypair, PublicKey, Signer}; + +use crate::keystore::models::NodeKeys; +use crate::utils::generate_key_pair; + +mod models; +pub mod utils; + +pub trait KeyStore { + fn regenerate_network_key(&mut self) -> Result; + fn create_validator_key(&self, timestamp: i64) -> Result; + fn get_validator_key(&self, timestamp: i64) -> Option; + fn delete_validator_key(&self, timestamp: i64); + fn sign_by_network_key(&self, data: &[u8]) -> [u8; 64]; + fn sign_by_validator_key(&self, timestamp: i64, data: &[u8]) -> Result<[u8; 64]>; +} + +#[derive(Clone)] +pub struct KeyStoreImpl { + network_key: Arc, + validator_keys: Arc>, +} + +impl KeyStoreImpl { + pub fn generate(timestamp: i64) -> Result { + let mut rng = rand::thread_rng(); + let network_key = Arc::new(generate_key_pair(&mut rng)?); + let keypair = generate_key_pair(&mut rng)?; + + let validator_keys = DashMap::new(); + validator_keys.insert(timestamp, keypair); + + Ok(Self { + network_key, + validator_keys: Arc::new(validator_keys), + }) + } + + pub fn load

(path: P, force_regenerate: bool, timestamp: Option) -> Result + where + P: AsRef + std::fmt::Display + Clone, + { + let file = std::fs::OpenOptions::new() + .create(true) + .write(true) + .read(true) + .open(path.clone()) + .context("Failed to open keystore keys")?; + + let keys = if force_regenerate { + Self::generate(timestamp.unwrap_or_default()) + } else { + match serde_json::from_reader::<&File, NodeKeys>(&file) { + Ok(keys) => Self::try_from(keys), + Err(_) => { + log::warn!("failed to read keys, generating new"); + Self::generate(timestamp.unwrap_or_default()) + } + } + }?; + + keys.save(file) + .context(format!("Failed to save keys to {}", path))?; + + Ok(keys) + } + + pub fn save(&self, mut file: W) -> Result<()> + where + W: Write + Seek, + { + file.rewind()?; + serde_json::to_writer_pretty(file, &NodeKeys::from(self))?; + Ok(()) + } +} + +impl KeyStore for KeyStoreImpl { + fn regenerate_network_key(&mut self) -> Result { + let mut rng = rand::thread_rng(); + let key_pair = Arc::new(generate_key_pair(&mut rng)?); + let public_key = key_pair.public; + self.network_key = key_pair; + Ok(public_key) + } + + fn create_validator_key(&self, timestamp: i64) -> Result { + let mut rng = rand::thread_rng(); + let key_pair = generate_key_pair(&mut rng)?; + let public_key = key_pair.public; + self.validator_keys.insert(timestamp, key_pair); + Ok(public_key) + } + + fn get_validator_key(&self, timestamp: i64) -> Option { + self.validator_keys + .get(×tamp) + .map(|r| r.value().public) + } + + fn delete_validator_key(&self, timestamp: i64) { + self.validator_keys.remove(×tamp); + } + + fn sign_by_network_key(&self, data: &[u8]) -> [u8; 64] { + self.network_key.sign(&data).to_bytes() + } + + fn sign_by_validator_key(&self, timestamp: i64, data: &[u8]) -> Result<[u8; 64]> { + if let Some(r) = self.validator_keys.get(×tamp) { + let keypair = r.value(); + Ok(keypair.sign(&data).to_bytes()) + } else { + Err(anyhow::anyhow!("No key for timestamp {} found", timestamp)) + } + } +} diff --git a/core/src/keystore/models.rs b/core/src/keystore/models.rs new file mode 100644 index 000000000..8040d52b3 --- /dev/null +++ b/core/src/keystore/models.rs @@ -0,0 +1,53 @@ +use std::collections::HashMap; +use std::sync::Arc; + +use anyhow::Result; +use dashmap::DashMap; +use ed25519_dalek::{Keypair, PublicKey, SecretKey}; + +use crate::KeyStoreImpl; + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct NodeKeys { + pub network_key: String, + pub validator_keys: HashMap, +} + +impl TryFrom for KeyStoreImpl { + type Error = anyhow::Error; + + fn try_from(value: NodeKeys) -> Result { + let secret = SecretKey::from_bytes(&hex::decode(value.network_key)?)?; + let public = PublicKey::from(&secret); + let network_key = Arc::new(Keypair { secret, public }); + + let validator_keys_dash: DashMap = DashMap::new(); + + for (timestamp, key) in value.validator_keys { + let secret = SecretKey::from_bytes(&hex::decode(key)?)?; + let public = PublicKey::from(&secret); + let key = Keypair { secret, public }; + validator_keys_dash.insert(timestamp, key); + } + Ok(Self { + network_key, + validator_keys: Arc::new(validator_keys_dash), + }) + } +} + +impl From<&KeyStoreImpl> for NodeKeys { + fn from(value: &KeyStoreImpl) -> Self { + let network_key = hex::encode(&value.network_key.secret); + + let mut validator_keys = HashMap::new(); + + for r in value.validator_keys.iter() { + validator_keys.insert(*r.key(), hex::encode(&r.value().secret)); + } + Self { + network_key, + validator_keys, + } + } +} diff --git a/core/src/keystore/utils.rs b/core/src/keystore/utils.rs new file mode 100644 index 000000000..9055f577a --- /dev/null +++ b/core/src/keystore/utils.rs @@ -0,0 +1,29 @@ +use anyhow::Result; +use ed25519_dalek::{Keypair, PublicKey, SecretKey, Signature, Verifier, SECRET_KEY_LENGTH}; +use rand::rngs::ThreadRng; +use rand::Rng; + +pub fn generate_key_pair(rng: &mut ThreadRng) -> Result { + let secret = SecretKey::from_bytes(&rng.gen::<[u8; SECRET_KEY_LENGTH]>())?; + let public = PublicKey::from(&secret); + Ok(Keypair { secret, public }) +} + +pub fn verify_signatures( + message: &[u8], + signatures: Vec<(PublicKey, &[u8; 64])>, +) -> Vec> { + let mut result = vec![]; + for (public, sign) in signatures { + let r = if let Ok(sign) = Signature::from_bytes(sign) { + match public.verify(message, &sign) { + Ok(_) => Ok(public), + Err(_) => Err(public), + } + } else { + Err(public) + }; + result.push(r); + } + result +} diff --git a/core/src/lib.rs b/core/src/lib.rs index 8b1378917..2dfa3f07a 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1 +1,3 @@ +mod keystore; +pub use keystore::*; From 6d7e5a1848fcccbdf662f7f21833bbf6fbd0248e Mon Sep 17 00:00:00 2001 From: serejkaaa512 <5125402@mail.ru> Date: Wed, 22 Nov 2023 15:36:13 +0300 Subject: [PATCH 2/3] clippy --- core/src/keystore/mod.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/core/src/keystore/mod.rs b/core/src/keystore/mod.rs index 0ab75e24e..34c83814a 100644 --- a/core/src/keystore/mod.rs +++ b/core/src/keystore/mod.rs @@ -58,12 +58,11 @@ impl KeyStoreImpl { let keys = if force_regenerate { Self::generate(timestamp.unwrap_or_default()) } else { - match serde_json::from_reader::<&File, NodeKeys>(&file) { - Ok(keys) => Self::try_from(keys), - Err(_) => { - log::warn!("failed to read keys, generating new"); - Self::generate(timestamp.unwrap_or_default()) - } + if let Ok(keys) = serde_json::from_reader::<&File, NodeKeys>(&file) { + Self::try_from(keys) + } else { + log::warn!("failed to read keys, generating new"); + Self::generate(timestamp.unwrap_or_default()) } }?; @@ -111,13 +110,13 @@ impl KeyStore for KeyStoreImpl { } fn sign_by_network_key(&self, data: &[u8]) -> [u8; 64] { - self.network_key.sign(&data).to_bytes() + self.network_key.sign(data).to_bytes() } fn sign_by_validator_key(&self, timestamp: i64, data: &[u8]) -> Result<[u8; 64]> { if let Some(r) = self.validator_keys.get(×tamp) { let keypair = r.value(); - Ok(keypair.sign(&data).to_bytes()) + Ok(keypair.sign(data).to_bytes()) } else { Err(anyhow::anyhow!("No key for timestamp {} found", timestamp)) } From c04eb28d0521462f1d2c6c67c1fecd4300021ef7 Mon Sep 17 00:00:00 2001 From: serejkaaa512 <5125402@mail.ru> Date: Wed, 22 Nov 2023 17:56:21 +0300 Subject: [PATCH 3/3] clippy --- core/src/keystore/mod.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/core/src/keystore/mod.rs b/core/src/keystore/mod.rs index 34c83814a..421e69a49 100644 --- a/core/src/keystore/mod.rs +++ b/core/src/keystore/mod.rs @@ -57,13 +57,11 @@ impl KeyStoreImpl { let keys = if force_regenerate { Self::generate(timestamp.unwrap_or_default()) + } else if let Ok(keys) = serde_json::from_reader::<&File, NodeKeys>(&file) { + Self::try_from(keys) } else { - if let Ok(keys) = serde_json::from_reader::<&File, NodeKeys>(&file) { - Self::try_from(keys) - } else { - log::warn!("failed to read keys, generating new"); - Self::generate(timestamp.unwrap_or_default()) - } + log::warn!("failed to read keys, generating new"); + Self::generate(timestamp.unwrap_or_default()) }?; keys.save(file)