Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,24 @@ jobs:
- name: Run the LifeHash differential fuzzer
run: npm --prefix fuzzing run fuzz:lifehash

# ── Fuzz: multisig wallet outputs (addresses, descriptors, checksums) ────
# vs an independent scure BIP32/script stack, plus co-signer suffix
# tolerance invariance. Same locked fuzzing/ tree, same determinism.

fuzz-msig:
name: Fuzz · multisig outputs vs scure
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install locked fuzzing dependencies
run: npm ci --ignore-scripts --prefix fuzzing
- name: Run the multisig differential fuzzer
run: npm --prefix fuzzing run fuzz:msig

# ── Artifact: commit the tested site after merges to rock ────────────────
# Gated on every behavioral job (unit, browser, structural, WASM), then
# commits the exact tested candidate — it never rebuilds the wallet HTML.
Expand All @@ -384,7 +402,7 @@ jobs:
artifact:
name: Artifact · commit tested site after merge
if: github.ref == 'refs/heads/rock' && github.event_name == 'push'
needs: [build, verify, test-ci, test-browser, build-wasm, fuzz-lifehash]
needs: [build, verify, test-ci, test-browser, build-wasm, fuzz-lifehash, fuzz-msig]
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
Expand Down Expand Up @@ -449,7 +467,7 @@ jobs:
deploy:
name: Deploy to GitHub Pages
if: github.ref == 'refs/heads/rock' && github.event_name != 'pull_request'
needs: [build, verify, test-ci, test-browser, build-wasm, fuzz-lifehash]
needs: [build, verify, test-ci, test-browser, build-wasm, fuzz-lifehash, fuzz-msig]
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
Expand Down
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ Official website: [entropylab.online](https://entropylab.online)
requiring private keys. Multisig script type and purpose are separate as
well; conventional script choices restore their standard purpose, while
pasted co-signer origins auto-detect and must agree with the selected path
indexes and hardening choices.
indexes and hardening choices. Addresses are derived from the exported
output descriptor itself by rust-miniscript (in the WASM crate), so the two
cannot drift.
- Inspects PSBT v0 transactions, reports PSBT-provided amounts and fees, checks
for repeated ECDSA nonces from the same public key — including signatures
carried by finalized scriptSig/witness fields, which are decoded and analyzed
Expand Down Expand Up @@ -257,10 +259,13 @@ EntropyLab's cryptography — secp256k1 curve operations (public-key
derivation, ECDSA signing and verification in PSBT inspection, curve point
math), hashes (SHA-256, SHA-512, RIPEMD-160, HMAC-SHA-512,
PBKDF2-HMAC-SHA-512), BIP32 extended-key derivation, BIP39 mnemonics,
Base58Check and bech32m encoding, and address/script construction
Base58Check and bech32m encoding, output descriptor evaluation
(BIP380-386; taproot `sortedmulti_a` is layered on top), and
address/script construction
(p2pkh/p2sh/p2wpkh/p2tr, bare and taproot multisig) — runs on rust-bitcoin's
`secp256k1` crate (libsecp256k1 v0.4.1 vendored by secp256k1-sys 0.10.1),
`bitcoin`, `bitcoin_hashes`, `base58ck`, `bech32`, and `bip39`, compiled to
`bitcoin`, `bitcoin_hashes`, `base58ck`, `bech32`, `bip39`, and
`miniscript`, compiled to
WebAssembly from the pinned Rust crate in `entropylab-wasm/` (exact crate
versions in `entropylab-wasm/Cargo.lock`, toolchain pinned by
`rust-toolchain.toml`) via the facades in `src/js/secp256k1.js`,
Expand Down Expand Up @@ -310,7 +315,7 @@ To remove generated files, run `npm run clean`.
│ ├── build.mjs Locked-dependency esbuild and HTML assembly
│ ├── build-wasm.mjs crypto WASM rebuild (npm run build:wasm)
│ └── verify-site.mjs Site artifact verification (npm run verify)
├── entropylab-wasm/ Pinned Rust crate: libsecp256k1 + bitcoin_hashes -> WebAssembly bindings
├── entropylab-wasm/ Pinned Rust crate: rust-bitcoin + rust-miniscript -> WebAssembly bindings
├── test/
│ ├── browser-instrumentation.html In-page browser test hooks
│ ├── browser-suite.html In-page browser test suite
Expand All @@ -336,7 +341,7 @@ To remove generated files, run `npm run clean`.
│ ├── bip39.js BIP39 mnemonic facade over the WASM module (scure-shaped API)
│ ├── bip39-english.js Canonical 2048-word English list (UI data)
│ ├── base58.js Base58Check facade over the WASM module
│ ├── addresses.js Script/address facade over the WASM module
│ ├── addresses.js Script/address/descriptor facade over the WASM module
│ ├── bech32.js bech32m facade over the WASM module (BIP352)
│ ├── coders.js hex/base64 byte coders (no cryptography)
│ ├── sqlite-writer.js Minimal SQLite database file writer
Expand Down
12 changes: 12 additions & 0 deletions entropylab-wasm/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions entropylab-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ bitcoin = { version = "=0.32.11", default-features = false, features = ["std", "
# implementation did), so the unicode-normalization tables stay out of the
# artifact.
bip39 = { version = "=2.2.2", default-features = false }
# rust-miniscript: output descriptors (BIP380-386, BIP389 multipath) and the
# multi/sortedmulti/multi_a multisig fragments. Taproot sortedmulti_a is
# layered on top in src/descriptor.rs (derived, sorted as x-only bytes, and
# rewritten to the multi_a it denotes).
miniscript = { version = "=13.1.0", default-features = false, features = ["std"] }
base58ck = { version = "=0.1.101", default-features = false, features = ["std"] }
# rust-bitcoin's bech32 crate, used directly for the word-level bech32m the
# BIP352 silent-payment code needs (extended length limit).
Expand Down
Loading