Caminhos de Derivação
A localização das chaves e endereços em uma carteira HD
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:
- BIP 44:
m/44'/0'/0'(1endereços) - BIP 49:
m/49'/0'/0'(3endereços) - BIP 84:
m/84'/0'/0'(bc1qendereços) - BIP 86:
m/86'/0'/0'(bc1pendereços)
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.
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'
- As barras
/indicam um novo nível na árvore (uma nova filha). - Os números (ex.
0,1,3') indicam o número do índice da filha a partir do pai. - O
'(ouh) indica uma filha endurecida (começando no índice2147483648).
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.
- Filhas Normais (
0 a 2147483647) — Estas filhas têm chaves públicas estendidas correspondentes que podem ser usadas para gerar chaves públicas independentemente sem gerar as chaves privadas ao mesmo tempo. - Filhas Endurecidas (
2147483648 a 4294967295) — Estas não têm a mesma capacidade que filhas normais. Você só pode gerar as chaves privadas e chaves públicas a partir da chave privada estendida.
- 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
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":
- Recebimento =
0— Endereços que daremos às pessoas para receber pagamentos. - Troco =
1— Endereços que usamos para enviar troco de volta a nós mesmos ao fazer transações.
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)
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
- Legacy (P2PKH)
- 1endereços
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:
BIP 49: m/49'/0'/0'/0/0
- Segwit Aninhado (P2SH-P2WPKH)
- 3endereços
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:
BIP 84: m/84'/0'/0'/0/0
- Segwit Nativo (P2WPKH)
- bc1qendereços
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:
BIP 86: m/86'/0'/0'/0/0
- Taproot (P2TR)
- bc1pendereços
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:
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.
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.
Resumindo, Output Descriptors são usados em vez disso.
Limite de Lacuna (Gap Limit)
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.
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:
- Guarde o caminho de derivação junto com sua seed phrase. Isto será útil se você precisar recuperar suas moedas usando uma carteira diferente posteriormente. Não é essencial, mas pode poupar você de um susto se acabar restaurando sua carteira e descobrir que não há moedas nela, pois a carteira que você está usando agora pode estar usando um caminho de derivação diferente por padrão.
- Mantenha-se com um caminho de derivação padrão. Ao criar uma carteira, é melhor usar um dos caminhos de derivação padrão oferecidos. Você pode ter a opção de escolher um personalizado, mas se usar um caminho de derivação personalizado e esquecê-lo, terá dificuldade em recuperar suas moedas depois. Isso não melhora significativamente a segurança, e não vale a dor de cabeça que inevitavelmente causará.
- Não se preocupe se você não sabe o caminho de derivação da sua carteira atual. Existem apenas alguns caminhos de derivação padrão em uso comum, então basta tentar os mais comuns ao recuperar sua carteira posteriormente (se necessário). A pior parte será a sensação inicial de que você perdeu suas moedas, mas tudo que você precisa fazer é tentar um caminho de derivação diferente para recuperar seus endereços. Uma boa carteira permitirá usar diferentes caminhos de derivação para sua seed (ex. Sparrow, Electrum). Veja walletsrecovery.org para uma lista dos caminhos de derivação usados por diferentes carteiras.
- Esteja ciente das diferentes notações de caminho de derivação. A maioria das carteiras Bitcoin usa apenas os primeiros 3 níveis para identificar diferentes caminhos de derivação (ex.
m/44'/0'/0') e calcula os endereços a partir daí. No entanto, ao usar algumas ferramentas (como a deste site), para chegar às chaves e endereços reais na carteira você precisa especificar o caminho de derivação completo (ex.m/44'/0'/0'/0/0). Então, se você não estiver obtendo os resultados corretos, verifique a notação. - Nunca insira sua seed phrase em um site. Como sempre, você nunca deve inserir sua seed phrase em um site. A ferramenta neste site é apenas para fins educacionais e de desenvolvimento. Se você precisar trabalhar na recuperação de uma carteira usando diferentes caminhos de derivação, use software confiável em seu computador local (ou use seu próprio código).
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
- BIP 44 (Marek Palatinus, Pavol Rusnak)
- BIP 49 (Daniel Weigl)
- BIP 84 (Pavol Rusnak)
- BIP 86 (Ava Chow)
- Ian Coleman BIP39 Tool — Ferramenta interativa fantástica para derivação de caminhos a partir de uma seed.