Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature request: add bech32 descriptor checksum #12

Open
devlzcode opened this issue Jun 18, 2023 · 3 comments
Open

feature request: add bech32 descriptor checksum #12

devlzcode opened this issue Jun 18, 2023 · 3 comments

Comments

@devlzcode
Copy link

devlzcode commented Jun 18, 2023

I don't want to interfere with the code base but it'd be useful to have this added

adapted from bitcoin core:

const INPUT_CHARSET =
    "0123456789()[],'/*abcdefgh@:$%{}" +
    "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~" +
    'ijklmnopqrstuvwxyzABCDEFGH`#"\\ ',
  CHECKSUM_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";

export const addChecksum = (str: string) => `${str}#${descChecksum(str)}`;

function polymod(c: bigint, val: number): bigint {
  let c0 = Number((c >> 35n) & 31n);
  c = ((c & 0x7ffffffffn) << 5n) ^ BigInt(val);
  if (c0 & 1) c ^= 0xf5dee51989n;
  if (c0 & 2) c ^= 0xa9fdca3312n;
  if (c0 & 4) c ^= 0x1bab10e32dn;
  if (c0 & 8) c ^= 0x3706b1677an;
  if (c0 & 16) c ^= 0x644d626ffdn;
  return c;
}

function descChecksum(span: string): string {
  let c = 1n;
  let cls = 0;
  let clscount = 0;
  for (let ch of span) {
    let pos = INPUT_CHARSET.indexOf(ch);
    if (pos === -1) return "";
    c = polymod(c, pos & 31);
    cls = cls * 3 + (pos >> 5);
    if (++clscount === 3) {
      c = polymod(c, cls);
      cls = 0;
      clscount = 0;
    }
  }
  if (clscount > 0) c = polymod(c, cls);
  for (let j = 0; j < 8; ++j) c = polymod(c, 0);
  c ^= 1n;

  let ret = new Array(8).fill(" ");
  for (let j = 0; j < 8; ++j)
    ret[j] = CHECKSUM_CHARSET[Number((c >> (5n * BigInt(7 - j))) & 31n)];
  return ret.join("");
}
@paulmillr
Copy link
Owner

I think bech32 computes and verifies checksum by default. Doesn't it?

@devlzcode
Copy link
Author

devlzcode commented Jun 20, 2023

I think bech32 computes and verifies checksum by default. Doesn't it?

I'm fairly certain these are two different formats (they even have different polymod generators). This is used for creating a bitcoin-core specific checksum of an output descriptor that is used quite often and afaik is only accessible via an rpc call unless you implement it yourself. More about this here: https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md#checksums

@paulmillr
Copy link
Owner

So, this is similar to bech32, but not quite bech32, and used only for BTC core RPC calls?

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

No branches or pull requests

2 participants