Programação da maturidade do coinbase

Como o Parallax mantém os subsídios dos mineradores em custódia até a maturidade usando atualizações de estado determinísticas e canônicas.

Parâmetros de maturidade
ParâmetroSímboloValor / OrigemNotas
Blocos de maturidade do coinbase
M
100 blocos
Maturidade de coinbase no estilo do Bitcoin
Endereço do lockbox
0x0000000000000000000000000000000000000042
Conta de sistema reservada
Prefixos de chave
"maturity:addr:", "maturity:amt:"
Keccak256(prefixo || altura em big-endian)
Visão geral
O Parallax mantém os subsídios de bloco em custódia até uma altura fixa de maturidade, liberando-os de forma determinística a partir de um lockbox no state trie.
  • Cada bloco agenda seu próprio pagamento de coinbase para a altura atual + M blocos, em que M = 100 blocos.
  • Uma conta especial de lockbox armazena pares "quando" (altura) → (endereço, valor) como slots de estado.
  • A cada altura h, o protocolo verifica se há algum pagamento devido para h e o transfere ao endereço registrado.
  • Isso separa a emissão pendente da oferta disponível para gasto e suaviza o tratamento de reorgs.
Fluxo de alto nível
pseudocódigo
Finalize(header, state):
  h = header.number
  R = calcBlockReward(h)
  M = 100 blocks
  if R > 0:
    putScheduledPayout(state, h + M, header.coinbase, R)
  if due(h):
    (addr, amt) = popDuePayout(state, h)
    state.AddBalance(addr, amt)
  header.Root = state.IntermediateRoot(...)
Chaves de estado e endereço do lockbox
Dois slots de armazenamento por altura de desbloqueio, sob um endereço de sistema reservado.
  • Para uma dada altura de desbloqueio H: armazena-se o endereço em schedKeyAddr(H) e o valor em schedKeyAmt(H).
  • As duas chaves são derivadas via keccak256 de um prefixo ASCII fixo mais H codificado como uint64 big-endian.
  • A presença é determinada pelo slot de valor; o pagamento apaga os dois slots para recuperar espaço no trie.
Derivação de chave (de consensus.go)
pseudocódigo
schedKeyAddr(H):
  b = bigEndianUint64(H)
  return keccak256("maturity:addr:" || b)

schedKeyAmt(H):
  b = bigEndianUint64(H)
  return keccak256("maturity:amt:" || b)
Ciclo de vida do pagamento
Da inclusão no bloco até a transferência após a maturação.
  • O bloco N é minerado → a recompensa R_N é calculada a partir do cronograma de halving.
  • Agenda-se (addr=coinbase_N, amt=R_N) na altura de desbloqueio U = N + M.
  • Na altura U, o nó lê (addr_U, amt_U); se amt_U ≠ 0, credita o valor e apaga os slots.
  • O gênesis (altura 0) não tem subsídio disponível para gasto.
Linha do tempo (diagrama textual)
pseudocódigo
N:   mine block, schedule payout for U=N+M
...
U-1: pending only
U:   popDuePayout → AddBalance(addr_U, amt_U) → clear slots
U+1: nothing due for U anymore
Validação e propriedades de segurança
Desbloqueios determinísticos, seguros contra replay e resistentes a reorgs.
  • A lógica de desbloqueio é calculada a partir da altura canônica; não são necessárias assinaturas nem gatilhos off-chain.
  • Os valores são computados pelo protocolo (calcBlockReward) — os peers não podem inflar os pagamentos.
  • A presença da chave de estado é o indicador de "devido"; o gasto duplo é evitado ao apagar os slots após o crédito.
  • A maturidade adia a disponibilidade do gasto pelo minerador, reduzindo o incentivo para reorgs próximos à ponta visando capturar taxas e subsídio imediatamente.
Detecção de devido e limpeza
pseudocódigo
popDuePayout(state, H):
  rawAmt  = state.Get(lockbox, schedKeyAmt(H))
  if rawAmt == 0: return (zero, 0, false)
  rawAddr = state.Get(lockbox, schedKeyAddr(H))
  state.Set(lockbox, schedKeyAmt(H), 0)
  state.Set(lockbox, schedKeyAddr(H), 0)
  return (Address(rawAddr), BigInt(rawAmt), true)
Comportamento em reorgs
O que acontece se a cadeia se reorganizar em torno de alturas de desbloqueio.
  • Em uma reorg, o estado é recomputado a partir da nova cadeia canônica; as entradas agendadas refletem a sequência canônica de blocos.
  • Se um pagamento ocorreu na altura H na ponta antiga mas não na nova cadeia, o replay de estado só creditará o que for devido pela nova história.
  • Como as entradas são chaveadas por altura, "créditos fantasmas" não sobrevivem a uma reorg — o status de apagado ou não apagado acompanha a execução canônica.
  • Isso espelha a forma como saldos e recibos são recomputados durante a reexecução de blocos.
Pseudocódigo conceitual de reorg
pseudocódigo
ReorgTo(newTip):
  rewind state → parent of fork
  for block in pathTo(newTip):
    Execute(block) // schedules & payouts naturally recompute
Configuração
Onde o parâmetro de maturidade reside e como os clientes o consomem.
  • A maturidade M é definida como 100 blocos
  • Os clientes devem exibir aos mineradores tanto os saldos "pendentes" (agendados) quanto os disponíveis para gasto.
  • Os exploradores podem mostrar desbloqueios futuros buscando por schedKeyAmt(h) diferente de zero.
  • As carteiras devem avisar aos mineradores que as UTXOs de recompensa (créditos de conta) só ficam disponíveis a partir da altura U.
Dica para explorador (pseudo-RPC)
pseudocódigo
for h in [current..current+K]:
  if getState(lockbox, schedKeyAmt(h)) != 0:
    // list upcoming payout at height h