Skip to content

Instantly share code, notes, and snippets.

@torkelrogstad
Created June 12, 2019 11:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save torkelrogstad/279c98643624d56e02b00b1f3d578655 to your computer and use it in GitHub Desktop.
Save torkelrogstad/279c98643624d56e02b00b1f3d578655 to your computer and use it in GitHub Desktop.
import scala.util.Success
import org.bitcoins.core.protocol.script._
import org.bitcoins.core.protocol.Bech32Address
import org.bitcoins.core.config.TestNet3
// first account -------┐
// bitcoin ----------┐ |
// segwit --------┐ | |
val accountPath = BIP32Path.fromString("m/84'/0'/0'")
// accountPath: BIP32Path = m/84'/0'/0'
val accountXpub = {
// this key is sensitive, keep away from prying eyes!
val accountXpriv = xpriv.deriveChildPrivKey(accountPath)
// this key is not sufficient to spend from, but we
// can generate addresses with it!
accountXpriv.extPublicKey
}
// accountXpub: ExtPublicKey = zpub6rFVjPLJN2jSekPmRnBZAuLXy9K82puEBdHnf7Dt9LutwRhBjHRn9iZXwJijfbcpwugM5FNQe2pHfBcXjefbf6KSj7ueP9e3qL32JVyexKr
// address no. 0 ---------------┐
// external address ----------┐ |
val firstAddressPath = SegWitHDPath.fromString("m/84'/0'/0'/0/0")
// firstAddressPath: SegWitHDPath = m/84'/0'/0'/0/0
val firstAccountAddress = {
// this is a bit quirky, but we're not interesting in
// deriving the complete path from our account xpub
// instead, we're only interested in the part after
// the account level (3rd level). the .diff() method
// achieves that
val Some(pathDiff) = accountPath.diff(firstAddressPath)
// deriving public keys from hardened extended keys
// is not possible, that's why .deriveChildPubKey()
// returns a Try[ExtPublicKey]. A hardened key is marked
// by a ' after the number in the notation we use above.
val Success(extPubKey) = accountXpub.deriveChildPubKey(pathDiff)
val pubkey = extPubKey.key
val scriptPubKey = P2WPKHWitnessSPKV0(pubkey)
Bech32Address(scriptPubKey, TestNet3)
}
// firstAccountAddress: Bech32Address = Bech32Address(tb1qdymd8a5z85d6nrafn3p7few8z7pk5spd4qejmx)
// tada! We just generated an address you can send money to,
// without having access to the private key!
firstAccountAddress.value
// res2: String = tb1qdymd8a5z85d6nrafn3p7few8z7pk5spd4qejmx
// you can now continue deriving addresses from the same public
// key, by imitating what we did above. To get the next
// HD path to generate an address at:
val nextAddressPath: SegWitHDPath = firstAddressPath.next
// nextAddressPath: SegWitHDPath = m/84'/0'/0'/0/1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment