diff --git a/Cargo.lock b/Cargo.lock index b1b08422..bc2b0395 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,7 +56,7 @@ dependencies = [ "amplify_num", "amplify_syn", "ascii", - "rand 0.8.5", + "rand 0.8.6", "serde", "stringly_conversions", "wasm-bindgen", @@ -258,9 +258,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-rs" -version = "1.16.2" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" dependencies = [ "aws-lc-sys", "zeroize", @@ -268,9 +268,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.39.1" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" +checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" dependencies = [ "cc", "cmake", @@ -384,9 +384,9 @@ dependencies = [ [[package]] name = "bdk_file_store" -version = "0.21.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446f02da319941ea78454a479fca72707f3355a62db3bb1c2c13b94e7f963ce0" +checksum = "c7b9a98edb58d02b601239832674a9ca9f1465e08e1dd1fac3a0e34004372406" dependencies = [ "bdk_core", "bincode", @@ -395,9 +395,9 @@ dependencies = [ [[package]] name = "bdk_wallet" -version = "2.0.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f278518ee6f2a17711fd4662dc34ce6153792a7a21575f05a9c8e2cb9ba36245" +checksum = "67f3c4f9526d22374fca5b7ff1d6bf8d921ab56db2dac8df66a2c5561b31d4ef" dependencies = [ "bdk_chain", "bdk_file_store", @@ -468,7 +468,7 @@ dependencies = [ "pkcs8 0.9.0", "prost", "prost-types", - "rand 0.8.5", + "rand 0.8.6", "rand_core 0.6.4", "regex", "serde_json", @@ -541,9 +541,9 @@ checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" [[package]] name = "bitcoin-units" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2" +checksum = "346568ebaab2918487cea76dd55dae13c27bb618cdb737c952e69eb2017c4118" dependencies = [ "bitcoin-internals", "serde", @@ -562,25 +562,25 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" dependencies = [ "serde_core", ] [[package]] name = "blake3" -version = "1.8.3" +version = "1.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2468ef7d57b3fb7e16b576e8377cdbde2320c60e1491e961d11da40fc4f02a2d" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "cpufeatures 0.2.17", + "cpufeatures 0.3.0", ] [[package]] @@ -627,9 +627,9 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "cc" -version = "1.2.58" +version = "1.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ "find-msvc-tools", "jobserver", @@ -637,12 +637,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - [[package]] name = "cfg-if" version = "1.0.4" @@ -674,7 +668,7 @@ checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if", "cpufeatures 0.3.0", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -717,9 +711,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -739,9 +733,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -878,9 +872,9 @@ dependencies = [ [[package]] name = "crc-catalog" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" [[package]] name = "crc32fast" @@ -1181,7 +1175,7 @@ dependencies = [ "byteorder", "libc", "log", - "rustls 0.23.37", + "rustls 0.23.40", "serde", "serde_json", "webpki-roots 0.25.4", @@ -1298,9 +1292,9 @@ checksum = "a35a73237400bde66c82e38387343f90d7182a2f2f22729e096a2abd57d75db9" [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "ff" @@ -1531,7 +1525,7 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "rand_core 0.10.0", + "rand_core 0.10.1", "wasip2", "wasip3", ] @@ -1606,9 +1600,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "hashlink" @@ -1678,11 +1672,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1732,9 +1726,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ "atomic-waker", "bytes", @@ -1747,7 +1741,6 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -1755,15 +1748,14 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.7" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ "http", "hyper", "hyper-util", - "rustls 0.23.37", - "rustls-pki-types", + "rustls 0.23.40", "tokio", "tokio-rustls", "tower-service", @@ -1836,12 +1828,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", @@ -1849,9 +1842,9 @@ 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", @@ -1862,9 +1855,9 @@ dependencies = [ [[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", @@ -1876,15 +1869,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", @@ -1896,15 +1889,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", @@ -1940,9 +1933,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", @@ -1950,12 +1943,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] @@ -1988,9 +1981,9 @@ checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "iri-string" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e7418f59cc01c88316161279a7f665217ae316b388e58a0d10e29f54f1e5eb" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" dependencies = [ "memchr", "serde", @@ -2030,27 +2023,32 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jni" -version = "0.21.1" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" dependencies = [ - "cesu8", "cfg-if", "combine", - "jni-sys 0.3.1", + "jni-macros", + "jni-sys", "log", - "thiserror 1.0.69", + "simd_cesu8", + "thiserror 2.0.18", "walkdir", - "windows-sys 0.45.0", + "windows-link", ] [[package]] -name = "jni-sys" -version = "0.3.1" +name = "jni-macros" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" dependencies = [ - "jni-sys 0.4.1", + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.117", ] [[package]] @@ -2084,9 +2082,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.92" +version = "0.3.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc4c90f45aa2e6eacbe8645f77fdea542ac97a494bcd117a67df9ff4d611f995" +checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf" dependencies = [ "cfg-if", "futures-util", @@ -2111,9 +2109,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.183" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libm" @@ -2123,14 +2121,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ "bitflags", "libc", "plain", - "redox_syscall 0.7.3", + "redox_syscall 0.7.4", ] [[package]] @@ -2152,9 +2150,9 @@ 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 = "lock_api" @@ -2177,6 +2175,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "mac_address" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0aeb26bf5e836cc1c341c8106051b573f1766dfa05aa87f0b98be5e51b02303" +dependencies = [ + "nix", + "serde", + "winapi", +] + [[package]] name = "matchers" version = "0.2.0" @@ -2202,6 +2211,15 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.17" @@ -2226,9 +2244,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniscript" -version = "12.3.5" +version = "12.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487906208f38448e186e3deb02f2b8ef046a9078b0de00bdb28bf4fb9b76951c" +checksum = "c14116d8342edd3626b0f8e84df16f4e6a76dc04799ba747493403236a1b8ac5" dependencies = [ "bech32", "bitcoin", @@ -2282,7 +2300,7 @@ dependencies = [ "hyper-util", "log", "pin-project-lite", - "rand 0.9.2", + "rand 0.9.4", "regex", "serde_json", "serde_urlencoded", @@ -2307,6 +2325,19 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + [[package]] name = "nom" version = "7.1.3" @@ -2347,16 +2378,16 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "smallvec", "zeroize", ] [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" [[package]] name = "num-integer" @@ -2408,9 +2439,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.76" +version = "0.10.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" +checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" dependencies = [ "bitflags", "cfg-if", @@ -2440,18 +2471,18 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-src" -version = "300.5.1+3.5.1" +version = "300.6.0+3.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "735230c832b28c000e3bc117119e6466a663ec73506bc0a9907ea4187508e42a" +checksum = "a8e8cbfd3a4a8c8f089147fd7aaa33cf8c7450c4d09f8f80698a0cf093abeff4" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.112" +version = "0.9.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" +checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" dependencies = [ "cc", "libc", @@ -2604,12 +2635,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "pkcs1" version = "0.7.5" @@ -2643,9 +2668,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plain" @@ -2666,9 +2691,9 @@ 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", ] @@ -2796,7 +2821,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.37", + "rustls 0.23.40", "socket2", "thiserror 2.0.18", "tokio", @@ -2814,10 +2839,10 @@ dependencies = [ "bytes", "getrandom 0.3.4", "lru-slab", - "rand 0.9.2", + "rand 0.9.4", "ring", "rustc-hash", - "rustls 0.23.37", + "rustls 0.23.40", "rustls-pki-types", "slab", "thiserror 2.0.18", @@ -2837,7 +2862,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -2863,9 +2888,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[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", @@ -2874,9 +2899,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -2884,13 +2909,13 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "chacha20 0.10.0", "getrandom 0.4.2", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -2933,9 +2958,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "redox_syscall" @@ -2948,9 +2973,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" +checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" dependencies = [ "bitflags", ] @@ -3006,9 +3031,9 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" dependencies = [ "base64 0.22.1", "bytes", @@ -3032,7 +3057,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.37", + "rustls 0.23.40", "rustls-pki-types", "rustls-platform-verifier", "serde", @@ -3062,9 +3087,9 @@ dependencies = [ [[package]] name = "rgb-aluvm" -version = "0.11.1-rc.2" +version = "0.11.1-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b9e41006564b48551e52e001181898982b11732348100216097033b3e536a2" +checksum = "b60686e4f1701ca4f73b77660777a49e651f3c611461ab62ef718db47a5a6caa" dependencies = [ "amplify", "baid64", @@ -3096,9 +3121,9 @@ dependencies = [ [[package]] name = "rgb-consensus" -version = "0.11.1-rc.9" +version = "0.11.1-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6e0da534613ed77953976b9be54c7db66bd5a6c66773bd5866b1bacdbfb41d" +checksum = "535483ee9143782e33ddebd3eda465de0184061fc3c480e24990e42fefc58bb0" dependencies = [ "amplify", "baid64", @@ -3110,7 +3135,7 @@ dependencies = [ "getrandom 0.3.4", "hex-conservative", "mime", - "rand 0.9.2", + "rand 0.9.4", "rgb-aluvm", "rgb-strict-encoding", "rgb-strict-types", @@ -3123,9 +3148,9 @@ dependencies = [ [[package]] name = "rgb-invoicing" -version = "0.11.1-rc.9" +version = "0.11.1-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22f7125c70fd8e959d85d29c0bdbeecb173d6aed9a72eae71f1e43bade383f" +checksum = "10400124af86de579b0f13603e014512b6166ad94ea791212b71579ffb91dd8a" dependencies = [ "amplify", "baid64", @@ -3133,7 +3158,7 @@ dependencies = [ "fluent-uri", "indexmap", "percent-encoding", - "rand 0.9.2", + "rand 0.9.4", "rgb-consensus", "rgb-strict-encoding", "rgb-strict-types", @@ -3162,7 +3187,7 @@ dependencies = [ "minreq", "mockito", "once_cell", - "rand 0.10.0", + "rand 0.10.1", "regex", "reqwest", "rgb-invoicing", @@ -3172,7 +3197,7 @@ dependencies = [ "rgb-schemas", "rgb-strict-encoding", "rgb-strict-types", - "rustls 0.23.37", + "rustls 0.23.40", "scrypt", "sea-orm", "sea-query", @@ -3202,9 +3227,9 @@ dependencies = [ [[package]] name = "rgb-ops" -version = "0.11.1-rc.9" +version = "0.11.1-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb298dfc6cddd4367c850bf621fca6b2b77a16c2ce472bc4e576811fe5b29be" +checksum = "3782a5ff1e5408e23c2d14fc556347684f5c8f72d96c4ca357527a3dbffb7378" dependencies = [ "amplify", "baid64", @@ -3215,7 +3240,7 @@ dependencies = [ "getrandom 0.3.4", "indexmap", "nonasync", - "rand 0.9.2", + "rand 0.9.4", "rgb-aluvm", "rgb-ascii-armor", "rgb-consensus", @@ -3223,14 +3248,15 @@ dependencies = [ "rgb-strict-encoding", "rgb-strict-types", "serde", + "serde_json", "wasm-bindgen", ] [[package]] name = "rgb-psbt-utils" -version = "0.11.1-rc.9" +version = "0.11.1-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9faab66bd883c85ffcb35f8dfa9d676184c5924f5076ffd9c72943bdf5b3df3c" +checksum = "0107634634c424a8b268ec6549df08da676768ec6ddbcda51f12e7882daeeee6" dependencies = [ "amplify", "baid64", @@ -3243,9 +3269,9 @@ dependencies = [ [[package]] name = "rgb-schemas" -version = "0.11.1-rc.9" +version = "0.11.1-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a80e2f45e850293c97d0e4fcd9b1c066a666b52b66617f4476365346c92111" +checksum = "1903961c836cc3f6963b06c69cb47491a815309f265439f20c932e0a3aa16a78" dependencies = [ "amplify", "rgb-aluvm", @@ -3395,16 +3421,16 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.37" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.10", + "rustls-webpki 0.103.13", "subtle", "zeroize", ] @@ -3423,9 +3449,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ "web-time", "zeroize", @@ -3433,23 +3459,23 @@ dependencies = [ [[package]] name = "rustls-platform-verifier" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ "core-foundation 0.10.1", "core-foundation-sys", "jni", "log", "once_cell", - "rustls 0.23.37", + "rustls 0.23.40", "rustls-native-certs", "rustls-platform-verifier-android", - "rustls-webpki 0.103.10", + "rustls-webpki 0.103.13", "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3470,9 +3496,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.10" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "aws-lc-rs", "ring", @@ -3577,9 +3603,9 @@ dependencies = [ [[package]] name = "sea-orm" -version = "1.1.19" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d945f62558fac19e5988680d2fdf747b734c2dbc6ce2cb81ba33ed8dde5b103" +checksum = "2dc312fedd460a47ea563911761d254a84e7b51d8cc73ec92c929e78f33fa957" dependencies = [ "async-stream", "async-trait", @@ -3588,6 +3614,7 @@ dependencies = [ "derive_more", "futures-util", "log", + "mac_address", "ouroboros", "pgvector", "rust_decimal", @@ -3607,9 +3634,9 @@ dependencies = [ [[package]] name = "sea-orm-cli" -version = "1.1.19" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94492e2ab6c045b4cc38013809ce255d14c3d352c9f0d11e6b920e2adc948ad" +checksum = "da80ebcdb44571e86f03a2bdcb5532136a87397f366f38bbce64673fc5e6a450" dependencies = [ "chrono", "clap", @@ -3626,9 +3653,9 @@ dependencies = [ [[package]] name = "sea-orm-macros" -version = "1.1.19" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c2e64a50a9cc8339f10a27577e10062c7f995488e469f2c95762c5ee847832" +checksum = "9b9a3f90e336ec74803e8eb98c61bc98754c1adfba3b4f84d946237b752b1c88" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -3640,9 +3667,9 @@ dependencies = [ [[package]] name = "sea-orm-migration" -version = "1.1.19" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7315c0cadb7e60fb17ee2bb282aa27d01911fc2a7e5836ec1d4ac37d19250bb4" +checksum = "07c577f2959277e936c1d08109acd1e08fc36a95ef29ec028190ba82cad8f96e" dependencies = [ "async-trait", "clap", @@ -3738,7 +3765,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ "bitcoin_hashes", - "rand 0.8.5", + "rand 0.8.6", "secp256k1-sys", "serde", ] @@ -3777,9 +3804,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" @@ -3836,9 +3863,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876ac351060d4f882bb1032b6369eb0aef79ad9df1ea8bc404874d8cc3d0cd98" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ "serde_core", ] @@ -3971,6 +3998,22 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "similar" version = "2.7.0" @@ -4104,7 +4147,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rustls 0.23.37", + "rustls 0.23.40", "serde", "serde_json", "sha2 0.10.9", @@ -4184,7 +4227,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rand 0.8.5", + "rand 0.8.6", "rsa", "serde", "sha1", @@ -4222,7 +4265,7 @@ dependencies = [ "md-5", "memchr", "once_cell", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_json", "sha2 0.10.9", @@ -4385,7 +4428,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.2", "once_cell", "rustix", "windows-sys 0.61.2", @@ -4451,9 +4494,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.45" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", @@ -4466,15 +4509,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.25" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -4482,9 +4525,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -4507,9 +4550,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.50.0" +version = "1.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" dependencies = [ "bytes", "libc", @@ -4522,9 +4565,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", @@ -4547,7 +4590,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.37", + "rustls 0.23.40", "tokio", ] @@ -4595,7 +4638,7 @@ checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ "indexmap", "serde_core", - "serde_spanned 1.1.0", + "serde_spanned 1.1.1", "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", @@ -4636,11 +4679,11 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.1.0+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.0", + "winnow 1.0.2", ] [[package]] @@ -4651,9 +4694,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "toml_writer" -version = "1.1.0+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d282ade6016312faf3e41e57ebbba0c073e4056dab1232ab1cb624199648f8ed" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "tower" @@ -4761,9 +4804,9 @@ checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "unicase" @@ -4852,9 +4895,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "serde_core", ] @@ -4898,11 +4941,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen 0.46.0", + "wit-bindgen 0.57.1", ] [[package]] @@ -4922,9 +4965,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.115" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6523d69017b7633e396a89c5efab138161ed5aafcbc8d3e5c5a42ae38f50495a" +checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" dependencies = [ "cfg-if", "once_cell", @@ -4936,9 +4979,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.65" +version = "0.4.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1faf851e778dfa54db7cd438b70758eba9755cb47403f3496edd7c8fc212f0" +checksum = "af934872acec734c2d80e6617bbb5ff4f12b052dd8e6332b0817bce889516084" dependencies = [ "js-sys", "wasm-bindgen", @@ -4946,9 +4989,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.115" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3a6c758eb2f701ed3d052ff5737f5bfe6614326ea7f3bbac7156192dc32e67" +checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4956,9 +4999,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.115" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "921de2737904886b52bcbb237301552d05969a6f9c40d261eb0533c8b055fedf" +checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" dependencies = [ "bumpalo", "proc-macro2", @@ -4969,9 +5012,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.115" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a93e946af942b58934c604527337bad9ae33ba1d5c6900bbb41c2c07c2364a93" +checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" dependencies = [ "unicode-ident", ] @@ -5012,9 +5055,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.92" +version = "0.3.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84cde8507f4d7cfcb1185b8cb5890c494ffea65edbe1ba82cfd63661c805ed94" +checksum = "2eadbac71025cd7b0834f20d1fe8472e8495821b4e9801eb0a60bd1f19827602" dependencies = [ "js-sys", "wasm-bindgen", @@ -5032,9 +5075,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" dependencies = [ "rustls-pki-types", ] @@ -5051,14 +5094,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.6", + "webpki-roots 1.0.7", ] [[package]] name = "webpki-roots" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ "rustls-pki-types", ] @@ -5174,15 +5217,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -5212,26 +5246,20 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.61.2" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-link", + "windows-targets 0.53.5", ] [[package]] -name = "windows-targets" -version = "0.42.2" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-link", ] [[package]] @@ -5258,7 +5286,7 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", @@ -5266,10 +5294,21 @@ dependencies = [ ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" +name = "windows-targets" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] [[package]] name = "windows_aarch64_gnullvm" @@ -5284,10 +5323,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" +name = "windows_aarch64_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -5302,10 +5341,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] -name = "windows_i686_gnu" -version = "0.42.2" +name = "windows_aarch64_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -5319,6 +5358,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" @@ -5326,10 +5371,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] -name = "windows_i686_msvc" -version = "0.42.2" +name = "windows_i686_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -5344,10 +5389,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" +name = "windows_i686_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -5362,10 +5407,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" +name = "windows_x86_64_gnu" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -5380,10 +5425,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" +name = "windows_x86_64_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -5397,6 +5442,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + [[package]] name = "winnow" version = "0.7.15" @@ -5408,15 +5459,9 @@ dependencies = [ [[package]] name = "winnow" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" - -[[package]] -name = "wit-bindgen" -version = "0.46.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" [[package]] name = "wit-bindgen" @@ -5427,6 +5472,12 @@ 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" @@ -5508,9 +5559,9 @@ dependencies = [ [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "yansi" @@ -5520,9 +5571,9 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[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", @@ -5531,9 +5582,9 @@ 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", "quote", @@ -5543,18 +5594,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.47" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.47" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", @@ -5563,18 +5614,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" 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", "quote", @@ -5590,9 +5641,9 @@ checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[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", @@ -5601,9 +5652,9 @@ 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 = [ "yoke", "zerofrom", @@ -5612,9 +5663,9 @@ 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", "quote", @@ -5623,9 +5674,9 @@ dependencies = [ [[package]] name = "zip" -version = "8.4.0" +version = "8.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7756d0206d058333667493c4014f545f4b9603c4330ccd6d9b3f86dcab59f7d9" +checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b" dependencies = [ "crc32fast", "indexmap", diff --git a/Cargo.toml b/Cargo.toml index 400a818c..ad28ca74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,15 +20,15 @@ members = [".", "migration"] base64 = { version = "0.22.1", default-features = false, features = [ "std", ] } -bdk_wallet = { version = "=2.0.0", default-features = false, features = [ +bdk_wallet = { version = "=3.0.0", default-features = false, features = [ "file_store", "keys-bip39", "std", ] } -bdk_electrum = { version = "0.23.0", optional = true, default-features = false, features = [ +bdk_electrum = { version = "0.23.2", optional = true, default-features = false, features = [ "use-rustls", ] } -bdk_esplora = { version = "0.22.0", optional = true, default-features = false, features = [ +bdk_esplora = { version = "0.22.2", optional = true, default-features = false, features = [ "blocking-https-rustls", ] } chacha20poly1305 = { version = "0.10.1", default-features = false, features = [ @@ -83,10 +83,10 @@ zip = { version = "8.4.0", default-features = false, features = [ # RGB-related deps amplify = { version = "=4.8.1", default-features = false } -rgb-invoicing = { version = "=0.11.1-rc.9", default-features = false } -rgb-psbt-utils = { version = "=0.11.1-rc.9", default-features = false } -rgb-schemas = { version = "=0.11.1-rc.9", default-features = false } -rgb-ops = { version = "=0.11.1-rc.9", default-features = false, features = [ +rgb-invoicing = { version = "=0.11.1-rc.10", default-features = false } +rgb-psbt-utils = { version = "=0.11.1-rc.10", default-features = false } +rgb-schemas = { version = "=0.11.1-rc.10", default-features = false } +rgb-ops = { version = "=0.11.1-rc.10", default-features = false, features = [ "serde", ] } rgb-strict-encoding = { version = "=1.0.1", default-features = false, features = [ diff --git a/bindings/c-ffi/Cargo.lock b/bindings/c-ffi/Cargo.lock index 1398aa57..29d430fe 100644 --- a/bindings/c-ffi/Cargo.lock +++ b/bindings/c-ffi/Cargo.lock @@ -56,7 +56,7 @@ dependencies = [ "amplify_num", "amplify_syn", "ascii", - "rand 0.8.5", + "rand 0.8.6", "serde", "stringly_conversions", "wasm-bindgen", @@ -248,9 +248,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-rs" -version = "1.16.2" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" dependencies = [ "aws-lc-sys", "zeroize", @@ -258,9 +258,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.39.1" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" +checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" dependencies = [ "cc", "cmake", @@ -362,9 +362,9 @@ dependencies = [ [[package]] name = "bdk_file_store" -version = "0.21.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446f02da319941ea78454a479fca72707f3355a62db3bb1c2c13b94e7f963ce0" +checksum = "c7b9a98edb58d02b601239832674a9ca9f1465e08e1dd1fac3a0e34004372406" dependencies = [ "bdk_core", "bincode", @@ -373,9 +373,9 @@ dependencies = [ [[package]] name = "bdk_wallet" -version = "2.0.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f278518ee6f2a17711fd4662dc34ce6153792a7a21575f05a9c8e2cb9ba36245" +checksum = "67f3c4f9526d22374fca5b7ff1d6bf8d921ab56db2dac8df66a2c5561b31d4ef" dependencies = [ "bdk_chain", "bdk_file_store", @@ -463,9 +463,9 @@ checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" [[package]] name = "bitcoin-units" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2" +checksum = "346568ebaab2918487cea76dd55dae13c27bb618cdb737c952e69eb2017c4118" dependencies = [ "bitcoin-internals", "serde", @@ -484,25 +484,25 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" dependencies = [ "serde_core", ] [[package]] name = "blake3" -version = "1.8.3" +version = "1.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2468ef7d57b3fb7e16b576e8377cdbde2320c60e1491e961d11da40fc4f02a2d" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "cpufeatures 0.2.17", + "cpufeatures 0.3.0", ] [[package]] @@ -559,9 +559,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.58" +version = "1.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ "find-msvc-tools", "jobserver", @@ -569,12 +569,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - [[package]] name = "cfg-if" version = "1.0.4" @@ -606,7 +600,7 @@ checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if", "cpufeatures 0.3.0", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -649,9 +643,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -671,9 +665,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -788,9 +782,9 @@ dependencies = [ [[package]] name = "crc-catalog" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" [[package]] name = "crc32fast" @@ -982,7 +976,7 @@ dependencies = [ "byteorder", "libc", "log", - "rustls 0.23.37", + "rustls 0.23.40", "serde", "serde_json", "webpki-roots 0.25.4", @@ -1067,9 +1061,9 @@ checksum = "a35a73237400bde66c82e38387343f90d7182a2f2f22729e096a2abd57d75db9" [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "file-format" @@ -1283,7 +1277,7 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "rand_core 0.10.0", + "rand_core 0.10.1", "wasip2", "wasip3", ] @@ -1347,9 +1341,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "hashlink" @@ -1419,11 +1413,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1467,9 +1461,9 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ "atomic-waker", "bytes", @@ -1481,7 +1475,6 @@ dependencies = [ "httparse", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -1489,15 +1482,14 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.7" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ "http", "hyper", "hyper-util", - "rustls 0.23.37", - "rustls-pki-types", + "rustls 0.23.40", "tokio", "tokio-rustls", "tower-service", @@ -1570,12 +1562,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", @@ -1583,9 +1576,9 @@ 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", @@ -1596,9 +1589,9 @@ dependencies = [ [[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", @@ -1610,15 +1603,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", @@ -1630,15 +1623,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", @@ -1674,9 +1667,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", @@ -1684,12 +1677,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] @@ -1722,9 +1715,9 @@ checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "iri-string" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e7418f59cc01c88316161279a7f665217ae316b388e58a0d10e29f54f1e5eb" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" dependencies = [ "memchr", "serde", @@ -1755,27 +1748,32 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jni" -version = "0.21.1" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" dependencies = [ - "cesu8", "cfg-if", "combine", - "jni-sys 0.3.1", + "jni-macros", + "jni-sys", "log", - "thiserror 1.0.69", + "simd_cesu8", + "thiserror 2.0.18", "walkdir", - "windows-sys 0.45.0", + "windows-link", ] [[package]] -name = "jni-sys" -version = "0.3.1" +name = "jni-macros" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" dependencies = [ - "jni-sys 0.4.1", + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.117", ] [[package]] @@ -1809,9 +1807,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.92" +version = "0.3.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc4c90f45aa2e6eacbe8645f77fdea542ac97a494bcd117a67df9ff4d611f995" +checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf" dependencies = [ "cfg-if", "futures-util", @@ -1836,9 +1834,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.183" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libm" @@ -1848,14 +1846,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ "bitflags", "libc", "plain", - "redox_syscall 0.7.3", + "redox_syscall 0.7.4", ] [[package]] @@ -1877,9 +1875,9 @@ 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 = "lock_api" @@ -1902,6 +1900,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "mac_address" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0aeb26bf5e836cc1c341c8106051b573f1766dfa05aa87f0b98be5e51b02303" +dependencies = [ + "nix", + "serde", + "winapi", +] + [[package]] name = "matchers" version = "0.2.0" @@ -1927,6 +1936,15 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.17" @@ -1945,9 +1963,9 @@ dependencies = [ [[package]] name = "miniscript" -version = "12.3.5" +version = "12.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487906208f38448e186e3deb02f2b8ef046a9078b0de00bdb28bf4fb9b76951c" +checksum = "c14116d8342edd3626b0f8e84df16f4e6a76dc04799ba747493403236a1b8ac5" dependencies = [ "bech32", "bitcoin", @@ -2002,6 +2020,19 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + [[package]] name = "nonasync" version = "0.1.3" @@ -2032,16 +2063,16 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "smallvec", "zeroize", ] [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" [[package]] name = "num-integer" @@ -2093,9 +2124,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.76" +version = "0.10.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" +checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" dependencies = [ "bitflags", "cfg-if", @@ -2125,18 +2156,18 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-src" -version = "300.5.1+3.5.1" +version = "300.6.0+3.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "735230c832b28c000e3bc117119e6466a663ec73506bc0a9907ea4187508e42a" +checksum = "a8e8cbfd3a4a8c8f089147fd7aaa33cf8c7450c4d09f8f80698a0cf093abeff4" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.112" +version = "0.9.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" +checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" dependencies = [ "cc", "libc", @@ -2277,12 +2308,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "pkcs1" version = "0.7.5" @@ -2306,9 +2331,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plain" @@ -2329,9 +2354,9 @@ 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", ] @@ -2417,7 +2442,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.37", + "rustls 0.23.40", "socket2", "thiserror 2.0.18", "tokio", @@ -2435,10 +2460,10 @@ dependencies = [ "bytes", "getrandom 0.3.4", "lru-slab", - "rand 0.9.2", + "rand 0.9.4", "ring", "rustc-hash", - "rustls 0.23.37", + "rustls 0.23.40", "rustls-pki-types", "slab", "thiserror 2.0.18", @@ -2484,9 +2509,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[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", @@ -2495,9 +2520,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -2505,13 +2530,13 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "chacha20 0.10.0", "getrandom 0.4.2", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -2554,9 +2579,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "redox_syscall" @@ -2569,9 +2594,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" +checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" dependencies = [ "bitflags", ] @@ -2627,9 +2652,9 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" dependencies = [ "base64 0.22.1", "bytes", @@ -2653,7 +2678,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.37", + "rustls 0.23.40", "rustls-pki-types", "rustls-platform-verifier", "serde", @@ -2673,9 +2698,9 @@ dependencies = [ [[package]] name = "rgb-aluvm" -version = "0.11.1-rc.2" +version = "0.11.1-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b9e41006564b48551e52e001181898982b11732348100216097033b3e536a2" +checksum = "b60686e4f1701ca4f73b77660777a49e651f3c611461ab62ef718db47a5a6caa" dependencies = [ "amplify", "baid64", @@ -2707,9 +2732,9 @@ dependencies = [ [[package]] name = "rgb-consensus" -version = "0.11.1-rc.9" +version = "0.11.1-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6e0da534613ed77953976b9be54c7db66bd5a6c66773bd5866b1bacdbfb41d" +checksum = "535483ee9143782e33ddebd3eda465de0184061fc3c480e24990e42fefc58bb0" dependencies = [ "amplify", "baid64", @@ -2721,7 +2746,7 @@ dependencies = [ "getrandom 0.3.4", "hex-conservative", "mime", - "rand 0.9.2", + "rand 0.9.4", "rgb-aluvm", "rgb-strict-encoding", "rgb-strict-types", @@ -2734,9 +2759,9 @@ dependencies = [ [[package]] name = "rgb-invoicing" -version = "0.11.1-rc.9" +version = "0.11.1-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22f7125c70fd8e959d85d29c0bdbeecb173d6aed9a72eae71f1e43bade383f" +checksum = "10400124af86de579b0f13603e014512b6166ad94ea791212b71579ffb91dd8a" dependencies = [ "amplify", "baid64", @@ -2744,7 +2769,7 @@ dependencies = [ "fluent-uri", "indexmap", "percent-encoding", - "rand 0.9.2", + "rand 0.9.4", "rgb-consensus", "rgb-strict-encoding", "rgb-strict-types", @@ -2764,7 +2789,7 @@ dependencies = [ "file-format", "generic-array", "hex", - "rand 0.10.0", + "rand 0.10.1", "reqwest", "rgb-invoicing", "rgb-lib-migration", @@ -2773,7 +2798,7 @@ dependencies = [ "rgb-schemas", "rgb-strict-encoding", "rgb-strict-types", - "rustls 0.23.37", + "rustls 0.23.40", "scrypt", "sea-orm", "sea-query", @@ -2813,9 +2838,9 @@ dependencies = [ [[package]] name = "rgb-ops" -version = "0.11.1-rc.9" +version = "0.11.1-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb298dfc6cddd4367c850bf621fca6b2b77a16c2ce472bc4e576811fe5b29be" +checksum = "3782a5ff1e5408e23c2d14fc556347684f5c8f72d96c4ca357527a3dbffb7378" dependencies = [ "amplify", "baid64", @@ -2826,7 +2851,7 @@ dependencies = [ "getrandom 0.3.4", "indexmap", "nonasync", - "rand 0.9.2", + "rand 0.9.4", "rgb-aluvm", "rgb-ascii-armor", "rgb-consensus", @@ -2834,14 +2859,15 @@ dependencies = [ "rgb-strict-encoding", "rgb-strict-types", "serde", + "serde_json", "wasm-bindgen", ] [[package]] name = "rgb-psbt-utils" -version = "0.11.1-rc.9" +version = "0.11.1-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9faab66bd883c85ffcb35f8dfa9d676184c5924f5076ffd9c72943bdf5b3df3c" +checksum = "0107634634c424a8b268ec6549df08da676768ec6ddbcda51f12e7882daeeee6" dependencies = [ "amplify", "baid64", @@ -2854,9 +2880,9 @@ dependencies = [ [[package]] name = "rgb-schemas" -version = "0.11.1-rc.9" +version = "0.11.1-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a80e2f45e850293c97d0e4fcd9b1c066a666b52b66617f4476365346c92111" +checksum = "1903961c836cc3f6963b06c69cb47491a815309f265439f20c932e0a3aa16a78" dependencies = [ "amplify", "rgb-aluvm", @@ -3006,16 +3032,16 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.37" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.10", + "rustls-webpki 0.103.13", "subtle", "zeroize", ] @@ -3034,9 +3060,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ "web-time", "zeroize", @@ -3044,19 +3070,19 @@ dependencies = [ [[package]] name = "rustls-platform-verifier" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ "core-foundation 0.10.1", "core-foundation-sys", "jni", "log", "once_cell", - "rustls 0.23.37", + "rustls 0.23.40", "rustls-native-certs", "rustls-platform-verifier-android", - "rustls-webpki 0.103.10", + "rustls-webpki 0.103.13", "security-framework", "security-framework-sys", "webpki-root-certs", @@ -3081,9 +3107,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.10" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "aws-lc-rs", "ring", @@ -3173,9 +3199,9 @@ dependencies = [ [[package]] name = "sea-orm" -version = "1.1.19" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d945f62558fac19e5988680d2fdf747b734c2dbc6ce2cb81ba33ed8dde5b103" +checksum = "2dc312fedd460a47ea563911761d254a84e7b51d8cc73ec92c929e78f33fa957" dependencies = [ "async-stream", "async-trait", @@ -3184,6 +3210,7 @@ dependencies = [ "derive_more", "futures-util", "log", + "mac_address", "ouroboros", "pgvector", "rust_decimal", @@ -3203,9 +3230,9 @@ dependencies = [ [[package]] name = "sea-orm-cli" -version = "1.1.19" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94492e2ab6c045b4cc38013809ce255d14c3d352c9f0d11e6b920e2adc948ad" +checksum = "da80ebcdb44571e86f03a2bdcb5532136a87397f366f38bbce64673fc5e6a450" dependencies = [ "chrono", "clap", @@ -3222,9 +3249,9 @@ dependencies = [ [[package]] name = "sea-orm-macros" -version = "1.1.19" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c2e64a50a9cc8339f10a27577e10062c7f995488e469f2c95762c5ee847832" +checksum = "9b9a3f90e336ec74803e8eb98c61bc98754c1adfba3b4f84d946237b752b1c88" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -3236,9 +3263,9 @@ dependencies = [ [[package]] name = "sea-orm-migration" -version = "1.1.19" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7315c0cadb7e60fb17ee2bb282aa27d01911fc2a7e5836ec1d4ac37d19250bb4" +checksum = "07c577f2959277e936c1d08109acd1e08fc36a95ef29ec028190ba82cad8f96e" dependencies = [ "async-trait", "clap", @@ -3319,7 +3346,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ "bitcoin_hashes", - "rand 0.8.5", + "rand 0.8.6", "secp256k1-sys", "serde", ] @@ -3358,9 +3385,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" @@ -3417,9 +3444,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876ac351060d4f882bb1032b6369eb0aef79ad9df1ea8bc404874d8cc3d0cd98" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ "serde_core", ] @@ -3506,6 +3533,22 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "slab" version = "0.4.12" @@ -3624,7 +3667,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rustls 0.23.37", + "rustls 0.23.40", "serde", "serde_json", "sha2", @@ -3704,7 +3747,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rand 0.8.5", + "rand 0.8.6", "rsa", "serde", "sha1", @@ -3742,7 +3785,7 @@ dependencies = [ "md-5", "memchr", "once_cell", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_json", "sha2", @@ -3971,9 +4014,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.45" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", @@ -3986,15 +4029,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.25" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -4002,9 +4045,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -4027,9 +4070,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.50.0" +version = "1.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" dependencies = [ "bytes", "libc", @@ -4042,9 +4085,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", @@ -4067,7 +4110,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.37", + "rustls 0.23.40", "tokio", ] @@ -4115,7 +4158,7 @@ checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ "indexmap", "serde_core", - "serde_spanned 1.1.0", + "serde_spanned 1.1.1", "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", @@ -4156,11 +4199,11 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.1.0+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.0", + "winnow 1.0.2", ] [[package]] @@ -4171,9 +4214,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "toml_writer" -version = "1.1.0+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d282ade6016312faf3e41e57ebbba0c073e4056dab1232ab1cb624199648f8ed" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "tower" @@ -4281,9 +4324,9 @@ checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "unicase" @@ -4372,9 +4415,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "serde_core", ] @@ -4418,11 +4461,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen 0.46.0", + "wit-bindgen 0.57.1", ] [[package]] @@ -4442,9 +4485,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.115" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6523d69017b7633e396a89c5efab138161ed5aafcbc8d3e5c5a42ae38f50495a" +checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" dependencies = [ "cfg-if", "once_cell", @@ -4456,9 +4499,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.65" +version = "0.4.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1faf851e778dfa54db7cd438b70758eba9755cb47403f3496edd7c8fc212f0" +checksum = "af934872acec734c2d80e6617bbb5ff4f12b052dd8e6332b0817bce889516084" dependencies = [ "js-sys", "wasm-bindgen", @@ -4466,9 +4509,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.115" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3a6c758eb2f701ed3d052ff5737f5bfe6614326ea7f3bbac7156192dc32e67" +checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4476,9 +4519,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.115" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "921de2737904886b52bcbb237301552d05969a6f9c40d261eb0533c8b055fedf" +checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" dependencies = [ "bumpalo", "proc-macro2", @@ -4489,9 +4532,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.115" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a93e946af942b58934c604527337bad9ae33ba1d5c6900bbb41c2c07c2364a93" +checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" dependencies = [ "unicode-ident", ] @@ -4532,9 +4575,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.92" +version = "0.3.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84cde8507f4d7cfcb1185b8cb5890c494ffea65edbe1ba82cfd63661c805ed94" +checksum = "2eadbac71025cd7b0834f20d1fe8472e8495821b4e9801eb0a60bd1f19827602" dependencies = [ "js-sys", "wasm-bindgen", @@ -4552,9 +4595,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" dependencies = [ "rustls-pki-types", ] @@ -4571,14 +4614,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.6", + "webpki-roots 1.0.7", ] [[package]] name = "webpki-roots" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ "rustls-pki-types", ] @@ -4694,15 +4737,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -4721,15 +4755,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.60.2" @@ -4748,21 +4773,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-targets" version = "0.48.5" @@ -4811,12 +4821,6 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -4835,12 +4839,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -4859,12 +4857,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -4895,12 +4887,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -4919,12 +4905,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -4943,12 +4923,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -4967,12 +4941,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -5002,15 +4970,9 @@ dependencies = [ [[package]] name = "winnow" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" - -[[package]] -name = "wit-bindgen" -version = "0.46.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" [[package]] name = "wit-bindgen" @@ -5021,6 +4983,12 @@ 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" @@ -5102,9 +5070,9 @@ dependencies = [ [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "yansi" @@ -5114,9 +5082,9 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[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", @@ -5125,9 +5093,9 @@ 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", "quote", @@ -5137,18 +5105,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.47" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.47" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", @@ -5157,18 +5125,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" 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", "quote", @@ -5184,9 +5152,9 @@ checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[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", @@ -5195,9 +5163,9 @@ 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 = [ "yoke", "zerofrom", @@ -5206,9 +5174,9 @@ 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", "quote", @@ -5217,9 +5185,9 @@ dependencies = [ [[package]] name = "zip" -version = "8.4.0" +version = "8.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7756d0206d058333667493c4014f545f4b9603c4330ccd6d9b3f86dcab59f7d9" +checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b" dependencies = [ "crc32fast", "indexmap", diff --git a/bindings/c-ffi/example.c b/bindings/c-ffi/example.c index 5dd19979..d05bda8c 100644 --- a/bindings/c-ffi/example.c +++ b/bindings/c-ffi/example.c @@ -163,7 +163,8 @@ int main() { return EXIT_FAILURE; } - CResultString sync_res = rgblib_sync(wlt, online); + CResultString sync_res = rgblib_sync( + wlt, online, "{\"keychain\":\"Colored\",\"type\":\"FullSync\"}"); if (sync_res.result == Ok) { printf("Synced\n"); } else { diff --git a/bindings/c-ffi/src/lib.rs b/bindings/c-ffi/src/lib.rs index c945fb64..fc2c8eb5 100644 --- a/bindings/c-ffi/src/lib.rs +++ b/bindings/c-ffi/src/lib.rs @@ -16,8 +16,8 @@ use rgb_lib::{ keys::WitnessVersion, utils::BitcoinNetwork, wallet::{ - Online, Recipient, RefreshFilter, RgbWalletOpsOffline, RgbWalletOpsOnline, SinglesigKeys, - Wallet, WalletData, + Online, OnlineOptions, Recipient, RefreshFilter, RgbWalletOpsOffline, RgbWalletOpsOnline, + SinglesigKeys, SyncOptions, Wallet, WalletData, }, }; @@ -66,6 +66,57 @@ pub extern "C" fn rgblib_backup_info(wallet: &COpaqueStruct) -> CResultString { backup_info(wallet).into() } +#[unsafe(no_mangle)] +pub extern "C" fn rgblib_burn( + wallet: &COpaqueStruct, + online: *const c_char, + asset_id: *const c_char, + amount: *const c_char, + fee_rate: *const c_char, + min_confirmations: *const c_char, +) -> CResultString { + burn( + wallet, + online, + asset_id, + amount, + fee_rate, + min_confirmations, + ) + .into() +} + +#[unsafe(no_mangle)] +pub extern "C" fn rgblib_burn_begin( + wallet: &COpaqueStruct, + online: *const c_char, + asset_id: *const c_char, + amount: *const c_char, + fee_rate: *const c_char, + min_confirmations: *const c_char, + dry_run: bool, +) -> CResultString { + burn_begin( + wallet, + online, + asset_id, + amount, + fee_rate, + min_confirmations, + dry_run, + ) + .into() +} + +#[unsafe(no_mangle)] +pub extern "C" fn rgblib_burn_end( + wallet: &COpaqueStruct, + online: *const c_char, + signed_psbt: *const c_char, +) -> CResultString { + burn_end(wallet, online, signed_psbt).into() +} + #[unsafe(no_mangle)] pub extern "C" fn rgblib_blind_receive( wallet: &COpaqueStruct, @@ -124,9 +175,8 @@ pub extern "C" fn rgblib_create_utxos_end( wallet: &COpaqueStruct, online: *const c_char, signed_psbt: *const c_char, - skip_sync: bool, ) -> CResultString { - create_utxos_end(wallet, online, signed_psbt, skip_sync).into() + create_utxos_end(wallet, online, signed_psbt).into() } #[unsafe(no_mangle)] @@ -214,10 +264,9 @@ pub extern "C" fn rgblib_get_fee_estimation( #[unsafe(no_mangle)] pub extern "C" fn rgblib_go_online( wallet: &COpaqueStruct, - skip_consistency_check: bool, - electrum_url: *const c_char, + online_options: *const c_char, ) -> CResultString { - go_online(wallet, skip_consistency_check, electrum_url).into() + go_online(wallet, online_options).into() } #[unsafe(no_mangle)] @@ -390,7 +439,6 @@ pub extern "C" fn rgblib_send( fee_rate: *const c_char, min_confirmations: *const c_char, expiration_timestamp_opt: *const c_char, - skip_sync: bool, ) -> CResultString { send( wallet, @@ -400,7 +448,6 @@ pub extern "C" fn rgblib_send( fee_rate, min_confirmations, expiration_timestamp_opt, - skip_sync, ) .into() } @@ -446,9 +493,8 @@ pub extern "C" fn rgblib_send_end( wallet: &COpaqueStruct, online: *const c_char, signed_psbt: *const c_char, - skip_sync: bool, ) -> CResultString { - send_end(wallet, online, signed_psbt, skip_sync).into() + send_end(wallet, online, signed_psbt).into() } #[unsafe(no_mangle)] @@ -460,8 +506,12 @@ pub extern "C" fn rgblib_sign_psbt( } #[unsafe(no_mangle)] -pub extern "C" fn rgblib_sync(wallet: &COpaqueStruct, online: *const c_char) -> CResultString { - sync(wallet, online).into() +pub extern "C" fn rgblib_sync( + wallet: &COpaqueStruct, + online: *const c_char, + options: *const c_char, +) -> CResultString { + sync(wallet, online, options).into() } #[unsafe(no_mangle)] diff --git a/bindings/c-ffi/src/utils.rs b/bindings/c-ffi/src/utils.rs index 1a07412c..eef4a1d3 100644 --- a/bindings/c-ffi/src/utils.rs +++ b/bindings/c-ffi/src/utils.rs @@ -185,6 +185,62 @@ pub(crate) fn backup_info(wallet: &COpaqueStruct) -> Result { Ok(serde_json::to_string(&res)?) } +pub(crate) fn burn( + wallet: &COpaqueStruct, + online: *const c_char, + asset_id: *const c_char, + amount: *const c_char, + fee_rate: *const c_char, + min_confirmations: *const c_char, +) -> Result { + let wallet = Wallet::from_opaque(wallet)?; + let online = convert_online(online)?; + let asset_id = ptr_to_string(asset_id); + let amount = ptr_to_num(amount)?; + let fee_rate = ptr_to_num(fee_rate)?; + let min_confirmations = ptr_to_num(min_confirmations)?; + let res = wallet.burn(online, asset_id, amount, fee_rate, min_confirmations)?; + Ok(serde_json::to_string(&res)?) +} + +pub(crate) fn burn_begin( + wallet: &COpaqueStruct, + online: *const c_char, + asset_id: *const c_char, + amount: *const c_char, + fee_rate: *const c_char, + min_confirmations: *const c_char, + dry_run: bool, +) -> Result { + let wallet = Wallet::from_opaque(wallet)?; + let online = convert_online(online)?; + let asset_id = ptr_to_string(asset_id); + let amount = ptr_to_num(amount)?; + let fee_rate = ptr_to_num(fee_rate)?; + let min_confirmations = ptr_to_num(min_confirmations)?; + let res = wallet.burn_begin( + online, + asset_id, + amount, + fee_rate, + min_confirmations, + dry_run, + )?; + Ok(serde_json::to_string(&res)?) +} + +pub(crate) fn burn_end( + wallet: &COpaqueStruct, + online: *const c_char, + signed_psbt: *const c_char, +) -> Result { + let wallet = Wallet::from_opaque(wallet)?; + let online = convert_online(online)?; + let signed_psbt = ptr_to_string(signed_psbt); + let res = wallet.burn_end(online, signed_psbt)?; + Ok(serde_json::to_string(&res)?) +} + pub(crate) fn blind_receive( wallet: &COpaqueStruct, asset_id_opt: *const c_char, @@ -252,12 +308,11 @@ pub(crate) fn create_utxos_end( wallet: &COpaqueStruct, online: *const c_char, signed_psbt: *const c_char, - skip_sync: bool, ) -> Result { let wallet = Wallet::from_opaque(wallet)?; let online = convert_online(online)?; let signed_psbt = ptr_to_string(signed_psbt); - let res = wallet.create_utxos_end(online, signed_psbt, skip_sync)?; + let res = wallet.create_utxos_end(online, signed_psbt)?; Ok(serde_json::to_string(&res)?) } @@ -355,11 +410,11 @@ pub(crate) fn get_fee_estimation( pub(crate) fn go_online( wallet: &COpaqueStruct, - skip_consistency_check: bool, - electrum_url: *const c_char, + online_options: *const c_char, ) -> Result { let wallet = Wallet::from_opaque(wallet)?; - let res = wallet.go_online(skip_consistency_check, ptr_to_string(electrum_url))?; + let online_options: OnlineOptions = serde_json::from_str(&ptr_to_string(online_options))?; + let res = wallet.go_online(online_options)?; Ok(serde_json::to_string(&res)?) } @@ -581,7 +636,6 @@ pub(crate) fn send( fee_rate: *const c_char, min_confirmations: *const c_char, expiration_timestamp_opt: *const c_char, - skip_sync: bool, ) -> Result { let wallet = Wallet::from_opaque(wallet)?; let online = convert_online(online)?; @@ -597,7 +651,6 @@ pub(crate) fn send( fee_rate, min_confirmations, expiration_timestamp, - skip_sync, )?; Ok(serde_json::to_string(&res)?) } @@ -653,12 +706,11 @@ pub(crate) fn send_end( wallet: &COpaqueStruct, online: *const c_char, signed_psbt: *const c_char, - skip_sync: bool, ) -> Result { let wallet = Wallet::from_opaque(wallet)?; let online = convert_online(online)?; let signed_psbt = ptr_to_string(signed_psbt); - let res = wallet.send_end(online, signed_psbt, skip_sync)?; + let res = wallet.send_end(online, signed_psbt)?; Ok(serde_json::to_string(&res)?) } @@ -671,10 +723,15 @@ pub(crate) fn sign_psbt( Ok(wallet.sign_psbt(unsigned_psbt, None)?) } -pub(crate) fn sync(wallet: &COpaqueStruct, online: *const c_char) -> Result<(), Error> { +pub(crate) fn sync( + wallet: &COpaqueStruct, + online: *const c_char, + options: *const c_char, +) -> Result<(), Error> { let wallet = Wallet::from_opaque(wallet)?; let online = convert_online(online)?; - wallet.sync(online)?; + let options: SyncOptions = serde_json::from_str(&ptr_to_string(options))?; + wallet.sync(online, options)?; Ok(()) } diff --git a/bindings/uniffi/Cargo.lock b/bindings/uniffi/Cargo.lock index 25b46afd..8f5f8188 100644 --- a/bindings/uniffi/Cargo.lock +++ b/bindings/uniffi/Cargo.lock @@ -56,7 +56,7 @@ dependencies = [ "amplify_num", "amplify_syn", "ascii", - "rand 0.8.5", + "rand 0.8.6", "serde", "stringly_conversions", "wasm-bindgen", @@ -290,9 +290,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-fips-sys" -version = "0.13.13" +version = "0.13.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bce4948d2520386c6d92a6ea2d472300257702242e5a1d01d6add52bd2e7c1" +checksum = "d3d619165468401dec3caa3366ebffbcb83f2f31883e5b3932f8e2dec2ddc568" dependencies = [ "bindgen", "cc", @@ -304,9 +304,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.16.2" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" dependencies = [ "aws-lc-fips-sys", "aws-lc-sys", @@ -315,9 +315,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.39.1" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" +checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" dependencies = [ "bindgen", "cc", @@ -429,9 +429,9 @@ dependencies = [ [[package]] name = "bdk_file_store" -version = "0.21.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446f02da319941ea78454a479fca72707f3355a62db3bb1c2c13b94e7f963ce0" +checksum = "c7b9a98edb58d02b601239832674a9ca9f1465e08e1dd1fac3a0e34004372406" dependencies = [ "bdk_core", "bincode", @@ -440,9 +440,9 @@ dependencies = [ [[package]] name = "bdk_wallet" -version = "2.0.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f278518ee6f2a17711fd4662dc34ce6153792a7a21575f05a9c8e2cb9ba36245" +checksum = "67f3c4f9526d22374fca5b7ff1d6bf8d921ab56db2dac8df66a2c5561b31d4ef" dependencies = [ "bdk_chain", "bdk_file_store", @@ -550,9 +550,9 @@ checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" [[package]] name = "bitcoin-units" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2" +checksum = "346568ebaab2918487cea76dd55dae13c27bb618cdb737c952e69eb2017c4118" dependencies = [ "bitcoin-internals", "serde", @@ -571,25 +571,25 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" dependencies = [ "serde_core", ] [[package]] name = "blake3" -version = "1.8.3" +version = "1.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2468ef7d57b3fb7e16b576e8377cdbde2320c60e1491e961d11da40fc4f02a2d" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "cpufeatures 0.2.17", + "cpufeatures 0.3.0", ] [[package]] @@ -633,9 +633,9 @@ checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" [[package]] name = "cc" -version = "1.2.58" +version = "1.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ "find-msvc-tools", "jobserver", @@ -643,12 +643,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - [[package]] name = "cexpr" version = "0.6.0" @@ -689,7 +683,7 @@ checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if", "cpufeatures 0.3.0", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -743,9 +737,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -765,9 +759,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -882,9 +876,9 @@ dependencies = [ [[package]] name = "crc-catalog" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" [[package]] name = "crc32fast" @@ -1076,7 +1070,7 @@ dependencies = [ "byteorder", "libc", "log", - "rustls 0.23.37", + "rustls 0.23.40", "serde", "serde_json", "webpki-roots 0.25.4", @@ -1161,9 +1155,9 @@ checksum = "a35a73237400bde66c82e38387343f90d7182a2f2f22729e096a2abd57d75db9" [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "file-format" @@ -1386,7 +1380,7 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "rand_core 0.10.0", + "rand_core 0.10.1", "wasip2", "wasip3", ] @@ -1461,9 +1455,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "hashlink" @@ -1533,11 +1527,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1581,9 +1575,9 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ "atomic-waker", "bytes", @@ -1595,7 +1589,6 @@ dependencies = [ "httparse", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -1603,15 +1596,14 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.7" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ "http", "hyper", "hyper-util", - "rustls 0.23.37", - "rustls-pki-types", + "rustls 0.23.40", "tokio", "tokio-rustls", "tower-service", @@ -1684,12 +1676,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", @@ -1697,9 +1690,9 @@ 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", @@ -1710,9 +1703,9 @@ dependencies = [ [[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", @@ -1724,15 +1717,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", @@ -1744,15 +1737,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", @@ -1788,9 +1781,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", @@ -1798,12 +1791,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] @@ -1836,9 +1829,9 @@ checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "iri-string" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e7418f59cc01c88316161279a7f665217ae316b388e58a0d10e29f54f1e5eb" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" dependencies = [ "memchr", "serde", @@ -1878,27 +1871,32 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jni" -version = "0.21.1" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" dependencies = [ - "cesu8", "cfg-if", "combine", - "jni-sys 0.3.1", + "jni-macros", + "jni-sys", "log", - "thiserror 1.0.69", + "simd_cesu8", + "thiserror 2.0.18", "walkdir", - "windows-sys 0.45.0", + "windows-link", ] [[package]] -name = "jni-sys" -version = "0.3.1" +name = "jni-macros" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" dependencies = [ - "jni-sys 0.4.1", + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.117", ] [[package]] @@ -1932,9 +1930,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.92" +version = "0.3.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc4c90f45aa2e6eacbe8645f77fdea542ac97a494bcd117a67df9ff4d611f995" +checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf" dependencies = [ "cfg-if", "futures-util", @@ -1959,9 +1957,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.183" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libloading" @@ -1981,14 +1979,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ "bitflags", "libc", "plain", - "redox_syscall 0.7.3", + "redox_syscall 0.7.4", ] [[package]] @@ -2010,9 +2008,9 @@ 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 = "lock_api" @@ -2035,6 +2033,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "mac_address" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0aeb26bf5e836cc1c341c8106051b573f1766dfa05aa87f0b98be5e51b02303" +dependencies = [ + "nix", + "serde", + "winapi", +] + [[package]] name = "matchers" version = "0.2.0" @@ -2060,6 +2069,15 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.17" @@ -2084,9 +2102,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniscript" -version = "12.3.5" +version = "12.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487906208f38448e186e3deb02f2b8ef046a9078b0de00bdb28bf4fb9b76951c" +checksum = "c14116d8342edd3626b0f8e84df16f4e6a76dc04799ba747493403236a1b8ac5" dependencies = [ "bech32", "bitcoin", @@ -2141,6 +2159,19 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + [[package]] name = "nom" version = "7.1.3" @@ -2181,16 +2212,16 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "smallvec", "zeroize", ] [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" [[package]] name = "num-integer" @@ -2242,9 +2273,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.76" +version = "0.10.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" +checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" dependencies = [ "bitflags", "cfg-if", @@ -2274,18 +2305,18 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-src" -version = "300.5.1+3.5.1" +version = "300.6.0+3.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "735230c832b28c000e3bc117119e6466a663ec73506bc0a9907ea4187508e42a" +checksum = "a8e8cbfd3a4a8c8f089147fd7aaa33cf8c7450c4d09f8f80698a0cf093abeff4" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.112" +version = "0.9.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" +checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" dependencies = [ "cc", "libc", @@ -2426,12 +2457,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "pkcs1" version = "0.7.5" @@ -2455,9 +2480,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plain" @@ -2478,9 +2503,9 @@ 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", ] @@ -2566,7 +2591,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.37", + "rustls 0.23.40", "socket2", "thiserror 2.0.18", "tokio", @@ -2584,10 +2609,10 @@ dependencies = [ "bytes", "getrandom 0.3.4", "lru-slab", - "rand 0.9.2", + "rand 0.9.4", "ring", "rustc-hash", - "rustls 0.23.37", + "rustls 0.23.40", "rustls-pki-types", "slab", "thiserror 2.0.18", @@ -2607,7 +2632,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -2633,9 +2658,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[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", @@ -2644,9 +2669,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -2654,13 +2679,13 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "chacha20 0.10.0", "getrandom 0.4.2", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -2703,9 +2728,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "redox_syscall" @@ -2718,9 +2743,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" +checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" dependencies = [ "bitflags", ] @@ -2776,9 +2801,9 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" dependencies = [ "base64 0.22.1", "bytes", @@ -2802,7 +2827,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.37", + "rustls 0.23.40", "rustls-pki-types", "rustls-platform-verifier", "serde", @@ -2822,9 +2847,9 @@ dependencies = [ [[package]] name = "rgb-aluvm" -version = "0.11.1-rc.2" +version = "0.11.1-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b9e41006564b48551e52e001181898982b11732348100216097033b3e536a2" +checksum = "b60686e4f1701ca4f73b77660777a49e651f3c611461ab62ef718db47a5a6caa" dependencies = [ "amplify", "baid64", @@ -2856,9 +2881,9 @@ dependencies = [ [[package]] name = "rgb-consensus" -version = "0.11.1-rc.9" +version = "0.11.1-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6e0da534613ed77953976b9be54c7db66bd5a6c66773bd5866b1bacdbfb41d" +checksum = "535483ee9143782e33ddebd3eda465de0184061fc3c480e24990e42fefc58bb0" dependencies = [ "amplify", "baid64", @@ -2870,7 +2895,7 @@ dependencies = [ "getrandom 0.3.4", "hex-conservative", "mime", - "rand 0.9.2", + "rand 0.9.4", "rgb-aluvm", "rgb-strict-encoding", "rgb-strict-types", @@ -2883,9 +2908,9 @@ dependencies = [ [[package]] name = "rgb-invoicing" -version = "0.11.1-rc.9" +version = "0.11.1-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22f7125c70fd8e959d85d29c0bdbeecb173d6aed9a72eae71f1e43bade383f" +checksum = "10400124af86de579b0f13603e014512b6166ad94ea791212b71579ffb91dd8a" dependencies = [ "amplify", "baid64", @@ -2893,7 +2918,7 @@ dependencies = [ "fluent-uri", "indexmap", "percent-encoding", - "rand 0.9.2", + "rand 0.9.4", "rgb-consensus", "rgb-strict-encoding", "rgb-strict-types", @@ -2913,7 +2938,7 @@ dependencies = [ "file-format", "generic-array", "hex", - "rand 0.10.0", + "rand 0.10.1", "reqwest", "rgb-invoicing", "rgb-lib-migration", @@ -2922,7 +2947,7 @@ dependencies = [ "rgb-schemas", "rgb-strict-encoding", "rgb-strict-types", - "rustls 0.23.37", + "rustls 0.23.40", "scrypt", "sea-orm", "sea-query", @@ -2960,9 +2985,9 @@ dependencies = [ [[package]] name = "rgb-ops" -version = "0.11.1-rc.9" +version = "0.11.1-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb298dfc6cddd4367c850bf621fca6b2b77a16c2ce472bc4e576811fe5b29be" +checksum = "3782a5ff1e5408e23c2d14fc556347684f5c8f72d96c4ca357527a3dbffb7378" dependencies = [ "amplify", "baid64", @@ -2973,7 +2998,7 @@ dependencies = [ "getrandom 0.3.4", "indexmap", "nonasync", - "rand 0.9.2", + "rand 0.9.4", "rgb-aluvm", "rgb-ascii-armor", "rgb-consensus", @@ -2981,14 +3006,15 @@ dependencies = [ "rgb-strict-encoding", "rgb-strict-types", "serde", + "serde_json", "wasm-bindgen", ] [[package]] name = "rgb-psbt-utils" -version = "0.11.1-rc.9" +version = "0.11.1-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9faab66bd883c85ffcb35f8dfa9d676184c5924f5076ffd9c72943bdf5b3df3c" +checksum = "0107634634c424a8b268ec6549df08da676768ec6ddbcda51f12e7882daeeee6" dependencies = [ "amplify", "baid64", @@ -3001,9 +3027,9 @@ dependencies = [ [[package]] name = "rgb-schemas" -version = "0.11.1-rc.9" +version = "0.11.1-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a80e2f45e850293c97d0e4fcd9b1c066a666b52b66617f4476365346c92111" +checksum = "1903961c836cc3f6963b06c69cb47491a815309f265439f20c932e0a3aa16a78" dependencies = [ "amplify", "rgb-aluvm", @@ -3153,16 +3179,16 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.37" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.10", + "rustls-webpki 0.103.13", "subtle", "zeroize", ] @@ -3181,9 +3207,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ "web-time", "zeroize", @@ -3191,23 +3217,23 @@ dependencies = [ [[package]] name = "rustls-platform-verifier" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ "core-foundation 0.10.1", "core-foundation-sys", "jni", "log", "once_cell", - "rustls 0.23.37", + "rustls 0.23.40", "rustls-native-certs", "rustls-platform-verifier-android", - "rustls-webpki 0.103.10", + "rustls-webpki 0.103.13", "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3228,9 +3254,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.10" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "aws-lc-rs", "ring", @@ -3340,9 +3366,9 @@ dependencies = [ [[package]] name = "sea-orm" -version = "1.1.19" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d945f62558fac19e5988680d2fdf747b734c2dbc6ce2cb81ba33ed8dde5b103" +checksum = "2dc312fedd460a47ea563911761d254a84e7b51d8cc73ec92c929e78f33fa957" dependencies = [ "async-stream", "async-trait", @@ -3351,6 +3377,7 @@ dependencies = [ "derive_more", "futures-util", "log", + "mac_address", "ouroboros", "pgvector", "rust_decimal", @@ -3370,9 +3397,9 @@ dependencies = [ [[package]] name = "sea-orm-cli" -version = "1.1.19" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94492e2ab6c045b4cc38013809ce255d14c3d352c9f0d11e6b920e2adc948ad" +checksum = "da80ebcdb44571e86f03a2bdcb5532136a87397f366f38bbce64673fc5e6a450" dependencies = [ "chrono", "clap", @@ -3389,9 +3416,9 @@ dependencies = [ [[package]] name = "sea-orm-macros" -version = "1.1.19" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c2e64a50a9cc8339f10a27577e10062c7f995488e469f2c95762c5ee847832" +checksum = "9b9a3f90e336ec74803e8eb98c61bc98754c1adfba3b4f84d946237b752b1c88" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -3403,9 +3430,9 @@ dependencies = [ [[package]] name = "sea-orm-migration" -version = "1.1.19" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7315c0cadb7e60fb17ee2bb282aa27d01911fc2a7e5836ec1d4ac37d19250bb4" +checksum = "07c577f2959277e936c1d08109acd1e08fc36a95ef29ec028190ba82cad8f96e" dependencies = [ "async-trait", "clap", @@ -3486,7 +3513,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ "bitcoin_hashes", - "rand 0.8.5", + "rand 0.8.6", "secp256k1-sys", "serde", ] @@ -3525,9 +3552,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" @@ -3584,9 +3611,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876ac351060d4f882bb1032b6369eb0aef79ad9df1ea8bc404874d8cc3d0cd98" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ "serde_core", ] @@ -3673,6 +3700,22 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "siphasher" version = "1.0.2" @@ -3803,7 +3846,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rustls 0.23.37", + "rustls 0.23.40", "serde", "serde_json", "sha2", @@ -3883,7 +3926,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rand 0.8.5", + "rand 0.8.6", "rsa", "serde", "sha1", @@ -3921,7 +3964,7 @@ dependencies = [ "md-5", "memchr", "once_cell", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_json", "sha2", @@ -4159,9 +4202,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.45" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", @@ -4174,15 +4217,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.25" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -4190,9 +4233,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -4215,9 +4258,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.50.0" +version = "1.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" dependencies = [ "bytes", "libc", @@ -4230,9 +4273,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", @@ -4255,7 +4298,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.37", + "rustls 0.23.40", "tokio", ] @@ -4303,7 +4346,7 @@ checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ "indexmap", "serde_core", - "serde_spanned 1.1.0", + "serde_spanned 1.1.1", "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", @@ -4344,11 +4387,11 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.1.0+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.0", + "winnow 1.0.2", ] [[package]] @@ -4359,9 +4402,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "toml_writer" -version = "1.1.0+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d282ade6016312faf3e41e57ebbba0c073e4056dab1232ab1cb624199648f8ed" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "tower" @@ -4469,9 +4512,9 @@ checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "unicase" @@ -4514,9 +4557,9 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "uniffi" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8c6dec3fc6645f71a16a3fa9ff57991028153bd194ca97f4b55e610c73ce66a" +checksum = "dc5f2297ee5b893405bed1a6929faec4713a061df158ecf5198089f23910d470" dependencies = [ "anyhow", "camino", @@ -4530,9 +4573,9 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ed0150801958d4825da56a41c71f000a457ac3a4613fa9647df78ac4b6b6881" +checksum = "8bc0c60a9607e7ab77a2ad47ec5530178015014839db25af7512447d2238016c" dependencies = [ "anyhow", "askama", @@ -4555,9 +4598,9 @@ dependencies = [ [[package]] name = "uniffi_build" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b78fd9271a4c2e85bd2c266c5a9ede1fac676eb39fd77f636c27eaf67426fd5f" +checksum = "4c39413c43b955e4aa8a4e2b34bbd1b6b5ff6bd85532b52f9eb92fbe88c14458" dependencies = [ "anyhow", "camino", @@ -4566,9 +4609,9 @@ dependencies = [ [[package]] name = "uniffi_core" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0ef62e69762fbb9386dcb6c87cd3dd05d525fa8a3a579a290892e60ddbda47e" +checksum = "77baf5d539fe2e1ad6805e942dbc5dbdeb2b83eb5f2b3a6535d422ca4b02a12f" dependencies = [ "anyhow", "bytes", @@ -4578,9 +4621,9 @@ dependencies = [ [[package]] name = "uniffi_internal_macros" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98f51ebca0d9a4b2aa6c644d5ede45c56f73906b96403c08a1985e75ccb64a01" +checksum = "b4b42137524f4be6400fcaca9d02c1d4ecb6ad917e4013c0b93235526d8396e5" dependencies = [ "anyhow", "indexmap", @@ -4591,9 +4634,9 @@ dependencies = [ [[package]] name = "uniffi_macros" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db9d12529f1223d014fd501e5f29ca0884d15d6ed5ddddd9f506e55350327dc3" +checksum = "d9273ec45330d8fe9a3701b7b983cea7a4e218503359831967cb95d26b873561" dependencies = [ "camino", "fs-err", @@ -4608,9 +4651,9 @@ dependencies = [ [[package]] name = "uniffi_meta" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9df6d413db2827c68588f8149d30d49b71d540d46539e435b23a7f7dbd4d4f86" +checksum = "431d2f443e7828a6c29d188de98b6771a6491ee98bba2d4372643bf93f988a18" dependencies = [ "anyhow", "siphasher", @@ -4620,9 +4663,9 @@ dependencies = [ [[package]] name = "uniffi_pipeline" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a806dddc8208f22efd7e95a5cdf88ed43d0f3271e8f63b47e757a8bbdb43b63a" +checksum = "761ef74f6175e15603d0424cc5f98854c5baccfe7bf4ccb08e5816f9ab8af689" dependencies = [ "anyhow", "heck 0.5.0", @@ -4633,9 +4676,9 @@ dependencies = [ [[package]] name = "uniffi_udl" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d1a7339539bf6f6fa3e9b534dece13f778bda2d54b1a6d4e40b4d6090ac26e7" +checksum = "68773ec0e1c067b6505a73bbf6a5782f31a7f9209333a0df97b87565c46bf370" dependencies = [ "anyhow", "textwrap", @@ -4691,9 +4734,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "serde_core", ] @@ -4737,11 +4780,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen 0.46.0", + "wit-bindgen 0.57.1", ] [[package]] @@ -4761,9 +4804,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.115" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6523d69017b7633e396a89c5efab138161ed5aafcbc8d3e5c5a42ae38f50495a" +checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" dependencies = [ "cfg-if", "once_cell", @@ -4775,9 +4818,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.65" +version = "0.4.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1faf851e778dfa54db7cd438b70758eba9755cb47403f3496edd7c8fc212f0" +checksum = "af934872acec734c2d80e6617bbb5ff4f12b052dd8e6332b0817bce889516084" dependencies = [ "js-sys", "wasm-bindgen", @@ -4785,9 +4828,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.115" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3a6c758eb2f701ed3d052ff5737f5bfe6614326ea7f3bbac7156192dc32e67" +checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4795,9 +4838,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.115" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "921de2737904886b52bcbb237301552d05969a6f9c40d261eb0533c8b055fedf" +checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" dependencies = [ "bumpalo", "proc-macro2", @@ -4808,9 +4851,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.115" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a93e946af942b58934c604527337bad9ae33ba1d5c6900bbb41c2c07c2364a93" +checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" dependencies = [ "unicode-ident", ] @@ -4851,9 +4894,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.92" +version = "0.3.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84cde8507f4d7cfcb1185b8cb5890c494ffea65edbe1ba82cfd63661c805ed94" +checksum = "2eadbac71025cd7b0834f20d1fe8472e8495821b4e9801eb0a60bd1f19827602" dependencies = [ "js-sys", "wasm-bindgen", @@ -4871,9 +4914,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" dependencies = [ "rustls-pki-types", ] @@ -4890,14 +4933,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.6", + "webpki-roots 1.0.7", ] [[package]] name = "webpki-roots" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ "rustls-pki-types", ] @@ -5022,15 +5065,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -5051,11 +5085,11 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.59.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.52.6", + "windows-targets 0.53.5", ] [[package]] @@ -5067,21 +5101,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-targets" version = "0.48.5" @@ -5106,7 +5125,7 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", @@ -5114,10 +5133,21 @@ dependencies = [ ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" +name = "windows-targets" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] [[package]] name = "windows_aarch64_gnullvm" @@ -5132,10 +5162,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" +name = "windows_aarch64_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -5150,10 +5180,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] -name = "windows_i686_gnu" -version = "0.42.2" +name = "windows_aarch64_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -5167,6 +5197,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" @@ -5174,10 +5210,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] -name = "windows_i686_msvc" -version = "0.42.2" +name = "windows_i686_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -5192,10 +5228,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" +name = "windows_i686_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -5210,10 +5246,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" +name = "windows_x86_64_gnu" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -5228,10 +5264,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" +name = "windows_x86_64_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -5245,6 +5281,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + [[package]] name = "winnow" version = "0.7.15" @@ -5256,15 +5298,9 @@ dependencies = [ [[package]] name = "winnow" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" - -[[package]] -name = "wit-bindgen" -version = "0.46.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" [[package]] name = "wit-bindgen" @@ -5275,6 +5311,12 @@ 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" @@ -5356,9 +5398,9 @@ dependencies = [ [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "yansi" @@ -5368,9 +5410,9 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[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", @@ -5379,9 +5421,9 @@ 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", "quote", @@ -5391,18 +5433,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.47" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.47" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", @@ -5411,18 +5453,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" 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", "quote", @@ -5438,9 +5480,9 @@ checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[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", @@ -5449,9 +5491,9 @@ 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 = [ "yoke", "zerofrom", @@ -5460,9 +5502,9 @@ 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", "quote", @@ -5471,9 +5513,9 @@ dependencies = [ [[package]] name = "zip" -version = "8.4.0" +version = "8.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7756d0206d058333667493c4014f545f4b9603c4330ccd6d9b3f86dcab59f7d9" +checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b" dependencies = [ "crc32fast", "indexmap", diff --git a/bindings/uniffi/src/lib.rs b/bindings/uniffi/src/lib.rs index 200a5d5a..ae5069d2 100644 --- a/bindings/uniffi/src/lib.rs +++ b/bindings/uniffi/src/lib.rs @@ -13,28 +13,63 @@ use rgb_lib::{ utils::BitcoinNetwork, wallet::{ Address as RgbLibAddress, AssetCFA, AssetIFA, AssetNIA, AssetUDA, Assets, - AssignmentsCollection, Balance, BlockTime, BtcBalance, Cosigner as CosignerData, - DatabaseType, EmbeddedMedia, HubInfo, InflateBeginResult, InflateDetails, - InitOperationResult, Invoice as RgbLibInvoice, InvoiceData as RgbLibInvoiceData, Media, - Metadata, MultisigKeys, MultisigVotingStatus as RgbLibMultisigVotingStatus, - MultisigWallet as RgbLibMultisigWallet, Online, Operation as RgbLibOperation, - OperationInfo as RgbLibOperationInfo, OperationResult, Outpoint, ProofOfReserves, - PsbtInputInfo, PsbtInspection, PsbtOutputInfo, ReceiveData, Recipient as RgbLibRecipient, - RecipientInfo as RgbLibRecipientInfo, RecipientType, RefreshFilter, RefreshTransferStatus, - RefreshedTransfer, RespondToOperation as RgbLibRespondToOperation, - RgbAllocation as RgbLibRgbAllocation, RgbInputInfo as RgbLibRgbInputInfo, - RgbInspection as RgbLibRgbInspection, RgbOperationInfo as RgbLibRgbOperationInfo, - RgbOutputInfo as RgbLibRgbOutputInfo, RgbTransitionInfo as RgbLibRgbTransitionInfo, - RgbWalletOpsOffline, RgbWalletOpsOnline, SendBeginResult, SendDetails, SinglesigKeys, - Token, TokenLight, Transaction, TransactionType, Transfer as RgbLibTransfer, TransferKind, - TransferTransportEndpoint, TransportEndpoint as RgbLibTransportEndpoint, TypeOfTransition, - Unspent as RgbLibUnspent, UserRole, Utxo, Wallet as RgbLibWallet, WalletData, - WalletDescriptors, WitnessData, + AssignmentsCollection, Balance, BlockTime, BtcBalance, BurnBeginResult, BurnDetails, + Cosigner as CosignerData, DatabaseType, EmbeddedMedia, HubInfo, InflateBeginResult, + InflateDetails, InitOperationResult, Invoice as RgbLibInvoice, + InvoiceData as RgbLibInvoiceData, Media, Metadata, MultisigKeys, MultisigOnlineOptions, + MultisigVotingStatus as RgbLibMultisigVotingStatus, MultisigWallet as RgbLibMultisigWallet, + Online, OnlineOptions, Operation as RgbLibOperation, OperationInfo as RgbLibOperationInfo, + OperationResult, Outpoint, ProofOfReserves, PsbtInputInfo, PsbtInspection, PsbtOutputInfo, + ReceiveData, Recipient as RgbLibRecipient, RecipientInfo as RgbLibRecipientInfo, + RecipientType, RefreshFilter, RefreshTransferStatus, RefreshedTransfer, + RespondToOperation as RgbLibRespondToOperation, RgbAllocation as RgbLibRgbAllocation, + RgbInputInfo as RgbLibRgbInputInfo, RgbInspection as RgbLibRgbInspection, + RgbOperationInfo as RgbLibRgbOperationInfo, RgbOutputInfo as RgbLibRgbOutputInfo, + RgbTransitionInfo as RgbLibRgbTransitionInfo, RgbWalletOpsOffline, RgbWalletOpsOnline, + SendBeginResult, SendDetails, SinglesigKeys, SyncKeychain as RgbLibSyncKeychain, + SyncOptions as RgbLibSyncOptions, SyncStrategy, Token, TokenLight, Transaction, + TransactionType, Transfer as RgbLibTransfer, TransferKind, TransferTransportEndpoint, + TransportEndpoint as RgbLibTransportEndpoint, TypeOfTransition, Unspent as RgbLibUnspent, + UserRole, Utxo, Wallet as RgbLibWallet, WalletData, WalletDescriptors, WitnessData, }, }; uniffi::include_scaffolding!("rgb-lib"); +// temporary solution needed because the Enum attribute doesn't support the Remote one +pub enum SyncKeychain { + Colored, + Vanilla { lookback: u32 }, +} +impl From for SyncKeychain { + fn from(orig: RgbLibSyncKeychain) -> Self { + match orig { + RgbLibSyncKeychain::Colored => SyncKeychain::Colored, + RgbLibSyncKeychain::Vanilla { lookback } => SyncKeychain::Vanilla { lookback }, + } + } +} +impl From for RgbLibSyncKeychain { + fn from(orig: SyncKeychain) -> Self { + match orig { + SyncKeychain::Colored => RgbLibSyncKeychain::Colored, + SyncKeychain::Vanilla { lookback } => RgbLibSyncKeychain::Vanilla { lookback }, + } + } +} +pub struct SyncOptions { + pub keychain: SyncKeychain, + pub strategy: SyncStrategy, +} +impl From for RgbLibSyncOptions { + fn from(orig: SyncOptions) -> Self { + Self { + keychain: orig.keychain.into(), + strategy: orig.strategy, + } + } +} + // temporary solution needed because the Enum attribute doesn't support the Remote one pub enum Assignment { Fungible { amount: u64 }, @@ -413,6 +448,24 @@ pub enum Operation { details: InflateDetails, status: MultisigVotingStatus, }, + BurnToReview { + psbt: String, + details: BurnDetails, + status: MultisigVotingStatus, + }, + BurnPending { + details: BurnDetails, + status: MultisigVotingStatus, + }, + BurnCompleted { + txid: String, + details: BurnDetails, + status: MultisigVotingStatus, + }, + BurnDiscarded { + details: BurnDetails, + status: MultisigVotingStatus, + }, IssuanceCompleted { asset_id: String, }, @@ -540,6 +593,32 @@ impl From for Operation { status: status.into(), } } + RgbLibOperation::BurnToReview { + psbt, + details, + status, + } => Operation::BurnToReview { + psbt, + details, + status: status.into(), + }, + RgbLibOperation::BurnPending { status, details } => Operation::BurnPending { + details, + status: status.into(), + }, + RgbLibOperation::BurnCompleted { + txid, + details, + status, + } => Operation::BurnCompleted { + txid, + details, + status: status.into(), + }, + RgbLibOperation::BurnDiscarded { details, status } => Operation::BurnDiscarded { + details, + status: status.into(), + }, RgbLibOperation::IssuanceCompleted { asset_id } => { Operation::IssuanceCompleted { asset_id } } @@ -641,6 +720,32 @@ impl From for RgbLibOperation { status: status.into(), } } + Operation::BurnToReview { + psbt, + details, + status, + } => RgbLibOperation::BurnToReview { + psbt, + details, + status: status.into(), + }, + Operation::BurnPending { status, details } => RgbLibOperation::BurnPending { + details, + status: status.into(), + }, + Operation::BurnCompleted { + txid, + details, + status, + } => RgbLibOperation::BurnCompleted { + txid, + details, + status: status.into(), + }, + Operation::BurnDiscarded { details, status } => RgbLibOperation::BurnDiscarded { + details, + status: status.into(), + }, Operation::IssuanceCompleted { asset_id } => { RgbLibOperation::IssuanceCompleted { asset_id } } @@ -938,14 +1043,8 @@ impl Wallet { .create_utxos_begin(online, up_to, num, size, fee_rate, skip_sync, dry_run) } - fn create_utxos_end( - &self, - online: Online, - signed_psbt: String, - skip_sync: bool, - ) -> Result { - self._get_wallet() - .create_utxos_end(online, signed_psbt, skip_sync) + fn create_utxos_end(&self, online: Online, signed_psbt: String) -> Result { + self._get_wallet().create_utxos_end(online, signed_psbt) } fn delete_transfers( @@ -1016,13 +1115,47 @@ impl Wallet { self._get_wallet().get_fee_estimation(online, blocks) } - fn go_online( + fn go_online(&self, online_options: OnlineOptions) -> Result { + self._get_wallet().go_online(online_options) + } + + fn burn( &self, - skip_consistency_check: bool, - indexer_url: String, - ) -> Result { + online: Online, + asset_id: String, + amount: u64, + fee_rate: u64, + min_confirmations: u8, + ) -> Result { self._get_wallet() - .go_online(skip_consistency_check, indexer_url) + .burn(online, asset_id, amount, fee_rate, min_confirmations) + } + + fn burn_begin( + &self, + online: Online, + asset_id: String, + amount: u64, + fee_rate: u64, + min_confirmations: u8, + dry_run: bool, + ) -> Result { + self._get_wallet().burn_begin( + online, + asset_id, + amount, + fee_rate, + min_confirmations, + dry_run, + ) + } + + fn burn_end( + &self, + online: Online, + signed_psbt: String, + ) -> Result { + self._get_wallet().burn_end(online, signed_psbt) } fn inflate( @@ -1184,7 +1317,6 @@ impl Wallet { fee_rate: u64, min_confirmations: u8, expiration_timestamp: Option, - skip_sync: bool, ) -> Result { self._get_wallet().send( online, @@ -1193,7 +1325,6 @@ impl Wallet { fee_rate, min_confirmations, expiration_timestamp, - skip_sync, ) } @@ -1222,9 +1353,8 @@ impl Wallet { &self, online: Online, signed_psbt: String, - skip_sync: bool, ) -> Result { - self._get_wallet().send_end(online, signed_psbt, skip_sync) + self._get_wallet().send_end(online, signed_psbt) } fn send_btc( @@ -1252,18 +1382,12 @@ impl Wallet { .send_btc_begin(online, address, amount, fee_rate, skip_sync, dry_run) } - fn send_btc_end( - &self, - online: Online, - signed_psbt: String, - skip_sync: bool, - ) -> Result { - self._get_wallet() - .send_btc_end(online, signed_psbt, skip_sync) + fn send_btc_end(&self, online: Online, signed_psbt: String) -> Result { + self._get_wallet().send_btc_end(online, signed_psbt) } - fn sync(&self, online: Online) -> Result<(), RgbLibError> { - self._get_wallet().sync(online) + fn sync(&self, online: Online, options: SyncOptions) -> Result<(), RgbLibError> { + self._get_wallet().sync(online, options.into()) } fn inspect_psbt(&self, psbt: String) -> Result { @@ -1432,19 +1556,29 @@ impl MultisigWallet { fn go_online( &self, - skip_consistency_check: bool, - indexer_url: String, - hub_url: String, - hub_token: String, + online_options: OnlineOptions, + multisig_online_options: MultisigOnlineOptions, ) -> Result { let mut wallet = self.wallet_mutex.lock().expect("wallet"); - wallet.go_online(skip_consistency_check, indexer_url, hub_url, hub_token) + wallet.go_online(online_options, multisig_online_options) } fn hub_info(&self, online: Online) -> Result { self._get_wallet().hub_info(online) } + fn burn_init( + &self, + online: Online, + asset_id: String, + amount: u64, + fee_rate: u64, + min_confirmations: u8, + ) -> Result { + self._get_wallet() + .burn_init(online, asset_id, amount, fee_rate, min_confirmations) + } + fn inflate_init( &self, online: Online, @@ -1606,9 +1740,9 @@ impl MultisigWallet { .send_btc_init(online, address, amount, fee_rate, skip_sync) } - fn sync(&self, online: Online) -> Result<(), RgbLibError> { + fn sync(&self, online: Online, options: SyncOptions) -> Result<(), RgbLibError> { let mut wallet = self.wallet_mutex.lock().expect("wallet"); - wallet.sync(online) + wallet.sync(online, options.into()) } fn get_address(&self, online: Online) -> Result { diff --git a/bindings/uniffi/src/rgb-lib.udl b/bindings/uniffi/src/rgb-lib.udl index d869ad50..e761de73 100644 --- a/bindings/uniffi/src/rgb-lib.udl +++ b/bindings/uniffi/src/rgb-lib.udl @@ -85,6 +85,7 @@ interface RgbLibError { Network(string details); NoConsignment(); NoCosignersSupplied(); + NoBurnAmount(); NoInflationAmounts(); NoIssuanceAmounts(); NoKeysSupplied(); @@ -107,6 +108,7 @@ interface RgbLibError { UnknownRgbSchema(string schema_id); UnknownTransfer(string txid); UnsupportedBackupVersion(string version); + UnsupportedBurn(AssetSchema asset_schema); UnsupportedInflation(AssetSchema asset_schema); UnsupportedLayer1(string layer_1); UnsupportedSchema(AssetSchema asset_schema); @@ -278,6 +280,24 @@ enum WitnessVersion { "Taproot", }; +[Enum] +interface SyncKeychain { + Colored(); + Vanilla(u32 lookback); +}; + +[Remote] +enum SyncStrategy { + "FullScan", + "FullSync", + "FastSync", +}; + +dictionary SyncOptions { + SyncKeychain keychain; + SyncStrategy strategy; +}; + interface Address { [Throws=RgbLibError] constructor(string address_string, BitcoinNetwork bitcoin_network); @@ -384,6 +404,19 @@ dictionary Online { u64 id; }; +[Remote] +dictionary OnlineOptions { + string indexer_url; + boolean skip_consistency_check; + u32 vanilla_sync_lookback; +}; + +[Remote] +dictionary MultisigOnlineOptions { + string hub_url; + string hub_token; +}; + [Remote] dictionary Outpoint { string txid; @@ -448,11 +481,13 @@ enum TransferKind { "ReceiveWitness", "Send", "Inflation", + "Burn", }; [Remote] enum TransferStatus { "WaitingCounterparty", + "WaitingSafeHeight", "WaitingConfirmations", "Settled", "Failed", @@ -559,6 +594,20 @@ dictionary MultisigVotingStatus { boolean? my_response; }; +[Remote] +dictionary BurnDetails { + string fascia_path; + u8 min_confirmations; + u64 entropy; +}; + +[Remote] +dictionary BurnBeginResult { + string psbt; + i32? batch_transfer_idx; + BurnDetails details; +}; + [Remote] dictionary InflateDetails { string fascia_path; @@ -606,6 +655,10 @@ interface Operation { InflationPending(InflateDetails details, MultisigVotingStatus status); InflationCompleted(string txid, InflateDetails details, MultisigVotingStatus status); InflationDiscarded(InflateDetails details, MultisigVotingStatus status); + BurnToReview(string psbt, BurnDetails details, MultisigVotingStatus status); + BurnPending(BurnDetails details, MultisigVotingStatus status); + BurnCompleted(string txid, BurnDetails details, MultisigVotingStatus status); + BurnDiscarded(BurnDetails details, MultisigVotingStatus status); IssuanceCompleted(string asset_id); BlindReceiveCompleted(ReceiveData details); WitnessReceiveCompleted(ReceiveData details); @@ -676,6 +729,7 @@ dictionary RgbOperationInfo { enum TypeOfTransition { "Inflate", "Transfer", + "Burn", }; [Remote] @@ -779,7 +833,7 @@ interface Wallet { boolean skip_sync, boolean dry_run); [Throws=RgbLibError] - u8 create_utxos_end(Online online, string signed_psbt, boolean skip_sync); + u8 create_utxos_end(Online online, string signed_psbt); [Throws=RgbLibError] boolean delete_transfers(i32? batch_transfer_idx, boolean no_asset_only); @@ -817,7 +871,20 @@ interface Wallet { f64 get_fee_estimation(Online online, u16 blocks); [Throws=RgbLibError] - Online go_online(boolean skip_consistency_check, string indexer_url); + Online go_online(OnlineOptions online_options); + + [Throws=RgbLibError] + OperationResult burn( + Online online, string asset_id, u64 amount, u64 fee_rate, + u8 min_confirmations); + + [Throws=RgbLibError] + BurnBeginResult burn_begin( + Online online, string asset_id, u64 amount, u64 fee_rate, + u8 min_confirmations, boolean dry_run); + + [Throws=RgbLibError] + OperationResult burn_end(Online online, string signed_psbt); [Throws=RgbLibError] OperationResult inflate( @@ -873,7 +940,7 @@ interface Wallet { OperationResult send( Online online, record> recipient_map, boolean donation, u64 fee_rate, u8 min_confirmations, - u64? expiration_timestamp, boolean skip_sync); + u64? expiration_timestamp); [Throws=RgbLibError] SendBeginResult send_begin( @@ -882,7 +949,7 @@ interface Wallet { u64? expiration_timestamp, boolean dry_run); [Throws=RgbLibError] - OperationResult send_end(Online online, string signed_psbt, boolean skip_sync); + OperationResult send_end(Online online, string signed_psbt); [Throws=RgbLibError] string send_btc( @@ -894,10 +961,10 @@ interface Wallet { boolean dry_run); [Throws=RgbLibError] - string send_btc_end(Online online, string signed_psbt, boolean skip_sync); + string send_btc_end(Online online, string signed_psbt); [Throws=RgbLibError] - void sync(Online online); + void sync(Online online, SyncOptions options); }; interface MultisigWallet { @@ -961,12 +1028,17 @@ interface MultisigWallet { f64 get_fee_estimation(Online online, u16 blocks); [Throws=RgbLibError] - Online go_online(boolean skip_consistency_check, string indexer_url, - string hub_url, string hub_token); + Online go_online(OnlineOptions online_options, + MultisigOnlineOptions multisig_online_options); [Throws=RgbLibError] HubInfo hub_info(Online online); + [Throws=RgbLibError] + InitOperationResult burn_init( + Online online, string asset_id, u64 amount, u64 fee_rate, + u8 min_confirmations); + [Throws=RgbLibError] InitOperationResult inflate_init( Online online, string asset_id, sequence inflation_amounts, @@ -1019,7 +1091,7 @@ interface MultisigWallet { Online online, string address, u64 amount, u64 fee_rate, boolean skip_sync); [Throws=RgbLibError] - void sync(Online online); + void sync(Online online, SyncOptions options); [Throws=RgbLibError] string get_address(Online online); diff --git a/src/api/multisig_hub.rs b/src/api/multisig_hub.rs index 0d845789..b94aa12f 100644 --- a/src/api/multisig_hub.rs +++ b/src/api/multisig_hub.rs @@ -126,6 +126,7 @@ pub(crate) enum OperationType { Inflation = 5, BlindReceive = 6, WitnessReceive = 7, + Burn = 8, } #[derive(Debug, Deserialize, Serialize)] diff --git a/src/database/enums.rs b/src/database/enums.rs index df960207..47730d42 100644 --- a/src/database/enums.rs +++ b/src/database/enums.rs @@ -242,6 +242,9 @@ pub enum TransferStatus { /// Waiting for the counterparty to take action #[sea_orm(num_value = 1)] WaitingCounterparty = 1, + /// Waiting for safe height to be reached + #[sea_orm(num_value = 6)] + WaitingSafeHeight = 6, /// Waiting for the transfer transaction to reach the required number of confirmations #[sea_orm(num_value = 2)] WaitingConfirmations = 2, @@ -269,6 +272,7 @@ impl TransferStatus { [ TransferStatus::Initiated, TransferStatus::WaitingCounterparty, + TransferStatus::WaitingSafeHeight, TransferStatus::WaitingConfirmations, ] .contains(self) @@ -278,6 +282,7 @@ impl TransferStatus { pub(crate) fn waiting(&self) -> bool { [ TransferStatus::WaitingCounterparty, + TransferStatus::WaitingSafeHeight, TransferStatus::WaitingConfirmations, ] .contains(self) @@ -294,6 +299,16 @@ impl TransferStatus { pub(crate) fn waiting_counterparty(&self) -> bool { self == &TransferStatus::WaitingCounterparty } + + #[cfg(any(feature = "electrum", feature = "esplora"))] + pub(crate) fn is_fallible(&self) -> bool { + [ + TransferStatus::Initiated, + TransferStatus::WaitingCounterparty, + TransferStatus::WaitingSafeHeight, + ] + .contains(self) + } } #[derive(Debug, Copy, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Deserialize, Serialize)] diff --git a/src/database/mod.rs b/src/database/mod.rs index 94359677..d4e65b90 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -69,13 +69,26 @@ impl DbBatchTransfer { }) } - pub(crate) fn failed(&self) -> bool { - self.status.failed() + #[cfg(any(feature = "electrum", feature = "esplora"))] + pub(crate) fn get_incoming_transfer( + &self, + asset_transfers: &[DbAssetTransfer], + transfers: &[DbTransfer], + ) -> Result<(DbAssetTransfer, DbTransfer), Error> { + let batch_transfer_data = self.get_transfers(asset_transfers, transfers)?; + let asset_transfer_data = batch_transfer_data + .asset_transfers_data + .first() // incoming batch transfer has only one asset transfer + .expect("asset transfer should be connected to a batch transfer"); + let transfer = asset_transfer_data + .transfers + .first() // incoming asset transfer has only one transfer + .expect("transfer should be connected to an asset transfer"); + Ok((asset_transfer_data.asset_transfer.clone(), transfer.clone())) } - #[cfg(any(feature = "electrum", feature = "esplora"))] - pub(crate) fn initiated(&self) -> bool { - self.status.initiated() + pub(crate) fn failed(&self) -> bool { + self.status.failed() } #[cfg(any(feature = "electrum", feature = "esplora"))] @@ -88,8 +101,8 @@ impl DbBatchTransfer { } #[cfg(any(feature = "electrum", feature = "esplora"))] - pub(crate) fn waiting_counterparty(&self) -> bool { - self.status.waiting_counterparty() + pub(crate) fn is_fallible(&self) -> bool { + self.status.is_fallible() } } @@ -815,22 +828,6 @@ impl RgbLibDatabase { } } - #[cfg(any(feature = "electrum", feature = "esplora"))] - pub(crate) fn get_incoming_transfer( - &self, - batch_transfer_data: &DbBatchTransferData, - ) -> Result<(DbAssetTransfer, DbTransfer), Error> { - let asset_transfer_data = batch_transfer_data - .asset_transfers_data - .first() - .expect("asset transfer should be connected to a batch transfer"); - let transfer = asset_transfer_data - .transfers - .first() - .expect("transfer should be connected to an asset transfer"); - Ok((asset_transfer_data.asset_transfer.clone(), transfer.clone())) - } - fn get_utxo_allocations( &self, utxo: &DbTxo, diff --git a/src/error.rs b/src/error.rs index 063d1311..8603ebf6 100644 --- a/src/error.rs +++ b/src/error.rs @@ -448,6 +448,10 @@ pub enum Error { details: String, }, + /// Cannot burn an asset with zero amount + #[error("Burn request with zero amount")] + NoBurnAmount, + /// No consignment found #[error("No consignment found")] NoConsignment, @@ -568,7 +572,14 @@ pub enum Error { version: String, }, - /// The schema doesn't support inflation + /// The schema doesn't support burn transitions + #[error("Burn not supported")] + UnsupportedBurn { + /// Asset schema + asset_schema: AssetSchema, + }, + + /// The schema doesn't support inflate transitions #[error("Inflation not supported")] UnsupportedInflation { /// Asset schema diff --git a/src/keys.rs b/src/keys.rs index 8ac702a9..60d26936 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -73,14 +73,13 @@ pub struct Keys { /// Generate a set of [`Keys`] for the given Bitcoin network and witness version. pub fn generate_keys(bitcoin_network: BitcoinNetwork, witness_version: WitnessVersion) -> Keys { - let bdk_network = BdkNetwork::from(bitcoin_network); let mnemonic = Mnemonic::generate((WordCount::Words12, Language::English)) .expect("to be able to generate a new mnemonic"); let xkey: ExtendedKey = mnemonic .clone() .into_extended_key() .expect("a valid key should have been provided"); - let xpub = &xkey.into_xpub(bdk_network, &Secp256k1::new()); + let xpub = &xkey.into_xpub(bitcoin_network.network_kind(), &Secp256k1::new()); let mnemonic_str = mnemonic.to_string(); let (account_xpub_vanilla, account_xpub_colored) = get_account_xpubs(&bitcoin_network, &mnemonic_str, witness_version).unwrap(); @@ -101,7 +100,6 @@ pub fn restore_keys( mnemonic: String, witness_version: WitnessVersion, ) -> Result { - let bdk_network = BdkNetwork::from(bitcoin_network); let (account_xpub_vanilla, account_xpub_colored) = get_account_xpubs(&bitcoin_network, &mnemonic, witness_version)?; let mnemonic_parsed = Mnemonic::parse_in(Language::English, &mnemonic)?; @@ -109,7 +107,7 @@ pub fn restore_keys( .clone() .into_extended_key() .expect("a valid key should have been provided"); - let xpub = &xkey.into_xpub(bdk_network, &Secp256k1::new()); + let xpub = &xkey.into_xpub(bitcoin_network.network_kind(), &Secp256k1::new()); let master_fingerprint = xpub.fingerprint().to_string(); Ok(Keys { mnemonic, diff --git a/src/lib.rs b/src/lib.rs index 0c449eb8..3f5b0230 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -200,7 +200,7 @@ use rgbstd::{ #[cfg(any(feature = "electrum", feature = "esplora"))] use rgbstd::{ TransitionType, - containers::{Consignment, Contract}, + containers::Consignment, contract::FilterIncludeAll, daggy::Walker, indexers::AnyResolver, @@ -211,7 +211,7 @@ use rgbstd::{ use schemata::{CfaWrapper, NiaWrapper, UdaWrapper}; use schemata::{ CollectibleFungibleAsset, IfaWrapper, InflatableFungibleAsset, NonInflatableAsset, OS_ASSET, - OS_INFLATION, TS_INFLATION, TS_TRANSFER, UniqueDigitalAsset, + OS_INFLATION, TS_BURN, TS_INFLATION, TS_TRANSFER, UniqueDigitalAsset, }; use scrypt::{ Params, Scrypt, diff --git a/src/utils.rs b/src/utils.rs index 4a617e47..318027fa 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -78,6 +78,15 @@ pub enum BitcoinNetwork { SignetCustom, } +impl BitcoinNetwork { + pub(crate) fn network_kind(&self) -> NetworkKind { + match self { + BitcoinNetwork::Mainnet => NetworkKind::Main, + _ => NetworkKind::Test, + } + } +} + impl fmt::Display for BitcoinNetwork { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self:?}") @@ -258,10 +267,10 @@ where deserialize_str_or_number(deserializer) } -pub(crate) fn str_to_xpub(xpub: &str, bdk_network: &BdkNetwork) -> Result { +pub(crate) fn str_to_xpub(xpub: &str, network_kind: &NetworkKind) -> Result { let pubkey_btc = Xpub::from_str(xpub)?; let extended_key_btc: ExtendedKey = ExtendedKey::from(pubkey_btc); - Ok(extended_key_btc.into_xpub(*bdk_network, &Secp256k1::new())) + Ok(extended_key_btc.into_xpub(*network_kind, &Secp256k1::new())) } pub(crate) fn get_coin_type(bitcoin_network: &BitcoinNetwork, rgb: bool) -> u32 { @@ -698,7 +707,7 @@ impl RgbRuntime { &mut self, contract: ValidTransfer, resolver: &R, - ) -> Result { + ) -> Result<(), InternalError> { self.stock .accept_transfer(contract, resolver) .map_err(InternalError::from) @@ -771,7 +780,7 @@ impl RgbRuntime { &mut self, contract: ValidContract, resolver: &R, - ) -> Result { + ) -> Result<(), InternalError> { self.stock .import_contract(contract, resolver) .map_err(InternalError::from) diff --git a/src/wallet/core.rs b/src/wallet/core.rs index 9918f2cd..971b5c89 100644 --- a/src/wallet/core.rs +++ b/src/wallet/core.rs @@ -13,6 +13,54 @@ pub(crate) const RGB_LIB_DB_NAME: &str = "rgb_lib_db"; pub(crate) const ASSETS_DIR: &str = "assets"; pub(crate) const MEDIA_DIR: &str = "media_files"; +/// Which keychain contributes SPKs to the sync request. +#[cfg(any(feature = "electrum", feature = "esplora"))] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum SyncKeychain { + /// Sync the colored keychain + Colored, + /// Sync the vanilla keychain + Vanilla { + /// Number of addresses preceding the lookback anchor (last used or, if none, last + /// revealed) to scan + lookback: u32, + }, +} + +#[cfg(any(feature = "electrum", feature = "esplora"))] +impl SyncKeychain { + fn keychain(&self) -> KeychainKind { + match self { + SyncKeychain::Colored => KeychainKind::External, + SyncKeychain::Vanilla { .. } => KeychainKind::Internal, + } + } +} + +/// Strategy used to build the indexer sync request. +#[cfg(any(feature = "electrum", feature = "esplora"))] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum SyncStrategy { + /// BIP44 stop-gap full scan + FullScan, + /// Sync all revealed SPKs + FullSync, + /// Sync only SPKs we strictly need to observe: + /// - colored: SPKs used in pending transfers or unconfirmed transactions + /// - vanilla: a tail of recently revealed SPKs + FastSync, +} + +/// Options driving a single sync invocation. +#[cfg(any(feature = "electrum", feature = "esplora"))] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub struct SyncOptions { + /// Which keychain to sync + pub keychain: SyncKeychain, + /// Sync strategy + pub strategy: SyncStrategy, +} + pub struct WalletInternals { pub(crate) wallet_data: WalletData, pub(crate) logger: Logger, @@ -181,6 +229,11 @@ pub trait WalletCore { &self.online_data().as_ref().unwrap().indexer } + #[cfg(any(feature = "electrum", feature = "esplora"))] + fn vanilla_sync_lookback(&self) -> u32 { + self.online_data().as_ref().unwrap().vanilla_sync_lookback + } + #[cfg(any(feature = "electrum", feature = "esplora"))] fn check_online(&self, online: Online) -> Result<(), Error> { if let Some(online_data) = &self.online_data() { @@ -196,15 +249,100 @@ pub trait WalletCore { } #[cfg(any(feature = "electrum", feature = "esplora"))] - fn sync_db_txos_with_bdk(&mut self, full_scan: bool, include_spent: bool) -> Result<(), Error> { - debug!(self.logger(), "Syncing TXOs..."); + fn fast_sync_colored_spks(&self) -> Result, Error> { + let mut spks: HashSet = HashSet::new(); + for pws in self.database().iter_pending_witness_scripts()? { + spks.insert(ScriptBuf::from_hex(&pws.script).expect("valid script")); + } + Ok(spks) + } + + #[cfg(any(feature = "electrum", feature = "esplora"))] + fn fast_sync_vanilla_spks(&self, lookback: u32) -> HashSet { + let spk_index = self.bdk_wallet().spk_index(); + let Some(last_revealed) = spk_index.last_revealed_index(KeychainKind::Internal) else { + return HashSet::new(); + }; + let lookback_anchor = spk_index + .last_used_index(KeychainKind::Internal) + .unwrap_or(last_revealed); + let start = lookback_anchor.saturating_sub(lookback); + spk_index + .revealed_keychain_spks(KeychainKind::Internal) + .filter(|(i, _)| *i >= start && *i <= last_revealed) + .map(|(_, spk)| spk) + .collect() + } - let update: Update = if full_scan { - let request = self.bdk_wallet().start_full_scan(); - self.indexer().full_scan(request)?.into() - } else { - let request = self.bdk_wallet().start_sync_with_revealed_spks(); - self.indexer().sync(request)?.into() + #[cfg(any(feature = "electrum", feature = "esplora"))] + fn unconfirmed_colored_spks(&self) -> HashSet { + let spk_index = self.bdk_wallet().spk_index(); + let mut spks: HashSet = HashSet::new(); + for tx in self + .bdk_wallet() + .transactions() + .filter(|tx| matches!(tx.chain_position, ChainPosition::Unconfirmed { .. })) + { + // first input is enough for the indexer's to return the TX info + for input in tx.tx_node.tx.input.iter() { + if let Some(((kc, _), txout)) = spk_index.txout(input.previous_output) + && kc == KeychainKind::External + { + spks.insert(txout.script_pubkey.clone()); + break; + } + } + } + spks + } + + #[cfg(any(feature = "electrum", feature = "esplora"))] + fn sync_bdk_and_db_txos( + &mut self, + options: SyncOptions, + include_spent: bool, + ) -> Result<(), Error> { + debug!(self.logger(), "Syncing {:?}...", options); + + let kc = options.keychain.keychain(); + let latest_checkpoint = self.bdk_wallet().latest_checkpoint(); + let update: Update = match options.strategy { + SyncStrategy::FullScan => { + let mut iters = self.bdk_wallet().spk_index().all_unbounded_spk_iters(); + let iter = iters.remove(&kc).expect("keychain must exist"); + let request = FullScanRequest::builder() + .chain_tip(latest_checkpoint) + .spks_for_keychain(kc, iter); + self.indexer().full_scan(request)?.into() + } + SyncStrategy::FullSync => { + let spks: Vec = self + .bdk_wallet() + .spk_index() + .revealed_keychain_spks(kc) + .map(|(_, spk)| spk) + .collect(); + let request = SyncRequest::builder() + .chain_tip(latest_checkpoint) + .spks(spks); + self.indexer().sync(request)?.into() + } + SyncStrategy::FastSync => { + let mut spks: HashSet = HashSet::new(); + match options.keychain { + SyncKeychain::Colored => { + spks.extend(self.fast_sync_colored_spks()?); + spks.extend(self.unconfirmed_colored_spks()); + } + SyncKeychain::Vanilla { lookback } => { + spks.extend(self.fast_sync_vanilla_spks(lookback)); + } + } + let request = SyncRequest::builder() + .chain_tip(latest_checkpoint) + .spks(spks); + self.indexer().sync(request)?.into() + } }; let (bdk_wallet, bdk_db) = self.bdk_wallet_db_mut(); bdk_wallet @@ -214,10 +352,19 @@ pub trait WalletCore { })?; bdk_wallet.persist(bdk_db)?; + if matches!(options.keychain, SyncKeychain::Colored) { + self.update_db_colored_txos_from_bdk(include_spent)?; + } + + debug!(self.logger(), "Synced"); + Ok(()) + } + + #[cfg(any(feature = "electrum", feature = "esplora"))] + fn update_db_colored_txos_from_bdk(&mut self, include_spent: bool) -> Result<(), Error> { let db_txos = self.database().iter_txos()?; let db_outpoints: HashSet = db_txos - .clone() .into_iter() .filter(|t| t.exists && (include_spent || !t.spent)) .map(|u| u.outpoint().to_string()) @@ -252,13 +399,11 @@ pub trait WalletCore { self.database().set_txo(new_db_utxo.clone())?; } - debug!(self.logger(), "Synced TXOs"); - Ok(()) } #[cfg(any(feature = "electrum", feature = "esplora"))] - fn sync_db_txos(&mut self, full_scan: bool, include_spent: bool) -> Result<(), Error> { - self.sync_db_txos_with_bdk(full_scan, include_spent) + fn sync_wallet(&mut self, options: SyncOptions, include_spent: bool) -> Result<(), Error> { + self.sync_bdk_and_db_txos(options, include_spent) } } diff --git a/src/wallet/indexer.rs b/src/wallet/indexer.rs index f2065983..efb18dc8 100644 --- a/src/wallet/indexer.rs +++ b/src/wallet/indexer.rs @@ -117,6 +117,23 @@ impl Indexer { } } + pub(crate) fn get_latest_block_height(&self) -> Result { + Ok(match self { + #[cfg(feature = "electrum")] + Indexer::Electrum(client) => { + let header = client + .inner + .block_headers_subscribe() + .map_err(IndexerError::from)?; + u32::try_from(header.height).map_err(|_| Error::Indexer { + details: s!("electrs returned invalid height"), + })? + } + #[cfg(feature = "esplora")] + Indexer::Esplora(client) => client.get_height().map_err(IndexerError::from)?, + }) + } + pub(crate) fn get_tx_confirmations(&self, txid: &str) -> Result, Error> { Ok(match self { #[cfg(feature = "electrum")] @@ -155,7 +172,7 @@ impl Indexer { let txid = Txid::from_str(txid).unwrap(); let tx_status = client.get_tx_status(&txid).map_err(IndexerError::from)?; if let Some(tx_height) = tx_status.block_height { - let height = client.get_height().map_err(IndexerError::from)?; + let height = self.get_latest_block_height()?; Some((height - tx_height + 1) as u64) } else if client.get_tx(&txid).map_err(IndexerError::from)?.is_none() { None diff --git a/src/wallet/mod.rs b/src/wallet/mod.rs index ce602a94..3500892c 100644 --- a/src/wallet/mod.rs +++ b/src/wallet/mod.rs @@ -21,8 +21,8 @@ pub use backup::restore_backup; pub use multisig::{Cosigner, MultisigKeys, MultisigWallet}; #[cfg(any(feature = "electrum", feature = "esplora"))] pub use multisig::{ - HubInfo, InitOperationResult, MultisigVotingStatus, Operation, OperationInfo, - RespondToOperation, UserRole, + HubInfo, InitOperationResult, MultisigOnlineOptions, MultisigVotingStatus, Operation, + OperationInfo, RespondToOperation, UserRole, }; pub use objects::{ Address, AssetCFA, AssetIFA, AssetNIA, AssetUDA, Assets, AssignmentsCollection, Balance, @@ -35,8 +35,9 @@ pub use objects::{ }; #[cfg(any(feature = "electrum", feature = "esplora"))] pub use objects::{ - InflateBeginResult, InflateDetails, OperationResult, RefreshFilter, RefreshResult, - RefreshTransferStatus, RefreshedTransfer, SendBeginResult, SendDetails, + BurnBeginResult, BurnDetails, InflateBeginResult, InflateDetails, OnlineOptions, + OperationResult, RefreshFilter, RefreshResult, RefreshTransferStatus, RefreshedTransfer, + SendBeginResult, SendDetails, }; pub use offline::RgbWalletOpsOffline; #[cfg(any(feature = "electrum", feature = "esplora"))] @@ -49,12 +50,14 @@ pub(crate) use core::{ setup_new_wallet, setup_rgb, }; #[cfg(any(feature = "electrum", feature = "esplora"))] +pub use core::{SyncKeychain, SyncOptions, SyncStrategy}; +#[cfg(any(feature = "electrum", feature = "esplora"))] pub(crate) use indexer::Indexer; #[cfg(any(feature = "electrum", feature = "esplora"))] pub(crate) use objects::{ AssetInfo, AssetSpend, BeginOperationData, BtcChange, LocalRecipient, LocalRecipientData, LocalWitnessData, OnlineData, PrepareRgbPsbtResult, PrepareTransferPsbtResult, - RefreshResultTrait, + ReceivedConsignmentMeta, RefreshResultTrait, }; pub(crate) use objects::{ InfoAssetTransfer, InfoBatchTransfer, IssueData, IssuedAssetDetails, LocalAssetData, @@ -79,7 +82,7 @@ pub(crate) const SCHEMA_ID_UDA: &str = pub(crate) const SCHEMA_ID_CFA: &str = "rgb:sch:JgqK5hJX9YBT4osCV7VcW_iLTcA5csUCnLzvaKTTrNY#mars-house-friend"; pub(crate) const SCHEMA_ID_IFA: &str = - "rgb:sch:p6H_wtDgei9HHUVLjKW0tNdHHFLhfHxrn9QX_QQUE78#scale-year-shave"; + "rgb:sch:IpjJhFLz3oywYKQxO3KmFgR0Aa415nlTNrNyEFqMZCE#shoe-colombo-mango"; pub(crate) const RGB_STATE_ASSET_OWNER: &str = "assetOwner"; pub(crate) const RGB_STATE_INFLATION_ALLOWANCE: &str = "inflationAllowance"; @@ -87,3 +90,7 @@ pub(crate) const RGB_GLOBAL_ISSUED_SUPPLY: &str = "issuedSupply"; pub(crate) const RGB_GLOBAL_REJECT_LIST_URL: &str = "rejectListUrl"; #[cfg(any(feature = "electrum", feature = "esplora"))] pub(crate) const RGB_METADATA_ALLOWED_INFLATION: &str = "allowedInflation"; +#[cfg(any(feature = "electrum", feature = "esplora"))] +pub(crate) const RGB_METADATA_BURNED_ASSET: &str = "burnedAsset"; +#[cfg(any(feature = "electrum", feature = "esplora"))] +pub(crate) const RGB_METADATA_BURNED_INFLATION: &str = "burnedInflation"; diff --git a/src/wallet/multisig.rs b/src/wallet/multisig.rs index edf8d862..d1be66df 100644 --- a/src/wallet/multisig.rs +++ b/src/wallet/multisig.rs @@ -213,7 +213,7 @@ impl WalletCore for MultisigWallet { } #[cfg(any(feature = "electrum", feature = "esplora"))] - fn sync_db_txos(&mut self, full_scan: bool, include_spent: bool) -> Result<(), Error> { + fn sync_wallet(&mut self, options: SyncOptions, include_spent: bool) -> Result<(), Error> { // sync addresses let response = self.hub_client().get_current_address_indices()?; let (bdk_wallet, bdk_database) = self.bdk_wallet_db_mut(); @@ -238,7 +238,7 @@ impl WalletCore for MultisigWallet { bdk_wallet.persist(bdk_database)?; } // sync UTXOs - self.sync_db_txos_with_bdk(full_scan, include_spent) + self.sync_bdk_and_db_txos(options, include_spent) } } @@ -331,6 +331,17 @@ impl RgbWalletOpsOnline for MultisigWallet { } } +/// Multisig-specific options for the [`MultisigWallet::go_online`] method. +#[cfg(any(feature = "electrum", feature = "esplora"))] +#[derive(Debug, Clone, Deserialize, Serialize)] +#[cfg_attr(feature = "camel_case", serde(rename_all = "camelCase"))] +pub struct MultisigOnlineOptions { + /// URL of the multisig hub + pub hub_url: String, + /// Authentication token for the multisig hub + pub hub_token: String, +} + /// Voting status for multisig operations. #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] #[cfg(any(feature = "electrum", feature = "esplora"))] @@ -480,6 +491,40 @@ pub enum Operation { status: MultisigVotingStatus, }, + // Burn variants + /// Burn operation waiting for user's response (ACK/NACK) + BurnToReview { + /// PSBT to sign + psbt: String, + /// Operation details + details: BurnDetails, + /// Operation voting status + status: MultisigVotingStatus, + }, + /// Burn operation already responded to, waiting for threshold to be met + BurnPending { + /// Operation details + details: BurnDetails, + /// Operation voting status + status: MultisigVotingStatus, + }, + /// Burn operation approved and finalized (threshold reached) + BurnCompleted { + /// Operation TXID + txid: String, + /// Operation details + details: BurnDetails, + /// Operation voting status + status: MultisigVotingStatus, + }, + /// Burn operation rejected (NACKs exceeded threshold) + BurnDiscarded { + /// Operation details + details: BurnDetails, + /// Operation voting status + status: MultisigVotingStatus, + }, + // Auto-approved operations /// Issuance operation completed (auto-approved) IssuanceCompleted { @@ -611,7 +656,7 @@ impl OperationHandler for CreateUtxosHandler { wallet: &mut MultisigWallet, combined_psbt: &Psbt, ) -> Result { - wallet.create_utxos_end_impl(combined_psbt, false)?; + wallet.create_utxos_end_impl(combined_psbt)?; Ok(combined_psbt.unsigned_tx.compute_txid().to_string()) } } @@ -647,7 +692,7 @@ impl OperationHandler for SendBtcHandler { wallet: &mut MultisigWallet, combined_psbt: &Psbt, ) -> Result { - wallet.send_btc_end_impl(combined_psbt, false)?; + wallet.send_btc_end_impl(combined_psbt)?; Ok(combined_psbt.unsigned_tx.compute_txid().to_string()) } } @@ -698,7 +743,7 @@ impl OperationHandler for SendRgbHandler { wallet: &mut MultisigWallet, combined_psbt: &Psbt, ) -> Result { - let res = wallet.send_end_impl(combined_psbt, false)?; + let res = wallet.send_end_impl(combined_psbt)?; Ok(res.txid) } @@ -777,6 +822,72 @@ impl OperationHandler for InflateHandler { } } +#[cfg(any(feature = "electrum", feature = "esplora"))] +pub(crate) struct BurnHandler; + +#[cfg(any(feature = "electrum", feature = "esplora"))] +impl OperationHandler for BurnHandler { + type Details = BurnDetails; + + fn extract_details(files: &[FileResponse]) -> Result { + let fascia_path = extract_fascia_path(files)?; + let info_batch_transfer = InfoBatchTransfer::extract_from_files(files)?; + if info_batch_transfer.transfers.len() != 1 { + return Err(Error::MultisigUnexpectedData { + details: format!( + "expected 1 transfer for burn, got {} transfers", + info_batch_transfer.transfers.len() + ), + }); + } + Ok(BurnDetails { + fascia_path, + min_confirmations: info_batch_transfer.min_confirmations, + entropy: info_batch_transfer.entropy, + }) + } + + fn to_review(psbt: String, details: Self::Details, status: MultisigVotingStatus) -> Operation { + Operation::BurnToReview { + psbt, + details, + status, + } + } + + fn pending(details: Self::Details, status: MultisigVotingStatus) -> Operation { + Operation::BurnPending { details, status } + } + + fn completed(txid: String, details: Self::Details, status: MultisigVotingStatus) -> Operation { + Operation::BurnCompleted { + txid, + details, + status, + } + } + + fn discarded(details: Self::Details, status: MultisigVotingStatus) -> Operation { + Operation::BurnDiscarded { details, status } + } + + fn finalize_and_execute( + wallet: &mut MultisigWallet, + combined_psbt: &Psbt, + ) -> Result { + let res = wallet.burn_end_impl(combined_psbt)?; + Ok(res.txid) + } + + fn reconstruct_transfer_directory( + wallet: &MultisigWallet, + txid: &str, + files: &[FileResponse], + ) -> Result<(), Error> { + wallet.reconstruct_rgb_transfer_directory(txid, files) + } +} + /// Information about an operation. #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] #[cfg(any(feature = "electrum", feature = "esplora"))] @@ -875,7 +986,6 @@ impl MultisigWallet { /// [`MultisigKeys`]. pub fn new(wallet_data: WalletData, keys: MultisigKeys) -> Result { let wdata = wallet_data.clone(); - let bdk_network = BdkNetwork::from(wdata.bitcoin_network); // wallet keys let descs = keys.build_descriptors(wdata.bitcoin_network)?; @@ -894,7 +1004,7 @@ impl MultisigWallet { descs.colored, descs.vanilla, true, - bdk_network, + BdkNetwork::from(wdata.bitcoin_network), )?; // setup RGB @@ -1054,23 +1164,15 @@ impl MultisigWallet { /// Return the existing or freshly generated wallet [`Online`] data. /// - /// Setting `skip_consistency_check` to false runs a check on assets (RGB vs rgb-lib DB) and - /// medias (DB vs actual files) to try and detect possible inconsistencies in the wallet. - /// Setting `skip_consistency_check` to true bypasses the check and allows operating an - /// inconsistent wallet. - /// - ///
Warning: setting skip_consistency_check to true is dangerous, - /// only do this if you know what you're doing!
+ /// See [`OnlineOptions`] and [`MultisigOnlineOptions`] for details on the available options. pub fn go_online( &mut self, - skip_consistency_check: bool, - indexer_url: String, - hub_url: String, - hub_token: String, + online_options: OnlineOptions, + multisig_online_options: MultisigOnlineOptions, ) -> Result { info!(self.logger(), "Going online..."); // check hub URL validity - let valid_url = match Url::parse(&hub_url) { + let valid_url = match Url::parse(&multisig_online_options.hub_url) { Ok(url) => matches!(url.scheme(), "http" | "https") && url.host_str().is_some(), Err(_) => false, }; @@ -1081,7 +1183,10 @@ impl MultisigWallet { } // check hub connectivity and configuration - let hub_client = MultisigHubClient::new(&hub_url, &hub_token)?; + let hub_client = MultisigHubClient::new( + &multisig_online_options.hub_url, + &multisig_online_options.hub_token, + )?; let info = hub_client.info()?; const RGB_LIB_VERSION: &str = env!("CARGO_PKG_VERSION"); let local_version = RGB_LIB_VERSION @@ -1101,7 +1206,7 @@ impl MultisigWallet { } // shared go online logic - let online = self.go_online_impl(skip_consistency_check, &indexer_url)?; + let online = self.go_online_impl(&online_options)?; // set multisig-specific OnlineData fields self.online_data_mut().as_mut().unwrap().hub_client = Some(hub_client); @@ -1452,27 +1557,18 @@ impl MultisigWallet { } fn accept_issuance_consignment(&mut self, files: &[FileResponse]) -> Result { - // get and validate contract + // get the validated contract let consignment_file = files .iter() .find(|f| matches!(f.r#type, FileType::Consignment)) .ok_or(Error::MultisigUnexpectedData { details: s!("issuance consignment not found"), })?; - let contract = - Contract::load_file(&consignment_file.filepath).map_err(InternalError::from)?; - let asset_schema: AssetSchema = contract.schema_id().try_into()?; - let validation_config = ValidationConfig { - chain_net: self.chain_net(), - trusted_typesystem: asset_schema.types(), - ..Default::default() - }; - let valid_contract = contract - .clone() - .validate(&DumbResolver, &validation_config) - .unwrap(); + let valid_contract = + ValidContract::load_file(&consignment_file.filepath).map_err(InternalError::from)?; + let asset_schema: AssetSchema = valid_contract.schema_id().try_into()?; - // import and save contract + // import and move contract file to the issue consignment path let mut runtime = self.rgb_runtime()?; runtime .import_contract(valid_contract.clone(), &DumbResolver) @@ -1480,7 +1576,7 @@ impl MultisigWallet { let contract_id = valid_contract.contract_id(); let asset_id = contract_id.to_string(); let contract_path = self.get_issue_consignment_path(&asset_id); - valid_contract.save_file(&contract_path)?; + fs::rename(&consignment_file.filepath, &contract_path)?; // handle media files, if any let media_files = files @@ -1532,7 +1628,13 @@ impl MultisigWallet { let txo = match self.database().get_txo(&outpoint)? { Some(txo) => txo, None => { - self.sync_db_txos(false, true)?; + self.sync_wallet( + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + true, + )?; self.database().get_txo(&outpoint)?.expect("should exist") } }; @@ -1642,7 +1744,22 @@ impl MultisigWallet { self.check_online(online)?; // make sure the wallet is synced and transfers are up-to-date - self.sync_db_txos(false, false)?; + self.sync_wallet( + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FullSync, + }, + false, + )?; + self.sync_wallet( + SyncOptions { + keychain: SyncKeychain::Vanilla { + lookback: self.vanilla_sync_lookback(), + }, + strategy: SyncStrategy::FullSync, + }, + false, + )?; self.refresh_impl(None, vec![], true)?; self.refresh_impl(None, vec![], true)?; @@ -1659,12 +1776,16 @@ impl MultisigWallet { op.operation_type, OperationType::SendRgb | OperationType::Inflation + | OperationType::Burn | OperationType::WitnessReceive | OperationType::BlindReceive ); if needs_refresh { let _ = self.refresh_impl(None, vec![], true); - if !matches!(op.operation_type, OperationType::Inflation) { + if !matches!( + op.operation_type, + OperationType::Inflation | OperationType::Burn + ) { let _ = self.refresh_impl(None, vec![], true); } } @@ -1788,6 +1909,7 @@ impl MultisigWallet { OperationType::SendBtc => self.handle_operation::(op, &files)?, OperationType::SendRgb => self.handle_operation::(op, &files)?, OperationType::Inflation => self.handle_operation::(op, &files)?, + OperationType::Burn => self.handle_operation::(op, &files)?, OperationType::Issuance => match op.status { OperationStatus::Approved => { let asset_id = self.accept_issuance_consignment(&files)?; @@ -2077,6 +2199,36 @@ impl MultisigWallet { info!(self.logger(), "Initiate inflating completed"); Ok(res) } + + /// Prepare the PSBT to burn the specified `amount` of RGB assets, with the provided `fee_rate` + /// (in sat/vB) and post the operation to the hub. + /// + /// The `min_confirmations` number determines the minimum number of confirmations needed for + /// the transaction anchoring the transfer for it to be considered final and move (while + /// refreshing) to the [`TransferStatus::Settled`] status. + /// + /// Returns a PSBT ready to be signed and the operation index on the hub. + pub fn burn_init( + &mut self, + online: Online, + asset_id: String, + amount: u64, + fee_rate: u64, + min_confirmations: u8, + ) -> Result { + info!(self.logger(), "Initiate burning amount: {}...", amount); + self.check_online(online)?; + self.check_is_cosigner()?; + + let data = self.burn_begin_impl(asset_id, amount, fee_rate, min_confirmations, true)?; + let res = self.post_operation( + OperationType::Burn, + PostData::BeginOperationData(Box::new(data)), + )?; + self.update_backup_info(false)?; + info!(self.logger(), "Initiate burning completed"); + Ok(res) + } } #[cfg(test)] diff --git a/src/wallet/objects.rs b/src/wallet/objects.rs index 1de14e09..7245c599 100644 --- a/src/wallet/objects.rs +++ b/src/wallet/objects.rs @@ -66,6 +66,28 @@ pub struct OnlineData { pub(crate) resolver: AnyResolver, pub(crate) hub_client: Option, pub(crate) user_role: Option, + pub(crate) vanilla_sync_lookback: u32, +} + +/// Options for the [`Wallet::go_online`] and [`MultisigWallet::go_online`] methods. +#[cfg(any(feature = "electrum", feature = "esplora"))] +#[derive(Debug, Clone, Deserialize, Serialize)] +#[cfg_attr(feature = "camel_case", serde(rename_all = "camelCase"))] +pub struct OnlineOptions { + /// URL of the indexer to use + pub indexer_url: String, + /// Whether to skip the consistency check when going online. + /// + /// Setting this to false runs a check on UTXOs (BDK vs rgb-lib DB), assets (RGB vs rgb-lib DB) + /// and media (DB vs actual files) to try and detect possible inconsistencies in the wallet. + /// Setting this to true bypasses the check and allows operating an inconsistent wallet. + /// + ///
Warning: setting skip_consistency_check to true is dangerous, + /// only do this if you know what you're doing!
+ pub skip_consistency_check: bool, + /// Number of addresses before the last used (or last revealed if none) address to sync when + /// doing an automatic FastSync for the vanilla keychain + pub vanilla_sync_lookback: u32, } // ──────────────────────────────────────────────────────────── @@ -849,6 +871,8 @@ pub enum TypeOfTransition { Inflate, /// Transfer transition (moving existing tokens) Transfer, + /// Burn transition (burning existing tokens) + Burn, } impl TypeOfTransition { @@ -857,6 +881,7 @@ impl TypeOfTransition { match self { Self::Inflate => "inflate", Self::Transfer => "transfer", + Self::Burn => "burn", } } } @@ -1163,6 +1188,8 @@ pub enum TransferKind { Send, /// An inflation transfer Inflation, + /// A burn transfer + Burn, } #[derive(Debug, Clone)] @@ -1563,9 +1590,35 @@ pub struct RgbInspection { } // ──────────────────────────────────────────────────────────── -// Send, inflate & refresh operations +// Send, inflate, burn & refresh operations // ──────────────────────────────────────────────────────────── +/// The result of a burn begin operation. +#[derive(Debug, Clone, Deserialize, Serialize)] +#[cfg(any(feature = "electrum", feature = "esplora"))] +#[cfg_attr(feature = "camel_case", serde(rename_all = "camelCase"))] +pub struct BurnBeginResult { + /// PSBT to inspect and sign + pub psbt: String, + /// Batch transfer idx, None when `dry_run: true` + pub batch_transfer_idx: Option, + /// Operation details + pub details: BurnDetails, +} + +/// Details for burn operations. +#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +#[cfg(any(feature = "electrum", feature = "esplora"))] +#[cfg_attr(feature = "camel_case", serde(rename_all = "camelCase"))] +pub struct BurnDetails { + /// Path to fascia file for inspection + pub fascia_path: String, + /// Minimum confirmations for the operation + pub min_confirmations: u8, + /// Entropy used for the merkle tree construction operation + pub entropy: u64, +} + /// The result of an inflate begin operation. #[derive(Debug, Clone, Deserialize, Serialize)] #[cfg(any(feature = "electrum", feature = "esplora"))] @@ -1840,3 +1893,10 @@ pub enum PrepareTransferPsbtResult { Retry, Success(Box), } + +#[cfg(any(feature = "electrum", feature = "esplora"))] +#[derive(Debug, Deserialize, Serialize)] +pub struct ReceivedConsignmentMeta { + pub txid: String, + pub vout: Option, +} diff --git a/src/wallet/offline.rs b/src/wallet/offline.rs index 01b296dd..e0917ee3 100644 --- a/src/wallet/offline.rs +++ b/src/wallet/offline.rs @@ -8,7 +8,7 @@ const TRANSFERS_DIR: &str = "transfers"; const CONSIGNMENT_RCV_FILE: &str = "rcv_compose.rgbc"; -const MIN_BTC_REQUIRED: u64 = 2000; +const CONSIGNMENT_RCV_META_FILE: &str = "rcv_compose.meta.json"; const ASSET_ID_PREFIX: &str = "rgb:"; @@ -269,18 +269,6 @@ pub trait WalletOffline: WalletBackup { .collect()) } - fn detect_btc_unspendable_err(&self) -> Result { - let available = self.get_uncolorable_btc_sum()?; - Ok(if available < MIN_BTC_REQUIRED { - Error::InsufficientBitcoins { - needed: MIN_BTC_REQUIRED, - available, - } - } else { - Error::InsufficientAllocationSlots - }) - } - fn get_utxo( &self, exclude_utxos: &[Outpoint], @@ -325,7 +313,7 @@ pub trait WalletOffline: WalletBackup { } Ok(selected.clone().utxo) } - None => Err(self.detect_btc_unspendable_err()?), + None => Err(Error::InsufficientAllocationSlots), } } @@ -1621,7 +1609,8 @@ pub trait WalletOffline: WalletBackup { online: Option, skip_sync: bool, ) -> Result { - self.sync_if_requested(online, skip_sync)?; + self.sync_if_requested(online, skip_sync, KeychainKind::External)?; + self.sync_if_requested(online, skip_sync, KeychainKind::Internal)?; let mut vanilla = self.get_btc_balance_for_keychain(KeychainKind::Internal)?; let colored = self.get_btc_balance_for_keychain(KeychainKind::External)?; @@ -1951,6 +1940,11 @@ pub trait WalletOffline: WalletBackup { )] online: Option, skip_sync: bool, + #[cfg_attr( + not(any(feature = "electrum", feature = "esplora")), + allow(unused_variables) + )] + keychain: KeychainKind, ) -> Result<(), Error> { if !skip_sync { #[cfg(not(any(feature = "electrum", feature = "esplora")))] @@ -1962,7 +1956,19 @@ pub trait WalletOffline: WalletBackup { } else { return Err(Error::OnlineNeeded); } - self.sync_db_txos(false, false)?; + let keychain = match keychain { + KeychainKind::Internal => SyncKeychain::Vanilla { + lookback: self.vanilla_sync_lookback(), + }, + KeychainKind::External => SyncKeychain::Colored, + }; + self.sync_wallet( + SyncOptions { + keychain, + strategy: SyncStrategy::FastSync, + }, + false, + )?; } } Ok(()) @@ -1973,7 +1979,8 @@ pub trait WalletOffline: WalletBackup { online: Option, skip_sync: bool, ) -> Result, Error> { - self.sync_if_requested(online, skip_sync)?; + self.sync_if_requested(online, skip_sync, KeychainKind::External)?; + self.sync_if_requested(online, skip_sync, KeychainKind::Internal)?; let mut create_utxos_txids = vec![]; let mut drain_txids = vec![]; @@ -2040,6 +2047,16 @@ pub trait WalletOffline: WalletBackup { .join(CONSIGNMENT_RCV_FILE) } + fn get_receive_consignment_meta_path(&self, recipient_id: &str) -> PathBuf { + self.get_transfers_dir() + .join(self.normalize_recipient_id(recipient_id)) + .join(CONSIGNMENT_RCV_META_FILE) + } + + fn get_receive_valid_consignment_path(&self, consignment_path: &Path) -> PathBuf { + consignment_path.with_extension("valid.rgbc") + } + fn send_consignment_path(&self, asset_id: &str, transfer_id: &str) -> PathBuf { let transfer_dir = self.get_transfer_dir(transfer_id); let asset_transfer_dir = self.get_asset_transfer_dir(transfer_dir, asset_id); @@ -2078,10 +2095,12 @@ pub trait WalletOffline: WalletBackup { RecipientTypeFull::Witness { .. } => TransferKind::ReceiveWitness, } } - } else if filtered_coloring.clone().count() > 0 - && filtered_coloring - .clone() - .any(|c| c.r#type == ColoringType::Issue) + } else if transfer.recipient_id.is_none() { + // burn is the only outgoing transfer with no recipient + TransferKind::Burn + } else if filtered_coloring + .clone() + .any(|c| c.r#type == ColoringType::Issue) { // inflation transfer is outgoing and connected to issue colorings TransferKind::Inflation @@ -2117,7 +2136,7 @@ pub trait WalletOffline: WalletBackup { }; let change_utxo = match kind { TransferKind::ReceiveBlind | TransferKind::ReceiveWitness => None, - TransferKind::Send | TransferKind::Inflation => { + TransferKind::Send | TransferKind::Inflation | TransferKind::Burn => { let change_txo_idx: Vec = filtered_coloring .filter(|c| c.r#type == ColoringType::Change) .map(|c| c.txo_idx) @@ -2134,10 +2153,12 @@ pub trait WalletOffline: WalletBackup { }; let consignment_path = match (&kind, batch_transfer.status) { - (TransferKind::Send | TransferKind::Inflation, _) => Some(self.send_consignment_path( - &asset_transfer.asset_id.clone().unwrap(), - &batch_transfer.txid.clone().unwrap(), - )), + (TransferKind::Send | TransferKind::Inflation | TransferKind::Burn, _) => { + Some(self.send_consignment_path( + &asset_transfer.asset_id.clone().unwrap(), + &batch_transfer.txid.clone().unwrap(), + )) + } ( TransferKind::ReceiveBlind | TransferKind::ReceiveWitness, TransferStatus::WaitingCounterparty, @@ -2207,7 +2228,8 @@ pub trait WalletOffline: WalletBackup { settled_only: bool, skip_sync: bool, ) -> Result, Error> { - self.sync_if_requested(online, skip_sync)?; + self.sync_if_requested(online, skip_sync, KeychainKind::External)?; + self.sync_if_requested(online, skip_sync, KeychainKind::Internal)?; let db_data = self.database().get_db_data(false)?; @@ -2521,6 +2543,7 @@ pub trait WalletOffline: WalletBackup { let kind = match transition.transition_type { TS_TRANSFER => TypeOfTransition::Transfer, TS_INFLATION => TypeOfTransition::Inflate, + TS_BURN => TypeOfTransition::Burn, _ => { return Err(Error::RgbInspection { details: format!( diff --git a/src/wallet/online.rs b/src/wallet/online.rs index 0bd08cfe..6171768b 100644 --- a/src/wallet/online.rs +++ b/src/wallet/online.rs @@ -4,6 +4,7 @@ use super::*; +const SCHEMAS_SUPPORTING_BURN: [database::enums::AssetSchema; 1] = [AssetSchema::Ifa]; const SCHEMAS_SUPPORTING_INFLATION: [database::enums::AssetSchema; 1] = [AssetSchema::Ifa]; const SIGNED_PSBT_FILE: &str = "signed.psbt"; @@ -24,7 +25,7 @@ pub trait WalletOnline: WalletOffline { fn check_fee_rate(&self, fee_rate: u64) -> Result { #[cfg(test)] if skip_check_fee_rate() { - return Ok(FeeRate::from_sat_per_vb_unchecked(fee_rate)); + return Ok(FeeRate::from_sat_per_vb(fee_rate).unwrap()); }; if fee_rate < MIN_FEE_RATE { return Err(Error::InvalidFeeRate { @@ -39,9 +40,9 @@ pub trait WalletOnline: WalletOffline { Ok(fee_rate) } - fn sync_impl(&mut self, online: Online) -> Result<(), Error> { + fn sync_impl(&mut self, online: Online, options: SyncOptions) -> Result<(), Error> { self.check_online(online)?; - self.sync_db_txos_with_bdk(false, false)?; + self.sync_bdk_and_db_txos(options, false)?; Ok(()) } @@ -87,11 +88,7 @@ pub trait WalletOnline: WalletOffline { } } - fn broadcast_psbt( - &mut self, - signed_psbt: &Psbt, - skip_sync: bool, - ) -> Result { + fn broadcast_psbt(&mut self, signed_psbt: &Psbt) -> Result { let tx = self.broadcast_tx( signed_psbt .clone() @@ -99,6 +96,17 @@ pub trait WalletOnline: WalletOffline { .map_err(InternalError::from)?, )?; + // apply the broadcast TX into BDK directly so its outputs are immediately visible + // (revealed change SPKs match without needing a wallet sync) + let seen_at = now().unix_timestamp() as u64; + let (bdk_wallet, bdk_db) = self.bdk_wallet_db_mut(); + bdk_wallet.apply_unconfirmed_txs([(tx.clone(), seen_at)]); + bdk_wallet.persist(bdk_db)?; + + // promote any newly-known colored UTXOs (e.g. the change output) from + // exists=false to exists=true in the rgb_lib DB + self.update_db_colored_txos_from_bdk(false)?; + for input in tx.clone().input { let txid = input.previous_output.txid.to_string(); let vout = input.previous_output.vout; @@ -109,10 +117,6 @@ pub trait WalletOnline: WalletOffline { } } - if !skip_sync { - self.sync_db_txos(false, false)?; - } - Ok(tx) } @@ -174,9 +178,8 @@ pub trait WalletOnline: WalletOffline { runtime: &mut RgbRuntime, signed_psbt: &Psbt, fascia: Fascia, - skip_sync: bool, ) -> Result { - let tx = self.broadcast_psbt(signed_psbt, skip_sync)?; + let tx = self.broadcast_psbt(signed_psbt)?; runtime.consume_fascia(fascia, None)?; Ok(tx) } @@ -212,7 +215,15 @@ pub trait WalletOnline: WalletOffline { let fee_rate_checked = self.check_fee_rate(fee_rate)?; if !skip_sync { - self.sync_db_txos(false, false)?; + self.sync_wallet( + SyncOptions { + keychain: SyncKeychain::Vanilla { + lookback: self.vanilla_sync_lookback(), + }, + strategy: SyncStrategy::FastSync, + }, + false, + )?; } let unspent_txos = self.database().get_unspent_txos(vec![])?; @@ -298,19 +309,17 @@ pub trait WalletOnline: WalletOffline { }) } - fn create_utxos_end_impl(&mut self, signed_psbt: &Psbt, skip_sync: bool) -> Result { - let tx = self.broadcast_psbt(signed_psbt, skip_sync)?; + fn create_utxos_end_impl(&mut self, signed_psbt: &Psbt) -> Result { + let tx = self.broadcast_psbt(signed_psbt)?; self.finalize_vanilla_wallet_transaction(signed_psbt, WalletTransactionType::CreateUtxos)?; let mut num_utxos_created = 0; - if !skip_sync { - let bdk_utxos: Vec = self.bdk_wallet().list_unspent().collect(); - let txid = tx.compute_txid(); - for utxo in bdk_utxos.into_iter() { - if utxo.outpoint.txid == txid && utxo.keychain == KeychainKind::External { - num_utxos_created += 1 - } + let bdk_utxos: Vec = self.bdk_wallet().list_unspent().collect(); + let txid = tx.compute_txid(); + for utxo in bdk_utxos.into_iter() { + if utxo.outpoint.txid == txid && utxo.keychain == KeychainKind::External { + num_utxos_created += 1 } } @@ -325,7 +334,22 @@ pub trait WalletOnline: WalletOffline { ) -> Result { let fee_rate_checked = self.check_fee_rate(fee_rate)?; - self.sync_db_txos(false, false)?; + self.sync_wallet( + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + false, + )?; + self.sync_wallet( + SyncOptions { + keychain: SyncKeychain::Vanilla { + lookback: self.vanilla_sync_lookback(), + }, + strategy: SyncStrategy::FastSync, + }, + false, + )?; let script_pubkey = self.get_script_pubkey(&address)?; @@ -359,7 +383,7 @@ pub trait WalletOnline: WalletOffline { } fn drain_to_end_impl(&mut self, signed_psbt: &Psbt) -> Result { - let tx = self.broadcast_psbt(signed_psbt, false)?; + let tx = self.broadcast_psbt(signed_psbt)?; self.finalize_vanilla_wallet_transaction(signed_psbt, WalletTransactionType::Drain)?; Ok(tx) } @@ -419,7 +443,13 @@ pub trait WalletOnline: WalletOffline { skip_sync: bool, ) -> Result { if !skip_sync { - self.sync_db_txos(false, false)?; + self.sync_wallet( + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + false, + )?; } let mut db_data = self.database().get_db_data(false)?; @@ -430,7 +460,7 @@ pub trait WalletOnline: WalletOffline { .database() .get_batch_transfer_or_fail(batch_transfer_idx, &db_data.batch_transfers)?; - if !(batch_transfer.initiated() || batch_transfer.waiting_counterparty()) { + if !batch_transfer.is_fallible() { return Err(Error::CannotFailBatchTransfer); } @@ -446,11 +476,11 @@ pub trait WalletOnline: WalletOffline { transfers_changed = true; self.try_fail_batch_transfer(batch_transfer, true, &mut db_data)? } else { - // fail all expired transfers in status Initiated or WaitingCounterparty + // fail all expired transfers that are in a fallible status let now = now().unix_timestamp(); let expired_batch_transfers = db_data.batch_transfers.clone().into_iter().filter(|t| { let expired = t.expiration.unwrap_or(now) < now; - expired && (t.initiated() || t.waiting_counterparty()) + expired && t.is_fallible() }); for batch_transfer in expired_batch_transfers { if no_asset_only { @@ -514,34 +544,36 @@ pub trait WalletOnline: WalletOffline { self.indexer().fee_estimation(blocks) } - fn get_online_data(&self, indexer_url: &str) -> Result<(Online, OnlineData), Error> { + fn get_online_data( + &self, + online_options: &OnlineOptions, + ) -> Result<(Online, OnlineData), Error> { let id = now().unix_timestamp_nanos() as u64; let online = Online { id }; - let (indexer, resolver) = get_indexer_and_resolver(indexer_url, self.bitcoin_network())?; + let (indexer, resolver) = + get_indexer_and_resolver(&online_options.indexer_url, self.bitcoin_network())?; indexer.populate_tx_cache(self.bdk_wallet()); let online_data = OnlineData { id: online.id, - indexer_url: indexer_url.to_string(), + indexer_url: online_options.indexer_url.to_string(), indexer, resolver, hub_client: None, user_role: None, + vanilla_sync_lookback: online_options.vanilla_sync_lookback, }; Ok((online, online_data)) } - fn go_online_impl( - &mut self, - skip_consistency_check: bool, - indexer_url: &str, - ) -> Result { + fn go_online_impl(&mut self, online_options: &OnlineOptions) -> Result { + let indexer_url = &online_options.indexer_url; let online = if let Some(online_data) = self.online_data().as_ref() { let online = Online { id: online_data.id }; - if online_data.indexer_url != indexer_url { - let (online, online_data) = self.get_online_data(indexer_url)?; + if online_data.indexer_url != *indexer_url { + let (online, online_data) = self.get_online_data(online_options)?; *self.online_data_mut() = Some(online_data); info!(self.logger(), "Went online with new indexer URL"); online @@ -550,12 +582,12 @@ pub trait WalletOnline: WalletOffline { online } } else { - let (online, online_data) = self.get_online_data(indexer_url)?; + let (online, online_data) = self.get_online_data(online_options)?; *self.online_data_mut() = Some(online_data); online }; - if !skip_consistency_check { + if !online_options.skip_consistency_check { let runtime = self.rgb_runtime()?; self.check_consistency(&runtime)?; } @@ -812,6 +844,68 @@ pub trait WalletOnline: WalletOffline { attachments } + fn safe_height(&self, min_confirmations: u8) -> Result { + Ok(self + .indexer() + .get_latest_block_height()? + .saturating_sub(min_confirmations as u32) + + 1) + } + + fn collect_unsafe_history_txids(warnings: &[Warning], exclude_txid: &str) -> HashSet { + let mut txids = HashSet::new(); + for warning in warnings { + if let Warning::UnsafeHistory(unsafe_history) = warning { + for other_txids in unsafe_history.values() { + for txid in other_txids { + let txid = txid.to_string(); + if txid != *exclude_txid { + txids.insert(txid); + } + } + } + } + } + txids + } + + fn ack_consignment( + &self, + batch_transfer: &DbBatchTransfer, + recipient_id: String, + updated_batch_transfer: &mut DbBatchTransferActMod, + proxy_url: String, + ) -> Result, Error> { + debug!(self.logger(), "ACKing consignment..."); + + match self.set_hub_accept_status(batch_transfer.idx)? { + Some(true) => {} + Some(false) => return Ok(Some(self.fail_batch_transfer(batch_transfer)?)), + None => return Ok(None), + } + + let proxy_client = ProxyClient::new(&proxy_url)?; + match proxy_client.post_ack(&recipient_id, true) { + Ok(r) => { + debug!(self.logger(), "Consignment ACK response: {:?}", r); + } + Err(e) if e.to_string().contains("Cannot change ACK") => { + warn!(self.logger(), "Found an NACK when trying ACK"); + } + Err(e) => { + error!(self.logger(), "Failed to post ACK: {e}"); + return Err(e); + } + }; + + updated_batch_transfer.status = ActiveValue::Set(TransferStatus::WaitingConfirmations); + + Ok(Some( + self.database() + .update_batch_transfer(updated_batch_transfer)?, + )) + } + fn wait_consignment( &self, batch_transfer: &DbBatchTransfer, @@ -819,18 +913,14 @@ pub trait WalletOnline: WalletOffline { ) -> Result, Error> { debug!(self.logger(), "Waiting consignment..."); - let batch_transfer_data = - batch_transfer.get_transfers(&db_data.asset_transfers, &db_data.transfers)?; - let (asset_transfer, transfer) = self - .database() - .get_incoming_transfer(&batch_transfer_data)?; + let (asset_transfer, transfer) = + batch_transfer.get_incoming_transfer(&db_data.asset_transfers, &db_data.transfers)?; let recipient_id = transfer .recipient_id .clone() .expect("transfer should have a recipient ID"); debug!(self.logger(), "Recipient ID: {recipient_id}"); - // check if a consignment has been posted let tte_data = self .database() .get_transfer_transport_endpoints_data(transfer.idx)?; @@ -839,10 +929,37 @@ pub trait WalletOnline: WalletOffline { { return Ok(Some(updated_transfer)); } - let mut proxy_res = None; - for (transfer_transport_endpoint, transport_endpoint) in tte_data { - let result = - match self.get_consignment(&transport_endpoint.endpoint, recipient_id.clone()) { + + let mut updated_batch_transfer: DbBatchTransferActMod = batch_transfer.clone().into(); + + // if we already downloaded the consignment and its metadata in a + // previous attempt that failed during validation for a transient + // reason (e.g. network error), reuse them instead of hitting the proxy + // again; the endpoint we used is recoverable from the DB via the + // `used` flag on the transfer transport endpoint + let consignment_path = self.get_receive_consignment_path(&recipient_id); + let consignment_meta_path = self.get_receive_consignment_meta_path(&recipient_id); + let (proxy_url, txid, vout) = if consignment_path.exists() + && consignment_meta_path.exists() + && let Some(cached_proxy_url) = tte_data + .iter() + .find(|(tte, _)| tte.used) + .map(|(_, te)| te.endpoint.clone()) + && let Ok(meta_str) = fs::read_to_string(&consignment_meta_path) + && let Ok(meta) = serde_json::from_str::(&meta_str) + { + debug!( + self.logger(), + "Reusing previously-downloaded consignment for {recipient_id}" + ); + (cached_proxy_url, meta.txid, meta.vout) + } else { + // download consignment and its metadata + let mut proxy_res = None; + for (transfer_transport_endpoint, transport_endpoint) in tte_data { + let result = match self + .get_consignment(&transport_endpoint.endpoint, recipient_id.clone()) + { Err(Error::NoConsignment) => { info!( self.logger(), @@ -854,46 +971,54 @@ pub trait WalletOnline: WalletOffline { Ok(r) => r, }; - proxy_res = Some(( - result.consignment, - transport_endpoint.endpoint, - result.txid, - result.vout, - )); - let mut updated_transfer_transport_endpoint: DbTransferTransportEndpointActMod = - transfer_transport_endpoint.into(); - updated_transfer_transport_endpoint.used = ActiveValue::Set(true); - self.database() - .update_transfer_transport_endpoint(&mut updated_transfer_transport_endpoint)?; - break; - } - let (consignment, proxy_url, txid, vout) = if let Some(res) = proxy_res { - (res.0, res.1, res.2, res.3) - } else { - return Ok(None); - }; + proxy_res = Some(( + result.consignment, + transport_endpoint.endpoint, + result.txid, + result.vout, + )); + let mut updated_transfer_transport_endpoint: DbTransferTransportEndpointActMod = + transfer_transport_endpoint.into(); + updated_transfer_transport_endpoint.used = ActiveValue::Set(true); + self.database() + .update_transfer_transport_endpoint(&mut updated_transfer_transport_endpoint)?; + break; + } + let (consignment_b64, proxy_url, txid, vout) = if let Some(res) = proxy_res { + (res.0, res.1, res.2, res.3) + } else { + return Ok(None); + }; - let mut updated_batch_transfer: DbBatchTransferActMod = batch_transfer.clone().into(); + // write consignment + let transfer_dir = consignment_path.parent().unwrap(); + fs::create_dir_all(transfer_dir)?; + let consignment_bytes = match general_purpose::STANDARD.decode(consignment_b64) { + Ok(b) => b, + Err(e) => { + error!(self.logger(), "Failed to decode consignment bytes: {e}"); + return self.refuse_consignment( + proxy_url, + recipient_id, + &mut updated_batch_transfer, + ); + } + }; + fs::write(&consignment_path, consignment_bytes).expect("Unable to write file"); - // write consignment - let consignment_path = self.get_receive_consignment_path(&recipient_id); - let transfer_dir = consignment_path.parent().unwrap(); - fs::create_dir_all(transfer_dir)?; - let consignment_bytes = match general_purpose::STANDARD.decode(consignment) { - Ok(b) => b, - Err(e) => { - error!(self.logger(), "Failed to decode consignment bytes: {e}"); - return self.refuse_consignment( - proxy_url, - recipient_id, - &mut updated_batch_transfer, - ); - } + // write consignment metadata + let meta = ReceivedConsignmentMeta { + txid: txid.clone(), + vout, + }; + let meta_str = serde_json::to_string(&meta).map_err(InternalError::from)?; + fs::write(&consignment_meta_path, meta_str)?; + + (proxy_url, txid, vout) }; - fs::write(consignment_path.clone(), consignment_bytes).expect("Unable to write file"); let mut runtime = self.rgb_runtime()?; - let consignment = match RgbTransfer::load_file(consignment_path) { + let consignment = match RgbTransfer::load_file(&consignment_path) { Ok(c) => c, Err(e) => { error!(self.logger(), "Failed to load consignment file: {e}"); @@ -948,12 +1073,12 @@ pub trait WalletOnline: WalletOffline { // validate consignment debug!(self.logger(), "Validating consignment..."); - let trusted_typesystem = asset_schema.types(); + let safe_height = NonZeroU32::new(self.safe_height(batch_transfer.min_confirmations)?); let validation_config = ValidationConfig { chain_net: self.chain_net(), - trusted_typesystem, + trusted_typesystem: asset_schema.types(), build_opouts_dag: true, - ..Default::default() + safe_height, }; let resolver = OffchainResolver { witness_id, @@ -1052,9 +1177,9 @@ pub trait WalletOnline: WalletOffline { } else { None }; - let received = + let receiving = self.extract_received_assignments(&consignment, witness_id, vout, known_concealed); - if received.is_empty() { + if receiving.is_empty() { error!(self.logger(), "Cannot find any receiving assignment"); return self.refuse_consignment(proxy_url, recipient_id, &mut updated_batch_transfer); }; @@ -1076,7 +1201,7 @@ pub trait WalletOnline: WalletOffline { .expect("build_opouts_dag is true"), &reject_opouts, &allow_opouts, - &received.clone().into_keys().collect(), + &receiving.clone().into_keys().collect(), )?; if !to_reject.is_empty() { @@ -1099,16 +1224,18 @@ pub trait WalletOnline: WalletOffline { } } - // add asset info to transfer if missing if asset_transfer.asset_id.is_none() { - // check if asset is known - let exists_check = self.database().check_asset_exists(asset_id.clone()); - if exists_check.is_err() { + if self + .database() + .check_asset_exists(asset_id.clone()) + .is_err() + { // unknown asset debug!(self.logger(), "Receiving unknown contract..."); let valid_contract = valid_consignment.clone().into_valid_contract(); let attachments = self.extract_attachments(&valid_contract, asset_schema); + let mut saved_media_paths = vec![]; for attachment in attachments { let digest = hex::encode(attachment.digest); let media_path = self.media_dir().join(&digest); @@ -1135,11 +1262,15 @@ pub trait WalletOnline: WalletOffline { ); } fs::write(&media_path, file_bytes)?; + saved_media_paths.push(media_path); } else { error!( self.logger(), "Cannot find the media file but the contract defines one" ); + for path in saved_media_paths { + fs::remove_file(path)?; + } return self.refuse_consignment( proxy_url, recipient_id, @@ -1158,40 +1289,27 @@ pub trait WalletOnline: WalletOffline { contract_id, asset_schema, valid_contract, - Some(valid_consignment), + Some(valid_consignment.clone()), )?; } + // add asset info to transfer if missing let mut updated_asset_transfer: DbAssetTransferActMod = asset_transfer.clone().into(); updated_asset_transfer.asset_id = ActiveValue::Set(Some(asset_id.clone())); self.database() .update_asset_transfer(&mut updated_asset_transfer)?; } + // save validated consignment + let valid_consignment_path = self.get_receive_valid_consignment_path(&consignment_path); + valid_consignment.save_file(&valid_consignment_path)?; + debug!( self.logger(), - "Consignment is valid. Received '{:?}' of contract '{}'", received, asset_id + "Consignment is valid. Receiving '{:?}' of contract '{}'", receiving, asset_id ); - match self.set_hub_accept_status(batch_transfer.idx)? { - Some(true) => {} - Some(false) => return Ok(Some(self.fail_batch_transfer(batch_transfer)?)), - None => return Ok(None), - } - - let proxy_client = ProxyClient::new(&proxy_url)?; - match proxy_client.post_ack(&recipient_id, true) { - Ok(r) => { - debug!(self.logger(), "Consignment ACK response: {:?}", r); - } - Err(e) if e.to_string().contains("Cannot change ACK") => { - warn!(self.logger(), "Found an NACK when trying ACK"); - } - Err(e) => { - error!(self.logger(), "Failed to post ACK: {e}"); - return Err(e); - } - }; + updated_batch_transfer.txid = ActiveValue::Set(Some(txid.clone())); let utxo_idx = match transfer.recipient_type { Some(RecipientTypeFull::Blind { ref unblinded_utxo }) => { @@ -1218,7 +1336,7 @@ pub trait WalletOnline: WalletOffline { } _ => return Err(InternalError::Unexpected.into()), }; - for assignment in received.into_values() { + for assignment in receiving.into_values() { let db_coloring = DbColoringActMod { txo_idx: ActiveValue::Set(utxo_idx), asset_transfer_idx: ActiveValue::Set(asset_transfer.idx), @@ -1229,20 +1347,87 @@ pub trait WalletOnline: WalletOffline { self.database().set_coloring(db_coloring)?; } - updated_batch_transfer.txid = ActiveValue::Set(Some(txid)); - updated_batch_transfer.status = ActiveValue::Set(TransferStatus::WaitingConfirmations); + // if the consignment contains unsafe history set status to WaitingSafeHeight and stop here + if validation_status.validity() == Validity::Warnings { + let unsafe_txids = + Self::collect_unsafe_history_txids(&validation_status.warnings, &txid); + if !unsafe_txids.is_empty() { + warn!( + self.logger(), + "Unsafe history detected in consignment: {unsafe_txids:?}" + ); + updated_batch_transfer.status = ActiveValue::Set(TransferStatus::WaitingSafeHeight); + return Ok(Some( + self.database() + .update_batch_transfer(&mut updated_batch_transfer)?, + )); + } + } - Ok(Some( - self.database() - .update_batch_transfer(&mut updated_batch_transfer)?, - )) + self.ack_consignment( + batch_transfer, + recipient_id, + &mut updated_batch_transfer, + proxy_url, + ) + } + + fn wait_safe_height( + &mut self, + batch_transfer: &DbBatchTransfer, + db_data: &mut DbData, + ) -> Result, Error> { + debug!(self.logger(), "Waiting safe height..."); + + let (_, transfer) = + batch_transfer.get_incoming_transfer(&db_data.asset_transfers, &db_data.transfers)?; + let recipient_id = transfer + .recipient_id + .clone() + .expect("transfer should have a recipient ID"); + let consignment_path = self.get_receive_consignment_path(&recipient_id); + let valid_consignment_path = self.get_receive_valid_consignment_path(&consignment_path); + let valid_consignment = + ValidTransfer::load_file(&valid_consignment_path).map_err(InternalError::from)?; + let validation_status = valid_consignment.validation_status(); + let txid = batch_transfer + .txid + .as_deref() + .expect("batch_transfer in WaitingSafeHeight must have a txid"); + let unsafe_txids = Self::collect_unsafe_history_txids(&validation_status.warnings, txid); + + if !unsafe_txids.is_empty() { + let safe_height = self.safe_height(batch_transfer.min_confirmations)?; + for txid in unsafe_txids { + let Some(tx_height) = self.tx_height(txid)? else { + return Ok(None); + }; + if tx_height > safe_height { + return Ok(None); + } + } + } + + let mut updated_batch_transfer: DbBatchTransferActMod = batch_transfer.clone().into(); + let tte_data = self + .database() + .get_transfer_transport_endpoints_data(transfer.idx)?; + let (_, transport_endpoint) = tte_data + .into_iter() + .find(|(tte, _)| tte.used) + .expect("there should be 1 used TTE"); + self.ack_consignment( + batch_transfer, + recipient_id, + &mut updated_batch_transfer, + transport_endpoint.endpoint, + ) } fn wait_ack( &mut self, batch_transfer: &DbBatchTransfer, db_data: &mut DbData, - skip_sync: bool, ) -> Result, Error> { debug!(self.logger(), "Waiting ACK..."); @@ -1322,7 +1507,7 @@ pub trait WalletOnline: WalletOffline { let fascia_path = transfer_dir.join(FASCIA_FILE); let fascia_str = fs::read_to_string(fascia_path)?; let fascia: Fascia = serde_json::from_str(&fascia_str).map_err(InternalError::from)?; - self.broadcast_and_update_rgb(&mut runtime, &signed_psbt, fascia, skip_sync)?; + self.broadcast_and_update_rgb(&mut runtime, &signed_psbt, fascia)?; updated_batch_transfer.status = ActiveValue::Set(TransferStatus::WaitingConfirmations); } else { return Ok(None); @@ -1379,23 +1564,23 @@ pub trait WalletOnline: WalletOffline { } if incoming { - let batch_transfer_data = - batch_transfer.get_transfers(&db_data.asset_transfers, &db_data.transfers)?; - let (asset_transfer, transfer) = self - .database() - .get_incoming_transfer(&batch_transfer_data)?; + let (asset_transfer, transfer) = batch_transfer + .get_incoming_transfer(&db_data.asset_transfers, &db_data.transfers)?; let recipient_id = transfer .clone() .recipient_id .expect("transfer should have a recipient ID"); debug!(self.logger(), "Recipient ID: {recipient_id}"); - let consignment_path = self.get_receive_consignment_path(&recipient_id); - let consignment = - RgbTransfer::load_file(consignment_path).map_err(InternalError::from)?; if let Some(RecipientTypeFull::Witness { vout }) = transfer.recipient_type { if !skip_sync { - self.sync_db_txos(false, false)?; + self.sync_wallet( + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + false, + )?; } let outpoint = Outpoint { txid: txid.clone(), @@ -1408,23 +1593,13 @@ pub trait WalletOnline: WalletOffline { } // accept consignment - let mut safe_height = None; - if let Some(tx_height) = self.tx_height(txid)? { - safe_height = Some(NonZeroU32::new(tx_height).unwrap()) - } - let asset_schema: AssetSchema = consignment.schema_id().try_into()?; - let validation_config = ValidationConfig { - chain_net: self.chain_net(), - trusted_typesystem: asset_schema.types(), - safe_height, - ..Default::default() - }; - let valid_consignment = consignment - .validate(self.blockchain_resolver(), &validation_config) - .map_err(|_| InternalError::Unexpected)?; + let consignment_path = self.get_receive_consignment_path(&recipient_id); + let valid_consignment_path = self.get_receive_valid_consignment_path(&consignment_path); + let valid_consignment = + ValidTransfer::load_file(&valid_consignment_path).map_err(InternalError::from)?; let mut runtime = self.rgb_runtime()?; - let validation_status = - runtime.accept_transfer(valid_consignment.clone(), self.blockchain_resolver())?; + runtime.accept_transfer(valid_consignment.clone(), self.blockchain_resolver())?; + let asset_schema: AssetSchema = valid_consignment.schema_id().try_into()?; if asset_schema == AssetSchema::Ifa { let contract_id = valid_consignment.contract_id(); let contract_wrapper = @@ -1445,21 +1620,6 @@ pub trait WalletOnline: WalletOffline { self.database().update_asset(&mut updated_asset)?; } } - - match validation_status.validity() { - Validity::Valid => {} - Validity::Warnings => { - if let Warning::UnsafeHistory(ref unsafe_history) = - validation_status.warnings[0] - { - warn!( - self.logger(), - "Cannot accept transfer because of unsafe history: {unsafe_history:?}" - ); - return Ok(None); - } - } - } } let mut updated_batch_transfer: DbBatchTransferActMod = batch_transfer.clone().into(); @@ -1475,12 +1635,11 @@ pub trait WalletOnline: WalletOffline { transfer: &DbBatchTransfer, db_data: &mut DbData, incoming: bool, - skip_sync: bool, ) -> Result, Error> { if incoming { self.wait_consignment(transfer, db_data) } else { - self.wait_ack(transfer, db_data, skip_sync) + self.wait_ack(transfer, db_data) } } @@ -1507,8 +1666,9 @@ pub trait WalletOnline: WalletOffline { if self.get_hub_fail_status(transfer.idx)? { return Ok(Some(self.fail_batch_transfer(transfer)?)); } - self.wait_counterparty(transfer, db_data, incoming, skip_sync) + self.wait_counterparty(transfer, db_data, incoming) } + TransferStatus::WaitingSafeHeight => self.wait_safe_height(transfer, db_data), TransferStatus::WaitingConfirmations => { self.wait_confirmations(transfer, db_data, incoming, skip_sync) } @@ -1772,13 +1932,30 @@ pub trait WalletOnline: WalletOffline { all_inputs.insert(a.utxo.into()); continue; } - return Err(self.detect_btc_unspendable_err()?); + return Err(Error::InsufficientAllocationSlots); } Err(e) => return Err(e), }; }) } + fn get_beneficiary_seal( + &self, + local_recipient_data: &LocalRecipientData, + ) -> BuilderSeal { + match local_recipient_data { + LocalRecipientData::Blind(secret_seal) => BuilderSeal::Concealed(*secret_seal), + LocalRecipientData::Witness(witness_data) => { + let graph_seal = if let Some(blinding) = witness_data.blinding { + GraphSeal::with_blinded_vout(witness_data.vout, blinding) + } else { + GraphSeal::new_random_vout(witness_data.vout) + }; + BuilderSeal::Revealed(graph_seal) + } + } + } + fn get_change_seal( &self, btc_change: &Option, @@ -1935,22 +2112,13 @@ pub trait WalletOnline: WalletOffline { let mut beneficiaries = vec![]; for recipient in &transfer_info.recipients { - let seal: BuilderSeal = match &recipient.local_recipient_data { - LocalRecipientData::Blind(secret_seal) => BuilderSeal::Concealed(*secret_seal), - LocalRecipientData::Witness(witness_data) => { - let graph_seal = if let Some(blinding) = witness_data.blinding { - GraphSeal::with_blinded_vout(witness_data.vout, blinding) - } else { - GraphSeal::new_random_vout(witness_data.vout) - }; - BuilderSeal::Revealed(graph_seal) - } - }; - - beneficiaries.push((seal, recipient.recipient_id.clone())); - + let seal; match &recipient.assignment { Assignment::Fungible(amt) => { + if *amt == 0 { + continue; + } + seal = self.get_beneficiary_seal(&recipient.local_recipient_data); asset_transition_builder = asset_transition_builder.add_fungible_state( RGB_STATE_ASSET_OWNER, seal, @@ -1959,12 +2127,19 @@ pub trait WalletOnline: WalletOffline { } Assignment::NonFungible => { if let AllocatedState::Data(state) = uda_state.clone().unwrap() { + seal = self.get_beneficiary_seal(&recipient.local_recipient_data); asset_transition_builder = asset_transition_builder .add_data(RGB_STATE_ASSET_OWNER, seal, Allocation::from(state)) .map_err(Error::from)?; + } else { + continue; } } Assignment::InflationRight(amt) => { + if *amt == 0 { + continue; + } + seal = self.get_beneficiary_seal(&recipient.local_recipient_data); asset_transition_builder = asset_transition_builder.add_fungible_state( RGB_STATE_INFLATION_ALLOWANCE, seal, @@ -1972,7 +2147,9 @@ pub trait WalletOnline: WalletOffline { )?; } _ => unreachable!(), - } + }; + + beneficiaries.push((seal, recipient.recipient_id.clone())); } let change = inputs_added.change(&transfer_info.original_assignments_needed); @@ -2001,16 +2178,28 @@ pub trait WalletOnline: WalletOffline { } }; - if transfer_info.main_transition == TypeOfTransition::Inflate { - let inflation = transfer_info.original_assignments_needed.inflation; - asset_transition_builder = asset_transition_builder - .add_global_state(RGB_GLOBAL_ISSUED_SUPPLY, Amount::from(inflation)) - .unwrap() - .add_metadata( - RGB_METADATA_ALLOWED_INFLATION, - Amount::from(change.inflation), - ) - .unwrap(); + // add necessary globals/metadata to transition + match transfer_info.main_transition { + TypeOfTransition::Inflate => { + let inflation = transfer_info.original_assignments_needed.inflation; + asset_transition_builder = asset_transition_builder + .add_global_state(RGB_GLOBAL_ISSUED_SUPPLY, Amount::from(inflation)) + .unwrap() + .add_metadata( + RGB_METADATA_ALLOWED_INFLATION, + Amount::from(change.inflation), + ) + .unwrap(); + } + TypeOfTransition::Burn => { + let burn = transfer_info.original_assignments_needed.fungible; + asset_transition_builder = asset_transition_builder + .add_metadata(RGB_METADATA_BURNED_ASSET, Amount::from(burn)) + .unwrap() + .add_metadata(RGB_METADATA_BURNED_INFLATION, Amount::from(0u64)) + .unwrap(); + } + _ => {} } let transition = asset_transition_builder.complete_transition()?; @@ -2363,7 +2552,13 @@ pub trait WalletOnline: WalletOffline { let txo_idx = match self.database().get_txo(&outpoint)? { Some(txo) => txo.idx, None => { - self.sync_db_txos(false, true)?; + self.sync_wallet( + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + true, + )?; let bdk_utxo = self.database().get_txo(&outpoint)?.expect("should exist"); let new_db_utxo: DbTxoActMod = bdk_utxo.clone().into(); self.database().set_txo(new_db_utxo)? @@ -2407,53 +2602,68 @@ pub trait WalletOnline: WalletOffline { } for recipient in transfer_info.recipients.clone() { - let recipient_type = if transfer_info.main_transition == TypeOfTransition::Inflate { - let local_witness_data = - if let LocalRecipientData::Witness(lwd) = recipient.local_recipient_data { + let (rcpt_id, rcpt_type, req_ass) = match transfer_info.main_transition { + TypeOfTransition::Inflate => { + let local_witness_data = if let LocalRecipientData::Witness(lwd) = + recipient.local_recipient_data + { lwd } else { unreachable!("inflation uses witness recipients") }; - let vout = local_witness_data.vout; - let txo_idx = match self.database().get_txo(&Outpoint { - txid: txid.clone(), - vout, - })? { - Some(txo) => txo.idx, - None => { - let db_utxo = DbTxoActMod { - txid: ActiveValue::Set(txid.clone()), - vout: ActiveValue::Set(vout), - btc_amount: ActiveValue::Set( - local_witness_data.amount_sat.to_string(), - ), - spent: ActiveValue::Set(false), - exists: ActiveValue::Set(false), - pending_witness: ActiveValue::Set(false), - ..Default::default() - }; - self.database().set_txo(db_utxo)? - } - }; - let db_coloring = DbColoringActMod { - txo_idx: ActiveValue::Set(txo_idx), - asset_transfer_idx: ActiveValue::Set(asset_transfer_idx), - r#type: ActiveValue::Set(ColoringType::Issue), - assignment: ActiveValue::Set(recipient.assignment.clone()), - ..Default::default() - }; - self.database().set_coloring(db_coloring)?; - Some(RecipientTypeFull::Witness { vout: Some(vout) }) - } else { - None + let vout = local_witness_data.vout; + let txo_idx = match self.database().get_txo(&Outpoint { + txid: txid.clone(), + vout, + })? { + Some(txo) => txo.idx, + None => { + let db_utxo = DbTxoActMod { + txid: ActiveValue::Set(txid.clone()), + vout: ActiveValue::Set(vout), + btc_amount: ActiveValue::Set( + local_witness_data.amount_sat.to_string(), + ), + spent: ActiveValue::Set(false), + exists: ActiveValue::Set(false), + pending_witness: ActiveValue::Set(false), + ..Default::default() + }; + self.database().set_txo(db_utxo)? + } + }; + let db_coloring = DbColoringActMod { + txo_idx: ActiveValue::Set(txo_idx), + asset_transfer_idx: ActiveValue::Set(asset_transfer_idx), + r#type: ActiveValue::Set(ColoringType::Issue), + assignment: ActiveValue::Set(recipient.assignment.clone()), + ..Default::default() + }; + self.database().set_coloring(db_coloring)?; + ( + Some(recipient.recipient_id.clone()), + Some(RecipientTypeFull::Witness { vout: Some(vout) }), + recipient.assignment, + ) + } + TypeOfTransition::Burn => ( + None, + None, + Assignment::Fungible(transfer_info.original_assignments_needed.fungible), + ), + TypeOfTransition::Transfer => ( + Some(recipient.recipient_id.clone()), + None, + recipient.assignment, + ), }; let transfer = DbTransferActMod { asset_transfer_idx: ActiveValue::Set(asset_transfer_idx), - requested_assignment: ActiveValue::Set(Some(recipient.assignment)), + requested_assignment: ActiveValue::Set(Some(req_ass)), incoming: ActiveValue::Set(false), - recipient_id: ActiveValue::Set(Some(recipient.recipient_id.clone())), - recipient_type: ActiveValue::Set(recipient_type), + recipient_id: ActiveValue::Set(rcpt_id), + recipient_type: ActiveValue::Set(rcpt_type), ..Default::default() }; let transfer_idx = self.database().set_transfer(transfer)?; @@ -2476,7 +2686,13 @@ pub trait WalletOnline: WalletOffline { let input_idx = match self.database().get_txo(&outpoint)? { Some(txo) => txo.idx, None => { - self.sync_db_txos(false, true)?; + self.sync_wallet( + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + true, + )?; let bdk_utxo = self.database().get_txo(&outpoint)?.expect("should exist"); let new_db_utxo: DbTxoActMod = bdk_utxo.clone().into(); self.database().set_txo(new_db_utxo)? @@ -2715,10 +2931,9 @@ pub trait WalletOnline: WalletOffline { status: TransferStatus, fascia: Fascia, sync_tte_used: bool, - skip_sync: bool, ) -> Result { let mut runtime = self.rgb_runtime()?; - self.broadcast_and_update_rgb(&mut runtime, psbt, fascia, skip_sync)?; + self.broadcast_and_update_rgb(&mut runtime, psbt, fascia)?; self.update_or_save_transfers(txid, info_contents, status, sync_tte_used) } @@ -2922,11 +3137,7 @@ pub trait WalletOnline: WalletOffline { }) } - fn send_end_impl( - &mut self, - signed_psbt: &Psbt, - skip_sync: bool, - ) -> Result { + fn send_end_impl(&mut self, signed_psbt: &Psbt) -> Result { let (txid, transfer_dir, mut info_contents, fascia) = self.get_transfer_end_data(signed_psbt)?; @@ -2976,7 +3187,6 @@ pub trait WalletOnline: WalletOffline { TransferStatus::WaitingConfirmations, fascia, sync_tte_used, - skip_sync, )? } else { self.update_or_save_transfers( @@ -3005,7 +3215,15 @@ pub trait WalletOnline: WalletOffline { let fee_rate_checked = self.check_fee_rate(fee_rate)?; if !skip_sync { - self.sync_db_txos(false, false)?; + self.sync_wallet( + SyncOptions { + keychain: SyncKeychain::Vanilla { + lookback: self.vanilla_sync_lookback(), + }, + strategy: SyncStrategy::FastSync, + }, + false, + )?; } let script_pubkey = self.get_script_pubkey(&address)?; @@ -3040,8 +3258,8 @@ pub trait WalletOnline: WalletOffline { Ok(psbt) } - fn send_btc_end_impl(&mut self, signed_psbt: &Psbt, skip_sync: bool) -> Result { - let tx = self.broadcast_psbt(signed_psbt, skip_sync)?; + fn send_btc_end_impl(&mut self, signed_psbt: &Psbt) -> Result { + let tx = self.broadcast_psbt(signed_psbt)?; self.finalize_vanilla_wallet_transaction(signed_psbt, WalletTransactionType::SendBtc)?; Ok(tx.compute_txid().to_string()) } @@ -3087,7 +3305,7 @@ pub trait WalletOnline: WalletOffline { input_unspents.clone(), )?; - let network: ChainNet = self.bitcoin_network().into(); + let chainnet: ChainNet = self.bitcoin_network().into(); let amount_sat = asset_spend.input_btc_amt / inflation_amounts.len() as u64; let dust = self .bdk_wallet() @@ -3102,7 +3320,7 @@ pub trait WalletOnline: WalletOffline { .get_new_addresses(KeychainKind::External, 1)? .script_pubkey(); let beneficiary = beneficiary_from_script_buf(script_pubkey.clone()); - let beneficiary = XChainNet::with(network, beneficiary); + let beneficiary = XChainNet::with(chainnet, beneficiary); let recipient_id = beneficiary.to_string(); witness_recipients.push((script_pubkey, amount_sat)); let vout = idx as u32 + 1; // start from 1 because of OP_RETURN @@ -3161,7 +3379,7 @@ pub trait WalletOnline: WalletOffline { dry_run, )? { PrepareTransferPsbtResult::Retry => { - unreachable!("unimplemented retry logic for inflate transition") + unreachable!("inflate transition has no retry logic") } PrepareTransferPsbtResult::Success(begin_operation_data) => *begin_operation_data, }, @@ -3179,7 +3397,6 @@ pub trait WalletOnline: WalletOffline { TransferStatus::WaitingConfirmations, fascia, false, - false, )?; let (asset_id, transfer_info) = info_contents.transfers.into_iter().next().unwrap(); @@ -3203,6 +3420,134 @@ pub trait WalletOnline: WalletOffline { entropy: info_contents.entropy, }) } + + fn burn_begin_impl( + &mut self, + asset_id: String, + amount: u64, + fee_rate: u64, + min_confirmations: u8, + dry_run: bool, + ) -> Result { + let asset = self.database().check_asset_exists(asset_id.clone())?; + let schema = asset.schema; + self.check_schema_support(&schema)?; + if !SCHEMAS_SUPPORTING_BURN.contains(&schema) { + return Err(Error::UnsupportedBurn { + asset_schema: schema, + }); + } + + if amount == 0 { + return Err(Error::NoBurnAmount); + } + + let (fee_rate_checked, unspents, input_unspents, mut runtime) = + self.get_transfer_begin_data(fee_rate)?; + + let assignments_needed = AssignmentsCollection { + fungible: amount, + ..Default::default() + }; + let asset_spend = self.select_rgb_inputs( + asset_id.clone(), + &assignments_needed, + input_unspents.clone(), + )?; + + let chainnet: ChainNet = self.bitcoin_network().into(); + let script_pubkey = self + .get_new_addresses(KeychainKind::External, 1)? + .script_pubkey(); + let dust = self + .bdk_wallet() + .public_descriptor(KeychainKind::External) + .dust_value() + .to_sat(); + let witness_recipients: Vec<(ScriptBuf, u64)> = vec![(script_pubkey.clone(), dust)]; + let beneficiary = beneficiary_from_script_buf(script_pubkey.clone()); + let beneficiary = XChainNet::with(chainnet, beneficiary); + let recipient_id = beneficiary.to_string(); + let local_recipients = vec![LocalRecipient { + recipient_id, + local_recipient_data: LocalRecipientData::Witness(LocalWitnessData { + amount_sat: dust, + blinding: None, + vout: 1, + }), + assignment: Assignment::Fungible(0), + transport_endpoints: vec![], + }]; + + let contract_id = ContractId::from_str(&asset_id).expect("invalid contract ID"); + let asset_info = AssetInfo { + contract_id, + reject_list_url: asset.reject_list_url, + }; + let transfer_info = InfoAssetTransfer { + asset_info, + recipients: local_recipients.clone(), + asset_spend: asset_spend.clone(), + change: AssignmentsCollection::default(), + original_assignments_needed: assignments_needed.clone(), + assignments_needed, + assignments_spent: HashMap::new(), + main_transition: TypeOfTransition::Burn, + beneficiaries_blinded: vec![], + beneficiaries_witness: vec![], + }; + let mut transfer_info_map: BTreeMap = + BTreeMap::from([(asset_id.clone(), transfer_info)]); + + let receive_ids: Vec = local_recipients + .iter() + .map(|lr| lr.recipient_id.clone()) + .collect(); + let transfer_dir = self.setup_transfer_directory(receive_ids)?; + + let mut rejected = HashSet::new(); + Ok( + match self.prepare_transfer_psbt( + &mut transfer_info_map, + transfer_dir.clone(), + false, + unspents, + &input_unspents, + &witness_recipients, + fee_rate_checked, + min_confirmations, + None, + &mut runtime, + &mut rejected, + dry_run, + )? { + PrepareTransferPsbtResult::Retry => { + unreachable!("burn transition has no retry logic") + } + PrepareTransferPsbtResult::Success(begin_operation_data) => *begin_operation_data, + }, + ) + } + + fn burn_end_impl(&mut self, signed_psbt: &Psbt) -> Result { + let (txid, _transfer_dir, info_contents, fascia) = + self.get_transfer_end_data(signed_psbt)?; + + let batch_transfer_idx = self.finalize_transfer_end( + txid.clone(), + signed_psbt, + &info_contents, + TransferStatus::WaitingConfirmations, + fascia, + false, + )?; + + Ok(OperationResult { + txid, + batch_transfer_idx, + entropy: info_contents.entropy, + }) + } } /// Online operations for a wallet. @@ -3238,10 +3583,14 @@ pub trait RgbWalletOpsOnline: RgbWalletOpsOffline + WalletOnline { Ok(changed) } - /// Sync the wallet and save new colored UTXOs to the DB - fn sync(&mut self, online: Online) -> Result<(), Error> { + /// Sync the wallet and save new colored UTXOs to the DB. + /// + /// Gets [`SyncOptions`] to configure the sync strategy and keychain. + /// + /// Callers that want both keychains synced must invoke this method once per keychain. + fn sync(&mut self, online: Online, options: SyncOptions) -> Result<(), Error> { info!(self.logger(), "Syncing..."); - self.sync_impl(online)?; + self.sync_impl(online, options)?; info!(self.logger(), "Sync completed"); Ok(()) } diff --git a/src/wallet/rust_only.rs b/src/wallet/rust_only.rs index 9a74b671..f18d78bc 100644 --- a/src/wallet/rust_only.rs +++ b/src/wallet/rust_only.rs @@ -374,7 +374,7 @@ impl Wallet { let received_rgb_assignments = self.extract_received_assignments(&consignment, witness_id, Some(vout), None); - let _status = runtime.accept_transfer(valid_consignment, &resolver)?; + runtime.accept_transfer(valid_consignment, &resolver)?; info!(self.logger(), "Accept transfer completed"); Ok(( @@ -527,7 +527,7 @@ impl Wallet { skip_sync: bool, ) -> Result, Error> { info!(self.logger(), "Listing unspents vanilla..."); - self.sync_if_requested(Some(online), skip_sync)?; + self.sync_if_requested(Some(online), skip_sync, KeychainKind::Internal)?; let unspents = self.internal_unspents(); diff --git a/src/wallet/singlesig.rs b/src/wallet/singlesig.rs index cd1ac1f3..df6978ac 100644 --- a/src/wallet/singlesig.rs +++ b/src/wallet/singlesig.rs @@ -28,10 +28,10 @@ impl SinglesigKeys { pub(crate) fn build_descriptors( &self, bitcoin_network: &BitcoinNetwork, - bdk_network: &BdkNetwork, ) -> Result<(WalletDescriptors, bool), Error> { - let xpub_rgb = str_to_xpub(&self.account_xpub_colored, bdk_network)?; - let xpub_btc = str_to_xpub(&self.account_xpub_vanilla, bdk_network)?; + let network_kind = bitcoin_network.network_kind(); + let xpub_rgb = str_to_xpub(&self.account_xpub_colored, &network_kind)?; + let xpub_btc = str_to_xpub(&self.account_xpub_vanilla, &network_kind)?; Ok(if let Some(mnemonic) = &self.mnemonic { let descs = get_descriptors( bitcoin_network, @@ -116,7 +116,22 @@ impl WalletOffline for Wallet {} #[cfg(any(feature = "electrum", feature = "esplora"))] impl WalletOnline for Wallet { fn wallet_specific_consistency_checks(&mut self) -> Result<(), Error> { - self.sync_db_txos(true, false)?; + self.sync_wallet( + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FullScan, + }, + false, + )?; + self.sync_wallet( + SyncOptions { + keychain: SyncKeychain::Vanilla { + lookback: self.vanilla_sync_lookback(), + }, + strategy: SyncStrategy::FullScan, + }, + false, + )?; let bdk_utxos: Vec = self .bdk_wallet() .list_unspent() @@ -154,10 +169,9 @@ impl Wallet { /// [`SinglesigKeys`]. pub fn new(wallet_data: WalletData, keys: SinglesigKeys) -> Result { let wdata = wallet_data.clone(); - let bdk_network = BdkNetwork::from(wdata.bitcoin_network); // wallet keys - let (descs, watch_only) = keys.build_descriptors(&wdata.bitcoin_network, &bdk_network)?; + let (descs, watch_only) = keys.build_descriptors(&wdata.bitcoin_network)?; // wallet directory and file logging setup let (wallet_dir, logger, _logger_guard) = @@ -170,7 +184,7 @@ impl Wallet { descs.colored, descs.vanilla, watch_only, - bdk_network, + BdkNetwork::from(wdata.bitcoin_network), )?; // setup RGB @@ -204,10 +218,7 @@ impl Wallet { /// Return the descriptors of the wallet. pub fn get_descriptors(&self) -> WalletDescriptors { self.keys - .build_descriptors( - &self.internals.wallet_data.bitcoin_network, - &BdkNetwork::from(self.internals.wallet_data.bitcoin_network), - ) + .build_descriptors(&self.internals.wallet_data.bitcoin_network) .expect("already succeeded at wallet creation") .0 } @@ -584,7 +595,7 @@ impl Wallet { self.check_online(online)?; let mut psbt = self.create_utxos_begin_impl(up_to, num, size, fee_rate, skip_sync, true)?; self.sign_psbt_impl(&mut psbt, None)?; - let res = self.create_utxos_end_impl(&psbt, skip_sync)?; + let res = self.create_utxos_end_impl(&psbt)?; self.update_backup_info(false)?; info!(self.logger(), "Create UTXOs completed"); Ok(res) @@ -641,38 +652,22 @@ impl Wallet { /// /// This doesn't require the wallet to have private keys. /// - /// Returns the number of created UTXOs, if `skip_sync` is set to true this will be 0. - pub fn create_utxos_end( - &mut self, - online: Online, - signed_psbt: String, - skip_sync: bool, - ) -> Result { + /// Returns the number of created UTXOs. + pub fn create_utxos_end(&mut self, online: Online, signed_psbt: String) -> Result { info!(self.logger(), "Creating UTXOs (end)..."); self.check_online(online)?; let psbt = Psbt::from_str(&signed_psbt)?; - let res = self.create_utxos_end_impl(&psbt, skip_sync)?; + let res = self.create_utxos_end_impl(&psbt)?; info!(self.logger(), "Create UTXOs (end) completed"); Ok(res) } /// Return the existing or freshly generated wallet [`Online`] data. /// - /// Setting `skip_consistency_check` to false runs a check on UTXOs (BDK vs rgb-lib DB), assets - /// (RGB vs rgb-lib DB) and medias (DB vs actual files) to try and detect possible - /// inconsistencies in the wallet. - /// Setting `skip_consistency_check` to true bypasses the check and allows operating an - /// inconsistent wallet. - /// - ///
Warning: setting skip_consistency_check to true is dangerous, - /// only do this if you know what you're doing!
- pub fn go_online( - &mut self, - skip_consistency_check: bool, - indexer_url: String, - ) -> Result { + /// See [`OnlineOptions`] for details on the available options. + pub fn go_online(&mut self, online_options: OnlineOptions) -> Result { info!(self.logger(), "Going online..."); - let online = self.go_online_impl(skip_consistency_check, &indexer_url)?; + let online = self.go_online_impl(&online_options)?; info!(self.logger(), "Go online completed"); Ok(online) } @@ -763,7 +758,6 @@ impl Wallet { fee_rate: u64, min_confirmations: u8, expiration_timestamp: Option, - skip_sync: bool, ) -> Result { info!(self.logger(), "Sending to: {:?}...", recipient_map); self.check_xprv()?; @@ -777,7 +771,7 @@ impl Wallet { true, )?; self.sign_psbt_impl(&mut begin_op_data.psbt, None)?; - let res = self.send_end_impl(&begin_op_data.psbt, skip_sync)?; + let res = self.send_end_impl(&begin_op_data.psbt)?; self.update_backup_info(false)?; info!(self.logger(), "Send completed"); Ok(res) @@ -811,6 +805,9 @@ impl Wallet { /// produced. [`send_end`](Wallet::send_end) can still complete the operation and will persist /// the transfer. /// + /// This API requires to be online since it checks the validity and reachability of the + /// transport endpoints. + /// /// Signing of the returned PSBT needs to be carried out separately. The signed PSBT then needs /// to be fed to the [`send_end`](Wallet::send_end) function to complete the send operation. /// @@ -868,12 +865,11 @@ impl Wallet { &mut self, online: Online, signed_psbt: String, - skip_sync: bool, ) -> Result { info!(self.logger(), "Sending (end)..."); self.check_online(online)?; let psbt = Psbt::from_str(&signed_psbt)?; - let res = self.send_end_impl(&psbt, skip_sync)?; + let res = self.send_end_impl(&psbt)?; self.update_backup_info(false)?; info!(self.logger(), "Send (end) completed"); Ok(res) @@ -898,7 +894,7 @@ impl Wallet { self.check_online(online)?; let mut psbt = self.send_btc_begin_impl(address, amount, fee_rate, skip_sync, true)?; self.sign_psbt_impl(&mut psbt, None)?; - let res = self.send_btc_end_impl(&psbt, skip_sync)?; + let res = self.send_btc_end_impl(&psbt)?; info!(self.logger(), "Send BTC completed"); Ok(res) } @@ -940,16 +936,11 @@ impl Wallet { /// This doesn't require the wallet to have private keys. /// /// Returns the TXID of the broadcasted transaction. - pub fn send_btc_end( - &mut self, - online: Online, - signed_psbt: String, - skip_sync: bool, - ) -> Result { + pub fn send_btc_end(&mut self, online: Online, signed_psbt: String) -> Result { info!(self.logger(), "Sending BTC (end)..."); self.check_online(online)?; let psbt = Psbt::from_str(&signed_psbt)?; - let res = self.send_btc_end_impl(&psbt, skip_sync)?; + let res = self.send_btc_end_impl(&psbt)?; info!(self.logger(), "Send BTC (end) completed"); Ok(res) } @@ -1057,8 +1048,6 @@ impl Wallet { /// /// This doesn't require the wallet to have private keys. /// - /// The API syncs and doesn't provide a way to skip that. - /// /// Returns a [`OperationResult`]. pub fn inflate_end( &mut self, @@ -1073,4 +1062,99 @@ impl Wallet { info!(self.logger(), "Inflate (end) completed"); Ok(res) } + + /// Burn RGB assets. + /// + /// This calls [`burn_begin`](Wallet::burn_begin), signs the resulting PSBT and finally + /// calls [`burn_end`](Wallet::burn_end). + /// + /// A wallet with private keys is required. + pub fn burn( + &mut self, + online: Online, + asset_id: String, + amount: u64, + fee_rate: u64, + min_confirmations: u8, + ) -> Result { + info!(self.logger(), "Burning amount: {}...", amount); + self.check_xprv()?; + self.check_online(online)?; + let mut begin_op_data = + self.burn_begin_impl(asset_id, amount, fee_rate, min_confirmations, true)?; + self.sign_psbt_impl(&mut begin_op_data.psbt, None)?; + let res = self.burn_end_impl(&begin_op_data.psbt)?; + self.update_backup_info(false)?; + info!(self.logger(), "Burn completed"); + Ok(res) + } + + /// Prepare the PSBT to burn RGB assets according to the given amount, with the provided + /// `fee_rate` (in sat/vB). + /// + /// The amount of assets to burn is specified by the `amount` parameter and cannot be zero. + /// + /// If `dry_run` is true, the wallet does not persist the transfer in + /// [`TransferStatus::Initiated`]. The returned [`BurnBeginResult::batch_transfer_idx`] is None + /// in that case. The PSBT and on-disk transfer data under the wallet directory are still + /// produced. [`burn_end`](Wallet::burn_end) can still complete the operation and will persist + /// the transfer. + /// + /// Signing of the returned PSBT needs to be carried out separately. The signed PSBT then needs + /// to be fed to the [`burn_end`](Wallet::burn_end) function for broadcasting. + /// + /// This doesn't require the wallet to have private keys. + /// + /// Returns a PSBT ready to be signed and operation details. + pub fn burn_begin( + &mut self, + online: Online, + asset_id: String, + amount: u64, + fee_rate: u64, + min_confirmations: u8, + dry_run: bool, + ) -> Result { + info!(self.logger(), "Burning (begin) amount: {}...", amount); + self.check_online(online)?; + let begin_operation_data = + self.burn_begin_impl(asset_id, amount, fee_rate, min_confirmations, dry_run)?; + self.update_backup_info(false)?; + info!(self.logger(), "Burn (begin) completed"); + Ok(BurnBeginResult { + psbt: begin_operation_data.psbt.to_string(), + batch_transfer_idx: begin_operation_data.batch_transfer_idx, + details: BurnDetails { + fascia_path: begin_operation_data + .transfer_dir + .join(FASCIA_FILE) + .to_string_lossy() + .to_string(), + min_confirmations, + entropy: begin_operation_data.info_batch_transfer.entropy, + }, + }) + } + + /// Complete the burn operation by broadcasting the provided PSBT and saving the transfer to DB. + /// + /// The provided PSBT, prepared with the [`burn_begin`](Wallet::burn_begin) function, needs to + /// have already been signed. + /// + /// This doesn't require the wallet to have private keys. + /// + /// Returns a [`OperationResult`]. + pub fn burn_end( + &mut self, + online: Online, + signed_psbt: String, + ) -> Result { + info!(self.logger(), "Burning (end)..."); + self.check_online(online)?; + let psbt = Psbt::from_str(&signed_psbt)?; + let res = self.burn_end_impl(&psbt)?; + self.update_backup_info(false)?; + info!(self.logger(), "Burn (end) completed"); + Ok(res) + } } diff --git a/src/wallet/test/backup.rs b/src/wallet/test/backup.rs index 53b69fbc..6ee4ea86 100644 --- a/src/wallet/test/backup.rs +++ b/src/wallet/test/backup.rs @@ -37,7 +37,7 @@ fn success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, Some(&asset.asset_id), None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -92,7 +92,7 @@ fn success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, Some(&asset.asset_id), None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); check_test_wallet_data(&mut wallet, &asset, None, 2, amount * 2); @@ -238,7 +238,7 @@ fn double_restore() { wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet_1, online_1, Some(&asset_1.asset_id), None); wait_for_refresh(&mut wallet_2, online_2, Some(&asset_2.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, Some(&asset_1.asset_id), None); wait_for_refresh(&mut wallet_1, online_1, Some(&asset_1.asset_id), None); wait_for_refresh(&mut wallet_2, online_2, Some(&asset_2.asset_id), None); diff --git a/src/wallet/test/blind_receive.rs b/src/wallet/test/blind_receive.rs index d1e1812c..8e3b813d 100644 --- a/src/wallet/test/blind_receive.rs +++ b/src/wallet/test/blind_receive.rs @@ -422,20 +422,14 @@ fn fail() { // insufficient funds let result = test_blind_receive_result(&mut wallet); - assert!(matches!( - result, - Err(Error::InsufficientBitcoins { - needed: _, - available: _ - }) - )); + assert!(matches!(result, Err(Error::InsufficientAllocationSlots))); // invalid recipient ID let result = RecipientInfo::new(s!("invalid")); assert!(matches!(result, Err(Error::InvalidRecipientID))); fund_wallet(test_get_address(&mut wallet)); - mine(false, false); + mine(false); test_create_utxos(&mut wallet, online, true, Some(1), None, FEE_RATE, None); // expiration in the past diff --git a/src/wallet/test/burn.rs b/src/wallet/test/burn.rs new file mode 100644 index 00000000..71c73b45 --- /dev/null +++ b/src/wallet/test/burn.rs @@ -0,0 +1,604 @@ +use super::*; + +#[cfg(feature = "electrum")] +fn assert_burn_unspents( + wallet: &mut Wallet, + asset_id: &str, + expected_change: Option<(&Outpoint, u64)>, +) { + let unspents = test_list_unspents(wallet, None, false); + + // the burnt allocation (Fungible(0)) must not surface anywhere in list_unspents + let zero_count = unspents + .iter() + .flat_map(|u| u.rgb_allocations.iter()) + .filter(|a| { + a.asset_id.as_deref() == Some(asset_id) + && matches!(a.assignment, Assignment::Fungible(0)) + }) + .count(); + assert_eq!(zero_count, 0); + + // when there's change, the change_utxo must hold exactly the change allocation (no Fungible(0)) + if let Some((outpoint, amount)) = expected_change { + let change_unspent = unspents + .iter() + .find(|u| &u.utxo.outpoint == outpoint) + .expect("change_utxo missing from list_unspents"); + let asset_assignments: Vec<&Assignment> = change_unspent + .rgb_allocations + .iter() + .filter(|a| a.asset_id.as_deref() == Some(asset_id)) + .map(|a| &a.assignment) + .collect(); + assert_eq!(asset_assignments, vec![&Assignment::Fungible(amount)]); + } +} + +#[cfg(feature = "electrum")] +#[test] +#[parallel] +fn success() { + initialize(); + + // wallets + let (mut wallet, online) = get_funded_wallet!(); + let (mut rcv_wallet, rcv_online) = get_funded_wallet!(); + + // issue + let issue_amounts = [AMOUNT, AMOUNT]; + let asset = test_issue_asset_ifa(&mut wallet, online, Some(&issue_amounts), None, None); + show_unspent_colorings(&mut wallet, "after issue"); + let initial_supply = issue_amounts.iter().sum::(); + assert_eq!(asset.initial_supply, initial_supply); + assert_eq!(asset.known_circulating_supply, initial_supply); + let transfers = test_list_transfers(&wallet, Some(&asset.asset_id)); + assert_eq!(transfers.len(), 1); + assert_eq!(transfers.first().unwrap().kind, TransferKind::Issuance); + let unspents: Vec = test_list_unspents(&mut wallet, None, false) + .into_iter() + .filter(|u| u.utxo.colorable) + .collect(); + assert_eq!(unspents.len(), 5); + + // burn + test_create_utxos_default(&mut wallet, online); + let burn_amount = 199; + let bak_info_before = wallet.database().get_backup_info().unwrap().unwrap(); + let res = test_burn(&mut wallet, online, &asset.asset_id, burn_amount); + let bak_info_after = wallet.database().get_backup_info().unwrap().unwrap(); + assert!(bak_info_after.last_operation_timestamp > bak_info_before.last_operation_timestamp); + show_unspent_colorings(&mut wallet, "after burn"); + + // check updated balance + let balance = test_get_asset_balance(&wallet, &asset.asset_id); + let burn_change = AMOUNT - burn_amount; + let remaining_after_burn = initial_supply - burn_amount; + assert_eq!( + balance, + Balance { + settled: initial_supply, + future: remaining_after_burn, + spendable: AMOUNT, + } + ); + + // mine and refresh + mine(false); + assert!(test_refresh_asset(&mut wallet, online, &asset.asset_id)); + + // check updated balance + let balance = test_get_asset_balance(&wallet, &asset.asset_id); + assert_eq!( + balance, + Balance { + settled: remaining_after_burn, + future: remaining_after_burn, + spendable: remaining_after_burn, + } + ); + + // check transfer info + let transfers = test_list_transfers(&wallet, Some(&asset.asset_id)); + assert_eq!(transfers.len(), 2); + let transfer = transfers.get(1).unwrap(); + assert_eq!(transfer.batch_transfer_idx, 2); + assert_eq!(transfer.status, TransferStatus::Settled); + assert_eq!( + transfer.requested_assignment.as_ref().unwrap(), + &Assignment::Fungible(burn_amount) + ); + assert_eq!( + transfer.assignments, + vec![Assignment::Fungible(burn_change)] + ); + assert_eq!(transfer.kind, TransferKind::Burn); + assert_eq!(transfer.txid.as_ref().unwrap(), &res.txid); + assert!(transfer.recipient_id.is_none()); + assert!(transfer.receive_utxo.is_none()); + assert!(transfer.change_utxo.is_some()); + assert!(transfer.expiration_timestamp.is_none()); + assert!(transfer.transport_endpoints.is_empty()); + assert!(transfer.invoice_string.is_none()); + assert!(transfer.consignment_path.is_some()); + + assert_burn_unspents( + &mut wallet, + &asset.asset_id, + transfer.change_utxo.as_ref().map(|o| (o, burn_change)), + ); + + // inflate using all the default inflation rights, producing a new Fungible allocation + // smaller than AMOUNT + test_create_utxos_default(&mut wallet, online); + let inflated_amount = AMOUNT_INFLATION; + assert!(inflated_amount < AMOUNT); + test_inflate(&mut wallet, online, &asset.asset_id, &[inflated_amount]); + show_unspent_colorings(&mut wallet, "after inflate"); + + let amount_after_inflate = remaining_after_burn + inflated_amount; + let balance = test_get_asset_balance(&wallet, &asset.asset_id); + assert_eq!( + balance, + Balance { + settled: remaining_after_burn, + future: amount_after_inflate, + spendable: remaining_after_burn, + } + ); + + mine(false); + assert!(test_refresh_asset(&mut wallet, online, &asset.asset_id)); + show_unspent_colorings(&mut wallet, "after inflate mine + refresh"); + + let balance = test_get_asset_balance(&wallet, &asset.asset_id); + assert_eq!( + balance, + Balance { + settled: amount_after_inflate, + future: amount_after_inflate, + spendable: amount_after_inflate, + } + ); + + // partial burn requiring both the burn change and the inflated allocation + // pick an amount higher than each individually but lower than their sum + // input selection sorts by main amount ascending, so it should pick the inflated allocation + // first, then the burn change, leaving the untouched AMOUNT allocation as the only spendable + // one before the burn tx is mined + test_create_utxos_default(&mut wallet, online); + let burn_amount_2 = burn_change + inflated_amount - 100; + assert!(burn_amount_2 > burn_change); + assert!(burn_amount_2 > inflated_amount); + assert!(burn_amount_2 < burn_change + inflated_amount); + let res_burn_2 = test_burn(&mut wallet, online, &asset.asset_id, burn_amount_2); + show_unspent_colorings(&mut wallet, "after second burn"); + + let remaining_amount = amount_after_inflate - burn_amount_2; + let burn_change_2 = burn_change + inflated_amount - burn_amount_2; + let balance = test_get_asset_balance(&wallet, &asset.asset_id); + assert_eq!( + balance, + Balance { + settled: amount_after_inflate, + future: remaining_amount, + spendable: AMOUNT, + } + ); + + mine(false); + assert!(test_refresh_asset(&mut wallet, online, &asset.asset_id)); + show_unspent_colorings(&mut wallet, "after second burn mine + refresh"); + + let balance = test_get_asset_balance(&wallet, &asset.asset_id); + assert_eq!( + balance, + Balance { + settled: remaining_amount, + future: remaining_amount, + spendable: remaining_amount, + } + ); + + // check second burn transfer info + let transfers = test_list_transfers(&wallet, Some(&asset.asset_id)); + assert_eq!(transfers.len(), 4); + let transfer = transfers.get(3).unwrap(); + assert_eq!(transfer.status, TransferStatus::Settled); + assert_eq!( + transfer.requested_assignment.as_ref().unwrap(), + &Assignment::Fungible(burn_amount_2) + ); + assert_eq!( + transfer.assignments, + vec![Assignment::Fungible(burn_change_2)] + ); + assert_eq!(transfer.kind, TransferKind::Burn); + assert_eq!(transfer.txid.as_ref().unwrap(), &res_burn_2.txid); + assert!(transfer.recipient_id.is_none()); + assert!(transfer.receive_utxo.is_none()); + assert!(transfer.change_utxo.is_some()); + + assert_burn_unspents( + &mut wallet, + &asset.asset_id, + transfer.change_utxo.as_ref().map(|o| (o, burn_change_2)), + ); + + // send all + let receive_data = test_blind_receive(&mut rcv_wallet); + let recipient_map = HashMap::from([( + asset.asset_id.clone(), + vec![Recipient { + assignment: Assignment::Fungible(remaining_amount), + recipient_id: receive_data.recipient_id.clone(), + witness_data: None, + transport_endpoints: TRANSPORT_ENDPOINTS.clone(), + }], + )]); + let txid = test_send(&mut wallet, online, &recipient_map); + assert!(!txid.is_empty()); + show_unspent_colorings(&mut wallet, "after send"); + let (transfer, _, _) = get_test_transfer_sender(&wallet, &txid); + let tte_data = wallet + .database() + .get_transfer_transport_endpoints_data(transfer.idx) + .unwrap(); + assert_eq!(tte_data.len(), 1); + let ce = tte_data.first().unwrap(); + assert_eq!(ce.1.endpoint, PROXY_URL); + assert!(ce.0.used); + + // check balance (no assets left) + let balance = test_get_asset_balance(&wallet, &asset.asset_id); + assert_eq!( + balance, + Balance { + settled: remaining_amount, + future: 0, + spendable: 0, + } + ); + + // transfers progress to status WaitingConfirmations after a refresh + wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); + let rcv_transfer = get_test_transfer_recipient(&rcv_wallet, &receive_data.recipient_id); + let (rcv_transfer_data, _rcv_asset_transfer) = + get_test_transfer_data(&rcv_wallet, &rcv_transfer); + wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); + let (transfer, _, _) = get_test_transfer_sender(&wallet, &txid); + let (transfer_data, _) = get_test_transfer_data(&wallet, &transfer); + assert_eq!( + rcv_transfer_data.status, + TransferStatus::WaitingConfirmations + ); + assert_eq!(transfer_data.status, TransferStatus::WaitingConfirmations); + + // asset has been received correctly + let rcv_assets = test_list_assets(&rcv_wallet, &[]); + let ifa_assets = rcv_assets.ifa.unwrap(); + assert_eq!(ifa_assets.len(), 1); + let rcv_asset = ifa_assets.last().unwrap(); + assert_eq!(rcv_asset.asset_id, asset.asset_id); + assert_eq!(rcv_asset.ticker, TICKER); + assert_eq!(rcv_asset.name, NAME); + assert_eq!(rcv_asset.precision, PRECISION); + assert_eq!( + rcv_asset.balance, + Balance { + settled: 0, + future: remaining_amount, + spendable: 0, + } + ); + assert_eq!(rcv_asset.initial_supply, initial_supply); + show_unspent_colorings(&mut wallet, "after send refresh 1"); + + // transfers progress to status Settled after tx mining + refresh + mine(false); + wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); + wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); + show_unspent_colorings(&mut wallet, "after send mine + refresh 2"); + + // check balance (no assets left) + let balance = test_get_asset_balance(&wallet, &asset.asset_id); + assert_eq!( + balance, + Balance { + settled: 0, + future: 0, + spendable: 0, + } + ); + + let rcv_transfer = get_test_transfer_recipient(&rcv_wallet, &receive_data.recipient_id); + let (rcv_transfer_data, _) = get_test_transfer_data(&rcv_wallet, &rcv_transfer); + let (transfer, _, _) = get_test_transfer_sender(&wallet, &txid); + let (transfer_data, _) = get_test_transfer_data(&wallet, &transfer); + assert_eq!(rcv_transfer_data.status, TransferStatus::Settled); + assert_eq!(transfer_data.status, TransferStatus::Settled); + assert_eq!(transfer_data.change_utxo, None); + + let asset_metadata = test_get_asset_metadata(&rcv_wallet, &asset.asset_id); + assert_eq!(asset_metadata.initial_supply, initial_supply); + + // check there's no change (sent all) + assert!(transfer_data.change_utxo.is_none()); + + // the receiving wallet now holds all remaining assets: burn part of them, then burn the rest + test_create_utxos_default(&mut rcv_wallet, rcv_online); + let rcv_burn_amount = 50; + let res_rcv_burn = test_burn( + &mut rcv_wallet, + rcv_online, + &asset.asset_id, + rcv_burn_amount, + ); + show_unspent_colorings(&mut rcv_wallet, "after rcv partial burn"); + + let rcv_remaining = remaining_amount - rcv_burn_amount; + let balance = test_get_asset_balance(&rcv_wallet, &asset.asset_id); + assert_eq!( + balance, + Balance { + settled: remaining_amount, + future: rcv_remaining, + spendable: 0, + } + ); + + mine(false); + assert!(test_refresh_asset( + &mut rcv_wallet, + rcv_online, + &asset.asset_id + )); + show_unspent_colorings(&mut rcv_wallet, "after rcv partial burn mine + refresh"); + + let balance = test_get_asset_balance(&rcv_wallet, &asset.asset_id); + assert_eq!( + balance, + Balance { + settled: rcv_remaining, + future: rcv_remaining, + spendable: rcv_remaining, + } + ); + + let rcv_transfers = test_list_transfers(&rcv_wallet, Some(&asset.asset_id)); + let rcv_burn_transfer = rcv_transfers.last().unwrap(); + assert_eq!(rcv_burn_transfer.status, TransferStatus::Settled); + assert_eq!(rcv_burn_transfer.kind, TransferKind::Burn); + assert_eq!( + rcv_burn_transfer.requested_assignment.as_ref().unwrap(), + &Assignment::Fungible(rcv_burn_amount) + ); + assert_eq!( + rcv_burn_transfer.assignments, + vec![Assignment::Fungible(rcv_remaining)] + ); + assert_eq!(rcv_burn_transfer.txid.as_ref().unwrap(), &res_rcv_burn.txid); + + assert_burn_unspents( + &mut rcv_wallet, + &asset.asset_id, + rcv_burn_transfer + .change_utxo + .as_ref() + .map(|o| (o, rcv_remaining)), + ); + + // burn everything from the receiving wallet + test_create_utxos_default(&mut rcv_wallet, rcv_online); + let res_rcv_burn_all = test_burn(&mut rcv_wallet, rcv_online, &asset.asset_id, rcv_remaining); + show_unspent_colorings(&mut rcv_wallet, "after rcv burn all"); + + let balance = test_get_asset_balance(&rcv_wallet, &asset.asset_id); + assert_eq!( + balance, + Balance { + settled: rcv_remaining, + future: 0, + spendable: 0, + } + ); + + mine(false); + assert!(test_refresh_asset( + &mut rcv_wallet, + rcv_online, + &asset.asset_id + )); + show_unspent_colorings(&mut rcv_wallet, "after rcv burn all mine + refresh"); + + let balance = test_get_asset_balance(&rcv_wallet, &asset.asset_id); + assert_eq!( + balance, + Balance { + settled: 0, + future: 0, + spendable: 0, + } + ); + + let rcv_transfers = test_list_transfers(&rcv_wallet, Some(&asset.asset_id)); + let rcv_burn_all_transfer = rcv_transfers.last().unwrap(); + assert_eq!(rcv_burn_all_transfer.status, TransferStatus::Settled); + assert_eq!(rcv_burn_all_transfer.kind, TransferKind::Burn); + assert_eq!( + rcv_burn_all_transfer.requested_assignment.as_ref().unwrap(), + &Assignment::Fungible(rcv_remaining) + ); + assert_eq!( + rcv_burn_all_transfer.txid.as_ref().unwrap(), + &res_rcv_burn_all.txid + ); + // nothing left to burn: no fungible change, no change_utxo + assert_eq!(rcv_burn_all_transfer.assignments, vec![]); + assert!(rcv_burn_all_transfer.change_utxo.is_none()); + assert_burn_unspents(&mut rcv_wallet, &asset.asset_id, None); +} + +#[cfg(feature = "electrum")] +#[test] +#[parallel] +fn fail() { + initialize(); + + let (mut wallet, online) = get_funded_wallet!(); + + let asset_ifa = test_issue_asset_ifa(&mut wallet, online, None, None, None); + + // don't check burn input params (checked in _begin/_end sections below) + + // burn errors + // - watch-only (_check_xprv) + let mut wallet_wo = get_test_wallet(false, None); + let online_wo = wallet_wo.go_online(test_go_online_options(None)).unwrap(); + let result = test_burn_result(&mut wallet_wo, online_wo, &asset_ifa.asset_id, 10); + assert_matches!(result, Err(Error::WatchOnly)); + + // - wrong online + let wrong_online = Online { id: 1 }; + + // burn_begin input params + // - check online is correct + let result = test_burn_begin_result(&mut wallet, wrong_online, &asset_ifa.asset_id, 10); + assert_matches!(result, Err(Error::CannotChangeOnline)); + // - invalid asset_id + let result = test_burn_begin_result(&mut wallet, online, "malformed", 10); + assert_matches!(result, Err(Error::AssetNotFound { asset_id: _ })); + // - check zero burn amount + let result = test_burn_begin_result(&mut wallet, online, &asset_ifa.asset_id, 0); + assert_matches!(result, Err(Error::NoBurnAmount)); + // - check fee_rate + // - low + let result = wallet.burn_begin( + online, + asset_ifa.asset_id.clone(), + 10, + 0, + MIN_CONFIRMATIONS, + false, + ); + assert_matches!(result, Err(Error::InvalidFeeRate { details: m }) if m == FEE_MSG_LOW); + // - overflow + let result = wallet.burn_begin( + online, + asset_ifa.asset_id.clone(), + 10, + u64::MAX, + MIN_CONFIRMATIONS, + false, + ); + assert_matches!(result, Err(Error::InvalidFeeRate { details: m }) if m == FEE_MSG_OVER); + + // burn_begin errors + // - inexistent asset + let result = test_burn_begin_result(&mut wallet, online, "rgb1nexistent", 10); + assert_matches!(result, Err(Error::AssetNotFound { asset_id: _ })); + // - schema not supported + create_test_data_dir(); + let bitcoin_network = BitcoinNetwork::Regtest; + let keys = generate_keys(bitcoin_network, WitnessVersion::Taproot); + let mut wallet_nia = Wallet::new( + WalletData { + data_dir: get_test_data_dir_string(), + bitcoin_network, + database_type: DatabaseType::Sqlite, + max_allocations_per_utxo: MAX_ALLOCATIONS_PER_UTXO, + supported_schemas: vec![AssetSchema::Nia, AssetSchema::Ifa], + }, + SinglesigKeys::from_keys(&keys, None), + ) + .unwrap(); + let online_nia = wallet_nia + .go_online(test_go_online_options(Some(ELECTRUM_URL))) + .unwrap(); + fund_wallet(wallet_nia.get_address().unwrap()); + test_create_utxos_default(&mut wallet_nia, online_nia); + let receive_data = test_blind_receive(&mut wallet_nia); + let recipient_map = HashMap::from([( + asset_ifa.asset_id.clone(), + vec![Recipient { + assignment: Assignment::Fungible(1), + recipient_id: receive_data.recipient_id.clone(), + witness_data: None, + transport_endpoints: TRANSPORT_ENDPOINTS.clone(), + }], + )]); + let txid = test_send(&mut wallet, online, &recipient_map); + assert!(!txid.is_empty()); + wait_for_refresh(&mut wallet_nia, online_nia, None, None); + wait_for_refresh(&mut wallet, online, None, None); + mine(false); + wait_for_refresh(&mut wallet_nia, online_nia, None, None); + wait_for_refresh(&mut wallet, online, None, None); + let transfer_recv = get_test_transfer_recipient(&wallet_nia, &receive_data.recipient_id); + let (transfer_send, _, _) = get_test_transfer_sender(&wallet, &txid); + let (transfer_data_recv, _) = get_test_transfer_data(&wallet_nia, &transfer_recv); + let (transfer_data_send, _) = get_test_transfer_data(&wallet, &transfer_send); + assert_eq!(transfer_data_recv.status, TransferStatus::Settled); + assert_eq!(transfer_data_send.status, TransferStatus::Settled); + drop(wallet_nia); + let mut wallet_nia = Wallet::new( + WalletData { + data_dir: get_test_data_dir_string(), + bitcoin_network, + database_type: DatabaseType::Sqlite, + max_allocations_per_utxo: MAX_ALLOCATIONS_PER_UTXO, + supported_schemas: vec![AssetSchema::Nia], + }, + SinglesigKeys::from_keys(&keys, None), + ) + .unwrap(); + let online_nia = wallet_nia + .go_online(test_go_online_options(Some(ELECTRUM_URL))) + .unwrap(); + let result = test_burn_begin_result(&mut wallet_nia, online_nia, &asset_ifa.asset_id, 10); + assert_matches!(result, Err(Error::UnsupportedSchema { asset_schema: _ })); + // - burn not supported + let asset_nia = test_issue_asset_nia(&mut wallet, online, None); + let asset_cfa = test_issue_asset_cfa(&mut wallet, online, None, None); + let asset_uda = test_issue_asset_uda(&mut wallet, online, None, None, vec![]); + let unsupported_asset_ids = [ + (asset_nia.asset_id, AssetSchema::Nia), + (asset_cfa.asset_id, AssetSchema::Cfa), + (asset_uda.asset_id, AssetSchema::Uda), + ]; + for (asset_id, schema) in unsupported_asset_ids { + let result = test_burn_result(&mut wallet, online, &asset_id, 10); + assert_matches!(result, Err(Error::UnsupportedBurn { asset_schema }) if asset_schema == schema); + } + // - burn zero amount + let result = test_burn_begin_result(&mut wallet, online, &asset_ifa.asset_id, 0); + assert_matches!(result, Err(Error::NoBurnAmount)); + + // burn_end input params + let address = test_get_address(&mut wallet); + let unsigned_psbt = wallet + .send_btc_begin(online, address, 1000, FEE_RATE, false, true) + .unwrap(); + let signed_psbt = wallet.sign_psbt(unsigned_psbt, None).unwrap(); + // - check online is correct + let result = test_burn_end_result(&mut wallet, wrong_online, &signed_psbt); + assert_matches!(result, Err(Error::CannotChangeOnline)); + // - check signed_psbt is valid + let result = test_burn_end_result(&mut wallet, online, ""); + assert_matches!(result, Err(Error::InvalidPsbt { details: _ })); + + // burn_end errors + // - no prior burn_begin + test_create_utxos(&mut wallet, online, false, Some(1), None, FEE_RATE, None); + let unsigned_psbt = test_burn_begin(&mut wallet, online, &asset_ifa.asset_id, 10); + let signed_psbt = wallet.sign_psbt(unsigned_psbt, None).unwrap(); + let psbt_txid = Psbt::from_str(&signed_psbt) + .unwrap() + .extract_tx() + .unwrap() + .compute_txid() + .to_string(); + let (mut wallet_2, online_2) = get_empty_wallet!(); + let result = test_burn_end_result(&mut wallet_2, online_2, &signed_psbt); + assert_matches!(result, Err(Error::UnknownTransfer { txid }) if txid == psbt_txid); +} diff --git a/src/wallet/test/create_utxos.rs b/src/wallet/test/create_utxos.rs index 45163d3f..c2d055df 100644 --- a/src/wallet/test/create_utxos.rs +++ b/src/wallet/test/create_utxos.rs @@ -161,7 +161,7 @@ fn up_to_allocation_checks() { assert!(matches!(result, Err(Error::AllocationsAlreadyAvailable))); // - settled - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); // UTXO 1 now spent, UTXO 2 (RGB+BTC change) has at least 1 free allocation, UTXO 3 is empty @@ -281,22 +281,40 @@ fn skip_sync() { ); // sync so the bitcoin UTXO becomes visible - wallet.sync(online).unwrap(); + wallet + .sync( + online, + SyncOptions { + keychain: SyncKeychain::Vanilla { + lookback: INDEXER_SYNC_LOOKBACK as u32, + }, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); let unspents = test_list_unspents(&mut wallet, None, false); assert_eq!(unspents.len(), 1); - // create UTXOs skipping sync (returns 0 created UTXOs) + // create UTXOs skipping sync let num_utxos_created = wallet .create_utxos(online, true, None, None, FEE_RATE, true) .unwrap(); - assert_eq!(num_utxos_created, 0); + assert_eq!(num_utxos_created, UTXO_NUM); - // created UTXOs not yet visible + // created UTXOs already visible let unspents = test_list_unspents(&mut wallet, None, false); - assert_eq!(unspents.len(), 1); + assert_eq!(unspents.len(), (UTXO_NUM + 1) as usize); - // created UTXOs become visible after syncing - wallet.sync(online).unwrap(); + // created UTXOs still consistent after syncing + wallet + .sync( + online, + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); let unspents = test_list_unspents(&mut wallet, None, false); assert_eq!(unspents.len(), (UTXO_NUM + 1) as usize); } diff --git a/src/wallet/test/drain_to.rs b/src/wallet/test/drain_to.rs index 6f7c69a4..be9eacce 100644 --- a/src/wallet/test/drain_to.rs +++ b/src/wallet/test/drain_to.rs @@ -29,13 +29,13 @@ fn success() { test_drain_to(&mut wallet, online, &address); let bak_info_after = wallet.database().get_backup_info().unwrap().unwrap(); assert!(bak_info_after.last_operation_timestamp > bak_info_before.last_operation_timestamp); - mine(false, false); + mine(false); wait_for_unspents(&mut wallet, Some(online), false, 0); // issue asset (to produce an RGB allocation) fund_wallet(test_get_address(&mut wallet)); test_create_utxos_default(&mut wallet, online); - mine(false, false); + mine(false); test_issue_asset_nia(&mut wallet, online, None); // drain funded wallet with RGB allocations @@ -53,7 +53,7 @@ fn success() { }; wait_for_btc_balance(&mut wallet, online, &expected_balance); test_drain_to(&mut wallet, online, &test_get_address(&mut rcv_wallet)); - mine(false, false); + mine(false); wait_for_unspents(&mut wallet, Some(online), false, 0); } @@ -93,7 +93,7 @@ fn pending_witness_receive() { // refresh receiver (no UTXOs created) + sender (to broadcast) + mine wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); // receiver sees the new UTXO let unspents = list_test_unspents(&mut rcv_wallet, "before draining"); @@ -145,7 +145,7 @@ fn drain_to_begin_and_end_success() { assert!(bak_info_after_end.last_operation_timestamp > bak_info_before.last_operation_timestamp); // verify the drain was effective - mine(false, false); + mine(false); wait_for_unspents(&mut wallet, Some(online), false, 0); } @@ -211,7 +211,17 @@ fn reservation_interaction() { for _ in 0..3 { fund_wallet(test_get_address(&mut wallet)); } - wallet.sync(online).unwrap(); + wallet + .sync( + online, + SyncOptions { + keychain: SyncKeychain::Vanilla { + lookback: INDEXER_SYNC_LOOKBACK as u32, + }, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); let (mut rcv_wallet, _rcv_online) = get_empty_wallet!(); let (mut drain_wallet, _drain_online) = get_empty_wallet!(); diff --git a/src/wallet/test/fail_transfers.rs b/src/wallet/test/fail_transfers.rs index 887360cb..f67e3434 100644 --- a/src/wallet/test/fail_transfers.rs +++ b/src/wallet/test/fail_transfers.rs @@ -67,7 +67,7 @@ fn success() { )]); let txid = test_send(&mut wallet, online, &recipient_map); assert!(!txid.is_empty()); - stop_mining(); + let _guard = stop_mining(); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); show_unspent_colorings(&mut rcv_wallet, "receiver run 1 after refresh 1"); show_unspent_colorings(&mut wallet, "sender run 1 no refresh"); @@ -107,7 +107,8 @@ fn success() { // progress transfer to Settled wait_for_refresh(&mut wallet, online, None, None); - mine(false, true); + drop(_guard); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, None, None); @@ -363,7 +364,7 @@ fn fail() { TransferStatus::WaitingCounterparty )); - stop_mining(); + let _guard = stop_mining(); // don't fail unknown idx let result = rcv_wallet.fail_transfers(rcv_online, Some(UNKNOWN_IDX), false, false); @@ -407,7 +408,8 @@ fn fail() { )); // mine and refresh so transfers can settle - mine(false, true); + drop(_guard); + mine(false); wait_for_refresh(&mut wallet, online, Some(&asset_id), None); wait_for_refresh(&mut rcv_wallet, rcv_online, Some(&asset_id), None); @@ -473,7 +475,6 @@ fn batch_fail() { FEE_RATE, MIN_CONFIRMATIONS, None, - false, ) .unwrap(); @@ -552,7 +553,7 @@ fn skip_sync() { )]); let txid = test_send(&mut wallet, online, &recipient_map); assert!(!txid.is_empty()); - stop_mining(); + let _guard = stop_mining(); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); show_unspent_colorings(&mut rcv_wallet, "receiver run 1 after refresh 1"); show_unspent_colorings(&mut wallet, "sender run 1 no refresh"); @@ -596,7 +597,8 @@ fn skip_sync() { // progress transfer to Settled wait_for_refresh(&mut wallet, online, None, None); - mine(false, true); + drop(_guard); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, None, None); @@ -687,3 +689,93 @@ fn skip_sync() { TransferStatus::Failed )); } + +#[cfg(feature = "electrum")] +#[test] +#[parallel] +fn waiting_safe_height() { + initialize(); + + let amount_1: u64 = 66; + let amount_2: u64 = 33; + + // wallets + let (mut wallet_1, online_1) = get_funded_wallet!(); + let (mut wallet_2, online_2) = get_funded_wallet!(); + + // issue + let asset = test_issue_asset_nia(&mut wallet_1, online_1, None); + + // 1st transfer: wallet 1 > wallet 2 + let receive_data_1 = test_blind_receive(&mut wallet_2); + let recipient_map_1 = HashMap::from([( + asset.asset_id.clone(), + vec![Recipient { + assignment: Assignment::Fungible(amount_1), + recipient_id: receive_data_1.recipient_id.clone(), + witness_data: None, + transport_endpoints: TRANSPORT_ENDPOINTS.clone(), + }], + )]); + let txid_1 = test_send(&mut wallet_1, online_1, &recipient_map_1); + assert!(!txid_1.is_empty()); + let _guard = stop_mining_when_alone(); + wait_for_refresh(&mut wallet_2, online_2, None, None); + wait_for_refresh(&mut wallet_1, online_1, Some(&asset.asset_id), None); + force_mine_no_resume_when_alone(false); + wait_for_refresh(&mut wallet_2, online_2, None, None); + wait_for_refresh(&mut wallet_1, online_1, Some(&asset.asset_id), None); + assert!(check_test_transfer_status_recipient( + &wallet_2, + &receive_data_1.recipient_id, + TransferStatus::Settled + )); + + // 2nd transfer: wallet 1 > wallet 2 with min_confirmations = 2 + // txid_1 has only one confirmation, so transfer parks in WaitingSafeHeight + let receive_data_2 = wallet_2 + .blind_receive( + None, + Assignment::Any, + Some((now().unix_timestamp() + DURATION_RCV_TRANSFER as i64) as u64), + TRANSPORT_ENDPOINTS.clone(), + 2, + ) + .unwrap(); + let recipient_map_2 = HashMap::from([( + asset.asset_id.clone(), + vec![Recipient { + assignment: Assignment::Fungible(amount_2), + recipient_id: receive_data_2.recipient_id.clone(), + witness_data: None, + transport_endpoints: TRANSPORT_ENDPOINTS.clone(), + }], + )]); + let txid_2 = test_send(&mut wallet_1, online_1, &recipient_map_2); + assert!(!txid_2.is_empty()); + + // transfer parks in WaitingSafeHeight because it contains unsafe history + wait_for_refresh( + &mut wallet_2, + online_2, + None, + Some(&[receive_data_2.batch_transfer_idx]), + ); + assert!(check_test_transfer_status_recipient( + &wallet_2, + &receive_data_2.recipient_id, + TransferStatus::WaitingSafeHeight + )); + + // fail the receive transfer in WaitingSafeHeight + assert!(test_fail_transfers_single( + &mut wallet_2, + online_2, + receive_data_2.batch_transfer_idx + )); + assert!(check_test_transfer_status_recipient( + &wallet_2, + &receive_data_2.recipient_id, + TransferStatus::Failed + )); +} diff --git a/src/wallet/test/get_asset_balance.rs b/src/wallet/test/get_asset_balance.rs index 759586b1..82b600b3 100644 --- a/src/wallet/test/get_asset_balance.rs +++ b/src/wallet/test/get_asset_balance.rs @@ -303,7 +303,7 @@ fn transfer_balances() { wait_for_asset_balance(&wallet_recv, &asset_1.asset_id, &expected_balance_1); // take transfers from WaitingConfirmations to Settled - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_recv, online_recv, Some(&asset_1.asset_id), None); wait_for_refresh(&mut wallet_send, online_send, Some(&asset_1.asset_id), None); // balances with transfer Settled @@ -411,7 +411,7 @@ fn transfer_balances() { wait_for_asset_balance(&wallet_recv, &asset_1.asset_id, &expected_balance); // take transfers from WaitingConfirmations to Settled - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_recv, online_recv, Some(&asset_1.asset_id), None); wait_for_refresh(&mut wallet_send, online_send, Some(&asset_1.asset_id), None); @@ -465,13 +465,28 @@ fn transfer_balances() { FEE_RATE, MIN_CONFIRMATIONS, None, - false, ) .unwrap(); // sync the wallets - wallet_send.sync(online_send).unwrap(); - wallet_recv.sync(online_recv).unwrap(); + wallet_send + .sync( + online_send, + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); + wallet_recv + .sync( + online_recv, + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); show_unspent_colorings(&mut wallet_send, "send after 3rd send"); show_unspent_colorings(&mut wallet_recv, "recv after 3rd send"); @@ -531,7 +546,7 @@ fn transfer_balances() { wait_for_asset_balance(&wallet_recv, &asset_1.asset_id, &expected_balance); // take transfers from WaitingConfirmations to Settled - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_recv, online_recv, Some(&asset_1.asset_id), None); wait_for_refresh(&mut wallet_send, online_send, Some(&asset_1.asset_id), None); diff --git a/src/wallet/test/get_btc_balance.rs b/src/wallet/test/get_btc_balance.rs index fa682c26..1c058092 100644 --- a/src/wallet/test/get_btc_balance.rs +++ b/src/wallet/test/get_btc_balance.rs @@ -29,7 +29,7 @@ fn success() { assert_eq!(balance, expected_balance); // future balance after funding - stop_mining(); + let _guard = stop_mining(); send_to_address(test_get_address(&mut wallet)); let expected_balance = BtcBalance { vanilla: Balance { @@ -46,7 +46,8 @@ fn success() { wait_for_btc_balance(&mut wallet, online, &expected_balance); // settled balance after mining - mine(false, true); + drop(_guard); + mine(false); let expected_balance = BtcBalance { vanilla: Balance { settled: 100000000, @@ -62,7 +63,7 @@ fn success() { assert_eq!(test_get_btc_balance(&mut wallet, online), expected_balance); // future vanilla change + colored UTXOs balance - stop_mining(); + let _guard = stop_mining(); test_create_utxos_default(&mut wallet, online); let expected_balance = BtcBalance { vanilla: Balance { @@ -79,7 +80,8 @@ fn success() { assert_eq!(test_get_btc_balance(&mut wallet, online), expected_balance); // settled balance after mining - mine(false, true); + drop(_guard); + mine(false); let expected_balance = BtcBalance { vanilla: Balance { settled: 99994347, @@ -112,7 +114,17 @@ fn skip_sync() { ) -> impl FnMut() -> bool + 'a { move || -> bool { if sync { - wallet.sync(online).unwrap(); + wallet + .sync( + online, + SyncOptions { + keychain: SyncKeychain::Vanilla { + lookback: INDEXER_SYNC_LOOKBACK as u32, + }, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); } let balance = wallet.get_btc_balance(None, true).unwrap(); balance == *expected_balance @@ -138,7 +150,7 @@ fn skip_sync() { assert_eq!(balance, expected_balance); // future balance after funding - stop_mining(); + let _guard = stop_mining(); send_to_address(test_get_address(&mut wallet)); let expected_balance = BtcBalance { vanilla: Balance { @@ -166,7 +178,8 @@ fn skip_sync() { )); // settled balance after mining - mine(false, true); + drop(_guard); + mine(false); let expected_balance = BtcBalance { vanilla: Balance { settled: 100000000, @@ -193,7 +206,7 @@ fn skip_sync() { )); // future vanilla change + colored UTXOs balance (create UTXOs skipping sync) - stop_mining(); + let _guard = stop_mining(); wallet .create_utxos(online, false, None, None, FEE_RATE, true) .unwrap(); @@ -209,13 +222,13 @@ fn skip_sync() { spendable: 5000, }, }; - // no change to balance if sync is skipped - assert!(!wait_for_function( + // balance reflects the self-broadcast TX immediately (no manual sync needed) + assert!(wait_for_function( get_check(&mut wallet, online, &expected_balance, false), check_timeout, check_interval, )); - // balance updated after manual sync + // still consistent after a manual sync assert!(wait_for_function( get_check(&mut wallet, online, &expected_balance, true), check_timeout, @@ -223,7 +236,8 @@ fn skip_sync() { )); // settled balance after mining - mine(false, true); + drop(_guard); + mine(false); let expected_balance = BtcBalance { vanilla: Balance { settled: 99994347, diff --git a/src/wallet/test/get_fee_estimation.rs b/src/wallet/test/get_fee_estimation.rs index aec0bd88..90712fcf 100644 --- a/src/wallet/test/get_fee_estimation.rs +++ b/src/wallet/test/get_fee_estimation.rs @@ -22,14 +22,24 @@ fn success_common(wallet: &mut Wallet, online: Online, esplora: bool) { break; } } - wallet.sync(online).unwrap(); + wallet + .sync( + online, + SyncOptions { + keychain: SyncKeychain::Vanilla { + lookback: INDEXER_SYNC_LOOKBACK as u32, + }, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); } for _ in 0..100 { for _ in 0..15 { random_send_btc(wallet, online); } - mine(esplora, false); + mine(esplora); for _ in 0..3 { random_send_btc(wallet, online); } @@ -73,7 +83,7 @@ fn success_esplora() { #[cfg(any(feature = "electrum", feature = "esplora"))] fn fail_common(wallet: &Wallet, online: Online, esplora: bool) { for _ in 0..100 { - mine_blocks(esplora, 100, false); + mine_blocks(esplora, 100); if let Err(e) = wallet.get_fee_estimation(online, 5) { assert!(matches!(e, Error::CannotEstimateFees)); return; diff --git a/src/wallet/test/inflate.rs b/src/wallet/test/inflate.rs index d24b07a3..95bd2c48 100644 --- a/src/wallet/test/inflate.rs +++ b/src/wallet/test/inflate.rs @@ -58,7 +58,7 @@ fn success() { } ); - mine(false, false); + mine(false); assert!(test_refresh_asset(&mut wallet, online, &asset.asset_id)); show_unspent_colorings(&mut wallet, "after inflate mine + refresh"); @@ -225,7 +225,7 @@ fn success() { show_unspent_colorings(&mut wallet, "after send refresh 1"); // transfers progress to status Settled after tx mining + refresh - mine(false, false); + mine(false); std::thread::sleep(Duration::from_millis(1000)); // make sure updated_at will be at least +1s wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -281,7 +281,7 @@ fn success() { &asset.asset_id, &last_inflation_amounts, ); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); show_unspent_colorings(&mut wallet, "after last inflate mine + refresh"); @@ -329,7 +329,7 @@ fn success() { wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -355,9 +355,7 @@ fn fail() { // inflate errors // - watch-only (_check_xprv) let mut wallet_wo = get_test_wallet(false, None); - let online_wo = wallet_wo - .go_online(false, ELECTRUM_URL.to_string()) - .unwrap(); + let online_wo = wallet_wo.go_online(test_go_online_options(None)).unwrap(); let result = test_inflate_result(&mut wallet_wo, online_wo, &asset_ifa.asset_id, &[1]); assert_matches!(result, Err(Error::WatchOnly)); @@ -434,7 +432,7 @@ fn fail() { ) .unwrap(); let online_nia = wallet_nia - .go_online(true, ELECTRUM_URL.to_string()) + .go_online(test_go_online_options(Some(ELECTRUM_URL))) .unwrap(); fund_wallet(wallet_nia.get_address().unwrap()); test_create_utxos_default(&mut wallet_nia, online_nia); @@ -452,7 +450,7 @@ fn fail() { assert!(!txid.is_empty()); wait_for_refresh(&mut wallet_nia, online_nia, None, None); wait_for_refresh(&mut wallet, online, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_nia, online_nia, None, None); wait_for_refresh(&mut wallet, online, None, None); let transfer_recv = get_test_transfer_recipient(&wallet_nia, &receive_data.recipient_id); @@ -474,7 +472,7 @@ fn fail() { ) .unwrap(); let online_nia = wallet_nia - .go_online(true, ELECTRUM_URL.to_string()) + .go_online(test_go_online_options(Some(ELECTRUM_URL))) .unwrap(); let result = test_inflate_begin_result(&mut wallet_nia, online_nia, &asset_ifa.asset_id, &[1]); assert_matches!(result, Err(Error::UnsupportedSchema { asset_schema: _ })); diff --git a/src/wallet/test/issue_asset_cfa.rs b/src/wallet/test/issue_asset_cfa.rs index 8a90407f..6862170f 100644 --- a/src/wallet/test/issue_asset_cfa.rs +++ b/src/wallet/test/issue_asset_cfa.rs @@ -389,16 +389,10 @@ fn fail() { // insufficient funds let result = test_issue_asset_cfa_result(&mut wallet, online, None, None); - assert!(matches!( - result, - Err(Error::InsufficientBitcoins { - needed: _, - available: _ - }) - )); + assert!(matches!(result, Err(Error::InsufficientAllocationSlots))); fund_wallet(test_get_address(&mut wallet)); - mine(false, false); + mine(false); // insufficient allocations let result = test_issue_asset_cfa_result(&mut wallet, online, None, None); diff --git a/src/wallet/test/issue_asset_ifa.rs b/src/wallet/test/issue_asset_ifa.rs index 31f89264..ba971e81 100644 --- a/src/wallet/test/issue_asset_ifa.rs +++ b/src/wallet/test/issue_asset_ifa.rs @@ -470,16 +470,10 @@ fn fail() { // insufficient funds let result = test_issue_asset_ifa_result(&mut wallet, online, None, None, None); - assert!(matches!( - result, - Err(Error::InsufficientBitcoins { - needed: _, - available: _ - }) - )); + assert!(matches!(result, Err(Error::InsufficientAllocationSlots))); fund_wallet(test_get_address(&mut wallet)); - mine(false, false); + mine(false); // insufficient allocations let result = test_issue_asset_ifa_result(&mut wallet, online, None, None, None); diff --git a/src/wallet/test/issue_asset_nia.rs b/src/wallet/test/issue_asset_nia.rs index 73c152a6..333bad76 100644 --- a/src/wallet/test/issue_asset_nia.rs +++ b/src/wallet/test/issue_asset_nia.rs @@ -301,16 +301,10 @@ fn fail() { // insufficient funds let result = test_issue_asset_nia_result(&mut wallet, online, None); - assert!(matches!( - result, - Err(Error::InsufficientBitcoins { - needed: _, - available: _ - }) - )); + assert!(matches!(result, Err(Error::InsufficientAllocationSlots))); fund_wallet(test_get_address(&mut wallet)); - mine(false, false); + mine(false); // insufficient allocations let result = test_issue_asset_nia_result(&mut wallet, online, None); diff --git a/src/wallet/test/issue_asset_uda.rs b/src/wallet/test/issue_asset_uda.rs index 38d4dda7..6c32d389 100644 --- a/src/wallet/test/issue_asset_uda.rs +++ b/src/wallet/test/issue_asset_uda.rs @@ -397,16 +397,10 @@ fn fail() { // insufficient funds let result = test_issue_asset_uda_result(&mut wallet, online, None, None, vec![]); - assert!(matches!( - result, - Err(Error::InsufficientBitcoins { - needed: _, - available: _ - }) - )); + assert!(matches!(result, Err(Error::InsufficientAllocationSlots))); fund_wallet(test_get_address(&mut wallet)); - mine(false, false); + mine(false); // insufficient allocations let result = test_issue_asset_uda_result(&mut wallet, online, None, None, vec![]); diff --git a/src/wallet/test/list_pending_vanilla_txs.rs b/src/wallet/test/list_pending_vanilla_txs.rs index dd166fa4..9bb6b984 100644 --- a/src/wallet/test/list_pending_vanilla_txs.rs +++ b/src/wallet/test/list_pending_vanilla_txs.rs @@ -55,7 +55,7 @@ fn success() { // completing the send_btc drops it from the list let signed = wallet.sign_psbt(send_psbt_str, None).unwrap(); - let _ = wallet.send_btc_end(online, signed, false).unwrap(); + let _ = wallet.send_btc_end(online, signed).unwrap(); let pending = wallet.list_pending_vanilla_txs().unwrap(); assert_eq!(pending.len(), 1); assert_eq!(pending[0].r#type, WalletTransactionType::CreateUtxos); diff --git a/src/wallet/test/list_transactions.rs b/src/wallet/test/list_transactions.rs index f53b8f35..891e2571 100644 --- a/src/wallet/test/list_transactions.rs +++ b/src/wallet/test/list_transactions.rs @@ -8,7 +8,7 @@ fn success() { let amount: u64 = 66; - stop_mining_when_alone(); + let _guard = stop_mining_when_alone(); let (mut wallet, online) = get_empty_wallet!(); let (mut rcv_wallet, rcv_online) = get_empty_wallet!(); @@ -57,7 +57,7 @@ fn success() { .any(|t| t.confirmation_time.is_none()) ); // sync wallet when online is provided - resume_mining(); + drop(_guard); let transactions = test_list_transactions(&mut wallet, Some(online)); let rcv_transactions = test_list_transactions(&mut rcv_wallet, Some(rcv_online)); assert!(transactions.iter().all(|t| t.confirmation_time.is_some())); @@ -85,7 +85,7 @@ fn success() { // settle the transfer so the tx gets broadcasted and receiver sees the new UTXO wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, None, None); let transactions = test_list_transactions(&mut wallet, Some(online)); @@ -110,7 +110,7 @@ fn success() { ); drain_wallet(&mut wallet, online); - mine(false, false); + mine(false); let transactions = test_list_transactions(&mut wallet, Some(online)); assert_eq!(transactions.len(), 4); assert!( @@ -141,7 +141,17 @@ fn skip_sync() { // transaction list reports the TX after manually syncing assert!(wait_for_function( || { - wallet.sync(online).unwrap(); + wallet + .sync( + online, + SyncOptions { + keychain: SyncKeychain::Vanilla { + lookback: INDEXER_SYNC_LOOKBACK as u32, + }, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); let transactions = test_list_transactions(&mut wallet, None); transactions.len() == 1 }, diff --git a/src/wallet/test/list_transfers.rs b/src/wallet/test/list_transfers.rs index 18820577..0dd406e1 100644 --- a/src/wallet/test/list_transfers.rs +++ b/src/wallet/test/list_transfers.rs @@ -150,7 +150,7 @@ fn success() { assert_eq!(transfer_recv_witness.txid, Some(txid.clone())); // refresh a second time to settle the transfers - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, None, None); diff --git a/src/wallet/test/list_unspents.rs b/src/wallet/test/list_unspents.rs index 138c01db..d5d902c6 100644 --- a/src/wallet/test/list_unspents.rs +++ b/src/wallet/test/list_unspents.rs @@ -23,7 +23,7 @@ fn success() { assert_eq!(unspent_list_all.len(), 0); fund_wallet(test_get_address(&mut wallet)); - mine(false, false); + mine(false); // one unspent, no RGB allocations let unspent_list_settled = test_list_unspents(&mut wallet, Some(online), true); @@ -335,7 +335,7 @@ fn success() { ); // transfer progresses to status Settled - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); show_unspent_colorings(&mut rcv_wallet, "receiver after send - Settled"); @@ -407,7 +407,17 @@ fn skip_sync() { assert_eq!(unspents.len(), 0); // 1 unspent after manually syncing - wallet.sync(online).unwrap(); + wallet + .sync( + online, + SyncOptions { + keychain: SyncKeychain::Vanilla { + lookback: INDEXER_SYNC_LOOKBACK as u32, + }, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); let unspents = test_list_unspents(&mut wallet, None, false); assert_eq!(unspents.len(), 1); } diff --git a/src/wallet/test/mod.rs b/src/wallet/test/mod.rs index 2f16b067..049eff0b 100644 --- a/src/wallet/test/mod.rs +++ b/src/wallet/test/mod.rs @@ -85,6 +85,8 @@ const TINY_BTC_AMOUNT: u32 = 330; const QUEUE_DEPTH_EXCEEDED: &str = "Work queue depth exceeded"; const DURATION_RCV_TRANSFER: u32 = 86400; const DURATION_SEND_TRANSFER: u32 = 3600; +#[cfg(any(feature = "electrum", feature = "esplora"))] +pub(crate) const INDEXER_SYNC_LOOKBACK: usize = 20; static INIT: Once = Once::new(); @@ -303,6 +305,7 @@ pub(crate) use utils::{api::*, chain::*, helpers::*}; mod abort_pending_vanilla_tx; mod backup; mod blind_receive; +mod burn; mod create_utxos; mod delete_transfers; mod drain_to; diff --git a/src/wallet/test/multisig/mod.rs b/src/wallet/test/multisig/mod.rs index cad70146..e813939b 100644 --- a/src/wallet/test/multisig/mod.rs +++ b/src/wallet/test/multisig/mod.rs @@ -133,7 +133,7 @@ fn success() { // fund wallet 1 let sats = 30_000; send_sats_to_address(wlt_1.get_address(), Some(sats)); - mine(false, false); + mine(false); check_hub_info(&mut [&mut wlt_1, &mut wlt_2, &mut wlt_3]); @@ -715,6 +715,43 @@ fn success() { false, ); + println!("\n=== burn (wlt_1) ==="); + check_wallets_up_to_date(&mut [&mut wlt_1, &mut wlt_2, &mut wlt_3]); + let burn_amount = 50; + let op_init = wlt_1.burn_init(&ifa_asset.asset_id, burn_amount); + inspect_burn(&wlt_3, &op_init, &ifa_asset); + operation_complete::( + op_init.operation_idx, + &mut [&mut wlt_1, &mut wlt_2, &mut wlt_3], + &mut [], + &mut [], + true, + ); + settle_transfer( + &mut [&mut wlt_1, &mut wlt_2, &mut wlt_3], + &mut [] as &mut [&mut MultisigParty], + Some(&ifa_asset.asset_id), + None, + Some(&op_init.psbt), + false, + ); + let post_burn_supply = new_supply - burn_amount; + check_asset_balance( + &[&wlt_1, &wlt_2, &wlt_3], + &ifa_asset.asset_id, + (post_burn_supply, post_burn_supply, post_burn_supply), + ); + + println!("\n=== burn discarded (wlt_3) ==="); + let op_init = wlt_3.burn_init(&ifa_asset.asset_id, 1); + operation_complete::( + op_init.operation_idx, + &mut [], + &mut [&mut wlt_1, &mut wlt_2], + &mut [&mut wlt_3], + false, + ); + println!("\n=== send BTC (wlt_1 → singlesig) ==="); check_wallets_up_to_date(&mut [&mut wlt_1, &mut wlt_2, &mut wlt_3]); let amount = 1000; @@ -743,7 +780,7 @@ fn success() { wlt_3.multisig_mut(), ], (0, 6442, 6442), - (16452, 16452, 16452), + (15366, 15366, 15366), ); let op_init_last_successful = op_init; @@ -831,12 +868,12 @@ fn success() { // final state expectations let btc_final_vanilla = (0, 6442, 6442); - let btc_final_colored = (16452, 16452, 16452); + let btc_final_colored = (15366, 15366, 15366); let tx_type_final = TransactionType::SendBtc; #[rustfmt::skip] let assets_final = HashMap::from([ (cfa_asset.asset_id.as_str(), (180, 180, 180, 3, TransferStatus::Settled)), - (ifa_asset.asset_id.as_str(), (201, 201, 201, 3, TransferStatus::Settled)), + (ifa_asset.asset_id.as_str(), (151, 151, 151, 4, TransferStatus::Settled)), (nia_asset_1.asset_id.as_str(), (84, 84, 84, 2, TransferStatus::Settled)), (nia_asset_2.asset_id.as_str(), (26, 26, 26, 4, TransferStatus::Failed)), (uda_asset.asset_id.as_str(), (1, 1, 1, 3, TransferStatus::Settled)), @@ -1148,17 +1185,18 @@ fn fail() { // invalid hub URL let err = wlt_badtoken_multisig .go_online( - false, - ELECTRUM_URL.to_string(), - s!("invalid"), - cosigner_tokens[0].to_string(), + test_go_online_options(None), + MultisigOnlineOptions { + hub_url: s!("invalid"), + hub_token: cosigner_tokens[0].to_string(), + }, ) .unwrap_err(); assert_matches!(err, Error::MultisigHubService { details: d } if d == "URL must be valid and start with http:// or https://"); // respond with PSBT that has no signatures send_sats_to_address(wlt_1.get_address(), Some(10_000)); - mine(false, false); + mine(false); let op_init = wlt_1.create_utxos_init(false, None, None, FEE_RATE); let op_idx_1 = op_init.operation_idx; let unsigned_psbt = op_init.psbt.clone(); @@ -1184,7 +1222,16 @@ fn fail() { let signed_psbt = wlt_2_singlesig .sign_psbt(unsigned_psbt.clone(), None) .unwrap(); - wlt_2.multisig_mut().sync_db_txos(false, false).unwrap(); + wlt_2 + .multisig_mut() + .sync_wallet( + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + false, + ) + .unwrap(); wlt_2.respond_to_operation(op_idx_1, RespondToOperation::Ack(signed_psbt.clone())); let err = wlt_3 .respond_to_operation_res(op_idx_1, RespondToOperation::Nack) diff --git a/src/wallet/test/multisig/utils.rs b/src/wallet/test/multisig/utils.rs index c6d20c24..fd46ff1b 100644 --- a/src/wallet/test/multisig/utils.rs +++ b/src/wallet/test/multisig/utils.rs @@ -110,6 +110,12 @@ impl Sanitizable for InflateDetails { } } +impl Sanitizable for BurnDetails { + fn sanitize(&mut self) { + self.fascia_path = sanitize_path(&self.fascia_path); + } +} + impl Sanitizable for SendDetails { fn sanitize(&mut self) { self.fascia_path = sanitize_path(&self.fascia_path); @@ -139,6 +145,26 @@ impl Sanitizable for Operation { } => { details.sanitize(); } + Operation::BurnCompleted { + txid: _, + details, + status: _, + } => { + details.sanitize(); + } + Operation::BurnDiscarded { details, status: _ } => { + details.sanitize(); + } + Operation::BurnPending { details, status: _ } => { + details.sanitize(); + } + Operation::BurnToReview { + psbt: _, + details, + status: _, + } => { + details.sanitize(); + } Operation::SendCompleted { txid: _, details, @@ -317,10 +343,11 @@ pub(super) fn get_test_ms_wallet(keys: &MultisigKeys, dir: String) -> MultisigWa pub(super) fn ms_go_online_res(wallet: &mut MultisigWallet, token: &str) -> Result { wallet.go_online( - false, - ELECTRUM_URL.to_string(), - MULTISIG_HUB_URL.to_string(), - token.to_string(), + test_go_online_options(None), + MultisigOnlineOptions { + hub_url: MULTISIG_HUB_URL.to_string(), + hub_token: token.to_string(), + }, ) } @@ -508,6 +535,25 @@ pub(super) trait MultisigOps { ) } + fn burn_init(&mut self, asset_id: &str, amount: u64) -> InitOperationResult { + println!( + "burn init {}", + self.multisig_mut().get_wallet_data().data_dir + ); + let bt_before = self.bak_ts(); + let res = self.burn_init_res(asset_id, amount).unwrap(); + assert!(self.bak_ts() > bt_before); + op_counter_bump(); + println!("initiated burn with operation ID {}", res.operation_idx); + res + } + + fn burn_init_res(&mut self, asset_id: &str, amount: u64) -> Result { + let online = self.online(); + self.multisig_mut() + .burn_init(online, asset_id.to_string(), amount, FEE_RATE, 1) + } + fn issue_asset_cfa(&mut self, amounts: Option<&[u64]>, file_path: Option) -> AssetCFA { println!( "issue CFA asset {}", @@ -1454,6 +1500,30 @@ pub(super) fn inspect_inflate( assert_eq!(sorted_inflate_outputs, sorted_expected); } +pub(super) fn inspect_burn( + wallet: &MultisigParty, + op_init: &InitOperationResult, + ifa_asset: &AssetIFA, +) { + let psbt = &op_init.psbt; + let (_, files) = wallet.get_op_and_files(op_init.operation_idx); + let details = BurnHandler::extract_details(&files).unwrap(); + let rgb_inspection = wallet + .multisig + .inspect_rgb_transfer(psbt.clone(), details.fascia_path, details.entropy) + .unwrap(); + assert_eq!(rgb_inspection.close_method, CloseMethod::OpretFirst); + assert_eq!(rgb_inspection.operations.len(), 1); + let ifa_op = &rgb_inspection.operations[0]; + assert_eq!(ifa_op.asset_id, ifa_asset.asset_id); + let burn_transitions: Vec<_> = ifa_op + .transitions + .iter() + .filter(|t| t.r#type == TypeOfTransition::Burn) + .collect(); + assert_eq!(burn_transitions.len(), 1); +} + pub(super) fn inspect_send( wallet: &MultisigParty, op_init: &InitOperationResult, @@ -1868,11 +1938,11 @@ pub(super) fn settle_transfer( } if let Some(psbt) = psbt { let txid = Psbt::from_str(psbt).unwrap().get_txid().to_string(); - mine_tx(false, false, &txid); + mine_tx(false, &txid); } else if let Some(txid) = txid { - mine_tx(false, false, txid); + mine_tx(false, txid); } else { - mine(false, false); + mine(false); } for wallet in &mut *receivers { wallet.refresh(asset_id); diff --git a/src/wallet/test/new.rs b/src/wallet/test/new.rs index 10d466dc..5bf143ec 100644 --- a/src/wallet/test/new.rs +++ b/src/wallet/test/new.rs @@ -298,7 +298,7 @@ fn re_instantiate_wallet() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -307,7 +307,7 @@ fn re_instantiate_wallet() { // re-instantiate wallet let mut wallet = Wallet::new(wallet_data.clone(), keys.clone()).unwrap(); - let _online = wallet.go_online(true, ELECTRUM_URL.to_string()).unwrap(); + let _online = wallet.go_online(test_go_online_options(None)).unwrap(); // check wallet asset check_test_wallet_data(&mut wallet, &asset, None, 1, amount); @@ -319,7 +319,7 @@ fn re_instantiate_wallet() { let mut keys_bad = keys.clone(); keys_bad.mnemonic = None; let mut wallet = Wallet::new(wallet_data.clone(), keys_bad).unwrap(); - let _online = wallet.go_online(true, ELECTRUM_URL.to_string()).unwrap(); + let _online = wallet.go_online(test_go_online_options(None)).unwrap(); } #[cfg(feature = "electrum")] @@ -344,7 +344,7 @@ fn watch_only_success() { ) .unwrap(); let online_watch = wallet_watch - .go_online(true, ELECTRUM_URL.to_string()) + .go_online(test_go_online_options(None)) .unwrap(); // signer wallet @@ -367,7 +367,7 @@ fn watch_only_success() { // fund wallet fund_wallet(address_watch); - mine(false, false); + mine(false); let unspents = test_list_unspents(&mut wallet_watch, Some(online_watch), false); assert_eq!(unspents.len(), 1); @@ -383,7 +383,7 @@ fn watch_only_success() { .unwrap(); let signed_psbt = wallet_sign.sign_psbt(unsigned_psbt, None).unwrap(); wallet_watch - .create_utxos_end(online_watch, signed_psbt, false) + .create_utxos_end(online_watch, signed_psbt) .unwrap(); let unspents = test_list_unspents(&mut wallet_watch, Some(online_watch), false); assert_eq!(unspents.len(), UTXO_NUM as usize + 1); @@ -455,10 +455,7 @@ fn get_descriptors_success() { // get descriptors from keys let keys = wallet.get_keys(); let bitcoin_network = wallet.bitcoin_network(); - let descriptors = keys - .build_descriptors(&bitcoin_network, &BdkNetwork::from(bitcoin_network)) - .unwrap() - .0; + let descriptors = keys.build_descriptors(&bitcoin_network).unwrap().0; // get descriptors from wallet let wlt_descriptors = wallet.get_descriptors(); @@ -487,9 +484,7 @@ fn supported_schemas() { SinglesigKeys::from_keys(&keys, None), ) .unwrap(); - let online_nia = wallet_nia - .go_online(true, ELECTRUM_URL.to_string()) - .unwrap(); + let online_nia = wallet_nia.go_online(test_go_online_options(None)).unwrap(); fund_wallet(wallet_nia.get_address().unwrap()); test_create_utxos_default(&mut wallet_nia, online_nia); @@ -519,7 +514,7 @@ fn supported_schemas() { ) .unwrap(); let rcv_online_uda = rcv_wallet_uda - .go_online(true, ELECTRUM_URL.to_string()) + .go_online(test_go_online_options(None)) .unwrap(); fund_wallet(rcv_wallet_uda.get_address().unwrap()); test_create_utxos_default(&mut rcv_wallet_uda, rcv_online_uda); @@ -562,9 +557,7 @@ fn supported_schemas() { SinglesigKeys::from_keys(&keys, None), ) .unwrap(); - let online_cfa = wallet_cfa - .go_online(true, ELECTRUM_URL.to_string()) - .unwrap(); + let online_cfa = wallet_cfa.go_online(test_go_online_options(None)).unwrap(); // send asset unsupported by the sender let receive_data = test_blind_receive(&mut rcv_wallet_uda); diff --git a/src/wallet/test/refresh.rs b/src/wallet/test/refresh.rs index 64cd498b..ffa87255 100644 --- a/src/wallet/test/refresh.rs +++ b/src/wallet/test/refresh.rs @@ -37,7 +37,7 @@ fn success() { // - 1 WaitingCounterparty + 1 WaitingConfirmations ountgoing // - 1 WaitingCounterparty + 1 WaitingConfirmations incoming - stop_mining(); + let _guard = stop_mining(); // wallet 1 > wallet 2 WaitingConfirmations and vice versa let receive_data_2a = test_blind_receive(&mut wallet_2); @@ -223,9 +223,10 @@ fn success() { TransferStatus::WaitingCounterparty )); - mine(false, true); - mine_tx(false, false, &txid_2a); - mine_tx(false, false, &txid_2b); + drop(_guard); + mine(false); + mine_tx(false, &txid_2a); + mine_tx(false, &txid_2b); // refresh incoming WaitingConfirmations only (wallet 2) assert!( @@ -366,7 +367,7 @@ fn nia_with_media() { let assets_list = test_list_assets(&wallet_2, &[]); assert!(assets_list.nia.unwrap()[0].media.is_some()); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -387,7 +388,7 @@ fn nia_with_media() { let assets_list = test_list_assets(&wallet_3, &[]); assert!(assets_list.nia.unwrap()[0].media.is_some()); wait_for_refresh(&mut wallet_2, online_2, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); let rcv_transfer = get_test_transfer_recipient(&wallet_3, &receive_data.recipient_id); @@ -439,7 +440,7 @@ fn nia_with_details() { // settle transfer wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -460,7 +461,7 @@ fn nia_with_details() { // settle transfer wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); let rcv_transfer = get_test_transfer_recipient(&wallet_3, &receive_data.recipient_id); @@ -539,7 +540,7 @@ fn uda_with_media() { let assets_list = test_list_assets(&wallet_2, &[]); assert!(assets_list.uda.unwrap()[0].media.is_some()); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -560,7 +561,7 @@ fn uda_with_media() { let assets_list = test_list_assets(&wallet_3, &[]); assert!(assets_list.uda.unwrap()[0].media.is_some()); wait_for_refresh(&mut wallet_2, online_2, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); let rcv_transfer = get_test_transfer_recipient(&wallet_3, &receive_data.recipient_id); @@ -631,7 +632,7 @@ fn uda_with_preview_and_reserves() { .is_none() ); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -661,7 +662,7 @@ fn uda_with_preview_and_reserves() { assert_eq!(token.attachments, HashMap::new()); assert!(token.reserves); wait_for_refresh(&mut wallet_2, online_2, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); let rcv_transfer = get_test_transfer_recipient(&wallet_3, &receive_data.recipient_id); @@ -724,7 +725,7 @@ fn skip_sync() { // - 1 WaitingCounterparty + 1 WaitingConfirmations ountgoing // - 1 WaitingCounterparty + 1 WaitingConfirmations incoming - stop_mining(); + let _guard = stop_mining(); // wallet 1 > wallet 2 WaitingConfirmations and vice versa let receive_data_2a = test_blind_receive(&mut wallet_2); @@ -744,7 +745,15 @@ fn skip_sync() { .unwrap() .transfers_changed() ); - wallet_2.sync(online_2).unwrap(); + wallet_2 + .sync( + online_2, + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); assert!( !wallet_2 .refresh(online_2, None, vec![], true) @@ -923,7 +932,8 @@ fn skip_sync() { TransferStatus::WaitingCounterparty )); - mine(false, true); + drop(_guard); + mine(false); // refresh incoming WaitingConfirmations only (wallet 2), skipping sync assert!( diff --git a/src/wallet/test/rust_only.rs b/src/wallet/test/rust_only.rs index 180722c3..2701481f 100644 --- a/src/wallet/test/rust_only.rs +++ b/src/wallet/test/rust_only.rs @@ -41,7 +41,7 @@ fn success() { address.assume_checked().script_pubkey(), BdkAmount::from_sat(amt_sat), ) - .fee_rate(FeeRate::from_sat_per_vb_unchecked(FEE_RATE)); + .fee_rate(FeeRate::from_sat_per_vb_u32(FEE_RATE as u32)); let mut psbt = tx_builder.finish().unwrap(); let mut psbt_copy = psbt.clone(); assert!( @@ -180,7 +180,7 @@ fn list_unspents_vanilla_success() { assert!(bak_info_after.is_none()); assert_eq!(unspent_list.len(), 0); - stop_mining(); + let _guard = stop_mining(); send_to_address(test_get_address(&mut wallet)); @@ -190,7 +190,8 @@ fn list_unspents_vanilla_success() { let unspent_list = test_list_unspents_vanilla(&mut wallet, online, Some(0)); assert_eq!(unspent_list.len(), 1); - mine(false, true); + drop(_guard); + mine(false); // one unspent, 1 confirmation let unspent_list = test_list_unspents_vanilla(&mut wallet, online, None); @@ -201,7 +202,7 @@ fn list_unspents_vanilla_success() { test_create_utxos_default(&mut wallet, online); // one unspent (change), colored unspents not listed - mine(false, false); + mine(false); let unspent_list = test_list_unspents_vanilla(&mut wallet, online, None); assert_eq!(unspent_list.len(), 1); } @@ -223,7 +224,17 @@ fn list_unspents_vanilla_skip_sync() { assert_eq!(unspents.len(), 0); // 1 unspent after manually syncing - wallet.sync(online).unwrap(); + wallet + .sync( + online, + SyncOptions { + keychain: SyncKeychain::Vanilla { + lookback: INDEXER_SYNC_LOOKBACK as u32, + }, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); let unspents = wallet .list_unspents_vanilla(online, MIN_CONFIRMATIONS, true) .unwrap(); @@ -385,7 +396,7 @@ fn color_psbt_uda() { tx_builder .drain_wallet() .drain_to(p2wpkh_addr.script_pubkey()) - .fee_rate(FeeRate::from_sat_per_vb_unchecked(FEE_RATE)); + .fee_rate(FeeRate::from_sat_per_vb_u32(FEE_RATE as u32)); let mut psbt = tx_builder.finish().unwrap(); assert!( !psbt @@ -501,7 +512,7 @@ fn color_psbt_fail() { address.assume_checked().script_pubkey(), BdkAmount::from_sat(amt_sat), ) - .fee_rate(FeeRate::from_sat_per_vb_unchecked(FEE_RATE)); + .fee_rate(FeeRate::from_sat_per_vb_u32(FEE_RATE as u32)); let mut psbt = tx_builder.finish().unwrap(); // prepare coloring data diff --git a/src/wallet/test/send.rs b/src/wallet/test/send.rs index 55e325ef..10874254 100644 --- a/src/wallet/test/send.rs +++ b/src/wallet/test/send.rs @@ -40,7 +40,6 @@ fn success() { FEE_RATE, MIN_CONFIRMATIONS, Some(expiration_timestamp), - false, ) .unwrap(); let bak_info_after = wallet.database().get_backup_info().unwrap().unwrap(); @@ -169,7 +168,7 @@ fn success() { ); // transfers progress to status Settled after tx mining + refresh - mine(false, false); + mine(false); std::thread::sleep(Duration::from_millis(1000)); // make sure updated_at will be at least +1s wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -256,7 +255,7 @@ fn success() { // settle transfer wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); let rcv_transfer = @@ -298,15 +297,7 @@ fn success() { let unspents = test_list_unspents(&mut wallet, None, false); let unspents_color_count_before = unspents.iter().filter(|u| u.utxo.colorable).count(); let txid = wallet - .send( - online, - recipient_map, - false, - 7, - MIN_CONFIRMATIONS, - None, - false, - ) + .send(online, recipient_map, false, 7, MIN_CONFIRMATIONS, None) .unwrap() .txid; assert!(!txid.is_empty()); @@ -339,7 +330,7 @@ fn success() { // settle transfer wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); let (transfer, _, _) = get_test_transfer_sender(&wallet, &txid); @@ -455,7 +446,7 @@ fn spend_all() { assert_eq!(transfer_data.status, TransferStatus::WaitingConfirmations); // transfers progress to status Settled after tx mining + refresh - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -524,7 +515,7 @@ fn send_twice_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -577,7 +568,7 @@ fn send_twice_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -678,7 +669,7 @@ fn send_extra_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -761,7 +752,7 @@ fn send_extra_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -864,7 +855,7 @@ fn send_extra_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -954,7 +945,7 @@ fn send_extra_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut wallet_1, online_1, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_1, online_1, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); @@ -1059,7 +1050,7 @@ fn send_extra_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut wallet_1, online_1, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_1, online_1, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); @@ -1115,7 +1106,7 @@ fn send_extra_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -1208,7 +1199,7 @@ fn send_received_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -1304,7 +1295,7 @@ fn send_received_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); @@ -1437,7 +1428,7 @@ fn send_received_uda_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, Some(&asset.asset_id), None); @@ -1484,7 +1475,7 @@ fn send_received_uda_success() { .is_none() ); wait_for_refresh(&mut wallet_2, online_2, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, Some(&asset.asset_id), None); @@ -1590,7 +1581,7 @@ fn send_received_cfa_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, Some(&asset.asset_id), None); @@ -1643,7 +1634,7 @@ fn send_received_cfa_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, Some(&asset.asset_id), None); @@ -1919,7 +1910,7 @@ fn receive_multiple_same_asset_success() { assert!(updated_at_2 > transfer_data_2.created_at); // transfers progress to status Settled after tx mining + refresh - mine(false, false); + mine(false); std::thread::sleep(Duration::from_millis(1000)); // make sure updated_at will be at least +1s wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -2226,7 +2217,7 @@ fn receive_multiple_different_assets_success() { // transfers progress to status Settled after tx mining + refresh std::thread::sleep(Duration::from_millis(1000)); // make sure updated_at will be at least +1s - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset_1.asset_id), None); @@ -2344,7 +2335,6 @@ fn batch_donation_success() { FEE_RATE, MIN_CONFIRMATIONS, None, - false, ) .unwrap() .txid; @@ -2386,7 +2376,7 @@ fn batch_donation_success() { test_list_transfers(&rcv_wallet_1, Some(&asset_b.asset_id)); test_list_transfers(&rcv_wallet_2, Some(&asset_a.asset_id)); test_list_transfers(&rcv_wallet_2, Some(&asset_b.asset_id)); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet_1, rcv_online_1, None, None); wait_for_refresh(&mut rcv_wallet_2, rcv_online_2, None, None); test_list_transfers(&rcv_wallet_1, Some(&asset_a.asset_id)); @@ -3039,7 +3029,7 @@ fn pending_incoming_transfer_fail() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -3488,13 +3478,7 @@ fn insufficient_bitcoins() { }], )]); let result = test_send_begin_result(&mut wallet, online, &recipient_map); - assert!(matches!( - result, - Err(Error::InsufficientBitcoins { - needed: _, - available: _ - }) - )); + assert!(matches!(result, Err(Error::InsufficientAllocationSlots))); // create 1 UTXO for change (add funds, create UTXO, send the rest) fund_wallet(test_get_address(&mut wallet)); @@ -3656,7 +3640,7 @@ fn send_to_oneself() { // transfers progress to status Settled after refreshes wait_for_refresh(&mut wallet, online, None, Some(&[2, 3])); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet, online, None, None); let batch_transfers = get_test_batch_transfers(&wallet, &txid); @@ -3748,7 +3732,7 @@ fn send_received_back_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -3801,7 +3785,7 @@ fn send_received_back_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut wallet, online, None, None); wait_for_refresh(&mut rcv_wallet, rcv_online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet, online, None, None); wait_for_refresh(&mut rcv_wallet, rcv_online, Some(&asset.asset_id), None); @@ -3860,7 +3844,7 @@ fn send_received_back_success() { // take transfers from WaitingCounterparty to Settled wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -3998,7 +3982,7 @@ fn witness_success() { ); // transfers progress to status Settled after tx mining + refresh - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -4240,7 +4224,7 @@ fn witness_multiple_assets_success() { }); // transfers progress to status Settled after tx mining + refresh - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, None, None); @@ -4366,7 +4350,7 @@ fn witness_multiple_assets_success() { ); // transfers progress to status Settled after tx mining + refresh - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, None, None); @@ -4434,7 +4418,7 @@ fn witness_multiple_inputs_success() { // settle transfers wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, Some(&asset.asset_id), None); @@ -4458,7 +4442,7 @@ fn witness_multiple_inputs_success() { // settle transfers wait_for_refresh(&mut wallet_1, online_1, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_1, online_1, None, None); wait_for_refresh(&mut wallet_2, online_2, Some(&asset.asset_id), None); @@ -4482,7 +4466,7 @@ fn witness_multiple_inputs_success() { // settle transfers wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, Some(&asset.asset_id), None); @@ -4579,7 +4563,7 @@ fn min_confirmations_common( let asset = test_issue_asset_nia(wallet, online, None); // avoid bitcoind sync issues - stop_mining_when_alone(); + let _guard = stop_mining_when_alone(); force_mine_no_resume_when_alone(esplora); // send @@ -4609,7 +4593,6 @@ fn min_confirmations_common( FEE_RATE, min_confirmations, None, - false, ) .unwrap() .txid; @@ -4695,7 +4678,6 @@ fn min_confirmations_common( FEE_RATE, min_confirmations, None, - false, ) .unwrap() .txid; @@ -4750,9 +4732,11 @@ fn min_confirmations_common( let txid = test_send(rcv_wallet, rcv_online, &recipient_map); assert!(!txid.is_empty()); + force_mine_no_resume_when_alone(esplora); wait_for_refresh(wallet, online, None, None); wait_for_refresh(rcv_wallet, rcv_online, Some(&asset.asset_id), None); - mine(esplora, true); + drop(_guard); + mine(esplora); wait_for_refresh(wallet, online, None, None); wait_for_refresh(rcv_wallet, rcv_online, Some(&asset.asset_id), None); @@ -4838,13 +4822,12 @@ fn spend_double_receive() { FEE_RATE, MIN_CONFIRMATIONS, None, - false, ) .unwrap() .txid; assert!(!txid_1.is_empty()); // settle transfer - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, Some(&asset.asset_id), None); @@ -4879,13 +4862,12 @@ fn spend_double_receive() { FEE_RATE, MIN_CONFIRMATIONS, None, - false, ) .unwrap() .txid; assert!(!txid_2.is_empty()); // settle transfer - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, Some(&asset.asset_id), None); @@ -4983,7 +4965,7 @@ fn spend_double_receive() { // settle transfer wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, Some(&asset.asset_id), None); // check transfer status @@ -5057,7 +5039,7 @@ fn input_sorting() { // settle transfers wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -5132,7 +5114,7 @@ fn spend_witness_receive_utxo() { ); // mine and refresh the sender wallet only (receiver transfer still WaitingConfirmations) - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_1, online_1, Some(&asset_a.asset_id), None); // sync DB TXOs for the receiver wallet @@ -5214,7 +5196,7 @@ fn rgb_change_on_btc_change() { assert_eq!(transfer_data.status, TransferStatus::WaitingConfirmations); // transfers progress to status Settled after tx mining + refresh - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, None, None); @@ -5365,7 +5347,6 @@ fn min_fee_rate() { fee_rate, MIN_CONFIRMATIONS, None, - false, ) .unwrap() .txid; @@ -5426,7 +5407,6 @@ fn max_fee_exceeded_common( fee_rate, MIN_CONFIRMATIONS, None, - false, ) .unwrap(); assert!(!send_result.txid.is_empty()); @@ -5556,7 +5536,6 @@ fn min_relay_fee_common( fee_rate, MIN_CONFIRMATIONS, None, - false, ) .unwrap(); assert!(!send_result.txid.is_empty()); @@ -5695,7 +5674,6 @@ fn skip_sync() { FEE_RATE, MIN_CONFIRMATIONS, None, - true, ) .unwrap() .txid; @@ -5746,7 +5724,6 @@ fn skip_sync() { FEE_RATE, MIN_CONFIRMATIONS, None, - true, ) .unwrap() .txid; @@ -5777,7 +5754,7 @@ fn skip_sync() { // settle transfers wait_for_refresh(&mut rcv_wallet, rcv_online, None, Some(&[1, 2])); wait_for_refresh(&mut wallet, online, None, Some(&[2, 3])); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, Some(&[1, 2])); wait_for_refresh(&mut wallet, online, None, Some(&[2, 3])); assert!(check_test_transfer_status_sender( @@ -5813,7 +5790,6 @@ fn skip_sync() { FEE_RATE, MIN_CONFIRMATIONS, None, - true, ) .unwrap() .txid; @@ -5863,7 +5839,7 @@ fn skip_sync() { assert_eq!(transfer_data.status, TransferStatus::WaitingConfirmations); // mine and refresh skipping sync > cannot refresh ReceiveWitness transfer as a sync is needed - mine(false, false); + mine(false); wallet.refresh(online, None, vec![], true).unwrap(); show_unspent_colorings(&mut wallet, "after refresh 2"); @@ -5877,7 +5853,15 @@ fn skip_sync() { assert_eq!(transfer_data.status, TransferStatus::Settled); // sync and refresh again (still skipping sync) > ReceiveWitness transfer now refreshes + new UTXO appears - wallet.sync(online).unwrap(); + wallet + .sync( + online, + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); wallet.refresh(online, None, vec![], true).unwrap(); show_unspent_colorings(&mut wallet, "after refresh 3"); @@ -5940,7 +5924,7 @@ fn ifa_success() { // transfers progress to status Settled after refreshing wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, None, None); @@ -5994,7 +5978,7 @@ fn ifa_success() { show_unspent_colorings(&mut wallet, "after asset send to oneself"); wait_for_refresh(&mut wallet, online, None, None); show_unspent_colorings(&mut wallet, "after asset send to oneself + refresh 1"); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet, online, None, None); // send InflationRight only @@ -6030,7 +6014,7 @@ fn ifa_success() { assert_eq!(balance, expected_balance); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, None, None); show_unspent_colorings(&mut wallet, "after InflationRights move + refresh"); @@ -6109,7 +6093,7 @@ fn test_reject_list_scenario_1() { let txid = test_send(&mut wallet_1, online_1, &recipient_map_1); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -6160,7 +6144,7 @@ fn test_reject_list_scenario_1() { let _txid = test_send(&mut wallet_1, online_1, &recipient_map_3); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -6172,7 +6156,7 @@ fn test_reject_list_scenario_1() { let _txid = test_send(&mut wallet_2, online_2, &recipient_map_2); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_3, online_3, None, None); } @@ -6208,7 +6192,7 @@ fn test_reject_list_scenario_2() { let txid = test_send(&mut wallet_1, online_1, &recipient_map_1); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -6226,7 +6210,7 @@ fn test_reject_list_scenario_2() { let _txid = test_send(&mut wallet_2, online_2, &recipient_map_2); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); @@ -6277,7 +6261,7 @@ fn test_reject_list_scenario_2() { let _txid = test_send(&mut wallet_1, online_1, &recipient_map_4); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -6289,7 +6273,7 @@ fn test_reject_list_scenario_2() { let _txid = test_send(&mut wallet_3, online_3, &recipient_map_3); wait_for_refresh(&mut wallet_4, online_4, None, None); wait_for_refresh(&mut wallet_3, online_3, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_4, online_4, None, None); wait_for_refresh(&mut wallet_3, online_3, None, None); } @@ -6325,7 +6309,7 @@ fn test_reject_list_scenario_3() { let txid = test_send(&mut wallet_1, online_1, &recipient_map_1); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -6350,7 +6334,7 @@ fn test_reject_list_scenario_3() { let _txid = test_send(&mut wallet_2, online_2, &recipient_map_2); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_3, online_3, None, None); } @@ -6387,7 +6371,7 @@ fn test_reject_list_scenario_4() { let txid_1 = test_send(&mut wallet_1, online_1, &recipient_map_1); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -6404,7 +6388,7 @@ fn test_reject_list_scenario_4() { let txid_2 = test_send(&mut wallet_2, online_2, &recipient_map_2); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); @@ -6421,7 +6405,7 @@ fn test_reject_list_scenario_4() { let _txid = test_send(&mut wallet_3, online_3, &recipient_map_3); wait_for_refresh(&mut wallet_4, online_4, None, None); wait_for_refresh(&mut wallet_3, online_3, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_4, online_4, None, None); wait_for_refresh(&mut wallet_3, online_3, None, None); @@ -6450,7 +6434,7 @@ fn test_reject_list_scenario_4() { let _txid = test_send(&mut wallet_4, online_4, &recipient_map_3); wait_for_refresh(&mut wallet_5, online_5, None, None); wait_for_refresh(&mut wallet_4, online_4, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_4, online_4, None, None); wait_for_refresh(&mut wallet_5, online_5, None, None); } @@ -6486,7 +6470,7 @@ fn test_reject_list_scenario_5() { let txid = test_send(&mut wallet_1, online_1, &recipient_map_1); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -6503,7 +6487,7 @@ fn test_reject_list_scenario_5() { let _txid = test_send(&mut wallet_1, online_1, &recipient_map_2); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -6528,7 +6512,7 @@ fn test_reject_list_scenario_5() { let _txid = test_send(&mut wallet_3, online_3, &recipient_map_3); wait_for_refresh(&mut wallet_4, online_4, None, None); wait_for_refresh(&mut wallet_3, online_3, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_3, online_3, None, None); wait_for_refresh(&mut wallet_4, online_4, None, None); } @@ -6545,9 +6529,7 @@ fn pending_witness_ma1_blind_receive_fail() { let (mut wallet, online) = get_funded_wallet!(); // recipient wallet let mut rcv_wallet = get_test_wallet(true, Some(1)); // MAX_ALLOCATIONS_PER_UTXO = 1 - let rcv_online = rcv_wallet - .go_online(true, ELECTRUM_URL.to_string()) - .unwrap(); + let rcv_online = rcv_wallet.go_online(test_go_online_options(None)).unwrap(); // issue let asset = test_issue_asset_nia(&mut wallet, online, None); @@ -6574,13 +6556,20 @@ fn pending_witness_ma1_blind_receive_fail() { FEE_RATE, MIN_CONFIRMATIONS, None, - false, ) .unwrap(); assert!(!txid.is_empty()); // sync recipient wallet (no refresh) to see the new UTXO but not the new allocation - rcv_wallet.sync(rcv_online).unwrap(); + rcv_wallet + .sync( + rcv_online, + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); // make sure the recipient wallet sees 1 colorable UTXO with no RGB allocations let unspents = test_list_unspents(&mut rcv_wallet, None, false); @@ -6593,7 +6582,7 @@ fn pending_witness_ma1_blind_receive_fail() { // try to blind the new UTXO: it should error as it already has the max allocation number let result = test_blind_receive_result(&mut rcv_wallet); - assert!(matches!(result, Err(Error::InsufficientBitcoins { .. }))) + assert!(matches!(result, Err(Error::InsufficientAllocationSlots))); } #[cfg(feature = "electrum")] @@ -6616,7 +6605,7 @@ fn pending_witness_txo() { // // send - stop_mining(); + let _guard = stop_mining(); let receive_data = test_witness_receive(&mut rcv_wallet); let recipient_map = HashMap::from([( asset.asset_id.clone(), @@ -6649,7 +6638,15 @@ fn pending_witness_txo() { assert_eq!(rcv_pending_witness_scripts.len(), 1); // sync recipient wallet - rcv_wallet.sync(rcv_online).unwrap(); + rcv_wallet + .sync( + rcv_online, + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); // check the recipient doesn't see the TXO yet + has one pending witness let rcv_txos = rcv_wallet.database().iter_txos().unwrap(); @@ -6693,7 +6690,15 @@ fn pending_witness_txo() { test_refresh_all(&mut wallet, online); // sync recipient wallet - rcv_wallet.sync(rcv_online).unwrap(); + rcv_wallet + .sync( + rcv_online, + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); // check the recipient TXO now exists and is still pending witness let rcv_txo = rcv_wallet @@ -6712,7 +6717,8 @@ fn pending_witness_txo() { assert!(rcv_pending_witness_scripts.is_empty()); // mine + refresh the recipient to move the transfer to Settled - mine(false, true); + drop(_guard); + mine(false); test_refresh_all(&mut rcv_wallet, rcv_online); test_refresh_all(&mut wallet, online); // so that change is spendable let rcv_transfer = get_test_transfer_recipient(&rcv_wallet, &receive_data.recipient_id); @@ -6736,7 +6742,7 @@ fn pending_witness_txo() { let (mut rcv_wallet, rcv_online) = get_empty_wallet!(); // send (donation) - stop_mining(); + let _guard = stop_mining(); let receive_data = test_witness_receive(&mut rcv_wallet); let recipient_map = HashMap::from([( asset.asset_id.clone(), @@ -6758,7 +6764,6 @@ fn pending_witness_txo() { FEE_RATE, MIN_CONFIRMATIONS, None, - false, ) .unwrap(); assert!(!txid.is_empty()); @@ -6779,7 +6784,15 @@ fn pending_witness_txo() { assert_eq!(rcv_pending_witness_scripts.len(), 1); // sync recipient wallet - rcv_wallet.sync(rcv_online).unwrap(); + rcv_wallet + .sync( + rcv_online, + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); // check the recipient now sees the TXO, as existent + pending witness let rcv_txos = rcv_wallet.database().iter_txos().unwrap(); @@ -6821,7 +6834,8 @@ fn pending_witness_txo() { // refresh + mine to move the transfer to Settled test_refresh_all(&mut wallet, online); - mine(false, true); + drop(_guard); + mine(false); test_refresh_all(&mut rcv_wallet, rcv_online); let rcv_transfer = get_test_transfer_recipient(&rcv_wallet, &receive_data.recipient_id); let (rcv_transfer_data, _) = get_test_transfer_data(&rcv_wallet, &rcv_transfer); @@ -6925,7 +6939,7 @@ fn blinded_change_failed_xfer() { // settle wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -6961,7 +6975,7 @@ fn blinded_change_failed_xfer() { // settle wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -6986,7 +7000,7 @@ fn blinded_change_failed_xfer() { // settle wait_for_refresh(&mut wallet_1, online_1, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_1, online_1, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); @@ -7091,7 +7105,7 @@ fn blinded_change_send_begin_only() { // settle wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -7127,7 +7141,7 @@ fn blinded_change_send_begin_only() { // settle wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -7152,7 +7166,7 @@ fn blinded_change_send_begin_only() { // settle wait_for_refresh(&mut wallet_1, online_1, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_1, online_1, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); @@ -7223,7 +7237,6 @@ fn donation_recipient_nack() { FEE_RATE, MIN_CONFIRMATIONS, None, - false, ) .unwrap() .txid; @@ -7239,7 +7252,7 @@ fn donation_recipient_nack() { .post_ack(&receive_data.recipient_id, false) .unwrap(); // settle on sender side - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_1, online_1, None, None); assert!(check_test_transfer_status_sender( &wallet_1, @@ -7273,7 +7286,7 @@ fn donation_recipient_nack() { // settle wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_2, online_2, None, None); wait_for_refresh(&mut wallet_1, online_1, None, None); @@ -7298,7 +7311,7 @@ fn donation_recipient_nack() { // settle wait_for_refresh(&mut wallet_1, online_1, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet_1, online_1, None, None); wait_for_refresh(&mut wallet_2, online_2, None, None); @@ -7349,7 +7362,7 @@ fn send_end_without_send_begin() { .unwrap() .compute_txid() .to_string(); - let result = wallet_2.send_end(online_2, signed_psbt, false); + let result = wallet_2.send_end(online_2, signed_psbt); assert_matches!(result, Err(Error::UnknownTransfer { txid }) if txid == psbt_txid); } @@ -7606,7 +7619,7 @@ fn allocations() { // settle transfers test_refresh_all(&mut wallet_2, online_2); test_refresh_all(&mut wallet_1, online_1); - mine(false, false); + mine(false); test_refresh_all(&mut wallet_2, online_2); test_refresh_all(&mut wallet_1, online_1); show_unspent_colorings(&mut wallet_1, "wallet 1 after setup send"); @@ -7621,7 +7634,7 @@ fn allocations() { check_allocations(&wallet_2, &unspents_colorable, &amounts_all, &[], false); // send the 2 smallest allocations from wallet 2 - stop_mining(); + let _guard = stop_mining(); let receive_data = test_blind_receive(&mut wallet_1); let recipient_map = HashMap::from([( asset_1.asset_id.clone(), @@ -7676,7 +7689,8 @@ fn allocations() { check_unspents(&unspents_colorable, &amounts_user, &amounts_auto, true); // settle transfer - mine(false, true); + drop(_guard); + mine(false); test_refresh_all(&mut wallet_1, online_1); test_refresh_all(&mut wallet_2, online_2); // check allocation colorings (no input colorings, same change colorings) @@ -7870,7 +7884,7 @@ fn p2wpkh_send_receive_nia() { // drive transfers from WaitingCounterparty to Settled wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -7913,7 +7927,7 @@ fn cross_type_p2tr_to_p2wpkh() { // drive transfers from WaitingCounterparty to Settled wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); - mine(false, false); + mine(false); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); wait_for_refresh(&mut wallet, online, Some(&asset.asset_id), None); @@ -7938,7 +7952,7 @@ fn cross_type_p2tr_to_p2wpkh() { wait_for_refresh(&mut wallet, online, None, None); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); - mine(false, false); + mine(false); wait_for_refresh(&mut wallet, online, None, None); wait_for_refresh(&mut rcv_wallet, rcv_online, None, None); @@ -7947,3 +7961,137 @@ fn cross_type_p2tr_to_p2wpkh() { let balance_receiver = test_get_asset_balance(&rcv_wallet, &asset.asset_id); assert_eq!(balance_receiver.settled, amount - amount_back); } + +#[cfg(feature = "electrum")] +#[test] +#[parallel] +fn unsafe_history_waits_for_safe_height() { + initialize(); + + let amount_1: u64 = 66; + let amount_2: u64 = 33; + + // wallets + let (mut wallet_1, online_1) = get_funded_wallet!(); + let (mut wallet_2, online_2) = get_funded_wallet!(); + + // issue + let asset = test_issue_asset_nia(&mut wallet_1, online_1, None); + + // 1st transfer: wallet 1 > wallet 2 + let receive_data_1 = test_blind_receive(&mut wallet_2); + let recipient_map_1 = HashMap::from([( + asset.asset_id.clone(), + vec![Recipient { + assignment: Assignment::Fungible(amount_1), + recipient_id: receive_data_1.recipient_id.clone(), + witness_data: None, + transport_endpoints: TRANSPORT_ENDPOINTS.clone(), + }], + )]); + let txid_1 = test_send(&mut wallet_1, online_1, &recipient_map_1); + assert!(!txid_1.is_empty()); + let _guard = stop_mining_when_alone(); + wait_for_refresh(&mut wallet_2, online_2, None, None); + wait_for_refresh(&mut wallet_1, online_1, Some(&asset.asset_id), None); + force_mine_no_resume_when_alone(false); + wait_for_refresh(&mut wallet_2, online_2, None, None); + wait_for_refresh(&mut wallet_1, online_1, Some(&asset.asset_id), None); + assert!(check_test_transfer_status_recipient( + &wallet_2, + &receive_data_1.recipient_id, + TransferStatus::Settled + )); + assert!(check_test_transfer_status_sender( + &wallet_1, + &txid_1, + TransferStatus::Settled + )); + + // 2nd transfer: wallet 1 > wallet 2 with min_confirmations = 2 + // txid_1 has only one confirmation, so transfer parks in WaitingSafeHeight + let receive_data_2 = wallet_2 + .blind_receive( + None, + Assignment::Any, + Some((now().unix_timestamp() + DURATION_RCV_TRANSFER as i64) as u64), + TRANSPORT_ENDPOINTS.clone(), + 2, + ) + .unwrap(); + let recipient_map_2 = HashMap::from([( + asset.asset_id.clone(), + vec![Recipient { + assignment: Assignment::Fungible(amount_2), + recipient_id: receive_data_2.recipient_id.clone(), + witness_data: None, + transport_endpoints: TRANSPORT_ENDPOINTS.clone(), + }], + )]); + let txid_2 = test_send(&mut wallet_1, online_1, &recipient_map_2); + assert!(!txid_2.is_empty()); + + // transfer parks in WaitingSafeHeight because it contains unsafe history + wait_for_refresh( + &mut wallet_2, + online_2, + None, + Some(&[receive_data_2.batch_transfer_idx]), + ); + assert!(check_test_transfer_status_recipient( + &wallet_2, + &receive_data_2.recipient_id, + TransferStatus::WaitingSafeHeight + )); + + // mine another block so txid_1 reaches 2 confirmations, then refresh to ACK + force_mine_no_resume_when_alone(false); + wait_for_refresh( + &mut wallet_2, + online_2, + None, + Some(&[receive_data_2.batch_transfer_idx]), + ); + assert!(check_test_transfer_status_recipient( + &wallet_2, + &receive_data_2.recipient_id, + TransferStatus::WaitingConfirmations + )); + + // sender sees the ACK and broadcasts txid_2 + wait_for_refresh(&mut wallet_1, online_1, Some(&asset.asset_id), None); + assert!(check_test_transfer_status_sender( + &wallet_1, + &txid_2, + TransferStatus::WaitingConfirmations + )); + + // mine, sender (min_confirmations = 1) settles, recipient (min_confirmations = 2) still in WaitingConfirmations + force_mine_no_resume_when_alone(false); + wait_for_refresh(&mut wallet_1, online_1, Some(&asset.asset_id), None); + assert!(check_test_transfer_status_sender( + &wallet_1, + &txid_2, + TransferStatus::Settled + )); + assert!(!test_refresh_all(&mut wallet_2, online_2)); + assert!(check_test_transfer_status_recipient( + &wallet_2, + &receive_data_2.recipient_id, + TransferStatus::WaitingConfirmations + )); + + // mine again so txid_2 reaches 2 confirmations, recipient settles + force_mine_no_resume_when_alone(false); + wait_for_refresh( + &mut wallet_2, + online_2, + None, + Some(&[receive_data_2.batch_transfer_idx]), + ); + assert!(check_test_transfer_status_recipient( + &wallet_2, + &receive_data_2.recipient_id, + TransferStatus::Settled + )); +} diff --git a/src/wallet/test/send_btc.rs b/src/wallet/test/send_btc.rs index c5c0b329..da71c687 100644 --- a/src/wallet/test/send_btc.rs +++ b/src/wallet/test/send_btc.rs @@ -15,7 +15,7 @@ fn success() { // initial balance fund_wallet(test_get_address(&mut wallet)); test_create_utxos_default(&mut wallet, online); - mine(false, false); + mine(false); let expected_balance = BtcBalance { vanilla: Balance { settled: 99994347, @@ -44,7 +44,7 @@ fn success() { bak_info_before.last_operation_timestamp ); assert!(!txid.is_empty()); - mine(false, false); + mine(false); let expected_balance = BtcBalance { vanilla: Balance { settled: 99993038, @@ -159,7 +159,7 @@ fn skip_sync() { assert_eq!(unspents.len(), 1); // send a 1st time skipping sync (spending the only UTXO) - let txid = wallet + let txid_1 = wallet .send_btc( online, test_get_address(&mut rcv_wallet), @@ -168,20 +168,10 @@ fn skip_sync() { true, ) .unwrap(); - assert!(!txid.is_empty()); - // send a 2nd time skipping sync > FailedBroadcast - let result = wallet.send_btc( - online, - test_get_address(&mut rcv_wallet), - amount, - FEE_RATE, - true, - ); - assert_matches!(result, Err(Error::FailedBroadcast { details: _ })); - - // sync and retry the 2nd send skipping sync > change UTXO is now available - wallet.sync(online).unwrap(); - let txid = wallet + assert!(!txid_1.is_empty()); + // send a 2nd time skipping sync > succeeds because the change UTXO from send 1 + // is staged into BDK by broadcast_psbt's apply_unconfirmed_txs + let txid_2 = wallet .send_btc( online, test_get_address(&mut rcv_wallet), @@ -190,7 +180,8 @@ fn skip_sync() { true, ) .unwrap(); - assert!(!txid.is_empty()); + assert!(!txid_2.is_empty()); + assert_ne!(txid_1, txid_2); } #[cfg(feature = "electrum")] @@ -268,7 +259,7 @@ fn begin_reservation_interactions() { // sign + end releases the reservations but keeps the wallet_transaction row let signed_psbt = wallet.sign_psbt(unsigned_psbt_str, None).unwrap(); - let _end_txid = wallet.send_btc_end(online, signed_psbt, false).unwrap(); + let _end_txid = wallet.send_btc_end(online, signed_psbt).unwrap(); assert!(wallet.database().iter_reserved_txos().unwrap().is_empty()); assert!(wallet.list_pending_vanilla_txs().unwrap().is_empty()); @@ -287,7 +278,7 @@ fn begin_reservation_interactions() { assert_eq!(wts.len(), 1); // list_transactions sees it as SendBtc - mine(false, false); + mine(false); let transactions = test_list_transactions(&mut wallet, Some(online)); let entry = transactions .iter() @@ -322,7 +313,7 @@ fn begin_reservation_interactions() { // end still creates the SendBtc row after broadcast (for list_transactions) let signed_psbt = wallet.sign_psbt(unsigned_psbt_str, None).unwrap(); - let end_txid = wallet.send_btc_end(online, signed_psbt, false).unwrap(); + let end_txid = wallet.send_btc_end(online, signed_psbt).unwrap(); assert_eq!(end_txid, psbt_txid); assert!(wallet.database().iter_reserved_txos().unwrap().is_empty()); let wts: Vec<_> = wallet @@ -348,7 +339,17 @@ fn two_concurrent_begins_pick_disjoint_inputs() { for _ in 0..3 { fund_wallet(test_get_address(&mut wallet)); } - wallet.sync(online).unwrap(); + wallet + .sync( + online, + SyncOptions { + keychain: SyncKeychain::Vanilla { + lookback: INDEXER_SYNC_LOOKBACK as u32, + }, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); let (mut rcv_wallet, _rcv_online) = get_empty_wallet!(); @@ -433,8 +434,6 @@ fn send_btc_end_twice() { let signed_psbt = wallet.sign_psbt(unsigned_psbt, None).unwrap(); // call send_btc_end twice with the same PSBT, which should work (idempotent) - wallet - .send_btc_end(online, signed_psbt.clone(), false) - .unwrap(); - wallet.send_btc_end(online, signed_psbt, false).unwrap(); + wallet.send_btc_end(online, signed_psbt.clone()).unwrap(); + wallet.send_btc_end(online, signed_psbt).unwrap(); } diff --git a/src/wallet/test/utils/api.rs b/src/wallet/test/utils/api.rs index 81ffb585..e0d914c1 100644 --- a/src/wallet/test/utils/api.rs +++ b/src/wallet/test/utils/api.rs @@ -26,6 +26,70 @@ pub(crate) fn test_witness_receive(wallet: &mut Wallet) -> ReceiveData { .unwrap() } +#[cfg(any(feature = "electrum", feature = "esplora"))] +pub(crate) fn test_burn( + wallet: &mut Wallet, + online: Online, + asset_id: &str, + amount: u64, +) -> OperationResult { + test_burn_result(wallet, online, asset_id, amount).unwrap() +} + +#[cfg(any(feature = "electrum", feature = "esplora"))] +pub(crate) fn test_burn_result( + wallet: &mut Wallet, + online: Online, + asset_id: &str, + amount: u64, +) -> Result { + wallet.burn( + online, + asset_id.to_string(), + amount, + FEE_RATE, + MIN_CONFIRMATIONS, + ) +} + +#[cfg(any(feature = "electrum", feature = "esplora"))] +pub(crate) fn test_burn_begin( + wallet: &mut Wallet, + online: Online, + asset_id: &str, + amount: u64, +) -> String { + test_burn_begin_result(wallet, online, asset_id, amount) + .unwrap() + .psbt +} + +#[cfg(any(feature = "electrum", feature = "esplora"))] +pub(crate) fn test_burn_begin_result( + wallet: &mut Wallet, + online: Online, + asset_id: &str, + amount: u64, +) -> Result { + wallet.burn_begin( + online, + asset_id.to_string(), + amount, + FEE_RATE, + MIN_CONFIRMATIONS, + true, + ) +} + +#[cfg(any(feature = "electrum", feature = "esplora"))] +pub(crate) fn test_burn_end_result( + wallet: &mut Wallet, + online: Online, + signed_psbt: &str, +) -> Result { + wallet.burn_end(online, signed_psbt.to_string()) +} + #[cfg(any(feature = "electrum", feature = "esplora"))] pub(crate) fn test_create_utxos_default(wallet: &mut Wallet, online: Online) { test_create_utxos(wallet, online, false, None, None, FEE_RATE, None); @@ -184,6 +248,15 @@ pub(crate) fn test_get_wallet_dir(wallet: &impl RgbWalletOpsOffline) -> PathBuf wallet.get_wallet_dir() } +#[cfg(any(feature = "electrum", feature = "esplora"))] +pub(crate) fn test_go_online_options(indexer_url: Option<&str>) -> OnlineOptions { + OnlineOptions { + indexer_url: indexer_url.unwrap_or(ELECTRUM_URL).to_string(), + skip_consistency_check: true, + vanilla_sync_lookback: INDEXER_SYNC_LOOKBACK as u32, + } +} + #[cfg(any(feature = "electrum", feature = "esplora"))] pub(crate) fn test_go_online( wallet: &mut Wallet, @@ -199,8 +272,9 @@ pub(crate) fn test_go_online_result( skip_consistency_check: bool, indexer_url: Option<&str>, ) -> Result { - let electrum = indexer_url.unwrap_or(ELECTRUM_URL).to_string(); - wallet.go_online(skip_consistency_check, electrum) + let mut online_options = test_go_online_options(indexer_url); + online_options.skip_consistency_check = skip_consistency_check; + wallet.go_online(online_options) } #[cfg(any(feature = "electrum", feature = "esplora"))] @@ -547,7 +621,15 @@ pub(crate) fn test_send( if let Err(e) = result { println!("send error: {e}"); std::thread::sleep(Duration::from_millis(500)); - wallet.sync(online).unwrap(); + wallet + .sync( + online, + SyncOptions { + keychain: SyncKeychain::Colored, + strategy: SyncStrategy::FastSync, + }, + ) + .unwrap(); continue; } break result.unwrap().txid; @@ -567,7 +649,6 @@ pub(crate) fn test_send_result( FEE_RATE, MIN_CONFIRMATIONS, Some((now().unix_timestamp() + DURATION_SEND_TRANSFER as i64) as u64), - false, ) } diff --git a/src/wallet/test/utils/chain.rs b/src/wallet/test/utils/chain.rs index df8c0c1e..46065eca 100644 --- a/src/wallet/test/utils/chain.rs +++ b/src/wallet/test/utils/chain.rs @@ -7,6 +7,14 @@ pub(crate) struct Miner { no_mine_count: u32, } +pub(crate) struct MinerStopGuard; + +impl Drop for MinerStopGuard { + fn drop(&mut self) { + MINER.write().unwrap().resume_mining(); + } +} + pub(crate) fn bitcoin_cli() -> Vec { let compose_file = ["tests", "compose.yaml"].join(MAIN_SEPARATOR_STR); vec![ @@ -94,11 +102,8 @@ impl Miner { } #[cfg(any(feature = "electrum", feature = "esplora"))] -pub(crate) fn mine_blocks(esplora: bool, blocks: u32, resume: bool) { +pub(crate) fn mine_blocks(esplora: bool, blocks: u32) { let t_0 = OffsetDateTime::now_utc(); - if resume { - resume_mining(); - } loop { if (OffsetDateTime::now_utc() - t_0).as_seconds_f32() > 120.0 { panic!("unable to mine"); @@ -112,8 +117,8 @@ pub(crate) fn mine_blocks(esplora: bool, blocks: u32, resume: bool) { } #[cfg(any(feature = "electrum", feature = "esplora"))] -pub(crate) fn mine(esplora: bool, resume: bool) { - mine_blocks(esplora, 1, resume) +pub(crate) fn mine(esplora: bool) { + mine_blocks(esplora, 1) } #[cfg(any(feature = "electrum", feature = "esplora"))] @@ -127,7 +132,7 @@ pub fn get_tx_height(esplora: bool, txid: &str) -> Option { } #[cfg(any(feature = "electrum", feature = "esplora"))] -pub fn mine_tx(esplora: bool, resume: bool, txid: &str) { +pub fn mine_tx(esplora: bool, txid: &str) { eprintln!("trying to have TX {txid} mined"); for _ in 0..10 { if let Some(conf_num) = get_tx_height(esplora, txid) @@ -136,7 +141,7 @@ pub fn mine_tx(esplora: bool, resume: bool, txid: &str) { println!("TX with ID {txid} has been mined"); return; } - mine(esplora, resume); + mine(esplora); } panic!("TX is not getting mined"); } @@ -158,11 +163,12 @@ pub(crate) fn force_mine_no_resume_when_alone(esplora: bool) { } } -pub(crate) fn stop_mining() { - MINER.write().unwrap().stop_mining() +pub(crate) fn stop_mining() -> MinerStopGuard { + MINER.write().unwrap().stop_mining(); + MinerStopGuard } -pub(crate) fn stop_mining_when_alone() { +pub(crate) fn stop_mining_when_alone() -> MinerStopGuard { let t_0 = OffsetDateTime::now_utc(); loop { if (OffsetDateTime::now_utc() - t_0).as_seconds_f32() > 120.0 { @@ -176,10 +182,7 @@ pub(crate) fn stop_mining_when_alone() { drop(miner); std::thread::sleep(std::time::Duration::from_millis(500)); } -} - -pub(crate) fn resume_mining() { - MINER.write().unwrap().resume_mining() + MinerStopGuard } pub(crate) fn estimate_smart_fee(esplora: bool) -> bool { diff --git a/src/wallet/test/utils/helpers.rs b/src/wallet/test/utils/helpers.rs index 275d4271..cfec1520 100644 --- a/src/wallet/test/utils/helpers.rs +++ b/src/wallet/test/utils/helpers.rs @@ -129,7 +129,7 @@ pub(crate) fn get_funded_wallet_p2wpkh() -> (Wallet, Online) { SinglesigKeys::from_keys(&keys, None), ) .unwrap(); - let online = wallet.go_online(true, ELECTRUM_URL.to_string()).unwrap(); + let online = wallet.go_online(test_go_online_options(None)).unwrap(); fund_wallet(wallet.get_address().unwrap()); test_create_utxos_default(&mut wallet, online); (wallet, online) @@ -142,7 +142,7 @@ pub(crate) fn get_empty_wallet( ) -> (Wallet, Online) { let mut wallet = get_test_wallet(private_keys, None); let online = wallet - .go_online(true, indexer_url.unwrap_or(ELECTRUM_URL.to_string())) + .go_online(test_go_online_options(indexer_url.as_deref())) .unwrap(); (wallet, online) } @@ -215,7 +215,7 @@ pub(crate) fn send_sats_to_address(address: String, sats: Option) { #[cfg(any(feature = "electrum", feature = "esplora"))] pub(crate) fn fund_wallet(address: String) { send_to_address(address); - mine(false, false); + mine(false); } pub(crate) fn check_test_transfer_status_recipient( diff --git a/tests/compose.yaml b/tests/compose.yaml index 200e747e..e1db75d8 100644 --- a/tests/compose.yaml +++ b/tests/compose.yaml @@ -87,7 +87,7 @@ services: depends_on: - bitcoind_signet_custom rgb-multisig-hub: - image: ghcr.io/rgb-tools/rgb-multisig-hub:0.1.0 + image: ghcr.io/rgb-tools/rgb-multisig-hub:0.1.1 ports: - 8141:3001 volumes: