Skip to content

fix(evolution): validate RewardAccount header type and bech32 prefix (#456) - #637

Open
Kshot3000 wants to merge 1 commit into
IntersectMBO:mainfrom
Kshot3000:fix/reward-account-header-prefix-validation
Open

Kshot3000 wants to merge 1 commit into
IntersectMBO:mainfrom
Kshot3000:fix/reward-account-header-prefix-validation

Conversation

@Kshot3000

Copy link
Copy Markdown

Summary

Fixes #456. RewardAccount parsing was looser than Address parsing for the same class of input: FromBytes accepted any CIP-19 header type whose low bit matched, so a 29-byte enterprise address (type 6, header 0x61…) or a pointer address (type 4) parsed successfully as a reward account, and FromBech32 never checked the human-readable prefix, so an addr… / addr_test… string — or a stake… string whose prefix disagreed with the header's network id — decoded as a RewardAccount. This is the RewardAccount-side counterpart to #391, which added the equivalent checks on Address.

Fix

In packages/evolution/src/RewardAccount.ts, mirroring the checks already present in Address:

  • FromBytes: the header type nibble must be a reward type — 14 (stake key) or 15 (script) — anything else fails with Invalid reward address type: <type>. This also covers FromHex, which composes over FromBytes.
  • FromBech32: the decoded prefix is now retained and must be stake / stake_test (Invalid reward account prefix: <prefix> otherwise), and it must agree with the network id decoded from the header (Prefix <prefix> does not match network <id>), exactly as Address.FromBech32 does.

No encoder changes: encoding already writes header types 14/15 and the stake / stake_test prefix from the network id.

Tests

New file packages/evolution/test/RewardAccount.HeaderValidation.test.ts (6 tests), each rejection verified failing on main first (run one at a time, since this repo's vitest bails a file after the first failure):

  • enterprise (0x61…), pointer (0x41…) and base (0x01…) headers rejected from hex, with the type named in the error;
  • the enterprise header rejected from raw bytes as well;
  • the same reward payload re-encoded under addr and addr_test prefixes rejected from bech32;
  • a testnet payload under stake and a mainnet payload under stake_test both rejected for prefix/network mismatch;
  • controls that pass before and after: valid stake / stake_test round-trips for a key credential (headers 0xe1 / 0xe0), and a script-credential account (type 15, header 0xf1) round-tripping through hex and bech32.

Full package suite: 1684 passed / 75 skipped / 0 failed, test files 102 passed / 1 skipped of 103 — exactly main's 1678 baseline + the 6 new tests. tsc --noEmit and eslint clean; both touched files are prettier-clean (the source file is prettier-clean on main too). A patch changeset is included.


Independent builder — not affiliated with the Cardano Foundation, IOG or Intersect.

@Kshot9000 (https://x.com/kshot9000) · ADA: addr1q8hnl6vl5a6k3rw3n5g3jtte696zcl76kfatzv7gpswa9r0dj7fma6klq55y4ffm7tf0em09udnyhuk4ah92pl5x9jpqjae44v

cc @cardano-foundation @IntersectMBO

This branch has not been deployed

No deployments
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.

RewardAccount: validate header type bits and bech32 prefix

1 participant