Generating Vanity Addresses

Discussing Vanity Addresses generation.
Follow up of Algorand Wallet - Open Source - #20 by scholtz

The question is the speed of generating vanity addresses.
Messages moved to keep topic focused.


The PureStake python code runs faster, appr. 10 thousand tries/sec/CPU core.
For four letters it is typically 10…20 sec.
But to match five letters takes a long time even with that…
e.g.

$ ./algo_vanity.py SCHOL
Detected 4 cpu(s)
Found a match for SCHOL after 15733226 tries in 422.53 seconds
Address:  SCHOLEJCKQ5L322NSZVECTUESR3Z5TG46SUZIWOMS6VOF3YXFO6RP7IPTE
Private key:  fix robot already recall digital punch kingdom boring spirit issue shaft seminar grape beef mixed assume entry when sweet soup venture duck flock abstract art
1 Like

You can be much faster if you’re ok with multisig accounts.
You first generate a public key / secret key.
And then you generate 1-out-of-2 multisig accounts with the second account being a random public key (to be on the safe side, you may consider hashing a random value with SHA256).
This will cost you 1 or 2 SHA256 hash per try, as opposed to 1 ED25519 key generation.

2 Likes

Hi, @fabrice , I have a question connected with your suggestion about using 1-of-2 multisig for vanity address generation.

You proposed to use 1-of-2 multisig, where the first address has private and public key, (a “standard” account), but the second is a “fake” address, having a public key, chosen arbitrarily?

Then the multisig address is generated from these two addresses with a hash, like we can see in the code below, taken from js-sdk?

export function fromMultisigPreImg({
  version,
  threshold,
  pks,
}: Omit<MultisigMetadata, 'addrs'> & {
  pks: Uint8Array[];
}) {
  if (version !== 1 || version > 255 || version < 0) {
    // ^ a tad redundant, but in case in the future version != 1, still check for uint8
    throw new Error(INVALID_MSIG_VERSION_ERROR_MSG);
  }
  if (
    threshold === 0 ||
    pks.length === 0 ||
    threshold > pks.length ||
    threshold > 255
  ) {
    throw new Error(INVALID_MSIG_THRESHOLD_ERROR_MSG);
  }
  const pkLen = ALGORAND_ADDRESS_BYTE_LENGTH - ALGORAND_CHECKSUM_BYTE_LENGTH;
  if (pkLen !== nacl.PUBLIC_KEY_LENGTH) {
    throw new Error(UNEXPECTED_PK_LEN_ERROR_MSG);
  }
  const merged = new Uint8Array(
    MULTISIG_PREIMG2ADDR_PREFIX.length + 2 + pkLen * pks.length
  );
  merged.set(MULTISIG_PREIMG2ADDR_PREFIX, 0);
  merged.set([version], MULTISIG_PREIMG2ADDR_PREFIX.length);
  merged.set([threshold], MULTISIG_PREIMG2ADDR_PREFIX.length + 1);
  for (let i = 0; i < pks.length; i++) {
    if (pks[i].length !== pkLen) {
      throw new Error(INVALID_MSIG_PK_ERROR_MSG);
    }
    merged.set(pks[i], MULTISIG_PREIMG2ADDR_PREFIX.length + 2 + i * pkLen);
  }
  return new Uint8Array(nacl.genericHash(merged));
}
1 Like

yes

You can directly call the JS function of the SDK.

Why not use GPU and OpenCL?