diff --git a/src/mnemonic.c b/src/mnemonic.c index 06f5f908a..510277faa 100644 --- a/src/mnemonic.c +++ b/src/mnemonic.c @@ -59,8 +59,9 @@ char *mnemonic_from_bytes(const struct words *w, const unsigned char *bytes, siz return str; } -int mnemonic_to_bytes(const struct words *w, const char *mnemonic, - unsigned char *bytes_out, size_t len, size_t *written) +int mnemonic_to_bytes_internal(const struct words *w, const char *mnemonic, + size_t(*lookup_fn)(const struct words *, const char *), + unsigned char *bytes_out, size_t len, size_t *written) { struct words *mnemonic_w = wordlist_init(mnemonic); size_t i; @@ -80,7 +81,7 @@ int mnemonic_to_bytes(const struct words *w, const char *mnemonic, wally_clear(bytes_out, len); for (i = 0; i < mnemonic_w->len; ++i) { - size_t idx = wordlist_lookup_word(w, mnemonic_w->indices[i]); + size_t idx = lookup_fn(w, mnemonic_w->indices[i]); if (!idx) { wordlist_free(mnemonic_w); wally_clear(bytes_out, len); @@ -95,3 +96,13 @@ int mnemonic_to_bytes(const struct words *w, const char *mnemonic, wordlist_free(mnemonic_w); return WALLY_OK; } + +int mnemonic_to_bytes(const struct words *w, const char *mnemonic, + unsigned char *bytes_out, size_t len, size_t *written) { + return mnemonic_to_bytes_internal(w, mnemonic, wordlist_lookup_word, bytes_out, len, written); +} + +int mnemonic_prefix_to_bytes(const struct words *w, const char *mnemonic, + unsigned char *bytes_out, size_t len, size_t *written) { + return mnemonic_to_bytes_internal(w, mnemonic, wordlist_lookup_prefix, bytes_out, len, written); +} diff --git a/src/mnemonic.h b/src/mnemonic.h index a17797680..e6060b526 100644 --- a/src/mnemonic.h +++ b/src/mnemonic.h @@ -33,4 +33,20 @@ int mnemonic_to_bytes( size_t len, size_t *written); +/** + * Convert a mnemonic representation into a block of bytes. Accepts unique prefixes of wordlist words. + * + * @w: List of words. + * @mnemonic: Mnemonic sentence to store. + * @bytes_out: Where to store the converted representation. + * @len: The length of @bytes_out in bytes. + * @written: Destination for the number of bytes written. + */ +int mnemonic_prefix_to_bytes( + const struct words *w, + const char *mnemonic, + unsigned char *bytes_out, + size_t len, + size_t *written); + #endif /* LIBWALLY_MNEMONIC_H */ diff --git a/src/wordlist.c b/src/wordlist.c index fb1481931..98bac021d 100644 --- a/src/wordlist.c +++ b/src/wordlist.c @@ -83,6 +83,24 @@ size_t wordlist_lookup_word(const struct words *w, const char *word) return found ? found - w->indices + 1u : 0u; } +size_t wordlist_lookup_prefix(const struct words *w, const char *prefix) +{ + const size_t prefix_len = strlen(prefix); + size_t found = 0; + + size_t i; + for (i = 0; i < w->len; ++i) { + if (!strncmp(prefix, w->indices[i], prefix_len)) { + if (found) { + return 0; // prefix match is not unique + } + found = i + 1; + } + } + + return found; +} + const char *wordlist_lookup_index(const struct words *w, size_t idx) { if (idx >= w->len) diff --git a/src/wordlist.h b/src/wordlist.h index c8189672e..64f758d9b 100644 --- a/src/wordlist.h +++ b/src/wordlist.h @@ -45,6 +45,19 @@ size_t wordlist_lookup_word( const struct words *w, const char *word); +/** + * Find the unique word matching a given prefix in a wordlist. + * + * @w: Parsed list of words to look up in. + * @word: The prefix to look up. + * + * Returns 0 if not found OR not unique, idx + 1 otherwise. + * @see wordlist_init. + */ +size_t wordlist_lookup_prefix( + const struct words *w, + const char *prefix); + /** * Return the Nth word in a wordlist. *