1

Here's my code to get a child public key from a parent HD key. I adapted it from freedomnode:

  public function address_from_master_pub($path = '0/0') {
    if ($this->xpub === NULL && $this->ypub === NULL && $this->zpub === NULL) {
      throw new Exception("XPUB, YPUB or ZPUB key is not present!");
    }

    $adapter = Bitcoin::getEcAdapter();
    $slip132 = new Slip132(new KeyToScriptHelper($adapter));
    $registry_classname = 'BitWasp\\Bitcoin\\Network\\Slip132\\'.$this->network_name.'Registry';
    $bitcoin_prefixes = new $registry_classname();

    if ($this->xpub !== NULL) {
      $pubPrefix = $slip132->p2pkh($bitcoin_prefixes);
      $pub = $this->xpub;
    } else if ($this->ypub !== NULL) {
      $pubPrefix = $slip132->p2shP2wpkh($bitcoin_prefixes);
      $pub = $this->ypub;
    } else if ($this->zpub !== NULL) {
      $pubPrefix = $slip132->p2wpkh($bitcoin_prefixes);
      $pub = $this->zpub;
    }

    $config = new GlobalPrefixConfig([
      new NetworkConfig($this->network, [
        $pubPrefix,
      ])
    ]);

    $serializer = new Base58ExtendedKeySerializer(
      new ExtendedKeySerializer($adapter, $config)
    );

    $key = $serializer->parse($this->network, $pub);
    $child_key = $key->derivePath($path);

    return $child_key->getAddress(new AddressCreator())->getAddress();
  }

If I use it for index 0 or 1 or 2 (paths 0/0, 0/1, 0/2), it works fine in the sense that if I send bitcoin to that address, I can see the transaction on the public blockchain under the parent xpub on blockchain.com and it shows the funds. Plus, the child addresses which I generate match what shows up in Mycelium HD account receiving address.

But when I used index 243 (thus creating a path of 0/243 it didn't show up on the receiving end (under that xpub) even though it showed up on my sending end as a confirmed transaction. That path 0/243 generated a valid bitcoin address, but it didn't show up under that xpub on blockchain.com even after it was confirmed.

What's the rule involved? If i > some limit it no longer works? Or if I use an index "out of order" it doesn't work? Or something else, like Mycelium stopping recognizing child addresses past a certain index (i) and really the fundsa safa just under a higher level new HD xpub? I used the same code to generate all the child addresses for i = 0, 1, 2, and 243.

5

Mycelium HD is BIP 44 compliant. As specified by BIP 44, the address gap limit is 20. This means that after 20 indexes of unused addresses, the wallet expects that no more addresses are used beyond that point. Therefore if you send funds to an address with a gap of more than 20 indexes between the last used address, the wallet software will not check if that address has received any funds.

  • oh so they did get the money. It just won't show up until they use 223 other addresses first, in this case! Kinda wild. This is actually good news. I was afraid there was a limit on i. – toddmo Jul 9 '18 at 17:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.