You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Tracking] Namecoin name-operation script recognition on signing screen
Summary
Namecoin (NMC) has been a first-class supported coin in trezor-firmware since 1.5.2, with two production blockbook backends operated by SatoshiLabs. The current support handles NMC as a Bitcoin clone for payments — UTXO sends and receives work end-to-end.
What is missing is recognition of Namecoin's name-operation outputs. A Namecoin transaction that registers, renews, or updates a name carries a small, fully OP_DROP-consumed prelude before the standard address script. Today, when a PSBT containing such an output is presented to the device, the signing screen has no way to render it as a known operation type — the user either sees the inner address script with the prelude bytes treated as an unparsable preamble, or the tx is flagged in a way that downgrades the device to a blind signer for the most security-sensitive use case Namecoin actually has: name ownership.
This issue proposes a narrow, gated change to make the signing screen recognise the three name-operation preludes (name_new, name_firstupdate, name_update), classify them, and render them with op-specific structured confirmations — without touching the generic Bitcoin signing path, without expanding any consensus surface, and without changing host behaviour.
Why this matters
NMC's high-value use case on a hardware wallet is not "send some NMC to an address". It is owning and updating a name — exactly the rare, high-stakes, high-blast-radius operation that hardware wallets exist to make safe. A name_update on d/mydomain whose value is rewritten to point at an attacker-controlled key is the Namecoin-equivalent of a malicious ERC-20 approve — and right now Trezor cannot show the user what they are about to sign.
Concrete user base
A growing real-world consumer of Namecoin names is the Nostr client Amethyst, which resolves Namecoin names as NIP-05 DNS identifiers (<name>@<relay>.bit-style) and gives users a censorship-resistant alternative to centralised DNS providers for their Nostr identity. As Amethyst's Namecoin integration ships to more users, the audience holding names worth protecting on a hardware wallet grows directly.
Today those users have two storage options for the key that controls their .bit identity:
Namecoin Core / Electrum-NMC software wallets — hot keys on a general-purpose computer.
A gpg-encrypted seed file — better, but still online during signing.
Neither is what someone with a long-held, high-value name actually wants. The natural answer is the same answer Bitcoin and Ethereum users settled on a decade ago: a hardware wallet that displays what you're about to sign on its trusted screen. Trezor already supports NMC as a payment coin; this issue closes the loop for the operations that matter.
The fix is mechanical, additive, and gated.
Background — name-op script shape
For reviewers unfamiliar with NMC's consensus rules, the prelude before the address script is one of:
<addr_script> is a standard address script controlled by an HD-derived key the device already knows how to sign for.
The prelude is provably stripped by the consensus interpreter via the OP_DROPs before the address script runs.
name ≤ 255 bytes, value ≤ 520 bytes, hash is exactly 20 bytes, rand is exactly 20 bytes. All bounded.
The prelude does not affect the sighash structure — sighash is unchanged.
Address-type scope for T1
Namecoin consensus does not constrain the inner address-script type — CNameScript in namecoin-core/src/script/names.cpp parses the prelude and treats whatever bytes remain as the inner address script, with no further inner-script validation. P2PKH, P2SH, P2WPKH, P2WSH, P2TR, or even bare multisig are all legal inner scripts from a consensus standpoint.
The settled facts on the NMC side:
Segwit has been active on Namecoin mainnet since block 475000 (namecoin-core/src/kernel/chainparams.cpp:116: consensus.SegwitHeight = 475000). This activation is years old — segwit is not a future or pending soft fork on NMC.
The bech32 HRP for Namecoin mainnet is "nc" (chainparams.cpp:189; testnet "tn", regtest "ncrt").
The P2SH base58 prefix is 13 (chainparams.cpp:183), set by Daniel Kraft in 4b33389f2e ("Set P2SH address prefix for namecoin.") on 2014-12-22. Trezor's namecoin.json has carried address_type_p2sh: 5 since well before that — for more than a decade — which means sending to a Namecoin P2SH address through Trezor today is broken, independent of name ops.
namecoin-core's wallet RPCs (name_new, name_firstupdate, name_update) honour wallet.m_default_address_type (src/wallet/rpc/walletnames.cpp:122). A user with their wallet's default address type set to bech32 produces P2WPKH inner scripts in name operations today, in production. A user with p2sh-segwit defaults produces P2SH-wrapped P2WPKH inner scripts.
Given that, the PR landing under this issue covers all of:
Recognise + display + sign the three name-op preludes (the core T1 ask), gated behind coin.has_name_ops.
Enable segwit for Namecoin in the coin definition. The change flips segwit: false → true, sets bech32_prefix: null → "nc", and populates the two segwit xpub magics (xpub_magic_segwit_p2sh, xpub_magic_segwit_native) so the device can derive nc1q... and Namecoin P2SH-P2WPKH receive addresses. The signer's existing bech32 path handles nc1q... outputs unchanged; the work is in the coin def and in the name-op wrapper. output_derive_name_op_script is widened to accept P2PKH, P2SH, P2WPKH, and P2WSH as legal inner shapes — the four shapes namecoin-core's wallet emits — and rejects anything else (notably witness v1 / taproot) with a clear DataError.
Correct the long-stale address_type_p2sh value from 5 to 13. This is independent of name ops but rides this PR because the name-op path needs to accept P2SH inner scripts to match namecoin-core's wallet output. The fix is its own commit and could be cherry-picked separately if a reviewer prefers.
SLIP-132 magic choice for segwit xpubs. Namecoin is not registered in SLIP-132. The PR reuses the Bitcoin ypub/zpub magics (0x049d7cb2 / 0x04b24746) because electrum-nmc and the existing Namecoin segwit-wallet ecosystem already use them in production. A future SLIP-132 registration for NMC could replace these without breaking existing users.
Out of scope for T1, deferred:
Taproot inner scripts. NMC mainnet taproot deployment state needs separate verification first; once that is settled, taproot becomes a follow-up that flips taproot: false → true and adds witness v1 to the inner-script acceptance set.
Suite-side composer UI for browsing / building name ops (T2 in the ladder).
Blockbook --names index (T3, only if T2 needs server-side enumeration).
Verified current state
common/defs/bitcoin/namecoin.json — address_type: 52, slip44: 7, signed_message_header: "Namecoin Signed Message:\n", segwit: false, taproot: false, maintainer Pavol Rusnak <stick@satoshilabs.com>.
core/src/apps/bitcoin/scripts_decred.py — structural precedent: a separate chain-specific script module that imports from scripts.py and is invoked from the signer when coin.decred is true. The proposal below mirrors this exactly.
Proposed change (T1)
Strictly the signing-screen recognition path. No host changes, no PSBT field changes, no signing-algorithm changes.
Files touched
common/defs/bitcoin/namecoin.json
Add "has_name_ops": true.
core/src/apps/common/coininfo.py
Add has_name_ops: bool (default False), populated from coin def. Same pattern as the existing decred / overwintered flags.
Returns one of three discriminated variants: NameNew(hash), NameFirstupdate(name, rand, value, addr_script), NameUpdate(name, value, addr_script).
Returns None when the script is not a name op — caller falls back to the standard classifier.
Mirrors scripts_decred.py shape; ~150 lines, pure parser, no I/O.
core/src/apps/bitcoin/sign_tx/bitcoin.py (or the equivalent confirm-output dispatch point)
For each output: if coin.has_name_ops, attempt parse_name_op_output(). On match, route to the new confirmation screen instead of the standard "send X to ADDR" screen. On no match, behaviour is byte-identical to today.
core/src/apps/bitcoin/sign_tx/layout.py
confirm_namecoin_op(ctx, op, addr, amount) — three layout variants:
NAME_NEW — show truncated commitment hash, recipient address, amount, and a warning that name_firstupdate must follow within 36 hours.
NAME_FIRSTUPDATE — show name (UTF-8 with non-printable byte escape), value (scrollable, truncated for display), recipient address, amount.
NAME_UPDATE — show name, value (scrollable, truncated for display), recipient address, amount.
tests/device_tests/bitcoin/test_namecoin.py (new)
Three canned PSBT fixtures, one per op kind.
Assert the confirm-output dialog is the new layout, not the generic one.
Assert the signed transaction matches a pre-computed reference vector.
Out of scope for T1
Name-op construction in firmware. Host software (Suite, namecoind, etc.) builds the prelude; the device only parses and presents.
PSBT field extensions. The prelude is already part of the standard scriptPubKey field — nothing new is needed in PSBT.
Suite UI for managing names (proposed as a separate T2 issue once T1 lands).
Emoji / Unicode-normalised name rendering. T1 shows bytes with non-printable escape; pretty rendering is a host-side concern.
AuxPoW header validation. Not relevant at signing time.
Every change is dead code unless coin.has_name_ops is true, which is only set on namecoin.json. Other coin signers are unaffected.
The new module is byte-counted on firmware (T1B1 size budget is the binding constraint). The parser is ~150 lines of MicroPython; preliminary estimate well within budget. Final number will be on the PR.
No new dependencies. No new crypto. No new sighash variants.
PR ladder (intent, for context only — not asking for blanket sign-off)
T2 (separate issue, after T1 ack): Suite UI for browsing / composing name ops, depends on T1.
T3 (separate issue, after T2 if needed): blockbook --names index, only if T2 needs server-side enumeration.
T1 stands on its own. T2/T3 are mentioned only so reviewers can see the shape of the larger plan and confirm T1 is scoped tightly.
Open questions for maintainers
Is the scripts_namecoin.py module shape — mirroring scripts_decred.py — the right precedent? Or would you prefer the parser live inline under a feature flag in scripts.py?
Acceptable to add has_name_ops to coininfo.py, or would you prefer a more generic script_prefix_protocol enum that future chains could reuse?
Firmware size budget concerns for T1B1 — would you like a preliminary build size delta posted in this issue before any PR is opened?
Three confirmation-screen mockups can be attached here (PNG) before the PR — preference for them as comments on this issue, or wait for the PR?
Next step
Awaiting maintainer signal on this issue before any PR is opened. Once acknowledged, the PR will:
Land as a single, narrow change against core/.
Include the emulator test (pytest tests/device_tests/bitcoin/test_namecoin.py via core/emu.py).
Be opened from mstrofnone/trezor-firmware:feat/namecoin-name-ops-display.
Thanks for your time reviewing this. NMC has been quietly supported here for nine years; making the name-op surface trustworthy on-device — and bringing the coin def into line with namecoin-core reality (segwit, correct P2SH prefix) — finally closes the gap that matters for the use case where a hardware wallet earns its keep.
The target user is concrete: Nostr clients like Amethyst resolve Namecoin names as NIP-05 DNS identifiers, giving users a censorship-resistant alternative to centralised DNS for their identity. As that audience grows, the people holding .bit names worth protecting want what every Bitcoin and Ethereum holder eventually wants: a hardware wallet that displays what they're about to sign, instead of namecoin.org's software wallets or a gpg-encrypted seed file. Trezor already supports NMC for payments; this PR closes the loop for the operations that actually matter.
Status
PR drafted:trezor/trezor-firmware#7010 — opened as a draft from mstrofnone/trezor-firmware:feat/namecoin-name-ops-display. 14 commits covering name-op recognition + display + sign, the segwit enable, the P2SH-prefix fix, and the test coverage described above. Ready for maintainer feedback; happy to split the P2SH-prefix fix into a precursor PR if you'd prefer.
[Tracking] Namecoin name-operation script recognition on signing screen
Summary
Namecoin (NMC) has been a first-class supported coin in
trezor-firmwaresince1.5.2, with two production blockbook backends operated by SatoshiLabs. The current support handles NMC as a Bitcoin clone for payments — UTXO sends and receives work end-to-end.What is missing is recognition of Namecoin's name-operation outputs. A Namecoin transaction that registers, renews, or updates a name carries a small, fully
OP_DROP-consumed prelude before the standard address script. Today, when a PSBT containing such an output is presented to the device, the signing screen has no way to render it as a known operation type — the user either sees the inner address script with the prelude bytes treated as an unparsable preamble, or the tx is flagged in a way that downgrades the device to a blind signer for the most security-sensitive use case Namecoin actually has: name ownership.This issue proposes a narrow, gated change to make the signing screen recognise the three name-operation preludes (
name_new,name_firstupdate,name_update), classify them, and render them with op-specific structured confirmations — without touching the generic Bitcoin signing path, without expanding any consensus surface, and without changing host behaviour.Why this matters
NMC's high-value use case on a hardware wallet is not "send some NMC to an address". It is owning and updating a name — exactly the rare, high-stakes, high-blast-radius operation that hardware wallets exist to make safe. A
name_updateond/mydomainwhose value is rewritten to point at an attacker-controlled key is the Namecoin-equivalent of a malicious ERC-20approve— and right now Trezor cannot show the user what they are about to sign.Concrete user base
A growing real-world consumer of Namecoin names is the Nostr client Amethyst, which resolves Namecoin names as NIP-05 DNS identifiers (
<name>@<relay>.bit-style) and gives users a censorship-resistant alternative to centralised DNS providers for their Nostr identity. As Amethyst's Namecoin integration ships to more users, the audience holding names worth protecting on a hardware wallet grows directly.Today those users have two storage options for the key that controls their
.bitidentity:gpg-encrypted seed file — better, but still online during signing.Neither is what someone with a long-held, high-value name actually wants. The natural answer is the same answer Bitcoin and Ethereum users settled on a decade ago: a hardware wallet that displays what you're about to sign on its trusted screen. Trezor already supports NMC as a payment coin; this issue closes the loop for the operations that matter.
The fix is mechanical, additive, and gated.
Background — name-op script shape
For reviewers unfamiliar with NMC's consensus rules, the prelude before the address script is one of:
Properties:
<addr_script>is a standard address script controlled by an HD-derived key the device already knows how to sign for.OP_DROPs before the address script runs.name≤ 255 bytes,value≤ 520 bytes,hashis exactly 20 bytes,randis exactly 20 bytes. All bounded.Address-type scope for T1
Namecoin consensus does not constrain the inner address-script type —
CNameScriptinnamecoin-core/src/script/names.cppparses the prelude and treats whatever bytes remain as the inner address script, with no further inner-script validation. P2PKH, P2SH, P2WPKH, P2WSH, P2TR, or even bare multisig are all legal inner scripts from a consensus standpoint.The settled facts on the NMC side:
namecoin-core/src/kernel/chainparams.cpp:116:consensus.SegwitHeight = 475000). This activation is years old — segwit is not a future or pending soft fork on NMC."nc"(chainparams.cpp:189; testnet"tn", regtest"ncrt").13(chainparams.cpp:183), set by Daniel Kraft in4b33389f2e("Set P2SH address prefix for namecoin.") on 2014-12-22. Trezor'snamecoin.jsonhas carriedaddress_type_p2sh: 5since well before that — for more than a decade — which means sending to a Namecoin P2SH address through Trezor today is broken, independent of name ops.namecoin-core's wallet RPCs (name_new,name_firstupdate,name_update) honourwallet.m_default_address_type(src/wallet/rpc/walletnames.cpp:122). A user with their wallet's default address type set to bech32 produces P2WPKH inner scripts in name operations today, in production. A user withp2sh-segwitdefaults produces P2SH-wrapped P2WPKH inner scripts.Given that, the PR landing under this issue covers all of:
coin.has_name_ops.segwit: false → true, setsbech32_prefix: null → "nc", and populates the two segwit xpub magics (xpub_magic_segwit_p2sh,xpub_magic_segwit_native) so the device can derivenc1q...and Namecoin P2SH-P2WPKH receive addresses. The signer's existing bech32 path handlesnc1q...outputs unchanged; the work is in the coin def and in the name-op wrapper.output_derive_name_op_scriptis widened to accept P2PKH, P2SH, P2WPKH, and P2WSH as legal inner shapes — the four shapesnamecoin-core's wallet emits — and rejects anything else (notably witness v1 / taproot) with a clearDataError.address_type_p2shvalue from5to13. This is independent of name ops but rides this PR because the name-op path needs to accept P2SH inner scripts to matchnamecoin-core's wallet output. The fix is its own commit and could be cherry-picked separately if a reviewer prefers.0x049d7cb2/0x04b24746) becauseelectrum-nmcand the existing Namecoin segwit-wallet ecosystem already use them in production. A future SLIP-132 registration for NMC could replace these without breaking existing users.Out of scope for T1, deferred:
taproot: false → trueand adds witness v1 to the inner-script acceptance set.--namesindex (T3, only if T2 needs server-side enumeration).Verified current state
common/defs/bitcoin/namecoin.json—address_type: 52,slip44: 7,signed_message_header: "Namecoin Signed Message:\n",segwit: false,taproot: false, maintainerPavol Rusnak <stick@satoshilabs.com>.common/defs/support.json—bitcoin:NMCsupported since1.5.2on T1B1; firmware noted as "not for T2B1 (Drop coins support for T2B1 #2793)" on model R.common/defs/blockchain_link.json— official backendshttps://nmc1.trezor.io,https://nmc2.trezor.io.core/src/apps/bitcoin/scripts.py— generic output-script classifier; no name-op awareness.core/src/apps/bitcoin/scripts_decred.py— structural precedent: a separate chain-specific script module that imports fromscripts.pyand is invoked from the signer whencoin.decredis true. The proposal below mirrors this exactly.Proposed change (T1)
Strictly the signing-screen recognition path. No host changes, no PSBT field changes, no signing-algorithm changes.
Files touched
common/defs/bitcoin/namecoin.json"has_name_ops": true.core/src/apps/common/coininfo.pyhas_name_ops: bool(defaultFalse), populated from coin def. Same pattern as the existingdecred/overwinteredflags.core/src/apps/bitcoin/scripts_namecoin.py(new)parse_name_op_output(script: bytes) -> NameOp | NoneNameNew(hash),NameFirstupdate(name, rand, value, addr_script),NameUpdate(name, value, addr_script).Nonewhen the script is not a name op — caller falls back to the standard classifier.scripts_decred.pyshape; ~150 lines, pure parser, no I/O.core/src/apps/bitcoin/sign_tx/bitcoin.py(or the equivalent confirm-output dispatch point)coin.has_name_ops, attemptparse_name_op_output(). On match, route to the new confirmation screen instead of the standard "send X to ADDR" screen. On no match, behaviour is byte-identical to today.core/src/apps/bitcoin/sign_tx/layout.pyconfirm_namecoin_op(ctx, op, addr, amount)— three layout variants:name_firstupdatemust follow within 36 hours.tests/device_tests/bitcoin/test_namecoin.py(new)Out of scope for T1
scriptPubKeyfield — nothing new is needed in PSBT.Gating and risk surface
coin.has_name_opsis true, which is only set onnamecoin.json. Other coin signers are unaffected.PR ladder (intent, for context only — not asking for blanket sign-off)
has_name_ops.--namesindex, only if T2 needs server-side enumeration.T1 stands on its own. T2/T3 are mentioned only so reviewers can see the shape of the larger plan and confirm T1 is scoped tightly.
Open questions for maintainers
scripts_namecoin.pymodule shape — mirroringscripts_decred.py— the right precedent? Or would you prefer the parser live inline under a feature flag inscripts.py?has_name_opstocoininfo.py, or would you prefer a more genericscript_prefix_protocolenum that future chains could reuse?Next step
Awaiting maintainer signal on this issue before any PR is opened. Once acknowledged, the PR will:
core/.pytest tests/device_tests/bitcoin/test_namecoin.pyviacore/emu.py).mstrofnone/trezor-firmware:feat/namecoin-name-ops-display.Thanks for your time reviewing this. NMC has been quietly supported here for nine years; making the name-op surface trustworthy on-device — and bringing the coin def into line with
namecoin-corereality (segwit, correct P2SH prefix) — finally closes the gap that matters for the use case where a hardware wallet earns its keep.The target user is concrete: Nostr clients like Amethyst resolve Namecoin names as NIP-05 DNS identifiers, giving users a censorship-resistant alternative to centralised DNS for their identity. As that audience grows, the people holding
.bitnames worth protecting want what every Bitcoin and Ethereum holder eventually wants: a hardware wallet that displays what they're about to sign, instead ofnamecoin.org's software wallets or agpg-encrypted seed file. Trezor already supports NMC for payments; this PR closes the loop for the operations that actually matter.Status
PR drafted: trezor/trezor-firmware#7010 — opened as a draft from
mstrofnone/trezor-firmware:feat/namecoin-name-ops-display. 14 commits covering name-op recognition + display + sign, the segwit enable, the P2SH-prefix fix, and the test coverage described above. Ready for maintainer feedback; happy to split the P2SH-prefix fix into a precursor PR if you'd prefer.