Repository navigation
[WIP] BIP93: Allow other human-readable parts - #2320
BenWestgate wants to merge 11 commits into
Conversation
Group the regular and long checksum definitions in the codex32 format section. Move the master-seed application profile to the end of the specification and keep seed-specific checksum motivation in the rationale. This is a behavior-neutral organization change on top of the bitcoin#2258 profile commit.
Keep the common format rules and checksum properties in one place, and replace the broad application-validity sentence with a concrete reference to the master seed requirements. Remove the redundant symbol encoder and decoder examples. Preserve their validation rules in the format and master seed text, including the encoded-length restriction for both secrets and shares. Retained checksum and interpolation code is unchanged. Checked retained Python ASTs against eb7bb6c, all 36 valid and 55 invalid vector occurrences, all six size mappings, legacy sizes, 1024 header combinations, checksum boundaries, share recovery, and nonzero padding. Link-format, README table, and whitespace checks pass. Refs: bitcoin#2258, bitcoin#2285
Let readers implement unshared master seeds from the format and master seed sections without reading the secret sharing procedures. Keep the common header and unshared-secret rules under codex32, and group share generation and recovery under SSSS-awareness. Give checksum and error correction one TOC entry each. Use bold labels for the individual checksums and generation cases, and preserve both MediaWiki anchors and GitHub permalinks for demoted headings. Put the interpolation helpers with generation and its recovery wrapper afterward. Retained executable code is unchanged. Checked the retained Python ASTs, existing valid/invalid vectors, size mappings, header combinations, checksum boundaries, recovery, and padding. Inspected the rendered TOC and table and checked fragment targets. Link-format, README table, and whitespace checks pass. Refs: bitcoin#2285
Describe seed sizes in bits in the encoding instructions, checksum rationale, and retained-size list, matching generation and the vectors. Keep bytes for decoded output and the historical contiguous byte-size range, and retain both units in the size table. The supported sizes and all numeric constraints are unchanged. The existing rationale already explains that BIP39 produces 512-bit seeds. Checked retained Python ASTs, all existing vector occurrences, size mappings, header combinations, checksum boundaries, recovery, padding, and rendered markup. Link-format, README table, and whitespace checks pass. Refs: bitcoin#2258, bitcoin#2285
Add a reverse-chronological draft changelog and matching Version header so readers can distinguish the earlier checksum-boundary and seed-size changes from this behavior-neutral reorganization. Assign retrospective versions to significant revisions and use their upstream integration dates, rather than individual patch author dates. Keep the Draft status and BSD-3-Clause license unchanged. Checked the historical entries against first-parent upstream history, the version and date ordering, and the metadata-only diff. Python ASTs, existing vectors, size and checksum boundaries, header combinations, recovery, padding, rendered markup, link formatting, README table, and whitespace checks pass. Refs: bitcoin#2258, bitcoin#2285
Define the integer-list representation once in the SSSS-awareness introduction, before either procedure needs it. Move the unchanged interpolation helpers there too, so recovery does not depend on code inside Generating shares. Describe interpolation's arguments and result beside its definition and refer to the shared representation from both generation and recovery. State that both checksum variants use the same procedures without an early reference to the interpolation function. Label the existing casing rules and remove the unnecessary word "workflows" from the rationale. No algorithms, validity conditions, version, or changelog entries change. Checked all Python blocks are byte-identical and that vectors, procedure conditions, casing rules, headings, anchors, and metadata are unchanged. Sixteen recovery cases pass using only the shared introduction and recovery snippets, covering regular and long checksums. Existing vector, size, header, checksum-boundary, recovery, and padding checks also pass. Local rendering, link formatting, README table, and whitespace checks pass; the casing label does not add a TOC entry. Refs: bitcoin#2285
Specify the human-readable part as in BIP-0173 instead of requiring "ms", so other applications, such as the registered "cl", can use the codex32 format. Master seeds and their shares keep "ms". Pass the human-readable part to the checksum functions and cover its BIP-0173 expansion, which already counts toward the checksum length limits. Rename the ms32 functions and constants that now serve every human-readable part to codex32. Results for "ms" are unchanged. Require every share in a set to have the same human-readable part, state that the interpolation helpers do not check the set conditions, and limit fresh-secret generation to applications that accept every payload, with rejection sampling allowed for those that do not. Implementations should not correct the human-readable part unless its application specifies how. Update the existing invalid-vector classifications for generalized human- readable parts. Add vectors for a Core Lightning "cl" secret, an 11-character human-readable part requiring the long checksum, the 83-character maximum, the 94-95 expanded-length gap, an uppercase human- readable-part checksum, and an overlong human-readable part. Checked the checksum functions against the previous ms32 functions for "ms" across data-part lengths 0 through 1029, and checked interpolation is unchanged. Checked every new vector with the specification's Python code and python-codex32, and checked each invalid group fails for its stated reason. Link-format, README table, and whitespace checks pass. Refs: bitcoin#2040, bitcoin#2258, bitcoin#2285
State explicitly that the checksum's substitution and erasure correction guarantees apply to errors in the data part. This avoids implying the same correction guarantees for the human-readable part.
Record the human-readable part generalization as version 0.3.0. It is a backward-compatible extension, so BIP 3 calls for a minor version bump: strings with the human-readable part "ms" are unchanged. Preamble, README table, link-format, and whitespace checks pass. Refs: bitcoin#2320
BenWestgate
left a comment
There was a problem hiding this comment.
Reviewed all through Test vectors
|
|
||
| * A human-readable part, which is the string "ms" (or "MS"). | ||
| * A separator, which is always "1". | ||
| * A human-readable part, as specified in BIP-0173. It identifies the application, which can further restrict validity. |
There was a problem hiding this comment.
Delete the second sentence?
Most specifically the application can further restrict payload validity. A BIP-0173 application HRP can define whatever it wants about the data part besides the checksum.
We additionally keep the codex32 header a normative requirement for all applications.
There was a problem hiding this comment.
I dislike the formula representation.
It may be cleaner to say maximum string length 1024 - len(hrp). any suggestions?
There was a problem hiding this comment.
This remains unresolved: whether to switch to maximum string length accounting or continue saying the payload length which is mathematically messier but potentially more useful.
| This requires an application that accepts every payload of the chosen length as a secret, as the master seed format does. | ||
| An application that does not MAY use rejection sampling instead: retry with a fresh set of shares until the resulting secret qualifies. |
There was a problem hiding this comment.
this might work better as a ref link to rationale, or placed after the fresh secret instructions so line 302 can remain unchanged.
|
|
||
| # Choose a bit size from 128, 160, 192, 224, 256, or 512 | ||
| # Choose the human-readable part of the application and a payload length it accepts | ||
| #* For a master seed, use <code>ms</code>, choose a bit size ''bitlength'' from 128, 160, 192, 224, 256, or 512, and use a payload of ceil(''bitlength / 5'') characters |
There was a problem hiding this comment.
nit: arguably doesn't need to be here.
| While we could use the 15 character checksum for both cases, we prefer to keep the strings as short as possible for the more common cases of 128-bit and 256-bit master seeds. | ||
| Longer strings mean more chances for transcription errors, so shorter strings are better. | ||
|
|
||
| If the prefix is damaged and a user is guessing that the data might be using this scheme, then the user can enter the available data explicitly using the suspected <code>MS1</code> prefix. |
There was a problem hiding this comment.
I prefer to keep this sentence. It works for MS and it's harmless to try MS1, where as replacing a damaged private HRP (e.g. xprv) with a guessed public one (e.g. xpub) could broadcast it unintentionally.
There was a problem hiding this comment.
9c5a8d3 LGTM, much better than expanding the hrp everywhere
BenWestgate
left a comment
There was a problem hiding this comment.
Much improved, requesting a couple changes.
| It reuses the base-32 character set from BIP-0173, and consists of: | ||
|
|
||
| * A human-readable part, as specified in BIP-0173. It identifies the application, which can further restrict validity. | ||
| * A human-readable part, as specified in BIP-0173. It identifies the application, which may impose additional validity requirements. |
There was a problem hiding this comment.
This second sentence should be removed. First it doesn't identify the application, it may identify a profile (of an application) but even then, some profiles like ln or the proposed <key origin>xpub use the HRP to show humans data. Removing it allows BIP-173 to remain authoritative here. We have no differences from bip173.
| In the case that the user wishes to generate a fresh secret, the user generates random initial shares, as follows. | ||
| This requires an application that accepts every payload of the chosen length as a secret, as the master seed format does. | ||
| An application that does not MAY use rejection sampling instead: retry with a fresh set of shares until the resulting secret qualifies. | ||
| If the application does not accept every payload of the chosen length, it MAY use rejection sampling: retry with a fresh set of shares until the resulting secret is valid for the application. |
There was a problem hiding this comment.
nit: technically only the last share or even only the offending characters of the last share need to be retried with fresh randomness.
| If the human-readable part is damaged and a user is guessing that the data might be using this scheme, then the user can enter the available data explicitly using the suspected human-readable part. | ||
| For master seeds, if the human-readable part is damaged, the user can enter the available data explicitly using the suspected <code>MS1</code> prefix. |
There was a problem hiding this comment.
Use the sentence:
For master seeds, if the human-readable part is damaged and a user is guessing that the data might be using this scheme, then the user can enter the available data explicitly using the suspected MS1 prefix.
Summary
Generalize codex32 so that the human-readable part is not restricted to
ms.This PR is based on top of behavior neutral #2285.
BIP-32 master seeds and their shares continue to use
ms, while otherapplications can use their own human-readable parts.
Changes
ms32checksum and interpolation helpers tocodex32.check the valid set conditions.
require rejection sampling otherwise.
application specifies how.
human-readable parts become valid.
clhuman-readable part used by Core Lightning;1;Strings using
msare unchanged.Testing
The
codex32checksum functions were checked against the previousms32functions for
msover random data parts of every length from 0 through 1029symbols, including both checksum variants, the 94–95 expanded-length gap, and
lengths beyond 1023.
The new vectors were checked with both the specification's Python code and an
independent implementation,
python-codex32. They agree except thatpython-codex32does not yet enforce the 83-character human-readable-partlimit.
Refs: #2040, #2258, #2285