diff --git a/Cargo.lock b/Cargo.lock index 3476ee6b..feffc358 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -59,171 +59,97 @@ checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" [[package]] name = "base58ck" version = "0.4.0" -source = "git+https://github.com/rust-bitcoin/rust-bitcoin?tag=bitcoin-crypto-0.2.0#11650c6c480088cc30a04e583e187cd7a84a2d8f" -dependencies = [ - "bitcoin-internals", - "bitcoin_hashes", -] - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "bech32" -version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32637268377fc7b10a8c6d51de3e7fba1ce5dd371a96e342b34e6078db558e7f" - -[[package]] -name = "bitcoin" -version = "0.33.0-beta" -source = "git+https://github.com/rust-bitcoin/rust-bitcoin?tag=bitcoin-crypto-0.2.0#11650c6c480088cc30a04e583e187cd7a84a2d8f" +checksum = "ed6a87a8367e7a4248c8dfd783c37ef492bca1307cd4b21b4cfad9cfd15bf060" dependencies = [ - "base58ck", - "base64", - "bech32", - "bitcoin-consensus-encoding", - "bitcoin-crypto", - "bitcoin-internals", - "bitcoin-io", - "bitcoin-network-kind", - "bitcoin-primitives", - "bitcoin-taproot-primitives", - "bitcoin-units", - "bitcoin_hashes", - "bitcoinconsensus", - "hex-conservative 0.3.2", - "hex-conservative 1.2.0", - "secp256k1", + "bitcoin-internals 0.5.0", + "bitcoin_hashes 0.20.0", ] [[package]] name = "bitcoin-consensus-encoding" -version = "0.2.0" -source = "git+https://github.com/rust-bitcoin/rust-bitcoin?tag=bitcoin-crypto-0.2.0#11650c6c480088cc30a04e583e187cd7a84a2d8f" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d7ca3dc8ff835693ad73bf1596240c06f974a31eeb3f611aaedf855f1f2725" dependencies = [ - "bitcoin-internals", + "bitcoin-internals 0.5.0", ] [[package]] -name = "bitcoin-crypto" -version = "0.2.0" -source = "git+https://github.com/rust-bitcoin/rust-bitcoin?tag=bitcoin-crypto-0.2.0#11650c6c480088cc30a04e583e187cd7a84a2d8f" +name = "bitcoin-consensus-encoding" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6712f9c6fd6785b3b270884e57c441c403dc5d7e19ca45368c97c7a1de3000ec" dependencies = [ - "base58ck", - "bitcoin-internals", - "bitcoin-network-kind", - "bitcoin_hashes", - "hex-conservative 0.3.2", + "bitcoin-internals 0.6.0", "hex-conservative 1.2.0", - "secp256k1", "serde", ] [[package]] name = "bitcoin-internals" version = "0.5.0" -source = "git+https://github.com/rust-bitcoin/rust-bitcoin?tag=bitcoin-crypto-0.2.0#11650c6c480088cc30a04e583e187cd7a84a2d8f" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a30a22d1f112dde8e16be7b45c63645dc165cef254f835b3e1e9553e485cfa64" dependencies = [ "hex-conservative 0.3.2", - "serde", -] - -[[package]] -name = "bitcoin-io" -version = "0.5.0" -source = "git+https://github.com/rust-bitcoin/rust-bitcoin?tag=bitcoin-crypto-0.2.0#11650c6c480088cc30a04e583e187cd7a84a2d8f" -dependencies = [ - "bitcoin-consensus-encoding", - "bitcoin-internals", - "bitcoin_hashes", ] [[package]] -name = "bitcoin-network-kind" -version = "0.1.0" -source = "git+https://github.com/rust-bitcoin/rust-bitcoin?tag=bitcoin-crypto-0.2.0#11650c6c480088cc30a04e583e187cd7a84a2d8f" -dependencies = [ - "bitcoin-internals", - "serde", -] - -[[package]] -name = "bitcoin-p2p-messages" -version = "0.1.0" -source = "git+https://github.com/rust-bitcoin/rust-bitcoin?tag=bitcoin-crypto-0.2.0#11650c6c480088cc30a04e583e187cd7a84a2d8f" +name = "bitcoin-internals" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d573f4cf32996a8dce612e4348cece65a241f1882ed594047c9ba348e8869fa5" dependencies = [ - "bitcoin", - "bitcoin-consensus-encoding", - "bitcoin-internals", - "bitcoin-io", - "bitcoin-network-kind", - "bitcoin-primitives", - "bitcoin-units", - "bitcoin_hashes", - "hex-conservative 0.3.2", - "hex-conservative 1.2.0", "serde", ] [[package]] name = "bitcoin-primitives" -version = "0.102.0" -source = "git+https://github.com/rust-bitcoin/rust-bitcoin?tag=bitcoin-crypto-0.2.0#11650c6c480088cc30a04e583e187cd7a84a2d8f" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e12cb1814d037edbd667554c2c0e6b067db72c83ee935b645a6b5829aca908" dependencies = [ - "bitcoin-consensus-encoding", - "bitcoin-internals", + "bitcoin-consensus-encoding 1.2.0", + "bitcoin-internals 0.6.0", "bitcoin-units", - "bitcoin_hashes", - "hex-conservative 0.3.2", + "bitcoin_hashes 1.2.0", "hex-conservative 1.2.0", "serde", ] -[[package]] -name = "bitcoin-taproot-primitives" -version = "0.1.0" -source = "git+https://github.com/rust-bitcoin/rust-bitcoin?tag=bitcoin-crypto-0.2.0#11650c6c480088cc30a04e583e187cd7a84a2d8f" -dependencies = [ - "bitcoin-crypto", - "bitcoin-internals", - "bitcoin_hashes", - "secp256k1", - "serde", -] - [[package]] name = "bitcoin-units" -version = "0.3.0" -source = "git+https://github.com/rust-bitcoin/rust-bitcoin?tag=bitcoin-crypto-0.2.0#11650c6c480088cc30a04e583e187cd7a84a2d8f" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae6dcb008158c2bdbe698470280439844be5f640310e4f5d6ef0a0209e066c2" dependencies = [ - "bitcoin-consensus-encoding", - "bitcoin-internals", + "bitcoin-consensus-encoding 1.2.0", + "bitcoin-internals 0.5.0", "serde", ] [[package]] name = "bitcoin_hashes" version = "0.20.0" -source = "git+https://github.com/rust-bitcoin/rust-bitcoin?tag=bitcoin-crypto-0.2.0#11650c6c480088cc30a04e583e187cd7a84a2d8f" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8a45c2b41c457a9a9e4670422fcbdf109afb3b22bc920b4045e8bdfd788a3d" dependencies = [ - "bitcoin-consensus-encoding", - "bitcoin-internals", + "bitcoin-consensus-encoding 0.1.0", + "bitcoin-internals 0.5.0", "hex-conservative 0.3.2", - "hex-conservative 1.2.0", - "serde", ] [[package]] -name = "bitcoinconsensus" -version = "0.106.0+26.0" +name = "bitcoin_hashes" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12cba9cce5043cdda968e07b9df6d05ec6b0b38aa27a9a40bb575cf3e521ae9" +checksum = "5304e53726dbe5f93141535e102ed97b5bf4714fbecefdda8f9fb98d7fdaff0e" dependencies = [ - "cc", + "bitcoin-consensus-encoding 1.2.0", + "bitcoin-internals 0.6.0", + "hex-conservative 1.2.0", + "serde", ] [[package]] @@ -410,14 +336,13 @@ checksum = "baf0a07a401f374238ab8e2f11a104d2851bf9ce711ec69804834de8af45c7af" [[package]] name = "console" -version = "0.15.11" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +checksum = "4fe5f465a4f6fee88fad41b85d990f84c835335e85b5d9e6e63e0d06d28cba7c" dependencies = [ "encode_unicode", "libc", - "once_cell", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -497,7 +422,7 @@ dependencies = [ "ctutils", "hybrid-array", "num-traits", - "rand_core 0.10.1", + "rand_core", "subtle", "zeroize", ] @@ -519,7 +444,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ "hybrid-array", - "rand_core 0.10.1", + "rand_core", ] [[package]] @@ -536,7 +461,7 @@ dependencies = [ name = "dash-dev" version = "0.0.0" dependencies = [ - "bitcoin-consensus-encoding", + "bitcoin-consensus-encoding 1.2.0", "built", "cfg-if", "chrono", @@ -563,7 +488,7 @@ dependencies = [ name = "dash-num" version = "0.0.0" dependencies = [ - "bitcoin-consensus-encoding", + "bitcoin-consensus-encoding 1.2.0", "dash-dev", "dash-types", "divan", @@ -576,11 +501,8 @@ dependencies = [ name = "dash-p2p-core" version = "0.0.0" dependencies = [ - "bitcoin-consensus-encoding", - "bitcoin-internals", - "bitcoin-p2p-messages", - "bitcoin-primitives", - "bitcoin-units", + "bitcoin-consensus-encoding 1.2.0", + "bitcoin-internals 0.6.0", "cfg-if", "dash-dev", "dash-num", @@ -598,7 +520,7 @@ dependencies = [ name = "dash-params" version = "0.0.0" dependencies = [ - "bitcoin-consensus-encoding", + "bitcoin-consensus-encoding 1.2.0", "bitcoin-primitives", "bitcoin-units", "dash-num", @@ -615,8 +537,8 @@ version = "0.0.0" dependencies = [ "aes", "base58ck", - "bitcoin-consensus-encoding", - "bitcoin_hashes", + "bitcoin-consensus-encoding 1.2.0", + "bitcoin_hashes 1.2.0", "blst", "cfg-if", "dash-dev", @@ -624,11 +546,11 @@ dependencies = [ "dash-types", "divan", "ff", - "getrandom 0.4.3", + "getrandom", "group", "hex-conservative 0.3.2", "k256", - "rand_core 0.10.1", + "rand_core", "rstest", "serde", "sha2 0.10.9", @@ -650,11 +572,11 @@ dependencies = [ name = "dash-primitives" version = "0.0.0" dependencies = [ - "bitcoin-consensus-encoding", - "bitcoin-internals", + "bitcoin-consensus-encoding 1.2.0", + "bitcoin-internals 0.6.0", "bitcoin-primitives", "bitcoin-units", - "bitcoin_hashes", + "bitcoin_hashes 1.2.0", "cfg-if", "dash-dev", "dash-num", @@ -674,7 +596,7 @@ name = "dash-script" version = "0.0.0" dependencies = [ "base58ck", - "bitcoin-consensus-encoding", + "bitcoin-consensus-encoding 1.2.0", "dash-num", "dash-pkc", "dash-types", @@ -688,10 +610,9 @@ name = "dash-types" version = "0.0.0" dependencies = [ "base58ck", - "bitcoin-consensus-encoding", - "bitcoin-p2p-messages", + "bitcoin-consensus-encoding 1.2.0", "bitcoin-primitives", - "bitcoin_hashes", + "bitcoin_hashes 1.2.0", "cfg-if", "dash-types-marker", "hex-conservative 0.3.2", @@ -811,7 +732,7 @@ dependencies = [ "ff", "group", "hybrid-array", - "rand_core 0.10.1", + "rand_core", "sec1", "subtle", "zeroize", @@ -836,7 +757,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -845,7 +766,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1f686ab92a9fb0eaf188f6c6c87b89490baa6fdb0db4544ba4dc47f7942489f" dependencies = [ - "rand_core 0.10.1", + "rand_core", "subtle", ] @@ -922,18 +843,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "libc", - "r-efi 5.3.0", - "wasip2", -] - [[package]] name = "getrandom" version = "0.4.3" @@ -942,8 +851,8 @@ checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", - "r-efi 6.0.0", - "rand_core 0.10.1", + "r-efi", + "rand_core", ] [[package]] @@ -972,7 +881,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fd1a1c7a5206c5b7a3f5a0d7ccd3ff85d0c8f5133d62a02680255b0004af5f4" dependencies = [ "ff", - "rand_core 0.10.1", + "rand_core", "subtle", ] @@ -1224,14 +1133,13 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.17.11" +version = "0.18.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +checksum = "9433806cd6b4ec1aba79c021c7e4c58fb4c3b9977c085062e611ac929998fb0c" dependencies = [ "console", - "number_prefix", "portable-atomic", - "web-time", + "unit-prefix", ] [[package]] @@ -1255,7 +1163,7 @@ version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" dependencies = [ - "getrandom 0.4.3", + "getrandom", "libc", ] @@ -1383,12 +1291,6 @@ dependencies = [ "libc", ] -[[package]] -name = "number_prefix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" - [[package]] name = "once_cell" version = "1.21.4" @@ -1471,15 +1373,6 @@ version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - [[package]] name = "primefield" version = "0.14.0" @@ -1489,7 +1382,7 @@ dependencies = [ "crypto-bigint", "crypto-common 0.2.2", "ff", - "rand_core 0.10.1", + "rand_core", "subtle", "zeroize", ] @@ -1532,47 +1425,12 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - [[package]] name = "r-efi" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" -[[package]] -name = "rand" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" -dependencies = [ - "rand_chacha", - "rand_core 0.9.5", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.5", -] - -[[package]] -name = "rand_core" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom 0.3.4", -] - [[package]] name = "rand_core" version = "0.10.1" @@ -1699,7 +1557,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -1722,25 +1580,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "secp256k1" -version = "0.32.0-beta.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5fdc7d6e800869d3fd60ff857c479bf0a83ea7bf44b389e64461e844204994" -dependencies = [ - "rand", - "secp256k1-sys", -] - -[[package]] -name = "secp256k1-sys" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d3be00697c88c00fe102af8dc316038cc2062eab8da646e7463f4c0e70ca9fd" -dependencies = [ - "cc", -] - [[package]] name = "semver" version = "1.0.28" @@ -1838,7 +1677,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5" dependencies = [ "digest 0.11.3", - "rand_core 0.10.1", + "rand_core", ] [[package]] @@ -1918,7 +1757,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ "rustix", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -2029,6 +1868,12 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unit-prefix" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" + [[package]] name = "url" version = "2.5.8" @@ -2065,15 +1910,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "wasip2" -version = "1.0.4+wasi-0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" -dependencies = [ - "wit-bindgen", -] - [[package]] name = "wasm-bindgen" version = "0.2.126" @@ -2119,16 +1955,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "winapi" version = "0.3.9" @@ -2263,15 +2089,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -2363,21 +2180,16 @@ dependencies = [ "memchr", ] -[[package]] -name = "wit-bindgen" -version = "0.57.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" - [[package]] name = "wnaf" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab12e7090f27e2ffd9322651492942d50c2926094af30601e1964337db39daf1" +checksum = "795ca18b3fdb5e62bf982199278341ddcf7ebf7d32e25e212ad05d496e95f6fa" dependencies = [ "ff", "group", "hybrid-array", + "primefield", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 10799d71..0ee07e5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,13 +14,12 @@ members = [ resolver = "2" [workspace.dependencies] -base58ck = { git = "https://github.com/rust-bitcoin/rust-bitcoin", tag = "bitcoin-crypto-0.2.0", default-features = false } -bitcoin-consensus-encoding = { git = "https://github.com/rust-bitcoin/rust-bitcoin", tag = "bitcoin-crypto-0.2.0", default-features = false } -bitcoin-internals = { git = "https://github.com/rust-bitcoin/rust-bitcoin", tag = "bitcoin-crypto-0.2.0", default-features = false } -bitcoin-p2p-messages = { git = "https://github.com/rust-bitcoin/rust-bitcoin", tag = "bitcoin-crypto-0.2.0", default-features = false } -bitcoin-primitives = { git = "https://github.com/rust-bitcoin/rust-bitcoin", tag = "bitcoin-crypto-0.2.0", default-features = false } -bitcoin-units = { git = "https://github.com/rust-bitcoin/rust-bitcoin", tag = "bitcoin-crypto-0.2.0", default-features = false } -bitcoin_hashes = { git = "https://github.com/rust-bitcoin/rust-bitcoin", tag = "bitcoin-crypto-0.2.0", default-features = false } +base58ck = { version = "0.4.0", default-features = false } +bitcoin-consensus-encoding = { version = "1.2.0", default-features = false } +bitcoin-internals = { version = "0.6.0", default-features = false } +bitcoin-primitives = { version = "0.103.0", default-features = false } +bitcoin-units = { version = "0.5.0", default-features = false } +bitcoin_hashes = { version = "1.2.0", default-features = false } [workspace.lints.clippy] expect_used = "deny" @@ -40,6 +39,11 @@ unsafe_code = "deny" unused_must_use = "deny" [workspace.package] +authors = ["Kittywhiskers Van Gogh "] +edition = "2021" +homepage = "https://dashpay.github.io/base-sdk" +license = "MIT" +repository = "https://github.com/dashpay/base-sdk" rust-version = "1.85.0" [profile.release] diff --git a/contrib/README.md b/contrib/README.md index 627ac8f0..f1522a55 100644 --- a/contrib/README.md +++ b/contrib/README.md @@ -32,6 +32,7 @@ source .venv/bin/activate [`pyproject.toml`](../pyproject.toml) supplies most but not all dependencies needed to run the lint suite, the following packages need to be additionally sourced. +* [cargo-deny](https://github.com/EmbarkStudios/cargo-deny) * [Git](https://git-scm.com/install/) * [CodeQL 2.24 or higher](https://github.com/github/codeql-cli-binaries/releases) (Rust support was added in 2.23.3, [source](https://github.blog/changelog/2025-10-23-codeql-2-23-3-adds-a-new-rust-query-rust-support-and-easier-c-c-scanning/)) @@ -46,7 +47,7 @@ packages need to be additionally sourced. > ([source](https://docs.brew.sh/FAQ#what-does-keg-only-mean)). ```bash -brew install codeql git node@24 +brew install cargo-deny codeql git node@24 ``` ### Linux/WSL @@ -79,12 +80,15 @@ cargo install taplo-cli # Required because Debian trixie ships Node 20.x, deprecated in April 2026 curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash - sudo apt install git nodejs -y + +# `cargo-deny` is currently unavailable on Debian (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=951368) +cargo install --locked cargo-deny ``` #### Fedora ```bash -sudo dnf install -y git nodejs24 +sudo dnf install -y cargo-deny git nodejs24 ``` diff --git a/contrib/nix/mods/nixpkgs.nix b/contrib/nix/mods/nixpkgs.nix index 38f2dc1a..62f7b593 100644 --- a/contrib/nix/mods/nixpkgs.nix +++ b/contrib/nix/mods/nixpkgs.nix @@ -24,6 +24,7 @@ let in { packages = [ + pkgs.cargo-deny pkgs.cargo-llvm-cov pkgs.git pkgs.nixfmt diff --git a/deny.toml b/deny.toml new file mode 100644 index 00000000..89c16658 --- /dev/null +++ b/deny.toml @@ -0,0 +1,5 @@ +[graph] +all-features = true + +[advisories] +yanked = "deny" diff --git a/docs/dev/about_docs.md b/docs/dev/about_docs.md index e50a7466..5d1c619a 100644 --- a/docs/dev/about_docs.md +++ b/docs/dev/about_docs.md @@ -95,7 +95,7 @@ edits and the pages that could be affected by your edits to ensure it remains pl To splice in a whole document, or a spliced segment of it (like `setup`), the syntax is as below. -```markdown +```text ``` @@ -106,14 +106,59 @@ To splice in a whole document, or a spliced segment of it (like `setup`), the sy To create a spliceable segment, wrap the desired text in `start` and `end` markers carrying its label (like `setup`). -```markdown +```text Carried into the splice. ``` Links in spliced material are resolved against the file that defines them, not the page splicing it in (see -[link processing](#link-processing)). Splices may nest, and a directive inside a code fence is inert. +[link processing](#link-processing)). Splices may nest. + +#### Inlining + +> [!TIP] +> To write directives as literal text without parsing it, wrap the text segment in a code block with +> formatting type text (i.e. ```text). This will instruct the preprocessor to *not* interpret the +> captured segment as directives, quoting or otherwise. + +Example code has a recurring problem of staleness, where (especially in early incubation), code segments may undergo +radical changes in shape, scope and location. This can result in examples that at best, don't compile at all and at +worst, enact behaviors that do not match the text description or mislead the reader. + +This is avoided by using segments from the live codebase, as shown below for inlining a complete file. + +````text +```toml + +``` +```` + +> [!WARNING] +> Splicing non-Markdown files outside code blocks is prohibited as Markdown files undergo additional processing steps +> and such files have a high tendency of disturbing the final page render. + +And for partial inlining, the syntax is similar to regular splicing. + +````text +# In Markdown + +```rust + +``` +```` + +With its counterpart in a source file appearing like so. + +```rust +// In Rust + +// [start:vec-codec] +impl Encoder for VecEncoder { + // ... +} +// [end:vec-codec] +``` ### Omitting @@ -124,7 +169,7 @@ situations where most of the file is included _except_ for a small portion. Omis To omit a segment, use the following syntax. Unlike other labels, `omit` can be used repeatedly but typos of `omit` will be treated as ordinary spliceable segments. -```markdown +```text Rendered on GitHub, absent from the site. diff --git a/docs/preprocess.py b/docs/preprocess.py index 4e50daf8..a8889e02 100644 --- a/docs/preprocess.py +++ b/docs/preprocess.py @@ -15,6 +15,7 @@ from contextlib import contextmanager from pathlib import Path from tempfile import TemporaryDirectory +from textwrap import dedent from typing import TYPE_CHECKING from common import off_disk, root_dir, spelt_as_stored @@ -99,8 +100,11 @@ def run(self, lines: list[str]) -> list[str]: # Matches a code block, and whatever trails the marker on that line. _FENCE_RE = re.compile(r"^\s*(`{3,}|~{3,})(.*)$") +# Info string of a fence holding a directive as the syntax being shown. +_LITERAL_INFO = "text" + # Matches a splice from another file, or one named section from it. -_INCLUDE_RE = re.compile(r"^\s*\s*$") +_INCLUDE_RE = re.compile(r"^(\s*)\s*$") # Matches any directive-shaped comment, by the verb and label it names. _DIRECTIVE_RE = re.compile(r"^\s*\s*$") @@ -114,6 +118,11 @@ def run(self, lines: list[str]) -> list[str]: # Matches a bound of such a segment. _OMIT_RE = re.compile(rf"^\s*\s*$") +# Matches a line holding a marker. +_MARKER_ONLY_RE = re.compile( + r"^[\s/*#<>!;%-]*\[(?:start|end):[^\]]+\][\s/*#<>!;%-]*$" +) + # Matches the target of an inline link, and any title trailing it. _LINK_RE = re.compile( r"\]\(\s*(<[^<>]*>|[^\s()]+)" @@ -123,6 +132,9 @@ def run(self, lines: list[str]) -> list[str]: # Directory holding this extension, which is the documentation root. _DOCS_ROOT = Path(__file__).resolve().parent +# Suffix of a file that is prose, and so a page rather than a quotation. +_PAGE_SUFFIX = ".md" + # Stems Zensical serves as a directory's own index, matched as spelt here. _INDEX_STEMS = frozenset({"README", "index"}) @@ -173,8 +185,14 @@ def _named_directive(line: str) -> None: class _Fences: """Running fence state over a sequence of lines.""" - def __init__(self, opener: str | None = None) -> None: + def __init__(self, opener: str | None = None, info: str = "") -> None: self.opener = opener + self.info = info + + @property + def literal(self) -> bool: + """Whether the open fence shows a directive rather than using it.""" + return self.opener is not None and self.info == _LITERAL_INFO def covers(self, line: str) -> bool: """Whether *line* is fenced, counting the fence markers themselves.""" @@ -184,6 +202,7 @@ def covers(self, line: str) -> bool: found, trailing = marker.group(1), marker.group(2) if self.opener is None: self.opener = found + self.info = trailing.strip() # A closing fence carries no info string, so a marker that does is # content the block holds rather than the end of it. elif ( @@ -192,6 +211,7 @@ def covers(self, line: str) -> bool: and not trailing.strip() ): self.opener = None + self.info = "" return True @@ -203,6 +223,16 @@ def _opens_a_fence(lines: list[str]) -> bool: return fences.opener is not None +def _quoted(lines: list[str]) -> list[str]: + """Return *lines* as code, at their own margin and without markers. + + A region may hold the bounds of another, which name a segment rather + than the code the reader is being shown. + """ + kept = (line for line in lines if not _MARKER_ONLY_RE.match(line)) + return dedent("\n".join(kept)).strip("\n").splitlines() + + def forge_url(repo_url: str, branch: str, source: Path) -> str: """Return the URL *source* is served from, by its kind.""" kind = "tree" if source.is_dir() else "blob" @@ -237,22 +267,28 @@ def _expand( output: list[str] = [] for line in lines: - # A directive inside a fence is the syntax being shown, not used. - fenced = fences.covers(line) - match = None if fenced else _INCLUDE_RE.match(line) + fences.covers(line) + # A directive a literal fence holds is the syntax being shown. + if fences.literal: + output.append(line) + continue + match = _INCLUDE_RE.match(line) if match is None: - if not fenced: - _named_directive(line) + _named_directive(line) output.append(line) continue if budget <= 0: - raise ValueError(f"{match.group(1)}: includes nested past the limit") - spliced = self._include(match.group(1), fences) - output.extend(self._expand(spliced, budget - 1, fences)) + raise ValueError(f"{match.group(2)}: includes nested past the limit") + # A directive stands at the margin of whatever holds it, so what it + # splices in has to be laid out from there and not from column zero. + margin = match.group(1) + spliced = self._include(match.group(2), fences, budget) + output.extend(margin + text if text else text for text in spliced) return output - def _include(self, spec: str, fences: _Fences) -> list[str]: + def _include(self, spec: str, fences: _Fences, budget: int) -> list[str]: + """Return the lines *spec* names, as the prose or the code they are.""" name, _, section = spec.partition(":") source = (root_dir() / name).resolve() # An absolute *name* would displace the root it is joined to, so the @@ -261,13 +297,25 @@ def _include(self, spec: str, fences: _Fences) -> list[str]: raise ValueError(f"{spec}: outside the repository") if not source.is_file(): raise ValueError(f"{spec}: no such file in the repository") + prose = source.suffix == _PAGE_SUFFIX + if not prose and fences.opener is None: + raise ValueError(f"{spec}: outside a code fence") - lines = _strip_omitted(source.read_text(encoding="utf-8").splitlines()) + lines = source.read_text(encoding="utf-8").splitlines() + if prose: + lines = _strip_omitted(lines) if section: lines = _section(lines, section, spec) + if not prose: + # Code holds no link the site can resolve and no directive it + # reads, so it stands as stored, at the margin its fence sets. + return _quoted(lines) + # `_rebase` walks these same lines, so it takes a copy of the fence # state at the splice point rather than advancing the caller's. - return self._rebase(lines, source.parent, _Fences(fences.opener)) + held = _Fences(fences.opener, fences.info) + spliced = self._rebase(lines, source.parent, held) + return self._expand(spliced, budget - 1, fences) def _rebase( self, lines: list[str], home: Path, fences: _Fences, @@ -376,6 +424,7 @@ def makeExtension(**kwargs: object) -> PreprocessorHost: """Construct the extension.""" return PreprocessorHost(**kwargs) + # Stand-in forge the tests resolve their fixtures against. _REPO = "https://forge.test/owner/repo" _BRANCH = "trunk" @@ -428,12 +477,22 @@ def test_include_splices_a_section(self) -> None: assert "above" not in out assert "below" not in out - def test_include_refuses_an_unknown_section(self) -> None: + def test_include_refuses_what_it_cannot_carry(self) -> None: import pytest with self._scratch(whole="nothing marked\n") as home: - with pytest.raises(ValueError, match="no such section"): - self._render(f'\n') + code = self._carve(home, "demo.rs", "fn main() {}\n") + cases = ( + ("/etc/hosts", "outside the repository"), + ("../../../../etc/hosts", "outside the repository"), + (f"{home}/gone.md", "no such file"), + (f"{home}/whole.md:mid", "no such section"), + # Code read as prose would be rendered as prose. + (code, "outside a code fence"), + ) + for spec, message in cases: + with pytest.raises(ValueError, match=message): + self._render(f'\n') def test_section_refuses_an_unclosed_fence(self) -> None: import pytest @@ -444,22 +503,17 @@ def test_section_refuses_an_unclosed_fence(self) -> None: with pytest.raises(ValueError, match="leaves a fence open"): self._render(f'\n') - def test_include_rejects_an_absolute_path(self) -> None: - import pytest - - with pytest.raises(ValueError, match="outside the repository"): - self._render('\n') - - def test_include_rejects_a_traversal(self) -> None: - import pytest - - with pytest.raises(ValueError, match="outside the repository"): - self._render('\n') - - def test_include_inside_a_fence_is_left_alone(self) -> None: - out = self._render('```\n\n```\n') - assert "[include:maint/unconv.toml]" in out - assert "[global]" not in out + def test_a_literal_fence_shows_the_directive_it_holds(self) -> None: + held = [ + "", + "", + "", + "", + ] + # Neither read nor refused, so a misspelt verb is text like the rest. + assert self._pointer().run(["```text", *held, "```"]) == [ + "```text", *held, "```", + ] def test_a_misspelt_directive_is_refused(self) -> None: import pytest @@ -471,13 +525,9 @@ def test_a_section_marker_is_a_known_directive(self) -> None: out = self._render("\nkept\n\n") assert "kept" in out - def test_a_misspelt_directive_in_a_fence_is_left_alone(self) -> None: - out = self._render("```\n\n```\n") - assert "[inclde:README.md]" in out - def test_include_nests(self) -> None: with self._scratch( - outer='\n', + outer='```toml\n\n```\n', ) as home: out = self._render(f'\n') assert "[include:" not in out @@ -533,21 +583,69 @@ def test_omit_applies_to_spliced_material(self) -> None: assert "carried" in out assert "nope.md" not in out - def test_titled_link_is_rebased(self) -> None: - with self._scratch(page='[a](../README.md "root")\n') as home: - out = self._render(f'\n') - assert f'href="{_REPO}/blob/{_BRANCH}/README.md"' in out - assert 'title="root"' in out - - def test_caged_link_is_rebased(self) -> None: - with self._scratch(page="[a](<../README.md>)\n") as home: - out = self._render(f'\n') - assert f'href="{_REPO}/blob/{_BRANCH}/README.md"' in out - - def test_bare_link_is_rebased(self) -> None: - with self._scratch(page="[a](../maint/unconv.toml)\n") as home: - out = self._render(f'\n') - assert f'href="{_REPO}/blob/{_BRANCH}/maint/unconv.toml"' in out + @staticmethod + def _carve(home: Path, name: str, text: str) -> str: + """Write *text* to *name* under *home* and return the spec for it.""" + (root_dir() / home / name).write_text(text, encoding="utf-8") + return f"{home}/{name}" + + def test_code_stands_in_the_fence_holding_it(self) -> None: + body = ( + "fn skipped() {}\n" + " // [start:shown]\n" + " fn shown() {\n" + " // [start:inner]\n" + " let x = 1;\n" + " // [end:inner]\n" + " }\n" + " // [end:shown]\n" + ) + def fenced(spec: str, margin: str = "") -> list[str]: + return [ + f"{margin}```rust", + f"{margin}", + f"{margin}```", + ] + + with self._scratch() as home: + spec = self._carve(home, "demo.rs", body) + whole = self._pointer().run(fenced(spec)) + region = self._pointer().run(fenced(f"{spec}:shown")) + held = self._pointer().run(fenced(f"{spec}:shown", " ")) + # A marker names a segment rather than the code being shown, so it is + # dropped wherever it falls, and a region is read at its own margin. + assert whole == [ + "```rust", + "fn skipped() {}", + " fn shown() {", + " let x = 1;", + " }", + "```", + ] + assert region == [ + "```rust", + "fn shown() {", + " let x = 1;", + "}", + "```", + ] + # A fence the page indents, such as one a content tab holds, carries + # the code it shows at that margin rather than at column zero. + assert held == [" " + line for line in region] + + def test_a_link_is_rebased_in_every_form_it_is_written(self) -> None: + blob = f"{_REPO}/blob/{_BRANCH}" + cases = ( + ('[a](../README.md "root")', + (f'href="{blob}/README.md"', 'title="root"')), + ("[a](<../README.md>)", (f'href="{blob}/README.md"',)), + ("[a](../maint/unconv.toml)", (f'href="{blob}/maint/unconv.toml"',)), + ) + for source, expected in cases: + with self._scratch(page=f"{source}\n") as home: + out = self._render(f'\n') + for fragment in expected: + assert fragment in out, source def test_page_under_docs_is_addressed_from_the_site(self) -> None: with self._scratch(page="[a](../docs/dev/guide_rust.md)\n") as home: @@ -560,12 +658,19 @@ def test_off_disk_link_is_left_alone(self) -> None: assert 'href="tel:+15551212"' in out assert 'href="irc://x/y"' in out - def test_missing_link_target_is_refused(self) -> None: + def test_a_link_naming_no_file_is_refused(self) -> None: import pytest - with self._scratch(page="[a](./nope.md)\n") as home: - with pytest.raises(ValueError, match="no such file"): - self._render(f'\n') + # A wrong-case link is refused either as missing or as misspelt, by + # the case rules of the host the tests run on. + cases = ( + ("[a](./nope.md)", "no such file"), + ("[a](../README.MD)", r"no such file|not spelt"), + ) + for source, message in cases: + with self._scratch(page=f"{source}\n") as home: + with pytest.raises(ValueError, match=message): + self._render(f'\n') @staticmethod def _pointer() -> IncludePreprocessor: @@ -590,17 +695,9 @@ def test_spelling_check_matches_the_stored_name(self) -> None: assert not spelt_as_stored(root, root / "README.MD") assert not spelt_as_stored(root, root / "Docs" / "README.md") - def test_wrong_case_link_is_refused(self) -> None: - import pytest - - # Refused either as missing or as misspelt, by the host's case rules. - with self._scratch(page="[a](../README.MD)\n") as home: - with pytest.raises(ValueError, match=r"no such file|not spelt"): - self._render(f'\n') - def test_include_survives_a_fenced_info_string(self) -> None: out = self._render( - '```\n```text\n\n```\n' + '```text\n```markdown\n\n```\n' ) assert "[include:maint/unconv.toml]" in out assert "[global]" not in out @@ -616,16 +713,16 @@ def test_site_root_link_is_left_for_postprocessing(self) -> None: assert 'href="/dev/about_docs/"' in out def test_a_fence_an_include_opens_holds_over_the_parent(self) -> None: - with self._scratch(opener="```\n", body="spliced text\n") as home: + with self._scratch(opener="```text\n", body="spliced text\n") as home: out = self._pointer().run([ f'', f'', "```", f'', ]) - # Held back while the fence the first splice opened is still open, - # then spliced once the parent's own marker closes that fence. - assert out[0] == "```" + # Held back while the literal fence the first splice opened is still + # open, then spliced once the parent's own marker closes that fence. + assert out[0] == "```text" assert out[1].startswith("