Files
wallet/Cargo.toml
T
grenadeandClaude Fable 5.1 1ca42fdbdf
ci / gate (push) Waiting to run
feat(substrate): a subxt config for quantus, and offline signing under the context
`QuantusConfig` is quantus-cli's `ChainConfig` with the signature enum
defined here: `DilithiumSignature { Dilithium87, Dilithium65 }`, variant
indices 0 and 1, each carrying signature-then-public-key as one raw array
because the account id is a hash of the key and the verifier needs the key
itself. Defining it locally keeps sp-core out of a desktop wallet.

subxt 0.44, deliberately: it is the version quantus-cli signs mainnet with,
and its extension resolver skips any extension whose type is empty, which
is how the chain's ReversibleTransactionExtension and
WormholeProofRecorderExtension are tolerated with the default set. A test
pins that both names are in the metadata and that building still works.

`sign_call` builds the v4 extrinsic offline from captured chain state,
takes the signer payload from subxt (blake2-hashed past 256 bytes, as the
runtime hashes when it verifies), signs it with a `wallet_core::Signer`
under the profile's FIPS 204 context, and hands the signature back to
subxt to assemble. The test decodes the result byte by byte: 0x84, Id
address equal to the signer's account id, the variant byte, the public key
riding with the signature, the extras, the call data as the tail.

Live acceptance against a1-planck.quantus.cat, from an unfunded account:
signed under QUANTUS_EXTRINSIC the node answers "Inability to pay some
fees", so the signature passed; signed under the empty context it answers
"Transaction has a bad signature". Ignored test, run by hand.

Metadata fixtures are live `state_getMetadata` from mainnet (spec 152) and
Planck (spec 148), 101 KB each, v14.

Closes #19

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ftBXYuba8ARhQeF74oUgW
2026-09-15 22:16:27 +03:00

68 lines
2.9 KiB
TOML

[workspace]
resolver = "3"
members = ["crates/*"]
[workspace.package]
version = "0.1.0"
edition = "2024"
rust-version = "1.85"
license = "GPL-3.0-or-later"
authors = ["Rob Thijssen <rob@lair.cafe>"]
repository = "https://git.lair.cafe/blackbeard/wallet"
[workspace.dependencies]
wallet-entities = { path = "crates/wallet-entities", version = "=0.1.0" }
wallet-core = { path = "crates/wallet-core", version = "=0.1.0" }
wallet-data = { path = "crates/wallet-data", version = "=0.1.0" }
anyhow = "1"
async-trait = "0.1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
thiserror = "2"
tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "time"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
# Types in `wallet-entities` are exported to the webview as TypeScript so the
# UI and the Rust side never disagree about a field. See .cargo/config.toml.
ts-rs = { version = "10", features = ["serde-compat", "no-serde-warnings"] }
toml = "0.8"
zeroize = { version = "1", features = ["derive"] }
# Quantus's post-quantum primitives. The dilithium crate is the FIPS 204
# implementation the chain verifies against; hdwallet is the BIP32/39/44
# derivation for lattice keys; poseidon is the account-id hash.
qp-rusty-crystals-dilithium = { version = "4.1.1", default-features = false, features = ["ml-dsa-65", "ml-dsa-87"] }
qp-rusty-crystals-hdwallet = { version = "4.1.1", features = ["ml-dsa-65", "ml-dsa-87"] }
qp-poseidon-core = "3.1.0"
# SS58: blake2b-512 checksum and base58. Nothing else from sp-core is needed.
blake2 = { version = "0.10", default-features = false }
bs58 = "0.5"
getrandom = "0.3"
# The quantus-cli keystore format: Argon2id (frozen m=19456,t=2,p=1) into
# AES-256-GCM. The versions are pinned to what the CLI itself uses.
argon2 = { version = "0.5", features = ["std"] }
aes-gcm = "0.10"
chrono = { version = "0.4", default-features = false, features = ["clock", "serde", "std"] }
directories = "6"
tempfile = "3"
# Mnemonics: the same bip39 the hdwallet crate pins, so validation and seed
# stretching cannot disagree about a phrase. The checkphrase crate is
# Quantus's human-readable address checksum; its wordlist is vendored.
bip39 = { version = "=2.2.2", features = ["zeroize"] }
qp-human-checkphrase = "2.2.1"
# subxt 0.44 is the version quantus-cli signs mainnet transactions with; its
# extension resolver skips extensions whose type is empty, which is how the
# chain's two custom extensions (Reversible, WormholeProofRecorder) are
# tolerated without a custom config. 0.51 will add a builder for them.
subxt = "0.44"
parity-scale-codec = { version = "3", features = ["derive"] }
hex = "0.4"
# `isolation`: the IPC isolation pattern (crates/wallet-app/isolation/index.html).
tauri = { version = "2", features = ["isolation"] }
tauri-build = { version = "2", features = ["isolation"] }
[profile.release]
lto = "thin"
codegen-units = 1
strip = "debuginfo"