Current section
Files
Jump to
Current section
Files
lib/key/public_key/serialization.ex
defmodule BitcoinLib.Key.PublicKey.Serialization do
@moduledoc """
Extended public key serialization module
To test the results, use https://www.npmjs.com/package/@swan-bitcoin/xpub-cli
Serialization types: https://github.com/satoshilabs/slips/blob/master/slip-0132.md
"""
@xpub_version_bytes 0x0488B21E
@ypub_version_bytes 0x049D7CB2
@zpub_version_bytes 0x04B24746
alias BitcoinLib.Crypto
alias BitcoinLib.Key.PublicKey
@doc """
Serialization of a master public key into an exportable version
## Examples
values from https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#test-vector-1
iex> %BitcoinLib.Key.PublicKey{
...> key: 0x339A36013301597DAEF41FBE593A02CC513D0B55527EC2DF1050E2E8FF49C85C2,
...> chain_code: 0x873DFF81C02F525623FD1FE5167EAC3A55A049DE3D314BB42EE227FFED37D508,
...> depth: 0,
...> index: 0,
...> parent_fingerprint: 0
...> }
...> |> BitcoinLib.Key.PublicKey.Serialization.serialize()
{
:ok,
"xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
}
"""
@spec serialize(%PublicKey{}, :xpub | :ypub | :zpub) :: {:ok, binary()} | {:error, binary()}
def serialize(%PublicKey{} = pub_key, :xpub) do
{:ok, execute(pub_key, @xpub_version_bytes)}
end
def serialize(%PublicKey{} = pub_key, :ypub) do
{:ok, execute(pub_key, @ypub_version_bytes)}
end
def serialize(%PublicKey{} = pub_key, :zpub) do
{:ok, execute(pub_key, @zpub_version_bytes)}
end
def serialize(%PublicKey{}, _) do
{:error, "unknown serialization format"}
end
@spec execute(%PublicKey{}, integer()) :: binary()
defp execute(
%PublicKey{
key: key,
depth: depth,
index: index,
parent_fingerprint: parent_fingerprint,
chain_code: chain_code
},
version_bytes
) do
data = <<
version_bytes::32,
depth::8,
parent_fingerprint::bitstring-32,
index::32,
chain_code::bitstring-256,
key::bitstring-264
>>
<<
data::bitstring,
Crypto.checksum(data)::bitstring
>>
|> Base58.encode()
end
end