Skip to content

release: land certified protocol lineage on fork master - #40

Merged
BitHighlander merged 9 commits into
masterfrom
feat/certified-solana-lut-alpha
Aug 27, 2026
Merged

release: land certified protocol lineage on fork master#40
BitHighlander merged 9 commits into
masterfrom
feat/certified-solana-lut-alpha

Conversation

@BitHighlander

Copy link
Copy Markdown
Owner

Vault v1.5.4 release dependency consolidation. Fast-forwards the BitHighlander fork master lineage to the exact device-protocol commit already pinned and validated by keepkey-vault develop. Includes protocol CI/build hardening and certified Solana delegate-certificate fields. Local verification: npm ci and npm run build pass; all 18 generated files postprocessed.

BitHighlander and others added 9 commits August 5, 2026 18:10
yarn install --frozen-lockfile fails on this branch with:
  @mapbox/node-pre-gyp@2.0.3: The engine "node" is incompatible with this
  module. Expected version ">=18". Got "17.2.0"

The unpinned legacy circleci/node image resolves to node 17.2.0. master
passes only because its older lockfile predates that transitive
requirement; any lockfile refresh trips it. Pin a maintained image.
The Ironwood enum was inserted above the file-level java_package /
java_outer_classname options, leaving them after a top-level definition.
protobufjs's parser rejects that outright:

  Error: illegal token 'option' (messages-zcash.proto, line 16)

so 'npm run build' (build:json -> lib/proto.json) fails on this branch.
protoc accepts either order, so the generated descriptors are unchanged;
every other proto in the repo already declares options directly after
syntax. Verified: pbjs now emits proto.json cleanly.
up/release-protocol carried two build fixes that exist only on this
upstream branch -- the cimg/node:20.11 CI pin and moving the zcash file
options into the preamble so pbjs can parse them -- while 34 commits of
7.15 protocol work sat on the fork's master. develop cannot pin the fork
commit, because a PR into upstream carries its submodule pins and a
reviewer cannot resolve one that exists only on a fork.

Merged rather than rebased so nothing is force-pushed over an open PR,
and so both histories stay readable.

Verified after the merge, because a clean auto-merge keeps hunks from
both sides and that is exactly how one side quietly loses:
  - cimg/node:20.11 still pinned in .circleci/config.yml
  - the zcash file options are still in the preamble
  - EthereumSignTypedData / EthereumTypedDataStructAck /
    EthereumTypedDataValueAck all present in messages-ethereum.proto
- ci: include messages-near.proto in the descriptor-validation protoc run so
  the shipped NEAR schema is actually compiled, matching both package builds
- solana: bound the KKSOLSW1 LUT fields (lut_account, lut_signature) and the
  SolanaTokenInfo attestation signature in messages-solana.options, so nanopb
  emits fixed-size fields instead of callbacks
- zcash: document the Zcash wire v2 breaking migration at the top of
  messages-zcash.proto (1307 rename and reshape, transparent output/ack
  phase, ZcashDisplayAddress 3-6 removal, compact signatures, sapling_digest)
- near: mark 1610-1613 and messages-near.proto as schema-only and not
  implemented by firmware 7.15/RC18, add messages-near.options, and move the
  Hive 1614-1617 IDs out from under the NEAR comment
- hive: drop the duplicated legacy paragraph on HiveSignAccountCreate that
  contradicted the attestation contract
The Ed25519 signature covers only SHA256(raw_tx), so the host-supplied
receiver_id and action_display were never bound to the bytes being signed.
A malicious host could display a benign receiver and action while obtaining
a signature over entirely different transaction bytes.

Reserve tags 4 and 5 so no implementation can reintroduce them, and state
the confirmation contract on the message: every value shown to the user is
derived by the device from raw_tx, and a transaction the device cannot parse
must be refused rather than displayed from host-provided text. A Borsh
NearTransaction already carries signer_id, public_key, nonce, receiver_id,
block_hash and the action list inside the signed bytes.
Hive account names are 3-16 characters (Graphene fixed_string_16), but nanopb
max_size includes the NUL terminator, so max_size:16 only admits 15 characters.
A valid 16-character account name was truncated or rejected by the generated
firmware structs. Size the five account-name fields at 17: HiveSignTx.from,
HiveSignTx.to, HiveSignAccountCreate.creator/new_account_name, and
HiveSignAccountUpdate.account.

RC18 is Orchard-only, but ZcashSignPCZT tags 19-20 advertised Ironwood /
transaction-v6 pool selection that no firmware in this release implements, so a
host selecting Ironwood could not receive the behavior the schema implied. Mark
ZCASH_SHIELDED_POOL_IRONWOOD and ironwood_digest SCHEMA ONLY on their
declarations, document that 7.15/RC18 rejects a non-Orchard pool and a present
ironwood_digest with Failure, and pin both markers plus the field declarations
in tools/check_zcash_contract.py so the schema-only status cannot silently
drift into an implied guarantee.
…b output

The build:postprocess sed matched only the generator's old single-line
`var global = Function('return this')();`. The current protoc-gen-js emits a
multi-line IIFE whose last resort is that same call, so the pattern silently
stopped matching and the dynamic-function fallback shipped in published
bindings -- it was present in all 12 generated files. Building a function from
a string is blocked under strict CSP, which is where these bindings run.

Replace the one-liner with tools/postprocess-lib.js, which rewrites the call
itself rather than the surrounding block (covering both the legacy and current
shapes) and then fails the build if any dynamic-function fallback survives.
This also drops the `sed -i ''` invocation, which is BSD-only and fails on the
GNU sed in CI and on Linux developer machines.

prepare ran only build:js, so Git-based installs got JavaScript but no
lib/proto.json -- that is produced by build:json and is present in published
packages. Point prepare at the full build so both artifact sets exist.

lib/ is gitignored generated output, but lib/messages-ripple_pb.js and its
.d.ts were committed, creating a second stale-prone source of truth. Untrack
both; they are regenerated by the build. lib/.keep stays.
…s dep

build:json invoked the bare `pbjs` bin, but two installed packages declare it:
protobufjs (whose CLI the --keep-case -t json flags actually belong to) and the
unrelated pbjs@0.0.5. On a clean `npm ci` the latter wins the .bin link, and its
vendored protocol-buffers-schema cannot parse `reserved`, so build:json died
with "Expected = but found 3" on the first reserved range it met. Stale local
node_modules linked protobufjs instead, which is why this never showed up
locally or in publish -- and why the previous prepare, which ran only build:js,
never exposed it.

Invoke ./node_modules/protobufjs/bin/pbjs explicitly, matching how build:js
already calls its generator by path, and remove pbjs from dependencies: nothing
requires it at runtime and its only effect was shadowing the real binary.
@BitHighlander
BitHighlander merged commit 23eadf8 into master Aug 27, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants