The extension has to build a signing payload, assemble an extrinsic and decode
a call well enough to show a user what they are approving. The obvious route was
@polkadot/api's codec. That is closed, and quantus/api#1 carries the tested
evidence:
- @polkadot/types caps fixed arrays at 2048 bytes, and ML-DSA signatures are
[u8;5261] and [u8;7219], so every Quantus extrinsic trips it
- api.rpc.chain.getBlock throws on every block of this chain, at the timestamp
inherent, because it reads the extrinsic preamble byte as a version when the
top two bits are a type tag
- it *guesses* that signed extensions it does not recognise contribute nothing
to the signed payload
The third is why this is a package rather than a patch. The guess is right
today — the registry says ReversibleTransactionExtension and
WormholeProofRecorderExtension are empty on both halves — and it is right only
by luck. This chain's encoding has changed between runtimes, transactionVersion
has gone 2 -> 3 -> 6 across four upgrades, and when the guess stops holding the
wallet keeps signing: valid signatures over a payload missing bytes the runtime
put there, reported by the chain as BadProof, which is also what it reports for
a wrong key.
So nothing here names a pallet, a call, an extension or a signature scheme.
Every type id is read from metadata the node produced by running
Metadata_metadata against the runtime WASM in a given block's state, the same
oracle blackbeard.observer has been decoding against across four upgrade
boundaries. encode_extensions walks the declared extensions in order and refuses
to build a payload when one that encodes to something has no value supplied —
a wallet that cannot sign is a bug report, one that signs the wrong bytes is a
support case nobody diagnoses.
Proven end to end on Heisenberg at spec 148: a balances.transfer_keep_alive
built entirely here, signed by @quantus/crypto under QUANTUS_EXTRINSIC, included
at block 1050475 and read back from that block — inherent at index 0 included,
which is the block @polkadot/api cannot decode at all.
Two notes carried over from @quantus/crypto, both load-bearing: decode_checked
walks with scale_decode's IgnoreVisitor before scale_value touches the bytes,
because scale_value sizes a Vec from the length prefix before decoding an item
and an aborted allocation leaves no Err to catch; and the build needs binaryen
123, since 105 silently corrupts the output.
Closes #3
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012uDUodEcRbBwNRi3UCmw8f
25 lines
686 B
JSON
25 lines
686 B
JSON
{
|
|
"author": "Quantus Network Developers <hello@quantus.com>",
|
|
"bugs": "https://git.lair.cafe/quantus/wasm/issues",
|
|
"description": "Metadata-driven SCALE encode/decode for the Quantus chain",
|
|
"engines": {
|
|
"node": ">=18"
|
|
},
|
|
"homepage": "https://git.lair.cafe/quantus/wasm/src/branch/main/packages/quantus-codec#readme",
|
|
"license": "Apache-2.0",
|
|
"name": "@quantus/codec",
|
|
"repository": {
|
|
"directory": "packages/quantus-codec",
|
|
"type": "git",
|
|
"url": "https://git.lair.cafe/quantus/wasm.git"
|
|
},
|
|
"sideEffects": false,
|
|
"type": "module",
|
|
"version": "0.1.0",
|
|
"main": "index.js",
|
|
"dependencies": {
|
|
"fflate": "^0.8.2",
|
|
"tslib": "^2.7.0"
|
|
}
|
|
}
|