Caminhos de Derivação

A localização das chaves e endereços em uma carteira HD

🛠️ Tradução em andamento — esta página mostra o conteúdo básico; a versão integral será publicada em breve.

BIP 44, BIP 49, BIP 84

Um caminho de derivação fornece a localização de chaves (e endereços) em uma carteira HD.

O legal das chaves estendidas é que elas podem derivar filhas, e essas chaves filhas podem derivar mais filhas, e assim por diante. Isso permite criar uma árvore de chaves estendidas, com cada chave tendo seu próprio caminho de derivação único a partir da chave mestra.

Você pode derivar chaves da forma que quiser. Mas para ajudar na compatibilidade entre carteiras, temos uma estrutura definida para como derivamos chaves para uso em uma carteira hierárquica determinística.

Os caminhos de derivação mais comuns usados no Bitcoin são:

Carteiras Bitcoin usam caminhos de derivação comuns para derivar novos endereços. Isso ajuda na compatibilidade e recuperação de chaves entre diferentes carteiras.

Caminhos de Derivação

ou seed usando um caminho de derivação especificado.>Derive múltiplas chaves privadas e endereços a partir de uma

0 bytes

, indique um caminho completo até uma chave filha específica. Por exemplo, os caminhos costumam ser encurtados para m/44'/0'/0', mas isso pressupõe que você quer a primeira chave da seção de recebimento, que é m/44'/0'/0'/0/0. Em outras palavras, talvez você precise adicionar /0/0 ao caminho base que vem da carteira para obter os endereços esperados.>Começando com

m / propósito' / tipo de moeda' / conta' / recebimento ou troca / índice

Chaves e endereços

Nunca introduzcas tu seed en un sitio, ni uses una seed generada por un sitio. Los sitios pueden guardar fácilmente la seed y usarla para robar todos tus bitcoins.

Notação

O que um caminho de derivação significa?

Primeiro, temos uma notação básica para descrever o caminho de derivação para uma chave privada estendida específica em uma carteira HD.

Por exemplo:

m/0/1/3'
Diagrama explicando a notação de um caminho de derivação.

Você pode derivar até 4.294.967.296 (pouco mais de 4 bilhões) de filhas de uma única chave estendida. A primeira metade é para filhas normais, e a segunda metade é para filhas endurecidas.

  • Derivar filhas endurecidas é o padrão. Filhas normais só são derivadas quando seria útil ter uma chave pública estendida correspondente para derivar chaves públicas independentemente.
  • As chaves e endereços que você usa em uma carteira HD típica serão de uma filha normal. Isso significa que você pode usar a chave pública estendida pai para gerar endereços em um computador diferente para receber pagamentos sem expor as chaves privadas naquele computador.

A sintaxe ' evita ter que escrever os números de índice completos para filhas endurecidas. Por exemplo, 3' significa índice 2147483651 (ou 2147483648 + 3).

Estrutura da Carteira

Para ajudar na consistência entre carteiras, o BIP 44 introduziu a seguinte estrutura para carteiras HD:

m / propósito' / tipo_de_moeda' / conta' / troco / índice
Diagrama mostrando o significado dos diferentes níveis em um caminho de derivação.

m: Mestra

Esta é a chave estendida mestra, que é a primeira chave privada estendida no topo da árvore da carteira HD.

Todos os caminhos de derivação começam com m.

Esta chave estendida mestra é criada a partir da seed.

m/44': Propósito (endurecido)

O primeiro nível especifica a estrutura da carteira que será usada.

Há quatro esquemas sendo usados atualmente por carteiras:

Este número reflete o número do BIP (Bitcoin Improvement Proposal).

m/44'/0': Tipo de Moeda (endurecido)

O segundo nível indica a criptomoeda específica para a qual as chaves serão usadas.

Criptomoedas diferentes podem usar as mesmas chaves privadas e chaves públicas. Então, em vez de ter seeds separadas para diferentes moedas (ou usar as mesmas chaves públicas em chains diferentes), podemos usar a mesma seed com caminhos de derivação diferentes.

0' = Bitcoin
1' = Bitcoin (Testnet)
2' = Litecoin
3' = Dogecoin
...

Lista completa: https://github.com/satoshilabs/slips/blob/master/slip-0044.md

Isto é útil em carteiras de hardware (ex. Trezor), onde você pode ter uma única seed e usá-la para guardar diversas moedas diferentes.

m/44'/0'/0': Conta (endurecido)

O terceiro nível permite criar contas separadas para fundos.

Por exemplo, você pode criar "potes" separados a partir da mesma seed, e as moedas nessas contas separadas não serão misturadas.

O índice de conta padrão é 0'.

Você poderia obviamente criar muitas contas diferentes em índices aleatórios neste nível. Mas para manter a recuperação simples, uma carteira deve criar contas em ordem sequencial, e não criar uma nova conta se uma anterior não tiver sido usada.

m/44'/0'/0'/0: Troco

O quarto nível separa as chaves e endereços em "Recebimento" e "Troco":

Isso permite diferenciar as moedas que chegaram de pagamentos externos das moedas que você enviou de volta a si mesmo como troco.

Estas são filhas normais. Isso significa que elas têm chaves públicas estendidas correspondentes, que podem ser usadas para derivar as chaves públicas independentemente para os filhos abaixo.

m/44'/0'/0'/0/0: Índice

O quinto nível contém as chaves que você realmente usa para enviar e receber pagamentos na carteira.

Então, cada vez que você gera um novo endereço para receber um pagamento, você está incrementando o índice da chave filha neste nível (começando de 0).

Portanto, as chaves realmente usadas para endereços estão no nível mais baixo da árvore de chaves; os primeiros níveis no caminho são apenas usados para estruturar a carteira hierárquica determinística de forma funcional.

Você não precisa realmente usar chaves estendidas neste nível porque você não precisa derivar mais filhos. Você usa as chaves filhas neste nível por suas chaves privadas e chaves públicas básicas.

Caminhos por Tipo de Endereço

Quais caminhos de derivação as carteiras Bitcoin usam?

Aqui estão os caminhos de derivação mais comuns usados por carteiras Bitcoin.

BIP 32: m/0'/0/0 (obsoleto)

Diagrama mostrando o caminho de derivação para uma carteira BIP 32.

Esta é a especificação de caminho de derivação original do BIP 32.

Ela usa o primeiro filho para contas, e o próximo filho abaixo para separar endereços externos (recebimento) e internos (troco). Os filhos destes são usados para suas chaves privadas e chaves públicas para criar endereços.

Este é um caminho de derivação simples, mas não permite a opção de criar esquemas de caminhos de derivação alternativos.

É aí que entram BIP 44, BIP 49, e BIP 84

BIP 44: m/44'/0'/0'/0/0

Diagrama mostrando o caminho de derivação para uma carteira BIP 44.

BIP 44 constrói sobre o esquema original do BIP 32 para incluir um propósito (que é como um número de versão para identificar o esquema seguinte), bem como um tipo de moeda para que a mesma seed possa ser usada para gerar chaves para diferentes criptomoedas.

O primeiro nível de 44' indica que a carteira usa 1endereços (P2PKH).

BIP 44 Endereços de Chave Estendida

O endereço para uma chave estendida no esquema de caminho de derivação BIP 44 começa com xprv ou xpub.

Por exemplo:

xprv9s21ZrQH143K4WrqpmjkXv7fTDm9HTALx3pVPAbE16BybEtwUg86tkJiSp17hRXwnZx2KxNENbdN872bWGDSLpQAsVRYY3HHne88218PQV1

Endereço (Chave Estendida)

em um endereço.>Codifique uma

Dados da chave estendida
Tipo
Legacy (BIP 44)

P2PKH>Nota:

Segwit (BIP 49)

(P2SH-P2WPKH)>Nota:

Segwit (BIP 84)

P2WPKH>Nota:

Quantas derivações de profundidade a partir da chave mestra (0 se for a mestra)

0d

da chave pública do pai (00000000 se for a mestra)>Os 4 primeiros bytes do

O número de índice desta chave com relação ao pai (0 se for a mestra)

0d

da chave pai (key+index, chain code) ou (seed, passphrase)>Os últimos 32 bytes do

0 bytes

Chave privada crua (32 bytes) ou chave pública (33 bytes)

0 bytes
0 bytes
0 bytes

da chave estendida serializada e do checksum>Codificação

0 caracteres

Nunca use uma chave privada gerada por um site, nem introduza sua chave privada em um site. Os sites podem guardar facilmente a chave privada e usá-la para roubar seus bitcoins.

BIP 49: m/49'/0'/0'/0/0

Diagrama mostrando o caminho de derivação para uma carteira BIP 49.

BIP 49 usa a mesma estrutura que o BIP 44.

O primeiro nível de 49' indica que a carteira usa 3endereços (P2SH-P2WPKH).

BIP 49 Endereços de Chave Estendida

O endereço para uma chave estendida no esquema de caminho de derivação BIP 49 começa com yprv ou ypub.

Por exemplo:

yprvABrGsX5C9janup3xf8XNk1DAdBubE59qsALiAZV7P6ZreLiAjLHfWoxrU1xhhLBsCD4q5RxnqFyv1PeADxdT945mjq7y7x6n4NBmQduEU8h

Endereço (Chave Estendida)

em um endereço.>Codifique uma

Dados da chave estendida
Tipo
Legacy (BIP 44)

P2PKH>Nota:

Segwit (BIP 49)

(P2SH-P2WPKH)>Nota:

Segwit (BIP 84)

P2WPKH>Nota:

Quantas derivações de profundidade a partir da chave mestra (0 se for a mestra)

0d

da chave pública do pai (00000000 se for a mestra)>Os 4 primeiros bytes do

O número de índice desta chave com relação ao pai (0 se for a mestra)

0d

da chave pai (key+index, chain code) ou (seed, passphrase)>Os últimos 32 bytes do

0 bytes

Chave privada crua (32 bytes) ou chave pública (33 bytes)

0 bytes
0 bytes
0 bytes

da chave estendida serializada e do checksum>Codificação

0 caracteres

Nunca use uma chave privada gerada por um site, nem introduza sua chave privada em um site. Os sites podem guardar facilmente a chave privada e usá-la para roubar seus bitcoins.

BIP 84: m/84'/0'/0'/0/0

Diagrama mostrando o caminho de derivação para uma carteira BIP 84.

BIP 84 usa a mesma estrutura que o BIP 44.

O primeiro nível de 84' indica que a carteira usa bc1qendereços (P2WPKH).

BIP 84 Endereços de Chave Estendida

O endereço para uma chave estendida no esquema de caminho de derivação BIP 84 começa com zprv ou zpub.

Por exemplo:

zprvAWgYBBk7JR8Gm7F5VVJzx6JfoA43Ah9LnGrvwxNzm6wjhSXPyzTE8sczVDvHhEqnbrBdpuZMHvLTtgFiwf3TwHmNcApPhrvGL6FQoAG9XuX

Endereço (Chave Estendida)

em um endereço.>Codifique uma

Dados da chave estendida
Tipo
Legacy (BIP 44)

P2PKH>Nota:

Segwit (BIP 49)

(P2SH-P2WPKH)>Nota:

Segwit (BIP 84)

P2WPKH>Nota:

Quantas derivações de profundidade a partir da chave mestra (0 se for a mestra)

0d

da chave pública do pai (00000000 se for a mestra)>Os 4 primeiros bytes do

O número de índice desta chave com relação ao pai (0 se for a mestra)

0d

da chave pai (key+index, chain code) ou (seed, passphrase)>Os últimos 32 bytes do

0 bytes

Chave privada crua (32 bytes) ou chave pública (33 bytes)

0 bytes
0 bytes
0 bytes

da chave estendida serializada e do checksum>Codificação

0 caracteres

Nunca use uma chave privada gerada por um site, nem introduza sua chave privada em um site. Os sites podem guardar facilmente a chave privada e usá-la para roubar seus bitcoins.

BIP 86: m/86'/0'/0'/0/0

Diagrama mostrando o caminho de derivação para uma carteira BIP 86.

BIP 86 usa a mesma estrutura que o BIP 44.

O primeiro nível de 86' indica que a carteira usa bc1pendereços (P2TR).

A especificação BIP 86 é usada para criar saídas P2TR apenas para gasto por caminho de chave. Portanto, ela não inclui nenhuma condição de gasto por caminho de script (o que significa que a raiz merkle está sempre vazia).

BIP 86 Endereços de Chave Estendida

O esquema de caminho de derivação BIP 86 não especifica um formato de endereço único para chaves estendidas. Portanto, as chaves estendidas parecem as mesmas que as usadas no BIP 44 (ou seja, começam com xprv ou xpub).

Por exemplo:

xprvA449goEeU9okwCzzZaxiy475EQGQzBkc65su82nXEvcwzfSskb2hAt2WymrjyRL6kpbVTGL3cKtp9herYXSjjQ1j4stsXXiRF7kXkCacK3T

Aqui estão algumas citações que explicam por que as chaves estendidas BIP 86 não têm seu próprio prefixo único:

Não existe algo como ypub/zpub para Taproot. A recomendação é usar xpriv/xpub junto com alguma informação extra indicando que o script a ser criado é Taproot (ex. com um descritor tr()).

Isso porque é uma violação de camada fazer o par de chaves estendido indicar o tipo de script a ser criado. As chaves não devem e não se importam com quais scripts criar. Além disso, xprv e xpub não devem indicar endereços legacy — eles são para chaves estendidas BIP 32 que são agnósticas a script. Usá-los para indicar endereços legacy é incorreto.

Ava Chow, bitcoin.stackexchange.com

Como o padrão xpub havia sido interpretado como apenas P2PKH (em vez de uma forma agnóstica a endereço de descrever chaves públicas), algo diferente de xpubs era necessário. É por isso que algumas pessoas adotaram ypub/zpub para este propósito.

Acredito que isso seja confuso, pois agora não está claro o que um xpub significa, e não é escalável: não podemos ficar inventando novos formatos tipo xpub para todos os tipos de endereços que possam ser inventados. Especialmente com a introdução de multisig e construções mais complexas, que simplesmente não cabem em uma única coisa tipo xpub (porque você precisaria combinar múltiplos deles).

Por esta razão, o Bitcoin Core está usando (e desenvolvendo) uma abordagem chamada Output Descriptors. Estas são strings que especificam exata e inequivocamente quais scripts/endereços são desejados, com base nas chaves públicas envolvidas.

Pieter Wuille, bitcoin.stackexchange.com

Resumindo, Output Descriptors são usados em vez disso.

Limite de Lacuna (Gap Limit)

Diagrama mostrando o limite de lacuna para endereços em uma carteira HD.

O limite de lacuna (gap limit) se refere a quantos endereços não usados uma carteira examinará antes de parar de procurar por saldo em endereços seguintes.

O limite de lacuna padrão é 20.

O limite de lacuna de endereço está atualmente definido como 20. Se o software encontrar 20 endereços não usados em sequência, ele espera que não haja endereços usados além deste ponto e para de procurar na cadeia de endereços.
BIP 44

Então, ao recuperar uma carteira HD a partir de uma seed, a carteira começará verificando se há saldo nos primeiros 20 endereços. Se nenhum saldo for encontrado em nenhum destes endereços, a carteira para de verificar endereços adicionais e assume que a carteira não recebeu nenhum pagamento.

Por exemplo, se você gerou sua própria seed mnemônica e decidiu receber seu primeiro pagamento em um endereço no índice m/44'/0'/0'/0/20, ao importar esta seed em uma carteira diferente, ela provavelmente exibirá um saldo de zero.

Este limite de lacuna se aplica a todos os endereços na carteira também. Então, se você receber um pagamento no endereço m/44'/0'/0'/0/5 (que está ok), mas depois decidir receber seu próximo pagamento em um endereço em m/44'/0'/0'/0/26 (uma lacuna de 21), esse segundo pagamento não será detectado se você decidir importar sua seed em uma carteira diferente posteriormente.

Portanto, basicamente, você deve evitar deixar uma lacuna de 20 endereços entre pagamentos.

  • Suas moedas não serão "perdidas" se você exceder o limite de lacuna. Apenas não ficarão visíveis se você importar sua seed em uma nova carteira. Você precisaria ajustar as configurações da carteira para aumentar o limite de lacuna, ou recuperar as chaves e endereços usando uma ferramenta personalizada.
  • O limite de lacuna não é algo para se preocupar como usuário típico de Bitcoin. Uma boa carteira avisará antes de você criar uma lacuna de mais de 20 endereços não usados.

Dicas

Algumas dicas gerais para trabalhar com caminhos de derivação:

Código

Aqui estão alguns trechos de código para mostrar como você pode criar diferentes caminhos de derivação a partir de uma seed.

Usei bibliotecas existentes para ajudar a manter o código simples.

Ruby

Este código requer a biblioteca bitcoin-ruby.

require 'bitcoin' # gem install bitcoin-ruby

seed = "67f93560761e20617de26e0cb84f7234aaf373ed2e66295c3d7397e6d7ebe882ea396d5d293808b0defd7edd2babd4c091ad942e6a9351e6d075a29d4df872af"

# ------
# BIP 44
# ------
# Nota: Chaves endurecidas começam em 2**31 (a segunda metade dos 2**32 filhos possíveis).

m = Bitcoin::ExtKey.generate_master(seed.htb) # converte hex para binário
purpose   = m.derive(2**31+44) # m/44'
coin_type = m.derive(2**31+44).derive(2**31+0) # m/44'/0'
account   = m.derive(2**31+44).derive(2**31+0).derive(2**31+0) # m/44'/0'/0'
receiving = m.derive(2**31+44).derive(2**31+0).derive(2**31+0).derive(0) # m/44'/0'/0'/0

20.times do |i|
  puts receiving.derive(i).addr # m/44'/0'/0'/0/*
end

Go

Este código requer a biblioteca hdkeychain.

package main

import (
  "encoding/hex" // array de bytes para string hex
  "fmt"

  "github.com/btcsuite/btcd/btcutil/hdkeychain" // go get -u github.com/btcsuite/btcd/btcutil/hdkeychain
  "github.com/btcsuite/btcd/chaincfg"           // chaincfg.MainNetParams
)

func main() {

  // A partir da Seed
  seedhex := "67f93560761e20617de26e0cb84f7234aaf373ed2e66295c3d7397e6d7ebe882ea396d5d293808b0defd7edd2babd4c091ad942e6a9351e6d075a29d4df872af"
  seed, _ := hex.DecodeString(seedhex) // hex para bytes
  // fmt.Println("seed: ", seedhex)

  // Gerar Seed
  // seed, _ := hdkeychain.GenerateSeed(uint8(16))
  // fmt.Println(hex.EncodeToString(seed)) // bytes para hex

  // ------
  // BIP 44
  // ------
  // m
  m, _ := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)

  // m/44h
  purpose, _ := m.Child(hdkeychain.HardenedKeyStart + 44)

  // m/44h/0h
  coin, _ := purpose.Child(hdkeychain.HardenedKeyStart + 0)

  // m/44h/0h/0h
  account, _ := coin.Child(hdkeychain.HardenedKeyStart + 0)

  // m/44h/0h/0h/0
  receiving, _ := account.Child(0) // 0 = recebimento, 1 = troco

  // m/44h/0h/0h/0/*
  for i := 0; i < 20; i++ {
    index, _ := receiving.Child(uint32(i)) // recebe um inteiro sem sinal
    address, _ := index.Address(&chaincfg.MainNetParams)
    fmt.Println(address)
  }
}

Recursos