diff --git a/Cargo.lock b/Cargo.lock index 6db90da..66cd371 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,24 +11,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi", -] - [[package]] name = "anstream" version = "0.6.21" @@ -97,23 +79,6 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - [[package]] name = "axum" version = "0.8.8" @@ -168,12 +133,11 @@ dependencies = [ [[package]] name = "base58ck" -version = "0.1.0" +version = "0.1.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" +checksum = "365c0acd5b2e8dd0111a46c4faea83fb3cfb6e39a49a7c73a06e090db7b2eff0" dependencies = [ - "bitcoin-internals", - "bitcoin_hashes", + "bitcoin_hashes 0.14.101", ] [[package]] @@ -188,65 +152,61 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "base64-compat" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a8d4d2746f89841e49230dd26917df1876050f95abafafbe34f47cb534b88d7" -dependencies = [ - "byteorder", -] - [[package]] name = "bech32" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32637268377fc7b10a8c6d51de3e7fba1ce5dd371a96e342b34e6078db558e7f" -[[package]] -name = "bip39" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90dbd31c98227229239363921e60fcf5e558e43ec69094d46fc4996f08d1d5bc" -dependencies = [ - "bitcoin_hashes", - "serde", - "unicode-normalization", -] - [[package]] name = "bitcoin" -version = "0.32.8" +version = "0.32.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e499f9fc0407f50fe98af744ab44fa67d409f76b6772e1689ec8485eb0c0f66" +checksum = "bb0ce8bd5baaa0d303a19915a6d93afed161f528654e42da2a7a97d05c59499a" dependencies = [ "base58ck", "base64 0.21.7", "bech32", - "bitcoin-internals", + "bitcoin-consensus-encoding", "bitcoin-io", "bitcoin-units", - "bitcoin_hashes", - "hex-conservative", + "bitcoin_hashes 0.14.101", + "hex-conservative 0.2.2", "hex_lit", "secp256k1", - "serde", ] [[package]] -name = "bitcoin-internals" -version = "0.3.0" +name = "bitcoin-consensus-encoding" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" +checksum = "9daa31138eb443d5751b207f3f64154e2bb09cd59960562ccc7a7112be38147f" dependencies = [ + "bitcoin-internals 0.7.0", + "hex-conservative 1.3.0", "serde", ] +[[package]] +name = "bitcoin-internals" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d573f4cf32996a8dce612e4348cece65a241f1882ed594047c9ba348e8869fa5" + +[[package]] +name = "bitcoin-internals" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8bea3a9f0cfece4564e37cb49a38cc245ca5184719e50d7d0dda3268722c4e2" + [[package]] name = "bitcoin-io" -version = "0.1.4" +version = "0.1.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" +checksum = "bb5de036369d1ac59d3c1819ebc4d850f89466f5401c571a285b6ed564a4cb78" +dependencies = [ + "bitcoin-consensus-encoding", +] [[package]] name = "bitcoin-private" @@ -256,23 +216,32 @@ checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" [[package]] name = "bitcoin-units" -version = "0.1.2" +version = "0.1.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2" +checksum = "9cb95693f371d089a4b5b6fc41c6f3ea6e01ee8c15388335dfac8ea685173b51" dependencies = [ - "bitcoin-internals", - "serde", + "bitcoin-consensus-encoding", ] [[package]] name = "bitcoin_hashes" -version = "0.14.1" +version = "0.14.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b" +checksum = "bca4c7abb40c8817d77403c880988cfd484f23ab2365726afb2f798363e2c4a2" dependencies = [ "bitcoin-io", - "hex-conservative", - "serde", + "hex-conservative 0.2.2", +] + +[[package]] +name = "bitcoin_hashes" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5304e53726dbe5f93141535e102ed97b5bf4714fbecefdda8f9fb98d7fdaff0e" +dependencies = [ + "bitcoin-consensus-encoding", + "bitcoin-internals 0.6.0", + "hex-conservative 1.3.0", ] [[package]] @@ -321,35 +290,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "chrono" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" -dependencies = [ - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-link", -] - -[[package]] -name = "clap" -version = "2.33.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" -dependencies = [ - "ansi_term", - "atty", - "bitflags 1.3.2", - "strsim 0.8.0", - "textwrap", - "unicode-width", - "vec_map", -] - [[package]] name = "clap" version = "4.5.53" @@ -369,7 +309,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.1", + "strsim", ] [[package]] @@ -395,13 +335,13 @@ name = "cli" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.5.53", + "clap", "core", - "hal-simplicity", - "hex 0.4.3", + "hex", "reqwest", "serde", "serde_json", + "simplicity-lang", ] [[package]] @@ -414,9 +354,9 @@ checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" name = "core" version = "0.1.0" dependencies = [ - "hal-simplicity", - "hex 0.4.3", + "hex", "hex-literal", + "simplicity-lang", "thiserror", ] @@ -456,7 +396,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.11.1", + "strsim", "syn", ] @@ -484,15 +424,17 @@ dependencies = [ [[package]] name = "elements" -version = "0.25.2" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b2569d3495bfdfce36c504fd4d78752ff4a7699f8a33e6f3ee523bddf9f6ad" +checksum = "34e00f7ddcd826d2f4c9bd72d79a6b6991a0ac4286e7e2b2ff8eecd130549073" dependencies = [ "bech32", "bitcoin", + "bitcoin-consensus-encoding", + "bitcoin-internals 0.6.0", + "bitcoin_hashes 1.2.0", + "hex-conservative 1.3.0", "secp256k1-zkp", - "serde", - "serde_json", ] [[package]] @@ -526,16 +468,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" -[[package]] -name = "fern" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e69ab0d5aca163e388c3a49d284fed6c3d0810700e77c5ae2756a50ec1a4daaa" -dependencies = [ - "chrono", - "log", -] - [[package]] name = "find-msvc-tools" version = "0.1.5" @@ -663,64 +595,13 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.12.1", + "indexmap", "slab", "tokio", "tokio-util", "tracing", ] -[[package]] -name = "hal" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f57a34f3cc18f2967a98c61abea03b1b9521075e880b18f45b63561a88c3c174" -dependencies = [ - "base64-compat", - "bip39", - "bitcoin", - "byteorder", - "chrono", - "clap 2.33.3", - "fern", - "hex 0.3.2", - "jobserver", - "lazy_static", - "lightning-invoice", - "log", - "miniscript", - "secp256k1", - "serde", - "serde_json", - "serde_yaml", - "shell-escape", -] - -[[package]] -name = "hal-simplicity" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a540615bef9124e283bbd087e007af922c9f6cfac210412bda4d1c34b2a74d" -dependencies = [ - "clap 2.33.3", - "elements", - "fern", - "hal", - "hex 0.3.2", - "log", - "serde", - "serde_json", - "serde_yaml", - "simplicity-lang", - "thiserror", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.16.1" @@ -733,21 +614,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hex" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" - [[package]] name = "hex" version = "0.4.3" @@ -763,6 +629,15 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "hex-conservative" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271e0d19bcb473b6675739a2b536076b24a082316cb5199ad918edce10c599e8" +dependencies = [ + "arrayvec", +] + [[package]] name = "hex-literal" version = "1.1.0" @@ -916,30 +791,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "iana-time-zone" -version = "0.1.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - [[package]] name = "icu_collections" version = "2.1.1" @@ -1048,16 +899,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.12.1" @@ -1065,7 +906,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown", ] [[package]] @@ -1086,16 +927,6 @@ version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ee5b5339afb4c41626dde77b7a611bd4f2c202b897852b4bcf5d03eddc61010" -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom 0.3.4", - "libc", -] - [[package]] name = "js-sys" version = "0.3.83" @@ -1118,32 +949,6 @@ version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" -[[package]] -name = "lightning-invoice" -version = "0.33.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11209f386879b97198b2bfc9e9c1e5d42870825c6bd4376f17f95357244d6600" -dependencies = [ - "bech32", - "bitcoin", - "lightning-types", -] - -[[package]] -name = "lightning-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cd84d4e71472035903e43caded8ecc123066ce466329ccd5ae537a8d5488c7" -dependencies = [ - "bitcoin", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -1227,15 +1032,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -1513,15 +1309,6 @@ version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62049b2877bf12821e8f9ad256ee38fdc31db7387ec2d3b3f403024de2034aea" -[[package]] -name = "santiago" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de36022292bc2086eb8f55bffa460fef3475e4459b478820711f4c421feb87ec" -dependencies = [ - "regex", -] - [[package]] name = "schannel" version = "0.1.28" @@ -1537,10 +1324,9 @@ version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ - "bitcoin_hashes", + "bitcoin_hashes 0.14.101", "rand", "secp256k1-sys", - "serde", ] [[package]] @@ -1562,7 +1348,6 @@ dependencies = [ "rand", "secp256k1", "secp256k1-zkp-sys", - "serde", ] [[package]] @@ -1673,31 +1458,19 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_yaml" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" -dependencies = [ - "indexmap 1.9.3", - "ryu", - "serde", - "yaml-rust", -] - [[package]] name = "service" version = "0.1.0" dependencies = [ "axum", "base64 0.22.1", - "clap 4.5.53", + "clap", "core", - "hal-simplicity", - "hex 0.4.3", + "hex", "log", "serde", "serde_json", + "simplicity-lang", "thiserror", "tokio", "toml", @@ -1715,12 +1488,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "shell-escape" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f" - [[package]] name = "shlex" version = "1.3.0" @@ -1729,30 +1496,28 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "simplicity-lang" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e57bd4d84853974a212eab24ed89da54f49fbccf5e33e93bcd29f0a6591cd5" +checksum = "cff7b10251528d46d9cf60238267911984fedbb0948cccea98dd74fc6bf9f729" dependencies = [ "bitcoin", - "bitcoin_hashes", + "bitcoin_hashes 1.2.0", "byteorder", "elements", "getrandom 0.2.16", "ghost-cell", - "hex-conservative", + "hex-conservative 1.3.0", "miniscript", - "santiago", - "serde", "simplicity-sys", ] [[package]] name = "simplicity-sys" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bcb4e5bfc15080d67e0ce2c17d1c31bfb7521d65c86ea26ed0de72d5119d119" +checksum = "955935733b2735665b4735d9b1361eade6be4c7aea6bca2640345e4c81756f58" dependencies = [ - "bitcoin_hashes", + "bitcoin_hashes 1.2.0", "cc", ] @@ -1794,12 +1559,6 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - [[package]] name = "strsim" version = "0.11.1" @@ -1874,15 +1633,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "thiserror" version = "2.0.17" @@ -1922,21 +1672,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "tinyvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" version = "1.48.0" @@ -1992,7 +1727,7 @@ version = "0.9.10+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48" dependencies = [ - "indexmap 2.12.1", + "indexmap", "serde_core", "serde_spanned", "toml_datetime", @@ -2123,21 +1858,6 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" -[[package]] -name = "unicode-normalization" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - [[package]] name = "url" version = "2.5.7" @@ -2204,12 +1924,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "want" version = "0.3.1" @@ -2302,87 +2016,12 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -2633,15 +2272,6 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - [[package]] name = "yoke" version = "0.8.1" diff --git a/Cargo.toml b/Cargo.toml index 013125e..01edd17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ members = [ ] [workspace.dependencies] -hal-simplicity = "0.2.0" +simplicity-lang = { version = "0.9.0", features = ["base64"] } clap = { version = "4.5.53", features = ["derive"] } hex = "0.4" serde = { version = "1.0", features = ["derive"] } diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 560d840..9cda983 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -11,7 +11,7 @@ path = "src/main.rs" anyhow = "1.0" clap = { workspace = true } core = { path = "../core" } -hal-simplicity = { workspace = true } +simplicity-lang = { workspace = true } hex = { workspace = true } reqwest = { version = "0.11", features = ["blocking", "json"] } serde = { workspace = true } diff --git a/cli/src/commands/address/multisig.rs b/cli/src/commands/address/multisig.rs index 08b236f..36a8c56 100644 --- a/cli/src/commands/address/multisig.rs +++ b/cli/src/commands/address/multisig.rs @@ -1,10 +1,10 @@ use anyhow::{Context, Result}; -use hal_simplicity::bitcoin::hashes::Hash; -use hal_simplicity::{bitcoin::TapNodeHash, simplicity::elements::AddressParams}; use serde_json::json; +use simplicity::bitcoin::hashes::Hash; +use simplicity::{bitcoin::TapNodeHash, elements::AddressParams}; -use hal_simplicity::simplicity::elements::bitcoin::PublicKey; -use hal_simplicity::simplicity::{bitcoin, elements}; +use simplicity::elements::bitcoin::PublicKey; +use simplicity::{bitcoin, elements}; use simplicity_unchained_core::utils::{generate_p2tr_address_btc, generate_p2tr_address_elements}; @@ -29,7 +29,9 @@ pub fn execute( let output = execute_over_elements( &pk1, &pk2, - elements::hashes::sha256::Hash::from_slice(&user_leaf_hash_bytes)?, + elements::hashes::sha256::Hash::from_byte_array( + user_leaf_hash_bytes.as_slice().try_into()?, + ), network, )?; println!("{}", serde_json::to_string_pretty(&output)?); diff --git a/cli/src/commands/btc_tx/create.rs b/cli/src/commands/btc_tx/create.rs index a916cf3..3dd7744 100644 --- a/cli/src/commands/btc_tx/create.rs +++ b/cli/src/commands/btc_tx/create.rs @@ -1,6 +1,6 @@ use anyhow::{Context, Result, anyhow}; -use hal_simplicity::simplicity::bitcoin; +use simplicity::bitcoin; use bitcoin::{ Address, Amount, Network, OutPoint, Transaction, TxIn, TxOut, psbt::Psbt, script::ScriptBuf, diff --git a/cli/src/commands/btc_tx/finalize.rs b/cli/src/commands/btc_tx/finalize.rs index 165a8d1..ee1fb5d 100644 --- a/cli/src/commands/btc_tx/finalize.rs +++ b/cli/src/commands/btc_tx/finalize.rs @@ -1,8 +1,8 @@ use anyhow::{Context, Result, anyhow}; -use hal_simplicity::bitcoin::{ +use serde_json::json; +use simplicity::bitcoin::{ self, Psbt, TapLeafHash, Transaction, Witness, consensus::serialize, psbt, taproot::LeafVersion, }; -use serde_json::json; use simplicity_unchained_core::utils::extract_pubkeys_from_p2tr_multisig_leaf_btc; pub fn execute(psbt_hex: &str) -> Result<()> { diff --git a/cli/src/commands/btc_tx/sign.rs b/cli/src/commands/btc_tx/sign.rs index 17a796a..73a9136 100644 --- a/cli/src/commands/btc_tx/sign.rs +++ b/cli/src/commands/btc_tx/sign.rs @@ -1,11 +1,9 @@ use anyhow::{Context, Result}; -use hal_simplicity::bitcoin::taproot::{LeafVersion, TaprootBuilder}; -use hal_simplicity::bitcoin::{self, TapNodeHash}; -use hal_simplicity::simplicity::bitcoin::{ - PublicKey, hashes::Hash, psbt::Psbt, sighash::SighashCache, -}; -use hal_simplicity::simplicity::elements::secp256k1_zkp::{Message, Secp256k1, SecretKey}; use serde_json::json; +use simplicity::bitcoin::taproot::{LeafVersion, TaprootBuilder}; +use simplicity::bitcoin::{self, TapNodeHash}; +use simplicity::bitcoin::{PublicKey, hashes::Hash, psbt::Psbt, sighash::SighashCache}; +use simplicity::elements::secp256k1_zkp::{Message, Secp256k1, SecretKey}; use simplicity_unchained_core::utils::{UNSPENDABLE_KEY_P2TR, p2tr_multisig_leaf_btc}; pub fn execute( @@ -34,9 +32,9 @@ pub fn execute( let public_key = PublicKey::from_private_key( &secp, - &hal_simplicity::simplicity::elements::bitcoin::PrivateKey { + &simplicity::elements::bitcoin::PrivateKey { compressed: true, - network: hal_simplicity::simplicity::elements::bitcoin::NetworkKind::Main, + network: simplicity::elements::bitcoin::NetworkKind::Main, inner: secret_key, }, ); diff --git a/cli/src/commands/btc_tx/spend_user_leaf.rs b/cli/src/commands/btc_tx/spend_user_leaf.rs index 9198b80..e380d1b 100644 --- a/cli/src/commands/btc_tx/spend_user_leaf.rs +++ b/cli/src/commands/btc_tx/spend_user_leaf.rs @@ -9,10 +9,10 @@ use bitcoin::{ sighash::{Prevouts, SighashCache}, taproot::{LeafVersion, Signature as TapSig}, }; -use hal_simplicity::bitcoin::base64::Engine; -use hal_simplicity::bitcoin::hashes::Hash; -use hal_simplicity::bitcoin::{self, base64}; use serde_json::json; +use simplicity::bitcoin::base64::Engine; +use simplicity::bitcoin::hashes::Hash; +use simplicity::bitcoin::{self, base64}; use simplicity_unchained_core::utils::{UNSPENDABLE_KEY_P2TR, p2tr_multisig_leaf_btc}; use std::str::FromStr; diff --git a/cli/src/commands/tx/create.rs b/cli/src/commands/tx/create.rs index 63637e5..95b119f 100644 --- a/cli/src/commands/tx/create.rs +++ b/cli/src/commands/tx/create.rs @@ -1,6 +1,6 @@ use anyhow::{Context, Result, anyhow}; -use hal_simplicity::simplicity::elements; +use simplicity::elements; use elements::{ Address, AddressParams, AssetId, OutPoint, Transaction, TxIn, TxOut, confidential, diff --git a/cli/src/commands/tx/finalize.rs b/cli/src/commands/tx/finalize.rs index 509b4ef..dfc6f4a 100644 --- a/cli/src/commands/tx/finalize.rs +++ b/cli/src/commands/tx/finalize.rs @@ -1,11 +1,11 @@ use anyhow::{Context, Result, anyhow}; -use hal_simplicity::simplicity::elements::taproot::TapLeafHash; -use hal_simplicity::simplicity::elements::{ +use serde_json::json; +use simplicity::elements::taproot::TapLeafHash; +use simplicity::elements::{ Transaction, encode::{deserialize, serialize}, pset::{self, PartiallySignedTransaction}, }; -use serde_json::json; use simplicity_unchained_core::utils::extract_pubkeys_from_p2tr_multisig_leaf_elements; pub fn execute(pset_hex: &str) -> Result<()> { @@ -94,7 +94,8 @@ fn finalize_p2tr(tx: &mut Transaction, i: usize, input: &pset::Input) -> Result< cosigner_sig.to_vec(), leaf_script.to_bytes(), control_block.serialize(), - ]; + ] + .into(); Ok(()) } diff --git a/cli/src/commands/tx/sign.rs b/cli/src/commands/tx/sign.rs index 945d4bf..3bab74c 100644 --- a/cli/src/commands/tx/sign.rs +++ b/cli/src/commands/tx/sign.rs @@ -1,22 +1,18 @@ use std::str::FromStr; use anyhow::{Context, Result, anyhow}; -use hal_simplicity::{ - bitcoin, - simplicity::{ - ToXOnlyPubkey, - elements::{ - self, SchnorrSig, - encode::{deserialize, serialize}, - hashes::Hash, - pset::PartiallySignedTransaction, - secp256k1_zkp::{Message, Secp256k1, SecretKey}, - sighash::{SchnorrSighashType, SighashCache}, - taproot::{LeafVersion, TaprootBuilder}, - }, +use serde_json::json; +use simplicity::{ + ToXOnlyPubkey, bitcoin, + elements::{ + self, SchnorrSig, + encode::{deserialize, serialize}, + pset::PartiallySignedTransaction, + secp256k1_zkp::{Message, Secp256k1, SecretKey}, + sighash::{SchnorrSighashType, SighashCache}, + taproot::{LeafVersion, TapNodeHash, TaprootBuilder}, }, }; -use serde_json::json; use simplicity_unchained_core::{ ElementsNetwork, utils::{UNSPENDABLE_KEY_P2TR, p2tr_multisig_leaf_elements}, @@ -54,9 +50,9 @@ pub fn execute( let public_key = bitcoin::PublicKey::from_private_key( &secp, - &hal_simplicity::simplicity::elements::bitcoin::PrivateKey { + &simplicity::elements::bitcoin::PrivateKey { compressed: true, - network: hal_simplicity::simplicity::elements::bitcoin::NetworkKind::Main, + network: simplicity::elements::bitcoin::NetworkKind::Main, inner: secret_key, }, ); @@ -68,10 +64,13 @@ pub fn execute( let multisig_leaf = p2tr_multisig_leaf_elements(&cosigner_pubkey, &public_key); - let user_leaf = elements::hashes::sha256::Hash::from_slice( - &hex::decode(user_leaf_hash_hex).context("Failed to decode user leaf hash hex")?, - ) - .context("Invalid user leaf hash")?; + let user_leaf = TapNodeHash::from_byte_array( + hex::decode(user_leaf_hash_hex) + .context("Failed to decode user leaf hash hex")? + .as_slice() + .try_into() + .context("Invalid user leaf hash")?, + ); let spend_info = TaprootBuilder::new() .add_leaf(1, multisig_leaf.clone()) diff --git a/cli/src/commands/tx/spend_user_leaf.rs b/cli/src/commands/tx/spend_user_leaf.rs index e8fcf54..3ee9479 100644 --- a/cli/src/commands/tx/spend_user_leaf.rs +++ b/cli/src/commands/tx/spend_user_leaf.rs @@ -1,17 +1,16 @@ use anyhow::{Context, Result, anyhow}; -use hal_simplicity::{ +use serde_json::json; +use simplicity::{ bitcoin::{self, key::UntweakedKeypair}, - simplicity::elements::{ + elements::{ self, SchnorrSig, encode::{deserialize, serialize}, - hashes::Hash, pset::PartiallySignedTransaction, secp256k1_zkp::{Message, Secp256k1, SecretKey}, sighash::{Prevouts, SchnorrSighashType, SighashCache}, taproot::{LeafVersion, TapLeafHash, TaprootBuilder}, }, }; -use serde_json::json; use simplicity_unchained_core::{ ElementsNetwork, utils::{UNSPENDABLE_KEY_P2TR, p2tr_multisig_leaf_elements}, diff --git a/cli/src/demo_script/csv_leaf_btc.rs b/cli/src/demo_script/csv_leaf_btc.rs index 99dccd0..a01890a 100644 --- a/cli/src/demo_script/csv_leaf_btc.rs +++ b/cli/src/demo_script/csv_leaf_btc.rs @@ -1,13 +1,13 @@ //! Timelocked user script for demo purposes use anyhow::{Context, Result, anyhow}; -use hal_simplicity::{ +use serde_json::json; +use simplicity::{ + ToXOnlyPubkey, bitcoin::{ - self, Psbt, TapLeafHash, Transaction, Witness, consensus::serialize, hashes::Hash, psbt, - taproot::LeafVersion, + self, Psbt, PublicKey, TapLeafHash, Transaction, Witness, consensus::serialize, + hashes::Hash, psbt, taproot::LeafVersion, }, - simplicity::{ToXOnlyPubkey, bitcoin::PublicKey}, }; -use serde_json::json; use std::str::FromStr; pub fn build_csv_script(user_pubkey_hex: &str, timelock: u16) -> Result<()> { diff --git a/cli/src/demo_script/csv_leaf_elements.rs b/cli/src/demo_script/csv_leaf_elements.rs index a427a9e..24cd08e 100644 --- a/cli/src/demo_script/csv_leaf_elements.rs +++ b/cli/src/demo_script/csv_leaf_elements.rs @@ -1,19 +1,16 @@ //! Timelocked user script for demo purposes use anyhow::{Context, Result, anyhow}; -use hal_simplicity::{ +use serde_json::json; +use simplicity::{ + ToXOnlyPubkey, bitcoin::PublicKey, - simplicity::{ - ToXOnlyPubkey, - elements::{ - self, - encode::{deserialize, serialize}, - hashes::Hash, - pset::{self, PartiallySignedTransaction}, - taproot::{LeafVersion, TapLeafHash}, - }, + elements::{ + self, + encode::{deserialize, serialize}, + pset::{self, PartiallySignedTransaction}, + taproot::{LeafVersion, TapLeafHash}, }, }; -use serde_json::json; pub fn build_csv_script(user_pubkey_hex: &str, timelock: u16) -> Result<()> { let user_pubkey_bytes = @@ -78,7 +75,8 @@ fn finalize_internal(tx: &mut elements::Transaction, i: usize, input: &pset::Inp sig.to_vec(), leaf_script.to_bytes(), control_block.serialize(), - ]; + ] + .into(); Ok(()) } diff --git a/core/Cargo.toml b/core/Cargo.toml index 6b7a6bc..acf6851 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -10,6 +10,6 @@ path = "src/lib.rs" [dependencies] hex-literal = "1.1.0" -hal-simplicity = { workspace = true } +simplicity-lang = { workspace = true } thiserror = { workspace = true } hex = { workspace = true } diff --git a/core/src/jets/base.rs b/core/src/jets/base.rs new file mode 100644 index 0000000..8539f6b --- /dev/null +++ b/core/src/jets/base.rs @@ -0,0 +1,99 @@ +//! Runs base jets (`Core`, `Elements`) on an [`UnchainedEnv`]. +//! +//! `JetEnvironment::c_jet_ptr` must return a plain `fn` pointer, so a base jet can't be wrapped in +//! a closure that swaps the unchained env for the base C env. Instead, every base jet gets its own +//! trampoline, a `fn` monomorphized over the jet's index in `ALL`. +use simplicity::ffi::CFrameItem; +use simplicity::jet::{Core, CoreEnv, Elements, ElementsTxEnv, Jet, JetEnvironment}; + +use super::environments::UnchainedEnv; + +/// C jet function running on an [`UnchainedEnv`]. +pub type UnchainedJetFn = fn(&mut CFrameItem, CFrameItem, &UnchainedEnv) -> bool; + +/// Upper bound on the number of jets in a base jet set, see [`fn_table`]. +const MAX_BASE_JETS: usize = 512; + +/// A base jet set together with the environment its C implementations run on. +pub trait BaseJet: Jet + Copy { + type Env: JetEnvironment; + + /// All jets of the set, indexed by [`BaseJet::index`]. + const ALL: &'static [Self]; + + /// Position of `self` inside [`BaseJet::ALL`]. + fn index(&self) -> usize; +} + +impl BaseJet for Core { + type Env = CoreEnv; + const ALL: &'static [Self] = &Core::ALL; + + fn index(&self) -> usize { + *self as usize + } +} + +impl BaseJet for Elements { + type Env = ElementsTxEnv; + const ALL: &'static [Self] = &Elements::ALL; + + fn index(&self) -> usize { + *self as usize + } +} + +/// Returns the C implementation of a base jet, adapted to run on an [`UnchainedEnv`]. +pub fn base_c_jet_ptr(jet: &J) -> UnchainedJetFn { + const { assert!(J::ALL.len() <= MAX_BASE_JETS) }; + + Trampolines::::TABLE.as_flattened().as_flattened()[jet.index()] +} + +fn trampoline( + dst: &mut CFrameItem, + src: CFrameItem, + env: &UnchainedEnv, +) -> bool { + let c_jet = ::c_jet_ptr(&J::ALL[I]); + c_jet(dst, src, env.env.c_jet_env()) +} + +/// Builds a `[[[_; 8]; 8]; 8]` table of `$f::` for every `I` below [`MAX_BASE_JETS`]. +// TODO: refactor into something less ugly, e.g. a flat table generated by a proc macro. +macro_rules! fn_table { + ($f:ident) => { + fn_table!(@a $f; 0 1 2 3 4 5 6 7) + }; + (@a $f:ident; $($a:literal)*) => { + [$(fn_table!(@b $f; $a; 0 1 2 3 4 5 6 7)),*] + }; + (@b $f:ident; $a:literal; $($b:literal)*) => { + [$(fn_table!(@c $f; $a; $b; 0 1 2 3 4 5 6 7)),*] + }; + (@c $f:ident; $a:literal; $b:literal; $($c:literal)*) => { + [$($f:: as UnchainedJetFn),*] + }; +} + +struct Trampolines(J); + +impl Trampolines { + #[allow(clippy::type_complexity)] + const TABLE: [[[UnchainedJetFn; 8]; 8]; 8] = fn_table!(trampoline); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn index_matches_position_in_all() { + for (i, jet) in Core::ALL.iter().enumerate() { + assert_eq!(jet.index(), i, "{jet}"); + } + for (i, jet) in Elements::ALL.iter().enumerate() { + assert_eq!(jet.index(), i, "{jet}"); + } + } +} diff --git a/core/src/jets/bitcoin.rs b/core/src/jets/bitcoin.rs index 54fa563..78039c5 100644 --- a/core/src/jets/bitcoin.rs +++ b/core/src/jets/bitcoin.rs @@ -1,20 +1,15 @@ -use std::collections::HashMap; use std::io::Write; use std::mem::MaybeUninit; -use std::sync::LazyLock; -use hal_simplicity::simplicity::Cmr; -use hal_simplicity::simplicity::Cost; -use hal_simplicity::simplicity::ffi::CFrameItem; -use hal_simplicity::simplicity::jet::type_name::TypeName; -use hal_simplicity::simplicity::jet::{Core, Jet}; -use hal_simplicity::simplicity::{BitIter, BitWriter, decode}; +use simplicity::Cmr; +use simplicity::Cost; +use simplicity::ffi::CFrameItem; +use simplicity::jet::type_name::TypeName; +use simplicity::jet::{Core, CoreEnv, Jet, JetEnvironment}; +use simplicity::{BitIter, BitWriter, decode}; -use super::environments::UnchainedEnv; - -type CJetPtr = dyn Fn(&mut CFrameItem, CFrameItem, &UnchainedEnv<()>) -> bool + Send + Sync; -static C_JET_PTRS: LazyLock> = - LazyLock::new(|| build_c_jet_ptrs()); +use super::base::base_c_jet_ptr; +use super::environments::BitcoinUnchainedEnv; // Local version of decode_bits macro that accepts expressions instead of just paths macro_rules! decode_bits { @@ -88,48 +83,30 @@ impl CoreExtension { } } -fn build_c_jet_ptrs() -> HashMap { - CoreExtension::ALL - .iter() - .map(|jet| { - let boxed: Box = match jet { - // rest of elements jets - CoreExtension::Core(inner_jet) => Box::new( - move |dst: &mut CFrameItem, src: CFrameItem, _: &UnchainedEnv<()>| -> bool { - inner_jet.c_jet_ptr()(dst, src, &()) - }, - ), - // custom jets - CoreExtension::GetOpcodeFromScript => Box::new( - move |dst: &mut CFrameItem, src: CFrameItem, env: &UnchainedEnv<()>| -> bool { - super::exec::get_opcode_from_script(dst, src, env) - }, - ), - CoreExtension::GetPubkeyFromScript => Box::new( - move |dst: &mut CFrameItem, src: CFrameItem, env: &UnchainedEnv<()>| -> bool { - super::exec::get_pubkey_from_script(dst, src, env) - }, - ), - }; - let leaked: &'static ( - dyn Fn(&mut CFrameItem, CFrameItem, &UnchainedEnv<()>) -> bool - + Send - + Sync - ) = Box::leak(boxed); - (*jet, leaked) - }) - .collect() -} -impl Jet for CoreExtension { - type Environment = UnchainedEnv<()>; - type CJetEnvironment = UnchainedEnv<()>; +impl JetEnvironment for BitcoinUnchainedEnv { + type Jet = CoreExtension; + type CJetEnvironment = Self; - fn c_jet_env(env: &Self::Environment) -> &Self::CJetEnvironment { + fn c_jet_env(&self) -> &Self::CJetEnvironment { // For the time being, we are goint to use the initial environment for unchained jets, // as we are going to implement them in rust. - env + self + } + + fn c_jet_ptr( + jet: &Self::Jet, + ) -> fn(&mut CFrameItem, CFrameItem, &Self::CJetEnvironment) -> bool { + match jet { + // rest of elements jets + CoreExtension::Core(inner_jet) => base_c_jet_ptr(inner_jet), + // custom jets + CoreExtension::GetOpcodeFromScript => super::exec::get_opcode_from_script::, + CoreExtension::GetPubkeyFromScript => super::exec::get_pubkey_from_script::, + } } +} +impl Jet for CoreExtension { fn cmr(&self) -> Cmr { if let CoreExtension::Core(inner_jet) = self { return inner_jet.cmr(); @@ -180,7 +157,7 @@ impl Jet for CoreExtension { TypeName(name) } - fn encode(&self, w: &mut BitWriter) -> std::io::Result { + fn encode(&self, w: &mut BitWriter<&mut dyn Write>) -> std::io::Result { if let CoreExtension::Core(inner_jet) = self { return inner_jet.encode(w); } @@ -257,12 +234,6 @@ impl Jet for CoreExtension { try_custom } - fn c_jet_ptr(&self) -> &dyn Fn(&mut CFrameItem, CFrameItem, &Self::CJetEnvironment) -> bool { - C_JET_PTRS - .get(self) - .expect("All enum variants should be initialized") - } - fn cost(&self) -> Cost { if let CoreExtension::Core(inner_jet) = self { return inner_jet.cost(); @@ -275,6 +246,10 @@ impl Jet for CoreExtension { _ => unreachable!(), } } + + fn parse(s: &str) -> Result { + s.parse() + } } impl std::fmt::Display for CoreExtension { @@ -288,7 +263,7 @@ impl std::fmt::Display for CoreExtension { } impl std::str::FromStr for CoreExtension { - type Err = hal_simplicity::simplicity::Error; + type Err = simplicity::Error; fn from_str(s: &str) -> Result { match s { diff --git a/core/src/jets/elements.rs b/core/src/jets/elements.rs index b97b9bd..c389274 100644 --- a/core/src/jets/elements.rs +++ b/core/src/jets/elements.rs @@ -1,26 +1,15 @@ -use std::collections::HashMap; use std::io::Write; use std::mem::MaybeUninit; -use std::sync::Arc; -use std::sync::LazyLock; -use hal_simplicity::simplicity::Cmr; -use hal_simplicity::simplicity::Cost; -use hal_simplicity::simplicity::ffi::CFrameItem; -use hal_simplicity::simplicity::jet::type_name::TypeName; -use hal_simplicity::simplicity::jet::{Elements, Jet}; -use hal_simplicity::simplicity::{BitIter, BitWriter, decode}; +use simplicity::Cmr; +use simplicity::Cost; +use simplicity::ffi::CFrameItem; +use simplicity::jet::type_name::TypeName; +use simplicity::jet::{Elements, ElementsTxEnv, Jet, JetEnvironment}; +use simplicity::{BitIter, BitWriter, decode}; -use hal_simplicity::simplicity::elements::Transaction; -use hal_simplicity::simplicity::jet::elements::ElementsEnv; - -use super::environments::UnchainedEnv; - -type CJetPtr = dyn Fn(&mut CFrameItem, CFrameItem, &UnchainedEnv>>) -> bool - + Send - + Sync; -static C_JET_PTRS: LazyLock> = - LazyLock::new(|| build_c_jet_ptrs()); +use super::base::base_c_jet_ptr; +use super::environments::ElementsUnchainedEnv; // Local version of decode_bits macro that accepts expressions instead of just paths macro_rules! decode_bits { @@ -94,87 +83,47 @@ impl ElementsExtension { } } -fn build_c_jet_ptrs() -> HashMap { - ElementsExtension::ALL - .iter() - .map(|jet| { - let boxed: Box = match jet { - // hijacked elements jets - ElementsExtension::Elements(Elements::CheckLockDuration) => Box::new( - move |dst: &mut CFrameItem, - src: CFrameItem, - env: &UnchainedEnv>>| - -> bool { - super::exec::check_lock_duration(dst, src, env) - }, - ), - ElementsExtension::Elements(Elements::CheckLockDistance) => Box::new( - move |dst: &mut CFrameItem, - src: CFrameItem, - env: &UnchainedEnv>>| - -> bool { - super::exec::check_lock_distance(dst, src, env) - }, - ), - ElementsExtension::Elements(Elements::TxLockDuration) => Box::new( - move |dst: &mut CFrameItem, - src: CFrameItem, - env: &UnchainedEnv>>| - -> bool { - super::exec::tx_lock_duration(dst, src, env) - }, - ), - ElementsExtension::Elements(Elements::TxLockDistance) => Box::new( - move |dst: &mut CFrameItem, - src: CFrameItem, - env: &UnchainedEnv>>| - -> bool { - super::exec::tx_lock_distance(dst, src, env) - }, - ), - // rest of elements jets - ElementsExtension::Elements(inner_jet) => Box::new( - move |dst: &mut CFrameItem, - src: CFrameItem, - env: &UnchainedEnv>>| - -> bool { - inner_jet.c_jet_ptr()(dst, src, env.env.c_tx_env()) - }, - ), - // custom jets - ElementsExtension::GetOpcodeFromScript => Box::new( - move |dst: &mut CFrameItem, - src: CFrameItem, - env: &UnchainedEnv>>| - -> bool { - super::exec::get_opcode_from_script(dst, src, env) - }, - ), - ElementsExtension::GetPubkeyFromScript => Box::new( - move |dst: &mut CFrameItem, - src: CFrameItem, - env: &UnchainedEnv>>| - -> bool { - super::exec::get_pubkey_from_script(dst, src, env) - }, - ), - }; - let leaked: &'static CJetPtr = Box::leak(boxed); - (*jet, leaked) - }) - .collect() -} - -impl Jet for ElementsExtension { - type Environment = UnchainedEnv>>; - type CJetEnvironment = UnchainedEnv>>; +impl JetEnvironment for ElementsUnchainedEnv { + type Jet = ElementsExtension; + type CJetEnvironment = Self; - fn c_jet_env(env: &Self::Environment) -> &Self::CJetEnvironment { + fn c_jet_env(&self) -> &Self::CJetEnvironment { // For the time being, we are goint to use the initial environment for unchained jets, // as we are going to implement them in rust. - env + self + } + + fn c_jet_ptr( + jet: &Self::Jet, + ) -> fn(&mut CFrameItem, CFrameItem, &Self::CJetEnvironment) -> bool { + match jet { + // hijacked elements jets + ElementsExtension::Elements(Elements::BrokenDoNotUseCheckLockDuration) => { + super::exec::check_lock_duration + } + ElementsExtension::Elements(Elements::BrokenDoNotUseCheckLockDistance) => { + super::exec::check_lock_distance + } + ElementsExtension::Elements(Elements::BrokenDoNotUseTxLockDuration) => { + super::exec::tx_lock_duration + } + ElementsExtension::Elements(Elements::BrokenDoNotUseTxLockDistance) => { + super::exec::tx_lock_distance + } + // rest of elements jets + ElementsExtension::Elements(inner_jet) => base_c_jet_ptr(inner_jet), + // custom jets + ElementsExtension::GetOpcodeFromScript => { + super::exec::get_opcode_from_script:: + } + ElementsExtension::GetPubkeyFromScript => { + super::exec::get_pubkey_from_script:: + } + } } +} +impl Jet for ElementsExtension { fn cmr(&self) -> Cmr { if let ElementsExtension::Elements(inner_jet) = self { return inner_jet.cmr(); @@ -225,7 +174,7 @@ impl Jet for ElementsExtension { TypeName(name) } - fn encode(&self, w: &mut BitWriter) -> std::io::Result { + fn encode(&self, w: &mut BitWriter<&mut dyn Write>) -> std::io::Result { if let ElementsExtension::Elements(inner_jet) = self { return inner_jet.encode(w); } @@ -302,12 +251,6 @@ impl Jet for ElementsExtension { try_custom } - fn c_jet_ptr(&self) -> &dyn Fn(&mut CFrameItem, CFrameItem, &Self::CJetEnvironment) -> bool { - C_JET_PTRS - .get(self) - .expect("All enum variants should be initialized") - } - fn cost(&self) -> Cost { if let ElementsExtension::Elements(inner_jet) = self { return inner_jet.cost(); @@ -320,6 +263,10 @@ impl Jet for ElementsExtension { _ => unreachable!(), } } + + fn parse(s: &str) -> Result { + s.parse() + } } impl std::fmt::Display for ElementsExtension { @@ -333,7 +280,7 @@ impl std::fmt::Display for ElementsExtension { } impl std::str::FromStr for ElementsExtension { - type Err = hal_simplicity::simplicity::Error; + type Err = simplicity::Error; fn from_str(s: &str) -> Result { match s { diff --git a/core/src/jets/environments.rs b/core/src/jets/environments.rs index 391f7ea..80b2618 100644 --- a/core/src/jets/environments.rs +++ b/core/src/jets/environments.rs @@ -1,12 +1,8 @@ -use std::sync::Arc; +use simplicity::elements::script::Script; +use simplicity::jet::{CoreEnv, ElementsTxEnv}; -use hal_simplicity::simplicity::ffi::CElementsTxEnv; -use hal_simplicity::simplicity::jet::elements::ElementsEnv; - -use hal_simplicity::simplicity::elements::{Transaction, script::Script}; - -pub type BitcoinUnchainedEnv = UnchainedEnv<()>; -pub type ElementsUnchainedEnv = UnchainedEnv>>; +pub type BitcoinUnchainedEnv = UnchainedEnv; +pub type ElementsUnchainedEnv = UnchainedEnv; pub struct UnchainedEnv { pub redeem_script: Script, @@ -18,15 +14,3 @@ impl UnchainedEnv { Self { redeem_script, env } } } - -impl<'a> From<&'a ElementsUnchainedEnv> for &'a CElementsTxEnv { - fn from(value: &'a ElementsUnchainedEnv) -> Self { - value.env.c_tx_env() - } -} - -impl<'a> From<&'a BitcoinUnchainedEnv> for &'a () { - fn from(value: &'a BitcoinUnchainedEnv) -> Self { - &value.env - } -} diff --git a/core/src/jets/exec.rs b/core/src/jets/exec.rs index a1cbca4..21e0adc 100644 --- a/core/src/jets/exec.rs +++ b/core/src/jets/exec.rs @@ -1,23 +1,27 @@ -use hal_simplicity::simplicity::{ +use simplicity::{ elements::{Transaction, opcodes::all::OP_PUSHBYTES_33}, ffi::CFrameItem, + ffi::c_jets::frame_ffi::{c_readBit, c_writeBit}, }; use crate::jets::environments::ElementsUnchainedEnv; use super::environments::UnchainedEnv; -#[allow(unused)] -unsafe extern "C" { - fn rustsimplicity_0_6_write8(dst: *mut CFrameItem, n: u64); - fn rustsimplicity_0_6_write16(dst: *mut CFrameItem, n: u16); - fn rustsimplicity_0_6_write32(dst: *mut CFrameItem, n: u32); - fn rustsimplicity_0_6_write64(dst: *mut CFrameItem, n: u64); - - fn rustsimplicity_0_6_read8(src: *const CFrameItem) -> u64; - fn rustsimplicity_0_6_read16(src: *const CFrameItem) -> u16; - fn rustsimplicity_0_6_read32(src: *const CFrameItem) -> u32; - fn rustsimplicity_0_6_read64(src: *const CFrameItem) -> u64; +/// Reads a big-endian `n`-bit value from a C read frame. +fn read_bits(src: &mut CFrameItem, n: u32) -> u64 { + let mut value = 0; + for _ in 0..n { + value = (value << 1) | u64::from(unsafe { c_readBit(src) }); + } + value +} + +/// Writes the low `n` bits of `value`, big-endian, to a C write frame. +fn write_bits(dst: &mut CFrameItem, value: u64, n: u32) { + for i in (0..n).rev() { + unsafe { c_writeBit(dst, (value >> i) & 1 == 1) }; + } } /// 2^8 |- 2^8 @@ -25,19 +29,17 @@ unsafe extern "C" { /// Returns the opcode at the given index in the redeem script, each opcode is one byte. pub fn get_opcode_from_script( dst: &mut CFrameItem, - src: CFrameItem, + mut src: CFrameItem, env: &UnchainedEnv, ) -> bool { - let index = unsafe { rustsimplicity_0_6_read8(&src as *const CFrameItem) } as usize; + let index = read_bits(&mut src, 8) as usize; if index >= env.redeem_script.len() { return false; } let opcode = env.redeem_script.as_bytes()[index]; - unsafe { - rustsimplicity_0_6_write8(dst as *mut CFrameItem, opcode as u64); - } + write_bits(dst, opcode.into(), 8); true } @@ -46,10 +48,10 @@ pub fn get_opcode_from_script( /// Each pubkey is encoded as: [OP_PUSHBYTES_33][0x02 or 0x03][32 bytes X coordinate] pub fn get_pubkey_from_script( dst: &mut CFrameItem, - src: CFrameItem, + mut src: CFrameItem, env: &UnchainedEnv, ) -> bool { - let start_index = unsafe { rustsimplicity_0_6_read8(&src as *const CFrameItem) } as usize; + let start_index = read_bits(&mut src, 8) as usize; if start_index + 34 > env.redeem_script.len() { return false; } @@ -74,9 +76,7 @@ pub fn get_pubkey_from_script( .collect::>(); for word in words.iter() { - unsafe { - rustsimplicity_0_6_write32(dst as *mut CFrameItem, *word); - } + write_bits(dst, (*word).into(), 32); } true @@ -87,7 +87,7 @@ pub fn get_pubkey_from_script( /// 2^16 |- ONE pub fn check_lock_duration( _dst: &mut CFrameItem, - src: CFrameItem, + mut src: CFrameItem, env: &ElementsUnchainedEnv, ) -> bool { let (tx, ix) = (env.env.tx(), env.env.ix()); @@ -96,14 +96,14 @@ pub fn check_lock_duration( return false; } - let req_duration = unsafe { rustsimplicity_0_6_read16(&src as *const CFrameItem) }; + let req_duration = read_bits(&mut src, 16) as u16; req_duration <= lock_duration(tx, ix) } /// 2^16 |- ONE pub fn check_lock_distance( _dst: &mut CFrameItem, - src: CFrameItem, + mut src: CFrameItem, env: &ElementsUnchainedEnv, ) -> bool { let (tx, ix) = (env.env.tx(), env.env.ix()); @@ -112,7 +112,7 @@ pub fn check_lock_distance( return false; } - let req_distance = unsafe { rustsimplicity_0_6_read16(&src as *const CFrameItem) }; + let req_distance = read_bits(&mut src, 16) as u16; req_distance <= lock_distance(tx, ix) } @@ -128,7 +128,7 @@ pub fn tx_lock_duration( return false; } - unsafe { rustsimplicity_0_6_write16(dst, lock_duration(tx, ix)) }; + write_bits(dst, lock_duration(tx, ix).into(), 16); true } @@ -144,7 +144,7 @@ pub fn tx_lock_distance( return false; } - unsafe { rustsimplicity_0_6_write16(dst, lock_distance(tx, ix)) }; + write_bits(dst, lock_distance(tx, ix).into(), 16); true } diff --git a/core/src/jets/mod.rs b/core/src/jets/mod.rs index a66019c..1bc69a0 100644 --- a/core/src/jets/mod.rs +++ b/core/src/jets/mod.rs @@ -1,3 +1,4 @@ +pub mod base; pub mod bitcoin; pub mod elements; pub mod environments; @@ -8,31 +9,29 @@ mod tests { use std::ptr; use std::sync::Arc; - use hal_simplicity::simplicity::Cmr; - use hal_simplicity::simplicity::elements::taproot::ControlBlock; - use hal_simplicity::simplicity::elements::{ + use hex_literal::hex; + use simplicity::Cmr; + use simplicity::elements::taproot::ControlBlock; + use simplicity::elements::{ AssetIssuance, BlockHash, LockTime, OutPoint, Sequence, Transaction, TxIn, TxInWitness, - hashes::Hash, }; - use hal_simplicity::simplicity::jet::elements::ElementsEnv; - use hex_literal::hex; + use simplicity::jet::elements::ElementsEnv; - use crate::jets::environments::UnchainedEnv; + use crate::jets::environments::{ElementsUnchainedEnv, UnchainedEnv}; use crate::jets::{bitcoin::CoreExtension, elements::ElementsExtension}; - use hal_simplicity::simplicity::elements::Script; - use hal_simplicity::simplicity::elements::hex::FromHex; - use hal_simplicity::simplicity::elements::opcodes::all::OP_PUSHNUM_2; - use hal_simplicity::simplicity::ffi::CFrameItem; - use hal_simplicity::simplicity::ffi::c_jets::c_frame::uword_width; - use hal_simplicity::simplicity::ffi::ffi::UWORD; - use hal_simplicity::simplicity::jet::Jet; - use hal_simplicity::simplicity::{BitIter, BitWriter}; + use simplicity::elements::Script; + use simplicity::elements::opcodes::all::OP_PUSHNUM_2; + use simplicity::ffi::CFrameItem; + use simplicity::ffi::c_jets::c_frame::uword_width; + use simplicity::ffi::ffi::UWORD; + use simplicity::jet::{Jet, JetEnvironment}; + use simplicity::{BitIter, BitWriter}; #[test] fn test_new_jets_decode() { for expected_jet in ElementsExtension::ALL { let mut source = vec![]; - let mut writer = BitWriter::new(&mut source); + let mut writer = BitWriter::new(&mut source as &mut dyn std::io::Write); let _ = expected_jet.encode(&mut writer).unwrap(); @@ -48,7 +47,7 @@ mod tests { for expected_jet in CoreExtension::ALL { let mut source = vec![]; - let mut writer = BitWriter::new(&mut source); + let mut writer = BitWriter::new(&mut source as &mut dyn std::io::Write); let _ = expected_jet.encode(&mut writer).unwrap(); @@ -65,7 +64,7 @@ mod tests { #[test] fn test_get_opcode() { - let script = Script::from_hex( + let script = Script::from_hex_no_prefix( "5221033523982d58e94be3b735731593f8225043880d53727235b566c515d24a0f7baf21025eb4655feae15a304653e27441ca8e8ced2bef89c22ab6b20424b4c07b3d14cc52ae" ).unwrap(); @@ -82,7 +81,7 @@ mod tests { let mut dst_frame = CFrameItem::new_write(8, dst_data.as_mut_ptr().add(output_uwords)); let jet = ElementsExtension::GetOpcodeFromScript; - let jet_fn = jet.c_jet_ptr(); + let jet_fn = ElementsUnchainedEnv::c_jet_ptr(&jet); let result = jet_fn(&mut dst_frame, src_frame, &env); assert!(result); @@ -99,7 +98,7 @@ mod tests { #[test] fn test_get_pubkey_from_script() { - let script = Script::from_hex( + let script = Script::from_hex_no_prefix( "5221033523982d58e94be3b735731593f8225043880d53727235b566c515d24a0f7baf21025eb4655feae15a304653e27441ca8e8ced2bef89c22ab6b20424b4c07b3d14cc52ae" ).unwrap(); @@ -118,7 +117,7 @@ mod tests { CFrameItem::new_write(OUTPUT_BITS, dst_data.as_mut_ptr().add(output_uwords)); let jet = ElementsExtension::GetPubkeyFromScript; - let jet_fn = jet.c_jet_ptr(); + let jet_fn = ElementsUnchainedEnv::c_jet_ptr(&jet); let result = jet_fn(&mut dst_frame, src_frame, &env); assert!(result); @@ -168,7 +167,7 @@ mod tests { Cmr::from_byte_array([0; 32]), ControlBlock::from_slice(&ctrl_blk).unwrap(), None, - BlockHash::all_zeros(), + BlockHash::from_byte_array([0; 32]), ) } } diff --git a/core/src/lib.rs b/core/src/lib.rs index e76d265..7347029 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,10 +1,10 @@ use std::str::FromStr; -use hal_simplicity::bitcoin::NetworkKind; -use hal_simplicity::simplicity::elements::BlockHash; -use hal_simplicity::simplicity::elements::hashes::Hash; +use simplicity::bitcoin::NetworkKind; +use simplicity::elements::BlockHash; pub mod jets; +pub mod program; pub mod runner; pub mod utils; diff --git a/core/src/program.rs b/core/src/program.rs new file mode 100644 index 0000000..ff7e5a8 --- /dev/null +++ b/core/src/program.rs @@ -0,0 +1,69 @@ +use std::marker::PhantomData; +use std::sync::Arc; + +use simplicity::base64::prelude::{BASE64_STANDARD, Engine as _}; +use simplicity::jet::Jet; +use simplicity::{BitIter, Cmr, CommitNode, ParseError, RedeemNode}; + +/// A Simplicity program decoded with jets of type `J`. +/// +/// Port of `hal_simplicity::Program`. +pub struct Program { + commit_prog: Arc, + redeem_prog: Option>, + _jet: PhantomData J>, +} + +impl Program { + /// Decodes a program and an optional witness, each given as hex or base64. + pub fn from_str(prog: &str, witness: Option<&str>) -> Result { + let prog_bytes = hex_or_base64(prog)?; + let commit_prog = CommitNode::decode::<_, J>(BitIter::new(prog_bytes.iter().copied())) + .map_err(ParseError::Decode)?; + + let redeem_prog = witness + .map(|witness| { + let wit_bytes = hex_or_base64(witness)?; + RedeemNode::decode::<_, _, J>( + BitIter::new(prog_bytes.into_iter()), + BitIter::new(wit_bytes.into_iter()), + ) + .map_err(ParseError::Decode) + }) + .transpose()?; + + Ok(Self { + commit_prog, + redeem_prog, + _jet: PhantomData, + }) + } + + /// The CMR of the program. + pub fn cmr(&self) -> Cmr { + self.commit_prog.cmr() + } + + /// The commitment-time program. + pub fn commit_prog(&self) -> &CommitNode { + &self.commit_prog + } + + /// The redemption-time program, if a witness was given. + pub fn redeem_node(&self) -> Option<&Arc> { + self.redeem_prog.as_ref() + } +} + +/// Same detection as `hal_simplicity::hex_or_base64`, kept so that existing inputs decode to the +/// same programs: hex only when every char is a lowercase hex letter, base64 otherwise. +fn hex_or_base64(s: &str) -> Result, ParseError> { + if s.len().is_multiple_of(2) + && s.bytes() + .all(|b| b.is_ascii_hexdigit() && b.is_ascii_lowercase()) + { + simplicity::hex::decode_to_vec(s).map_err(ParseError::Hex) + } else { + BASE64_STANDARD.decode(s).map_err(ParseError::Base64) + } +} diff --git a/core/src/runner.rs b/core/src/runner.rs index d82546b..8a5412c 100644 --- a/core/src/runner.rs +++ b/core/src/runner.rs @@ -1,15 +1,15 @@ use std::sync::Arc; -use hal_simplicity::hal_simplicity::Program; -use hal_simplicity::simplicity::BitMachine; -use hal_simplicity::simplicity::bit_machine::ExecutionError; -use hal_simplicity::simplicity::bitcoin::psbt; -use hal_simplicity::simplicity::elements::taproot::{LeafVersion, TaprootMerkleBranch}; -use hal_simplicity::simplicity::elements::{BlockHash, Script}; -use hal_simplicity::simplicity::elements::{Transaction, pset, schnorr::UntweakedPublicKey}; -use hal_simplicity::simplicity::{ +use simplicity::BitMachine; +use simplicity::bit_machine::ExecutionError; +use simplicity::bitcoin::psbt; +use simplicity::elements::taproot::{LeafVersion, TaprootMerkleBranch}; +use simplicity::elements::{BlockHash, Script}; +use simplicity::elements::{Transaction, pset, schnorr::UntweakedPublicKey}; +use simplicity::{ Cmr, elements::taproot::ControlBlock, + jet::CoreEnv, jet::elements::{ElementsEnv, ElementsUtxo}, }; @@ -18,6 +18,7 @@ use hex_literal::hex; use crate::jets::bitcoin::CoreExtension; use crate::jets::elements::ElementsExtension; use crate::jets::environments::UnchainedEnv; +use crate::program::Program; use crate::{BitcoinNetwork, ElementsNetwork}; pub struct SimplicityRunner; @@ -27,26 +28,23 @@ pub enum RunnerError { #[error("input index {index} out-of-range for PSET with {total} inputs")] InputIndexOutOfRange { index: usize, total: usize }, - #[error("failed to parse genesis hash: {0}")] - GenesisHashParse(hal_simplicity::simplicity::elements::hashes::hex::HexToArrayError), - #[error("could not find Simplicity leaf in PSET taptree with CMR {cmr})")] MissingSimplicityLeaf { cmr: String }, #[error("failed to extract transaction from PSET: {0}")] - PsetExtract(hal_simplicity::simplicity::elements::pset::Error), + PsetExtract(simplicity::elements::pset::Error), #[error("witness_utxo field not populated for input {0}")] MissingWitnessUtxo(usize), #[error("invalid program: {0}")] - ProgramParse(hal_simplicity::simplicity::ParseError), + ProgramParse(simplicity::ParseError), #[error("program does not have a redeem node")] NoRedeemNode, #[error("failed to construct bit machine: {0}")] - BitMachineConstruction(hal_simplicity::simplicity::bit_machine::LimitError), + BitMachineConstruction(simplicity::bit_machine::LimitError), #[error("execution error: {0}")] ExecutionError(ExecutionError), @@ -92,7 +90,7 @@ impl SimplicityRunner { let program = Program::::from_str(program, witness) .map_err(RunnerError::ProgramParse)?; - let env = UnchainedEnv::new(redeem_script, ()); + let env = UnchainedEnv::new(redeem_script, CoreEnv::new()); let redeem_node = program.redeem_node().ok_or(RunnerError::NoRedeemNode)?; @@ -154,7 +152,7 @@ fn dummy_control_block() -> ControlBlock { ControlBlock { leaf_version, internal_key, - output_key_parity: hal_simplicity::simplicity::elements::secp256k1_zkp::Parity::Even, + output_key_parity: simplicity::elements::secp256k1_zkp::Parity::Even, merkle_branch: TaprootMerkleBranch::default(), } } diff --git a/core/src/utils.rs b/core/src/utils.rs index f3c45c6..250908b 100644 --- a/core/src/utils.rs +++ b/core/src/utils.rs @@ -1,16 +1,15 @@ use std::str::FromStr; use std::sync::LazyLock; -use hal_simplicity::bitcoin::KnownHrp; -use hal_simplicity::bitcoin::taproot::TaprootSpendInfo; -use hal_simplicity::simplicity::elements::{ +use simplicity::bitcoin::KnownHrp; +use simplicity::bitcoin::taproot::TaprootSpendInfo; +use simplicity::elements::{ self, bitcoin::PublicKey, - hashes::Hash as ElementsHash, secp256k1_zkp::{Secp256k1, SecretKey, rand::rngs::OsRng}, }; -use hal_simplicity::simplicity::hashes::{HashEngine, sha256}; -use hal_simplicity::simplicity::{ToXOnlyPubkey, bitcoin}; +use simplicity::hashes::{HashEngine, sha256}; +use simplicity::{ToXOnlyPubkey, bitcoin}; use thiserror::Error; @@ -29,10 +28,14 @@ pub enum UtilsError { const SIMPLICITY_TAG_PREFIX: &[u8] = b"Simplicity\x1fCommitment\x1f"; -const JETIV: sha256::Midstate = sha256::Midstate([ - 0x95, 0x32, 0xee, 0x28, 0xcd, 0xca, 0x69, 0xde, 0xc8, 0xa0, 0xa2, 0x18, 0xb7, 0x9b, 0xe3, 0x62, - 0xf7, 0x40, 0xce, 0xaf, 0x64, 0x7f, 0x15, 0xb3, 0x8a, 0xed, 0x91, 0x68, 0x16, 0x3f, 0x92, 0x1b, -]); +const JETIV: sha256::Midstate = sha256::Midstate::new( + [ + 0x95, 0x32, 0xee, 0x28, 0xcd, 0xca, 0x69, 0xde, 0xc8, 0xa0, 0xa2, 0x18, 0xb7, 0x9b, 0xe3, + 0x62, 0xf7, 0x40, 0xce, 0xaf, 0x64, 0x7f, 0x15, 0xb3, 0x8a, 0xed, 0x91, 0x68, 0x16, 0x3f, + 0x92, 0x1b, + ], + 0, +); /// The standard NUMS internal key for Taproot outputs. /// @@ -60,7 +63,7 @@ fn cmr(name: &str) -> [u8; 32] { let right_state = sha256::Hash::hash(&name).as_byte_array().to_owned(); - let mut engine = sha256::HashEngine::from_midstate(JETIV, 0); + let mut engine = sha256::HashEngine::from_midstate(JETIV); engine.input(&right_state); right_state @@ -244,7 +247,10 @@ pub fn generate_p2tr_address_elements( let spend_info = elements::taproot::TaprootBuilder::new() .add_leaf(1, multisig_leaf) .map_err(UtilsError::TaprootBuilderErrorElements)? - .add_hidden(1, user_leaf_hash) + .add_hidden( + 1, + elements::taproot::TapNodeHash::from_byte_array(user_leaf_hash.to_byte_array()), + ) .map_err(UtilsError::TaprootBuilderErrorElements)? .finalize(&secp, *UNSPENDABLE_KEY_P2TR) .map_err(|_| UtilsError::TaprootFinalizationError)?; @@ -282,9 +288,7 @@ pub fn generate_p2tr_address_btc( #[cfg(test)] mod tests { use super::*; - use hal_simplicity::simplicity::elements::secp256k1_zkp::{ - PublicKey as Secp256k1PublicKey, Secp256k1, - }; + use simplicity::elements::secp256k1_zkp::{PublicKey as Secp256k1PublicKey, Secp256k1}; #[test] fn test_generate_keypair() { diff --git a/service/Cargo.toml b/service/Cargo.toml index 1cc1f0f..76cacac 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -18,5 +18,5 @@ tracing = "0.1" tracing-subscriber = "0.3.0" validator = { version = "0.20.0", features = ["derive"] } -hal-simplicity = { workspace = true } +simplicity-lang = { workspace = true } core = { path = "../core" } diff --git a/service/src/handlers/mod.rs b/service/src/handlers/mod.rs index 4e78817..506ec72 100644 --- a/service/src/handlers/mod.rs +++ b/service/src/handlers/mod.rs @@ -14,7 +14,7 @@ use serde::Serialize; use serde_json::json; -use hal_simplicity::simplicity::elements::secp256k1_zkp::{All, Secp256k1, SecretKey}; +use simplicity::elements::secp256k1_zkp::{All, Secp256k1, SecretKey}; use simplicity_unchained_core::{BitcoinNetwork, ElementsNetwork}; diff --git a/service/src/handlers/sign_psbt.rs b/service/src/handlers/sign_psbt.rs index d983b33..4e18fcd 100644 --- a/service/src/handlers/sign_psbt.rs +++ b/service/src/handlers/sign_psbt.rs @@ -2,15 +2,15 @@ use std::str::FromStr; use axum::{Json, extract::State, http::StatusCode, response::IntoResponse}; -use hal_simplicity::bitcoin::key::{TapTweak, TweakedKeypair, UntweakedKeypair}; -use hal_simplicity::bitcoin::sighash::{Prevouts, ScriptPath}; -use hal_simplicity::bitcoin::taproot::{LeafVersion, TaprootBuilder}; -use hal_simplicity::bitcoin::{self, TapSighashType}; -use hal_simplicity::bitcoin::{TapNodeHash, Transaction, TxOut}; +use simplicity::bitcoin::key::{TapTweak, TweakedKeypair, UntweakedKeypair}; +use simplicity::bitcoin::sighash::{Prevouts, ScriptPath}; +use simplicity::bitcoin::taproot::{LeafVersion, TaprootBuilder}; +use simplicity::bitcoin::{self, TapSighashType}; +use simplicity::bitcoin::{TapNodeHash, Transaction, TxOut}; -use hal_simplicity::simplicity::bitcoin::{hashes::Hash, psbt::Psbt, sighash::SighashCache}; +use simplicity::bitcoin::{hashes::Hash, psbt::Psbt, sighash::SighashCache}; -use hal_simplicity::simplicity::elements::secp256k1_zkp::Message; +use simplicity::elements::secp256k1_zkp::Message; use serde::{Deserialize, Serialize}; @@ -123,9 +123,9 @@ fn sign_psbt_internal( Some(str) => { let bytes = hex::decode(str) .map_err(|e| format!("Failed to decode redeem script hex: {}", e))?; - hal_simplicity::simplicity::elements::Script::from(bytes) + simplicity::elements::Script::from(bytes) } - None => hal_simplicity::simplicity::elements::Script::new(), + None => simplicity::elements::Script::new(), }; let cmr = SimplicityRunner::execute_bitcoin( @@ -252,16 +252,14 @@ mod tests { use std::sync::Arc; use super::*; - use hal_simplicity::bitcoin::{self}; - use hal_simplicity::hal_simplicity::Program; - use hal_simplicity::simplicity::bitcoin::{ + use simplicity::bitcoin::{self}; + use simplicity::bitcoin::{ NetworkKind, OutPoint, PrivateKey, Transaction, TxIn, TxOut, Txid, psbt::Psbt, script::ScriptBuf, taproot::LeafVersion, }; - use hal_simplicity::simplicity::elements::{ - secp256k1_zkp::Secp256k1, secp256k1_zkp::SecretKey, - }; + use simplicity::elements::{secp256k1_zkp::Secp256k1, secp256k1_zkp::SecretKey}; use simplicity_unchained_core::BitcoinNetwork; + use simplicity_unchained_core::program::Program; use std::str::FromStr; use simplicity_unchained_core::utils::generate_p2tr_address_btc; @@ -285,19 +283,19 @@ mod tests { .unwrap(); Transaction { - version: hal_simplicity::simplicity::bitcoin::transaction::Version::TWO, - lock_time: hal_simplicity::simplicity::bitcoin::absolute::LockTime::ZERO, + version: simplicity::bitcoin::transaction::Version::TWO, + lock_time: simplicity::bitcoin::absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint { txid: prev_txid, vout: 0, }, script_sig: ScriptBuf::new(), - sequence: hal_simplicity::simplicity::bitcoin::Sequence::MAX, + sequence: simplicity::bitcoin::Sequence::MAX, witness: Default::default(), }], output: vec![TxOut { - value: hal_simplicity::simplicity::bitcoin::Amount::from_sat(50_000), + value: simplicity::bitcoin::Amount::from_sat(50_000), script_pubkey: ScriptBuf::new(), }], } @@ -306,7 +304,7 @@ mod tests { fn create_test_psbt(tx: Transaction, script_pubkey: ScriptBuf) -> Psbt { let mut psbt = Psbt::from_unsigned_tx(tx).unwrap(); psbt.inputs[0].witness_utxo = Some(TxOut { - value: hal_simplicity::simplicity::bitcoin::Amount::from_sat(100_000), + value: simplicity::bitcoin::Amount::from_sat(100_000), script_pubkey, }); psbt diff --git a/service/src/handlers/sign_pset.rs b/service/src/handlers/sign_pset.rs index 9538b40..8c8ae79 100644 --- a/service/src/handlers/sign_pset.rs +++ b/service/src/handlers/sign_pset.rs @@ -2,9 +2,9 @@ use std::str::FromStr; use axum::{Json, extract::State, http::StatusCode, response::IntoResponse}; -use hal_simplicity::{ +use simplicity::{ bitcoin::{self}, - simplicity::elements::{ + elements::{ self, SchnorrSig, SchnorrSighashType, Transaction, TxOut, encode::Encodable, schnorr::{TapTweak, TweakedKeypair, UntweakedKeypair}, @@ -14,7 +14,7 @@ use hal_simplicity::{ }; use elements::{ - encode::deserialize, hashes::Hash, pset::PartiallySignedTransaction, secp256k1_zkp::Message, + encode::deserialize, pset::PartiallySignedTransaction, secp256k1_zkp::Message, sighash::SighashCache, }; use serde::{Deserialize, Serialize}; @@ -122,16 +122,20 @@ fn sign_pset_internal( let bytes = hex::decode(&request.user_leaf_hash_hex) .map_err(|e| format!("Failed to decode user leaf hash hex: {}", e))?; - elements::hashes::sha256::Hash::from_slice(&bytes).map_err(|e| e.to_string())? + let bytes: [u8; 32] = bytes + .as_slice() + .try_into() + .map_err(|_| format!("invalid slice length {} (expected 32)", bytes.len()))?; + elements::hashes::sha256::Hash::from_byte_array(bytes) }; let redeem_script = match request.redeem_script_hex { Some(str) => { let bytes = hex::decode(str) .map_err(|e| format!("Failed to decode redeem script hex: {}", e))?; - hal_simplicity::simplicity::elements::Script::from(bytes) + simplicity::elements::Script::from(bytes) } - None => hal_simplicity::simplicity::elements::Script::new(), + None => simplicity::elements::Script::new(), }; let cmr = SimplicityRunner::execute_elements( @@ -204,7 +208,10 @@ fn sign_p2tr( let spend_info = TaprootBuilder::new() .add_leaf(1, multisig_leaf.clone()) .map_err(|e| format!("Failed to add multisig leaf: {}", e))? - .add_hidden(1, user_leaf_hash) + .add_hidden( + 1, + TapNodeHash::from_byte_array(user_leaf_hash.to_byte_array()), + ) .map_err(|e| format!("Failed to add recovery leaf: {}", e))? .finalize(secp, *UNSPENDABLE_KEY_P2TR) .map_err(|_| "Failed to finalize taproot".to_string())?; @@ -259,9 +266,9 @@ mod tests { use super::*; use bitcoin::PublicKey; - use hal_simplicity::{ + use simplicity::{ bitcoin::{NetworkKind, PrivateKey}, - simplicity::elements::{ + elements::{ OutPoint, Transaction, TxIn, TxOut, Txid, pset::PartiallySignedTransaction as Pset, secp256k1_zkp::{Secp256k1, SecretKey}, diff --git a/service/src/handlers/tweak.rs b/service/src/handlers/tweak.rs index 459db51..c31e76b 100644 --- a/service/src/handlers/tweak.rs +++ b/service/src/handlers/tweak.rs @@ -1,16 +1,18 @@ use axum::{Json, extract::State, http::StatusCode, response::IntoResponse}; -use hal_simplicity::{ +use simplicity::{ bitcoin::{self, secp256k1}, - hal_simplicity::Program, - simplicity::elements::{self, schnorr::TapTweak}, + elements::{self, schnorr::TapTweak}, }; -use elements::{bitcoin::PublicKey, hashes::Hash}; +use bitcoin::hashes::Hash; +use elements::bitcoin::PublicKey; use serde::{Deserialize, Serialize}; use validator::Validate; +use simplicity_unchained_core::jets::bitcoin::CoreExtension; use simplicity_unchained_core::jets::elements::ElementsExtension; +use simplicity_unchained_core::program::Program; use crate::handlers::{ErrorResponse, SignerState}; @@ -84,7 +86,7 @@ fn get_tweaked_key_bitcoin( ) -> Result { // Parse Simplicity program and get CMR from commitment let cmr = { - let program = Program::::from_str(&request.program, None) + let program = Program::::from_str(&request.program, None) .map_err(|e| format!("Failed to parse program: {}", e))?; program.commit_prog().cmr() diff --git a/service/src/validation.rs b/service/src/validation.rs index 0205f9c..d29811b 100644 --- a/service/src/validation.rs +++ b/service/src/validation.rs @@ -1,4 +1,4 @@ -use hal_simplicity::bitcoin; +use simplicity::bitcoin; use validator::ValidationError; pub fn validate_hex(hex: &str) -> Result<(), ValidationError> {