diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 454f9f052..47f6043eb 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -16,6 +16,7 @@ jobs: - cross-chain-hub - router-pay - udt-router-pay + - watchtower release: - "0.116.1" test_env: diff --git a/Cargo.lock b/Cargo.lock index 6b27d8e4a..ff73a3151 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,9 +64,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -79,43 +79,43 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arcode" @@ -127,6 +127,12 @@ dependencies = [ "fenwick", ] +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "async-stream" version = "0.3.6" @@ -146,7 +152,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -157,7 +163,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -344,7 +350,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.79", + "syn 2.0.90", "which", ] @@ -368,12 +374,18 @@ checksum = "1945a5048598e4189e239d3f809b19bdad4845c4b2ba400d304d2dcf26d2c462" dependencies = [ "bech32 0.9.1", "bitcoin-private", - "bitcoin_hashes", + "bitcoin_hashes 0.12.0", "hex_lit", "secp256k1 0.27.0", "serde", ] +[[package]] +name = "bitcoin-io" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" + [[package]] name = "bitcoin-private" version = "0.1.0" @@ -390,6 +402,16 @@ dependencies = [ "serde", ] +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io", + "hex-conservative 0.2.1", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -462,9 +484,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" dependencies = [ "serde", ] @@ -498,9 +520,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.30" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "jobserver", "libc", @@ -897,9 +919,9 @@ dependencies = [ [[package]] name = "ckb-sdk" -version = "3.4.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03ffec62a524764661f5e64349fceccee1a677197fcef625a5fb93efd1a31100" +checksum = "75d816b57b37c49a99c715f07e120928d8139993523efec0b9e2faa94db7edce" dependencies = [ "anyhow", "bech32 0.8.1", @@ -1109,9 +1131,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -1141,9 +1163,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -1160,20 +1182,20 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "console" @@ -1232,9 +1254,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -1309,7 +1331,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1333,7 +1355,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1344,7 +1366,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1391,7 +1413,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1414,6 +1436,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "dlv-list" version = "0.5.2" @@ -1449,9 +1482,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if 1.0.0", ] @@ -1476,12 +1509,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1492,9 +1525,9 @@ checksum = "51e2ce894d53b295cf97b05685aa077950ff3e8541af83217fc720a6437169f8" [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "fenwick" @@ -1529,9 +1562,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", @@ -1677,7 +1710,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1767,7 +1800,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -1849,9 +1882,9 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heapsize" @@ -1874,12 +1907,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hex" version = "0.4.3" @@ -1892,6 +1919,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec", +] + [[package]] name = "hex_lit" version = "0.1.1" @@ -2046,6 +2082,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -2054,12 +2208,23 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", ] [[package]] @@ -2101,7 +2266,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.2", "serde", ] @@ -2158,9 +2323,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -2173,9 +2338,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "fb15147158e79fd8b8afd0252522769c4f48725460b37338544d8379d94fc8f9" dependencies = [ "wasm-bindgen", ] @@ -2241,7 +2406,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -2304,15 +2469,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.159" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if 1.0.0", "windows-targets 0.52.6", @@ -2325,7 +2490,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b0c1f811ae288f86c6767055c55b5f7a721ca1e61bf1897a9ae2ec663e8aba1" dependencies = [ "bitcoin", - "hex-conservative", + "hex-conservative 0.1.2", ] [[package]] @@ -2362,6 +2527,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + [[package]] name = "lnd-grpc-tonic-client" version = "0.3.0" @@ -2470,7 +2641,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -2496,11 +2667,10 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi", "libc", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", @@ -2673,9 +2843,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.67" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b8cefcf97f41316955f9294cd61f639bdcfa9f2f230faac6cb896aa8ab64704" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags 2.6.0", "cfg-if 1.0.0", @@ -2694,7 +2864,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -2822,29 +2992,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -2892,12 +3062,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -2935,9 +3105,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.87" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -2979,7 +3149,7 @@ dependencies = [ "prost 0.12.6", "prost-types", "regex", - "syn 2.0.79", + "syn 2.0.90", "tempfile", ] @@ -3006,7 +3176,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -3134,9 +3304,9 @@ dependencies = [ [[package]] name = "reflink-copy" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc31414597d1cd7fdd2422798b7652a6329dda0fe0219e6335a13d5bcaa9aeb6" +checksum = "17400ed684c3a0615932f00c271ae3eea13e47056a1455821995122348ab6438" dependencies = [ "cfg-if 1.0.0", "rustix", @@ -3145,13 +3315,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -3166,9 +3336,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -3281,9 +3451,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags 2.6.0", "errno", @@ -3324,9 +3494,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] @@ -3377,7 +3547,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" dependencies = [ - "bitcoin_hashes", + "bitcoin_hashes 0.12.0", "rand 0.8.5", "secp256k1-sys 0.8.1", "serde", @@ -3403,6 +3573,17 @@ dependencies = [ "secp256k1-sys 0.10.1", ] +[[package]] +name = "secp256k1" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" +dependencies = [ + "bitcoin_hashes 0.14.0", + "rand 0.8.5", + "secp256k1-sys 0.10.1", +] + [[package]] name = "secp256k1-sys" version = "0.8.1" @@ -3445,9 +3626,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", @@ -3461,22 +3642,22 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -3492,9 +3673,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -3541,7 +3722,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -3670,9 +3851,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3728,6 +3909,12 @@ dependencies = [ "xxhash-rust", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "strsim" version = "0.11.1" @@ -3753,7 +3940,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -3775,9 +3962,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -3790,6 +3977,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -3813,9 +4011,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if 1.0.0", "fastrand", @@ -3826,9 +4024,9 @@ dependencies = [ [[package]] name = "tentacle" -version = "0.6.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d335523ec132a2bbefbaf403b52eba047fb50bc83bed2d0b1d22c119bae2fec1" +checksum = "6218c3269605008b5e88f4e91fa2e98e20491213c464dc6da8370858db89d92b" dependencies = [ "async-trait", "bytes", @@ -3838,7 +4036,6 @@ dependencies = [ "log", "molecule", "nohash-hasher", - "once_cell", "rand 0.8.5", "socket2", "tentacle-multiaddr", @@ -3867,9 +4064,9 @@ dependencies = [ [[package]] name = "tentacle-secio" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac8b23a7879426a4961acea6ae66287f7fe9a934d131a722cbb88f145e97fea" +checksum = "99df015b8649588f2958d4853eee221860f95d2721995857e9dde1462ceb3dc4" dependencies = [ "bs58", "bytes", @@ -3884,7 +4081,7 @@ dependencies = [ "rand 0.8.5", "rand_core 0.6.4", "ring", - "secp256k1 0.29.1", + "secp256k1 0.30.0", "sha2", "tokio", "tokio-util", @@ -3894,22 +4091,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -3962,6 +4159,16 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.8.0" @@ -3979,9 +4186,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -4013,7 +4220,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -4067,9 +4274,9 @@ dependencies = [ [[package]] name = "tokio-yamux" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ed88a04bfbf9e70343a5748a423200ee0591c55e7e487d784a55ee8af17db9" +checksum = "208cecd45a38868bfc0a45aac52cb1aea4583c6b801bf57f351e9d531b23cb86" dependencies = [ "bytes", "futures", @@ -4077,6 +4284,7 @@ dependencies = [ "nohash-hasher", "tokio", "tokio-util", + "web-time", ] [[package]] @@ -4174,7 +4382,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -4244,9 +4452,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -4256,20 +4464,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -4298,9 +4506,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", @@ -4326,26 +4534,11 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "unicode-bidi" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" - [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" - -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-width" @@ -4383,15 +4576,27 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -4449,9 +4654,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "21d3b25c3ea1126a2ad5f4f9068483c2af1e64168f847abe863a526b8dbfe00b" dependencies = [ "cfg-if 1.0.0", "once_cell", @@ -4460,36 +4665,37 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "52857d4c32e496dc6537646b5b117081e71fd2ff06de792e3577a150627db283" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.45" +version = "0.4.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +checksum = "951fe82312ed48443ac78b66fa43eded9999f738f6022e67aead7b708659e49a" dependencies = [ "cfg-if 1.0.0", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "920b0ffe069571ebbfc9ddc0b36ba305ef65577c94b06262ed793716a1afd981" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4497,28 +4703,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "bf59002391099644be3524e23b781fa43d2be0c5aa0719a18c0731b9d195cab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "e5047c5392700766601942795a436d7d2599af60dcc3cc1248c9120bfb0827b0" [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "476364ff87d0ae6bfb661053a9104ab312542658c3d8f963b7ace80b6f9b26b9" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -4607,7 +4823,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -4618,7 +4834,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", ] [[package]] @@ -4807,6 +5023,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "x25519-dalek" version = "2.0.1" @@ -4825,6 +5053,30 @@ version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -4843,7 +5095,28 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", ] [[package]] @@ -4863,5 +5136,27 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.90", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", ] diff --git a/rust-toolchain.toml b/rust-toolchain.toml index d8e821e88..e2df5b625 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.76.0" +channel = "1.81.0" components = [ "rustfmt", "clippy" ] profile = "minimal" diff --git a/src/ckb/funding/funding_tx.rs b/src/ckb/funding/funding_tx.rs index b9f92cf80..1671ba6f2 100644 --- a/src/ckb/funding/funding_tx.rs +++ b/src/ckb/funding/funding_tx.rs @@ -192,7 +192,6 @@ impl FundingTxBuilder { .capacity(Capacity::shannons(ckb_amount).pack()) .lock(self.context.funding_cell_lock_script.clone()) .build(); - debug!("build_funding_cell debug ckb_output: {:?}", ckb_output); Ok((ckb_output, packed::Bytes::default())) } } @@ -297,10 +296,6 @@ impl FundingTxBuilder { .lock(Some(molecule::bytes::Bytes::from(vec![0u8; 170])).pack()) .build(); - debug!( - "request.funding_fee_rate: {}", - self.request.funding_fee_rate - ); let balancer = CapacityBalancer::new_simple( sender.clone(), placeholder_witness, diff --git a/src/fiber/channel.rs b/src/fiber/channel.rs index f0aa15a67..e8804386f 100644 --- a/src/fiber/channel.rs +++ b/src/fiber/channel.rs @@ -9,7 +9,7 @@ use crate::{ fiber::{ fee::calculate_tlc_forward_fee, network::{get_chain_hash, SendOnionPacketCommand}, - serde_utils::PubNonceAsBytes, + serde_utils::{CompactSignatureAsBytes, PubNonceAsBytes}, types::{ChannelUpdate, PeeledPaymentOnionPacket, TlcErr, TlcErrPacket, TlcErrorCode}, }, invoice::{CkbInvoice, CkbInvoiceStatus, InvoiceStore}, @@ -47,7 +47,7 @@ use tokio::sync::oneshot; use std::{ borrow::Borrow, - collections::BTreeMap, + collections::{BTreeMap, HashMap}, fmt::Debug, sync::Arc, time::{SystemTime, UNIX_EPOCH}, @@ -87,6 +87,13 @@ use super::{ // - `pubkey`: 32 bytes, x only aggregated public key // - `signature`: 64 bytes, aggregated signature pub const FUNDING_CELL_WITNESS_LEN: usize = 16 + 32 + 64; + +// - `empty_witness_args`: 16 bytes, fixed to 0x10000000100000001000000010000000, for compatibility with the xudt +// - `unlock_type`: 1 byte +// - `pubkey`: 32 bytes, x only aggregated public key +// - `signature`: 64 bytes, aggregated signature +pub const COMMITMENT_CELL_WITNESS_LEN: usize = 16 + 1 + 32 + 64; + // Some part of the code liberally gets previous commitment number, which is // the current commitment number minus 1. We deliberately set initial commitment number to 1, // so that we can get previous commitment point/number without checking if the channel @@ -691,7 +698,6 @@ where .apply_remove_tlc_operation(myself, state, remove_tlc) .await .map_err(|e| { - debug!("error happened in apply_remove_tlc_operation: {:?}", e); error!("Error handling apply_remove_tlc_operation: {:?}", e); }); } @@ -713,11 +719,6 @@ where assert!(previous_tlc.is_received()); assert!(previous_channel_id != state.get_id()); - debug!( - "begin to remove tlc from previous channel: {:?}", - &previous_tlc - ); - let remove_reason = remove_reason.clone().backward(&tlc_info.shared_secret); // TODO: encrypt the error to backward @@ -777,10 +778,6 @@ where } } - debug!( - "register remove reason: {:?} with reason: {:?}", - tlc.tlc_id, remove_reason - ); self.register_retryable_tlc_remove(myself, state, tlc.tlc_id, remove_reason) .await; } @@ -856,10 +853,6 @@ where let payment_hash = add_tlc.payment_hash; let received_amount = add_tlc.amount; let forward_amount = peeled_onion_packet.current.amount; - debug!( - "received_amount: {} forward_amount: {}", - add_tlc.amount, forward_amount - ); if peeled_onion_packet.is_last() { if forward_amount != add_tlc.amount { @@ -1075,10 +1068,6 @@ where ))); } ChannelState::CollaboratingFundingTx(_) => { - debug!( - "Processing commitment_signed command in from CollaboratingFundingTx state {:?}", - &state.state - ); CommitmentSignedFlags::SigningCommitment(SigningCommitmentFlags::empty()) } ChannelState::SigningCommitment(flags) @@ -1090,19 +1079,11 @@ where ))); } ChannelState::SigningCommitment(flags) => { - debug!( - "Processing commitment_signed command in from SigningCommitment state {:?}", - &state.state - ); CommitmentSignedFlags::SigningCommitment(flags) } ChannelState::ChannelReady() => CommitmentSignedFlags::ChannelReady(), ChannelState::ShuttingDown(flags) => { if flags.contains(ShuttingDownFlags::AWAITING_PENDING_TLCS) { - debug!( - "Signing commitment transactions while shutdown is pending, current state {:?}", - &state.state - ); CommitmentSignedFlags::PendingShutdown(flags) } else { return Err(ProcessingChannelError::InvalidState(format!( @@ -1118,33 +1099,14 @@ where ))); } }; - - debug!( - "Building and signing commitment tx for state {:?}", - &state.state - ); - let PartiallySignedCommitmentTransaction { - version, - commitment_tx, - funding_tx_partial_signature, - commitment_tx_partial_signature, - } = state.build_and_sign_commitment_tx()?; - - debug!( - "Sending next local nonce {:?} (previous nonce {:?})", - state.get_next_local_nonce(), - state.get_local_nonce().borrow() - ); + let (funding_tx_partial_signature, commitment_tx_partial_signature) = + state.build_and_sign_commitment_tx()?; let commitment_signed = CommitmentSigned { channel_id: state.get_id(), funding_tx_partial_signature, commitment_tx_partial_signature, next_local_nonce: state.get_next_local_nonce(), }; - debug!( - "Sending built commitment_signed message: {:?}", - &commitment_signed - ); self.network .send_message(NetworkActorMessage::new_command( NetworkActorCommand::SendFiberMessage(FiberMessageWithPeerId::new( @@ -1153,17 +1115,6 @@ where )), )) .expect(ASSUME_NETWORK_ACTOR_ALIVE); - self.network - .send_message(NetworkActorMessage::new_notification( - NetworkServiceEvent::LocalCommitmentSigned( - state.get_remote_peer_id(), - state.get_id(), - version, - commitment_tx, - ), - )) - .expect("myself alive"); - state.save_remote_nonce_for_raa(); match flags { @@ -1192,7 +1143,6 @@ where state.tlc_state.add_local_tlc(tlc.clone()); state.increment_next_offered_tlc_id(); - debug!("Inserted tlc into channel state: {:?}", &tlc); let add_tlc = AddTlc { channel_id: state.get_id(), tlc_id: tlc.tlc_id().into(), @@ -1206,7 +1156,6 @@ where // Send tlc update message to peer. let msg = FiberMessageWithPeerId::new(state.get_remote_peer_id(), FiberMessage::add_tlc(add_tlc)); - debug!("Sending AddTlc message: {:?}", &msg); self.network .send_message(NetworkActorMessage::new_command( @@ -1246,13 +1195,6 @@ where )) .expect(ASSUME_NETWORK_ACTOR_ALIVE); - debug!( - "Channel ({:?}) balance after removing tlc {:?}: local balance: {}, remote balance: {}", - state.get_id(), - tlc_kind, - state.to_local_amount, - state.to_remote_amount - ); state.maybe_transition_to_shutdown(&self.network)?; self.handle_commitment_signed_command(state)?; state.tlc_state.set_waiting_ack(true); @@ -1264,9 +1206,42 @@ where state: &mut ChannelActorState, command: ShutdownCommand, ) -> ProcessingChannelResult { - // The force shutdown command has been handled speically in the `NetworkActorState#send_command_to_channel` function. - // We only need to handle the normal shutdown command here. debug!("Handling shutdown command: {:?}", &command); + if command.force { + match state.state { + ChannelState::ChannelReady() => { + debug!("Handling force shutdown command in ChannelReady state"); + } + ChannelState::ShuttingDown(flags) => { + debug!( + "Handling force shutdown command in ShuttingDown state, flags: {:?}", + &flags + ); + } + _ => { + return Err(ProcessingChannelError::InvalidState(format!( + "Handling force shutdown command invalid state {:?}", + &state.state + ))); + } + }; + + let transaction = state + .latest_commitment_transaction + .clone() + .expect("latest_commitment_transaction should exist when channel is in ChannelReady of ShuttingDown state"); + self.network + .send_message(NetworkActorMessage::new_event( + NetworkActorEvent::CommitmentTransactionPending(transaction, state.get_id()), + )) + .expect(ASSUME_NETWORK_ACTOR_ALIVE); + + state.update_state(ChannelState::ShuttingDown( + ShuttingDownFlags::WAITING_COMMITMENT_CONFIRMATION, + )); + return Ok(()); + } + let flags = match state.state { ChannelState::ChannelReady() => { debug!("Handling shutdown command in ChannelReady state"); @@ -1550,8 +1525,10 @@ where } TxCollaborationCommand::TxComplete() => { state.check_tx_complete_preconditions()?; + let commitment_tx_partial_signature = state.build_init_commitment_tx_signature()?; let fiber_message = FiberMessage::tx_complete(TxComplete { channel_id: state.get_id(), + commitment_tx_partial_signature, }); self.network .send_message(NetworkActorMessage::new_command( @@ -2119,7 +2096,7 @@ impl CommitmentNumbers { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, Hash)] pub enum TLCId { Offered(u64), Received(u64), @@ -2726,6 +2703,35 @@ impl ChannelConstraints { } } +#[serde_as] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct RevocationData { + pub commitment_number: u64, + pub x_only_aggregated_pubkey: [u8; 32], + #[serde_as(as = "CompactSignatureAsBytes")] + pub aggregated_signature: CompactSignature, + #[serde_as(as = "EntityHex")] + pub output: CellOutput, + #[serde_as(as = "EntityHex")] + pub output_data: Bytes, +} + +#[serde_as] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct SettlementData { + pub x_only_aggregated_pubkey: [u8; 32], + #[serde_as(as = "CompactSignatureAsBytes")] + pub aggregated_signature: CompactSignature, + #[serde_as(as = "EntityHex")] + pub to_local_output: CellOutput, + #[serde_as(as = "EntityHex")] + pub to_local_output_data: Bytes, + #[serde_as(as = "EntityHex")] + pub to_remote_output: CellOutput, + #[serde_as(as = "EntityHex")] + pub to_remote_output_data: Bytes, +} + #[serde_as] #[derive(Clone, Serialize, Deserialize)] pub struct ChannelActorState { @@ -2822,7 +2828,8 @@ pub struct ChannelActorState { #[serde_as(as = "Vec<(U64Hex, PubNonceAsBytes)>")] pub remote_nonces: Vec<(u64, PubNonce)>, - // The latest commitment transaction we're holding + // The latest commitment transaction we're holding, + // it can be broadcasted to blockchain by us to force close the channel. #[serde_as(as = "Option")] pub latest_commitment_transaction: Option, @@ -3332,30 +3339,13 @@ impl ChannelActorState { capacity, self.funding_udt_type_script.clone(), ); - debug!( - "Created unsigned channel announcement for channel {:?}: {:?}", - &self.get_id(), - &channel_announcement, - ); channel_announcement } }; - debug!( - "Trying to complete channel announcement signatures for channel {:?}: {:?}", - &self.get_id(), - channel_announcement, - ); - let local_nonce = self .get_channel_announcement_musig2_secnonce() .public_nonce(); - debug!( - "Local nonce: {:?}, remote nonce: {:?}, remote signatures: {:?}", - &local_nonce, - self.get_remote_channel_announcement_nonce(), - self.get_remote_channel_announcement_signature() - ); let remote_nonce = self.get_remote_channel_announcement_nonce()?; let agg_nonce = AggNonce::sum(self.order_things_for_musig2(local_nonce, remote_nonce.clone())); @@ -3375,8 +3365,6 @@ impl ChannelActorState { let (remote_node_signature, remote_partial_signature) = self.get_remote_channel_announcement_signature()?; - debug!("Aggregating partial signatures for channel {:?}", &self.id); - if self.local_is_node1() { channel_announcement.node1_signature = Some(local_node_signature); channel_announcement.node2_signature = Some(remote_node_signature); @@ -3441,12 +3429,6 @@ impl ChannelActorState { network: &ActorRef, ) { let channel_update = self.generate_channel_update(network).await; - - debug!( - "Broadcasting channel update message to peers: {:?}", - &channel_update - ); - network .send_message(NetworkActorMessage::new_command( NetworkActorCommand::ProccessChannelUpdate( @@ -3570,7 +3552,6 @@ impl ChannelActorState { remote_shutdown_info: None, local_reserved_ckb_amount, remote_reserved_ckb_amount, - latest_commitment_transaction: None, local_constraints: ChannelConstraints::new( local_max_tlc_value_in_flight, local_max_tlc_number_in_flight, @@ -3579,6 +3560,7 @@ impl ChannelActorState { remote_max_tlc_value_in_flight, remote_max_tlc_number_in_flight, ), + latest_commitment_transaction: None, reestablishing: false, created_at: SystemTime::now(), }; @@ -4009,65 +3991,102 @@ impl ChannelActorState { // Send RevokeAndAck message to the counterparty, and update the // channel state accordingly. - fn send_revoke_and_ack_message(&mut self, network: &ActorRef) { - let commitment_tx_fee = - calculate_commitment_tx_fee(self.commitment_fee_rate, &self.funding_udt_type_script); - let lock_script = self.get_remote_shutdown_script(); - let (output, output_data) = if let Some(udt_type_script) = &self.funding_udt_type_script { - let capacity = self.get_total_reserved_ckb_amount() - commitment_tx_fee; - let output = CellOutput::new_builder() - .lock(lock_script) - .type_(Some(udt_type_script.clone()).pack()) - .capacity(capacity.pack()) - .build(); - - let output_data = self.get_total_udt_amount().to_le_bytes().pack(); - (output, output_data) - } else { - let capacity = self.get_total_ckb_amount() - commitment_tx_fee; - let output = CellOutput::new_builder() - .lock(lock_script) - .capacity(capacity.pack()) - .build(); - let output_data = Bytes::default(); - (output, output_data) + fn send_revoke_and_ack_message( + &mut self, + network: &ActorRef, + ) -> ProcessingChannelResult { + let key_agg_ctx = { + let local_pubkey = self.get_local_channel_public_keys().funding_pubkey; + let remote_pubkey = self.get_remote_channel_public_keys().funding_pubkey; + KeyAggContext::new([remote_pubkey, local_pubkey]).expect("Valid pubkeys") + }; + let x_only_aggregated_pubkey = key_agg_ctx.aggregated_pubkey::().serialize_xonly(); + let sign_ctx = { + let local_nonce = self.get_local_nonce(); + let remote_nonce = self.get_remote_nonce(); + let nonces = [local_nonce, remote_nonce]; + let agg_nonce = AggNonce::sum(nonces); + Musig2SignContext { + key_agg_ctx, + agg_nonce, + seckey: self.signer.funding_key.clone(), + secnonce: self.get_local_musig2_secnonce(), + } }; - let local_pubkey = self.get_local_channel_public_keys().funding_pubkey; - let remote_pubkey = self.get_remote_channel_public_keys().funding_pubkey; - let key_agg_ctx = KeyAggContext::new([remote_pubkey, local_pubkey]).expect("Valid pubkeys"); + let revocation_partial_signature = { + let commitment_tx_fee = calculate_commitment_tx_fee( + self.commitment_fee_rate, + &self.funding_udt_type_script, + ); + let lock_script = self.get_remote_shutdown_script(); + let (output, output_data) = if let Some(udt_type_script) = &self.funding_udt_type_script + { + let capacity = self.get_total_reserved_ckb_amount() - commitment_tx_fee; + let output = CellOutput::new_builder() + .lock(lock_script) + .type_(Some(udt_type_script.clone()).pack()) + .capacity(capacity.pack()) + .build(); + + let output_data = self.get_total_udt_amount().to_le_bytes().pack(); + (output, output_data) + } else { + let capacity = self.get_total_ckb_amount() - commitment_tx_fee; + let output = CellOutput::new_builder() + .lock(lock_script) + .capacity(capacity.pack()) + .build(); + let output_data = Bytes::default(); + (output, output_data) + }; - let x_only_aggregated_pubkey = key_agg_ctx.aggregated_pubkey::().serialize_xonly(); - let delay_epoch = self.commitment_delay_epoch; - let commitment_number = self.get_remote_commitment_number(); - let commitment_lock_script_args = [ - &blake2b_256(x_only_aggregated_pubkey)[0..20], - (Since::new(SinceType::EpochNumberWithFraction, delay_epoch, true).value()) - .to_le_bytes() - .as_slice(), - commitment_number.to_be_bytes().as_slice(), - ] - .concat(); + let commitment_number = self.get_remote_commitment_number() - 1; + let commitment_lock_script_args = [ + &blake2b_256(x_only_aggregated_pubkey)[0..20], + self.get_delay_epoch_as_lock_args_bytes().as_slice(), + commitment_number.to_be_bytes().as_slice(), + ] + .concat(); + + let message = blake2b_256( + [ + output.as_slice(), + output_data.as_slice(), + commitment_lock_script_args.as_slice(), + ] + .concat(), + ); + sign_ctx + .clone() + .sign(message.as_slice()) + .expect("valid signature") + }; - let message = blake2b_256( - [ - output.as_slice(), - output_data.as_slice(), - commitment_lock_script_args.as_slice(), + let commitment_tx_partial_signature = { + let ( + [to_local_output, to_remote_output], + [to_local_output_data, to_remote_output_data], + ) = self.build_settlement_transaction_outputs(false); + let commitment_lock_script_args = [ + &blake2b_256(x_only_aggregated_pubkey)[0..20], + self.get_delay_epoch_as_lock_args_bytes().as_slice(), + self.get_remote_commitment_number().to_be_bytes().as_slice(), ] - .concat(), - ); - let local_nonce = self.get_local_nonce(); - let remote_nonce = self.get_remote_nonce(); - let nonces = [local_nonce, remote_nonce]; - let agg_nonce = AggNonce::sum(nonces); - let sign_ctx = Musig2SignContext { - key_agg_ctx, - agg_nonce, - seckey: self.signer.funding_key.clone(), - secnonce: self.get_local_musig2_secnonce(), + .concat(); + let message = blake2b_256( + [ + to_local_output.as_slice(), + to_local_output_data.as_slice(), + to_remote_output.as_slice(), + to_remote_output_data.as_slice(), + commitment_lock_script_args.as_slice(), + ] + .concat(), + ); + + sign_ctx.sign(message.as_slice())? }; - let signature = sign_ctx.sign(message.as_slice()).expect("valid signature"); // Note that we must update channel state here to update commitment number, // so that next step will obtain the correct commitment point. @@ -4080,12 +4099,14 @@ impl ChannelActorState { self.get_remote_peer_id(), FiberMessage::revoke_and_ack(RevokeAndAck { channel_id: self.get_id(), - partial_signature: signature, + revocation_partial_signature, + commitment_tx_partial_signature, next_per_commitment_point: point, }), )), )) .expect(ASSUME_NETWORK_ACTOR_ALIVE); + Ok(()) } pub fn get_id(&self) -> Hash256 { @@ -4120,10 +4141,6 @@ impl ChannelActorState { pub fn get_remote_nonce(&self) -> PubNonce { let comitment_number = self.get_remote_commitment_number(); - debug!( - "Getting remote nonce: commitment number {}, current nonces: {:?}", - comitment_number, &self.remote_nonces - ); assert!(self.remote_nonces.len() <= 2); self.remote_nonces .iter() @@ -4139,11 +4156,6 @@ impl ChannelActorState { } fn save_remote_nonce(&mut self, nonce: PubNonce) { - debug!( - "Saving remote nonce: new nonce {:?}, current nonces {:?}, commitment numbers {:?}", - &nonce, &self.remote_nonces, self.commitment_numbers - ); - let next_remote_number = if self.remote_nonces.is_empty() { 0 } else { @@ -4157,18 +4169,10 @@ impl ChannelActorState { fn save_remote_nonce_for_raa(&mut self) { let nonce = self.get_remote_nonce(); - debug!( - "Saving remote nonce used in commitment signed: {:?}", - &nonce - ); self.last_used_nonce_in_commitment_signed = Some(nonce); } fn take_remote_nonce_for_raa(&mut self) -> PubNonce { - debug!( - "Taking remote nonce used in commitment signed: {:?}", - &self.last_used_nonce_in_commitment_signed - ); self.last_used_nonce_in_commitment_signed .take() .expect("set last_used_nonce_in_commitment_signed in commitment signed") @@ -4187,10 +4191,6 @@ impl ChannelActorState { } fn set_remote_commitment_number(&mut self, number: u64) { - debug!( - "Setting remote commitment number from {} to {}", - self.commitment_numbers.remote, number - ); self.commitment_numbers.remote = number; } @@ -4202,16 +4202,16 @@ impl ChannelActorState { self.commitment_numbers.increment_remote(); } - pub fn get_current_commitment_number(&self, local: bool) -> u64 { - if local { + pub fn get_current_commitment_number(&self, for_remote: bool) -> u64 { + if for_remote { self.get_local_commitment_number() } else { self.get_remote_commitment_number() } } - pub fn get_next_commitment_number(&self, local: bool) -> u64 { - self.get_current_commitment_number(local) + 1 + pub fn get_next_commitment_number(&self, for_remote: bool) -> u64 { + self.get_current_commitment_number(for_remote) + 1 } pub fn get_next_offering_tlc_id(&self) -> u64 { @@ -4258,7 +4258,6 @@ impl ChannelActorState { } if tlc.is_offered() { let sent_tlc_value = self.get_offered_tlc_balance(); - debug!("Value of local sent tlcs: {}", sent_tlc_value); debug_assert!(self.to_local_amount >= sent_tlc_value); if sent_tlc_value + tlc.amount > self.to_local_amount { return Err(ProcessingChannelError::InvalidParameter(format!( @@ -4270,7 +4269,6 @@ impl ChannelActorState { } } else { let received_tlc_value = self.get_received_tlc_balance(); - debug!("Value of remote received tlcs: {}", received_tlc_value); debug_assert!(self.to_remote_amount >= received_tlc_value); if received_tlc_value + tlc.amount > self.to_remote_amount { return Err(ProcessingChannelError::InvalidParameter(format!( @@ -4281,14 +4279,6 @@ impl ChannelActorState { ))); } } - debug!( - "Adding new tlc {:?} to channel {:?} with local balance {} and remote balance {}", - &tlc, - &self.get_id(), - self.to_local_amount, - self.to_remote_amount - ); - Ok(()) } @@ -4318,9 +4308,6 @@ impl ChannelActorState { tlc_id, current_removed_at, reason, removed_at, current_remove_reason))); } None => { - debug!("Inserting remove reason {:?} at commitment number {:?} for tlc {:?} hash_algorithm: {:?}", - reason, removed_at, current, current.hash_algorithm); - if let RemoveTlcReason::RemoveTlcFulfill(fulfill) = reason { let filled_payment_hash: Hash256 = current.hash_algorithm.hash(fulfill.payment_preimage).into(); @@ -4404,20 +4391,11 @@ impl ChannelActorState { } fn get_local_commitment_point(&self, commitment_number: u64) -> Pubkey { - let commitment_point = self.signer.get_commitment_point(commitment_number); - debug!( - "Obtained {}th local commitment point: {:?}", - commitment_number, commitment_point - ); - commitment_point + self.signer.get_commitment_point(commitment_number) } /// Get the counterparty commitment point for the given commitment number. fn get_remote_commitment_point(&self, commitment_number: u64) -> Pubkey { - debug!( - "Getting remote commitment point #{} from remote_commitment_points: {:?}", - commitment_number, &self.remote_commitment_points - ); self.remote_commitment_points .iter() .find_map(|(number, point)| { @@ -4503,10 +4481,7 @@ impl ChannelActorState { AggNonce::sum(nonces) } - pub fn get_active_received_tlcs( - &self, - local_commitment: bool, - ) -> impl Iterator { + fn get_active_received_tlcs(&self, local_commitment: bool) -> impl Iterator { self.tlc_state .get_tlcs_with(local_commitment) .into_iter() @@ -4516,10 +4491,7 @@ impl ChannelActorState { }) } - pub fn get_active_offered_tlcs( - &self, - local_commitment: bool, - ) -> impl Iterator { + fn get_active_offered_tlcs(&self, local_commitment: bool) -> impl Iterator { self.tlc_state .get_tlcs_with(local_commitment) .into_iter() @@ -4529,6 +4501,50 @@ impl ChannelActorState { }) } + // Get the total amount of pending tlcs that are fulfilled + fn get_pending_fulfilled_tlcs_amount(&self, for_remote: bool, offered: bool) -> u128 { + let (local_pending_tlcs, remote_pending_tlcs) = if for_remote { + ( + &self.tlc_state.local_pending_tlcs, + &self.tlc_state.remote_pending_tlcs, + ) + } else { + ( + &self.tlc_state.remote_pending_tlcs, + &self.tlc_state.local_pending_tlcs, + ) + }; + let mut pending = local_pending_tlcs + .get_committed_tlcs() + .into_iter() + .chain(remote_pending_tlcs.get_committed_tlcs().into_iter()) + .filter_map(|tlc| { + if matches!(tlc, TlcKind::AddTlc(info) if info.removed_at.is_none() && info.is_offered() == offered) { + Some((tlc.tlc_id(), tlc.amount())) + } else { + None + } + }).collect::>(); + let mut fulfilled = 0; + + for tlc in local_pending_tlcs.get_staging_tlcs() { + match tlc { + TlcKind::AddTlc(_info) => { + pending.insert(tlc.tlc_id(), tlc.amount()); + } + TlcKind::RemoveTlc(remove_tlc) => { + if let Some(amount) = pending.remove(&remove_tlc.tlc_id) { + if matches!(remove_tlc.reason, RemoveTlcReason::RemoveTlcFulfill(_)) { + fulfilled += amount; + } + } + } + } + } + + fulfilled + } + pub fn get_all_received_tlcs(&self) -> impl Iterator { self.tlc_state.all_tlcs().filter(|tlc| tlc.is_received()) } @@ -4569,7 +4585,7 @@ impl ChannelActorState { } } - pub fn get_active_received_tlc_with_pubkeys( + fn get_active_received_tlc_with_pubkeys( &self, local: bool, ) -> Vec<(AddTlcInfo, Pubkey, Pubkey)> { @@ -4581,7 +4597,7 @@ impl ChannelActorState { .collect() } - pub fn get_active_offered_tlc_with_pubkeys( + fn get_active_offered_tlc_with_pubkeys( &self, local: bool, ) -> Vec<(AddTlcInfo, Pubkey, Pubkey)> { @@ -4850,50 +4866,100 @@ impl ChannelActorState { Ok(tlc_info) } - pub fn create_witness_for_funding_cell( - &self, - signature: CompactSignature, - ) -> [u8; FUNDING_CELL_WITNESS_LEN] { - create_witness_for_funding_cell(self.get_funding_lock_script_xonly(), signature) - } - - pub fn aggregate_partial_signatures_to_consume_funding_cell( + fn aggregate_partial_signatures_to_consume_funding_cell( &self, partial_signatures: [PartialSignature; 2], tx: &TransactionView, ) -> Result { - let funding_out_point = self.must_get_funding_transaction_outpoint(); - debug_assert_eq!( - tx.input_pts_iter().next().as_ref(), - Some(&funding_out_point), - "The first input of the tx must be the funding cell outpoint" - ); - let verify_ctx = Musig2VerifyContext::from(self); - let signature = aggregate_partial_signatures_for_msg( - tx.hash().as_slice(), - verify_ctx, - partial_signatures, - )?; + let signature = verify_ctx + .aggregate_partial_signatures_for_msg(partial_signatures, tx.hash().as_slice())?; - let witness = self.create_witness_for_funding_cell(signature); + let witness = + create_witness_for_funding_cell(self.get_funding_lock_script_xonly(), signature); Ok(tx .as_advanced_builder() .set_witnesses(vec![witness.pack()]) .build()) } - pub fn sign_tx_to_consume_funding_cell( + fn complete_partially_signed_tx( &self, psct: &PartiallySignedCommitmentTransaction, - ) -> Result { - let sign_ctx = Musig2SignContext::from(self); - let signature2 = sign_ctx.sign(psct.commitment_tx.hash().as_slice())?; + ) -> Result<(TransactionView, SettlementData), ProcessingChannelError> { + let completed_commitment_tx = { + let sign_ctx = Musig2SignContext::from(self); + let our_funding_tx_partial_signature = + sign_ctx.sign(psct.commitment_tx.hash().as_slice())?; + self.aggregate_partial_signatures_to_consume_funding_cell( + [ + psct.funding_tx_partial_signature, + our_funding_tx_partial_signature, + ], + &psct.commitment_tx, + )? + }; - self.aggregate_partial_signatures_to_consume_funding_cell( - [psct.funding_tx_partial_signature, signature2], - &psct.commitment_tx, - ) + let settlement_data = { + let settlement_tx = &psct.settlement_tx; + let commitment_tx = &psct.commitment_tx; + let to_local_output = settlement_tx + .outputs() + .get(0) + .expect("get output 0 of settlement tx"); + let to_local_output_data = settlement_tx + .outputs_data() + .get(0) + .expect("get output 0 data of settlement tx"); + let to_remote_output = settlement_tx + .outputs() + .get(1) + .expect("get output 1 of settlement tx"); + let to_remote_output_data = settlement_tx + .outputs_data() + .get(1) + .expect("get output 1 data of settlement tx"); + let args = commitment_tx + .outputs() + .get(0) + .expect("get output 0 of commitment tx") + .lock() + .args() + .raw_data(); + let message = blake2b_256( + [ + to_local_output.as_slice(), + to_local_output_data.as_slice(), + to_remote_output.as_slice(), + to_remote_output_data.as_slice(), + &args[0..36], + ] + .concat(), + ); + let sign_ctx = Musig2SignContext::from((self, false)); + let our_commitment_tx_partial_signature = sign_ctx.sign(message.as_slice())?; + + let verify_ctx = Musig2VerifyContext::from((self, false)); + let aggregated_signature = verify_ctx.aggregate_partial_signatures_for_msg( + [ + our_commitment_tx_partial_signature, + psct.commitment_tx_partial_signature, + ], + message.as_slice(), + )?; + let x_only_aggregated_pubkey = self.get_commitment_lock_script_xonly(false); + + SettlementData { + x_only_aggregated_pubkey, + aggregated_signature, + to_local_output, + to_local_output_data, + to_remote_output, + to_remote_output_data, + } + }; + + Ok((completed_commitment_tx, settlement_data)) } pub fn maybe_transition_to_shutdown( @@ -5125,22 +5191,23 @@ impl ChannelActorState { )); } } - TxCollaborationMsg::TxComplete(_msg) => { + TxCollaborationMsg::TxComplete(tx_complete) => { self.check_tx_complete_preconditions()?; + let settlement_data = self.check_init_commitment_tx_signature( + tx_complete.commitment_tx_partial_signature, + )?; + network + .send_message(NetworkActorMessage::new_notification( + NetworkServiceEvent::RemoteTxComplete( + self.get_remote_peer_id(), + self.get_id(), + self.get_funding_lock_script(), + settlement_data, + ), + )) + .expect(ASSUME_NETWORK_ACTOR_ALIVE); let flags = flags | CollaboratingFundingTxFlags::THEIR_TX_COMPLETE_SENT; self.update_state(ChannelState::CollaboratingFundingTx(flags)); - if flags.contains(CollaboratingFundingTxFlags::COLLABRATION_COMPLETED) { - // Notify outside observers. - network - .send_message(NetworkActorMessage::new_notification( - NetworkServiceEvent::CommitmentSignaturePending( - self.get_remote_peer_id(), - self.get_id(), - self.get_current_commitment_number(false), - ), - )) - .expect(ASSUME_NETWORK_ACTOR_ALIVE); - } } } Ok(()) @@ -5161,10 +5228,6 @@ impl ChannelActorState { ))); } ChannelState::CollaboratingFundingTx(_) => { - debug!( - "Processing commitment_signed message in state {:?}", - &self.state - ); CommitmentSignedFlags::SigningCommitment(SigningCommitmentFlags::empty()) } ChannelState::SigningCommitment(flags) @@ -5176,16 +5239,9 @@ impl ChannelActorState { ))); } ChannelState::SigningCommitment(flags) => { - debug!( - "Processing commitment_signed message in state {:?}", - &self.state - ); CommitmentSignedFlags::SigningCommitment(flags) } - ChannelState::ChannelReady() => { - debug!("Processing commitment_signed message while channel ready"); - CommitmentSignedFlags::ChannelReady() - } + ChannelState::ChannelReady() => CommitmentSignedFlags::ChannelReady(), ChannelState::ShuttingDown(flags) => { if flags.contains(ShuttingDownFlags::AWAITING_PENDING_TLCS) { debug!( @@ -5208,18 +5264,10 @@ impl ChannelActorState { } }; - let tx = self.verify_and_complete_tx( + let (commitment_tx, settlement_data) = self.verify_and_complete_tx( commitment_signed.funding_tx_partial_signature, commitment_signed.commitment_tx_partial_signature, )?; - // This is the commitment transaction that both parties signed, - // can be broadcasted to the network if necessary - let num = self.get_current_commitment_number(false); - - info!( - "Successfully handled commitment signed message: {:?}, tx: {:?}", - &commitment_signed, &tx - ); // Notify outside observers. network @@ -5227,19 +5275,14 @@ impl ChannelActorState { NetworkServiceEvent::RemoteCommitmentSigned( self.get_remote_peer_id(), self.get_id(), - num, - tx.clone(), + commitment_tx.clone(), + settlement_data, ), )) .expect(ASSUME_NETWORK_ACTOR_ALIVE); - debug!( - "Updating peer next remote nonce from {:?} to {:?}", - self.get_remote_nonce(), - &commitment_signed.next_local_nonce - ); self.save_remote_nonce(commitment_signed.next_local_nonce); - self.latest_commitment_transaction = Some(tx.data()); + self.latest_commitment_transaction = Some(commitment_tx.data()); match flags { CommitmentSignedFlags::SigningCommitment(flags) => { let flags = flags | SigningCommitmentFlags::THEIR_COMMITMENT_SIGNED_SENT; @@ -5247,7 +5290,7 @@ impl ChannelActorState { self.maybe_transition_to_tx_signatures(flags, network)?; } CommitmentSignedFlags::ChannelReady() | CommitmentSignedFlags::PendingShutdown(_) => { - self.send_revoke_and_ack_message(network); + self.send_revoke_and_ack_message(network)?; match flags { CommitmentSignedFlags::ChannelReady() => {} CommitmentSignedFlags::PendingShutdown(_) => { @@ -5264,23 +5307,6 @@ impl ChannelActorState { } } } - - if let ChannelState::SigningCommitment(flags) = self.state { - if !flags.contains(SigningCommitmentFlags::OUR_COMMITMENT_SIGNED_SENT) { - // TODO: maybe we should send our commitment_signed message here. - debug!("CommitmentSigned message received, but we haven't sent our commitment_signed message yet"); - // Notify outside observers. - network - .send_message(NetworkActorMessage::new_notification( - NetworkServiceEvent::CommitmentSignaturePending( - self.get_remote_peer_id(), - self.get_id(), - self.get_current_commitment_number(false), - ), - )) - .expect(ASSUME_NETWORK_ACTOR_ALIVE); - } - } Ok(()) } @@ -5479,88 +5505,137 @@ impl ChannelActorState { network: &ActorRef, revoke_and_ack: RevokeAndAck, ) -> ProcessingChannelResult { - let commitment_tx_fee = - calculate_commitment_tx_fee(self.commitment_fee_rate, &self.funding_udt_type_script); - let lock_script = self.get_local_shutdown_script(); - let (output, output_data) = if let Some(udt_type_script) = &self.funding_udt_type_script { - let capacity = self.get_total_reserved_ckb_amount() - commitment_tx_fee; - let output = CellOutput::new_builder() - .lock(lock_script) - .type_(Some(udt_type_script.clone()).pack()) - .capacity(capacity.pack()) - .build(); + let RevokeAndAck { + channel_id: _, + revocation_partial_signature, + commitment_tx_partial_signature, + next_per_commitment_point, + } = revoke_and_ack; - let output_data = self.get_total_udt_amount().to_le_bytes().pack(); - (output, output_data) - } else { - let capacity = self.get_total_ckb_amount() - commitment_tx_fee; - let output = CellOutput::new_builder() - .lock(lock_script) - .capacity(capacity.pack()) - .build(); - let output_data = Bytes::default(); - (output, output_data) + let key_agg_ctx = { + let local_pubkey = self.get_local_channel_public_keys().funding_pubkey; + let remote_pubkey = self.get_remote_channel_public_keys().funding_pubkey; + KeyAggContext::new([local_pubkey, remote_pubkey]).expect("Valid pubkeys") }; - - let local_pubkey = self.get_local_channel_public_keys().funding_pubkey; - let remote_pubkey = self.get_remote_channel_public_keys().funding_pubkey; - let key_agg_ctx = KeyAggContext::new([local_pubkey, remote_pubkey]).expect("Valid pubkeys"); - let x_only_aggregated_pubkey = key_agg_ctx.aggregated_pubkey::().serialize_xonly(); - let delay_epoch = self.commitment_delay_epoch; - let commitment_number = self.get_local_commitment_number(); - - let commitment_lock_script_args = [ - &blake2b_256(x_only_aggregated_pubkey)[0..20], - (Since::new(SinceType::EpochNumberWithFraction, delay_epoch, true).value()) - .to_le_bytes() - .as_slice(), - commitment_number.to_be_bytes().as_slice(), - ] - .concat(); - - let message = blake2b_256( - [ - output.as_slice(), - output_data.as_slice(), - commitment_lock_script_args.as_slice(), - ] - .concat(), - ); - - let local_nonce = self.get_local_nonce(); - let remote_nonce = self.take_remote_nonce_for_raa(); - let nonces = [remote_nonce.clone(), local_nonce]; - let agg_nonce = AggNonce::sum(nonces); + let (verify_ctx, sign_ctx) = { + let local_nonce = self.get_local_nonce(); + let remote_nonce = self.take_remote_nonce_for_raa(); + let nonces = [remote_nonce.clone(), local_nonce]; + let agg_nonce = AggNonce::sum(nonces); - let verify_ctx = Musig2VerifyContext { - key_agg_ctx: key_agg_ctx.clone(), - agg_nonce: agg_nonce.clone(), - pubkey: *self.get_remote_funding_pubkey(), - pubnonce: remote_nonce, + ( + Musig2VerifyContext { + key_agg_ctx: key_agg_ctx.clone(), + agg_nonce: agg_nonce.clone(), + pubkey: *self.get_remote_funding_pubkey(), + pubnonce: remote_nonce, + }, + Musig2SignContext { + key_agg_ctx, + agg_nonce, + seckey: self.signer.funding_key.clone(), + secnonce: self.get_local_musig2_secnonce(), + }, + ) }; - let RevokeAndAck { - channel_id: _, - partial_signature, - next_per_commitment_point, - } = revoke_and_ack; + let revocation_data = { + let commitment_tx_fee = calculate_commitment_tx_fee( + self.commitment_fee_rate, + &self.funding_udt_type_script, + ); + let lock_script = self.get_local_shutdown_script(); + let (output, output_data) = if let Some(udt_type_script) = &self.funding_udt_type_script + { + let capacity = self.get_total_reserved_ckb_amount() - commitment_tx_fee; + let output = CellOutput::new_builder() + .lock(lock_script) + .type_(Some(udt_type_script.clone()).pack()) + .capacity(capacity.pack()) + .build(); + + let output_data = self.get_total_udt_amount().to_le_bytes().pack(); + (output, output_data) + } else { + let capacity = self.get_total_ckb_amount() - commitment_tx_fee; + let output = CellOutput::new_builder() + .lock(lock_script) + .capacity(capacity.pack()) + .build(); + let output_data = Bytes::default(); + (output, output_data) + }; - verify_ctx.verify(partial_signature, message.as_slice())?; + let commitment_number = self.get_local_commitment_number() - 1; - let sign_ctx: Musig2SignContext = Musig2SignContext { - key_agg_ctx, - agg_nonce, - seckey: self.signer.funding_key.clone(), - secnonce: self.get_local_musig2_secnonce(), + let commitment_lock_script_args = [ + &blake2b_256(x_only_aggregated_pubkey)[0..20], + self.get_delay_epoch_as_lock_args_bytes().as_slice(), + commitment_number.to_be_bytes().as_slice(), + ] + .concat(); + + let message = blake2b_256( + [ + output.as_slice(), + output_data.as_slice(), + commitment_lock_script_args.as_slice(), + ] + .concat(), + ); + verify_ctx.verify(revocation_partial_signature, message.as_slice())?; + let our_signature = sign_ctx.clone().sign(message.as_slice())?; + let aggregated_signature = verify_ctx.aggregate_partial_signatures_for_msg( + [revocation_partial_signature, our_signature], + message.as_slice(), + )?; + RevocationData { + commitment_number, + x_only_aggregated_pubkey, + aggregated_signature, + output, + output_data, + } }; - let signature2 = sign_ctx.sign(message.as_slice())?; - let aggregate_signature = aggregate_partial_signatures_for_msg( - message.as_slice(), - verify_ctx, - [partial_signature, signature2], - )?; + let settlement_data = { + let ( + [to_local_output, to_remote_output], + [to_local_output_data, to_remote_output_data], + ) = self.build_settlement_transaction_outputs(true); + let commitment_lock_script_args = [ + &blake2b_256(x_only_aggregated_pubkey)[0..20], + self.get_delay_epoch_as_lock_args_bytes().as_slice(), + self.get_local_commitment_number().to_be_bytes().as_slice(), + ] + .concat(); + let message = blake2b_256( + [ + to_local_output.as_slice(), + to_local_output_data.as_slice(), + to_remote_output.as_slice(), + to_remote_output_data.as_slice(), + commitment_lock_script_args.as_slice(), + ] + .concat(), + ); + verify_ctx.verify(commitment_tx_partial_signature, message.as_slice())?; + let our_signature = sign_ctx.sign(message.as_slice())?; + let aggregated_signature = verify_ctx.aggregate_partial_signatures_for_msg( + [commitment_tx_partial_signature, our_signature], + message.as_slice(), + )?; + + SettlementData { + x_only_aggregated_pubkey, + aggregated_signature, + to_local_output, + to_local_output_data, + to_remote_output, + to_remote_output_data, + } + }; self.increment_local_commitment_number(); self.append_remote_commitment_point(next_per_commitment_point); @@ -5579,11 +5654,8 @@ impl ChannelActorState { NetworkServiceEvent::RevokeAndAckReceived( self.get_remote_peer_id(), self.get_id(), - commitment_number, - x_only_aggregated_pubkey, - aggregate_signature, - output, - output_data, + revocation_data, + settlement_data, ), )) .expect(ASSUME_NETWORK_ACTOR_ALIVE); @@ -5687,7 +5759,7 @@ impl ChannelActorState { // Resetting our remote commitment number to the actual remote commitment number // and resend the RevokeAndAck message. self.set_remote_commitment_number(acutal_remote_commitment_number); - self.send_revoke_and_ack_message(network); + self.send_revoke_and_ack_message(network)?; } else { // unreachable state, just log an error for potential bugs error!( @@ -5775,12 +5847,14 @@ impl ChannelActorState { // Otherwise, it is possible that when the network actor is processing ControlFiberChannel, // it receives another SendFiberMessage command, and that message (e.g. CommitmentSigned) // is processed first, thus breaking the order of messages. + let commitment_tx_partial_signature = self.build_init_commitment_tx_signature()?; network .send_message(NetworkActorMessage::new_command( NetworkActorCommand::SendFiberMessage(FiberMessageWithPeerId::new( self.get_remote_peer_id(), FiberMessage::tx_complete(TxComplete { channel_id: self.get_id(), + commitment_tx_partial_signature, }), )), )) @@ -5800,6 +5874,116 @@ impl ChannelActorState { Ok(()) } + fn build_init_commitment_tx_signature(&self) -> Result { + let key_agg_ctx = { + let local_pubkey = self.get_local_channel_public_keys().funding_pubkey; + let remote_pubkey = self.get_remote_channel_public_keys().funding_pubkey; + KeyAggContext::new([remote_pubkey, local_pubkey]).expect("Valid pubkeys") + }; + let x_only_aggregated_pubkey = key_agg_ctx.aggregated_pubkey::().serialize_xonly(); + let sign_ctx = { + let local_nonce = self.get_local_nonce(); + let remote_nonce = self.get_remote_nonce(); + let nonces = [local_nonce, remote_nonce]; + let agg_nonce = AggNonce::sum(nonces); + Musig2SignContext { + key_agg_ctx, + agg_nonce, + seckey: self.signer.funding_key.clone(), + secnonce: self.get_local_musig2_secnonce(), + } + }; + let ([to_local_output, to_remote_output], [to_local_output_data, to_remote_output_data]) = + self.build_settlement_transaction_outputs(false); + let version = 0u64; + let commitment_lock_script_args = [ + &blake2b_256(x_only_aggregated_pubkey)[0..20], + self.get_delay_epoch_as_lock_args_bytes().as_slice(), + version.to_be_bytes().as_slice(), + ] + .concat(); + let message = blake2b_256( + [ + to_local_output.as_slice(), + to_local_output_data.as_slice(), + to_remote_output.as_slice(), + to_remote_output_data.as_slice(), + commitment_lock_script_args.as_slice(), + ] + .concat(), + ); + + sign_ctx.sign(message.as_slice()) + } + + fn check_init_commitment_tx_signature( + &self, + signature: PartialSignature, + ) -> Result { + let key_agg_ctx = { + let local_pubkey = self.get_local_channel_public_keys().funding_pubkey; + let remote_pubkey = self.get_remote_channel_public_keys().funding_pubkey; + KeyAggContext::new([local_pubkey, remote_pubkey]).expect("Valid pubkeys") + }; + let x_only_aggregated_pubkey = key_agg_ctx.aggregated_pubkey::().serialize_xonly(); + let local_nonce = self.get_local_nonce(); + let remote_nonce = self.get_remote_nonce(); + let nonces = [remote_nonce.clone(), local_nonce]; + let agg_nonce = AggNonce::sum(nonces); + let verify_ctx = Musig2VerifyContext { + key_agg_ctx: key_agg_ctx.clone(), + agg_nonce: agg_nonce.clone(), + pubkey: *self.get_remote_funding_pubkey(), + pubnonce: remote_nonce, + }; + let ([to_local_output, to_remote_output], [to_local_output_data, to_remote_output_data]) = + self.build_settlement_transaction_outputs(true); + let version = 0u64; + let commitment_lock_script_args = [ + &blake2b_256(x_only_aggregated_pubkey)[0..20], + self.get_delay_epoch_as_lock_args_bytes().as_slice(), + version.to_be_bytes().as_slice(), + ] + .concat(); + let message = blake2b_256( + [ + to_local_output.as_slice(), + to_local_output_data.as_slice(), + to_remote_output.as_slice(), + to_remote_output_data.as_slice(), + commitment_lock_script_args.as_slice(), + ] + .concat(), + ); + + verify_ctx.verify(signature, message.as_slice())?; + + let settlement_data = { + let sign_ctx = Musig2SignContext { + key_agg_ctx, + agg_nonce, + seckey: self.signer.funding_key.clone(), + secnonce: self.get_local_musig2_secnonce(), + }; + + let our_signature = sign_ctx.sign(message.as_slice())?; + let aggregated_signature = verify_ctx.aggregate_partial_signatures_for_msg( + [signature, our_signature], + message.as_slice(), + )?; + + SettlementData { + x_only_aggregated_pubkey, + aggregated_signature, + to_local_output, + to_local_output_data, + to_remote_output, + to_remote_output_data, + } + }; + Ok(settlement_data) + } + // TODO: More checks to the funding tx. fn check_tx_complete_preconditions(&mut self) -> ProcessingChannelResult { match self.funding_tx.as_ref() { @@ -5915,27 +6099,28 @@ impl ChannelActorState { "shutdown_tx local_capacity: {} - {} = {}", self.local_reserved_ckb_amount, local_shutdown_fee, local_capacity ); - let local_output = CellOutput::new_builder() + let to_local_output = CellOutput::new_builder() .lock(local_shutdown_script) .type_(Some(type_script.clone()).pack()) .capacity(local_capacity.pack()) .build(); - let local_output_data = self.to_local_amount.to_le_bytes().pack(); + let to_local_output_data = self.to_local_amount.to_le_bytes().pack(); let remote_capacity: u64 = self.remote_reserved_ckb_amount - remote_shutdown_fee; debug!( "shutdown_tx remote_capacity: {} - {} = {}", self.remote_reserved_ckb_amount, remote_shutdown_fee, remote_capacity ); - let remote_output = CellOutput::new_builder() + let to_remote_output = CellOutput::new_builder() .lock(remote_shutdown_script) .type_(Some(type_script.clone()).pack()) .capacity(remote_capacity.pack()) .build(); - let remote_output_data = self.to_remote_amount.to_le_bytes().pack(); + let to_remote_output_data = self.to_remote_amount.to_le_bytes().pack(); - let outputs = self.order_things_for_musig2(local_output, remote_output); - let outputs_data = self.order_things_for_musig2(local_output_data, remote_output_data); + let outputs = self.order_things_for_musig2(to_local_output, to_remote_output); + let outputs_data = + self.order_things_for_musig2(to_local_output_data, to_remote_output_data); let tx = tx_builder .set_outputs(outputs.to_vec()) .set_outputs_data(outputs_data.to_vec()) @@ -5955,15 +6140,15 @@ impl ChannelActorState { "Building shutdown transaction with values: local {}, remote {}", local_value, remote_value ); - let local_output = CellOutput::new_builder() + let to_local_output = CellOutput::new_builder() .capacity(local_value.pack()) .lock(local_shutdown_script) .build(); - let remote_output = CellOutput::new_builder() + let to_remote_output = CellOutput::new_builder() .capacity(remote_value.pack()) .lock(remote_shutdown_script) .build(); - let outputs = self.order_things_for_musig2(local_output, remote_output); + let outputs = self.order_things_for_musig2(to_local_output, to_remote_output); let tx = tx_builder .set_outputs(outputs.to_vec()) .set_outputs_data(vec![Default::default(), Default::default()]) @@ -5972,8 +6157,8 @@ impl ChannelActorState { } } - // The parameter `local` here specifies whether we are building the commitment transaction - // for the local party or the remote party. If `local` is true, then we are building a + // The parameter `for_remote` here specifies whether we are building the commitment transaction + // for the local party or the remote party. If `for_remote` is false, then we are building a // commitment transaction which can be broadcasted by ourself (with valid partial // signature from the other party), else we are building a commitment transaction // for the remote party (we build this commitment transaction @@ -5984,13 +6169,13 @@ impl ChannelActorState { // commitment transaction. fn build_commitment_and_settlement_tx( &self, - local: bool, + for_remote: bool, ) -> (TransactionView, TransactionView) { let commitment_tx = { let funding_out_point = self.must_get_funding_transaction_outpoint(); let cell_deps = get_cell_deps(vec![Contract::FundingLock], &self.funding_udt_type_script); - let (output, output_data) = self.build_commitment_transaction_output(local); + let (output, output_data) = self.build_commitment_transaction_output(for_remote); TransactionBuilder::default() .cell_deps(cell_deps) @@ -6010,7 +6195,7 @@ impl ChannelActorState { vec![Contract::CommitmentLock], &self.funding_udt_type_script, ); - let (outputs, outputs_data) = self.build_settlement_transaction_outputs(local); + let (outputs, outputs_data) = self.build_settlement_transaction_outputs(for_remote); TransactionBuilder::default() .cell_deps(cell_deps) @@ -6027,28 +6212,14 @@ impl ChannelActorState { (commitment_tx, settlement_tx) } - fn build_commitment_transaction_output(&self, local: bool) -> (CellOutput, Bytes) { - let local_pubkey = self.get_local_channel_public_keys().funding_pubkey; - let remote_pubkey = self.get_remote_channel_public_keys().funding_pubkey; - let pubkeys = if local { - [local_pubkey, remote_pubkey] - } else { - [remote_pubkey, local_pubkey] - }; - let x_only_aggregated_pubkey = KeyAggContext::new(pubkeys) - .expect("Valid pubkeys") - .aggregated_pubkey::() - .serialize_xonly(); - - let delay_epoch = self.commitment_delay_epoch; - let version = self.get_current_commitment_number(local); - let htlcs = self.get_active_htlcs(local); + fn build_commitment_transaction_output(&self, for_remote: bool) -> (CellOutput, Bytes) { + let x_only_aggregated_pubkey = self.get_commitment_lock_script_xonly(for_remote); + let version = self.get_current_commitment_number(for_remote); + let htlcs = self.get_active_htlcs(for_remote); let mut commitment_lock_script_args = [ &blake2b_256(x_only_aggregated_pubkey)[0..20], - (Since::new(SinceType::EpochNumberWithFraction, delay_epoch, true).value()) - .to_le_bytes() - .as_slice(), + self.get_delay_epoch_as_lock_args_bytes().as_slice(), version.to_be_bytes().as_slice(), ] .concat(); @@ -6084,39 +6255,51 @@ impl ChannelActorState { } } - fn build_settlement_transaction_outputs(&self, local: bool) -> ([CellOutput; 2], [Bytes; 2]) { - let received_tlc_value = self - .get_active_received_tlcs(local) - .map(|tlc| tlc.amount) - .sum::(); - let offered_tlc_value = self - .get_active_offered_tlcs(local) - .map(|tlc| tlc.amount) - .sum::(); + fn get_commitment_lock_script_xonly(&self, for_remote: bool) -> [u8; 32] { + let local_pubkey = self.get_local_channel_public_keys().funding_pubkey; + let remote_pubkey = self.get_remote_channel_public_keys().funding_pubkey; + let pubkeys = if for_remote { + [local_pubkey, remote_pubkey] + } else { + [remote_pubkey, local_pubkey] + }; + KeyAggContext::new(pubkeys) + .expect("Valid pubkeys") + .aggregated_pubkey::() + .serialize_xonly() + } - let to_local_value = - self.to_local_amount + self.local_reserved_ckb_amount as u128 - offered_tlc_value; - let to_remote_value = - self.to_remote_amount + self.remote_reserved_ckb_amount as u128 - received_tlc_value; + fn build_settlement_transaction_outputs( + &self, + for_remote: bool, + ) -> ([CellOutput; 2], [Bytes; 2]) { + let offered_fulfilled = self.get_pending_fulfilled_tlcs_amount(for_remote, true); + let received_fulfilled = self.get_pending_fulfilled_tlcs_amount(for_remote, false); + + let to_local_value = self.to_local_amount - offered_fulfilled + received_fulfilled; + let to_remote_value = self.to_remote_amount - received_fulfilled + offered_fulfilled; + let commitment_tx_fee = + calculate_commitment_tx_fee(self.commitment_fee_rate, &self.funding_udt_type_script); let to_local_output_script = self.get_local_shutdown_script(); let to_remote_output_script = self.get_remote_shutdown_script(); + // to simplify the fee calculation, we assume that the fee is double paid by both parties if let Some(udt_type_script) = &self.funding_udt_type_script { let to_local_output = CellOutput::new_builder() .lock(to_local_output_script) .type_(Some(udt_type_script.clone()).pack()) - .capacity(self.local_reserved_ckb_amount.pack()) + .capacity((self.local_reserved_ckb_amount - commitment_tx_fee).pack()) .build(); let to_local_output_data = to_local_value.to_le_bytes().pack(); let to_remote_output = CellOutput::new_builder() .lock(to_remote_output_script) .type_(Some(udt_type_script.clone()).pack()) - .capacity(self.remote_reserved_ckb_amount.pack()) + .capacity((self.remote_reserved_ckb_amount - commitment_tx_fee).pack()) .build(); let to_remote_output_data = to_remote_value.to_le_bytes().pack(); - if local { + if for_remote { ( [to_local_output, to_remote_output], [to_local_output_data, to_remote_output_data], @@ -6130,16 +6313,22 @@ impl ChannelActorState { } else { let to_local_output = CellOutput::new_builder() .lock(to_local_output_script) - .capacity((to_local_value as u64).pack()) + .capacity( + (to_local_value as u64 + self.local_reserved_ckb_amount - commitment_tx_fee) + .pack(), + ) .build(); let to_local_output_data = Bytes::default(); let to_remote_output = CellOutput::new_builder() .lock(to_remote_output_script) - .capacity((to_remote_value as u64).pack()) + .capacity( + (to_remote_value as u64 + self.remote_reserved_ckb_amount - commitment_tx_fee) + .pack(), + ) .build(); let to_remote_output_data = Bytes::default(); - if local { + if for_remote { ( [to_local_output, to_remote_output], [to_local_output_data, to_remote_output_data], @@ -6205,6 +6394,7 @@ impl ChannelActorState { Ok(PartiallySignedCommitmentTransaction { version: self.get_current_commitment_number(false), commitment_tx, + settlement_tx, funding_tx_partial_signature, commitment_tx_partial_signature, }) @@ -6212,7 +6402,7 @@ impl ChannelActorState { fn build_and_sign_commitment_tx( &self, - ) -> Result { + ) -> Result<(PartialSignature, PartialSignature), ProcessingChannelError> { let (commitment_tx, settlement_tx) = self.build_commitment_and_settlement_tx(true); let sign_ctx = Musig2SignContext::from(self); @@ -6255,12 +6445,10 @@ impl ChannelActorState { let commitment_tx_partial_signature = sign_ctx.sign(message.as_slice())?; - Ok(PartiallySignedCommitmentTransaction { - version: self.get_current_commitment_number(true), - commitment_tx, + Ok(( funding_tx_partial_signature, commitment_tx_partial_signature, - }) + )) } /// Verify the partial signature from the peer and create a complete transaction @@ -6269,12 +6457,21 @@ impl ChannelActorState { &self, funding_tx_partial_signature: PartialSignature, commitment_tx_partial_signature: PartialSignature, - ) -> Result { + ) -> Result<(TransactionView, SettlementData), ProcessingChannelError> { let tx = self.build_and_verify_commitment_tx( funding_tx_partial_signature, commitment_tx_partial_signature, )?; - self.sign_tx_to_consume_funding_cell(&tx) + self.complete_partially_signed_tx(&tx) + } + + fn get_delay_epoch_as_lock_args_bytes(&self) -> [u8; 8] { + let since = Since::new( + SinceType::EpochNumberWithFraction, + self.commitment_delay_epoch, + true, + ); + since.value().to_le_bytes() } } @@ -6311,6 +6508,8 @@ pub struct PartiallySignedCommitmentTransaction { pub version: u64, // The commitment transaction. pub commitment_tx: TransactionView, + // The settlement transaction. + pub settlement_tx: TransactionView, // The partial signature to unlock the funding transaction. pub funding_tx_partial_signature: PartialSignature, // The partial signature to unlock the commitment transaction. @@ -6329,12 +6528,23 @@ pub fn create_witness_for_funding_cell( witness.extend_from_slice(&empty_witness_args); witness.extend_from_slice(lock_key_xonly.as_slice()); witness.extend_from_slice(signature.serialize().as_slice()); + witness + .try_into() + .expect("Witness length should be correct") +} - debug!( - "Building witnesses for transaction to consume funding cell: {:?}", - hex::encode(&witness) - ); - +pub fn create_witness_for_commitment_cell( + lock_key_xonly: [u8; 32], + signature: CompactSignature, +) -> [u8; COMMITMENT_CELL_WITNESS_LEN] { + let mut witness = Vec::with_capacity(COMMITMENT_CELL_WITNESS_LEN); + // for xudt compatibility issue, + // refer to: https://github.com/nervosnetwork/fiber-scripts/pull/5 + let empty_witness_args = [16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0]; + witness.extend_from_slice(&empty_witness_args); + witness.extend_from_slice(&[0xFE]); + witness.extend_from_slice(lock_key_xonly.as_slice()); + witness.extend_from_slice(signature.serialize().as_slice()); witness .try_into() .expect("Witness length should be correct") @@ -6348,24 +6558,28 @@ pub struct Musig2VerifyContext { } impl Musig2VerifyContext { - pub fn verify(&self, signature: PartialSignature, message: &[u8]) -> ProcessingChannelResult { - let result = verify_partial( + pub fn verify(&self, signature: PartialSignature, message: &[u8]) -> Result<(), VerifyError> { + verify_partial( &self.key_agg_ctx, signature, &self.agg_nonce, self.pubkey, &self.pubnonce, message, - ); - debug!( - "Verifying partial signature {:?} with message {:?}, nonce {:?}, agg nonce {:?}, result {:?}", - &signature, - hex::encode(message), - &self.pubnonce, + ) + } + + pub fn aggregate_partial_signatures_for_msg( + &self, + partial_signatures: [PartialSignature; 2], + message: &[u8], + ) -> Result { + aggregate_partial_signatures( + &self.key_agg_ctx, &self.agg_nonce, - result - ); - Ok(result?) + partial_signatures, + message, + ) } } @@ -6378,44 +6592,17 @@ pub struct Musig2SignContext { } impl Musig2SignContext { - pub fn sign(self, message: &[u8]) -> Result { - let result = sign_partial( + pub fn sign(self, message: &[u8]) -> Result { + sign_partial( &self.key_agg_ctx, self.seckey, self.secnonce.clone(), &self.agg_nonce, message, - ); - debug!( - "Musig2 signing partial message {:?} with nonce {:?} (public nonce: {:?}), agg nonce {:?}: result {:?}", - hex::encode(message), - self.secnonce, - self.secnonce.public_nonce(), - &self.agg_nonce, - &result - ); - Ok(result?) + ) } } -pub fn aggregate_partial_signatures_for_msg( - message: &[u8], - verify_ctx: Musig2VerifyContext, - partial_signatures: [PartialSignature; 2], -) -> Result { - debug!( - "Message to aggregate signatures: {:?}", - hex::encode(message) - ); - let signature: CompactSignature = aggregate_partial_signatures( - &verify_ctx.key_agg_ctx, - &verify_ctx.agg_nonce, - partial_signatures, - message, - )?; - Ok(signature) -} - /// One counterparty's public keys which do not change over the life of a channel. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct ChannelBasePublicKeys { @@ -6547,10 +6734,6 @@ impl InMemorySigner { pub fn derive_musig2_nonce(&self, commitment_number: u64) -> SecNonce { let commitment_point = self.get_commitment_point(commitment_number); let seckey = derive_private_key(&self.musig2_base_nonce, &commitment_point); - debug!( - "Deriving Musig2 nonce: commitment number: {}, commitment point: {:?}", - commitment_number, commitment_point - ); SecNonce::build(seckey.as_ref()).build() } } diff --git a/src/fiber/config.rs b/src/fiber/config.rs index 57060c98b..894373086 100644 --- a/src/fiber/config.rs +++ b/src/fiber/config.rs @@ -189,6 +189,15 @@ pub struct FiberConfig { help = "Whether to sync the network graph from the network. [default: true]" )] pub(crate) sync_network_graph: Option, + + /// The interval to check watchtower, in seconds. 0 means never check. [default: 60 (1 minute)] + #[arg( + name = "FIBER_WATCHTOWER_CHECK_INTERVAL_SECONDS", + long = "fiber-watchtower-check-interval-seconds", + env, + help = "The interval to check watchtower, in seconds. 0 means never check. [default: 60 (1 minute)]" + )] + pub watchtower_check_interval_seconds: Option, } #[derive(PartialEq, Copy, Clone, Default)] diff --git a/src/fiber/fee.rs b/src/fiber/fee.rs index caec2d67c..a42236e4f 100644 --- a/src/fiber/fee.rs +++ b/src/fiber/fee.rs @@ -90,16 +90,9 @@ pub(crate) fn shutdown_tx_size( } pub(crate) fn calculate_commitment_tx_fee(fee_rate: u64, udt_type_script: &Option