Files
qapi/patches/@polkadot-api__signers-common.patch
grenadeandClaude Opus 5 933ffecc8f feat: accept the Quantus signature type, and list Quantus chains
## The check that fired before code that would have worked

`getSignerType` pulls the extrinsic's `Address` and `Signature` types **out of
the metadata** — the runtime-as-oracle approach, and better than polkadot-js,
which hardcodes `ExtrinsicSignature: 'MultiSignature'` in a type definition file.
Then it threw the answer away:

    if (signature.type !== "enum" || ["Ecdsa", "Ed25519", "Sr25519"].some(...))
      throw unkownSignerType();

Quantus's `DilithiumSignatureScheme` carries `Dilithium87` and `Dilithium65`, so
this raised `Unkown signer` and nothing downstream ever ran. Asking the runtime
and then not believing it is the trap this whole port exists to avoid.

Everything past that point was already correct: `createV4Tx` concatenates and
compact-prefixes and never asserts a signature size, and the address prefix is
the `MultiAddress::Id` variant index read from metadata. The name whitelist only
separated the Substrate shape from the Ethereum one, and the Ethereum arm one
line above already decides that structurally. So the patch drops the names and
keeps `signature.type !== "enum"`.

pnpm `patchedDependencies`, keyed on the package name rather than a version, so
it reaches all fifteen resolved copies in the tree — the nested ones under
pjs-signer, ledger-signer, raw-tx-creator and polkadot-api itself are what
actually run.

## Evidence

Byte-for-byte against the quantus/extension#7 tier-1 harness, same call, same
nonce, same signature:

    papi assembled 7300 bytes
    IDENTICAL to the tier-1 harness

That is the corroboration this repo exists for. polkadot-api shares no code with
the five polkadot-js forks, so until now our stack had only agreed with itself.

Also verified the patch is load-bearing and narrow:

  - the unpatched copy still in the store raises `Unkown signer` on the same
    inputs, so the check really was the blocker
  - Polkadot metadata still takes the Substrate path, and still gets its `01`
    variant byte prepended when a caller names a signing type

## Networks

Quantus, Heisenberg and Planck, with the endpoints verified reachable on
2026-09-15, and Quantus as the default. The Substrate networks stay: a signature
that works on both is the only evidence that the patch widened a check rather
than broke one.

Refs #1, #3. Closes quantus/extension#7's cross-tier comparison.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012uDUodEcRbBwNRi3UCmw8f
2026-09-15 22:16:40 +03:00

31 lines
1.7 KiB
Diff

diff --git a/dist/v4.js b/dist/v4.js
index e8ec50ec7fb5d3dab4f30cbc21fe36d0416f8a9d..cddc959ac2f0f396f17c18680d3d3fb0ca310f46 100644
--- a/dist/v4.js
+++ b/dist/v4.js
@@ -21,8 +21,23 @@ const getSignerType = (metadata) => {
}
if (address.type === "AccountId20" && signature.type === "array" && signature.len === 65 && signature.value.type === "primitive" && signature.value.value === "u8")
return [1 /* Ethereum */, []];
- if (signature.type !== "enum" || ["Ecdsa", "Ed25519", "Sr25519"].some((x) => !(x in signature.value)))
- throw unkownSignerType();
+ // Quantus patch: the variant *names* are not load-bearing.
+ //
+ // Upstream required the signature enum to carry Ecdsa, Ed25519 and Sr25519.
+ // That whitelist exists only to tell the Substrate shape from the Ethereum
+ // one, and the Ethereum arm one line above already decides that structurally —
+ // AccountId20 plus a 65-byte array. Everything below this point is
+ // length-agnostic: createV4Tx concatenates whatever the signer returned and
+ // compact-prefixes the result.
+ //
+ // So this check fired before code that would have worked. Quantus's
+ // DilithiumSignatureScheme carries Dilithium87 and Dilithium65, and the
+ // metadata said so — getSignerType read the type out of the metadata and then
+ // threw the answer away in favour of three hardcoded names. Asking the runtime
+ // and then not believing it is the trap this whole port exists to avoid.
+ //
+ // See quantus/papi-console#1.
+ if (signature.type !== "enum") throw unkownSignerType();
if (address.type === "enum") {
const id = address.value["Id"];
if (id.type === "lookupEntry" && id.value.type === "AccountId32")