mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-22 16:44:20 +01:00
98 lines
2.9 KiB
C
98 lines
2.9 KiB
C
#include "internal.h"
|
|
#include "mnemonic.h"
|
|
#include "wordlist.h"
|
|
|
|
#define U8_AT(bytes, pos) (bytes)[(pos) / 8u]
|
|
#define U8_MASK(pos) (1u << (7u - (pos) % 8u))
|
|
|
|
/* Get n'th value (of w->bits length) from bytes */
|
|
static size_t extract_index(size_t bits, const unsigned char *bytes_in, size_t n)
|
|
{
|
|
size_t pos, end, value;
|
|
for (pos = n * bits, end = pos + bits, value = 0; pos < end; ++pos)
|
|
value = (value << 1u) | !!(U8_AT(bytes_in, pos) & U8_MASK(pos));
|
|
return value;
|
|
}
|
|
|
|
/* Store n'th value (of w->bits length) to bytes
|
|
* Assumes: 1) the bits we are writing to are zero
|
|
* 2) value fits within w->bits
|
|
*/
|
|
static void store_index(size_t bits, unsigned char *bytes_out, size_t n, size_t value)
|
|
{
|
|
size_t i, pos;
|
|
for (pos = n * bits, i = 0; i < bits; ++i, ++pos)
|
|
if (value & (1u << (bits - i - 1u)))
|
|
U8_AT(bytes_out, pos) |= U8_MASK(pos);
|
|
}
|
|
|
|
char *mnemonic_from_bytes(const struct words *w, const unsigned char *bytes_in, size_t len_in)
|
|
{
|
|
size_t total_bits = len_in * 8u; /* bits in 'bytes' */
|
|
size_t total_mnemonics = total_bits / w->bits; /* Mnemonics in 'bytes' */
|
|
size_t i, str_len = 0;
|
|
char *str = NULL;
|
|
|
|
/* Compute length of result */
|
|
for (i = 0; i < total_mnemonics; ++i) {
|
|
size_t idx = extract_index(w->bits, bytes_in, i);
|
|
size_t mnemonic_len = strlen(w->indices[idx]);
|
|
|
|
str_len += mnemonic_len + 1; /* +1 for following separator or NUL */
|
|
}
|
|
|
|
/* Allocate and fill result */
|
|
if (str_len && (str = wally_malloc(str_len))) {
|
|
char *out = str;
|
|
|
|
for (i = 0; i < total_mnemonics; ++i) {
|
|
size_t idx = extract_index(w->bits, bytes_in, i);
|
|
size_t mnemonic_len = strlen(w->indices[idx]);
|
|
|
|
memcpy(out, w->indices[idx], mnemonic_len);
|
|
out[mnemonic_len] = ' '; /* separator */
|
|
out += mnemonic_len + 1;
|
|
}
|
|
str[str_len - 1] = '\0'; /* Overwrite the last separator with NUL */
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
int mnemonic_to_bytes(const struct words *w, const char *mnemonic,
|
|
unsigned char *bytes_out, size_t len, size_t *written)
|
|
{
|
|
struct words *mnemonic_w = wordlist_init(mnemonic);
|
|
size_t i;
|
|
|
|
if (written)
|
|
*written = 0;
|
|
|
|
if (!mnemonic_w)
|
|
return WALLY_ENOMEM;
|
|
|
|
if (!w || !bytes_out || !len)
|
|
return WALLY_EINVAL;
|
|
|
|
if ((mnemonic_w->len * w->bits + 7u) / 8u > len)
|
|
goto cleanup; /* Return the length we would have written */
|
|
|
|
clear(bytes_out, len);
|
|
|
|
for (i = 0; i < mnemonic_w->len; ++i) {
|
|
size_t idx = wordlist_lookup_word(w, mnemonic_w->indices[i]);
|
|
if (!idx) {
|
|
wordlist_free(mnemonic_w);
|
|
clear(bytes_out, len);
|
|
return WALLY_EINVAL;
|
|
}
|
|
store_index(w->bits, bytes_out, i, idx - 1);
|
|
}
|
|
|
|
cleanup:
|
|
if (written)
|
|
*written = (mnemonic_w->len * w->bits + 7u) / 8u;
|
|
wordlist_free(mnemonic_w);
|
|
return WALLY_OK;
|
|
}
|