diff --git a/Cargo.lock b/Cargo.lock index cab26e4..0611770 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 4 [[package]] name = "addr2line" -version = "0.24.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aead" @@ -28,9 +28,9 @@ dependencies = [ [[package]] name = "age" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23100453ca2a1bbda9bfc6deac1bebb828d7e66ba481ebccfedfddf29321b6b9" +checksum = "815e87cc8c39227cfff259f9550bd9f1c1a082370eccf4e9a176327fb7f906c9" dependencies = [ "age-core", "base64 0.13.1", @@ -45,7 +45,7 @@ dependencies = [ "nom", "pin-project", "rand 0.7.3", - "rand 0.8.5", + "rand 0.8.6", "rust-embed", "scrypt", "sha2 0.9.9", @@ -65,26 +65,20 @@ dependencies = [ "cookie-factory", "hkdf", "nom", - "rand 0.8.5", + "rand 0.8.6", "secrecy 0.8.0", "sha2 0.9.9", ] [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] -[[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" @@ -114,15 +108,18 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.92" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "arc-swap" -version = "1.7.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207" +dependencies = [ + "rustversion", +] [[package]] name = "arrayref" @@ -159,7 +156,7 @@ checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", - "pin-project-lite 0.2.15", + "pin-project-lite 0.2.17", ] [[package]] @@ -168,9 +165,9 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -190,28 +187,28 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" dependencies = [ - "autocfg 1.4.0", + "autocfg 1.5.1", ] [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", - "cfg-if 1.0.0", + "cfg-if 1.0.4", "libc", "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-link", ] [[package]] @@ -244,15 +241,15 @@ checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" -version = "1.6.0" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "basic-toml" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" +checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" dependencies = [ "serde", ] @@ -269,18 +266,21 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9ff0bbfd639f15c74af777d81383cf53efb7c93613f6cab67c6c11e05bbf8b" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bit-vec" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" -[[package]] -name = "bitflags" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" - [[package]] name = "bitflags" version = "1.3.2" @@ -289,9 +289,12 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a" +dependencies = [ + "serde_core", +] [[package]] name = "blake2-rfc" @@ -361,18 +364,18 @@ checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" [[package]] name = "built" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" +checksum = "5c0e531d93d39c34eef561e929e8a7f86d77a5af08aac4f6d6e39976c51858e9" dependencies = [ "git2", ] [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "byte-tools" @@ -404,15 +407,15 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[package]] name = "bytes" -version = "1.8.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "cc" -version = "1.2.56" +version = "1.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" dependencies = [ "find-msvc-tools", "jobserver", @@ -428,9 +431,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chacha20" @@ -438,7 +441,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.4", "cipher", "cpufeatures", "zeroize", @@ -459,17 +462,16 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits 0.2.19", "serde", "wasm-bindgen", - "windows-targets", + "windows-link", ] [[package]] @@ -518,7 +520,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2" dependencies = [ - "futures 0.3.31", + "futures 0.3.32", ] [[package]] @@ -531,6 +533,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -539,20 +551,20 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.4", ] [[package]] @@ -576,9 +588,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -594,16 +606,25 @@ dependencies = [ ] [[package]] -name = "crossbeam-utils" -version = "0.8.20" +name = "crossbeam-queue" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array 0.14.7", "typenum", @@ -621,21 +642,21 @@ dependencies = [ [[package]] name = "csv" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" dependencies = [ "csv-core", - "itoa 1.0.11", + "itoa 1.0.18", "ryu", - "serde", + "serde_core", ] [[package]] name = "csv-core" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" dependencies = [ "memchr", ] @@ -646,7 +667,7 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ - "quote 1.0.37", + "quote 1.0.45", "syn 1.0.109", ] @@ -682,28 +703,39 @@ version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.4", "hashbrown 0.14.5", - "lock_api 0.4.12", + "lock_api 0.4.14", "once_cell", - "parking_lot_core 0.9.10", + "parking_lot_core 0.9.12", ] [[package]] name = "data-encoding" -version = "2.6.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] -name = "derivative" -version = "2.2.0" +name = "derive_more" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 1.0.109", + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "proc-macro2 1.0.106", + "quote 1.0.45", + "rustc_version", + "syn 2.0.117", + "unicode-xid 0.2.6", ] [[package]] @@ -783,7 +815,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf36e65a80337bea855cd4ef9b8401ffce06a7baedf2e85ec467b1ac3f6e82b6" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.4", "dirs-sys-next", ] @@ -793,7 +825,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.4", "dirs-sys-next", ] @@ -821,13 +853,22 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", +] + +[[package]] +name = "doxygen-rs" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415b6ec780d34dcf624666747194393603d0373b7141eef01d12ee58881507d9" +dependencies = [ + "phf", ] [[package]] @@ -849,7 +890,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6368dbd2c6685fb84fc6e6a4749917ddc98905793fd06341c7e11a2504f2724" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro2 0.4.30", "quote 0.6.13", "syn 0.15.44", @@ -880,9 +921,9 @@ dependencies = [ [[package]] name = "either" -version = "1.13.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "encode_unicode" @@ -896,7 +937,7 @@ version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.4", ] [[package]] @@ -910,25 +951,25 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "fastrand" -version = "2.1.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "find-crate" @@ -947,9 +988,9 @@ checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "flate2" -version = "1.0.34" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", @@ -975,7 +1016,7 @@ dependencies = [ "fluent-syntax", "intl-memoizer", "intl_pluralrules", - "rustc-hash", + "rustc-hash 1.1.0", "self_cell 0.10.3", "smallvec", "unic-langid", @@ -983,9 +1024,9 @@ dependencies = [ [[package]] name = "fluent-langneg" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4ad0989667548f06ccd0e306ed56b61bd4d35458d54df5ec7587c0e8ed5e94" +checksum = "7eebbe59450baee8282d71676f3bfed5689aeab00b27545e83e5f14b1195e8b0" dependencies = [ "unic-langid", ] @@ -996,7 +1037,7 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a530c4694a6a8d528794ee9bbd8ba0122e779629ac908d15ad5a7ae7763a33d" dependencies = [ - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1005,6 +1046,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "foreign-types" version = "0.3.2" @@ -1059,9 +1106,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -1074,9 +1121,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -1084,15 +1131,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -1101,38 +1148,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -1141,17 +1188,10 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.15", - "pin-utils", + "pin-project-lite 0.2.17", "slab", ] -[[package]] -name = "gcc" -version = "0.3.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" - [[package]] name = "generic-array" version = "0.12.4" @@ -1177,51 +1217,74 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.4", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.4", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if 1.0.4", + "libc", + "r-efi 5.3.0", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if 1.0.4", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", ] [[package]] name = "gimli" -version = "0.31.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "git2" -version = "0.20.4" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b88256088d75a56f8ecfa070513a775dd9107f6530ef14919dac831af9cfe2b" +checksum = "ddddbf932745a6be37109b6112d3ee09696106f848449069d3a57bba937ab82e" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.12.1", "libc", "libgit2-sys", "log", - "url", ] [[package]] name = "grin_api" version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f8d4159c8b006a921c0e98b34f1419c175127ee48519b8b1ad00b2036d5011" +source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f" dependencies = [ "async-stream", - "bytes 1.8.0", + "bytes 1.11.1", "easy-jsonrpc-mw", - "futures 0.3.31", + "futures 0.3.32", "grin_chain", "grin_core", "grin_p2p", @@ -1241,8 +1304,8 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "thiserror", - "tokio 1.42.1", + "thiserror 1.0.69", + "tokio 1.52.3", "tokio-rustls 0.23.4", "url", ] @@ -1250,8 +1313,7 @@ dependencies = [ [[package]] name = "grin_chain" version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ae4110494f8864a7acaa95a6565cea73a769203353d33afa2491a0303ef5e96" +source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f" dependencies = [ "bit-vec", "bitflags 1.3.2", @@ -1268,14 +1330,13 @@ dependencies = [ "lru-cache", "serde", "serde_derive", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "grin_core" version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f7959afef3976c8530f39416364dd8e47c24b20774a8c5432645fc70aeba67" +source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f" dependencies = [ "blake2-rfc", "byteorder", @@ -1293,16 +1354,15 @@ dependencies = [ "rand 0.6.5", "serde", "serde_derive", - "siphasher", - "thiserror", + "siphasher 0.3.11", + "thiserror 1.0.69", "zeroize", ] [[package]] name = "grin_keychain" version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4da89816a601ca89d9718aa3fac1ae933086d36790fb3b9d85a57b64ba20173f" +source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f" dependencies = [ "blake2-rfc", "byteorder", @@ -1324,10 +1384,10 @@ dependencies = [ [[package]] name = "grin_p2p" version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d8ee1812124b8843de27626c5e65f43eae7ca855eeb6060286c6b3f31880548" +source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f" dependencies = [ "bitflags 1.3.2", + "built", "bytes 0.5.6", "chrono", "enum_primitive", @@ -1347,8 +1407,7 @@ dependencies = [ [[package]] name = "grin_pool" version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddce3861a8af1036d36746eeb80d5efc805587ab7dbc19d7bef13c127d567cc8" +source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f" dependencies = [ "blake2-rfc", "chrono", @@ -1359,7 +1418,7 @@ dependencies = [ "rand 0.6.5", "serde", "serde_derive", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1380,28 +1439,26 @@ dependencies = [ [[package]] name = "grin_store" version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6d8762c27886d4dbeeae187e761bafef84e099096f0da4987d96dba7192e33" +source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f" dependencies = [ "byteorder", "croaring", "grin_core", "grin_util", + "heed", "libc", - "lmdb-zero", "log", "memmap", "serde", "serde_derive", "tempfile", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "grin_util" version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ecf6160820c449a0d5a2f856cd8d9b0bacf1fff4a09785cf2b6762d9475a6a" +source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f" dependencies = [ "anyhow", "backtrace", @@ -1444,11 +1501,11 @@ dependencies = [ "remove_dir_all", "rpassword", "rustyline", - "semver", + "semver 0.10.0", "serde", "serde_derive", "serde_json", - "thiserror", + "thiserror 1.0.69", "url", ] @@ -1499,7 +1556,7 @@ dependencies = [ "chrono", "easy-jsonrpc-mw", "ed25519-dalek", - "futures 0.3.31", + "futures 0.3.32", "grin_api", "grin_chain", "grin_core", @@ -1522,7 +1579,7 @@ dependencies = [ "serde_derive", "serde_json", "term 0.6.1", - "thiserror", + "thiserror 1.0.69", "tokio 0.2.25", "url", "uuid", @@ -1538,7 +1595,7 @@ dependencies = [ "chrono", "data-encoding", "ed25519-dalek", - "futures 0.3.31", + "futures 0.3.32", "grin_api", "grin_chain", "grin_core", @@ -1559,7 +1616,7 @@ dependencies = [ "serde_derive", "serde_json", "sysinfo", - "thiserror", + "thiserror 1.0.69", "timer", "tokio 0.2.25", "url", @@ -1597,10 +1654,10 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "sha2 0.10.8", + "sha2 0.10.9", "strum", "strum_macros", - "thiserror", + "thiserror 1.0.69", "uuid", "x25519-dalek 0.6.0", ] @@ -1617,7 +1674,7 @@ dependencies = [ "serde", "serde_derive", "sha3", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1646,16 +1703,16 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" dependencies = [ - "bytes 1.8.0", + "bytes 1.11.1", "fnv", "futures-core", "futures-sink", "futures-util", "http", - "indexmap 2.6.0", + "indexmap 2.14.0", "slab", - "tokio 1.42.1", - "tokio-util 0.7.17", + "tokio 1.52.3", + "tokio-util 0.7.18", "tracing", ] @@ -1673,9 +1730,18 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "heck" @@ -1686,6 +1752,50 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "heed" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad82d6598ccf1dac15c8b758a1bd282b755b6776be600429176757190a1b0202" +dependencies = [ + "bitflags 2.12.1", + "byteorder", + "heed-traits", + "heed-types", + "libc", + "lmdb-master-sys", + "once_cell", + "page_size", + "serde", + "synchronoise", + "url", +] + +[[package]] +name = "heed-traits" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3130048d404c57ce5a1ac61a903696e8fcde7e8c2991e9fcfc1f27c3ef74ff" + +[[package]] +name = "heed-types" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c255bdf46e07fb840d120a36dcc81f385140d7191c76a7391672675c01a55d" +dependencies = [ + "bincode", + "byteorder", + "heed-traits", + "serde", + "serde_json", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1697,15 +1807,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.9" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hkdf" @@ -1742,9 +1846,9 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "bytes 1.8.0", + "bytes 1.11.1", "fnv", - "itoa 1.0.11", + "itoa 1.0.18", ] [[package]] @@ -1763,16 +1867,16 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ - "bytes 1.8.0", + "bytes 1.11.1", "http", - "pin-project-lite 0.2.15", + "pin-project-lite 0.2.17", ] [[package]] name = "httparse" -version = "1.9.5" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" @@ -1788,9 +1892,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "hyper" @@ -1822,7 +1926,7 @@ version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ - "bytes 1.8.0", + "bytes 1.11.1", "futures-channel", "futures-core", "futures-util", @@ -1831,10 +1935,10 @@ dependencies = [ "http-body 0.4.6", "httparse", "httpdate 1.0.3", - "itoa 1.0.11", - "pin-project-lite 0.2.15", - "socket2 0.5.8", - "tokio 1.42.1", + "itoa 1.0.18", + "pin-project-lite 0.2.17", + "socket2 0.5.10", + "tokio 1.52.3", "tower-service", "tracing", "want", @@ -1867,7 +1971,7 @@ dependencies = [ "log", "rustls 0.20.9", "rustls-native-certs", - "tokio 1.42.1", + "tokio 1.52.3", "tokio-rustls 0.23.4", ] @@ -1878,8 +1982,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ "hyper 0.14.32", - "pin-project-lite 0.2.15", - "tokio 1.42.1", + "pin-project-lite 0.2.17", + "tokio 1.52.3", "tokio-io-timeout", ] @@ -1898,15 +2002,15 @@ dependencies = [ [[package]] name = "i18n-config" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e88074831c0be5b89181b05e6748c4915f77769ecc9a4c372f88b169a8509c9" +checksum = "3e06b90c8a0d252e203c94344b21e35a30f3a3a85dc7db5af8f8df9f3e0c63ef" dependencies = [ "basic-toml", "log", "serde", "serde_derive", - "thiserror", + "thiserror 1.0.69", "unic-langid", ] @@ -1924,9 +2028,9 @@ dependencies = [ "intl-memoizer", "lazy_static", "log", - "parking_lot 0.12.3", + "parking_lot 0.12.5", "rust-embed", - "thiserror", + "thiserror 1.0.69", "unic-langid", "walkdir", ] @@ -1945,10 +2049,10 @@ dependencies = [ "i18n-embed", "lazy_static", "proc-macro-error", - "proc-macro2 1.0.89", - "quote 1.0.37", + "proc-macro2 1.0.106", + "quote 1.0.45", "strsim 0.10.0", - "syn 2.0.86", + "syn 2.0.117", "unic-langid", ] @@ -1960,21 +2064,22 @@ checksum = "0f2cc0e0523d1fe6fc2c6f66e5038624ea8091b3e7748b5e8e0c84b1698db6c2" dependencies = [ "find-crate", "i18n-config", - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -1990,12 +2095,13 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -2003,22 +2109,22 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", - "tinystr 0.8.2", + "tinystr", "writeable", "zerovec", ] [[package]] name = "icu_normalizer" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -2030,15 +2136,15 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ "icu_collections", "icu_locale_core", @@ -2050,15 +2156,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -2069,6 +2175,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "idna" version = "1.1.0" @@ -2082,9 +2194,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", @@ -2096,25 +2208,27 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ - "autocfg 1.4.0", + "autocfg 1.5.1", "hashbrown 0.12.3", ] [[package]] name = "indexmap" -version = "2.6.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.17.1", + "serde", + "serde_core", ] [[package]] name = "intl-memoizer" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe22e020fce238ae18a6d5d8c502ee76a52a6e880d99477657e6acc30ec57bda" +checksum = "310da2e345f5eb861e7a07ee182262e94975051db9e4223e909ba90f392f163f" dependencies = [ "type-map", "unic-langid", @@ -2140,19 +2254,19 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.10.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "is-terminal" -version = "0.4.13" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ - "hermit-abi 0.4.0", + "hermit-abi 0.5.2", "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2163,25 +2277,29 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ + "getrandom 0.3.4", "libc", ] [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" dependencies = [ + "cfg-if 1.0.4", + "futures-util", + "once_cell", "wasm-bindgen", ] @@ -2200,9 +2318,9 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ "cpufeatures", ] @@ -2224,16 +2342,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] -name = "libc" -version = "0.2.161" +name = "leb128fmt" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libgit2-sys" -version = "0.18.3+1.9.2" +version = "0.18.5+1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9b3acc4b91781bb0b3386669d325163746af5f6e4f73e6d2d630e09a35f3487" +checksum = "005d6ae6eac1912906073e069f7db60b1fa98e052a68227824afe3e3a1c59ca2" dependencies = [ "cc", "libc", @@ -2241,31 +2365,20 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "liblmdb-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feed38a3a580f60bf61aaa067b0ff4123395966839adeaf67258a9e50c4d2e49" -dependencies = [ - "gcc", - "libc", -] - [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" dependencies = [ - "bitflags 2.6.0", "libc", ] [[package]] name = "libz-sys" -version = "1.1.20" +version = "1.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +checksum = "85bc9657773828b90eeb625adff10eeac83cc21bbfd8e23a03eaa8a33c9e28d9" dependencies = [ "cc", "libc", @@ -2292,26 +2405,25 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] -name = "lmdb-zero" -version = "0.4.4" +name = "lmdb-master-sys" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13416eee745b087c22934f35f1f24da22da41ba2a5ce197143d168ce055cc58d" +checksum = "aaeb9bd22e73bd1babffff614994b341e9b2008de7bb73bf1f7e9154f1978f8b" dependencies = [ - "bitflags 0.9.1", + "cc", + "doxygen-rs", "libc", - "liblmdb-sys", - "supercow", ] [[package]] @@ -2325,21 +2437,20 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg 1.4.0", "scopeguard", ] [[package]] name = "log" -version = "0.4.22" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "113b30b4cd05f7c06868fdb2854f66a7b9fece9a48425351cd532e810d74024f" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -2350,30 +2461,31 @@ checksum = "a94d21414c1f4a51209ad204c1776a3d0765002c76c6abcb602a6f09f1e881c7" [[package]] name = "log4rs" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0816135ae15bd0391cf284eab37e6e3ee0a6ee63d2ceeb659862bd8d0a984ca6" +checksum = "3e947bb896e702c711fccc2bf02ab2abb6072910693818d1d6b07ee2b9dfd86c" dependencies = [ "anyhow", "arc-swap", "chrono", - "derivative", + "derive_more", "flate2", "fnv", "humantime", "libc", "log", "log-mdc", - "once_cell", - "parking_lot 0.12.3", - "rand 0.8.5", + "mock_instant", + "parking_lot 0.12.5", + "rand 0.9.4", "serde", "serde-value", "serde_json", "serde_yaml", - "thiserror", + "thiserror 2.0.18", "thread-id", "typemap-ors", + "unicode-segmentation", "winapi 0.3.9", ] @@ -2388,9 +2500,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.4" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" [[package]] name = "memmap" @@ -2426,11 +2538,12 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] @@ -2454,12 +2567,12 @@ dependencies = [ [[package]] name = "mio" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.61.2", ] @@ -2507,13 +2620,19 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "mock_instant" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce6dd36094cac388f119d2e9dc82dc730ef91c32a6222170d630e5414b956e6" + [[package]] name = "mortal" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c624fa1b7aab6bd2aff6e9b18565cc0363b6d45cbcd7465c9ed5e3740ebf097" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.12.1", "libc", "nix 0.26.4", "smallstr", @@ -2525,17 +2644,17 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.12" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" dependencies = [ "libc", "log", "openssl", - "openssl-probe", + "openssl-probe 0.2.1", "openssl-sys", "schannel", - "security-framework", + "security-framework 3.7.0", "security-framework-sys", "tempfile", ] @@ -2570,7 +2689,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", - "cfg-if 1.0.0", + "cfg-if 1.0.4", "libc", ] @@ -2592,9 +2711,9 @@ dependencies = [ [[package]] name = "ntapi" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" dependencies = [ "winapi 0.3.9", ] @@ -2619,7 +2738,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" dependencies = [ - "autocfg 1.4.0", + "autocfg 1.5.1", "num-integer", "num-traits 0.2.19", ] @@ -2630,7 +2749,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" dependencies = [ - "autocfg 1.4.0", + "autocfg 1.5.1", "num-traits 0.2.19", ] @@ -2649,7 +2768,7 @@ version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ - "autocfg 1.4.0", + "autocfg 1.5.1", "num-integer", "num-traits 0.2.19", ] @@ -2660,7 +2779,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ - "autocfg 1.4.0", + "autocfg 1.5.1", "num-bigint", "num-integer", "num-traits 0.2.19", @@ -2681,33 +2800,33 @@ version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "autocfg 1.4.0", + "autocfg 1.5.1", ] [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi 0.5.2", "libc", ] [[package]] name = "object" -version = "0.36.5" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.20.2" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "opaque-debug" @@ -2727,8 +2846,8 @@ version = "0.10.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967" dependencies = [ - "bitflags 2.6.0", - "cfg-if 1.0.0", + "bitflags 2.12.1", + "cfg-if 1.0.4", "foreign-types", "libc", "openssl-macros", @@ -2741,16 +2860,22 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" @@ -2782,6 +2907,16 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "page_size" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "parking_lot" version = "0.10.2" @@ -2794,12 +2929,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ - "lock_api 0.4.12", - "parking_lot_core 0.9.10", + "lock_api 0.4.14", + "parking_lot_core 0.9.12", ] [[package]] @@ -2818,15 +2953,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.4", "libc", - "redox_syscall 0.5.7", + "redox_syscall 0.5.18", "smallvec", - "windows-targets", + "windows-link", ] [[package]] @@ -2870,18 +3005,19 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ + "phf_macros", "phf_shared", ] [[package]] name = "phf_codegen" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ "phf_generator", "phf_shared", @@ -2889,41 +3025,54 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand 0.8.5", + "rand 0.8.6", +] + +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "siphasher", + "siphasher 1.0.3", ] [[package]] name = "pin-project" -version = "1.1.7" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.7" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -2934,21 +3083,15 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" -version = "0.3.31" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "poly1305" @@ -2963,18 +3106,18 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] @@ -2991,6 +3134,16 @@ dependencies = [ "output_vt100", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2 1.0.106", + "syn 2.0.117", +] + [[package]] name = "prettytable-rs" version = "0.10.0" @@ -3012,8 +3165,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.89", - "quote 1.0.37", + "proc-macro2 1.0.106", + "quote 1.0.45", "syn 1.0.109", "version_check", ] @@ -3024,8 +3177,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", + "proc-macro2 1.0.106", + "quote 1.0.45", "version_check", ] @@ -3035,14 +3188,14 @@ version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" dependencies = [ - "unicode-xid", + "unicode-xid 0.1.0", ] [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -3064,13 +3217,25 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.37" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ - "proc-macro2 1.0.89", + "proc-macro2 1.0.106", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rand" version = "0.5.6" @@ -3118,15 +3283,25 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", ] +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + [[package]] name = "rand_chacha" version = "0.1.1" @@ -3157,6 +3332,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + [[package]] name = "rand_core" version = "0.3.1" @@ -3187,7 +3372,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", ] [[package]] @@ -3263,9 +3457,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -3273,9 +3467,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -3298,11 +3492,11 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.12.1", ] [[package]] @@ -3322,16 +3516,16 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.17", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -3341,9 +3535,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -3352,9 +3546,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "remove_dir_all" @@ -3393,7 +3587,7 @@ dependencies = [ "mime_guess", "native-tls", "percent-encoding", - "pin-project-lite 0.2.15", + "pin-project-lite 0.2.17", "rustls 0.18.1", "serde", "serde_urlencoded", @@ -3431,8 +3625,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", - "cfg-if 1.0.0", - "getrandom 0.2.15", + "cfg-if 1.0.4", + "getrandom 0.2.17", "libc", "untrusted 0.9.0", "windows-sys 0.52.0", @@ -3488,10 +3682,10 @@ version = "6.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49b94b81e5b2c284684141a2fb9e2a31be90638caf040bf9afbc5a0416afe1ac" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", + "proc-macro2 1.0.106", + "quote 1.0.45", "rust-embed-utils", - "syn 2.0.86", + "syn 2.0.117", "walkdir", ] @@ -3501,15 +3695,15 @@ version = "7.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d38ff6bf570dc3bb7100fce9f7b60c33fa71d80e88da3f2580df4ff2bdded74" dependencies = [ - "sha2 0.10.8", + "sha2 0.10.9", "walkdir", ] [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" [[package]] name = "rustc-hash" @@ -3518,16 +3712,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] -name = "rustix" -version = "0.38.38" +name = "rustc-hash" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "bitflags 2.6.0", + "semver 1.0.28", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.12.1", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3561,10 +3770,10 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ - "openssl-probe", + "openssl-probe 0.1.6", "rustls-pemfile", "schannel", - "security-framework", + "security-framework 2.11.1", ] [[package]] @@ -3578,9 +3787,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "rustyline" @@ -3603,9 +3812,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "safemem" @@ -3633,11 +3842,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.26" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3655,7 +3864,7 @@ dependencies = [ "hmac 0.12.1", "pbkdf2 0.10.1", "salsa20", - "sha2 0.10.8", + "sha2 0.10.9", ] [[package]] @@ -3702,8 +3911,21 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.6.0", - "core-foundation", + "bitflags 2.12.1", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags 2.12.1", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -3711,9 +3933,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -3725,14 +3947,14 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d" dependencies = [ - "self_cell 1.0.4", + "self_cell 1.2.2", ] [[package]] name = "self_cell" -version = "1.0.4" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" +checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" [[package]] name = "semver" @@ -3743,6 +3965,12 @@ dependencies = [ "semver-parser", ] +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + [[package]] name = "semver-parser" version = "0.7.0" @@ -3751,10 +3979,11 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] @@ -3769,26 +3998,36 @@ dependencies = [ ] [[package]] -name = "serde_derive" -version = "1.0.214" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ - "itoa 1.0.11", + "itoa 1.0.18", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] @@ -3798,7 +4037,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.11", + "itoa 1.0.18", "ryu", "serde", ] @@ -3809,8 +4048,8 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.6.0", - "itoa 1.0.11", + "indexmap 2.14.0", + "itoa 1.0.18", "ryu", "serde", "unsafe-libyaml", @@ -3823,7 +4062,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", - "cfg-if 1.0.0", + "cfg-if 1.0.4", "cpufeatures", "digest 0.9.0", "opaque-debug 0.3.1", @@ -3831,11 +4070,11 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.4", "cpufeatures", "digest 0.10.7", ] @@ -3855,16 +4094,17 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -3874,6 +4114,12 @@ version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + [[package]] name = "siphasher" version = "0.3.11" @@ -3881,13 +4127,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] -name = "slab" -version = "0.4.9" +name = "siphasher" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg 1.4.0", -] +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallstr" @@ -3900,9 +4149,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" @@ -3910,21 +4159,31 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.4", "libc", "winapi 0.3.9", ] [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "spin" version = "0.5.2" @@ -3961,9 +4220,9 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" dependencies = [ - "heck", - "proc-macro2 1.0.89", - "quote 1.0.37", + "heck 0.3.3", + "proc-macro2 1.0.106", + "quote 1.0.45", "syn 1.0.109", ] @@ -3973,12 +4232,6 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" -[[package]] -name = "supercow" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171758edb47aa306a78dfa4ab9aeb5167405bd4e3dc2b64e88f6a84bbe98bd63" - [[package]] name = "syn" version = "0.15.44" @@ -3987,7 +4240,7 @@ checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" dependencies = [ "proc-macro2 0.4.30", "quote 0.6.13", - "unicode-xid", + "unicode-xid 0.1.0", ] [[package]] @@ -3996,31 +4249,40 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", + "proc-macro2 1.0.106", + "quote 1.0.45", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.86" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89275301d38033efb81a6e60e3497e734dfcc62571f2854bf4b16690398824c" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", + "proc-macro2 1.0.106", + "quote 1.0.45", "unicode-ident", ] +[[package]] +name = "synchronoise" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dbc01390fc626ce8d1cffe3376ded2b72a11bb70e1c75f404a210e4daa4def2" +dependencies = [ + "crossbeam-queue", +] + [[package]] name = "synstructure" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -4029,7 +4291,7 @@ version = "0.29.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.4", "core-foundation-sys", "libc", "ntapi", @@ -4040,15 +4302,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.13.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ - "cfg-if 1.0.0", "fastrand", + "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4096,32 +4358,52 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", ] [[package]] name = "thiserror-impl" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] name = "thread-id" -version = "4.2.2" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe8f25bbdd100db7e1d34acf7fd2dc59c4bf8f7483f505eaa7d4f12f76cc0ea" +checksum = "2010d27add3f3240c1fef7959f46c814487b216baee662af53be645ba7831c07" dependencies = [ "libc", - "winapi 0.3.9", + "windows-sys 0.61.2", ] [[package]] @@ -4135,28 +4417,20 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", -] - -[[package]] -name = "tinystr" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", + "serde_core", "zerovec", ] [[package]] name = "tinyvec" -version = "1.8.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -4193,20 +4467,19 @@ dependencies = [ [[package]] name = "tokio" -version = "1.42.1" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2209a14885b74764cce87ffa777ffa1b8ce81a3f3166c6f886b83337fe7e077f" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ - "backtrace", - "bytes 1.8.0", + "bytes 1.11.1", "libc", - "mio 1.1.0", - "parking_lot 0.12.3", - "pin-project-lite 0.2.15", + "mio 1.2.1", + "parking_lot 0.12.5", + "pin-project-lite 0.2.17", "signal-hook-registry", - "socket2 0.5.8", - "tokio-macros 2.4.0", - "windows-sys 0.52.0", + "socket2 0.6.4", + "tokio-macros 2.7.0", + "windows-sys 0.61.2", ] [[package]] @@ -4215,8 +4488,8 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bd86198d9ee903fedd2f9a2e72014287c0d9167e4ae43b5853007205dda1b76" dependencies = [ - "pin-project-lite 0.2.15", - "tokio 1.42.1", + "pin-project-lite 0.2.17", + "tokio 1.52.3", ] [[package]] @@ -4225,20 +4498,20 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", + "proc-macro2 1.0.106", + "quote 1.0.45", "syn 1.0.109", ] [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -4260,7 +4533,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ "rustls 0.20.9", - "tokio 1.42.1", + "tokio 1.52.3", "webpki 0.22.4", ] @@ -4272,8 +4545,8 @@ checksum = "d611fd5d241872372d52a0a3d309c52d0b95a6a67671a6c8f7ab2c4a37fb2539" dependencies = [ "bytes 0.4.12", "either", - "futures 0.3.31", - "thiserror", + "futures 0.3.32", + "thiserror 1.0.69", "tokio 0.2.25", ] @@ -4303,15 +4576,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.17" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ - "bytes 1.8.0", + "bytes 1.11.1", "futures-core", "futures-sink", - "pin-project-lite 0.2.15", - "tokio 1.42.1", + "pin-project-lite 0.2.17", + "tokio 1.52.3", ] [[package]] @@ -4331,20 +4604,20 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", - "pin-project-lite 0.2.15", + "pin-project-lite 0.2.17", "tracing-core", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", ] @@ -4367,11 +4640,11 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "type-map" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb68604048ff8fa93347f02441e4487594adc20bb8a084f9e564d2b827a0a9f" +checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90" dependencies = [ - "rustc-hash", + "rustc-hash 2.1.2", ] [[package]] @@ -4385,55 +4658,55 @@ dependencies = [ [[package]] name = "typenum" -version = "1.17.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "unic-langid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dd9d1e72a73b25e07123a80776aae3e7b0ec461ef94f9151eed6ec88005a44" +checksum = "a28ba52c9b05311f4f6e62d5d9d46f094bd6e84cb8df7b3ef952748d752a7d05" dependencies = [ "unic-langid-impl", ] [[package]] name = "unic-langid-impl" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5422c1f65949306c99240b81de9f3f15929f5a8bfe05bb44b034cc8bf593e5" +checksum = "dce1bf08044d4b7a94028c93786f8566047edc11110595914de93362559bc658" dependencies = [ "serde", - "tinystr 0.7.6", + "tinystr", ] [[package]] name = "unicase" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-normalization" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-width" @@ -4447,6 +4720,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "universal-hash" version = "0.4.1" @@ -4514,7 +4793,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.17", "serde", ] @@ -4563,84 +4842,124 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasm-bindgen" -version = "0.2.95" +name = "wasip2" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "cfg-if 1.0.0", - "once_cell", - "serde", - "serde_json", - "wasm-bindgen-macro", + "wit-bindgen 0.57.1", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.95" +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "bumpalo", - "log", + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" +dependencies = [ + "cfg-if 1.0.4", "once_cell", - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "rustversion", + "serde", + "serde_json", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.45" +version = "0.4.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f" dependencies = [ - "cfg-if 1.0.0", "js-sys", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" dependencies = [ - "quote 1.0.37", + "quote 1.0.45", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", - "wasm-bindgen-backend", + "bumpalo", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.14.0", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.12.1", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "semver 1.0.28", +] [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436" dependencies = [ "js-sys", "wasm-bindgen", @@ -4705,11 +5024,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4720,11 +5039,37 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.52.0" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ - "windows-targets", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -4734,19 +5079,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-sys" -version = "0.52.0" +name = "windows-result" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-targets", + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", ] [[package]] name = "windows-sys" -version = "0.59.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets", ] @@ -4834,10 +5188,104 @@ dependencies = [ ] [[package]] -name = "writeable" -version = "0.6.2" +name = "wit-bindgen" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.14.0", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.12.1", + "indexmap 2.14.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.14.0", + "log", + "semver 1.0.28", + "serde", + "serde_derive", + "serde_json", + "unicode-xid 0.2.6", + "wasmparser", +] + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "ws2_32-sys" @@ -4879,9 +5327,9 @@ checksum = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" [[package]] name = "yoke" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -4890,83 +5338,82 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", "synstructure", ] [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" dependencies = [ - "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] name = "zerotrie" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -4975,10 +5422,11 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ + "serde", "yoke", "zerofrom", "zerovec-derive", @@ -4986,13 +5434,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ - "proc-macro2 1.0.89", - "quote 1.0.37", - "syn 2.0.86", + "proc-macro2 1.0.106", + "quote 1.0.45", + "syn 2.0.117", ] [[package]] @@ -5003,5 +5451,11 @@ checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815" dependencies = [ "byteorder", "crc32fast", - "thiserror", + "thiserror 1.0.69", ] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml index e90314a..acef614 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,10 +41,10 @@ grin_wallet_util = { path = "./util", version = "5.4.0-alpha.1" } ##### Grin Imports # For Release -grin_core = "5.4.0" -grin_keychain = "5.4.0" -grin_util = "5.4.0" -grin_api = "5.4.0" +#grin_core = "5.4.0" +#grin_keychain = "5.4.0" +#grin_util = "5.4.0" +#grin_api = "5.4.0" # For beta release @@ -54,10 +54,10 @@ grin_api = "5.4.0" # grin_api = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # For bleeding edge -# grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_api = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_core = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_keychain = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_util = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_api = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } # For local testing # grin_core = { path = "../grin/core"} diff --git a/api/Cargo.toml b/api/Cargo.toml index a85781e..b86cfbd 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -30,9 +30,9 @@ grin_wallet_util = { path = "../util", version = "5.4.0-alpha.1" } ##### Grin Imports # For Release -grin_core = "5.4.0" -grin_keychain = "5.4.0" -grin_util = "5.4.0" +#grin_core = "5.4.0" +#grin_keychain = "5.4.0" +#grin_util = "5.4.0" # For beta release @@ -41,9 +41,9 @@ grin_util = "5.4.0" # grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # For bleeding edge -# grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_core = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_keychain = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_util = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } # For local testing # grin_core = { path = "../../grin/core"} diff --git a/api/src/foreign.rs b/api/src/foreign.rs index 1d96256..f5e8276 100644 --- a/api/src/foreign.rs +++ b/api/src/foreign.rs @@ -146,7 +146,7 @@ where /// // by the reference wallet implementation. /// // These traits can be replaced with alternative implementations if desired /// - /// let mut wallet = Box::new(DefaultWalletImpl::<'static, HTTPNodeClient>::new(node_client.clone()).unwrap()) + /// let mut wallet = Box::new(DefaultWalletImpl::::new(node_client.clone()).unwrap()) /// as Box, HTTPNodeClient, ExtKeychain>>; /// /// // Wallet LifeCycle Provider provides all functions init wallet and work with seeds, etc... @@ -286,7 +286,7 @@ where )?; } foreign::build_coinbase( - &mut **w, + w, (&self.keychain_mask).as_ref(), block_fees, self.doctest_mode, @@ -362,7 +362,7 @@ where )?; } let ret_slate = foreign::receive_tx( - &mut **w, + w, (&self.keychain_mask).as_ref(), slate, dest_acct_name, @@ -380,8 +380,8 @@ where self.doctest_mode, ); match res { - Ok(s) => return Ok(s.unwrap()), - Err(_) => return Ok(ret_slate), + Ok(s) => Ok(s.unwrap()), + Err(_) => Ok(ret_slate), } } None => Ok(ret_slate), @@ -443,12 +443,7 @@ where true => false, false => post_automatically, }; - foreign::finalize_tx( - &mut **w, - (&self.keychain_mask).as_ref(), - slate, - post_automatically, - ) + foreign::finalize_tx(w, (&self.keychain_mask).as_ref(), slate, post_automatically) } } @@ -496,17 +491,16 @@ macro_rules! doctest_helper_setup_doc_env_foreign { let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None).unwrap(); - let mut wallet = Box::new( - DefaultWalletImpl::<'static, HTTPNodeClient>::new(node_client.clone()).unwrap(), - ) - as Box< - dyn WalletInst< - 'static, - DefaultLCProvider, - HTTPNodeClient, - ExtKeychain, - >, - >; + let mut wallet = + Box::new(DefaultWalletImpl::::new(node_client.clone()).unwrap()) + as Box< + dyn WalletInst< + 'static, + DefaultLCProvider, + HTTPNodeClient, + ExtKeychain, + >, + >; let lc = wallet.lc_provider().unwrap(); let _ = lc.set_top_level_directory(&wallet_config.data_file_dir); lc.open_wallet(None, pw, false, false); diff --git a/api/src/foreign_rpc.rs b/api/src/foreign_rpc.rs index 1d2b526..55004a9 100644 --- a/api/src/foreign_rpc.rs +++ b/api/src/foreign_rpc.rs @@ -381,7 +381,6 @@ pub fn run_doctest_foreign( Box::new(DefaultWalletImpl::::new(client1.clone()).unwrap()) as Box< dyn WalletInst< - 'static, DefaultLCProvider, LocalWalletClient, ExtKeychain, @@ -416,7 +415,6 @@ pub fn run_doctest_foreign( Box::new(DefaultWalletImpl::::new(client2.clone()).unwrap()) as Box< dyn WalletInst< - 'static, DefaultLCProvider, LocalWalletClient, ExtKeychain, @@ -473,7 +471,7 @@ pub fn run_doctest_foreign( amount, ..Default::default() }; - api_impl::owner::issue_invoice_tx(&mut **w, (&mask2).as_ref(), args, true).unwrap() + api_impl::owner::issue_invoice_tx(w, (&mask2).as_ref(), args, true).unwrap() }; slate = { let mut w_lock = wallet1.lock(); @@ -487,8 +485,7 @@ pub fn run_doctest_foreign( selection_strategy_is_use_all: true, ..Default::default() }; - api_impl::owner::process_invoice_tx(&mut **w, (&mask1).as_ref(), &slate, args, true) - .unwrap() + api_impl::owner::process_invoice_tx(w, (&mask1).as_ref(), &slate, args, true).unwrap() }; println!("INIT INVOICE SLATE"); // Spit out slate for input to finalize_tx @@ -508,7 +505,7 @@ pub fn run_doctest_foreign( selection_strategy_is_use_all: true, ..Default::default() }; - let slate = api_impl::owner::init_send_tx(&mut **w, (&mask1).as_ref(), args, true).unwrap(); + let slate = api_impl::owner::init_send_tx(w, (&mask1).as_ref(), args, true).unwrap(); println!("INIT SLATE"); // Spit out slate for input to finalize_tx println!("{}", serde_json::to_string_pretty(&slate).unwrap()); diff --git a/api/src/owner.rs b/api/src/owner.rs index d291b2b..d1e930c 100644 --- a/api/src/owner.rs +++ b/api/src/owner.rs @@ -97,7 +97,7 @@ where /// /// Each method will call the [`WalletBackend`](../grin_wallet_libwallet/types/trait.WalletBackend.html)'s /// [`open_with_credentials`](../grin_wallet_libwallet/types/trait.WalletBackend.html#tymethod.open_with_credentials) - /// (initialising a keychain with the master seed,) perform its operation, then close the keychain + /// initializing a keychain with the master seed, perform its operation, then close the keychain /// with a call to [`close`](../grin_wallet_libwallet/types/trait.WalletBackend.html#tymethod.close) /// /// # Arguments @@ -147,11 +147,11 @@ where /// let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None).unwrap(); /// /// // impls::DefaultWalletImpl is provided for convenience in instantiating the wallet - /// // It contains the LMDBBackend, DefaultLCProvider (lifecycle) and ExtKeychain used + /// // It contains the WalletBackend, DefaultLCProvider (lifecycle) and ExtKeychain used /// // by the reference wallet implementation. /// // These traits can be replaced with alternative implementations if desired /// - /// let mut wallet = Box::new(DefaultWalletImpl::<'static, HTTPNodeClient>::new(node_client.clone()).unwrap()) + /// let mut wallet = Box::new(DefaultWalletImpl::::new(node_client.clone()).unwrap()) /// as Box, HTTPNodeClient, ExtKeychain>>; /// /// // Wallet LifeCycle Provider provides all functions init wallet and work with seeds, etc... @@ -258,7 +258,7 @@ where let w = w_lock.lc_provider()?.wallet_inst()?; // Test keychain mask, to keep API consistent let _ = w.keychain(keychain_mask)?; - owner::accounts(&mut **w) + owner::accounts(w) } /// Creates a new 'account', which is a mapping of a user-specified @@ -308,7 +308,7 @@ where ) -> Result { let mut w_lock = self.wallet_inst.lock(); let w = w_lock.lc_provider()?.wallet_inst()?; - owner::create_account_path(&mut **w, keychain_mask, label) + owner::create_account_path(w, keychain_mask, label) } /// Sets the wallet's currently active account. This sets the @@ -358,7 +358,7 @@ where let w = w_lock.lc_provider()?.wallet_inst()?; // Test keychain mask, to keep API consistent let _ = w.keychain(keychain_mask)?; - owner::set_active_account(&mut **w, label) + owner::set_active_account(w, label) } /// Returns a list of outputs from the active account in the wallet. @@ -665,7 +665,7 @@ where let slate = { let mut w_lock = self.wallet_inst.lock(); let w = w_lock.lc_provider()?.wallet_inst()?; - owner::init_send_tx(&mut **w, keychain_mask, args, self.doctest_mode)? + owner::init_send_tx(w, keychain_mask, args, self.doctest_mode)? }; // Helper functionality. If send arguments exist, attempt to send sync and // finalize @@ -701,17 +701,17 @@ where match result { Ok(_) => { info!("Tx sent ok",); - return Ok(ret_slate); + Ok(ret_slate) } Err(e) => { error!("Tx sent fail: {}", e); - return Err(e); + Err(e) } } } else { self.tx_lock_outputs(keychain_mask, &s)?; let ret_slate = self.finalize_tx(keychain_mask, &s)?; - return Ok(ret_slate); + Ok(ret_slate) } } Ok(None) => Ok(slate), @@ -724,7 +724,7 @@ where /// Issues a new invoice transaction slate, essentially a `request for payment`. /// The slate created by this function will contain the amount, an output for the amount, - /// as well as round 1 of singature creation complete. The slate should then be send + /// as well as round 1 of signature creation complete. The slate should then be sent /// to the payer, who should add their inputs and signature data and return the slate /// via the [Foreign API's `finalize_tx`](struct.Foreign.html#method.finalize_tx) method. /// @@ -764,14 +764,14 @@ where ) -> Result { let mut w_lock = self.wallet_inst.lock(); let w = w_lock.lc_provider()?.wallet_inst()?; - owner::issue_invoice_tx(&mut **w, keychain_mask, args, self.doctest_mode) + owner::issue_invoice_tx(w, keychain_mask, args, self.doctest_mode) } - /// Processes an invoice tranaction created by another party, essentially + /// Processes an invoice transaction created by another party, essentially /// a `request for payment`. The incoming slate should contain a requested - /// amount, an output created by the invoicer convering the amount, and + /// amount, an output created by the invoicer converting the amount, and /// part 1 of signature creation completed. This function will add inputs - /// equalling the amount + fees, as well as perform round 1 and 2 of signature + /// equaling the amount + fees, as well as perform round 1 and 2 of signature /// creation. /// /// Callers should note that no prompting of the user will be done by this function @@ -837,8 +837,7 @@ where let mut w_lock = self.wallet_inst.lock(); let w = w_lock.lc_provider()?.wallet_inst()?; let send_args = args.send_args.clone(); - let slate = - owner::process_invoice_tx(&mut **w, keychain_mask, slate, args, self.doctest_mode)?; + let slate = owner::process_invoice_tx(w, keychain_mask, slate, args, self.doctest_mode)?; // Helper functionality. If send arguments exist, attempt to send match send_args { Some(sa) => { @@ -871,7 +870,7 @@ where /// Locks the outputs associated with the inputs to the transaction in the given /// [`Slate`](../grin_wallet_libwallet/slate/struct.Slate.html), /// making them unavailable for use in further transactions. This function is called - /// by the sender, (or more generally, all parties who have put inputs into the transaction,) + /// by the sender, (or more generally, all parties who have put inputs into the transaction) /// and must be called before the corresponding call to [`finalize_tx`](struct.Owner.html#method.finalize_tx) /// that completes the transaction. /// @@ -929,7 +928,7 @@ where ) -> Result<(), Error> { let mut w_lock = self.wallet_inst.lock(); let w = w_lock.lc_provider()?.wallet_inst()?; - owner::tx_lock_outputs(&mut **w, keychain_mask, slate) + owner::tx_lock_outputs(w, keychain_mask, slate) } /// Finalizes a transaction, after all parties @@ -995,7 +994,7 @@ where ) -> Result { let mut w_lock = self.wallet_inst.lock(); let w = w_lock.lc_provider()?.wallet_inst()?; - owner::finalize_tx(&mut **w, keychain_mask, slate) + owner::finalize_tx(w, keychain_mask, slate) } /// Posts a completed transaction to the listening node for validation and inclusion in a block @@ -1186,7 +1185,7 @@ where let w = w_lock.lc_provider()?.wallet_inst()?; // Test keychain mask, to keep API consistent let _ = w.keychain(keychain_mask)?; - owner::get_stored_tx(&**w, tx_id, slate_id) + owner::get_stored_tx(w, tx_id, slate_id) } /// Return the rewind hash of the wallet. @@ -2422,7 +2421,7 @@ where ) -> Result { let mut w_lock = self.wallet_inst.lock(); let w = w_lock.lc_provider()?.wallet_inst()?; - owner::build_output(&mut **w, keychain_mask, features, amount) + owner::build_output(w, keychain_mask, features, amount) } // MWIXNET @@ -2481,7 +2480,7 @@ where let mut w_lock = self.wallet_inst.lock(); let w = w_lock.lc_provider()?.wallet_inst()?; owner::create_mwixnet_req( - &mut **w, + w, keychain_mask, params, commitment, @@ -2499,7 +2498,7 @@ pub fn try_slatepack_sync_workflow( tor_sender: Option, send_to_finalize: bool, test_mode: bool, -) -> Result, libwallet::Error> { +) -> Result, Error> { if let Some(tc) = &tor_config { if tc.skip_send_attempt == Some(true) { return Ok(None); @@ -2604,7 +2603,7 @@ macro_rules! doctest_helper_setup_doc_env { use uuid::Uuid; - // don't run on windows CI, which gives very inconsistent results + // don't run on Windows CI, which gives very inconsistent results if cfg!(windows) { return; } @@ -2624,17 +2623,16 @@ macro_rules! doctest_helper_setup_doc_env { let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None).unwrap(); - let mut wallet = Box::new( - DefaultWalletImpl::<'static, HTTPNodeClient>::new(node_client.clone()).unwrap(), - ) - as Box< - dyn WalletInst< - 'static, - DefaultLCProvider, - HTTPNodeClient, - ExtKeychain, - >, - >; + let mut wallet = + Box::new(DefaultWalletImpl::::new(node_client.clone()).unwrap()) + as Box< + dyn WalletInst< + 'static, + DefaultLCProvider, + HTTPNodeClient, + ExtKeychain, + >, + >; let lc = wallet.lc_provider().unwrap(); let _ = lc.set_top_level_directory(&wallet_config.data_file_dir); lc.open_wallet(None, pw, false, false); diff --git a/api/src/owner_rpc.rs b/api/src/owner_rpc.rs index c983c20..d1c31f7 100644 --- a/api/src/owner_rpc.rs +++ b/api/src/owner_rpc.rs @@ -272,6 +272,7 @@ pub trait OwnerRpc { "stored_tx": null, "ttl_cutoff_height": null, "tx_slate_id": null, + "tx_slate_state": null, "payment_proof": null, "reverted_after": null, "tx_type": "ConfirmedCoinbase" @@ -294,6 +295,7 @@ pub trait OwnerRpc { "payment_proof": null, "reverted_after": null, "tx_slate_id": null, + "tx_slate_state": null, "tx_type": "ConfirmedCoinbase" } ] @@ -363,6 +365,7 @@ pub trait OwnerRpc { "stored_tx": null, "ttl_cutoff_height": null, "tx_slate_id": null, + "tx_slate_state": null, "payment_proof": null, "reverted_after": null, "tx_type": "ConfirmedCoinbase" @@ -385,6 +388,7 @@ pub trait OwnerRpc { "payment_proof": null, "reverted_after": null, "tx_slate_id": null, + "tx_slate_state": null, "tx_type": "ConfirmedCoinbase" } ] @@ -2137,6 +2141,14 @@ where VersionedSlate::into_version(out_slate, version) } + fn tx_lock_outputs(&self, token: Token, in_slate: VersionedSlate) -> Result<(), Error> { + Owner::tx_lock_outputs( + self, + (&token.keychain_mask).as_ref(), + &Slate::from(in_slate), + ) + } + fn finalize_tx(&self, token: Token, in_slate: VersionedSlate) -> Result { let out_slate = Owner::finalize_tx( self, @@ -2147,11 +2159,12 @@ where VersionedSlate::into_version(out_slate, version) } - fn tx_lock_outputs(&self, token: Token, in_slate: VersionedSlate) -> Result<(), Error> { - Owner::tx_lock_outputs( + fn post_tx(&self, token: Token, slate: VersionedSlate, fluff: bool) -> Result<(), Error> { + Owner::post_tx( self, (&token.keychain_mask).as_ref(), - &Slate::from(in_slate), + &Slate::from(slate), + fluff, ) } @@ -2185,15 +2198,6 @@ where } } - fn post_tx(&self, token: Token, slate: VersionedSlate, fluff: bool) -> Result<(), Error> { - Owner::post_tx( - self, - (&token.keychain_mask).as_ref(), - &Slate::from(slate), - fluff, - ) - } - fn get_rewind_hash(&self, token: Token) -> Result { Owner::get_rewind_hash(self, (&token.keychain_mask).as_ref()) } @@ -2625,26 +2629,25 @@ pub fn run_doctest_owner( payment_proof_recipient_address: proof_address, ..Default::default() }; - let mut slate = - api_impl::owner::init_send_tx(&mut **w, (&mask1).as_ref(), args, true).unwrap(); + let mut slate = api_impl::owner::init_send_tx(w, (&mask1).as_ref(), args, true).unwrap(); println!("INITIAL SLATE"); println!("{}", serde_json::to_string_pretty(&slate).unwrap()); { let mut w_lock = wallet2.lock(); let w2 = w_lock.lc_provider().unwrap().wallet_inst().unwrap(); - slate = api_impl::foreign::receive_tx(&mut **w2, (&mask2).as_ref(), &slate, None, true) - .unwrap(); + slate = + api_impl::foreign::receive_tx(w2, (&mask2).as_ref(), &slate, None, true).unwrap(); w2.close().unwrap(); } // Spit out slate for input to finalize_tx if lock_tx { println!("LOCKING TX"); - api_impl::owner::tx_lock_outputs(&mut **w, (&mask1).as_ref(), &slate).unwrap(); + api_impl::owner::tx_lock_outputs(w, (&mask1).as_ref(), &slate).unwrap(); } println!("RECEIPIENT SLATE"); println!("{}", serde_json::to_string_pretty(&slate).unwrap()); if finalize_tx { - slate = api_impl::owner::finalize_tx(&mut **w, (&mask1).as_ref(), &slate).unwrap(); + slate = api_impl::owner::finalize_tx(w, (&mask1).as_ref(), &slate).unwrap(); error!("FINALIZED TX SLATE"); println!("{}", serde_json::to_string_pretty(&slate).unwrap()); } diff --git a/config/Cargo.toml b/config/Cargo.toml index f646b3d..137dc36 100644 --- a/config/Cargo.toml +++ b/config/Cargo.toml @@ -21,8 +21,8 @@ grin_wallet_util = { path = "../util", version = "5.4.0-alpha.1" } ##### Grin Imports # For Release -grin_core = "5.4.0" -grin_util = "5.4.0" +#grin_core = "5.4.0" +#grin_util = "5.4.0" # For beta release @@ -30,8 +30,8 @@ grin_util = "5.4.0" #grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # For bleeding edge -# grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_core = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_util = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } # For local testing # grin_core = { path = "../../grin/core"} diff --git a/controller/Cargo.toml b/controller/Cargo.toml index 6a3a5ca..3425119 100644 --- a/controller/Cargo.toml +++ b/controller/Cargo.toml @@ -39,10 +39,11 @@ grin_wallet_config = { path = "../config", version = "5.4.0-alpha.1" } ##### Grin Imports # For Release -grin_core = "5.4.0" -grin_keychain = "5.4.0" -grin_util = "5.4.0" -grin_api = "5.4.0" +#grin_core = "5.4.0" +#grin_keychain = "5.4.0" +#grin_util = "5.4.0" +#grin_api = "5.4.0" +#grin_chain = "5.4.0" # For beta release @@ -50,39 +51,24 @@ grin_api = "5.4.0" # grin_keychain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # grin_api = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } +# grin_chain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # For bleeding edge -# grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_api = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_core = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_keychain = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_util = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_api = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_chain = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } # For local testing # grin_core = { path = "../../grin/core"} # grin_keychain = { path = "../../grin/keychain"} # grin_util = { path = "../../grin/util"} # grin_api = { path = "../../grin/api"} +# grin_chain = { path = "../../grin/chain"} ##### [dev-dependencies] ed25519-dalek = "1.0.0-pre.4" remove_dir_all = "0.7" - -##### Grin Imports - -# For Release -grin_chain = "5.4.0" - -# For beta release - -# grin_chain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } - -# For bleeding edge -# grin_chain = { git = "https://github.com/mimblewimble/grin", branch = "master" } - -# For local testing -# grin_chain = { path = "../../grin/chain"} - -##### - diff --git a/controller/src/display.rs b/controller/src/display.rs index 5668485..e5f2f88 100644 --- a/controller/src/display.rs +++ b/controller/src/display.rs @@ -152,6 +152,7 @@ pub fn txs( table.set_titles(row![ bMG->"Id", bMG->"Type", + bMG->"State", bMG->"Shared Transaction Id", bMG->"Creation Time", bMG->"TTL Cutoff Height", @@ -174,6 +175,10 @@ pub fn txs( Some(m) => format!("{}", m), None => "None".to_owned(), }; + let slate_state = match t.tx_slate_state.as_ref() { + Some(m) => format!("{}", m), + None => "None".to_owned(), + }; let entry_type = format!("{}", t.tx_type); let creation_ts = format!("{}", t.creation_ts.format("%Y-%m-%d %H:%M:%S")); let ttl_cutoff_height = match t.ttl_cutoff_height { @@ -220,6 +225,7 @@ pub fn txs( table.add_row(row![ bFC->id, bFC->entry_type, + bFC->slate_state, bFC->slate_id, bFB->creation_ts, bFB->ttl_cutoff_height, diff --git a/controller/tests/common/mod.rs b/controller/tests/common/mod.rs index 24f600d..ff1066e 100644 --- a/controller/tests/common/mod.rs +++ b/controller/tests/common/mod.rs @@ -98,7 +98,7 @@ pub fn create_wallet_proxy( test_dir: &str, ) -> WalletProxy< '_, - DefaultLCProvider<'_, LocalWalletClient, ExtKeychain>, + DefaultLCProvider, LocalWalletClient, ExtKeychain, > { @@ -117,7 +117,7 @@ pub fn create_local_wallet( Box< dyn WalletInst< 'static, - DefaultLCProvider<'static, LocalWalletClient, ExtKeychain>, + DefaultLCProvider, LocalWalletClient, ExtKeychain, >, @@ -129,7 +129,7 @@ pub fn create_local_wallet( let mut wallet = Box::new(DefaultWalletImpl::::new(client).unwrap()) as Box< dyn WalletInst< - DefaultLCProvider<'static, LocalWalletClient, ExtKeychain>, + DefaultLCProvider, LocalWalletClient, ExtKeychain, >, @@ -156,7 +156,7 @@ pub fn open_local_wallet( Box< dyn WalletInst< 'static, - DefaultLCProvider<'static, LocalWalletClient, ExtKeychain>, + DefaultLCProvider, LocalWalletClient, ExtKeychain, >, @@ -168,7 +168,7 @@ pub fn open_local_wallet( let mut wallet = Box::new(DefaultWalletImpl::::new(client).unwrap()) as Box< dyn WalletInst< - DefaultLCProvider<'static, LocalWalletClient, ExtKeychain>, + DefaultLCProvider, LocalWalletClient, ExtKeychain, >, diff --git a/controller/tests/revert.rs b/controller/tests/revert.rs index ea6c0b2..5286c85 100644 --- a/controller/tests/revert.rs +++ b/controller/tests/revert.rs @@ -41,7 +41,7 @@ type Wallet = Arc< Box< dyn WalletInst< 'static, - DefaultLCProvider<'static, LocalWalletClient, ExtKeychain>, + DefaultLCProvider, LocalWalletClient, ExtKeychain, >, diff --git a/controller/tests/tx_list_filter.rs b/controller/tests/tx_list_filter.rs index 7a8dab0..d744694 100644 --- a/controller/tests/tx_list_filter.rs +++ b/controller/tests/tx_list_filter.rs @@ -45,7 +45,7 @@ fn test_wallet_tx_filtering( Box< dyn WalletInst< 'static, - DefaultLCProvider<'static, LocalWalletClient, ExtKeychain>, + DefaultLCProvider, LocalWalletClient, ExtKeychain, >, diff --git a/doc/design/design.md b/doc/design/design.md index d113504..2da52d2 100644 --- a/doc/design/design.md +++ b/doc/design/design.md @@ -55,24 +55,22 @@ the default client only supports single-user - single recipient, an arbitrary nu ### Wallet Traits -In the current code, a Wallet implementation is just a combination of these three traits. The vast majority of functions within libwallet +In the current code, a Wallet implementation is just a combination of these two traits. The vast majority of functions within libwallet and libTX have a signature similar to the following: ```rust pub fn retrieve_outputs( -!·wallet: &mut T, +!·wallet: &mut WalletBackend, !·show_spent: bool, !·tx_id: Option, ) -> Result, Error> where -!·T: WalletBackend, !·C: NodeClient, !·K: Keychain, { ``` -With `T` in this instance being a class that implements the `WalletBackend` trait, which is further parameterized with implementations of -`NodeClient` and `Keychain`. +Provided `WalletBackend` parameterized with implementations of `NodeClient` and `Keychain`. There is currently only a single implementation of the Keychain trait within the Grin code, in the `keychain` crate exported as `ExtKeyChain`. The `Keychain` trait makes several assumptions about the underlying implementation, particularly that it will adhere to a @@ -81,9 +79,4 @@ The `Keychain` trait makes several assumptions about the underlying implementati There are two implementations of `NodeClient` within the code, the main version being the `HTTPNodeClient` found within `wallet/src/client.rs` and the seconds a test client that communicates with an in-process instance of a chain. The NodeClient isolates all network calls, so upgrading wallet communication from the current simple http interaction to a more secure protocol (or allowing for many options) should be a simple -matter of dropping in different `NodeClient` implementations. - -There are also two implementations of `WalletBackend` within the code at the base of the `wallet` crate. `LMDBBackend` found within -`wallet/src/lmdb_wallet.rs` is the main implementation, and is now used by all grin wallet commands. The earlier `FileWallet` still exists -within the code, however it is not invoked, and given there are no real advantages to running it over a DB implementation, development on it -has been dropped in favour of the LMDB implementation. \ No newline at end of file +matter of dropping in different `NodeClient` implementations. \ No newline at end of file diff --git a/impls/Cargo.toml b/impls/Cargo.toml index 6dfc918..9625570 100644 --- a/impls/Cargo.toml +++ b/impls/Cargo.toml @@ -43,12 +43,12 @@ grin_wallet_libwallet = { path = "../libwallet", version = "5.4.0-alpha.1" } ##### Grin Imports # For Release -grin_core = "5.4.0" -grin_keychain = "5.4.0" -grin_chain = "5.4.0" -grin_util = "5.4.0" -grin_api = "5.4.0" -grin_store = "5.4.0" +#grin_core = "5.4.0" +#grin_keychain = "5.4.0" +#grin_chain = "5.4.0" +#grin_util = "5.4.0" +#grin_api = "5.4.0" +#grin_store = "5.4.0" # For beta release @@ -60,12 +60,12 @@ grin_store = "5.4.0" # grin_store = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # For bleeding edge -# grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_chain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_api = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_store = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_core = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_keychain = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_chain = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_util = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_api = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_store = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } # For local testing # grin_core = { path = "../../grin/core"} diff --git a/impls/src/backends/lmdb.rs b/impls/src/backends/lmdb.rs deleted file mode 100644 index e0df269..0000000 --- a/impls/src/backends/lmdb.rs +++ /dev/null @@ -1,777 +0,0 @@ -// Copyright 2021 The Grin Developers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::cell::RefCell; -use std::{fs, path}; - -// for writing stored transaction files -use std::fs::File; -use std::io::{Read, Write}; -use std::marker::PhantomData; -use std::path::Path; - -use uuid::Uuid; - -use crate::blake2::blake2b::{Blake2b, Blake2bResult}; - -use crate::keychain::{ChildNumber, ExtKeychain, Identifier, Keychain, SwitchCommitmentType}; -use crate::store::{self, option_to_not_found, to_key, to_key_u64}; - -use crate::core::core::Transaction; -use crate::core::ser; -use crate::libwallet::{ - AcctPathMapping, Context, Error, NodeClient, OutputData, ScannedBlockInfo, TxLogEntry, - WalletBackend, WalletInitStatus, WalletOutputBatch, -}; -use crate::util::secp::constants::SECRET_KEY_SIZE; -use crate::util::secp::key::SecretKey; -use crate::util::{self, secp, ToHex}; - -use rand::rngs::mock::StepRng; -use rand::thread_rng; - -pub const DB_DIR: &str = "db"; -pub const TX_SAVE_DIR: &str = "saved_txs"; - -const OUTPUT_PREFIX: u8 = b'o'; -const DERIV_PREFIX: u8 = b'd'; -const CONFIRMED_HEIGHT_PREFIX: u8 = b'c'; -const PRIVATE_TX_CONTEXT_PREFIX: u8 = b'p'; -const TX_LOG_ENTRY_PREFIX: u8 = b't'; -const TX_LOG_ID_PREFIX: u8 = b'i'; -const ACCOUNT_PATH_MAPPING_PREFIX: u8 = b'a'; -const LAST_SCANNED_BLOCK: u8 = b'l'; -const LAST_SCANNED_KEY: &str = "LAST_SCANNED_KEY"; -const WALLET_INIT_STATUS: u8 = b'w'; -const WALLET_INIT_STATUS_KEY: &str = "WALLET_INIT_STATUS"; - -/// test to see if database files exist in the current directory. If so, -/// use a DB backend for all operations -pub fn wallet_db_exists(data_file_dir: &str) -> bool { - let db_path = path::Path::new(data_file_dir).join(DB_DIR); - db_path.exists() -} - -/// Helper to derive XOR keys for storing private transaction keys in the DB -/// (blind_xor_key, nonce_xor_key) -fn private_ctx_xor_keys( - keychain: &K, - slate_id: &[u8], -) -> Result<([u8; SECRET_KEY_SIZE], [u8; SECRET_KEY_SIZE]), Error> -where - K: Keychain, -{ - let root_key = keychain.derive_key(0, &K::root_key_id(), SwitchCommitmentType::Regular)?; - - // derive XOR values for storing secret values in DB - // h(root_key|slate_id|"blind") - let mut hasher = Blake2b::new(SECRET_KEY_SIZE); - hasher.update(&root_key.0[..]); - hasher.update(&slate_id[..]); - hasher.update(&b"blind"[..]); - let blind_xor_key = hasher.finalize(); - let mut ret_blind = [0; SECRET_KEY_SIZE]; - ret_blind.copy_from_slice(&blind_xor_key.as_bytes()[0..SECRET_KEY_SIZE]); - - // h(root_key|slate_id|"nonce") - let mut hasher = Blake2b::new(SECRET_KEY_SIZE); - hasher.update(&root_key.0[..]); - hasher.update(&slate_id[..]); - hasher.update(&b"nonce"[..]); - let nonce_xor_key = hasher.finalize(); - let mut ret_nonce = [0; SECRET_KEY_SIZE]; - ret_nonce.copy_from_slice(&nonce_xor_key.as_bytes()[0..SECRET_KEY_SIZE]); - - Ok((ret_blind, ret_nonce)) -} - -pub struct LMDBBackend<'ck, C, K> -where - C: NodeClient + 'ck, - K: Keychain + 'ck, -{ - db: store::Store, - data_file_dir: String, - /// Keychain - pub keychain: Option, - /// Check value for XORed keychain seed - pub master_checksum: Box>, - /// Parent path to use by default for output operations - parent_key_id: Identifier, - /// wallet to node client - w2n_client: C, - ///phantom - _phantom: &'ck PhantomData, -} - -impl<'ck, C, K> LMDBBackend<'ck, C, K> -where - C: NodeClient + 'ck, - K: Keychain + 'ck, -{ - pub fn new(data_file_dir: &str, n_client: C) -> Result { - let db_path = path::Path::new(data_file_dir).join(DB_DIR); - fs::create_dir_all(&db_path).expect("Couldn't create wallet backend directory!"); - - let stored_tx_path = path::Path::new(data_file_dir).join(TX_SAVE_DIR); - fs::create_dir_all(&stored_tx_path) - .expect("Couldn't create wallet backend tx storage directory!"); - - let store = store::Store::new(db_path.to_str().unwrap(), None, Some(DB_DIR), None)?; - - // Make sure default wallet derivation path always exists - // as well as path (so it can be retrieved by batches to know where to store - // completed transactions, for reference - let default_account = AcctPathMapping { - label: "default".to_owned(), - path: LMDBBackend::::default_path(), - }; - let acct_key = to_key( - ACCOUNT_PATH_MAPPING_PREFIX, - &mut default_account.label.as_bytes().to_vec(), - ); - - { - let batch = store.batch()?; - batch.put_ser(&acct_key, &default_account)?; - batch.commit()?; - } - - let res = LMDBBackend { - db: store, - data_file_dir: data_file_dir.to_owned(), - keychain: None, - master_checksum: Box::new(None), - parent_key_id: LMDBBackend::::default_path(), - w2n_client: n_client, - _phantom: &PhantomData, - }; - Ok(res) - } - - fn default_path() -> Identifier { - // return the default parent wallet path, corresponding to the default account - // in the BIP32 spec. Parent is account 0 at level 2, child output identifiers - // are all at level 3 - ExtKeychain::derive_key_id(2, 0, 0, 0, 0) - } - - /// Just test to see if database files exist in the current directory. If - /// so, use a DB backend for all operations - pub fn exists(data_file_dir: &str) -> bool { - let db_path = path::Path::new(data_file_dir).join(DB_DIR); - db_path.exists() - } -} - -impl<'ck, C, K> WalletBackend<'ck, C, K> for LMDBBackend<'ck, C, K> -where - C: NodeClient + 'ck, - K: Keychain + 'ck, -{ - /// Set the keychain, which should already have been opened - fn set_keychain( - &mut self, - mut k: Box, - mask: bool, - use_test_rng: bool, - ) -> Result, Error> { - // store hash of master key, so it can be verified later after unmasking - let root_key = k.derive_key(0, &K::root_key_id(), SwitchCommitmentType::Regular)?; - let mut hasher = Blake2b::new(SECRET_KEY_SIZE); - hasher.update(&root_key.0[..]); - self.master_checksum = Box::new(Some(hasher.finalize())); - - let mask_value = { - match mask { - true => { - // Random value that must be XORed against the stored wallet seed - // before it is used - let mask_value = match use_test_rng { - true => { - let mut test_rng = StepRng::new(1_234_567_890_u64, 1); - secp::key::SecretKey::new(&k.secp(), &mut test_rng) - } - false => secp::key::SecretKey::new(&k.secp(), &mut thread_rng()), - }; - k.mask_master_key(&mask_value)?; - Some(mask_value) - } - false => None, - } - }; - - self.keychain = Some(*k); - Ok(mask_value) - } - - /// Close wallet - fn close(&mut self) -> Result<(), Error> { - self.keychain = None; - Ok(()) - } - - /// Return the keychain being used, cloned with XORed token value - /// for temporary use - fn keychain(&self, mask: Option<&SecretKey>) -> Result { - match self.keychain.as_ref() { - Some(k) => { - let mut k_masked = k.clone(); - if let Some(m) = mask { - k_masked.mask_master_key(m)?; - } - // Check if master seed is what is expected (especially if it's been xored) - let root_key = - k_masked.derive_key(0, &K::root_key_id(), SwitchCommitmentType::Regular)?; - let mut hasher = Blake2b::new(SECRET_KEY_SIZE); - hasher.update(&root_key.0[..]); - if *self.master_checksum != Some(hasher.finalize()) { - error!("Supplied keychain mask is invalid"); - return Err(Error::InvalidKeychainMask); - } - Ok(k_masked) - } - None => Err(Error::KeychainDoesntExist), - } - } - - /// Return the node client being used - fn w2n_client(&mut self) -> &mut C { - &mut self.w2n_client - } - - /// return the version of the commit for caching - fn calc_commit_for_cache( - &mut self, - keychain_mask: Option<&SecretKey>, - amount: u64, - id: &Identifier, - ) -> Result, Error> { - //TODO: Check if this is really necessary, it's the only thing - //preventing removing the need for config in the wallet backend - /*if self.config.no_commit_cache == Some(true) { - Ok(None) - } else {*/ - Ok(Some( - self.keychain(keychain_mask)? - .commit(amount, &id, SwitchCommitmentType::Regular)? - .0 - .to_vec() - .to_hex(), // TODO: proper support for different switch commitment schemes - )) - /*}*/ - } - - /// Set parent path by account name - fn set_parent_key_id_by_name(&mut self, label: &str) -> Result<(), Error> { - let label = label.to_owned(); - let res = self.acct_path_iter().find(|l| l.label == label); - if let Some(a) = res { - self.set_parent_key_id(a.path); - Ok(()) - } else { - Err(Error::UnknownAccountLabel(label)) - } - } - - /// set parent path - fn set_parent_key_id(&mut self, id: Identifier) { - self.parent_key_id = id; - } - - fn parent_key_id(&mut self) -> Identifier { - self.parent_key_id.clone() - } - - fn get(&self, id: &Identifier, mmr_index: &Option) -> Result { - let key = match mmr_index { - Some(i) => to_key_u64(OUTPUT_PREFIX, &mut id.to_bytes().to_vec(), *i), - None => to_key(OUTPUT_PREFIX, &mut id.to_bytes().to_vec()), - }; - option_to_not_found(self.db.get_ser(&key, None), || format!("Key Id: {}", id)) - .map_err(|e| e.into()) - } - - // TODO - fix this awkward conversion between PrefixIterator and our Box - fn iter<'a>(&'a self) -> Box + 'a> { - let protocol_version = self.db.protocol_version(); - let prefix_iter = self.db.iter(&[OUTPUT_PREFIX], move |_, mut v| { - ser::deserialize( - &mut v, - protocol_version, - ser::DeserializationMode::default(), - ) - .map_err(From::from) - }); - let iter = prefix_iter.expect("deserialize").into_iter(); - Box::new(iter) - } - - fn get_tx_log_entry(&self, u: &Uuid) -> Result, Error> { - let key = to_key(TX_LOG_ENTRY_PREFIX, &mut u.as_bytes().to_vec()); - self.db.get_ser(&key, None).map_err(|e| e.into()) - } - - // TODO - fix this awkward conversion between PrefixIterator and our Box - fn tx_log_iter<'a>(&'a self) -> Box + 'a> { - let protocol_version = self.db.protocol_version(); - let prefix_iter = self.db.iter(&[TX_LOG_ENTRY_PREFIX], move |_, mut v| { - ser::deserialize( - &mut v, - protocol_version, - ser::DeserializationMode::default(), - ) - .map_err(From::from) - }); - let iter = prefix_iter.expect("deserialize").into_iter(); - Box::new(iter) - } - - fn get_private_context( - &mut self, - keychain_mask: Option<&SecretKey>, - slate_id: &[u8], - ) -> Result { - let ctx_key = to_key_u64(PRIVATE_TX_CONTEXT_PREFIX, &mut slate_id.to_vec(), 0); - let (blind_xor_key, nonce_xor_key) = - private_ctx_xor_keys(&self.keychain(keychain_mask)?, slate_id)?; - - let mut ctx: Context = option_to_not_found(self.db.get_ser(&ctx_key, None), || { - format!("Slate id: {:x?}", slate_id.to_vec()) - })?; - - for i in 0..SECRET_KEY_SIZE { - ctx.sec_key.0[i] ^= blind_xor_key[i]; - ctx.sec_nonce.0[i] ^= nonce_xor_key[i]; - } - - Ok(ctx) - } - - // TODO - fix this awkward conversion between PrefixIterator and our Box - fn acct_path_iter<'a>(&'a self) -> Box + 'a> { - let protocol_version = self.db.protocol_version(); - let prefix_iter = self - .db - .iter(&[ACCOUNT_PATH_MAPPING_PREFIX], move |_, mut v| { - ser::deserialize( - &mut v, - protocol_version, - ser::DeserializationMode::default(), - ) - .map_err(From::from) - }); - let iter = prefix_iter.expect("deserialize").into_iter(); - Box::new(iter) - } - - fn get_acct_path(&self, label: String) -> Result, Error> { - let acct_key = to_key(ACCOUNT_PATH_MAPPING_PREFIX, &mut label.as_bytes().to_vec()); - self.db.get_ser(&acct_key, None).map_err(|e| e.into()) - } - - fn store_tx(&self, uuid: &str, tx: &Transaction) -> Result<(), Error> { - let filename = format!("{}.grintx", uuid); - let path = path::Path::new(&self.data_file_dir) - .join(TX_SAVE_DIR) - .join(filename); - let path_buf = Path::new(&path).to_path_buf(); - let mut stored_tx = File::create(path_buf)?; - let tx_hex = ser::ser_vec(tx, ser::ProtocolVersion(1)).unwrap().to_hex(); - stored_tx.write_all(&tx_hex.as_bytes())?; - stored_tx.sync_all()?; - Ok(()) - } - - fn get_stored_tx(&self, uuid: &str) -> Result, Error> { - let filename = format!("{}.grintx", uuid); - let path = path::Path::new(&self.data_file_dir) - .join(TX_SAVE_DIR) - .join(filename); - let tx_file = Path::new(&path).to_path_buf(); - let mut tx_f = File::open(tx_file)?; - let mut content = String::new(); - tx_f.read_to_string(&mut content)?; - let tx_bin = util::from_hex(&content).unwrap(); - Ok(Some( - ser::deserialize( - &mut &tx_bin[..], - ser::ProtocolVersion(1), - ser::DeserializationMode::default(), - ) - .unwrap(), - )) - } - - fn batch<'a>( - &'a mut self, - keychain_mask: Option<&SecretKey>, - ) -> Result + 'a>, Error> { - Ok(Box::new(Batch { - _store: self, - db: RefCell::new(Some(self.db.batch()?)), - keychain: Some(self.keychain(keychain_mask)?), - })) - } - - fn batch_no_mask<'a>(&'a mut self) -> Result + 'a>, Error> { - Ok(Box::new(Batch { - _store: self, - db: RefCell::new(Some(self.db.batch()?)), - keychain: None, - })) - } - - fn current_child_index<'a>(&mut self, parent_key_id: &Identifier) -> Result { - let index = { - let batch = self.db.batch()?; - let deriv_key = to_key(DERIV_PREFIX, &mut parent_key_id.to_bytes().to_vec()); - match batch.get_ser(&deriv_key, None)? { - Some(idx) => idx, - None => 0, - } - }; - Ok(index) - } - - fn next_child<'a>(&mut self, keychain_mask: Option<&SecretKey>) -> Result { - let parent_key_id = self.parent_key_id.clone(); - let mut deriv_idx = { - let batch = self.db.batch()?; - let deriv_key = to_key(DERIV_PREFIX, &mut self.parent_key_id.to_bytes().to_vec()); - match batch.get_ser(&deriv_key, None)? { - Some(idx) => idx, - None => 0, - } - }; - let mut return_path = self.parent_key_id.to_path(); - return_path.depth += 1; - return_path.path[return_path.depth as usize - 1] = ChildNumber::from(deriv_idx); - deriv_idx += 1; - let mut batch = self.batch(keychain_mask)?; - batch.save_child_index(&parent_key_id, deriv_idx)?; - batch.commit()?; - Ok(Identifier::from_path(&return_path)) - } - - fn last_confirmed_height<'a>(&mut self) -> Result { - let batch = self.db.batch()?; - let height_key = to_key( - CONFIRMED_HEIGHT_PREFIX, - &mut self.parent_key_id.to_bytes().to_vec(), - ); - let last_confirmed_height = match batch.get_ser(&height_key, None)? { - Some(h) => h, - None => 0, - }; - Ok(last_confirmed_height) - } - - fn last_scanned_block<'a>(&mut self) -> Result { - let batch = self.db.batch()?; - let scanned_block_key = to_key( - LAST_SCANNED_BLOCK, - &mut LAST_SCANNED_KEY.as_bytes().to_vec(), - ); - let last_scanned_block = match batch.get_ser(&scanned_block_key, None)? { - Some(b) => b, - None => ScannedBlockInfo { - height: 0, - hash: "".to_owned(), - start_pmmr_index: 0, - last_pmmr_index: 0, - }, - }; - Ok(last_scanned_block) - } - - fn init_status<'a>(&mut self) -> Result { - let batch = self.db.batch()?; - let init_status_key = to_key( - WALLET_INIT_STATUS, - &mut WALLET_INIT_STATUS_KEY.as_bytes().to_vec(), - ); - let status = match batch.get_ser(&init_status_key, None)? { - Some(s) => s, - None => WalletInitStatus::InitComplete, - }; - Ok(status) - } -} - -/// An atomic batch in which all changes can be committed all at once or -/// discarded on error. -pub struct Batch<'a, C, K> -where - C: NodeClient, - K: Keychain, -{ - _store: &'a LMDBBackend<'a, C, K>, - db: RefCell>>, - /// Keychain - keychain: Option, -} - -#[allow(missing_docs)] -impl<'a, C, K> WalletOutputBatch for Batch<'a, C, K> -where - C: NodeClient, - K: Keychain, -{ - fn keychain(&mut self) -> &mut K { - self.keychain.as_mut().unwrap() - } - - fn save(&mut self, out: OutputData) -> Result<(), Error> { - // Save the output data to the db. - { - let key = match out.mmr_index { - Some(i) => to_key_u64(OUTPUT_PREFIX, &mut out.key_id.to_bytes().to_vec(), i), - None => to_key(OUTPUT_PREFIX, &mut out.key_id.to_bytes().to_vec()), - }; - self.db.borrow().as_ref().unwrap().put_ser(&key, &out)?; - } - - Ok(()) - } - - fn get(&self, id: &Identifier, mmr_index: &Option) -> Result { - let key = match mmr_index { - Some(i) => to_key_u64(OUTPUT_PREFIX, &mut id.to_bytes().to_vec(), *i), - None => to_key(OUTPUT_PREFIX, &mut id.to_bytes().to_vec()), - }; - option_to_not_found( - self.db.borrow().as_ref().unwrap().get_ser(&key, None), - || format!("Key ID: {}", id), - ) - .map_err(|e| e.into()) - } - - // TODO - fix this awkward conversion between PrefixIterator and our Box - fn iter(&self) -> Box> { - let db = self.db.borrow(); - let db = db.as_ref().unwrap(); - let protocol_version = db.protocol_version(); - let prefix_iter = db.iter(&[OUTPUT_PREFIX], move |_, mut v| { - ser::deserialize( - &mut v, - protocol_version, - ser::DeserializationMode::default(), - ) - .map_err(From::from) - }); - let iter = prefix_iter.expect("deserialize").into_iter(); - Box::new(iter) - } - - fn delete(&mut self, id: &Identifier, mmr_index: &Option) -> Result<(), Error> { - // Delete the output data. - { - let key = match mmr_index { - Some(i) => to_key_u64(OUTPUT_PREFIX, &mut id.to_bytes().to_vec(), *i), - None => to_key(OUTPUT_PREFIX, &mut id.to_bytes().to_vec()), - }; - let _ = self.db.borrow().as_ref().unwrap().delete(&key); - } - - Ok(()) - } - - fn next_tx_log_id(&mut self, parent_key_id: &Identifier) -> Result { - let tx_id_key = to_key(TX_LOG_ID_PREFIX, &mut parent_key_id.to_bytes().to_vec()); - let last_tx_log_id = match self - .db - .borrow() - .as_ref() - .unwrap() - .get_ser(&tx_id_key, None)? - { - Some(t) => t, - None => 0, - }; - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&tx_id_key, &(last_tx_log_id + 1))?; - Ok(last_tx_log_id) - } - - // TODO - fix this awkward conversion between PrefixIterator and our Box - fn tx_log_iter(&self) -> Box> { - let db = self.db.borrow(); - let db = db.as_ref().unwrap(); - let protocol_version = db.protocol_version(); - let prefix_iter = db.iter(&[TX_LOG_ENTRY_PREFIX], move |_, mut v| { - ser::deserialize( - &mut v, - protocol_version, - ser::DeserializationMode::default(), - ) - .map_err(From::from) - }); - let iter = prefix_iter.expect("deserialize").into_iter(); - Box::new(iter) - } - - fn save_last_confirmed_height( - &mut self, - parent_key_id: &Identifier, - height: u64, - ) -> Result<(), Error> { - let height_key = to_key( - CONFIRMED_HEIGHT_PREFIX, - &mut parent_key_id.to_bytes().to_vec(), - ); - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&height_key, &height)?; - Ok(()) - } - - fn save_last_scanned_block(&mut self, block_info: ScannedBlockInfo) -> Result<(), Error> { - let pmmr_index_key = to_key( - LAST_SCANNED_BLOCK, - &mut LAST_SCANNED_KEY.as_bytes().to_vec(), - ); - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&pmmr_index_key, &block_info)?; - Ok(()) - } - - fn save_init_status(&mut self, value: WalletInitStatus) -> Result<(), Error> { - let init_status_key = to_key( - WALLET_INIT_STATUS, - &mut WALLET_INIT_STATUS_KEY.as_bytes().to_vec(), - ); - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&init_status_key, &value)?; - Ok(()) - } - - fn save_child_index(&mut self, parent_id: &Identifier, child_n: u32) -> Result<(), Error> { - let deriv_key = to_key(DERIV_PREFIX, &mut parent_id.to_bytes().to_vec()); - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&deriv_key, &child_n)?; - Ok(()) - } - - fn save_tx_log_entry( - &mut self, - tx_in: TxLogEntry, - parent_id: &Identifier, - ) -> Result<(), Error> { - let tx_log_key = to_key_u64( - TX_LOG_ENTRY_PREFIX, - &mut parent_id.to_bytes().to_vec(), - tx_in.id as u64, - ); - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&tx_log_key, &tx_in)?; - Ok(()) - } - - fn delete_tx_log_entry(&mut self, tx_id: u32, parent_id: &Identifier) -> Result<(), Error> { - let tx_log_key = to_key_u64( - TX_LOG_ENTRY_PREFIX, - &mut parent_id.to_bytes().to_vec(), - tx_id as u64, - ); - self.db.borrow().as_ref().unwrap().delete(&tx_log_key)?; - Ok(()) - } - - fn save_acct_path(&mut self, mapping: AcctPathMapping) -> Result<(), Error> { - let acct_key = to_key( - ACCOUNT_PATH_MAPPING_PREFIX, - &mut mapping.label.as_bytes().to_vec(), - ); - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&acct_key, &mapping)?; - Ok(()) - } - - // TODO - fix this awkward conversion between PrefixIterator and our Box - fn acct_path_iter(&self) -> Box> { - let db = self.db.borrow(); - let db = db.as_ref().unwrap(); - let protocol_version = db.protocol_version(); - let prefix_iter = db.iter(&[ACCOUNT_PATH_MAPPING_PREFIX], move |_, mut v| { - ser::deserialize( - &mut v, - protocol_version, - ser::DeserializationMode::default(), - ) - .map_err(From::from) - }); - let iter = prefix_iter.expect("deserialize").into_iter(); - Box::new(iter) - } - - fn lock_output(&mut self, out: &mut OutputData) -> Result<(), Error> { - out.lock(); - self.save(out.clone()) - } - - fn save_private_context(&mut self, slate_id: &[u8], ctx: &Context) -> Result<(), Error> { - let ctx_key = to_key_u64(PRIVATE_TX_CONTEXT_PREFIX, &mut slate_id.to_vec(), 0); - let (blind_xor_key, nonce_xor_key) = private_ctx_xor_keys(self.keychain(), slate_id)?; - - let mut s_ctx = ctx.clone(); - for i in 0..SECRET_KEY_SIZE { - s_ctx.sec_key.0[i] ^= blind_xor_key[i]; - s_ctx.sec_nonce.0[i] ^= nonce_xor_key[i]; - } - - self.db - .borrow() - .as_ref() - .unwrap() - .put_ser(&ctx_key, &s_ctx)?; - Ok(()) - } - - fn delete_private_context(&mut self, slate_id: &[u8]) -> Result<(), Error> { - let ctx_key = to_key_u64(PRIVATE_TX_CONTEXT_PREFIX, &mut slate_id.to_vec(), 0); - self.db - .borrow() - .as_ref() - .unwrap() - .delete(&ctx_key) - .map_err(|e| e.into()) - } - - fn commit(&self) -> Result<(), Error> { - let db = self.db.replace(None); - db.unwrap().commit()?; - Ok(()) - } -} diff --git a/impls/src/backends/mod.rs b/impls/src/backends/mod.rs deleted file mode 100644 index 56b5df6..0000000 --- a/impls/src/backends/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2021 The Grin Developers -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -mod lmdb; - -pub use self::lmdb::{wallet_db_exists, LMDBBackend}; diff --git a/impls/src/lib.rs b/impls/src/lib.rs index b18ad7c..9e9c32c 100644 --- a/impls/src/lib.rs +++ b/impls/src/lib.rs @@ -28,14 +28,12 @@ use grin_api as api; use grin_chain as chain; use grin_core as core; use grin_keychain as keychain; -use grin_store as store; use grin_util as util; use grin_wallet_libwallet as libwallet; use grin_wallet_config as config; mod adapters; -mod backends; mod client_utils; mod error; mod lifecycle; @@ -47,7 +45,6 @@ pub use crate::adapters::{ HttpSlateSender, PathToSlate, PathToSlatepack, SlateGetter, SlatePutter, SlateReceiver, SlateSender, }; -pub use crate::backends::{wallet_db_exists, LMDBBackend}; pub use crate::error::Error; pub use crate::lifecycle::DefaultLCProvider; pub use crate::node_clients::HTTPNodeClient; @@ -57,35 +54,31 @@ use crate::keychain::{ExtKeychain, Keychain}; use libwallet::{NodeClient, WalletInst, WalletLCProvider}; /// Main wallet instance -pub struct DefaultWalletImpl<'a, C> +pub struct DefaultWalletImpl where - C: NodeClient + 'a, + C: NodeClient, { - lc_provider: DefaultLCProvider<'a, C, ExtKeychain>, + lc_provider: DefaultLCProvider, } -impl<'a, C> DefaultWalletImpl<'a, C> +impl DefaultWalletImpl where - C: NodeClient + 'a, + C: NodeClient, { pub fn new(node_client: C) -> Result { let lc_provider = DefaultLCProvider::new(node_client); - Ok(DefaultWalletImpl { - lc_provider: lc_provider, - }) + Ok(DefaultWalletImpl { lc_provider }) } } -impl<'a, L, C, K> WalletInst<'a, L, C, K> for DefaultWalletImpl<'a, C> +impl<'a, L, C, K> WalletInst<'a, L, C, K> for DefaultWalletImpl where - DefaultLCProvider<'a, C, ExtKeychain>: WalletLCProvider<'a, C, K>, + DefaultLCProvider: WalletLCProvider<'a, C, K>, L: WalletLCProvider<'a, C, K>, C: NodeClient + 'a, K: Keychain + 'a, { - fn lc_provider( - &mut self, - ) -> Result<&mut (dyn WalletLCProvider<'a, C, K> + 'a), libwallet::Error> { + fn lc_provider(&mut self) -> Result<&mut dyn WalletLCProvider<'a, C, K>, libwallet::Error> { Ok(&mut self.lc_provider) } } diff --git a/impls/src/lifecycle/default.rs b/impls/src/lifecycle/default.rs index 0b24b68..4514eb3 100644 --- a/impls/src/lifecycle/default.rs +++ b/impls/src/lifecycle/default.rs @@ -23,13 +23,12 @@ use crate::libwallet::{Error, NodeClient, WalletBackend, WalletInitStatus, Walle use crate::lifecycle::seed::WalletSeed; use crate::util::secp::key::SecretKey; use crate::util::ZeroingString; -use crate::LMDBBackend; use grin_util::logger::LoggingConfig; use std::fs; use std::path::PathBuf; use std::path::MAIN_SEPARATOR; -// Helper fuction to format paths according to OS, avoids bugs on Linux +/// Helper function to format paths according to OS, avoids bugs on Linux pub fn fmt_path(path: String) -> String { let sep = &MAIN_SEPARATOR.to_string(); let path = path.replace("/", &sep); @@ -37,20 +36,20 @@ pub fn fmt_path(path: String) -> String { path } -pub struct DefaultLCProvider<'a, C, K> +pub struct DefaultLCProvider where - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { data_dir: String, node_client: C, - backend: Option + 'a>>, + backend: Option>, } -impl<'a, C, K> DefaultLCProvider<'a, C, K> +impl DefaultLCProvider where - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { /// Create new provider pub fn new(node_client: C) -> Self { @@ -62,7 +61,7 @@ where } } -impl<'a, C, K> WalletLCProvider<'a, C, K> for DefaultLCProvider<'a, C, K> +impl<'a, C, K> WalletLCProvider<'a, C, K> for DefaultLCProvider where C: NodeClient + 'a, K: Keychain + 'a, @@ -217,8 +216,8 @@ where Error::Lifecycle("Error creating wallet seed (is mnemonic valid?)".to_owned()) })?; info!("Wallet seed file created"); - let mut wallet: LMDBBackend<'a, C, K> = - match LMDBBackend::new(&data_dir_name, self.node_client.clone()) { + let mut wallet: WalletBackend = + match WalletBackend::new(&data_dir_name, self.node_client.clone()) { Err(e) => { let msg = format!("Error creating wallet: {}, Data Dir: {}", e, &data_dir_name); error!("{}", msg); @@ -247,8 +246,8 @@ where let mut data_dir_name = PathBuf::from(self.data_dir.clone()); data_dir_name.push(GRIN_WALLET_DIR); let data_dir_name = fmt_path(data_dir_name.to_str().unwrap().to_string()); - let mut wallet: LMDBBackend<'a, C, K> = - match LMDBBackend::new(&data_dir_name, self.node_client.clone()) { + let mut wallet: WalletBackend = + match WalletBackend::new(&data_dir_name, self.node_client.clone()) { Err(e) => { let msg = format!("Error opening wallet: {}, Data Dir: {}", e, &data_dir_name); return Err(Error::Lifecycle(msg)); @@ -262,8 +261,8 @@ where .derive_keychain(global::is_testnet()) .map_err(|_| Error::Lifecycle("Error deriving keychain".to_owned()))?; - let mask = wallet.set_keychain(Box::new(keychain), create_mask, use_test_rng)?; - self.backend = Some(Box::new(wallet)); + let mask = wallet.set_keychain(keychain, create_mask, use_test_rng)?; + self.backend = Some(wallet); Ok(mask) } @@ -329,8 +328,7 @@ where let mut data_dir_name = PathBuf::from(self.data_dir.clone()); data_dir_name.push(GRIN_WALLET_DIR); let data_dir_name = data_dir_name.to_str().unwrap(); - // get seed for later check - + // Get seed for later check let orig_wallet_seed = WalletSeed::from_file(&data_dir_name, old) .map_err(|_| Error::Lifecycle("Error opening wallet seed file".into()))?; let orig_mnemonic = orig_wallet_seed @@ -366,7 +364,7 @@ where .to_string(); return Err(Error::Lifecycle(msg)); } - // Removin + // Removing old file info!("Password change confirmed, removing old seed file."); fs::remove_file(backup_name).map_err(|e| Error::IO(e.to_string()))?; @@ -383,13 +381,13 @@ where Ok(()) } - fn wallet_inst(&mut self) -> Result<&mut Box + 'a>, Error> { + fn wallet_inst(&mut self) -> Result<&mut WalletBackend, Error> { match self.backend.as_mut() { None => { let msg = "Wallet has not been opened".into(); Err(Error::Lifecycle(msg)) } - Some(_) => Ok(&mut *self.backend.as_mut().unwrap()), + Some(b) => Ok(b), } } } diff --git a/impls/src/lifecycle/seed.rs b/impls/src/lifecycle/seed.rs index 59dcd34..5dbbd6c 100644 --- a/impls/src/lifecycle/seed.rs +++ b/impls/src/lifecycle/seed.rs @@ -25,6 +25,7 @@ use ring::aead; use ring::pbkdf2; use crate::keychain::{mnemonic, Keychain}; +use crate::lifecycle::default::fmt_path; use crate::util::{self, ToHex}; use crate::Error; @@ -56,13 +57,6 @@ impl WalletSeed { self.0.to_vec().to_hex() } - // Helper fuction to format paths according to OS, avoids bugs on Linux - pub fn fmt_path(path: String) -> String { - let sep = &MAIN_SEPARATOR.to_string(); - let path = path.replace("/", &sep); - let path = path.replace("\\", &sep); - path - } pub fn to_mnemonic(&self) -> Result { let result = mnemonic::from_entropy(&self.0); match result { @@ -105,7 +99,7 @@ impl WalletSeed { pub fn seed_file_exists(data_file_dir: &str) -> Result { let seed_file_path = &format!( "{}{}{}", - Self::fmt_path(data_file_dir.to_string()), + fmt_path(data_file_dir.to_string()), MAIN_SEPARATOR, SEED_FILE, ); @@ -145,7 +139,7 @@ impl WalletSeed { ) -> Result<(), Error> { let seed_file_path = &format!( "{}{}{}", - Self::fmt_path(data_file_dir.to_string()), + fmt_path(data_file_dir.to_string()), MAIN_SEPARATOR, SEED_FILE, ); @@ -184,11 +178,11 @@ impl WalletSeed { let seed_file_path = &format!( "{}{}{}", - Self::fmt_path(data_file_dir.to_string()), + fmt_path(data_file_dir.to_string()), MAIN_SEPARATOR, SEED_FILE, ); - let data_file_dir = Self::fmt_path(data_file_dir.to_string()); + let data_file_dir = fmt_path(data_file_dir.to_string()); warn!("Generating wallet seed file at: {}", seed_file_path); let exists = WalletSeed::seed_file_exists(&data_file_dir)?; if exists && !test_mode { @@ -219,7 +213,7 @@ impl WalletSeed { let seed_file_path = &format!( "{}{}{}", - Self::fmt_path(data_file_dir.to_string()), + fmt_path(data_file_dir.to_string()), MAIN_SEPARATOR, SEED_FILE, ); @@ -247,7 +241,7 @@ impl WalletSeed { pub fn delete_seed_file(data_file_dir: &str) -> Result<(), Error> { let seed_file_path = &format!( "{}{}{}", - Self::fmt_path(data_file_dir.to_string()), + fmt_path(data_file_dir.to_string()), MAIN_SEPARATOR, SEED_FILE, ); diff --git a/impls/src/test_framework/mod.rs b/impls/src/test_framework/mod.rs index 2479793..c90eac5 100644 --- a/impls/src/test_framework/mod.rs +++ b/impls/src/test_framework/mod.rs @@ -18,7 +18,6 @@ use crate::chain::Chain; use crate::core; use crate::core::core::{Output, Transaction, TxKernel}; use crate::core::{consensus, global, pow}; -use crate::keychain; use crate::libwallet; use crate::libwallet::api_impl::{foreign, owner}; use crate::libwallet::{ @@ -28,6 +27,7 @@ use crate::util::secp::key::SecretKey; use crate::util::secp::pedersen; use crate::util::Mutex; use chrono::Duration; +use grin_keychain::Keychain; use std::sync::Arc; use std::thread; @@ -36,7 +36,7 @@ mod testclient; pub use self::{testclient::LocalWalletClient, testclient::WalletProxy}; /// Get an output from the chain locally and present it back as an API output -fn get_output_local(chain: &chain::Chain, commit: pedersen::Commitment) -> Option { +fn get_output_local(chain: &Chain, commit: pedersen::Commitment) -> Option { if chain.get_unspent(commit).unwrap().is_some() { let block_height = chain.get_header_for_output(commit).unwrap().height; let output_pos = chain.get_output_pos(&commit).unwrap_or(0); @@ -48,7 +48,7 @@ fn get_output_local(chain: &chain::Chain, commit: pedersen::Commitment) -> Optio /// Get a kernel from the chain locally fn get_kernel_local( - chain: Arc, + chain: Arc, excess: &pedersen::Commitment, min_height: Option, max_height: Option, @@ -65,7 +65,7 @@ fn get_kernel_local( /// get output listing traversing pmmr from local fn get_outputs_by_pmmr_index_local( - chain: Arc, + chain: Arc, start_index: u64, end_index: Option, max: u64, @@ -86,7 +86,7 @@ fn get_outputs_by_pmmr_index_local( /// get output listing in a given block range fn height_range_to_pmmr_indices_local( - chain: Arc, + chain: Arc, start_index: u64, end_index: Option, ) -> api::OutputListing { @@ -147,13 +147,13 @@ pub fn create_block_for_wallet<'a, L, C, K>( chain: &Chain, prev: core::core::BlockHeader, txs: &[Transaction], - wallet: Arc + 'a>>>, + wallet: Arc>>>, keychain_mask: Option<&SecretKey>, ) -> Result where L: WalletLCProvider<'a, C, K>, C: NodeClient + 'a, - K: keychain::Keychain + 'a, + K: Keychain + 'a, { // build block fees let fee_amt = txs.iter().map(|tx| tx.fee()).sum(); @@ -166,7 +166,7 @@ where let coinbase_tx = { let mut w_lock = wallet.lock(); let w = w_lock.lc_provider()?.wallet_inst()?; - foreign::build_coinbase(&mut **w, keychain_mask, &block_fees, false)? + foreign::build_coinbase(w, keychain_mask, &block_fees, false)? }; let block = create_block_with_reward(chain, prev, txs, coinbase_tx.output, coinbase_tx.kernel); Ok(block) @@ -178,13 +178,13 @@ where pub fn award_block_to_wallet<'a, L, C, K>( chain: &Chain, txs: &[Transaction], - wallet: Arc + 'a>>>, + wallet: Arc>>>, keychain_mask: Option<&SecretKey>, ) -> Result<(), libwallet::Error> where L: WalletLCProvider<'a, C, K>, C: NodeClient + 'a, - K: keychain::Keychain + 'a, + K: Keychain + 'a, { let prev = chain.head_header().unwrap(); let block = create_block_for_wallet(chain, prev, txs, wallet, keychain_mask)?; @@ -200,7 +200,7 @@ pub fn process_block(chain: &Chain, block: core::core::Block) { /// Award a blocks to a wallet directly pub fn award_blocks_to_wallet<'a, L, C, K>( chain: &Chain, - wallet: Arc + 'a>>>, + wallet: Arc>>>, keychain_mask: Option<&SecretKey>, number: usize, pause_between: bool, @@ -208,7 +208,7 @@ pub fn award_blocks_to_wallet<'a, L, C, K>( where L: WalletLCProvider<'a, C, K>, C: NodeClient + 'a, - K: keychain::Keychain + 'a, + K: Keychain + 'a, { for _ in 0..number { award_block_to_wallet(chain, &[], wallet.clone(), keychain_mask)?; @@ -231,7 +231,7 @@ pub fn send_to_dest<'a, L, C, K>( where L: WalletLCProvider<'a, C, K>, C: NodeClient + 'a, - K: keychain::Keychain + 'a, + K: Keychain + 'a, { let slate = { let mut w_lock = wallet.lock(); @@ -245,10 +245,10 @@ where selection_strategy_is_use_all: true, ..Default::default() }; - let slate_i = owner::init_send_tx(&mut **w, keychain_mask, args, test_mode)?; + let slate_i = owner::init_send_tx(w, keychain_mask, args, test_mode)?; let slate = client.send_tx_slate_direct(dest, &slate_i)?; - owner::tx_lock_outputs(&mut **w, keychain_mask, &slate)?; - owner::finalize_tx(&mut **w, keychain_mask, &slate)? + owner::tx_lock_outputs(w, keychain_mask, &slate)?; + owner::finalize_tx(w, keychain_mask, &slate)? }; let client = { let mut w_lock = wallet.lock(); @@ -267,7 +267,7 @@ pub fn wallet_info<'a, L, C, K>( where L: WalletLCProvider<'a, C, K>, C: NodeClient + 'a, - K: keychain::Keychain + 'a, + K: Keychain + 'a, { let (wallet_refreshed, wallet_info) = owner::retrieve_summary_info(wallet, keychain_mask, &None, true, 1)?; diff --git a/impls/src/test_framework/testclient.rs b/impls/src/test_framework/testclient.rs index 05eb083..dcd2ac1 100644 --- a/impls/src/test_framework/testclient.rs +++ b/impls/src/test_framework/testclient.rs @@ -70,7 +70,7 @@ where String, ( Sender, - Arc + 'a>>>, + Arc>>>, Option, ), >, @@ -100,14 +100,15 @@ where genesis_block, pow::verify_size, false, + None, ) .unwrap(); let (tx, rx) = channel(); WalletProxy { chain_dir: chain_dir.to_owned(), chain: Arc::new(c), - tx: tx, - rx: rx, + tx, + rx, wallets: HashMap::new(), running: Arc::new(AtomicBool::new(false)), } @@ -118,7 +119,7 @@ where &mut self, addr: &str, tx: Sender, - wallet: Arc + 'a>>>, + wallet: Arc>>>, keychain_mask: Option, ) { self.wallets @@ -218,8 +219,7 @@ where let w = w_lock.lc_provider()?.wallet_inst()?; let mask = wallet.2.clone(); // receive tx - match foreign::receive_tx(&mut **w, (&mask).as_ref(), &Slate::from(slate), None, false) - { + match foreign::receive_tx(w, (&mask).as_ref(), &Slate::from(slate), None, false) { Err(e) => { return Ok(WalletProxyMessage { sender_id: m.dest, diff --git a/libwallet/Cargo.toml b/libwallet/Cargo.toml index e826004..65354a6 100644 --- a/libwallet/Cargo.toml +++ b/libwallet/Cargo.toml @@ -46,10 +46,10 @@ grin_wallet_config = { path = "../config", version = "5.4.0-alpha.1" } ##### Grin Imports # For Release -grin_core = "5.4.0" -grin_keychain = "5.4.0" -grin_util = "5.4.0" -grin_store = "5.4.0" +#grin_core = "5.4.0" +#grin_keychain = "5.4.0" +#grin_util = "5.4.0" +#grin_store = "5.4.0" # For beta release @@ -59,10 +59,10 @@ grin_store = "5.4.0" # grin_store = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # For bleeding edge -# grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } -# grin_store = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_core = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_keychain = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_util = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } +grin_store = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } # For local testing # grin_core = { path = "../../grin/core"} @@ -70,4 +70,4 @@ grin_store = "5.4.0" # grin_util = { path = "../../grin/util"} # grin_store = { path = "../../grin/store"} -##### +##### diff --git a/libwallet/src/api_impl/foreign.rs b/libwallet/src/api_impl/foreign.rs index 315091c..f3cb611 100644 --- a/libwallet/src/api_impl/foreign.rs +++ b/libwallet/src/api_impl/foreign.rs @@ -13,9 +13,13 @@ // limitations under the License. //! Generic implementation of owner API functions + +use grin_keychain::Identifier; use strum::IntoEnumIterator; +use super::owner::tx_lock_outputs; use crate::api_impl::owner::{check_ttl, post_tx}; +use crate::backend::WalletBackend; use crate::grin_core::core::FeeFields; use crate::grin_keychain::Keychain; use crate::grin_util::secp::key::SecretKey; @@ -23,11 +27,8 @@ use crate::internal::{selection, tx, updater}; use crate::slate_versions::SlateVersion; use crate::{ address, BlockFees, CbData, Error, NodeClient, Slate, SlateState, TxLogEntryType, VersionInfo, - WalletBackend, }; -use super::owner::tx_lock_outputs; - const FOREIGN_API_VERSION: u16 = 2; /// Return the version info @@ -39,32 +40,30 @@ pub fn check_version() -> VersionInfo { } /// Build a coinbase transaction -pub fn build_coinbase<'a, T: ?Sized, C, K>( - w: &mut T, +pub fn build_coinbase( + w: &mut WalletBackend, keychain_mask: Option<&SecretKey>, block_fees: &BlockFees, test_mode: bool, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { - updater::build_coinbase(&mut *w, keychain_mask, block_fees, test_mode) + updater::build_coinbase(w, keychain_mask, block_fees, test_mode) } /// Receive a tx as recipient -pub fn receive_tx<'a, T: ?Sized, C, K>( - w: &mut T, +pub fn receive_tx( + w: &mut WalletBackend, keychain_mask: Option<&SecretKey>, slate: &Slate, dest_acct_name: Option<&str>, use_test_rng: bool, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let mut ret_slate = slate.clone(); check_ttl(w, &ret_slate)?; @@ -80,7 +79,7 @@ where }; // Don't do this multiple times let tx = updater::retrieve_txs( - &mut *w, + w, None, Some(ret_slate.id), None, @@ -99,7 +98,7 @@ where let keychain = w.keychain(keychain_mask)?; let context = tx::add_output_to_slate( - &mut *w, + w, keychain_mask, &mut ret_slate, height, @@ -127,22 +126,23 @@ where ret_slate.amount = 0; ret_slate.fee_fields = FeeFields::zero(); ret_slate.remove_other_sigdata(&keychain, &context.sec_nonce, &context.sec_key)?; + ret_slate.state = SlateState::Standard2; + update_tx_slate_state(w, keychain_mask, &parent_key_id, &ret_slate)?; Ok(ret_slate) } /// Receive a tx that this wallet has issued -pub fn finalize_tx<'a, T: ?Sized, C, K>( - w: &mut T, +pub fn finalize_tx( + w: &mut WalletBackend, keychain_mask: Option<&SecretKey>, slate: &Slate, post_automatically: bool, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let mut sl = slate.clone(); let mut context = w.get_private_context(keychain_mask, sl.id.as_bytes())?; @@ -154,10 +154,10 @@ where let mut temp_ctx = context.clone(); temp_ctx.sec_key = context.initial_sec_key.clone(); temp_ctx.sec_nonce = context.initial_sec_nonce.clone(); - selection::repopulate_tx(&mut *w, keychain_mask, &mut sl, &temp_ctx, false)?; + selection::repopulate_tx(w, keychain_mask, &mut sl, &temp_ctx, false)?; - tx::complete_tx(&mut *w, keychain_mask, &mut sl, &context)?; - tx::update_stored_tx(&mut *w, keychain_mask, &context, &mut sl, true)?; + tx::complete_tx(w, keychain_mask, &mut sl, &context)?; + tx::update_stored_tx(w, keychain_mask, &context, &mut sl, true)?; { let mut batch = w.batch(keychain_mask)?; batch.delete_private_context(sl.id.as_bytes())?; @@ -165,6 +165,9 @@ where } sl.state = SlateState::Invoice3; sl.amount = 0; + + let parent_key_id = w.parent_key_id(); + update_tx_slate_state(w, keychain_mask, &parent_key_id, &sl)?; } else if sl.state == SlateState::Standard2 { let keychain = w.keychain(keychain_mask)?; let parent_key_id = w.parent_key_id(); @@ -175,7 +178,7 @@ where let current_height = w.w2n_client().get_chain_tip()?.0; let mut temp_sl = - tx::new_tx_slate(&mut *w, context.amount, false, 2, false, args.ttl_blocks)?; + tx::new_tx_slate(w, context.amount, false, 2, false, args.ttl_blocks)?; let temp_context = selection::build_send_tx( w, &keychain, @@ -211,11 +214,11 @@ where // Add our contribution to the offset sl.adjust_offset(&keychain, &context)?; - selection::repopulate_tx(&mut *w, keychain_mask, &mut sl, &context, true)?; + selection::repopulate_tx(w, keychain_mask, &mut sl, &context, true)?; - tx::complete_tx(&mut *w, keychain_mask, &mut sl, &context)?; - tx::verify_slate_payment_proof(&mut *w, keychain_mask, &parent_key_id, &context, &sl)?; - tx::update_stored_tx(&mut *w, keychain_mask, &context, &sl, false)?; + tx::complete_tx(w, keychain_mask, &mut sl, &context)?; + tx::verify_slate_payment_proof(w, keychain_mask, &parent_key_id, &context, &sl)?; + tx::update_stored_tx(w, keychain_mask, &context, &sl, false)?; { let mut batch = w.batch(keychain_mask)?; batch.delete_private_context(sl.id.as_bytes())?; @@ -223,6 +226,8 @@ where } sl.state = SlateState::Standard3; sl.amount = 0; + + update_tx_slate_state(w, keychain_mask, &parent_key_id, &sl)?; } else { return Err(Error::SlateState); } @@ -231,3 +236,39 @@ where } Ok(sl) } + +/// Update transaction slate state. +fn update_tx_slate_state( + wallet: &mut WalletBackend, + keychain_mask: Option<&SecretKey>, + parent_key_id: &Identifier, + slate: &Slate, +) -> Result<(), Error> +where + C: NodeClient, + K: Keychain, +{ + let mut bad_records = 0; + let tx = wallet + .tx_log_iter()? + .filter(|tx| { + if tx.is_err() { + bad_records += 1; + } + tx.is_ok() + }) + .map(|tx| tx.unwrap()) + .find(|tx| tx.tx_slate_id == Some(slate.id)); + if let Some(mut tx) = tx { + let mut batch = wallet.batch(keychain_mask)?; + tx.tx_slate_state = Some(slate.state.clone()); + batch.save_tx_log_entry(tx.clone(), parent_key_id)?; + batch.commit()?; + } else { + return Err(Error::Backend(format!( + "Tx log entry with slate id {} not found, there are {} bad tx log records", + slate.id, bad_records + ))); + } + Ok(()) +} diff --git a/libwallet/src/api_impl/owner.rs b/libwallet/src/api_impl/owner.rs index 9ff8e0f..67f642e 100644 --- a/libwallet/src/api_impl/owner.rs +++ b/libwallet/src/api_impl/owner.rs @@ -31,15 +31,14 @@ use crate::api_impl::owner_updater::StatusMessage; use crate::grin_keychain::{BlindingFactor, Identifier, Keychain, SwitchCommitmentType}; use crate::internal::{keys, scan, selection, tx, updater}; use crate::slate::{PaymentInfo, Slate, SlateState}; -use crate::types::{AcctPathMapping, NodeClient, TxLogEntry, WalletBackend, WalletInfo}; -use crate::Error; +use crate::types::{AcctPathMapping, NodeClient, TxLogEntry, WalletInfo}; use crate::{ address, mwixnet::{create_onion, ComSignature, Hop, MixnetReqCreationParams, SwapReq}, - wallet_lock, BuiltOutput, InitTxArgs, IssueInvoiceTxArgs, NodeHeightResult, + wallet_lock, BuiltOutput, Error, InitTxArgs, IssueInvoiceTxArgs, NodeHeightResult, OutputCommitMapping, PaymentProof, RetrieveTxQueryArgs, ScannedBlockInfo, Slatepack, - SlatepackAddress, Slatepacker, SlatepackerArgs, TxLogEntryType, ViewWallet, WalletInitStatus, - WalletInst, WalletLCProvider, + SlatepackAddress, Slatepacker, SlatepackerArgs, TxLogEntryType, ViewWallet, WalletBackend, + WalletInitStatus, WalletInst, WalletLCProvider, }; use ed25519_dalek::PublicKey as DalekPublicKey; @@ -52,35 +51,32 @@ use std::sync::mpsc::Sender; use std::sync::Arc; /// List of accounts -pub fn accounts<'a, T: ?Sized, C, K>(w: &mut T) -> Result, Error> +pub fn accounts(w: &mut WalletBackend) -> Result, Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { - keys::accounts(&mut *w) + keys::accounts(w) } /// new account path -pub fn create_account_path<'a, T: ?Sized, C, K>( - w: &mut T, +pub fn create_account_path( + w: &mut WalletBackend, keychain_mask: Option<&SecretKey>, label: &str, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { - keys::new_acct_path(&mut *w, keychain_mask, label) + keys::new_acct_path(w, keychain_mask, label) } /// set active account -pub fn set_active_account<'a, T: ?Sized, C, K>(w: &mut T, label: &str) -> Result<(), Error> +pub fn set_active_account(w: &mut WalletBackend, label: &str) -> Result<(), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { w.set_parent_key_id_by_name(label) } @@ -196,7 +192,7 @@ where dec_key: None, }); let slatepack = packer.deser_slatepack(slatepack.as_bytes(), true)?; - return packer.get_slate(&slatepack); + packer.get_slate(&slatepack) } else { for index in secret_indices { let dec_key = Some(get_slatepack_secret_key( @@ -218,11 +214,11 @@ where }; return packer.get_slate(&slatepack); } - return Err(Error::SlatepackDecryption( + Err(Error::SlatepackDecryption( "Could not decrypt slatepack with any provided index on the address derivation path" .to_owned(), ) - .into()); + .into()) } } @@ -302,13 +298,7 @@ where Ok(( validated, - updater::retrieve_outputs( - &mut **w, - keychain_mask, - include_spent, - tx_id, - Some(&parent_key_id), - )?, + updater::retrieve_outputs(w, keychain_mask, include_spent, tx_id, Some(&parent_key_id))?, )) } @@ -341,7 +331,7 @@ where wallet_lock!(wallet_inst, w); let parent_key_id = w.parent_key_id(); let txs = updater::retrieve_txs( - &mut **w, + w, tx_id, tx_slate_id, query_args, @@ -378,7 +368,7 @@ where wallet_lock!(wallet_inst, w); let parent_key_id = w.parent_key_id(); - let wallet_info = updater::retrieve_info(&mut **w, &parent_key_id, minimum_confirmations)?; + let wallet_info = updater::retrieve_info(w, &parent_key_id, minimum_confirmations)?; Ok((validated, wallet_info)) } @@ -469,8 +459,8 @@ where } }; Ok(PaymentProof { - amount: amount, - excess: excess, + amount, + excess, recipient_address: SlatepackAddress::new(&proof.receiver_address), recipient_sig: r_sig, sender_address: SlatepackAddress::new(&proof.sender_address), @@ -479,16 +469,15 @@ where } /// Initiate tx as sender -pub fn init_send_tx<'a, T: ?Sized, C, K>( - w: &mut T, +pub fn init_send_tx( + w: &mut WalletBackend, keychain_mask: Option<&SecretKey>, args: InitTxArgs, use_test_rng: bool, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let parent_key_id = match &args.src_acct_name { Some(d) => { @@ -501,14 +490,7 @@ where None => w.parent_key_id(), }; - let mut slate = tx::new_tx_slate( - &mut *w, - args.amount, - false, - 2, - use_test_rng, - args.ttl_blocks, - )?; + let mut slate = tx::new_tx_slate(w, args.amount, false, 2, use_test_rng, args.ttl_blocks)?; if let Some(v) = args.target_slate_version { slate.version_info.version = v; @@ -518,7 +500,7 @@ where // back if let Some(true) = args.estimate_only { let (total, fee) = tx::estimate_send_tx( - &mut *w, + w, keychain_mask, args.amount, args.amount_includes_fee.unwrap_or(false), @@ -536,7 +518,7 @@ where let height = w.w2n_client().get_chain_tip()?.0; let mut context = if args.late_lock.unwrap_or(false) { tx::create_late_lock_context( - &mut *w, + w, keychain_mask, &mut slate, height, @@ -546,7 +528,7 @@ where )? } else { tx::add_inputs_to_slate( - &mut *w, + w, keychain_mask, &mut slate, height, @@ -595,16 +577,15 @@ where } /// Initiate a transaction as the recipient (invoicing) -pub fn issue_invoice_tx<'a, T: ?Sized, C, K>( - w: &mut T, +pub fn issue_invoice_tx( + w: &mut WalletBackend, keychain_mask: Option<&SecretKey>, args: IssueInvoiceTxArgs, use_test_rng: bool, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let parent_key_id = match args.dest_acct_name { Some(d) => { @@ -617,10 +598,10 @@ where None => w.parent_key_id(), }; - let mut slate = tx::new_tx_slate(&mut *w, args.amount, true, 2, use_test_rng, None)?; + let mut slate = tx::new_tx_slate(w, args.amount, true, 2, use_test_rng, None)?; let height = w.w2n_client().get_chain_tip()?.0; let context = tx::add_output_to_slate( - &mut *w, + w, keychain_mask, &mut slate, height, @@ -648,17 +629,16 @@ where /// Receive an invoice tx, essentially adding inputs to whatever /// output was specified -pub fn process_invoice_tx<'a, T: ?Sized, C, K>( - w: &mut T, +pub fn process_invoice_tx( + w: &mut WalletBackend, keychain_mask: Option<&SecretKey>, slate: &Slate, args: InitTxArgs, use_test_rng: bool, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let mut ret_slate = slate.clone(); check_ttl(w, &ret_slate)?; @@ -674,7 +654,7 @@ where }; // Don't do this multiple times let tx = updater::retrieve_txs( - &mut *w, + w, None, Some(ret_slate.id), None, @@ -704,7 +684,7 @@ where let context_res = w.get_private_context(keychain_mask, slate.id.as_bytes()); let mut context = tx::add_inputs_to_slate( - &mut *w, + w, keychain_mask, &mut ret_slate, height, @@ -750,7 +730,7 @@ where } } - selection::repopulate_tx(&mut *w, keychain_mask, &mut ret_slate, &context, false)?; + selection::repopulate_tx(w, keychain_mask, &mut ret_slate, &context, false)?; // Save the aggsig context in our DB for when we // recieve the transaction back @@ -769,15 +749,14 @@ where } /// Lock sender outputs -pub fn tx_lock_outputs<'a, T: ?Sized, C, K>( - w: &mut T, +pub fn tx_lock_outputs( + w: &mut WalletBackend, keychain_mask: Option<&SecretKey>, slate: &Slate, ) -> Result<(), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let context = w.get_private_context(keychain_mask, slate.id.as_bytes())?; let mut excess_override = None; @@ -786,7 +765,7 @@ where if sl.tx == None { sl.tx = Some(Slate::empty_transaction()); - selection::repopulate_tx(&mut *w, keychain_mask, &mut sl, &context, true)?; + selection::repopulate_tx(w, keychain_mask, &mut sl, &context, true)?; } if slate.participant_data.len() == 1 { @@ -795,26 +774,18 @@ where } let height = w.w2n_client().get_chain_tip()?.0; - selection::lock_tx_context( - &mut *w, - keychain_mask, - &sl, - height, - &context, - excess_override, - ) + selection::lock_tx_context(w, keychain_mask, &sl, height, &context, excess_override) } /// Finalize slate -pub fn finalize_tx<'a, T: ?Sized, C, K>( - w: &mut T, +pub fn finalize_tx( + w: &mut WalletBackend, keychain_mask: Option<&SecretKey>, slate: &Slate, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { foreign_finalize(w, keychain_mask, slate, false) } @@ -844,24 +815,27 @@ where } wallet_lock!(wallet_inst, w); let parent_key_id = w.parent_key_id(); - tx::cancel_tx(&mut **w, keychain_mask, &parent_key_id, tx_id, tx_slate_id) + tx::cancel_tx(w, keychain_mask, &parent_key_id, tx_id, tx_slate_id) } /// get stored tx /// crashes if stored tx has total fees exceeding 2^40 nanogrin -pub fn get_stored_tx<'a, T: ?Sized, C, K>( - w: &T, +pub fn get_stored_tx( + w: &WalletBackend, tx_id: Option, slate_id: Option<&Uuid>, ) -> Result, Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let mut uuid = None; if let Some(i) = tx_id { - let tx = w.tx_log_iter().find(|t| t.id == i); + let tx = w + .tx_log_iter()? + .filter(|tx| tx.is_ok()) + .map(|tx| tx.unwrap()) + .find(|t| t.id == i); if let Some(t) = tx { uuid = t.tx_slate_id; } @@ -896,9 +870,9 @@ where /// Posts a transaction to the chain /// take a client impl instead of wallet so as not to have to lock the wallet -pub fn post_tx<'a, C>(client: &C, tx: &Transaction, fluff: bool) -> Result<(), Error> +pub fn post_tx(client: &C, tx: &Transaction, fluff: bool) -> Result<(), Error> where - C: NodeClient + 'a, + C: NodeClient, { let res = client.post_tx(tx, fluff); if let Err(e) = res { @@ -930,8 +904,7 @@ where let is_hex = rewind_hash.chars().all(|c| c.is_ascii_hexdigit()); let rewind_hash = rewind_hash.to_lowercase(); if !(is_hex && rewind_hash.len() == 64) { - let msg = format!("Invalid Rewind Hash"); - return Err(Error::RewindHash(msg)); + return Err(Error::RewindHash("Invalid Rewind Hash".to_string())); } let tip = { @@ -939,10 +912,7 @@ where w.w2n_client().get_chain_tip()? }; - let start_height = match start_height { - Some(h) => h, - None => 1, - }; + let start_height = start_height.unwrap_or_else(|| 1); let info = scan::scan_rewind_hash( wallet_inst, @@ -979,7 +949,7 @@ where // Scan every 10k heights to save data between batches in case of interruption. let mut total_pmmr_range = None; - for h in (start_height..tip.0).step_by(10001) { + for h in (start_height..tip.0 + 1).step_by(10001) { let batch_end_height = cmp::min(tip.0, h + 10000); let (mut info, range) = scan::scan( wallet_inst.clone(), @@ -1030,10 +1000,12 @@ where }), Err(_) => { let outputs = retrieve_outputs(wallet_inst, keychain_mask, &None, true, false, None)?; - let height = match outputs.1.iter().map(|m| m.output.height).max() { - Some(height) => height, - None => 0, - }; + let height = outputs + .1 + .iter() + .map(|m| m.output.height) + .max() + .unwrap_or_else(|| 0); Ok(NodeHeightResult { height, header_hash: "".to_owned(), @@ -1093,7 +1065,7 @@ where // Step 2: Update outstanding transactions with no change outputs by kernel let mut txs = { wallet_lock!(wallet_inst, w); - updater::retrieve_txs(&mut **w, None, None, None, Some(&parent_key_id), true)? + updater::retrieve_txs(w, None, None, None, Some(&parent_key_id), true)? }; result = update_txs_via_kernel(wallet_inst.clone(), keychain_mask, &mut txs)?; if !result { @@ -1152,7 +1124,7 @@ where // Scan every 10k heights to save data between batches in case of interruption. let mut total_pmmr_range = None; - for h in (start_height..tip.0).step_by(10001) { + for h in (start_height..tip.0 + 1).step_by(10001) { let batch_end_height = cmp::min(tip.0, h + 10000); let (mut info, range) = scan::scan( wallet_inst.clone(), @@ -1186,7 +1158,7 @@ where if tip.0 >= e { wallet_lock!(wallet_inst, w); let parent_key_id = w.parent_key_id(); - tx::cancel_tx(&mut **w, keychain_mask, &parent_key_id, Some(tx.id), None)?; + tx::cancel_tx(w, keychain_mask, &parent_key_id, Some(tx.id), None)?; } } } @@ -1195,11 +1167,10 @@ where } /// Check TTL -pub fn check_ttl<'a, T: ?Sized, C, K>(w: &mut T, slate: &Slate) -> Result<(), Error> +pub fn check_ttl(w: &mut WalletBackend, slate: &Slate) -> Result<(), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { // Refuse if TTL is expired let last_confirmed_height = w.last_confirmed_height()?; @@ -1265,7 +1236,7 @@ where return Err(Error::PaymentProof("Invalid sender signature".to_owned())); }; - // for now, simple test as to whether one of the addresses belongs to this wallet + // for now, simple test whether one of the addresses belongs to this wallet let sec_key = address::address_from_derivation_path(&keychain, &parent_key_id, 0)?; let d_skey = match DalekSecretKey::from_bytes(&sec_key.0) { Ok(k) => k, @@ -1294,7 +1265,7 @@ where { wallet_lock!(wallet_inst, w); let parent_key_id = w.parent_key_id(); - match updater::refresh_outputs(&mut **w, keychain_mask, &parent_key_id, update_all) { + match updater::refresh_outputs(w, keychain_mask, &parent_key_id, update_all) { Ok(_) => Ok(true), Err(e) => { if let Error::InvalidKeychainMask = e { @@ -1361,20 +1332,19 @@ where } /// Builds an output for the wallet's next available key -pub fn build_output<'a, T: ?Sized, C, K>( - w: &mut T, +pub fn build_output( + w: &mut WalletBackend, keychain_mask: Option<&SecretKey>, features: OutputFeatures, amount: u64, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let k = w.keychain(keychain_mask)?; - let key_id = keys::next_available_key(&mut *w, keychain_mask)?; + let key_id = keys::next_available_key(w, keychain_mask)?; let blind = k.derive_key(amount, &key_id, SwitchCommitmentType::Regular)?; let commit = k.secp().commit(amount, blind.clone())?; @@ -1394,14 +1364,14 @@ where Ok(BuiltOutput { blind: BlindingFactor::from_secret_key(blind), - key_id: key_id, - output: output, + key_id, + output, }) } /// Create MXMixnet request -pub fn create_mwixnet_req<'a, T: ?Sized, C, K>( - w: &mut T, +pub fn create_mwixnet_req( + w: &mut WalletBackend, keychain_mask: Option<&SecretKey>, params: &MixnetReqCreationParams, commitment: &Commitment, @@ -1409,9 +1379,8 @@ pub fn create_mwixnet_req<'a, T: ?Sized, C, K>( use_test_rng: bool, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let parent_key_id = w.parent_key_id(); let keychain = w.keychain(keychain_mask)?; diff --git a/libwallet/src/backend.rs b/libwallet/src/backend.rs new file mode 100644 index 0000000..2fa0a08 --- /dev/null +++ b/libwallet/src/backend.rs @@ -0,0 +1,755 @@ +// Copyright 2021 The Grin Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use byteorder::{BigEndian, WriteBytesExt}; +use std::fs; +use std::fs::File; +use std::io::{Read, Write}; +use std::path::Path; +use uuid::Uuid; + +use crate::blake2::blake2b::{Blake2b, Blake2bResult}; + +use crate::{ + AcctPathMapping, Context, Error, NodeClient, OutputData, ScannedBlockInfo, TxLogEntry, + WalletInitStatus, +}; +use grin_core::core::Transaction; +use grin_core::ser; +use grin_keychain::{ChildNumber, ExtKeychain, Identifier, Keychain, SwitchCommitmentType}; +use grin_store::{option_to_not_found, Store}; +use grin_util::secp::constants::SECRET_KEY_SIZE; +use grin_util::secp::SecretKey; +use grin_util::ToHex; +use rand::rngs::mock::StepRng; +use rand::thread_rng; + +pub const DB_DIR: &str = "db"; +pub const TX_SAVE_DIR: &str = "saved_txs"; + +const OUTPUT_PREFIX: u8 = b'o'; +const DERIV_PREFIX: u8 = b'd'; +const CONFIRMED_HEIGHT_PREFIX: u8 = b'c'; +const PRIVATE_TX_CONTEXT_PREFIX: u8 = b'p'; +const TX_LOG_ENTRY_PREFIX: u8 = b't'; +const TX_LOG_ID_PREFIX: u8 = b'i'; +const ACCOUNT_PATH_MAPPING_PREFIX: u8 = b'a'; +const LAST_SCANNED_BLOCK: u8 = b'l'; +const LAST_SCANNED_KEY: &str = "LAST_SCANNED_KEY"; +const WALLET_INIT_STATUS: u8 = b'w'; +const WALLET_INIT_STATUS_KEY: &str = "WALLET_INIT_STATUS"; + +const DB_PREFIXES: [u8; 9] = [ + OUTPUT_PREFIX, + DERIV_PREFIX, + CONFIRMED_HEIGHT_PREFIX, + PRIVATE_TX_CONTEXT_PREFIX, + TX_LOG_ENTRY_PREFIX, + TX_LOG_ID_PREFIX, + ACCOUNT_PATH_MAPPING_PREFIX, + LAST_SCANNED_BLOCK, + WALLET_INIT_STATUS, +]; + +/// Helper to derive XOR keys for storing private transaction keys in the DB +/// (blind_xor_key, nonce_xor_key) +fn private_ctx_xor_keys( + keychain: &K, + slate_id: &[u8], +) -> Result<([u8; SECRET_KEY_SIZE], [u8; SECRET_KEY_SIZE]), Error> +where + K: Keychain, +{ + let root_key = keychain.derive_key(0, &K::root_key_id(), SwitchCommitmentType::Regular)?; + + // derive XOR values for storing secret values in DB + // h(root_key|slate_id|"blind") + let mut hasher = Blake2b::new(SECRET_KEY_SIZE); + hasher.update(&root_key.0[..]); + hasher.update(&slate_id[..]); + hasher.update(&b"blind"[..]); + let blind_xor_key = hasher.finalize(); + let mut ret_blind = [0; SECRET_KEY_SIZE]; + ret_blind.copy_from_slice(&blind_xor_key.as_bytes()[0..SECRET_KEY_SIZE]); + + // h(root_key|slate_id|"nonce") + let mut hasher = Blake2b::new(SECRET_KEY_SIZE); + hasher.update(&root_key.0[..]); + hasher.update(&slate_id[..]); + hasher.update(&b"nonce"[..]); + let nonce_xor_key = hasher.finalize(); + let mut ret_nonce = [0; SECRET_KEY_SIZE]; + ret_nonce.copy_from_slice(&nonce_xor_key.as_bytes()[0..SECRET_KEY_SIZE]); + + Ok((ret_blind, ret_nonce)) +} + +/// Wallet backend. All functions here expect that the wallet instance +/// has instantiated itself or stored whatever credentials it needs. +pub struct WalletBackend +where + C: NodeClient, + K: Keychain, +{ + db: Store, + data_file_dir: String, + /// Keychain + pub keychain: Option, + /// Check value for XORed keychain seed + pub master_checksum: Box>, + /// Parent path to use by default for output operations + parent_key_id: Identifier, + /// wallet to node client + w2n_client: C, +} + +impl WalletBackend +where + C: NodeClient, + K: Keychain, +{ + /// Create new wallet backend. + pub fn new(data_file_dir: &str, n_client: C) -> Result { + let db_path = Path::new(data_file_dir).join(DB_DIR); + fs::create_dir_all(&db_path)?; + + let stored_tx_path = Path::new(data_file_dir).join(TX_SAVE_DIR); + fs::create_dir_all(&stored_tx_path)?; + + let store = Store::new( + db_path.to_str().unwrap(), + None, + Some(DB_DIR), + DB_PREFIXES.to_vec(), + None, + None, + )?; + + // Make sure default wallet derivation path always exists + // as well as path (so it can be retrieved by batches to know where to store + // completed transactions, for reference + let default_account = AcctPathMapping { + label: "default".to_owned(), + path: WalletBackend::::default_path(), + }; + + { + let mut batch = store.batch()?; + batch.put_ser( + Some(ACCOUNT_PATH_MAPPING_PREFIX), + default_account.label.as_bytes(), + &default_account, + )?; + batch.commit()?; + } + + let res = WalletBackend { + db: store, + data_file_dir: data_file_dir.to_owned(), + keychain: None, + master_checksum: Box::new(None), + parent_key_id: WalletBackend::::default_path(), + w2n_client: n_client, + }; + Ok(res) + } + + /// Return the default parent wallet path, corresponding to the default account + /// in the BIP32 spec. Parent is account 0 at level 2, child output identifiers + /// are all at level 3. + pub fn default_path() -> Identifier { + ExtKeychain::derive_key_id(2, 0, 0, 0, 0) + } + + /// Just test to see if database files exist in the current directory. If + /// so, use a DB backend for all operations. + pub fn exists(data_file_dir: &str) -> bool { + let db_path = Path::new(data_file_dir).join(DB_DIR); + db_path.exists() + } + + /// Set the keychain, which should already be initialized + /// Optionally return a token value used to XOR the stored + /// key value + pub fn set_keychain( + &mut self, + mut k: K, + mask: bool, + use_test_rng: bool, + ) -> Result, Error> { + // store hash of master key, so it can be verified later after unmasking + let root_key = k.derive_key(0, &K::root_key_id(), SwitchCommitmentType::Regular)?; + let mut hasher = Blake2b::new(SECRET_KEY_SIZE); + hasher.update(&root_key.0[..]); + self.master_checksum = Box::new(Some(hasher.finalize())); + + let mask_value = { + match mask { + true => { + // Random value that must be XORed against the stored wallet seed + // before it is used + let mask_value = match use_test_rng { + true => { + let mut test_rng = StepRng::new(1_234_567_890_u64, 1); + SecretKey::new(&k.secp(), &mut test_rng) + } + false => SecretKey::new(&k.secp(), &mut thread_rng()), + }; + k.mask_master_key(&mask_value)?; + Some(mask_value) + } + false => None, + } + }; + + self.keychain = Some(k); + Ok(mask_value) + } + + /// Close wallet by removing stored keychain. + pub fn close(&mut self) -> Result<(), Error> { + self.keychain = None; + Ok(()) + } + + /// Return the keychain being used, cloned with XORed token value + /// for temporary use + /// Can optionally take a mask value + pub fn keychain(&self, mask: Option<&SecretKey>) -> Result { + match self.keychain.as_ref() { + Some(k) => { + let mut k_masked = k.clone(); + if let Some(m) = mask { + k_masked.mask_master_key(m)?; + } + // Check if master seed is what is expected (especially if it's been xored) + let root_key = + k_masked.derive_key(0, &K::root_key_id(), SwitchCommitmentType::Regular)?; + let mut hasher = Blake2b::new(SECRET_KEY_SIZE); + hasher.update(&root_key.0[..]); + if *self.master_checksum != Some(hasher.finalize()) { + error!("Supplied keychain mask is invalid"); + return Err(Error::InvalidKeychainMask); + } + Ok(k_masked) + } + None => Err(Error::KeychainDoesntExist), + } + } + + /// Return the client being used to communicate with the node. + pub fn w2n_client(&mut self) -> &mut C { + &mut self.w2n_client + } + + /// Return the version of the commit for caching if allowed. + pub fn calc_commit_for_cache( + &mut self, + keychain_mask: Option<&SecretKey>, + amount: u64, + id: &Identifier, + ) -> Result, Error> { + //TODO: Check if this is really necessary, it's the only thing + //preventing removing the need for config in the wallet backend + /*if self.config.no_commit_cache == Some(true) { + Ok(None) + } else {*/ + Ok(Some( + self.keychain(keychain_mask)? + .commit(amount, &id, SwitchCommitmentType::Regular)? + .0 + .to_vec() + .to_hex(), // TODO: proper support for different switch commitment schemes + )) + /*}*/ + } + + /// Set parent key id by stored account name. + pub fn set_parent_key_id_by_name(&mut self, label: &str) -> Result<(), Error> { + let label = label.to_owned(); + let res = self.acct_path_iter()?.find(|l| l.label == label); + if let Some(a) = res { + self.set_parent_key_id(a.path); + Ok(()) + } else { + Err(Error::UnknownAccountLabel(label)) + } + } + + /// The BIP32 path of the parent path to use for all output-related + /// functions, essentially 'accounts' within a wallet. + pub fn set_parent_key_id(&mut self, id: Identifier) { + self.parent_key_id = id; + } + + /// Get the parent path. + pub fn parent_key_id(&mut self) -> Identifier { + self.parent_key_id.clone() + } + + /// Get output data by id. + pub fn get(&self, id: &Identifier, mmr_index: &Option) -> Result { + let key = match mmr_index { + Some(i) => to_key_u64(id.to_bytes(), *i), + None => id.to_bytes().to_vec(), + }; + option_to_not_found(self.db.get_ser(Some(OUTPUT_PREFIX), &key, None), || { + format!("Key Id: {}", id) + }) + .map_err(|e| e.into()) + } + + /// Iterate over all output data stored by the backend. + pub fn iter(&self) -> Result, Error> { + let protocol_version = self.db.protocol_version(); + let prefix_iter = self.db.iter(Some(OUTPUT_PREFIX), move |_, mut v| { + ser::deserialize( + &mut v, + protocol_version, + ser::DeserializationMode::default(), + ) + .map_err(From::from) + }); + let items: Vec = prefix_iter?.collect::, _>>()?; + Ok(items.into_iter()) + } + + /// Get an (Optional) tx log entry by uuid. + pub fn get_tx_log_entry(&self, u: &Uuid) -> Result, Error> { + self.db + .get_ser(Some(TX_LOG_ENTRY_PREFIX), u.as_bytes(), None) + .map_err(|e| e.into()) + } + + /// Iterate over all tx log data stored by the backend. + pub fn tx_log_iter( + &self, + ) -> Result>, Error> { + let protocol_version = self.db.protocol_version(); + self.db + .iter(Some(TX_LOG_ENTRY_PREFIX), move |_, mut v| { + ser::deserialize( + &mut v, + protocol_version, + ser::DeserializationMode::default(), + ) + .map_err(From::from) + }) + .map_err(From::from) + } + + /// Retrieve the private context associated with a given slate id. + pub fn get_private_context( + &mut self, + keychain_mask: Option<&SecretKey>, + slate_id: &[u8], + ) -> Result { + let ctx_key = to_key_u64(slate_id, 0); + let (blind_xor_key, nonce_xor_key) = + private_ctx_xor_keys(&self.keychain(keychain_mask)?, slate_id)?; + + let mut ctx: Context = option_to_not_found( + self.db + .get_ser(Some(PRIVATE_TX_CONTEXT_PREFIX), &ctx_key, None), + || format!("Slate id: {:x?}", slate_id.to_vec()), + )?; + + for i in 0..SECRET_KEY_SIZE { + ctx.sec_key.0[i] ^= blind_xor_key[i]; + ctx.sec_nonce.0[i] ^= nonce_xor_key[i]; + } + + Ok(ctx) + } + + /// Iterate over all stored account paths. + pub fn acct_path_iter(&self) -> Result, Error> { + let protocol_version = self.db.protocol_version(); + let prefix_iter = self + .db + .iter(Some(ACCOUNT_PATH_MAPPING_PREFIX), move |_, mut v| { + ser::deserialize( + &mut v, + protocol_version, + ser::DeserializationMode::default(), + ) + .map_err(From::from) + }); + let items: Vec = prefix_iter?.collect::, _>>()?; + Ok(items.into_iter()) + } + + /// Gets an account path for a given label. + pub fn get_acct_path(&self, label: String) -> Result, Error> { + self.db + .get_ser(Some(ACCOUNT_PATH_MAPPING_PREFIX), label.as_bytes(), None) + .map_err(|e| e.into()) + } + + /// Stores a transaction. + pub fn store_tx(&self, uuid: &str, tx: &Transaction) -> Result<(), Error> { + let filename = format!("{}.grintx", uuid); + let path = Path::new(&self.data_file_dir) + .join(TX_SAVE_DIR) + .join(filename); + let path_buf = Path::new(&path).to_path_buf(); + let mut stored_tx = File::create(path_buf)?; + let tx_hex = ser::ser_vec(tx, ser::ProtocolVersion(1)).unwrap().to_hex(); + stored_tx.write_all(&tx_hex.as_bytes())?; + stored_tx.sync_all()?; + Ok(()) + } + + /// Retrieves a stored transaction. + //TODO: Store content of .grintx file at TxLogEntry? + pub fn get_stored_tx(&self, uuid: &str) -> Result, Error> { + let filename = format!("{}.grintx", uuid); + let path = Path::new(&self.data_file_dir) + .join(TX_SAVE_DIR) + .join(filename); + let tx_file = Path::new(&path).to_path_buf(); + let mut tx_f = File::open(tx_file)?; + let mut content = String::new(); + tx_f.read_to_string(&mut content)?; + let tx_bin = grin_util::from_hex(&content).unwrap(); + Ok(Some( + ser::deserialize( + &mut &tx_bin[..], + ser::ProtocolVersion(1), + ser::DeserializationMode::default(), + ) + .unwrap(), + )) + } + + /// Create a new write batch to update or remove output data. + pub fn batch( + &mut self, + keychain_mask: Option<&SecretKey>, + ) -> Result, Error> { + Ok(WalletBatch { + db: self.db.batch()?, + keychain: Some(self.keychain(keychain_mask)?), + }) + } + + /// Batch for use when keychain isn't available or required. + pub fn batch_no_mask(&mut self) -> Result, Error> { + Ok(WalletBatch { + db: self.db.batch()?, + keychain: None, + }) + } + + /// Return the current child index. + pub fn current_child_index(&mut self, parent_key_id: &Identifier) -> Result { + let index = { + let batch = self.db.batch()?; + batch + .get_ser(Some(DERIV_PREFIX), &parent_key_id.to_bytes(), None)? + .unwrap_or_else(|| 0) + }; + Ok(index) + } + + /// Next child ID when we want to create a new output, based on current parent. + pub fn next_child(&mut self, keychain_mask: Option<&SecretKey>) -> Result { + let parent_key_id = self.parent_key_id.clone(); + let mut deriv_idx = { + let batch = self.db.batch()?; + batch + .get_ser(Some(DERIV_PREFIX), &self.parent_key_id.to_bytes(), None)? + .unwrap_or_else(|| 0) + }; + let mut return_path = self.parent_key_id.to_path(); + return_path.depth += 1; + return_path.path[return_path.depth as usize - 1] = ChildNumber::from(deriv_idx); + deriv_idx += 1; + let mut batch = self.batch(keychain_mask)?; + batch.save_child_index(&parent_key_id, deriv_idx)?; + batch.commit()?; + Ok(Identifier::from_path(&return_path)) + } + + /// Last verified height of outputs directly descending from the given parent key. + pub fn last_confirmed_height(&mut self) -> Result { + let batch = self.db.batch()?; + let last_confirmed_height = batch + .get_ser( + Some(CONFIRMED_HEIGHT_PREFIX), + &self.parent_key_id.to_bytes(), + None, + )? + .unwrap_or_else(|| 0); + Ok(last_confirmed_height) + } + + /// Last block scanned during scan or restore. + pub fn last_scanned_block(&mut self) -> Result { + let batch = self.db.batch()?; + let last_scanned_block = batch + .get_ser(Some(LAST_SCANNED_BLOCK), LAST_SCANNED_KEY.as_bytes(), None)? + .unwrap_or_else(|| ScannedBlockInfo { + height: 0, + hash: "".to_owned(), + start_pmmr_index: 0, + last_pmmr_index: 0, + }); + Ok(last_scanned_block) + } + + /// Flag whether the wallet needs a full UTXO scan on next update attempt. + pub fn init_status(&mut self) -> Result { + let batch = self.db.batch()?; + let status = batch + .get_ser( + Some(WALLET_INIT_STATUS), + WALLET_INIT_STATUS_KEY.as_bytes(), + None, + )? + .unwrap_or_else(|| WalletInitStatus::InitComplete); + Ok(status) + } +} + +/// An atomic batch in which all changes can be committed all at once or +/// discarded on error. +pub struct WalletBatch<'a, K> +where + K: Keychain, +{ + db: grin_store::Batch<'a>, + /// Keychain + keychain: Option, +} + +#[allow(missing_docs)] +impl<'a, K> WalletBatch<'a, K> +where + K: Keychain, +{ + /// Return the keychain being used. + pub fn keychain(&mut self) -> &mut K { + self.keychain.as_mut().unwrap() + } + + /// Add or update data about an output to the backend. + pub fn save(&mut self, out: OutputData) -> Result<(), Error> { + let key = match out.mmr_index { + Some(i) => to_key_u64(out.key_id.to_bytes(), i), + None => out.key_id.to_bytes().to_vec(), + }; + self.db.put_ser(Some(OUTPUT_PREFIX), &key, &out)?; + Ok(()) + } + + /// Gets output data by id + pub fn get(&self, id: &Identifier, mmr_index: &Option) -> Result { + let key = match mmr_index { + Some(i) => to_key_u64(id.to_bytes(), *i), + None => id.to_bytes().to_vec(), + }; + option_to_not_found(self.db.get_ser(Some(OUTPUT_PREFIX), &key, None), || { + format!("Key ID: {}", id) + }) + .map_err(|e| e.into()) + } + + /// Iterate over all output data stored by the backend. + pub fn iter(&'a self) -> Result + 'a, Error> { + let protocol_version = self.db.protocol_version(); + let prefix_iter = self.db.iter(Some(OUTPUT_PREFIX), move |_, mut v| { + ser::deserialize( + &mut v, + protocol_version, + ser::DeserializationMode::default(), + ) + .map_err(From::from) + }); + let items: Vec = prefix_iter?.collect::, _>>()?; + Ok(items.into_iter()) + } + + /// Delete data about an output from the backend. + pub fn delete(&mut self, id: &Identifier, mmr_index: &Option) -> Result<(), Error> { + // Delete the output data. + let key = match mmr_index { + Some(i) => to_key_u64(id.to_bytes(), *i), + None => id.to_bytes().to_vec(), + }; + self.db.delete(Some(OUTPUT_PREFIX), &key)?; + Ok(()) + } + + /// Save last stored child index of a given parent. + pub fn save_child_index(&mut self, parent_id: &Identifier, child_n: u32) -> Result<(), Error> { + self.db + .put_ser(Some(DERIV_PREFIX), &parent_id.to_bytes(), &child_n)?; + Ok(()) + } + + /// Save last confirmed height of outputs for a given parent. + pub fn save_last_confirmed_height( + &mut self, + parent_key_id: &Identifier, + height: u64, + ) -> Result<(), Error> { + self.db.put_ser( + Some(CONFIRMED_HEIGHT_PREFIX), + &parent_key_id.to_bytes(), + &height, + )?; + Ok(()) + } + + /// Save the last PMMR index that was scanned via a scan operation. + pub fn save_last_scanned_block(&mut self, block_info: ScannedBlockInfo) -> Result<(), Error> { + self.db.put_ser( + Some(LAST_SCANNED_BLOCK), + LAST_SCANNED_KEY.as_bytes(), + &block_info, + )?; + Ok(()) + } + + /// Save flag indicating whether wallet needs a full UTXO scan. + pub fn save_init_status(&mut self, value: WalletInitStatus) -> Result<(), Error> { + self.db.put_ser( + Some(WALLET_INIT_STATUS), + WALLET_INIT_STATUS_KEY.as_bytes(), + &value, + )?; + Ok(()) + } + + /// Get next transaction log entry for the parent. + pub fn next_tx_log_id(&mut self, parent_key_id: &Identifier) -> Result { + let last_tx_log_id = self + .db + .get_ser(Some(TX_LOG_ID_PREFIX), &parent_key_id.to_bytes(), None)? + .unwrap_or_else(|| 0); + self.db.put_ser( + Some(TX_LOG_ID_PREFIX), + &parent_key_id.to_bytes(), + &(last_tx_log_id + 1), + )?; + Ok(last_tx_log_id) + } + + /// Iterate over transactions data stored by the backend. + pub fn tx_log_iter( + &'a self, + ) -> Result> + 'a, Error> { + let protocol_version = self.db.protocol_version(); + self.db + .iter(Some(TX_LOG_ENTRY_PREFIX), move |_, mut v| { + ser::deserialize( + &mut v, + protocol_version, + ser::DeserializationMode::default(), + ) + .map_err(From::from) + }) + .map_err(From::from) + } + + /// Save a transaction log entry. + pub fn save_tx_log_entry( + &mut self, + tx_in: TxLogEntry, + parent_id: &Identifier, + ) -> Result<(), Error> { + let tx_log_key = to_key_u64(parent_id.to_bytes(), tx_in.id as u64); + self.db + .put_ser(Some(TX_LOG_ENTRY_PREFIX), &tx_log_key, &tx_in)?; + Ok(()) + } + + /// Delete a transaction log entry. + pub fn delete_tx_log_entry(&mut self, tx_id: u32, parent_id: &Identifier) -> Result<(), Error> { + let tx_log_key = to_key_u64(parent_id.to_bytes(), tx_id as u64); + self.db.delete(Some(TX_LOG_ENTRY_PREFIX), &tx_log_key)?; + Ok(()) + } + + /// Save an account label -> path mapping. + pub fn save_acct_path(&mut self, mapping: AcctPathMapping) -> Result<(), Error> { + self.db.put_ser( + Some(ACCOUNT_PATH_MAPPING_PREFIX), + mapping.label.as_bytes(), + &mapping, + )?; + Ok(()) + } + + /// Iterate over account names stored in backend. + pub fn acct_path_iter(&'a self) -> Result + 'a, Error> { + let protocol_version = self.db.protocol_version(); + let prefix_iter = self + .db + .iter(Some(ACCOUNT_PATH_MAPPING_PREFIX), move |_, mut v| { + ser::deserialize( + &mut v, + protocol_version, + ser::DeserializationMode::default(), + ) + .map_err(From::from) + }); + let items: Vec = prefix_iter?.collect::, _>>()?; + Ok(items.into_iter()) + } + + /// Save an output as locked in the backend. + pub fn lock_output(&mut self, out: &mut OutputData) -> Result<(), Error> { + out.lock(); + self.save(out.clone()) + } + + /// Save the private context associated with a slate id. + pub fn save_private_context(&mut self, slate_id: &[u8], ctx: &Context) -> Result<(), Error> { + let ctx_key = to_key_u64(slate_id, 0); + let (blind_xor_key, nonce_xor_key) = private_ctx_xor_keys(self.keychain(), slate_id)?; + + let mut s_ctx = ctx.clone(); + for i in 0..SECRET_KEY_SIZE { + s_ctx.sec_key.0[i] ^= blind_xor_key[i]; + s_ctx.sec_nonce.0[i] ^= nonce_xor_key[i]; + } + + self.db + .put_ser(Some(PRIVATE_TX_CONTEXT_PREFIX), &ctx_key, &s_ctx)?; + Ok(()) + } + + /// Delete the private context associated with the slate id. + pub fn delete_private_context(&mut self, slate_id: &[u8]) -> Result<(), Error> { + let ctx_key = to_key_u64(slate_id, 0); + self.db + .delete(Some(PRIVATE_TX_CONTEXT_PREFIX), &ctx_key) + .map_err(|e| e.into()) + } + + /// Write the wallet data to backend file. + pub fn commit(self) -> Result<(), Error> { + self.db.commit()?; + Ok(()) + } +} + +/// Build a db key from a byte vector identifier and numeric identifier +fn to_key_u64>(k: K, val: u64) -> Vec { + let mut res = k.as_ref().to_vec(); + res.write_u64::(val).unwrap(); + res +} diff --git a/libwallet/src/internal/keys.rs b/libwallet/src/internal/keys.rs index 9d8f4cb..21c937a 100644 --- a/libwallet/src/internal/keys.rs +++ b/libwallet/src/internal/keys.rs @@ -16,32 +16,31 @@ use crate::error::Error; use crate::grin_keychain::{ChildNumber, ExtKeychain, Identifier, Keychain}; use crate::grin_util::secp::key::SecretKey; -use crate::types::{AcctPathMapping, NodeClient, WalletBackend}; +use crate::types::{AcctPathMapping, NodeClient}; +use crate::WalletBackend; /// Get next available key in the wallet for a given parent -pub fn next_available_key<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn next_available_key( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let child = wallet.next_child(keychain_mask)?; Ok(child) } /// Retrieve an existing key from a wallet -pub fn retrieve_existing_key<'a, T: ?Sized, C, K>( - wallet: &T, +pub fn retrieve_existing_key( + wallet: &WalletBackend, key_id: Identifier, mmr_index: Option, ) -> Result<(Identifier, u32), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let existing = wallet.get(&key_id, &mmr_index)?; let key_id = existing.key_id.clone(); @@ -50,28 +49,26 @@ where } /// Returns a list of account to BIP32 path mappings -pub fn accounts<'a, T: ?Sized, C, K>(wallet: &mut T) -> Result, Error> +pub fn accounts(wallet: &WalletBackend) -> Result, Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { - Ok(wallet.acct_path_iter().collect()) + Ok(wallet.acct_path_iter()?.collect()) } -/// Adds an new parent account path with a given label -pub fn new_acct_path<'a, T: ?Sized, C, K>( - wallet: &mut T, +/// Adds a new parent account path with a given label +pub fn new_acct_path( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, label: &str, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let label = label.to_owned(); - if wallet.acct_path_iter().any(|l| l.label == label) { + if wallet.acct_path_iter()?.any(|l| l.label == label) { return Err(Error::AccountLabelAlreadyExists(label)); } @@ -79,7 +76,7 @@ where // so find the highest of those, then increment (to conform with external/internal // derivation chains in BIP32 spec) - let highest_entry = wallet.acct_path_iter().max_by(|a, b| { + let highest_entry = wallet.acct_path_iter()?.max_by(|a, b| { ::from(a.path.to_path().path[0]).cmp(&::from(b.path.to_path().path[0])) }); @@ -94,7 +91,7 @@ where }; let save_path = AcctPathMapping { - label: label, + label, path: return_id.clone(), }; @@ -105,20 +102,19 @@ where } /// Adds/sets a particular account path with a given label -pub fn set_acct_path<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn set_acct_path( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, label: &str, path: &Identifier, ) -> Result<(), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let label = label.to_owned(); let save_path = AcctPathMapping { - label: label, + label, path: path.clone(), }; diff --git a/libwallet/src/internal/scan.rs b/libwallet/src/internal/scan.rs index 955674f..85f0e9a 100644 --- a/libwallet/src/internal/scan.rs +++ b/libwallet/src/internal/scan.rs @@ -66,14 +66,14 @@ struct RestoredTxStats { pub num_outputs: usize, } -fn identify_utxo_outputs<'a, K>( +fn identify_utxo_outputs( keychain: &K, outputs: Vec<(pedersen::Commitment, pedersen::RangeProof, bool, u64, u64)>, status_send_channel: &Option>, percentage_complete: u8, ) -> Result, Error> where - K: Keychain + 'a, + K: Keychain, { let mut wallet_outputs: Vec = Vec::new(); @@ -137,7 +137,7 @@ where n_child: key_id.to_path().last_path_index(), value: amount, height: *height, - lock_height: lock_height, + lock_height, is_coinbase: *is_coinbase, mmr_index: *mmr_index, }); @@ -145,7 +145,7 @@ where Ok(wallet_outputs) } -fn collect_chain_outputs_rewind_hash<'a, C>( +fn collect_chain_outputs_rewind_hash( client: C, rewind_hash: String, start_index: u64, @@ -153,13 +153,13 @@ fn collect_chain_outputs_rewind_hash<'a, C>( status_send_channel: &Option>, ) -> Result where - C: NodeClient + 'a, + C: NodeClient, { let batch_size = 1000; let start_index_stat = start_index; let mut start_index = start_index; let mut vw = ViewWallet { - rewind_hash: rewind_hash, + rewind_hash, output_result: vec![], total_balance: 0, last_pmmr_index: 0, @@ -198,7 +198,7 @@ where continue; } - let info = info.unwrap(); + let info = info?; vw.total_balance += info.value; let lock_height = if *is_coinbase { *height + global::coinbase_maturity() @@ -212,7 +212,7 @@ where height: *height, mmr_index: *mmr_index, is_coinbase: *is_coinbase, - lock_height: lock_height, + lock_height, }; vw.output_result.push(output_info); @@ -285,7 +285,6 @@ where Ok((result_vec, last_retrieved_return_index, perc_complete)) } -/// fn restore_missing_output<'a, L, C, K>( wallet_inst: Arc>>>, keychain_mask: Option<&SecretKey>, @@ -384,7 +383,7 @@ where wallet_lock!(wallet_inst, w); let updated_tx_entry = if output.tx_log_entry.is_some() { let entries = updater::retrieve_txs( - &mut **w, + w, output.tx_log_entry, None, None, @@ -536,7 +535,7 @@ where // Now, get all outputs owned by this wallet (regardless of account) let wallet_outputs = { wallet_lock!(wallet_inst, w); - updater::retrieve_outputs(&mut **w, keychain_mask, true, None, None)? + updater::retrieve_outputs(w, keychain_mask, true, None, None)? }; let mut missing_outs = vec![]; @@ -646,7 +645,7 @@ where // restore labels, account paths and child derivation indices wallet_lock!(wallet_inst, w); let label_base = "account"; - let accounts: Vec = w.acct_path_iter().map(|m| m.path).collect(); + let accounts: Vec = w.acct_path_iter()?.map(|m| m.path).collect(); let mut acct_index = accounts.len(); for (path, max_child_index) in found_parents.iter() { // Only restore paths that don't exist @@ -656,7 +655,7 @@ where if let Some(ref s) = status_send_channel { let _ = s.send(StatusMessage::Scanning(msg, perc_complete)); } - keys::set_acct_path(&mut **w, keychain_mask, &label, path)?; + keys::set_acct_path(w, keychain_mask, &label, path)?; acct_index += 1; } let current_child_index = w.current_child_index(&path)?; diff --git a/libwallet/src/internal/selection.rs b/libwallet/src/internal/selection.rs index 5bc4500..a145662 100644 --- a/libwallet/src/internal/selection.rs +++ b/libwallet/src/internal/selection.rs @@ -14,7 +14,6 @@ //! Selection of inputs for building transactions -use crate::address; use crate::error::Error; use crate::grin_core::core::amount_to_hr_string; use crate::grin_core::libtx::{ @@ -29,6 +28,7 @@ use crate::internal::keys; use crate::slate::Slate; use crate::types::*; use crate::util::OnionV3Address; +use crate::{address, WalletBackend}; use std::collections::HashMap; use std::convert::TryInto; @@ -37,8 +37,8 @@ use std::convert::TryInto; /// and saves the private wallet identifiers of our selected outputs /// into our transaction context -pub fn build_send_tx<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn build_send_tx( + wallet: &mut WalletBackend, keychain: &K, keychain_mask: Option<&SecretKey>, slate: &mut Slate, @@ -54,9 +54,8 @@ pub fn build_send_tx<'a, T: ?Sized, C, K>( amount_includes_fee: bool, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let (elems, inputs, change_amounts_derivations, fee) = select_send_tx( wallet, @@ -73,7 +72,7 @@ where )?; if amount_includes_fee { slate.amount = slate.amount.checked_sub(fee).ok_or(Error::GenericError( - format!("Transaction amount is too small to include fee").into(), + "Transaction amount is too small to include fee".to_string(), ))?; }; @@ -119,8 +118,8 @@ where /// Locks all corresponding outputs in the context, creates /// change outputs and tx log entry -pub fn lock_tx_context<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn lock_tx_context( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, slate: &Slate, current_height: u64, @@ -128,9 +127,8 @@ pub fn lock_tx_context<'a, T: ?Sized, C, K>( excess_override: Option, ) -> Result<(), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let mut output_commits: HashMap, u64)> = HashMap::new(); // Store cached commits before locking wallet @@ -159,6 +157,7 @@ where let log_id = batch.next_tx_log_id(&parent_key_id)?; let mut t = TxLogEntry::new(parent_key_id.clone(), TxLogEntryType::TxSent, log_id); t.tx_slate_id = Some(slate_id); + t.tx_slate_state = Some(slate.state.clone()); let filename = format!("{}.grintx", slate_id); t.stored_tx = Some(filename); t.fee = context.fee; @@ -178,7 +177,7 @@ where let mut amount_debited = 0; t.num_inputs = lock_inputs.len(); for id in lock_inputs { - let mut coin = batch.get(&id.0, &id.1).unwrap(); + let mut coin = batch.get(&id.0, &id.1)?; coin.tx_log_entry = Some(log_id); amount_debited += coin.value; batch.lock_output(&mut coin)?; @@ -221,11 +220,11 @@ where root_key_id: parent_key_id.clone(), key_id: id.clone(), n_child: id.to_path().last_path_index(), - commit: commit, + commit, mmr_index: None, value: change_amount, status: OutputStatus::Unconfirmed, - height: height, + height, lock_height: 0, is_coinbase: false, tx_log_entry: Some(log_id), @@ -245,8 +244,8 @@ where /// Creates a new output in the wallet for the recipient, /// returning the key of the fresh output /// Also creates a new transaction containing the output -pub fn build_recipient_output<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn build_recipient_output( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, slate: &mut Slate, current_height: u64, @@ -255,9 +254,8 @@ pub fn build_recipient_output<'a, T: ?Sized, C, K>( is_initiator: bool, ) -> Result<(Identifier, Context, TxLogEntry), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { // Create a potential output for this transaction let key_id = keys::next_available_key(wallet, keychain_mask).unwrap(); @@ -284,6 +282,7 @@ where let log_id = batch.next_tx_log_id(&parent_key_id)?; let mut t = TxLogEntry::new(parent_key_id.clone(), TxLogEntryType::TxReceived, log_id); t.tx_slate_id = Some(slate_id); + t.tx_slate_state = Some(slate.state.clone()); t.amount_credited = amount; t.num_outputs = 1; t.ttl_cutoff_height = match slate.ttl_cutoff_height { @@ -300,10 +299,10 @@ where key_id: key_id_inner.clone(), mmr_index: None, n_child: key_id_inner.to_path().last_path_index(), - commit: commit, + commit, value: amount, status: OutputStatus::Unconfirmed, - height: height, + height, lock_height: 0, is_coinbase: false, tx_log_entry: Some(log_id), @@ -317,8 +316,8 @@ where /// Builds a transaction to send to someone from the HD seed associated with the /// wallet and the amount to send. Handles reading through the wallet data file, /// selecting outputs to spend and building the change. -pub fn select_send_tx<'a, T: ?Sized, C, K, B>( - wallet: &mut T, +pub fn select_send_tx( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, amount: u64, amount_includes_fee: bool, @@ -339,9 +338,8 @@ pub fn select_send_tx<'a, T: ?Sized, C, K, B>( Error, > where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, B: ProofBuild, { let (coins, _total, amount, fee) = select_coins_and_fee( @@ -371,8 +369,8 @@ where } /// Select outputs and calculating fee. -pub fn select_coins_and_fee<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn select_coins_and_fee( + wallet: &mut WalletBackend, amount: u64, amount_includes_fee: bool, current_height: u64, @@ -391,9 +389,8 @@ pub fn select_coins_and_fee<'a, T: ?Sized, C, K>( Error, > where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { // select some spendable coins from the wallet let (max_outputs, mut coins) = select_coins( @@ -404,10 +401,10 @@ where max_outputs, selection_strategy_is_use_all, parent_key_id, - ); + )?; // sender is responsible for setting the fee on the partial tx - // recipient should double check the fee calculation and not blindly trust the + // recipient should double-check the fee calculation and not blindly trust the // sender // First attempt to spend without change @@ -422,8 +419,8 @@ where return Err(Error::NotEnoughFunds { available: 0, available_disp: amount_to_hr_string(0, false), - needed: amount_with_fee as u64, - needed_disp: amount_to_hr_string(amount_with_fee as u64, false), + needed: amount_with_fee, + needed_disp: amount_to_hr_string(amount_with_fee, false), }); } @@ -432,8 +429,8 @@ where return Err(Error::NotEnoughFunds { available: total, available_disp: amount_to_hr_string(total, false), - needed: amount_with_fee as u64, - needed_disp: amount_to_hr_string(amount_with_fee as u64, false), + needed: amount_with_fee, + needed_disp: amount_to_hr_string(amount_with_fee, false), }); } @@ -453,10 +450,10 @@ where // End the loop if we have selected all the outputs and still not enough funds if coins.len() == max_outputs { return Err(Error::NotEnoughFunds { - available: total as u64, + available: total, available_disp: amount_to_hr_string(total, false), - needed: amount_with_fee as u64, - needed_disp: amount_to_hr_string(amount_with_fee as u64, false), + needed: amount_with_fee, + needed_disp: amount_to_hr_string(amount_with_fee, false), }); } @@ -469,7 +466,7 @@ where max_outputs, selection_strategy_is_use_all, parent_key_id, - ) + )? .1; fee = tx_fee(coins.len(), num_outputs, 1); total = coins.iter().map(|c| c.value).sum(); @@ -483,7 +480,7 @@ where // be reduced, to accommodate the fee. let new_amount = match amount_includes_fee { true => amount.checked_sub(fee).ok_or(Error::GenericError( - format!("Transaction amount is too small to include fee").into(), + "Transaction amount is too small to include fee".to_string(), ))?, false => amount, }; @@ -491,9 +488,9 @@ where } /// Selects inputs and change for a transaction -pub fn inputs_and_change<'a, T: ?Sized, C, K, B>( +pub fn inputs_and_change( coins: &[OutputData], - wallet: &mut T, + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, amount: u64, fee: u64, @@ -507,9 +504,8 @@ pub fn inputs_and_change<'a, T: ?Sized, C, K, B>( Error, > where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, B: ProofBuild, { let mut parts = vec![]; @@ -554,7 +550,7 @@ where part_change }; - let change_key = wallet.next_child(keychain_mask).unwrap(); + let change_key = wallet.next_child(keychain_mask)?; change_amounts_derivations.push((change_amount, change_key.clone(), None)); parts.push(build::output(change_amount, change_key)); @@ -569,26 +565,23 @@ where /// max_outputs). Alternative strategy is to spend smallest outputs first /// but only as many as necessary. When we introduce additional strategies /// we should pass something other than a bool in. -/// TODO: Possibly move this into another trait to be owned by a wallet? - -pub fn select_coins<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn select_coins( + wallet: &WalletBackend, amount: u64, current_height: u64, minimum_confirmations: u64, max_outputs: usize, select_all: bool, parent_key_id: &Identifier, -) -> (usize, Vec) +) -> Result<(usize, Vec), Error> // max_outputs_available, Outputs where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { // first find all eligible outputs based on number of confirmations let mut eligible = wallet - .iter() + .iter()? .filter(|out| { out.root_key_id == *parent_key_id && out.eligible_to_spend(current_height, minimum_confirmations) @@ -612,7 +605,7 @@ where for window in eligible.windows(max_outputs) { let windowed_eligibles = window.to_vec(); if let Some(outputs) = select_from(amount, select_all, windowed_eligibles) { - return (max_available, outputs); + return Ok((max_available, outputs)); } } // Not exist in any window of which total amount >= amount. @@ -623,20 +616,20 @@ where "Extending maximum number of outputs. {} outputs selected.", outputs.len() ); - return (max_available, outputs); + return Ok((max_available, outputs)); } } else if let Some(outputs) = select_from(amount, select_all, eligible.clone()) { - return (max_available, outputs); + return Ok((max_available, outputs)); } // we failed to find a suitable set of outputs to spend, // so return the largest amount we can so we can provide guidance on what is // possible eligible.reverse(); - ( + Ok(( max_available, eligible.iter().take(max_outputs).cloned().collect(), - ) + )) } fn select_from(amount: u64, select_all: bool, outputs: Vec) -> Option> { @@ -663,21 +656,20 @@ fn select_from(amount: u64, select_all: bool, outputs: Vec) -> Optio } } -/// Repopulates output in the slate's tranacstion +/// Repopulates output in the slate's transaction /// with outputs from the stored context /// change outputs and tx log entry /// Remove the explicitly stored excess -pub fn repopulate_tx<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn repopulate_tx( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, slate: &mut Slate, context: &Context, update_fee: bool, ) -> Result<(), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { // restore the original amount, fee slate.amount = context.amount; @@ -694,7 +686,7 @@ where let mut parts = vec![]; for (id, _, value) in &context.get_inputs() { - let input = wallet.iter().find(|out| out.key_id == *id); + let input = wallet.iter()?.find(|out| out.key_id == *id); if let Some(i) = input { if i.is_coinbase { parts.push(build::coinbase_input(*value, i.key_id.clone())); @@ -704,7 +696,7 @@ where } } for (id, _, value) in &context.get_outputs() { - let output = wallet.iter().find(|out| out.key_id == *id); + let output = wallet.iter()?.find(|out| out.key_id == *id); if let Some(i) = output { parts.push(build::output(*value, i.key_id.clone())); } diff --git a/libwallet/src/internal/tx.rs b/libwallet/src/internal/tx.rs index a5dde1a..57e2fec 100644 --- a/libwallet/src/internal/tx.rs +++ b/libwallet/src/internal/tx.rs @@ -26,10 +26,10 @@ use crate::grin_util::secp::pedersen; use crate::grin_util::Mutex; use crate::internal::{selection, updater}; use crate::slate::Slate; -use crate::types::{Context, NodeClient, StoredProofInfo, TxLogEntryType, WalletBackend}; +use crate::types::{Context, NodeClient, StoredProofInfo, TxLogEntryType}; use crate::util::OnionV3Address; -use crate::InitTxArgs; use crate::{address, Error}; +use crate::{InitTxArgs, WalletBackend}; use ed25519_dalek::Keypair as DalekKeypair; use ed25519_dalek::PublicKey as DalekPublicKey; use ed25519_dalek::SecretKey as DalekSecretKey; @@ -44,8 +44,8 @@ lazy_static! { /// Creates a new slate for a transaction, can be called by anyone involved in /// the transaction (sender(s), receiver(s)) -pub fn new_tx_slate<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn new_tx_slate( + wallet: &mut WalletBackend, amount: u64, is_invoice: bool, num_participants: u8, @@ -53,9 +53,8 @@ pub fn new_tx_slate<'a, T: ?Sized, C, K>( ttl_blocks: Option, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let current_height = wallet.w2n_client().get_chain_tip()?.0; let mut slate = Slate::blank(num_participants, is_invoice); @@ -92,8 +91,8 @@ where } /// Estimates locked amount and fee for the transaction without creating one -pub fn estimate_send_tx<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn estimate_send_tx( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, amount: u64, amount_includes_fee: bool, @@ -110,9 +109,8 @@ pub fn estimate_send_tx<'a, T: ?Sized, C, K>( Error, > where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { // Get lock height let current_height = wallet.w2n_client().get_chain_tip()?.0; @@ -141,8 +139,8 @@ where } /// Add inputs to the slate (effectively becoming the sender) -pub fn add_inputs_to_slate<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn add_inputs_to_slate( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, slate: &mut Slate, current_height: u64, @@ -156,9 +154,8 @@ pub fn add_inputs_to_slate<'a, T: ?Sized, C, K>( amount_includes_fee: bool, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { // sender should always refresh outputs updater::refresh_outputs(wallet, keychain_mask, parent_key_id, false)?; @@ -207,8 +204,8 @@ where } /// Add receiver output to the slate -pub fn add_output_to_slate<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn add_output_to_slate( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, slate: &mut Slate, current_height: u64, @@ -217,9 +214,8 @@ pub fn add_output_to_slate<'a, T: ?Sized, C, K>( use_test_rng: bool, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let keychain = wallet.keychain(keychain_mask)?; // create an output using the amount in the slate @@ -252,8 +248,8 @@ where } /// Create context, without adding inputs to slate -pub fn create_late_lock_context<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn create_late_lock_context( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, slate: &mut Slate, current_height: u64, @@ -262,9 +258,8 @@ pub fn create_late_lock_context<'a, T: ?Sized, C, K>( use_test_rng: bool, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { // sender should always refresh outputs updater::refresh_outputs(wallet, keychain_mask, parent_key_id, false)?; @@ -300,16 +295,15 @@ where } /// Complete a transaction -pub fn complete_tx<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn complete_tx( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, slate: &mut Slate, context: &Context, ) -> Result<(), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { // when self sending invoice tx, use initiator nonce to finalize let (sec_key, sec_nonce) = { @@ -333,17 +327,16 @@ where } /// Rollback outputs associated with a transaction in the wallet -pub fn cancel_tx<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn cancel_tx( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, parent_key_id: &Identifier, tx_id: Option, tx_slate_id: Option, ) -> Result<(), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let mut tx_id_string = String::new(); if let Some(tx_id) = tx_id { @@ -384,17 +377,16 @@ where } /// Update the stored transaction (this update needs to happen when the TX is finalised) -pub fn update_stored_tx<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn update_stored_tx( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, context: &Context, slate: &Slate, is_invoiced: bool, ) -> Result<(), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { // finalize command let tx_vec = updater::retrieve_txs(wallet, None, Some(slate.id), None, None, false)?; @@ -421,10 +413,7 @@ where } if let Some(ref p) = slate.clone().payment_proof { - let derivation_index = match context.payment_proof_derivation_index { - Some(i) => i, - None => 0, - }; + let derivation_index = context.payment_proof_derivation_index.unwrap_or_else(|| 0); let keychain = wallet.keychain(keychain_mask)?; let parent_key_id = wallet.parent_key_id(); let excess = slate.calc_excess(keychain.secp())?; @@ -506,17 +495,16 @@ pub fn create_payment_proof_signature( } /// Verify all aspects of a completed payment proof on the current slate -pub fn verify_slate_payment_proof<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn verify_slate_payment_proof( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, parent_key_id: &Identifier, context: &Context, slate: &Slate, ) -> Result<(), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let tx_vec = updater::retrieve_txs( wallet, diff --git a/libwallet/src/internal/updater.rs b/libwallet/src/internal/updater.rs index 09c8943..3383d9e 100644 --- a/libwallet/src/internal/updater.rs +++ b/libwallet/src/internal/updater.rs @@ -30,32 +30,29 @@ use crate::grin_util::secp::key::SecretKey; use crate::grin_util::secp::pedersen; use crate::grin_util::static_secp_instance; use crate::internal::keys; -use crate::types::{ - NodeClient, OutputData, OutputStatus, TxLogEntry, TxLogEntryType, WalletBackend, WalletInfo, -}; +use crate::types::{NodeClient, OutputData, OutputStatus, TxLogEntry, TxLogEntryType, WalletInfo}; use crate::{ BlockFees, CbData, OutputCommitMapping, RetrieveTxQueryArgs, RetrieveTxQuerySortField, - RetrieveTxQuerySortOrder, + RetrieveTxQuerySortOrder, WalletBackend, }; use num_bigint::BigInt; -/// Retrieve all of the outputs (doesn't attempt to update from node) -pub fn retrieve_outputs<'a, T: ?Sized, C, K>( - wallet: &mut T, +/// Retrieve all the outputs (don't attempt to update from node) +pub fn retrieve_outputs( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, show_spent: bool, tx_id: Option, parent_key_id: Option<&Identifier>, ) -> Result, Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { // just read the wallet here, no need for a write lock let mut outputs = wallet - .iter() + .iter()? .filter(|out| show_spent || out.status != OutputStatus::Spent) .collect::>(); @@ -94,192 +91,200 @@ where } /// Apply advanced filtering to resultset from retrieve_txs below -pub fn apply_advanced_tx_list_filtering<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn apply_advanced_tx_list_filtering( + wallet: &mut WalletBackend, parent_key_id: Option<&Identifier>, query_args: &RetrieveTxQueryArgs, -) -> Vec +) -> Result, Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { // Apply simple bool, GTE or LTE fields - let txs_iter: Box> = Box::new( - wallet - .tx_log_iter() - .filter(|tx_entry| match parent_key_id { - Some(k) => tx_entry.parent_key_id == *k, - None => true, - }) - .filter(|tx_entry| { - if let Some(v) = query_args.exclude_cancelled { - if v { - tx_entry.tx_type != TxLogEntryType::TxReceivedCancelled - && tx_entry.tx_type != TxLogEntryType::TxSentCancelled - } else { - true - } + let mut bad_records = 0; + let txs_iter = wallet + .tx_log_iter()? + .filter(|tx| { + if tx.is_err() { + bad_records += 1; + } + tx.is_ok() + }) + .map(|tx| tx.unwrap()) + .filter(|tx_entry| match parent_key_id { + Some(k) => tx_entry.parent_key_id == *k, + None => true, + }) + .filter(|tx_entry| { + if let Some(v) = query_args.exclude_cancelled { + if v { + tx_entry.tx_type != TxLogEntryType::TxReceivedCancelled + && tx_entry.tx_type != TxLogEntryType::TxSentCancelled } else { true } - }) - .filter(|tx_entry| { - if let Some(v) = query_args.include_outstanding_only { - if v { - !tx_entry.confirmed - } else { - true - } + } else { + true + } + }) + .filter(|tx_entry| { + if let Some(v) = query_args.include_outstanding_only { + if v { + !tx_entry.confirmed } else { true } - }) - .filter(|tx_entry| { - if let Some(v) = query_args.include_confirmed_only { - if v { - tx_entry.confirmed - } else { - true - } + } else { + true + } + }) + .filter(|tx_entry| { + if let Some(v) = query_args.include_confirmed_only { + if v { + tx_entry.confirmed } else { true } - }) - .filter(|tx_entry| { - if let Some(v) = query_args.include_sent_only { - if v { - tx_entry.tx_type == TxLogEntryType::TxSent - || tx_entry.tx_type == TxLogEntryType::TxSentCancelled - } else { - true - } - } else { - true - } - }) - .filter(|tx_entry| { - if let Some(v) = query_args.include_received_only { - if v { - tx_entry.tx_type == TxLogEntryType::TxReceived - || tx_entry.tx_type == TxLogEntryType::TxReceivedCancelled - } else { - true - } - } else { - true - } - }) - .filter(|tx_entry| { - if let Some(v) = query_args.include_coinbase_only { - if v { - tx_entry.tx_type == TxLogEntryType::ConfirmedCoinbase - } else { - true - } - } else { - true - } - }) - .filter(|tx_entry| { - if let Some(v) = query_args.include_reverted_only { - if v { - tx_entry.tx_type == TxLogEntryType::TxReverted - } else { - true - } - } else { - true - } - }) - .filter(|tx_entry| { - if let Some(v) = query_args.min_id { - tx_entry.id >= v - } else { - true - } - }) - .filter(|tx_entry| { - if let Some(v) = query_args.max_id { - tx_entry.id <= v - } else { - true - } - }) - .filter(|tx_entry| { - if let Some(v) = query_args.min_amount { - if tx_entry.tx_type == TxLogEntryType::TxSent + } else { + true + } + }) + .filter(|tx_entry| { + if let Some(v) = query_args.include_sent_only { + if v { + tx_entry.tx_type == TxLogEntryType::TxSent || tx_entry.tx_type == TxLogEntryType::TxSentCancelled - { - BigInt::from(tx_entry.amount_debited) - - BigInt::from(tx_entry.amount_credited) - >= BigInt::from(v) - } else { - BigInt::from(tx_entry.amount_credited) - - BigInt::from(tx_entry.amount_debited) - >= BigInt::from(v) - } } else { true } - }) - .filter(|tx_entry| { - if let Some(v) = query_args.max_amount { - if tx_entry.tx_type == TxLogEntryType::TxSent - || tx_entry.tx_type == TxLogEntryType::TxSentCancelled - { - BigInt::from(tx_entry.amount_debited) - - BigInt::from(tx_entry.amount_credited) - <= BigInt::from(v) - } else { - BigInt::from(tx_entry.amount_credited) - - BigInt::from(tx_entry.amount_debited) - <= BigInt::from(v) - } + } else { + true + } + }) + .filter(|tx_entry| { + if let Some(v) = query_args.include_received_only { + if v { + tx_entry.tx_type == TxLogEntryType::TxReceived + || tx_entry.tx_type == TxLogEntryType::TxReceivedCancelled } else { true } - }) - .filter(|tx_entry| { - if let Some(v) = query_args.min_creation_timestamp { - tx_entry.creation_ts >= v + } else { + true + } + }) + .filter(|tx_entry| { + if let Some(v) = query_args.include_coinbase_only { + if v { + tx_entry.tx_type == TxLogEntryType::ConfirmedCoinbase } else { true } - }) - .filter(|tx_entry| { - if let Some(v) = query_args.min_confirmed_timestamp { - tx_entry.creation_ts <= v + } else { + true + } + }) + .filter(|tx_entry| { + if let Some(v) = query_args.include_reverted_only { + if v { + tx_entry.tx_type == TxLogEntryType::TxReverted } else { true } - }) - .filter(|tx_entry| { - if let Some(v) = query_args.min_confirmed_timestamp { - if let Some(t) = tx_entry.confirmation_ts { - t >= v - } else { - true - } + } else { + true + } + }) + .filter(|tx_entry| { + if let Some(v) = query_args.min_id { + tx_entry.id >= v + } else { + true + } + }) + .filter(|tx_entry| { + if let Some(v) = query_args.max_id { + tx_entry.id <= v + } else { + true + } + }) + .filter(|tx_entry| { + if let Some(v) = query_args.min_amount { + if tx_entry.tx_type == TxLogEntryType::TxSent + || tx_entry.tx_type == TxLogEntryType::TxSentCancelled + { + BigInt::from(tx_entry.amount_debited) - BigInt::from(tx_entry.amount_credited) + >= BigInt::from(v) + } else { + BigInt::from(tx_entry.amount_credited) - BigInt::from(tx_entry.amount_debited) + >= BigInt::from(v) + } + } else { + true + } + }) + .filter(|tx_entry| { + if let Some(v) = query_args.max_amount { + if tx_entry.tx_type == TxLogEntryType::TxSent + || tx_entry.tx_type == TxLogEntryType::TxSentCancelled + { + BigInt::from(tx_entry.amount_debited) - BigInt::from(tx_entry.amount_credited) + <= BigInt::from(v) + } else { + BigInt::from(tx_entry.amount_credited) - BigInt::from(tx_entry.amount_debited) + <= BigInt::from(v) + } + } else { + true + } + }) + .filter(|tx_entry| { + if let Some(v) = query_args.min_creation_timestamp { + tx_entry.creation_ts >= v + } else { + true + } + }) + .filter(|tx_entry| { + if let Some(v) = query_args.min_confirmed_timestamp { + tx_entry.creation_ts <= v + } else { + true + } + }) + .filter(|tx_entry| { + if let Some(v) = query_args.min_confirmed_timestamp { + if let Some(t) = tx_entry.confirmation_ts { + t >= v } else { true } - }) - .filter(|tx_entry| { - if let Some(v) = query_args.max_confirmed_timestamp { - if let Some(t) = tx_entry.confirmation_ts { - t <= v - } else { - true - } + } else { + true + } + }) + .filter(|tx_entry| { + if let Some(v) = query_args.max_confirmed_timestamp { + if let Some(t) = tx_entry.confirmation_ts { + t <= v } else { true } - }), - ); + } else { + true + } + }); + // }; + //TODO: apply limit + introduce skip before collecting all records. + // Introduce comparator for LMDB to not request all records with limit. let mut return_txs: Vec = txs_iter.collect(); + if bad_records != 0 { + error!("apply_advanced_tx_list_filtering: tx history is missing {} records, cause db read error", bad_records); + } + // Now apply requested sorting if let Some(ref s) = query_args.sort_field { match s { @@ -326,13 +331,13 @@ where return_txs = return_txs.into_iter().take(l as usize).collect() } - return_txs + Ok(return_txs) } -/// Retrieve all of the transaction entries, or a particular entry +/// Retrieve all the transaction entries, or a particular entry /// if `parent_key_id` is set, only return entries from that key -pub fn retrieve_txs<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn retrieve_txs( + wallet: &mut WalletBackend, tx_id: Option, tx_slate_id: Option, query_args: Option, @@ -340,18 +345,25 @@ pub fn retrieve_txs<'a, T: ?Sized, C, K>( outstanding_only: bool, ) -> Result, Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let mut txs; // Adding in new transaction list query logic. If `tx_id` or `tx_slate_id` // is provided, then `query_args` is ignored and old logic is followed. if query_args.is_some() && tx_id.is_none() && tx_slate_id.is_none() { - txs = apply_advanced_tx_list_filtering(wallet, parent_key_id, &query_args.unwrap()) + txs = apply_advanced_tx_list_filtering(wallet, parent_key_id, &query_args.unwrap())? } else { + let mut bad_records = 0; txs = wallet - .tx_log_iter() + .tx_log_iter()? + .filter(|tx| { + if tx.is_err() { + bad_records += 1; + } + tx.is_ok() + }) + .map(|tx| tx.unwrap()) .filter(|tx_entry| { let f_pk = match parent_key_id { Some(k) => tx_entry.parent_key_id == *k, @@ -377,6 +389,12 @@ where f_pk && f_tx_id && f_txs && f_outstanding }) .collect(); + if bad_records != 0 { + error!( + "retrieve_txs: tx history is missing {} records, cause db read error", + bad_records + ); + } txs.sort_by_key(|tx| tx.creation_ts); } Ok(txs) @@ -384,16 +402,15 @@ where /// Refreshes the outputs in a wallet with the latest information /// from a node -pub fn refresh_outputs<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn refresh_outputs( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, parent_key_id: &Identifier, update_all: bool, ) -> Result<(), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let height = wallet.w2n_client().get_chain_tip()?.0; refresh_output_state(wallet, keychain_mask, height, parent_key_id, update_all)?; @@ -402,21 +419,20 @@ where /// build a local map of wallet outputs keyed by commit /// and a list of outputs we want to query the node for -pub fn map_wallet_outputs<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn map_wallet_outputs( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, parent_key_id: &Identifier, update_all: bool, ) -> Result, Option, bool)>, Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let mut wallet_outputs = HashMap::new(); let keychain = wallet.keychain(keychain_mask)?; let unspents: Vec = wallet - .iter() + .iter()? .filter(|x| x.root_key_id == *parent_key_id && x.status != OutputStatus::Spent) .collect(); @@ -453,17 +469,16 @@ where } /// Cancel transaction and associated outputs -pub fn cancel_tx_and_outputs<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn cancel_tx_and_outputs( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, mut tx: TxLogEntry, outputs: Vec, parent_key_id: &Identifier, ) -> Result<(), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let mut batch = wallet.batch(keychain_mask)?; @@ -490,8 +505,8 @@ where } /// Apply refreshed API output data to the wallet -pub fn apply_api_outputs<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn apply_api_outputs( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, wallet_outputs: &HashMap, Option, bool)>, api_outputs: &HashMap, @@ -500,9 +515,8 @@ pub fn apply_api_outputs<'a, T: ?Sized, C, K>( parent_key_id: &Identifier, ) -> Result<(), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { // now for each commit, find the output in the wallet and the corresponding // api output (if it exists) and refresh it in-place in the wallet. @@ -556,10 +570,14 @@ where && (output.status == OutputStatus::Unconfirmed || output.status == OutputStatus::Reverted) { - let tx = batch.tx_log_iter().find(|t| { - Some(t.id) == output.tx_log_entry - && t.parent_key_id == *parent_key_id - }); + let tx = batch + .tx_log_iter()? + .filter(|t| t.is_ok()) + .map(|t| t.unwrap()) + .find(|t| { + Some(t.id) == output.tx_log_entry + && t.parent_key_id == *parent_key_id + }); if let Some(mut t) = tx { if t.tx_type == TxLogEntryType::TxReverted { t.tx_type = TxLogEntryType::TxReceived; @@ -568,6 +586,10 @@ where t.update_confirmation_ts(); t.confirmed = true; batch.save_tx_log_entry(t, &parent_key_id)?; + } else { + if let Some(tx_id) = output.tx_log_entry { + error!("apply_api_outputs: tx with id {:?} not found", tx_id); + } } } output.height = o.1; @@ -590,7 +612,18 @@ where } } - for mut tx in batch.tx_log_iter() { + let mut txs_to_save = vec![]; + let mut bad_records = 0; + for mut tx in batch + .tx_log_iter()? + .filter(|tx| { + if tx.is_err() { + bad_records += 1; + } + tx.is_ok() + }) + .map(|t| t.unwrap()) + { if reverted_kernels.contains(&tx.id) && tx.parent_key_id == *parent_key_id { tx.tx_type = TxLogEntryType::TxReverted; tx.reverted_after = tx.confirmation_ts.clone().and_then(|t| { @@ -598,10 +631,21 @@ where (now - t).to_std().ok() }); tx.confirmed = false; - batch.save_tx_log_entry(tx, &parent_key_id)?; + txs_to_save.push(tx); } } + if bad_records > 0 { + error!( + "apply_api_outputs: tx history is missing {} records, cause db read error", + bad_records + ); + } + + for tx in txs_to_save { + batch.save_tx_log_entry(tx, &parent_key_id)?; + } + { batch.save_last_confirmed_height(parent_key_id, height)?; } @@ -612,17 +656,16 @@ where /// Builds a single api query to retrieve the latest output data from the node. /// So we can refresh the local wallet outputs. -fn refresh_output_state<'a, T: ?Sized, C, K>( - wallet: &mut T, +fn refresh_output_state( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, height: u64, parent_key_id: &Identifier, update_all: bool, ) -> Result<(), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { debug!("Refreshing wallet outputs"); @@ -654,16 +697,15 @@ where Ok(()) } -fn find_reverted_kernels<'a, T: ?Sized, C, K>( - wallet: &mut T, +fn find_reverted_kernels( + wallet: &mut WalletBackend, wallet_outputs: &HashMap, Option, bool)>, api_outputs: &HashMap, parent_key_id: &Identifier, ) -> Result, Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let mut client = wallet.w2n_client().clone(); let mut ids = HashSet::new(); @@ -678,8 +720,16 @@ where } // Get corresponding kernels + let mut bad_records = 0; let kernels = wallet - .tx_log_iter() + .tx_log_iter()? + .filter(|tx| { + if tx.is_err() { + bad_records += 1; + } + tx.is_ok() + }) + .map(|t| t.unwrap()) .filter(|t| { ids.contains(&t.id) && t.parent_key_id == *parent_key_id @@ -698,24 +748,30 @@ where } } + if bad_records > 0 { + error!( + "find_reverted_kernels: tx history is missing {} records, cause db read error", + bad_records + ); + } + Ok(reverted) } -fn clean_old_unconfirmed<'a, T: ?Sized, C, K>( - wallet: &mut T, +fn clean_old_unconfirmed( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, height: u64, ) -> Result<(), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { if height < 50 { return Ok(()); } let mut ids_to_del = vec![]; - for out in wallet.iter() { + for out in wallet.iter()? { if out.status == OutputStatus::Unconfirmed && out.height > 0 && out.height < height - 50 @@ -734,19 +790,18 @@ where /// Retrieve summary info about the wallet /// caller should refresh first if desired -pub fn retrieve_info<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn retrieve_info( + wallet: &mut WalletBackend, parent_key_id: &Identifier, minimum_confirmations: u64, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let current_height = wallet.last_confirmed_height()?; let outputs = wallet - .iter() + .iter()? .filter(|out| out.root_key_id == *parent_key_id); let mut unspent_total = 0; @@ -800,16 +855,15 @@ where } /// Build a coinbase output and insert into wallet -pub fn build_coinbase<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn build_coinbase( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, block_fees: &BlockFees, test_mode: bool, ) -> Result where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let (out, kern, block_fees) = receive_coinbase(wallet, keychain_mask, block_fees, test_mode)?; @@ -822,16 +876,15 @@ where //TODO: Split up the output creation and the wallet insertion /// Build a coinbase output and the corresponding kernel -pub fn receive_coinbase<'a, T: ?Sized, C, K>( - wallet: &mut T, +pub fn receive_coinbase( + wallet: &mut WalletBackend, keychain_mask: Option<&SecretKey>, block_fees: &BlockFees, test_mode: bool, ) -> Result<(Output, TxKernel, BlockFees), Error> where - T: WalletBackend<'a, C, K>, - C: NodeClient + 'a, - K: Keychain + 'a, + C: NodeClient, + K: Keychain, { let height = block_fees.height; let lock_height = height + global::coinbase_maturity(); @@ -856,11 +909,11 @@ where key_id: key_id.clone(), n_child: key_id.to_path().last_path_index(), mmr_index: None, - commit: commit, + commit, value: amount, status: OutputStatus::Unconfirmed, - height: height, - lock_height: lock_height, + height, + lock_height, is_coinbase: true, tx_log_entry: None, })?; diff --git a/libwallet/src/lib.rs b/libwallet/src/lib.rs index 95185c5..a73cdb4 100644 --- a/libwallet/src/lib.rs +++ b/libwallet/src/lib.rs @@ -45,6 +45,7 @@ extern crate strum_macros; pub mod address; pub mod api_impl; +mod backend; mod error; mod internal; pub mod mwixnet; @@ -69,13 +70,13 @@ pub use api_impl::types::{ NodeHeightResult, OutputCommitMapping, PaymentProof, RetrieveTxQueryArgs, RetrieveTxQuerySortField, RetrieveTxQuerySortOrder, VersionInfo, }; +pub use backend::{WalletBackend, WalletBatch}; pub use internal::scan::scan; pub use slate_versions::ser as dalek_ser; pub use types::{ AcctPathMapping, BlockIdentifier, CbData, Context, NodeClient, NodeVersionInfo, OutputData, OutputStatus, ScannedBlockInfo, StoredProofInfo, TxLogEntry, TxLogEntryType, TxWrapper, - ViewWallet, WalletBackend, WalletInfo, WalletInitStatus, WalletInst, WalletLCProvider, - WalletOutputBatch, + ViewWallet, WalletInfo, WalletInitStatus, WalletInst, WalletLCProvider, }; /// Helper for taking a lock on the wallet instance diff --git a/libwallet/src/slate.rs b/libwallet/src/slate.rs index 43a7ba9..a29233c 100644 --- a/libwallet/src/slate.rs +++ b/libwallet/src/slate.rs @@ -81,7 +81,7 @@ impl ParticipantData { } } -/// A 'Slate' is passed around to all parties to build up all of the public +/// A 'Slate' is passed around to all parties to build up all the public /// transaction data needed to create a finalized transaction. Callers can pass /// the slate around by whatever means they choose, (but we can provide some /// binary or JSON serialization helpers here). @@ -115,7 +115,7 @@ pub struct Slate { /// 2: height_locked /// 3: NRD pub kernel_features: u8, - /// Offset, needed when posting of transasction is deferred + /// Offset, needed when posting of transaction is deferred pub offset: BlindingFactor, /// Participant data, each participant in the transaction will /// insert their public data here. For now, 0 is sender and 1 @@ -134,7 +134,7 @@ impl fmt::Display for Slate { } /// Slate state definition -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub enum SlateState { /// Unknown, coming from earlier slate versions Unknown, @@ -148,7 +148,7 @@ pub enum SlateState { Invoice1, ///Invoice flow, return journey Invoice2, - /// Invoice flow, ready for tranasction posting + /// Invoice flow, ready for transaction posting Invoice3, } diff --git a/libwallet/src/types.rs b/libwallet/src/types.rs index 12b552e..41ca9a5 100644 --- a/libwallet/src/types.rs +++ b/libwallet/src/types.rs @@ -28,7 +28,7 @@ use crate::grin_util::secp::key::{PublicKey, SecretKey}; use crate::grin_util::secp::{self, pedersen, Secp256k1}; use crate::grin_util::{ToHex, ZeroingString}; use crate::slate_versions::ser as dalek_ser; -use crate::InitTxArgs; +use crate::{InitTxArgs, SlateState, WalletBackend}; use chrono::prelude::*; use ed25519_dalek::PublicKey as DalekPublicKey; use ed25519_dalek::Signature as DalekSignature; @@ -49,7 +49,7 @@ where K: Keychain + 'a, { /// Return the stored instance - fn lc_provider(&mut self) -> Result<&mut (dyn WalletLCProvider<'a, C, K> + 'a), Error>; + fn lc_provider(&mut self) -> Result<&mut dyn WalletLCProvider<'a, C, K>, Error>; } /// Trait for a provider of wallet lifecycle methods @@ -131,182 +131,7 @@ where fn delete_wallet(&self, name: Option<&str>) -> Result<(), Error>; /// return wallet instance - fn wallet_inst(&mut self) -> Result<&mut Box + 'a>, Error>; -} - -/// TODO: -/// Wallets should implement this backend for their storage. All functions -/// here expect that the wallet instance has instantiated itself or stored -/// whatever credentials it needs -pub trait WalletBackend<'ck, C, K>: Send + Sync -where - C: NodeClient + 'ck, - K: Keychain + 'ck, -{ - /// Set the keychain, which should already be initialized - /// Optionally return a token value used to XOR the stored - /// key value - fn set_keychain( - &mut self, - k: Box, - mask: bool, - use_test_rng: bool, - ) -> Result, Error>; - - /// Close wallet and remove any stored credentials (TBD) - fn close(&mut self) -> Result<(), Error>; - - /// Return the keychain being used. Ensure a cloned copy so it will be dropped - /// and zeroized by the caller - /// Can optionally take a mask value - fn keychain(&self, mask: Option<&SecretKey>) -> Result; - - /// Return the client being used to communicate with the node - fn w2n_client(&mut self) -> &mut C; - - /// return the commit for caching if allowed, none otherwise - fn calc_commit_for_cache( - &mut self, - keychain_mask: Option<&SecretKey>, - amount: u64, - id: &Identifier, - ) -> Result, Error>; - - /// Set parent key id by stored account name - fn set_parent_key_id_by_name(&mut self, label: &str) -> Result<(), Error>; - - /// The BIP32 path of the parent path to use for all output-related - /// functions, (essentially 'accounts' within a wallet. - fn set_parent_key_id(&mut self, _: Identifier); - - /// return the parent path - fn parent_key_id(&mut self) -> Identifier; - - /// Iterate over all output data stored by the backend - fn iter<'a>(&'a self) -> Box + 'a>; - - /// Get output data by id - fn get(&self, id: &Identifier, mmr_index: &Option) -> Result; - - /// Get an (Optional) tx log entry by uuid - fn get_tx_log_entry(&self, uuid: &Uuid) -> Result, Error>; - - /// Retrieves the private context associated with a given slate id - fn get_private_context( - &mut self, - keychain_mask: Option<&SecretKey>, - slate_id: &[u8], - ) -> Result; - - /// Iterate over all output data stored by the backend - fn tx_log_iter<'a>(&'a self) -> Box + 'a>; - - /// Iterate over all stored account paths - fn acct_path_iter<'a>(&'a self) -> Box + 'a>; - - /// Gets an account path for a given label - fn get_acct_path(&self, label: String) -> Result, Error>; - - /// Stores a transaction - fn store_tx(&self, uuid: &str, tx: &Transaction) -> Result<(), Error>; - - /// Retrieves a stored transaction from a TxLogEntry - fn get_stored_tx(&self, uuid: &str) -> Result, Error>; - - /// Create a new write batch to update or remove output data - fn batch<'a>( - &'a mut self, - keychain_mask: Option<&SecretKey>, - ) -> Result + 'a>, Error>; - - /// Batch for use when keychain isn't available or required - fn batch_no_mask<'a>(&'a mut self) -> Result + 'a>, Error>; - - /// Return the current child Index - fn current_child_index(&mut self, parent_key_id: &Identifier) -> Result; - - /// Next child ID when we want to create a new output, based on current parent - fn next_child(&mut self, keychain_mask: Option<&SecretKey>) -> Result; - - /// last verified height of outputs directly descending from the given parent key - fn last_confirmed_height(&mut self) -> Result; - - /// last block scanned during scan or restore - fn last_scanned_block(&mut self) -> Result; - - /// Flag whether the wallet needs a full UTXO scan on next update attempt - fn init_status(&mut self) -> Result; -} - -/// Batch trait to update the output data backend atomically. Trying to use a -/// batch after commit MAY result in a panic. Due to this being a trait, the -/// commit method can't take ownership. -/// TODO: Should these be split into separate batch objects, for outputs, -/// tx_log entries and meta/details? -pub trait WalletOutputBatch -where - K: Keychain, -{ - /// Return the keychain being used - fn keychain(&mut self) -> &mut K; - - /// Add or update data about an output to the backend - fn save(&mut self, out: OutputData) -> Result<(), Error>; - - /// Gets output data by id - fn get(&self, id: &Identifier, mmr_index: &Option) -> Result; - - /// Iterate over all output data stored by the backend - fn iter(&self) -> Box>; - - /// Delete data about an output from the backend - fn delete(&mut self, id: &Identifier, mmr_index: &Option) -> Result<(), Error>; - - /// Save last stored child index of a given parent - fn save_child_index(&mut self, parent_key_id: &Identifier, child_n: u32) -> Result<(), Error>; - - /// Save last confirmed height of outputs for a given parent - fn save_last_confirmed_height( - &mut self, - parent_key_id: &Identifier, - height: u64, - ) -> Result<(), Error>; - - /// Save the last PMMR index that was scanned via a scan operation - fn save_last_scanned_block(&mut self, block: ScannedBlockInfo) -> Result<(), Error>; - - /// Save flag indicating whether wallet needs a full UTXO scan - fn save_init_status(&mut self, value: WalletInitStatus) -> Result<(), Error>; - - /// get next tx log entry for the parent - fn next_tx_log_id(&mut self, parent_key_id: &Identifier) -> Result; - - /// Iterate over tx log data stored by the backend - fn tx_log_iter(&self) -> Box>; - - /// save a tx log entry - fn save_tx_log_entry(&mut self, t: TxLogEntry, parent_id: &Identifier) -> Result<(), Error>; - - /// delete a tx log entry - fn delete_tx_log_entry(&mut self, tx_id: u32, parent_id: &Identifier) -> Result<(), Error>; - - /// save an account label -> path mapping - fn save_acct_path(&mut self, mapping: AcctPathMapping) -> Result<(), Error>; - - /// Iterate over account names stored in backend - fn acct_path_iter(&self) -> Box>; - - /// Save an output as locked in the backend - fn lock_output(&mut self, out: &mut OutputData) -> Result<(), Error>; - - /// Saves the private context associated with a slate id - fn save_private_context(&mut self, slate_id: &[u8], ctx: &Context) -> Result<(), Error>; - - /// Delete the private context associated with the slate id - fn delete_private_context(&mut self, slate_id: &[u8]) -> Result<(), Error>; - - /// Write the wallet data to backend file - fn commit(&self) -> Result<(), Error>; + fn wallet_inst(&mut self) -> Result<&mut WalletBackend, Error>; } /// Encapsulate all wallet-node communication functions. No functions within libwallet @@ -798,6 +623,8 @@ pub struct TxLogEntry { pub id: u32, /// Slate transaction this entry is associated with, if any pub tx_slate_id: Option, + /// Transaction slate state + pub tx_slate_state: Option, /// Transaction type (as above) pub tx_type: TxLogEntryType, /// Time this tx entry was created @@ -861,10 +688,11 @@ impl TxLogEntry { /// Return a new blank with TS initialised with next entry pub fn new(parent_key_id: Identifier, t: TxLogEntryType, id: u32) -> Self { TxLogEntry { - parent_key_id: parent_key_id, + parent_key_id, tx_type: t, - id: id, + id, tx_slate_id: None, + tx_slate_state: None, creation_ts: Utc::now(), confirmation_ts: None, confirmed: false, @@ -1053,7 +881,7 @@ pub struct ViewWalletOutputResult { impl ViewWalletOutputResult { pub fn num_confirmations(&self, tip_height: u64) -> u64 { if self.height > tip_height { - return 0; + 0 } else { 1 + (tip_height - self.height) } diff --git a/src/cli/cli.rs b/src/cli/cli.rs index c14f3d4..cf01dd7 100644 --- a/src/cli/cli.rs +++ b/src/cli/cli.rs @@ -115,7 +115,7 @@ pub fn command_loop( test_mode: bool, ) -> Result<(), Error> where - DefaultWalletImpl<'static, C>: WalletInst<'static, L, C, K>, + DefaultWalletImpl: WalletInst<'static, L, C, K>, L: WalletLCProvider<'static, C, K> + 'static, C: NodeClient + 'static, K: keychain::Keychain + 'static, diff --git a/src/cmd/wallet_args.rs b/src/cmd/wallet_args.rs index 205cc0e..1345cdd 100644 --- a/src/cmd/wallet_args.rs +++ b/src/cmd/wallet_args.rs @@ -92,7 +92,7 @@ fn prompt_recovery_phrase( wallet: Arc>>>, ) -> Result where - DefaultWalletImpl<'static, C>: WalletInst<'static, L, C, K>, + DefaultWalletImpl: WalletInst<'static, L, C, K>, L: WalletLCProvider<'static, C, K>, C: NodeClient + 'static, K: keychain::Keychain + 'static, @@ -224,12 +224,12 @@ pub fn inst_wallet( node_client: C, ) -> Result>>>, ParseError> where - DefaultWalletImpl<'static, C>: WalletInst<'static, L, C, K>, + DefaultWalletImpl: WalletInst<'static, L, C, K>, L: WalletLCProvider<'static, C, K>, C: NodeClient + 'static, K: keychain::Keychain + 'static, { - let mut wallet = Box::new(DefaultWalletImpl::<'static, C>::new(node_client.clone()).unwrap()) + let mut wallet = Box::new(DefaultWalletImpl::::new(node_client.clone()).unwrap()) as Box>; let lc = wallet.lc_provider().unwrap(); let _ = lc.set_top_level_directory(&config.data_file_dir); @@ -335,7 +335,7 @@ pub fn parse_init_args( _test_mode: bool, ) -> Result where - DefaultWalletImpl<'static, C>: WalletInst<'static, L, C, K>, + DefaultWalletImpl: WalletInst<'static, L, C, K>, L: WalletLCProvider<'static, C, K>, C: NodeClient + 'static, K: keychain::Keychain + 'static, @@ -355,16 +355,16 @@ where println!("Please enter a password for your new wallet"); } - let password = match g_args.password.clone() { - Some(p) => p, - None => prompt_password_confirm(), - }; + let password = g_args + .password + .clone() + .unwrap_or_else(|| prompt_password_confirm()); Ok(command::InitArgs { - list_length: list_length, - password: password, + list_length, + password, config: config.clone(), - recovery_phrase: recovery_phrase, + recovery_phrase, restore: false, }) } @@ -375,9 +375,7 @@ pub fn parse_recover_args( where { let passphrase = prompt_password(&g_args.password); - Ok(command::RecoverArgs { - passphrase: passphrase, - }) + Ok(command::RecoverArgs { passphrase }) } pub fn parse_listen_args( @@ -977,7 +975,7 @@ where Box< dyn WalletInst< 'static, - DefaultLCProvider<'static, C, keychain::ExtKeychain>, + DefaultLCProvider, C, keychain::ExtKeychain, >, @@ -1112,7 +1110,7 @@ pub fn parse_and_execute( cli_mode: bool, ) -> Result<(), Error> where - DefaultWalletImpl<'static, C>: WalletInst<'static, L, C, K>, + DefaultWalletImpl: WalletInst<'static, L, C, K>, L: WalletLCProvider<'static, C, K> + 'static, C: NodeClient + 'static, K: keychain::Keychain + 'static, diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 2116457..ee01a40 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -226,7 +226,7 @@ pub fn instantiate_wallet( Box< dyn WalletInst< 'static, - DefaultLCProvider<'static, LocalWalletClient, ExtKeychain>, + DefaultLCProvider, LocalWalletClient, ExtKeychain, >, @@ -241,7 +241,7 @@ pub fn instantiate_wallet( let mut wallet = Box::new(DefaultWalletImpl::::new(node_client).unwrap()) as Box< dyn WalletInst< - DefaultLCProvider<'static, LocalWalletClient, ExtKeychain>, + DefaultLCProvider, LocalWalletClient, ExtKeychain, >, @@ -302,18 +302,7 @@ pub fn execute_command_no_setup( where C: NodeClient + 'static + Clone, F: FnOnce( - Arc< - Mutex< - Box< - dyn WalletInst< - 'static, - DefaultLCProvider<'static, C, ExtKeychain>, - C, - ExtKeychain, - >, - >, - >, - >, + Arc, C, ExtKeychain>>>>, ), { let args = app.clone().get_matches_from(arg_vec); diff --git a/tests/owner_v3_lifecycle.rs b/tests/owner_v3_lifecycle.rs index 42295d5..fd27a50 100644 --- a/tests/owner_v3_lifecycle.rs +++ b/tests/owner_v3_lifecycle.rs @@ -57,7 +57,7 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> { let wallet_proxy_a: Arc< Mutex< WalletProxy< - DefaultLCProvider<'static, LocalWalletClient, ExtKeychain>, + DefaultLCProvider, LocalWalletClient, ExtKeychain, >, diff --git a/util/Cargo.toml b/util/Cargo.toml index ef22dde..1cb5aa8 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -21,14 +21,14 @@ thiserror = "1" ##### Grin Imports # For Release -grin_util = "5.4.0" +#grin_util = "5.4.0" # For beta release # grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" } # For bleeding edge -# grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" } +grin_util = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" } # For local testing