Bech32

Formato de endereço para scripts de travamento segwit

Diagrama mostrando a estrutura de um endereço Bech32.

Bech32 ("besh trinta e dois") é um formato de endereço usado para representar scripts de travamento segwit como P2WPKH, P2WSH e P2TR.

Ele foi introduzido logo após a atualização Segregated Witness para fornecer um formato de endereço melhor para os novos scripts de travamento segwit. É uma melhoria em relação ao formato legado Base58.

Aqui estão alguns exemplos de como eles se parecem:

Exemplos de endereços Bech32 por tipo
Tipo Endereço Comprimento
P2WPKH bc1qx5y8r50l39cap3r9cd65fz7xfvlkjrl258hs8m 42 caracteres
P2WSH bc1q37qzzxnhnwdsde7yjzq5hc0wktmnqejp3zt0pj9l0pgn9f2gpyls4hahsc 62 caracteres
P2TR bc1p4pzgu93t5nlw9mscn0v6s7spfya7qntp0afynva267lr0vp0sxyqqj24dc 62 caracteres

Você identifica um endereço Bech32 pelo prefixo bc1.

Nesta página vou mostrar como codificar e decodificar um endereço Bech32, e explicar por que eles são melhores que os endereços Base58.

Benefícios

Quais são as vantagens do Bech32?

O Bech32 é mais amigável e mais eficiente que o formato legado Base58 para endereços.

Em resumo, é uma evolução em comparação ao Base58.

Mais amigável

Os endereços Bech32 são mais amigáveis que os endereços Base58 por três motivos:

1. Insensível a maiúsculas/minúsculas

Os endereços Bech32 não usam uma combinação de letras maiúsculas e minúsculas, o que os torna mais fáceis de digitar e de ler em voz alta em comparação ao Base58.

Então, se você estiver passando o seu endereço para alguém por telefone, não precisa mais ficar alternando entre "x maiúsculo, y minúsculo...", e assim por diante.

Os endereços Bech32 são tipicamente todos em minúsculas, mas é perfeitamente válido usar tudo em maiúsculas (que é como eles ficam armazenados em um QR code).

Para evitar confusão, os endereços Bech32 não devem usar uma combinação de letras maiúsculas e minúsculas. Uma carteira deve considerar um endereço Bech32 com letras misturadas como inválido.

O fato de o Bech32 usar menos caracteres que o Base58 (ou seja, base 32 em vez de base 58) significa que os endereços são tipicamente mais longos, mas ter todos os caracteres em um único caso torna os endereços Bech32 mais fáceis de usar no geral.

2. Conjunto de caracteres amigável

Isto não é exatamente uma "evolução", já que o Base58 faz algo parecido, mas o Bech32 não usa caracteres parecidos entre si.

Para ser preciso, a parte de dados do endereço usa todos os caracteres alfanuméricos exceto "1", "b", "i" e "o":

Conjunto de Caracteres Base32 do Bitcoin

0 1 2 3 4 5 6 7 8 9
a b c d e f g h i j k l m n o p q r s t u v w x y z

Então, dos 36 caracteres alfanuméricos possíveis, 4 dos menos distintos foram removidos para deixar 32 caracteres no total.

Isto é um pouco diferente dos conjuntos de caracteres "base 32" já existentes. Por exemplo:

  • z-base-32 — remove "0", "l", "v" e "2"
  • RFC3548 — remove "0", "1", "8" e "9"

A parte legível por humanos não está restrita aos caracteres base 32 acima. Ela pode conter qualquer caractere US-ASCII (na faixa 33-126), e é por isso que você pode usar um "b" no início de um endereço.

3. Checksum melhor

Os endereços Bech32 usam um algoritmo de checksum aprimorado que permite detectar e corrigir erros no endereço.

Para resumir as diferenças:

Então, em resumo, o checksum do Bech32 é mais esperto.

Mais eficiente

Os endereços Bech32 são mais eficientes que os endereços Base58 por três motivos:

1. QR codes menores

O fato de os endereços Bech32 serem de caso único permite codificá-los em QR codes usando o modo alfanumérico.

Isso significa que você pode criar QR codes mais compactos, porque o Base58 exige ambas as letras maiúsculas e minúsculas (o que impede o uso do modo alfanumérico), enquanto o Bech32 não.

Por exemplo:

Endereço Base58

1MHKKX3cN2RnWrxnzg9kLfPzi6vCd1B2H7

QR code de exemplo de um endereço Base58 (sensível a maiúsculas/minúsculas).

Endereço Bech32

BC1QMEU8D90HWHFHM49GHGN5ZFGEXDPJSSPZGN28T4

QR code de exemplo de um endereço Bech32 (insensível a maiúsculas/minúsculas).

Como você pode ver, embora o endereço Bech32 tenha mais caracteres, a capacidade de usar o modo alfanumérico faz com que o QR code use menos dados no total.

O modo alfanumérico dos QR codes só suporta letras maiúsculas. É por isso que, ao escanear um QR code contendo um endereço Bech32, ele normalmente aparece todo em maiúsculas. Isso é perfeitamente válido, pois os endereços Bech32 são insensíveis a maiúsculas/minúsculas.

2. Codificação mais rápida

É mais rápido calcular um checksum Bech32 do que um checksum Base58, o que torna mais rápido codificar endereços Bech32.

Eu sei que o algoritmo de checksum do Bech32 parece bem complicado, mas ele ainda é mais rápido que o SHA256 duplo necessário para criar o checksum do Base58.

3. Decodificação mais rápida

Os caracteres em um endereço Bech32 mapeiam para valores específicos, o que é mais rápido que a aritmética modular sobre números grandes necessária para decodificar um endereço Base58.

O Base58 não é absurdamente lento para codificar/decodificar em comparação ao Bech32, mas o Bech32 é mais eficiente mesmo assim.

Ferramenta

Endereço (Bech32)

Codifique um script de travamento P2WPKH, P2WSH ou P2TR em um endereço.

ScriptPubKey
Versão
0 bytes
0 bytes Tipo:
Rede

Codificação Bech32 do ScriptPubKey

0 caracteres

    Codificar

    Converter um ScriptPubKey em um endereço Bech32

    Um ScriptPubKey de um script de travamento segwit (ex.: P2WPKH, P2WSH, P2TR) pode ser convertido em um endereço Bech32.

    A maior parte do processo de codificação envolve converter os bytes do ScriptPubKey em binário (1s e 0s), dividir esses 1s e 0s em grupos de 5 bits e depois converter esses grupos de 5 bits em seus caracteres base32 correspondentes.

    Essa é uma explicação simplificada do processo, mas é basicamente assim que funciona. A parte mais difícil é calcular o checksum.

    Aqui está um guia passo a passo:

    Diagrama mostrando como codificar um ScriptPubKey segwit em um endereço Bech32.

    A codificação Bech32 foi projetada para funcionar apenas com scripts de travamento segwit (ou seja, P2WPKH, P2WSH, P2TR). Isso acontece porque eles seguem um padrão específico exigido pela codificação Bech32 (eles essencialmente exigem um número de versão e alguns bytes de dados).

    1. Parte legível por humanos

    Para começar, você precisa escolher qual será o prefixo do endereço final.

    No Bitcoin, você tem 3 opções para esse prefixo:

    • bc = mainnet
    • tb = testnet
    • bcrt = regtest

    Isso é chamado de parte legível por humanos, e indica se o endereço deve ser usado na mainnet, testnet ou regtest.

    Você precisa escolher a parte legível por humanos logo no início, pois ela será usada ao calcular o checksum.

    2. ScriptPubKey

    Em seguida, pegue o ScriptPubKey completo que você quer converter para Bech32.

    Aqui está um exemplo de ScriptPubKey P2WPKH:

    0014751e76e8199196d454941c45d1b3a323f1433bd6

    Se você ainda não sabe, cada ScriptPubKey segwit segue uma estrutura parecida. Essa estrutura pode ser dividida em 3 partes:

    1. Versão

    O primeiro byte corresponde a um opcode OP_N.

    Bytes de opcode de versão e seus opcodes
    Byte Opcode
    00OP_0
    51OP_1
    52OP_2
    53OP_3
    54OP_4
    55OP_5
    56OP_6
    57OP_7
    58OP_8
    59OP_9
    5aOP_10
    5bOP_11
    5cOP_12
    5dOP_13
    5eOP_14
    5fOP_15
    60OP_16

    O valor inteiro que esse opcode representa indica a versão do script de travamento segwit.

    No nosso exemplo, o byte 00 corresponde ao opcode OP_0, que indica um script de travamento segwit versão 0 (ou seja, P2WPKH ou P2WSH).

    O byte de versão deve ser 00, ou de 51 a 60 (ou seja, OP_0 a OP_16).

    2. Tamanho

    O segundo byte indica o tamanho do programa de testemunha que vem a seguir.

    Esse byte é 14 no nosso exemplo, o que indica que o programa de testemunha a seguir tem 20 bytes de comprimento.

    O byte de tamanho não é incluído na codificação Bech32. Isso acontece porque você consegue descobrir o tamanho do programa de testemunha após decodificar um endereço Bech32, então não há necessidade de incluir o byte de tamanho explicitamente. Isso economiza um ou dois caracteres no endereço final.

    3. Programa de testemunha

    Os dados restantes no ScriptPubKey são o programa de testemunha.

    Essa é a parte única do ScriptPubKey, e geralmente contém um de 3 tipos de dados:

    1. hash de chave pública de 20 bytes (P2WPKH)
    2. hash de script de 32 bytes (P2WSH)
    3. chave pública com tweak de 32 bytes (P2TR)

    No nosso exemplo P2WPKH, o programa de testemunha é um hash de chave pública de 20 bytes:

    751e76e8199196d454941c45d1b3a323f1433bd6

    Esses dados têm a maior influência sobre como o nosso endereço Bech32 final vai ficar.

    3. Versão (5 bits)

    Em seguida, precisamos converter o número de versão do ScriptPubKey para um valor inteiro de 5 bits.

    No nosso exemplo, o byte de versão é 00, que corresponde ao opcode OP_0. Portanto, o número de versão desse ScriptPubKey é 0. Isso pode então ser representado como um valor binário de 5 bits:

    version = 00000

    Use o número representado pelo opcode, não o valor do byte. Os opcodes OP_1 a OP_16 usam os bytes na faixa de 51 a 60. Então é importante converter o byte para o seu opcode OP_N correspondente para obter o número de versão correto, em vez de usar o valor do byte diretamente.

    • O número de versão influencia o primeiro caractere após o prefixo do endereço final.
      • Um script de travamento segwit versão 0 começa com bc1q (P2WPKH ou P2WSH)
      • Um script de travamento segwit versão 1 começa com bc1p (P2TR)
    • O número de versão deve estar entre 0 e 16, então ele nunca excederá o valor máximo de 5 bits (que é 31).

    4. Programa de testemunha (grupos de 8 bits)

    Em seguida, convertemos o programa de testemunha em grupos de 8 bits.

    Este é o nosso programa de testemunha como um array de bytes:

    witness program = 75 1e 76 e8 19 91 96 d4 54 94 1c 45 d1 b3 a3 23 f1 43 3b d6

    Se convertermos cada byte em bits, obtemos:

    witness program = 01110101 00011110 01110110 11101000 00011001 10010001 10010110 11010100 01010100 10010100 00011100 01000101 11010001 10110011 10100011 00100011 11110001 01000011 00111011 11010110

    Há 8 bits em um byte.

    5. Programa de testemunha (grupos de 5 bits)

    Rearranje o programa de testemunha de grupos de 8 bits para grupos de 5 bits.

    witness program = 01110 10100 01111 00111 01101 11010 00000 11001 10010 00110 01011 01101 01000 10101 00100 10100 00011 10001 00010 11101 00011 01100 11101 00011 00100 01111 11000 10100 00110 01110 11110 10110

    Como você pode ver, rearranjamos o programa de testemunha de 20 grupos de 8 bits para 32 grupos de 5 bits.

    Preenchimento (padding). Se você não tiver bits suficientes nos grupos iniciais de 8 bits para converter em grupos completos de 5 bits, preencha o último grupo de 5 bits com zeros.

    6. Checksum

    O checksum é calculado usando a parte legível por humanos, a versão de 5 bits e os grupos de 5 bits do programa de testemunha.

    Então estes são os dados que vamos usar como entrada do algoritmo de checksum:

    hrp             = 'bc'
    version         = 00000
    witness program = 01110 10100 01111 00111 01101 11010 00000 11001 10010 00110 01011 01101 01000 10101 00100 10100 00011 10001 00010 11101 00011 01100 11101 00011 00100 01111 11000 10100 00110 01110 11110 10110
    

    O checksum resultante para o nosso exemplo é:

    checksum = 01100 00111 01001 10001 01011 10101

    Esse processo é bem trabalhoso, então pulei ele por enquanto. Veja o algoritmo de checksum para os detalhes.

    7. Combinar

    Adicione o checksum que acabamos de calcular ao final da versão de 5 bits e dos grupos de 5 bits do programa de testemunha:

    version + witness_program + checksum = 00000 01110 10100 01111 00111 01101 11010 00000 11001 10010 00110 01011 01101 01000 10101 00100 10100 00011 10001 00010 11101 00011 01100 11101 00011 00100 01111 11000 10100 00110 01110 11110 10110 01100 00111 01001 10001 01011 10101

    8. Base32

    Converta os grupos de 5 bits combinados do passo anterior em inteiros, depois use esses inteiros para selecionar o caractere base32 correspondente de cada um:

    Caracteres Base32
    
    0 = q
    1 = p
    2 = z
    3 = r
    4 = y
    5 = 9
    6 = x
    7 = 8
    8 = g
    9 = f
    10 = 2
    11 = t
    12 = v
    13 = d
    14 = w
    15 = 0
    16 = s
    17 = 3
    18 = j
    19 = n
    20 = 5
    21 = 4
    22 = k
    23 = h
    24 = c
    25 = e
    26 = 6
    27 = m
    28 = u
    29 = a
    30 = 7
    31 = l
    

    Os caracteres base32 foram organizados nesta ordem específica para melhorar a capacidade de correção de erros do checksum.

    Por exemplo:

    version + witness_program + checksum (grupos de 5 bits) = 00000 01110 10100 01111 00111 01101 11010 00000 11001 10010 00110 01011 01101 01000 10101 00100 10100 00011 10001 00010 11101 00011 01100 11101 00011 00100 01111 11000 10100 00110 01110 11110 10110 01100 00111 01001 10001 01011 10101
    version + witness_program + checksum (inteiros) = 0 14 20 15 7 13 26 0 25 18 6 11 13 8 21 4 20 3 17 2 29 3 12 29 3 4 15 24 20 6 14 30 22 12 7 9 17 11 21
    version + witness_program + checksum (base32) = q w 5 0 8 d 6 q e j x t d g 4 y 5 r 3 z a r v a r y 0 c 5 x w 7 k v 8 f 3 t 4
    

    Essa string base32 forma a parte de dados do endereço Bech32 final.

    9. Bech32

    Por fim, adicione a parte legível por humanos e o separador ao início da string base32 para obter o endereço Bech32 final.

    hrp       = bc
    separator = 1
    base32    = qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
    
    bech32    = bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
    

    O separador é sempre 1. Ele é usado para separar a parte legível por humanos da parte de dados base32, porque a parte legível por humanos pode variar em comprimento. Um "1" não pode aparecer na parte de dados do endereço (já que foi excluído do conjunto de caracteres base32), e é por isso que ele funciona de forma confiável como caractere separador.

    Código

    # --------
    # configurações
    # --------
    
    # prefixo legível por humanos a ser usado no endereço Bech32 final
    hrp = "bc" # bc = mainnet, tb = testnet
    
    # separador entre a parte legível por humanos e a parte de dados
    separator = "1" # isto é sempre 1
    
    # conjunto de caracteres base32
    characters = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" # todos os caracteres alfanuméricos minúsculos exceto "1", "b", "i", "o"
    
    # exibe o algoritmo de checksum completo
    display_checksum_algorithm = true # true ou false
    
    puts "------------"
    puts "scriptpubkey"
    puts "------------"
    puts
    
    # scriptpubkey que queremos converter para Bech32
    scriptpubkey = "0014751e76e8199196d454941c45d1b3a323f1433bd6" # scriptpubkey P2WPKH de exemplo
    puts "scriptpubkey: #{scriptpubkey}"
    puts
    
    # divide o scriptpubkey em versão e programa de testemunha
    version = scriptpubkey[0..1] # primeiro byte
    witness_program = scriptpubkey[4..-1] # do byte 2 até o fim
    puts "version: #{version}"
    puts "program: #{witness_program}"
    puts
    # nota: o byte de tamanho entre a versão e o programa de testemunha não é usado na codificação Bech32
    
    puts "-------"
    puts "version"
    puts "-------"
    puts
    
    # converte o byte de versão para o valor inteiro representado pelo seu opcode correspondente
    #
    # 0x00 = OP_0 = 0 (P2WPKH and P2WSH)
    # 0x51 = OP_1 = 1 (P2TR)
    # 0x52 = OP_2 = 2
    # ...
    # 0x60 = OP_16 = 16
    #
    # cuidado: OP_1 a OP_16 começam em 0x51, não em 0x01
    if (version == "00")
      version_opcode_int = 0
    elsif (version.to_i(16) >= 0x51 && version.to_i(16) <= 0x60)
      version_opcode_int = version.to_i(16) - 0x50
    else
      puts "Invalid version byte." # o byte de versão deve estar entre OP_0 e OP_16
      exit
    end
    
    # converte a versão para um valor de 5 bits
    version_5_bits = version_opcode_int & 0b11111 # a versão já deveria ter 5 bits (ou seja, 0 a 16), mas pega os últimos 5 bits por garantia
    
    # exibe os detalhes da versão
    puts "version (byte):   #{version}"
    puts "version (opcode): OP_#{version_opcode_int}"
    puts "version (5-bits): #{version_5_bits.to_s(2).rjust(5, "0")}"
    puts
    
    puts "------------"
    puts "8-bit groups"
    puts "------------"
    puts
    
    # converte o programa de testemunha para um array de inteiros de 8 bits
    version_8_bits = [version_opcode_int] # coloca o valor inteiro de 8 bits em um array
    witness_program_8_bits = [witness_program].pack("H*").unpack("C*") # converte a string hex para binário e depois de volta para arrays de inteiros de 8 bits (1 byte)
    
    # exibe o array de 8 bits do programa de testemunha como strings binárias
    puts "program: #{witness_program_8_bits.map { |v| v.to_s(2).rjust(8, "0") }.join(' ')}"
    puts
    
    puts "------------"
    puts "5-bit groups"
    puts "------------"
    puts
    
    # rearranja o programa de testemunha de um array de inteiros de 8 bits para um array de inteiros de 5 bits
    from = 8 # número de bits no inteiro de partida
    to   = 5 # número de bits no inteiro de destino
    accumulator  = 0
    counter = 0
    max_value = (1 << to) - 1 # valor máximo (5 bits = 0b100000 = 32)
    max_accumulator = (1 << (from + to -1)) -1 # 8 bits + 5 bits - 1 bit = 12 bits = 4095 = 0b111111111111
    witness_program_5_bits = [] # o array de retorno
    
    # percorre cada inteiro de 8 bits no array do programa de testemunha
    witness_program_8_bits.each do |int_8_bits|
    
      # retorna nil se for negativo
      if int_8_bits < 0
        return nil
      end
    
      # retorna nil se o tamanho do inteiro for maior que o tamanho especificado do grupo de bits de partida
      if (int_8_bits >> from) != 0
        return nil
      end
    
      # adiciona os bits de partida ao acumulador
      accumulator = accumulator << from           # << = deslocamento de bits à esquerda
      accumulator = accumulator | int_8_bits      # | = OU bit a bit (nota: este comentário é necessário para o realce de sintaxe funcionar corretamente no site learnmeabitcoin.com — um pipe sozinho em uma linha quebra o realce por algum motivo)
      accumulator = accumulator & max_accumulator # & = E bit a bit
    
      # incrementa o contador
      counter += from
    
      # enquanto houver bits suficientes para produzir um novo grupo de 5 bits
      while counter >= to
    
        # decrementa o contador
        counter -= to
    
        # adiciona o valor de 5 bits ao resultado
        witness_program_5_bits << ((accumulator >> counter) & max_value)
      end
    end
    
    # adiciona preenchimento (padding)
    if (counter > 0)
      witness_program_5_bits << ((accumulator << (to - counter)) & max_value)
    end
    
    # exibe o resultado
    puts "program: #{witness_program_5_bits.map { |v| v.to_s(2).rjust(5, "0") }.join(' ')}"
    puts
    
    puts "------------------"
    puts "checksum algorithm"
    puts "------------------"
    puts
    
    # exibe a parte legível por humanos
    puts "hrp:          #{hrp}"
    
    # converte a parte legível por humanos para os valores de caractere UTF-8 correspondentes
    hrp_values = hrp.split("").map { |c| c.ord }
    puts "hrp_values:   #{hrp_values.map { |v| v.to_s(2).rjust(8, "0") }.join(' ')}"
    
    # expande a parte legível por humanos em grupos de 5 bits
    hrp_expanded = []
    
    # pega os primeiros 3 bits do valor inteiro de cada caractere
    hrp_values.each do |v|
      hrp_expanded << (v >> 5) # desloca 5 bits à direita para obter os primeiros 3 bits
    end
    
    # adiciona o separador
    hrp_expanded << 0
    
    # pega os últimos 5 bits do valor inteiro de cada caractere
    hrp_values.each do |v|
      hrp_expanded << (v & 0b11111) # usa uma máscara de bits para extrair os últimos 5 bits
    end
    
    # exibe o resultado
    puts "hrp_expanded: #{hrp_expanded.map { |v| v.to_s(2).rjust(5, "0") }.join(' ')}"
    puts
    
    # combina a parte legível por humanos expandida com a versão e o programa de testemunha (todos em grupos de 5 bits)
    combined = hrp_expanded + [version_5_bits] + witness_program_5_bits
    
    # adiciona preenchimento (padding)
    combined_with_padding = combined + [0, 0, 0, 0, 0, 0]
    puts "hrp + version + program + padding: #{combined_with_padding.map { |v| v.to_s(2).rjust(5, "0") }.join(' ')}"
    puts
    
    # valores geradores do checksum
    generator = [
      0b111011011010100101011110110010, # 0x3b6a57b2
      0b100110010100001000111001101101, # 0x26508e6d
      0b011110101000010001100111111010, # 0x1ea119fa
      0b111101010000100011001111011101, # 0x3d4233dd
      0b101010000101000110001010110011, # 0x2a1462b3
    ]
    
    # valor inicial do checksum (o resultado final do checksum terá 30 bits)
    checksum = 1
    
    # percorre cada grupo de 5 bits no array combinado
    combined_with_padding.each do |v|
    
      # exibe o valor atual do checksum
      puts "checksum: #{checksum.to_s(2).rjust(30, "0")}" if display_checksum_algorithm
      
      # remove 25 bits da direita do valor atual do checksum e guarda o resultado
      top = checksum >> 25
      puts "top:      #{top.to_s(2).rjust(5, "0")}" if display_checksum_algorithm
    
      # extrai os 25 bits inferiores do valor atual do checksum usando uma máscara de bits
      checksum = checksum & 0b1111111111111111111111111
      puts "bottom:        #{checksum.to_s(2).rjust(25, "0")}" if display_checksum_algorithm
    
      # desloca o valor do checksum à esquerda (adiciona 5 bits zero ao final, criando espaço para o xor com o valor atual de 5 bits)
      checksum = checksum << 5
      puts "padded:        #{checksum.to_s(2).rjust(30, "0")}" if display_checksum_algorithm
    
      # faz o xor do checksum atual com o próximo valor de 5 bits
      checksum = checksum ^ v
      puts "5-bit group:                            #{v.to_s(2).rjust(5, "0")}" if display_checksum_algorithm
      puts "xor:           #{checksum.to_s(2).rjust(30, "0")}" if display_checksum_algorithm
    
      # percorre os últimos 5 bits do valor "top"
      5.times do |i|
    
        # mostra o gerador atual
        print "generator #{i}:   #{generator[i].to_s(2).rjust(30, "0")}" if display_checksum_algorithm
    
        # se o próximo bit do valor "top" for 1
        if ((top >> i) & 1) == 1
    
          # faz o xor do checksum atual com o valor gerador correspondente
          checksum = checksum ^ generator[i]
    
          # adiciona um indicador se este valor gerador foi usado no xor
          puts " xor" if display_checksum_algorithm
        else 
          puts if display_checksum_algorithm
        end
      end
    
      # exibe o valor do checksum após este grupo de 5 bits
      puts "checksum:      #{checksum.to_s(2).rjust(30, "0")}" if display_checksum_algorithm
      puts if display_checksum_algorithm
    
    end
    
    # exibe o valor do checksum após percorrer todos os grupos de 5 bits
    puts "checksum:      #{checksum.to_s(2).rjust(30, "0")}" if display_checksum_algorithm
    
    # define a constante para o xor do checksum com base no número da versão
    if (version_opcode_int == 0)
      constant = 1 # bech32
    else
      constant = 0x2bc830a3 # bech32m
    end
    
    # exibe a constante
    puts "constant:      #{constant.to_s(2).rjust(30, "0")}" if display_checksum_algorithm
    
    # faz o xor do checksum com a constante
    checksum = checksum ^ constant
    
    # exibe a constante e o valor final do checksum
    puts "checksum:      #{checksum.to_s(2).rjust(30, "0")}" if display_checksum_algorithm
    puts if display_checksum_algorithm
    
    # converte o checksum em 6 grupos de 5 bits
    checksum_5_bits = []
    
    # queremos 6 grupos de 5 bits
    6.times do |i|
    
      # calcula o deslocamento à direita para pegar cada grupo de 5 bits do checksum de 30 bits
      right_shift = 5 * (5 - i)
    
      # desloca o valor do checksum à direita
      shifted = (checksum >> right_shift)
    
      # extrai os últimos 5 bits do valor deslocado
      bits = shifted & 0b11111
    
      # adiciona o grupo de 5 bits ao array do checksum
      checksum_5_bits << bits
    end
    
    # exibe o resultado
    puts "checksum: #{checksum_5_bits.map { |v| v.to_s(2).rjust(5, "0") }.join(' ')}"
    puts
    
    puts "------"
    puts "base32"
    puts "------"
    puts
    
    # combina a versão, o programa e o checksum
    data = [version_5_bits] + witness_program_5_bits + checksum_5_bits
    puts "version + program + checksum: #{data.map { |v| v.to_s(2).rjust(5, "0") }.join(' ')}"
    puts "version + program + checksum: #{data.map { |v| v }.join(' ')}"
    
    # converte cada grupo de 5 bits para o seu caractere base32 correspondente
    base32 = data.map { |i| characters[i] }
    puts "base32: #{base32.join(' ')}"
    puts
    
    puts "------"
    puts "bech32"
    puts "------"
    puts
    
    # exibe a hrp e o separador
    puts "hrp:       #{hrp}"
    puts "separator: #{separator}"
    puts
    
    # combina a parte legível por humanos, o separador e os dados base32
    bech32 = hrp + separator + base32.join
    puts "bech32:    #{bech32}" # bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4

    Decodificar

    Converter um endereço Bech32 em um ScriptPubKey

    Um endereço Bech32 pode ser decodificado em um ScriptPubKey segwit.

    Para fazer isso, basicamente você converte os caracteres base32 em seus valores de 5 bits correspondentes, rearranja esses bits em grupos de 8 bits para obter os valores em bytes hex e depois reconstrói o ScriptPubKey completo.

    Aqui está um guia passo a passo:

    Diagrama mostrando como decodificar um endereço Bech32 em um ScriptPubKey segwit.

    1. Endereço

    Primeiro de tudo, pegue o endereço que você quer converter em um ScriptPubKey.

    Aqui está um exemplo:

    bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4

    Em seguida, você precisa dividir o endereço em 3 partes:

    1. Parte legível por humanos. Os caracteres antes do separador são a parte legível por humanos. Essa parte pode ter entre 1 e 83 caracteres de comprimento. No Bitcoin, ela indica se o endereço é usado na mainnet ("bc"), testnet ("tb") ou regtest ("bcrt").
    2. Separador. A última ocorrência de um "1" no endereço é o separador. Ele separa a parte legível por humanos da parte de dados. Um endereço válido precisa conter um caractere separador "1".
    3. Dados. Tudo após o separador é a parte de "dados". Esta é uma codificação base32 da versão, do programa de testemunha e do checksum.

    A forma de dividir um endereço Bech32 na parte legível por humanos e na parte de dados é procurando o separador, que é a última ocorrência de um caractere "1".

    Então, para este endereço, temos:

    1. Parte legível por humanos = bc
    2. Separador = 1
    3. Dados = qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
    • Não leia um número fixo de caracteres para extrair a parte legível por humanos. Normalmente são 2 ou 4 caracteres, mas tecnicamente ela pode ter entre 1 e 83 caracteres de comprimento no futuro.
    • Não procure a primeira ocorrência de um "1". É tecnicamente possível que a parte legível por humanos contenha um "1", então você acabaria dividindo o endereço cedo demais e teria uma parte de dados incorreta. Para ter certeza de que está obtendo a posição correta do separador, você deve procurar a última ocorrência de um "1".

    O separador não é mais usado daqui em diante. A partir daqui, vamos usar apenas a parte legível por humanos e a parte de dados.

    2. Grupos de 5 bits

    Converta a parte de dados de caracteres base32 em seus valores inteiros de 5 bits correspondentes.

    Por exemplo:

    base32 = qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
    integers = 0 14 20 15 7 13 26 0 25 18 6 11 13 8 21 4 20 3 17 2 29 3 12 29 3 4 15 24 20 6 14 30 22 12 7 9 17 11 21

    Caracteres Base32
    
    0 = q
    1 = p
    2 = z
    3 = r
    4 = y
    5 = 9
    6 = x
    7 = 8
    8 = g
    9 = f
    10 = 2
    11 = t
    12 = v
    13 = d
    14 = w
    15 = 0
    16 = s
    17 = 3
    18 = j
    19 = n
    20 = 5
    21 = 4
    22 = k
    23 = h
    24 = c
    25 = e
    26 = 6
    27 = m
    28 = u
    29 = a
    30 = 7
    31 = l
    

    Esse array de inteiros pode ser dividido em 3 partes:

    1. Versão. O primeiro inteiro representa a versão.
    2. Programa de testemunha. Os inteiros entre a versão e o checksum são o programa de testemunha.
    3. Checksum. Os últimos 6 inteiros são o checksum.

    Então temos:

    version         = 0
    witness program = 14 20 15 7 13 26 0 25 18 6 11 13 8 21 4 20 3 17 2 29 3 12 29 3 4 15 24 20 6 14 30 22
    checksum        = 12 7 9 17 11 21

    Se quiser, você pode exibir esses inteiros em suas representações binárias de 5 bits:

    version         = 00000
    witness program = 01110 10100 01111 00111 01101 11010 00000 11001 10010 00110 01011 01101 01000 10101 00100 10100 00011 10001 00010 11101 00011 01100 11101 00011 00100 01111 11000 10100 00110 01110 11110 10110
    checksum        = 01100 00111 01001 10001 01011 10101

    Estou exibindo os inteiros de 5 bits em binário apenas para fins visuais. Você não precisa fazer isso ao decodificar, pois pode mantê-los como arrays de inteiros de 5 bits.

    3. Verificar o checksum

    Em seguida, devemos verificar se o checksum do endereço é válido.

    Para fazer isso, calculamos o checksum usando a parte legível por humanos do passo 1 e a versão e o programa de testemunha que decodificamos no passo 2:

    checksum (calculado) = 01100 00111 01001 10001 01011 10101

    Em seguida, comparamos isso ao checksum fornecido no endereço:

    checksum (endereço)  = 01100 00111 01001 10001 01011 10101
    

    Se os checksums coincidem, sabemos que o endereço foi digitado corretamente e que nenhum erro foi cometido.

    Esta é apenas uma verificação simples. O checksum, na verdade, permite detectar a posição de possíveis erros e fornecer sugestões de como corrigi-los.

    4. Versão

    Em seguida, o inteiro da versão precisa ser convertido em um byte hex correspondente a um opcode OP_N.

    Por exemplo:

    Versão para opcode e byte hex
    Versão Opcode Hex
    0OP_000
    1OP_151
    2OP_252
    .........
    16OP_1660

    A versão é 0 no nosso exemplo, que corresponde ao opcode OP_0, representado pelo seguinte byte hex:

    version = 00
    

    Conversão rápida. Se a versão for maior que zero, some 0x51 para obter o byte do opcode OP_N.

    • Não converta o valor inteiro da versão diretamente para um byte hex. Por exemplo, a versão 1 corresponde a OP_1, representado pelo byte 51. Se você convertê-la diretamente para hex, vai obter 01, que é um opcode inválido para o número de versão.
    • O número de versão deve estar entre 0 e 16. Qualquer outro número de versão é inválido.

    5. Grupos de 8 bits

    Rearranje o programa de testemunha de grupos de 5 bits para grupos de 8 bits:

    witness program (grupos de 5 bits) = 01110 10100 01111 00111 01101 11010 00000 11001 10010 00110 01011 01101 01000 10101 00100 10100 00011 10001 00010 11101 00011 01100 11101 00011 00100 01111 11000 10100 00110 01110 11110 10110
    
    witness program (grupos de 8 bits) = 01110101 00011110 01110110 11101000 00011001 10010001 10010110 11010100 01010100 10010100 00011100 01000101 11010001 10110011 10100011 00100011 11110001 01000011 00111011 11010110

    Como você pode ver, simplesmente reagrupamos os bits em grupos de 8 bits.

    Verifique se os grupos de 5 bits não contêm preenchimento demais. Se o resto da divisão do total de bits nos grupos de 5 bits pelo total de bits nos grupos de 8 bits resultantes for 5 ou maior, então o endereço continha preenchimento demais.

    Verifique se o preenchimento contém apenas zeros. A quantidade de preenchimento é o total de bits nos grupos de 5 bits menos o total de bits nos grupos de 8 bits. Se esse preenchimento contiver qualquer coisa além de zeros, o preenchimento é inválido.

    Se convertermos esses grupos de 8 bits em bytes hex, obtemos:

    witness program (bytes) = 75 1e 76 e8 19 91 96 d4 54 94 1c 45 d1 b3 a3 23 f1 43 3b d6

    6. ScriptPubKey

    Por fim, para construir o ScriptPubKey final, primeiro precisamos calcular o tamanho do programa de testemunha do passo anterior.

    No nosso exemplo, o programa de testemunha tem 20 bytes de comprimento, que como byte hex é 14. Isso nos dá:

    version = 00
    size = 14
    witness program = 75 1e 76 e8 19 91 96 d4 54 94 1c 45 d1 b3 a3 23 f1 43 3b d6

    Se combinarmos essas 3 partes de dados, temos o nosso ScriptPubKey completo:

    scriptpubkey = 0014751e76e8199196d454941c45d1b3a323f1433bd6
    

    Como esta é uma versão 0 com um programa de testemunha de 20 bytes, conseguimos dizer que este é um script de travamento P2WPKH.

    Código

    # --------
    # configurações
    # --------
    
    # conjunto de caracteres base32
    characters = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" # todos os caracteres alfanuméricos minúsculos exceto "1", "b", "i", "o"
    
    # exibe o algoritmo de checksum completo
    display_checksum_algorithm = false # true ou false
    
    puts "-------"
    puts "address"
    puts "-------"
    puts
    
    # endereço Bech32 que queremos converter para um scriptpubkey
    address = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4" # scriptpubkey P2WPKH de exemplo
    puts "address:   #{address}"
    puts
    
    # encontra a posição do separador (a última ocorrência de um "1")
    separator_position = address.rindex("1")
    # nota: o separador é sempre "1"
    # cuidado: você quer a _última_ ocorrência de "1", pois a parte legível por humanos pode conter um "1"
    
    # tudo antes do separador é a parte legível por humanos
    hrp = address[0..separator_position - 1]
    
    # tudo depois do separador é a parte de dados
    data = address[separator_position + 1..-1]
    
    puts "hrp:       #{hrp}"
    puts "data:      #{data}"
    puts
    # nota: o separador não é usado ao converter o endereço para um scriptpubkey
    
    puts "------------"
    puts "5-bit groups"
    puts "------------"
    puts
    
    # converte cada caractere base32 para o seu valor inteiro de 5 bits correspondente
    data_5_bits = data.split("").map { |c| characters.index(c) }
    
    # o primeiro grupo de 5 bits é a versão
    version_5_bits = data_5_bits.shift
    
    # os últimos 6 grupos de 5 bits são o checksum
    checksum_5_bits = data_5_bits.pop(6)
    
    # os grupos de 5 bits restantes são o programa de testemunha
    witness_program_5_bits = data_5_bits
    
    # exibe os grupos de 5 bits como inteiros
    puts "version:   #{version_5_bits}"
    puts "program:   #{witness_program_5_bits.join(' ')}"
    puts "checksum:  #{checksum_5_bits.join(' ')}"
    puts
    
    # mostra os grupos de 5 bits como strings binárias
    puts "version:   #{version_5_bits.to_s(2).rjust(5, "0")}"
    puts "program:   #{witness_program_5_bits.map { |v| v.to_s(2).rjust(5, "0") }.join(' ')}"
    puts "checksum:  #{checksum_5_bits.map { |v| v.to_s(2).rjust(5, "0") }.join(' ')}"
    puts
    
    puts "---------------------"
    puts "checksum verification"
    puts "---------------------"
    puts
    # calcula o checksum a partir da hrp e do programa de testemunha fornecidos
    
    # converte a parte legível por humanos para os valores de caractere UTF-8 correspondentes
    hrp_values = hrp.split("").map { |c| c.ord }
    
    # expande a parte legível por humanos em grupos de 5 bits
    hrp_expanded = []
    
    # pega os primeiros 3 bits do valor inteiro de cada caractere
    hrp_values.each do |v|
      hrp_expanded << (v >> 5) # desloca 5 bits à direita para obter os primeiros 3 bits
    end
    
    # adiciona o separador
    hrp_expanded << 0
    
    # pega os últimos 5 bits do valor inteiro de cada caractere
    hrp_values.each do |v|
      hrp_expanded << (v & 0b11111) # usa uma máscara de bits para extrair os últimos 5 bits
    end
    
    # combina a parte legível por humanos expandida com a versão e o programa de testemunha (todos em grupos de 5 bits)
    combined = hrp_expanded + [version_5_bits] + witness_program_5_bits
    
    # adiciona preenchimento (padding)
    combined_with_padding = combined + [0, 0, 0, 0, 0, 0]
    
    # valores geradores do checksum
    generator = [
      0b111011011010100101011110110010, # 0x3b6a57b2
      0b100110010100001000111001101101, # 0x26508e6d
      0b011110101000010001100111111010, # 0x1ea119fa
      0b111101010000100011001111011101, # 0x3d4233dd
      0b101010000101000110001010110011, # 0x2a1462b3
    ]
    
    # valor inicial do checksum (o resultado final do checksum terá 30 bits)
    checksum = 1
    
    # percorre cada grupo de 5 bits no array combinado
    combined_with_padding.each do |v|
      
      # remove 25 bits da direita do valor atual do checksum e guarda o resultado
      top = checksum >> 25
    
      # extrai os 25 bits inferiores do valor atual do checksum usando uma máscara de bits
      checksum = checksum & 0b1111111111111111111111111
    
      # desloca o valor do checksum à esquerda (adiciona 5 bits zero ao final, criando espaço para o xor com o valor atual de 5 bits)
      checksum = checksum << 5
    
      # faz o xor do checksum atual com o próximo valor de 5 bits
      checksum = checksum ^ v
    
      # percorre os últimos 5 bits do valor "top"
      5.times do |i|
    
        # se o próximo bit do valor "top" for 1
        if ((top >> i) & 1) == 1
    
          # faz o xor do checksum atual com o valor gerador correspondente
          checksum = checksum ^ generator[i]
        end
      end
    
    end
    
    # define a constante para o xor do checksum com base no número da versão
    if (version_5_bits == 0)
      constant = 1 # bech32
    else
      constant = 0x2bc830a3 # bech32m
    end
    
    # exibe a constante
    puts "constant:      #{constant.to_s(2).rjust(30, "0")}" if display_checksum_algorithm
    
    # faz o xor do checksum com a constante
    checksum = checksum ^ constant
    
    # converte o checksum em 6 grupos de 5 bits
    checksum_verify = []
    
    # queremos 6 grupos de 5 bits
    6.times do |i|
    
      # calcula o deslocamento à direita para pegar cada grupo de 5 bits do checksum de 30 bits
      right_shift = 5 * (5 - i)
    
      # desloca o valor do checksum à direita
      shifted = (checksum >> right_shift)
    
      # extrai os últimos 5 bits do valor deslocado
      bits = shifted & 0b11111
    
      # adiciona o grupo de 5 bits ao array do checksum
      checksum_verify << bits
    end
    
    # exibe o checksum calculado
    print "checksum:  #{checksum_verify.map { |v| v.to_s(2).rjust(5, "0") }.join(' ')}"
    
    # verifica se o checksum calculado bate com o checksum do endereço
    if checksum_5_bits == checksum_verify
      puts " ✓"
    else
      puts " ✗"
    end
    puts
    
    
    puts "-------"
    puts "version"
    puts "-------"
    puts
    
    # converte o valor inteiro da versão para o seu byte hex OP_N correspondente
    if (version_5_bits == 0)
      version_op_n_hex = version_5_bits.to_s(16).rjust(2, "0") # OP_0
    else
      version_op_n_hex = (version_5_bits + 0x50).to_s(16).rjust(2, "0") # OP_1 a OP_16
    end
    
    puts "5-bits:    #{version_5_bits.to_s(2).rjust(5, "0")}"
    puts "opcode:    OP_#{version_5_bits}"
    puts "hex:       #{version_op_n_hex}"
    puts
    
    
    puts "------------"
    puts "8-bit groups"
    puts "------------"
    puts
    
    # rearranja o programa de testemunha de um array de inteiros de 5 bits para um array de inteiros de 8 bits
    from = 5 # número de bits no inteiro de partida
    to   = 8 # número de bits no inteiro de destino
    accumulator  = 0
    counter = 0
    max_value = (1 << to) - 1 # valor máximo (5 bits = 0b100000 = 32)
    max_accumulator = (1 << (from + to -1)) -1 # 8 bits + 5 bits - 1 bit = 12 bits = 4095 = 0b111111111111
    witness_program_8_bits = [] # o array de retorno
    
    # percorre cada inteiro de 5 bits no array do programa de testemunha
    witness_program_5_bits.each do |int_5_bits|
    
      # retorna nil se for negativo
      if int_5_bits < 0
        return nil
      end
    
      # retorna nil se o tamanho do inteiro for maior que o tamanho especificado do grupo de bits de partida
      if (int_5_bits >> from) != 0
        return nil
      end
    
      # adiciona os bits de partida ao acumulador
      accumulator = accumulator << from           # << = deslocamento de bits à esquerda
      accumulator = accumulator | int_8_bits      # | = OU bit a bit (nota: este comentário é necessário para o realce de sintaxe funcionar corretamente no site learnmeabitcoin.com — um pipe sozinho em uma linha quebra o realce por algum motivo)
      accumulator = accumulator & max_accumulator # & = E bit a bit
    
      # incrementa o contador
      counter += from
    
      # enquanto houver bits suficientes para produzir um novo grupo de 8 bits
      while counter >= to
    
        # decrementa o contador
        counter -= to
    
        # adiciona o valor de 8 bits ao resultado
        witness_program_8_bits << ((accumulator >> counter) & max_value)
      end
    end
    
    # exibe o resultado
    puts "program:   #{witness_program_8_bits.map { |v| v.to_s(2).rjust(8, "0") }.join(' ')}"
    puts
    
    puts "------------"
    puts "scriptpubkey"
    puts "------------"
    puts
    
    # calcula o tamanho do programa de testemunha e converte para byte hex
    witness_program_size_hex = witness_program_8_bits.size.to_s(16).rjust(2, "0")
    
    # converte o programa de testemunha para hex
    witness_program_hex = witness_program_8_bits.map { |v| v.to_s(16).rjust(2, "0") }.join
    
    # exibe a versão, o tamanho e o programa de testemunha em hex
    puts "version:   #{version_op_n_hex}"
    puts "size:      #{witness_program_size_hex}"
    puts "program:   #{witness_program_hex}"
    puts
    
    # combina a versão, o tamanho e o programa de testemunha em um scriptpubkey
    scriptpubkey = version_op_n_hex + witness_program_size_hex + witness_program_hex
    puts "scriptpubkey: #{scriptpubkey}" # 0014751e76e8199196d454941c45d1b3a323f1433bd6

    Checksum

    Como calcular um checksum Bech32?

    A parte mais complexa da codificação Bech32 é calcular o checksum.

    O algoritmo de checksum usa códigos BCH, que permitem correção de erros ao longo dos dados (o que não é possível com o checksum simples usado no Base58). Isso torna o checksum do Bech32 muito mais útil, mas também mais complexo de calcular.

    Eu não conheço o suficiente sobre códigos BCH para explicar o projeto do algoritmo, então vou apenas mostrar como calcular o checksum.

    Diagrama mostrando como calcular o checksum de um endereço Bech32.

    1. Preparar os dados

    O checksum de um endereço Bech32 é calculado a partir dos seguintes dados:

    1. Parte legível por humanos. O prefixo que você quer usar no endereço final precisa ser escolhido antes de criar o checksum. Essa string normalmente é 'bc' (mainnet), 'tb' (testnet) ou 'bcrt' (regtest).
    2. Versão. Este é o número de versão do ScriptPubKey segwit. É um valor inteiro de 5 bits indicado por um opcode OP_N.
    3. Programa de testemunha. Este é o programa de testemunha do ScriptPubKey como um array de valores de 5 bits. Então, se você está calculando o checksum a partir de um ScriptPubKey bruto, primeiro precisa rearranjar o programa de testemunha de um array de bytes de 8 bits para um array de valores de 5 bits.

    Aqui estão alguns dados de exemplo:

    hrp             = 'bc'
    version         = 00000
    witness program = 01110 10100 01111 00111 01101 11010 00000 11001 10010 00110 01011 01101 01000 10101 00100 10100 00011 10001 00010 11101 00011 01100 11101 00011 00100 01111 11000 10100 00110 01110 11110 10110
    

    O byte de tamanho do ScriptPubKey e o separador do endereço não são cobertos pelo checksum.

    2. Expandir a parte legível por humanos

    Diagrama mostrando como expandir a parte legível por humanos em grupos de 5 bits.

    A parte legível por humanos é usada como prefixo do endereço. Ela precisa ser incluída no checksum para que possamos detectar se foi digitada corretamente.

    Esse prefixo é uma string de 1 a 83 caracteres US-ASCII. Portanto, precisamos "expandir" esses caracteres para transformá-los em um array de valores de 5 bits.

    É assim que você expande a parte legível por humanos:

    1. Converta cada caractere para o seu valor de byte ASCII de 8 bits.
    2. Pegue os primeiros 3 bits do valor de byte de cada caractere.
    3. Adicione um zero como separador.
    4. Pegue os últimos 5 bits do valor de byte de cada caractere.

    Então, basicamente, como cada caractere ASCII representa um valor de 8 bits, nós os dividimos para obter um array de valores de 5 bits.

    Por exemplo:

    hrp            = 'bc'
    hrp (ASCII)    = 01100010 01100011
    hrp (expandido) = 00011 00011 00000 00010 00011
    

    A parte legível por humanos agora está representada como um array de inteiros de 5 bits. Isso combina com a estrutura da versão e do programa de testemunha (que também estão em arrays de inteiros de 5 bits).

    3. Construir o array de 5 bits

    A entrada do algoritmo de checksum é um array de 5 bits com os seguintes dados:

    1. Parte legível por humanos expandida. O array de inteiros de 5 bits do passo 2.
    2. Versão. Um inteiro de 5 bits baseado no valor do opcode OP_N.
    3. Programa de testemunha. Um array de inteiros de 5 bits.
    4. Preenchimento. Um array de 6 inteiros zero de 5 bits.

    Então você basicamente pega a hrp, a versão e o programa de testemunha, e adiciona um preenchimento ao final.

    Por exemplo:

    hrp (expandido)  = 00011 00011 00000 00010 00011
    version         = 00000
    witness program = 01110 10100 01111 00111 01101 11010 00000 11001 10010 00110 01011 01101 01000 10101 00100 10100 00011 10001 00010 11101 00011 01100 11101 00011 00100 01111 11000 10100 00110 01110 11110 10110
    padding         = 00000 00000 00000 00000 00000 00000
    
    5-bit array     = 00011 00011 00000 00010 00011 00000 01110 10100 01111 00111 01101 11010 00000 11001 10010 00110 01011 01101 01000 10101 00100 10100 00011 10001 00010 11101 00011 01100 11101 00011 00100 01111 11000 10100 00110 01110 11110 10110 00000 00000 00000 00000 00000 00000
    

    Esse array combinado de inteiros de 5 bits é a entrada do algoritmo de checksum principal.

    4. Polymod

    Esta é a parte divertida.

    O checksum final será um valor de 30 bits. O valor inicial do checksum é 1, então o nosso checksum inicial fica assim:

    000000000000000000000000000001

    Agora vamos percorrer cada inteiro de 5 bits do nosso array e executar os seguintes passos:

    1. Top

    Pegue os primeiros 5 bits do valor atual do checksum. Este é o valor "top", e será usado em um passo posterior.

    top = 00000

    2. Bottom

    Pegue os 25 bits inferiores do valor atual do checksum. Este é o valor "bottom", e é o que vamos ajustar.

    bottom = 0000000000000000000000001

    3. Preenchimento

    Adicione 5 bits de preenchimento aos 25 bits "bottom" do passo anterior para totalizar 30 bits.

    padded = 000000000000000000000000100000

    4. XOR com o próximo valor de 5 bits

    Pegue o próximo valor de 5 bits do array e faça um XOR com o valor de checksum de 30 bits preenchido do passo anterior:

    padded      = 000000000000000000000000100000
    5-bit value =                          00011
    xor         = 000000000000000000000000100011
    

    5. XOR com os valores geradores

    Agora fazemos o XOR do valor do passo anterior com os seguintes valores geradores:

    generator 0 = 111011011010100101011110110010
    generator 1 = 100110010100001000111001101101
    generator 2 = 011110101000010001100111111010
    generator 3 = 111101010000100011001111011101
    generator 4 = 101010000101000110001010110011
    

    No entanto, nem sempre fazemos o XOR com todos esses valores geradores. Em vez disso, usamos o valor "top" para determinar com quais valores geradores realmente fazemos o XOR.

    Usando o valor "top", lemos os bits da direita para a esquerda para determinar com quais valores geradores fazemos o XOR do valor atual do checksum. Se o bit estiver setado (ou seja, "1"), fazemos o XOR com aquele valor gerador correspondente.

    Usando o nosso exemplo atual:

    top = 00000
    
    generator 0 = 111011011010100101011110110010 (bit 4 = 0, não faz XOR)
    generator 1 = 100110010100001000111001101101 (bit 3 = 0, não faz XOR)
    generator 2 = 011110101000010001100111111010 (bit 2 = 0, não faz XOR)
    generator 3 = 111101010000100011001111011101 (bit 1 = 0, não faz XOR)
    generator 4 = 101010000101000110001010110011 (bit 0 = 0, não faz XOR)
    xor         = 000000000000000000000000100011
    
    result      = 000000000000000000000000100011
    

    Nenhum dos bits em "top" está setado, então não fazemos o XOR do valor atual do checksum com nenhum dos geradores.

    Se o bit mais à direita estiver setado, fazemos o XOR com o gerador 0. Se o próximo bit a partir da direita estiver setado, também fazemos o XOR com o gerador 1, e assim por diante.

    6. Repetir

    Repita os passos anteriores para todos os inteiros de 5 bits do array.

    Cálculos passo a passo completos
    checksum: 000000000000000000000000000001
    top:      00000
    bottom:        0000000000000000000000001
    padded:        000000000000000000000000100000
    5-bit group:                            00011
    xor:           000000000000000000000000100011
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      000000000000000000000000100011
    
    checksum: 000000000000000000000000100011
    top:      00000
    bottom:        0000000000000000000100011
    padded:        000000000000000000010001100000
    5-bit group:                            00011
    xor:           000000000000000000010001100011
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      000000000000000000010001100011
    
    checksum: 000000000000000000010001100011
    top:      00000
    bottom:        0000000000000010001100011
    padded:        000000000000001000110001100000
    5-bit group:                            00000
    xor:           000000000000001000110001100000
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      000000000000001000110001100000
    
    checksum: 000000000000001000110001100000
    top:      00000
    bottom:        0000000001000110001100000
    padded:        000000000100011000110000000000
    5-bit group:                            00010
    xor:           000000000100011000110000000010
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      000000000100011000110000000010
    
    checksum: 000000000100011000110000000010
    top:      00000
    bottom:        0000100011000110000000010
    padded:        000010001100011000000001000000
    5-bit group:                            00011
    xor:           000010001100011000000001000011
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      000010001100011000000001000011
    
    checksum: 000010001100011000000001000011
    top:      00001
    bottom:        0001100011000000001000011
    padded:        000110001100000000100001100000
    5-bit group:                            00000
    xor:           000110001100000000100001100000
    generator 0:   111011011010100101011110110010 xor
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      111101010110100101111111010010
    
    checksum: 111101010110100101111111010010
    top:      11110
    bottom:        1010110100101111111010010
    padded:        101011010010111111101001000000
    5-bit group:                            01110
    xor:           101011010010111111101001001110
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101 xor
    generator 4:   101010000101000110001010110011 xor
    checksum:      000100111011000011110010110111
    
    checksum: 000100111011000011110010110111
    top:      00010
    bottom:        0111011000011110010110111
    padded:        011101100001111001011011100000
    5-bit group:                            10100
    xor:           011101100001111001011011110100
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      111011110101110001100010011001
    
    checksum: 111011110101110001100010011001
    top:      11101
    bottom:        1110101110001100010011001
    padded:        111010111000110001001100100000
    5-bit group:                            01111
    xor:           111010111000110001001100101111
    generator 0:   111011011010100101011110110010 xor
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101 xor
    generator 4:   101010000101000110001010110011 xor
    checksum:      001000011111100000110000001001
    
    checksum: 001000011111100000110000001001
    top:      00100
    bottom:        0011111100000110000001001
    padded:        001111110000011000000100100000
    5-bit group:                            00111
    xor:           001111110000011000000100100111
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      010001011000001001100011011101
    
    checksum: 010001011000001001100011011101
    top:      01000
    bottom:        1011000001001100011011101
    padded:        101100000100110001101110100000
    5-bit group:                            01101
    xor:           101100000100110001101110101101
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101 xor
    generator 4:   101010000101000110001010110011
    checksum:      010001010100010010100001110000
    
    checksum: 010001010100010010100001110000
    top:      01000
    bottom:        1010100010010100001110000
    padded:        101010001001010000111000000000
    5-bit group:                            11010
    xor:           101010001001010000111000011010
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101 xor
    generator 4:   101010000101000110001010110011
    checksum:      010111011001110011110111000111
    
    checksum: 010111011001110011110111000111
    top:      01011
    bottom:        1011001110011110111000111
    padded:        101100111001111011100011100000
    5-bit group:                            00000
    xor:           101100111001111011100011100000
    generator 0:   111011011010100101011110110010 xor
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101 xor
    generator 4:   101010000101000110001010110011
    checksum:      001100100111110101001011100010
    
    checksum: 001100100111110101001011100010
    top:      00110
    bottom:        0100111110101001011100010
    padded:        010011111010100101110001000000
    5-bit group:                            11001
    xor:           010011111010100101110001011001
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      101011000110111100101111001110
    
    checksum: 101011000110111100101111001110
    top:      10101
    bottom:        1000110111100101111001110
    padded:        100011011110010111100111000000
    5-bit group:                            10010
    xor:           100011011110010111100111010010
    generator 0:   111011011010100101011110110010 xor
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011 xor
    checksum:      101100101001100101010100101001
    
    checksum: 101100101001100101010100101001
    top:      10110
    bottom:        0101001100101010100101001
    padded:        010100110010101010010100100000
    5-bit group:                            00110
    xor:           010100110010101010010100100110
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011 xor
    checksum:      000110001011110101000000000010
    
    checksum: 000110001011110101000000000010
    top:      00011
    bottom:        0001011110101000000000010
    padded:        000101111010100000000001000000
    5-bit group:                            01011
    xor:           000101111010100000000001001011
    generator 0:   111011011010100101011110110010 xor
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      011000110100001101100110010100
    
    checksum: 011000110100001101100110010100
    top:      01100
    bottom:        0110100001101100110010100
    padded:        011010000110110011001010000000
    5-bit group:                            01101
    xor:           011010000110110011001010001101
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101 xor
    generator 4:   101010000101000110001010110011
    checksum:      111001111110000001100010101010
    
    checksum: 111001111110000001100010101010
    top:      11100
    bottom:        1111110000001100010101010
    padded:        111111000000110001010101000000
    5-bit group:                            01000
    xor:           111111000000110001010101001000
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101 xor
    generator 4:   101010000101000110001010110011 xor
    checksum:      110110111101000101110111011100
    
    checksum: 110110111101000101110111011100
    top:      11011
    bottom:        0111101000101110111011100
    padded:        011110100010111011101110000000
    5-bit group:                            10101
    xor:           011110100010111011101110010101
    generator 0:   111011011010100101011110110010 xor
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101 xor
    generator 4:   101010000101000110001010110011 xor
    checksum:      010100111001110011001100100100
    
    checksum: 010100111001110011001100100100
    top:      01010
    bottom:        0111001110011001100100100
    padded:        011100111001100110010010000000
    5-bit group:                            00100
    xor:           011100111001100110010010000100
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101 xor
    generator 4:   101010000101000110001010110011
    checksum:      000111111101001101100100110100
    
    checksum: 000111111101001101100100110100
    top:      00011
    bottom:        1111101001101100100110100
    padded:        111110100110110010011010000000
    5-bit group:                            10100
    xor:           111110100110110010011010010100
    generator 0:   111011011010100101011110110010 xor
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      100011101000011111111101001011
    
    checksum: 100011101000011111111101001011
    top:      10001
    bottom:        1101000011111111101001011
    padded:        110100001111111110100101100000
    5-bit group:                            00011
    xor:           110100001111111110100101100011
    generator 0:   111011011010100101011110110010 xor
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011 xor
    checksum:      100101010000011101110001100010
    
    checksum: 100101010000011101110001100010
    top:      10010
    bottom:        1010000011101110001100010
    padded:        101000001110111000110001000000
    5-bit group:                            10001
    xor:           101000001110111000110001010001
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011 xor
    checksum:      100100011111110110000010001111
    
    checksum: 100100011111110110000010001111
    top:      10010
    bottom:        0011111110110000010001111
    padded:        001111111011000001000111100000
    5-bit group:                            00010
    xor:           001111111011000001000111100010
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011 xor
    checksum:      000011101010001111110100111100
    
    checksum: 000011101010001111110100111100
    top:      00001
    bottom:        1101010001111110100111100
    padded:        110101000111111010011110000000
    5-bit group:                            11101
    xor:           110101000111111010011110011101
    generator 0:   111011011010100101011110110010 xor
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      001110011101011111000000101111
    
    checksum: 001110011101011111000000101111
    top:      00111
    bottom:        0011101011111000000101111
    padded:        001110101111100000010111100000
    5-bit group:                            00011
    xor:           001110101111100000010111100011
    generator 0:   111011011010100101011110110010 xor
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      001101001001011100010111000110
    
    checksum: 001101001001011100010111000110
    top:      00110
    bottom:        1001001011100010111000110
    padded:        100100101110001011100011000000
    5-bit group:                            01100
    xor:           100100101110001011100011001100
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      011100010010010010111101011011
    
    checksum: 011100010010010010111101011011
    top:      01110
    bottom:        0010010010010111101011011
    padded:        001001001001011110101101100000
    5-bit group:                            11101
    xor:           001001001001011110101101111101
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101 xor
    generator 4:   101010000101000110001010110011
    checksum:      001100100101100100111100110111
    
    checksum: 001100100101100100111100110111
    top:      00110
    bottom:        0100101100100111100110111
    padded:        010010110010011110011011100000
    5-bit group:                            00011
    xor:           010010110010011110011011100011
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      101010001110000111000101110100
    
    checksum: 101010001110000111000101110100
    top:      10101
    bottom:        0001110000111000101110100
    padded:        000111000011100010111010000000
    5-bit group:                            00100
    xor:           000111000011100010111010000100
    generator 0:   111011011010100101011110110010 xor
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011 xor
    checksum:      001000110100010000001001111111
    
    checksum: 001000110100010000001001111111
    top:      00100
    bottom:        0110100010000001001111111
    padded:        011010001000000100111111100000
    5-bit group:                            01111
    xor:           011010001000000100111111101111
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      000100100000010101011000010101
    
    checksum: 000100100000010101011000010101
    top:      00010
    bottom:        0100000010101011000010101
    padded:        010000001010101100001010100000
    5-bit group:                            11000
    xor:           010000001010101100001010111000
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      110110011110100100110011010101
    
    checksum: 110110011110100100110011010101
    top:      11011
    bottom:        0011110100100110011010101
    padded:        001111010010011001101010100000
    5-bit group:                            10100
    xor:           001111010010011001101010110100
    generator 0:   111011011010100101011110110010 xor
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101 xor
    generator 4:   101010000101000110001010110011 xor
    checksum:      000101001001010001001000000101
    
    checksum: 000101001001010001001000000101
    top:      00010
    bottom:        1001001010001001000000101
    padded:        100100101000100100000010100000
    5-bit group:                            00110
    xor:           100100101000100100000010100110
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      000010111100101100111011001011
    
    checksum: 000010111100101100111011001011
    top:      00001
    bottom:        0111100101100111011001011
    padded:        011110010110011101100101100000
    5-bit group:                            01110
    xor:           011110010110011101100101101110
    generator 0:   111011011010100101011110110010 xor
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      100101001100111000111011011100
    
    checksum: 100101001100111000111011011100
    top:      10010
    bottom:        1001100111000111011011100
    padded:        100110011100011101101110000000
    5-bit group:                            11110
    xor:           100110011100011101101110011110
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011 xor
    checksum:      101010001101010011011101000000
    
    checksum: 101010001101010011011101000000
    top:      10101
    bottom:        0001101010011011101000000
    padded:        000110101001101110100000000000
    5-bit group:                            10110
    xor:           000110101001101110100000010110
    generator 0:   111011011010100101011110110010 xor
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011 xor
    checksum:      001001011110011100010011101101
    
    checksum: 001001011110011100010011101101
    top:      00100
    bottom:        1011110011100010011101101
    padded:        101111001110001001110110100000
    5-bit group:                            00000
    xor:           101111001110001001110110100000
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      110001100110011000010001011010
    
    checksum: 110001100110011000010001011010
    top:      11000
    bottom:        1100110011000010001011010
    padded:        110011001100001000101101000000
    5-bit group:                            00000
    xor:           110011001100001000101101000000
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101 xor
    generator 4:   101010000101000110001010110011 xor
    checksum:      100100011001101101101000101110
    
    checksum: 100100011001101101101000101110
    top:      10010
    bottom:        0011001101101101000101110
    padded:        001100110110110100010111000000
    5-bit group:                            00000
    xor:           001100110110110100010111000000
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101 xor
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011 xor
    checksum:      000000100111111010100100011110
    
    checksum: 000000100111111010100100011110
    top:      00000
    bottom:        0100111111010100100011110
    padded:        010011111101010010001111000000
    5-bit group:                            00000
    xor:           010011111101010010001111000000
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101
    generator 4:   101010000101000110001010110011
    checksum:      010011111101010010001111000000
    
    checksum: 010011111101010010001111000000
    top:      01001
    bottom:        1111101010010001111000000
    padded:        111110101001000111100000000000
    5-bit group:                            00000
    xor:           111110101001000111100000000000
    generator 0:   111011011010100101011110110010 xor
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010
    generator 3:   111101010000100011001111011101 xor
    generator 4:   101010000101000110001010110011
    checksum:      111000100011000001110001101111
    
    checksum: 111000100011000001110001101111
    top:      11100
    bottom:        0100011000001110001101111
    padded:        010001100000111000110111100000
    5-bit group:                            00000
    xor:           010001100000111000110111100000
    generator 0:   111011011010100101011110110010
    generator 1:   100110010100001000111001101101
    generator 2:   011110101000010001100111111010 xor
    generator 3:   111101010000100011001111011101 xor
    generator 4:   101010000101000110001010110011 xor
    checksum:      011000011101001100010101110100
    

    Para o nosso exemplo, isso nos dá um valor de checksum resultante de:

    checksum = 011000011101001100010101110100

    5. Constante

    Por último, fazemos o XOR do valor atual do checksum com uma constante.

    A constante que usamos depende da versão do ScriptPubKey (veja Bech32m):

    Version 0  = 000000000000000000000000000001
    Version 1+ = 101011110010000011000010100011
    

    O nosso exemplo é um ScriptPubKey P2WPKH, que é versão 0:

    checksum = 011000011101001100010101110100
    constant = 000000000000000000000000000001
    result   = 011000011101001100010101110101
    

    6. Dividir em grupos de 5 bits

    Por fim, podemos dividir o nosso checksum de 30 bits em 6 grupos de 5 bits:

    checksum = 011000011101001100010101110101
    checksum = 01100 00111 01001 10001 01011 10101
    

    Este é o nosso checksum final.

    Código

    Veja codificar ou decodificar para o algoritmo de checksum.

    Bech32m

    BIP 350

    Bech32m se refere a um pequeno ajuste feito no algoritmo de checksum para endereços Bech32 da versão 1 em diante.

    A única diferença é que você usa uma constante diferente antes de calcular o valor final do checksum:

    Constante de checksum por versão
    Versão Constante Tipo(s) de endereço
    0 0b000000000000000000000000000001 P2WPKH, P2WSH
    1+ 0b101011110010000011000010100011 P2TR

    Todo o resto da codificação Bech32 permanece igual.

    Essa mudança corrige um problema em que, se o último caractere do endereço for "p", inserir ou remover qualquer número de caracteres "q" não torna o checksum inválido.

    Isso não é um problema grave, já que os endereços P2WPKH e P2WSH existentes não são afetados, pelo fato de estarem restritos a dois comprimentos específicos. Mesmo assim, daqui em diante essa mudança garante que o checksum seja confiável para todos os endereços futuros.

    É mais fácil pensar nisso como o novo método de codificação padrão do "Bech32". Em outras palavras, os scripts de travamento versão 0 (P2WPKH e P2WSH) usam uma constante "legada" diferente.

    Etimologia

    De onde vem o nome "Bech32"?

    O nome "Bech32" (besh trinta e dois) vem do fato de o endereço usar caracteres base32, e de o checksum usar códigos BCH para o algoritmo de detecção/correção de erros.

    Então, se você juntar "base32" e "BCH", obtém "Bech32". Mais ou menos.

    "Bech" contém os caracteres BCH (o algoritmo de detecção de erros usado) e soa um pouco como "base".
    Pieter Wuille, BIP 173

    Não é perfeito, eu sei. Mas serve.

    Resumo

    O Bech32 é simplesmente um formato melhor para endereços em comparação ao Base58.

    O Base58 era/é útil porque te dá um bom conjunto de caracteres para trabalhar e um checksum simples para detectar erros. Mas o Bech32 oferece um monte de melhorias úteis:

    O Base58 foi um esforço bem decente, e você não pode culpar o Satoshi por ele não ser perfeito, já que ele provavelmente não tinha meses para passar construindo o formato de endereço definitivo; era simples e eficaz. Mas, desde então, tivemos o luxo do tempo para construir algo melhor.

    Ainda usamos o Base58 para scripts de travamento legados, chaves privadas e chaves estendidas:

    Mas o Bech32 agora é usado para todos os scripts de travamento modernos:

    A única desvantagem cruel do Bech32 é que o conjunto de caracteres base32 não inclui a letra "b", então eu não consigo construir um endereço vanity com a palavra "beer" (cerveja) nele. Mas isso é só algo com que eu preciso conviver.

    Recursos