TXID
A referência única de uma transação
Um TXID (Transaction ID) é uma referência única para uma transação de bitcoin.
Eles são usados para procurar transações específicas em um explorador de blocos. Por exemplo:
- f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16 — A primeira transação de Bitcoin da história, para Hal Finney, em 2009.
- a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d — A transação da pizza por 10.000 BTC, em 2010.
- 4ce18f49ba153a51bcda9bb80d7f978e3de6e81b5fc326f00465464530c052f4 — A transação contendo a primeira doação que recebi por fazer este site.
As letras e números em um TXID não têm significado especial. São só um monte de 32 bytes de aparência aleatória (representados como 64 caracteres hexadecimais). Mas são únicos para cada transação.
Criando
Como você cria um TXID?
Um TXID é criado fazendo o hash dos dados da transação. Mais precisamente, passando partes específicas dos dados da transação pela função de hash SHA256 e passando o resultado pelo SHA256 de novo (esse hash duplo, ou double-SHA256, é chamado de HASH256).
- Para transações legadas, você faz o HASH256 de todos os dados da transação.
- Para transações segwit, você faz o HASH256 de todos os dados da transação exceto os campos marker, flag e witness.
Então, em transações segwit, as assinaturas não fazem mais parte do TXID.
Os TXIDs que você vê nos exploradores de blocos estão, na verdade, em ordem de bytes invertida. Isso é só uma peculiaridade do bitcoin.
Código
Um TXID é criado da mesma forma que um hash de bloco. Você só precisa fazer o HASH256 das partes corretas dos dados da transação para criar o TXID:
require 'digest'
# ----------------
# dados da transação
# ----------------
data = "0100000001c997a5e56e104102fa209c6a852dd90660a20b2d9c352423edce25857fcd3704000000004847304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901ffffffff0200ca9a3b00000000434104ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84cac00286bee0000000043410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac00000000"
# ----
# TXID
# ----
# Nota: não passe os dados da transação para a função de hash como string.
# Converta-os de hexadecimal para bytes brutos primeiro.
# converte string hexadecimal para sequência de bytes
bytes = [data].pack("H*") # H = string hex (byte mais significativo primeiro), * = múltiplos bytes
# SHA-256 (primeira rodada)
hash1 = Digest::SHA256.digest(bytes)
# SHA-256 (segunda rodada)
hash2 = Digest::SHA256.digest(hash1)
# converte da sequência de bytes de volta para string hexadecimal
txid = hash2.unpack("H*")[0]
# imprime o resultado (ordem natural de bytes)
puts txid #=> 169e1e83e930853391bc6f35f605c6754cfead57cf8387639d3b4096c54f18f4
# imprime o resultado (ordem de bytes invertida)
puts txid.scan(/../).reverse.join #=> f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16 Lembre-se de que, ao trabalhar com transações segwit, você não inclui o marker, o flag e a testemunha como parte dos dados da transação que estão sendo hasheados.
Exemplos
Como é um TXID?
1. Transação Legada
Para criar um TXID de uma transação legada, você faz o HASH256 de todos os dados da transação:
0100000001c997a5e56e104102fa209c6a852dd90660a20b2d9c352423edce25857fcd3704000000004847304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901ffffffff0200ca9a3b00000000434104ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84cac00286bee0000000043410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac00000000 Nota: Os dados que são hasheados para criar o TXID estão destacados em verde.
Se você fizer o HASH256 de todos esses dados, obtém 169e1e83e930853391bc6f35f605c6754cfead57cf8387639d3b4096c54f18f4, que é o TXID em ordem natural de bytes e é o que se encontra dentro dos dados brutos da transação.
Depois, se você inverter a ordem dos bytes, obtém o TXID f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16, que é a ordem de bytes usada ao procurar transações nos exploradores de blocos.
2. Transação SegWit
Para criar um TXID de uma transação segwit, você faz o HASH256 de todos os dados da transação exceto os campos marker, flag e witness.
020000000001013a53de6e1fe821452674c5435e3989eecdf35cb1de1c8bafb674f543a55d658c3600000000fdffffff01599aea0400000000160014cfbd92a6337e8b6043552d6fc5c35c7e5062281e0247304402201250febbce0a5b333c2d715b869cb960f5abf1702192c7af6e112c6d6030be880220073c55f4814a064bf804d9ed16b57eaaeaafb536c4187e6260ef3fc61ca98a77012102e71911951e1f9799d5ccd05200ea0c18f786cb1bb45754d4a0799a06c2b80e8000000000 Nota: Os dados que são hasheados para criar o TXID estão destacados em verde.
Se você fizer o HASH256 dos dados destacados, obtém 01cda497b58d876f207b74c1f0b741f397c376852b3c68b0b6db042a24ffd96c; depois, invertendo a ordem dos bytes, obtém o TXID 6cd9ff242a04dbb6b0683c2b8576c397f341b7f0c1747b206f878db597a4cd01.
Ao criar um TXID para uma transação segwit, você não faz o hash dos campos que são novos nas transações segwit. Isso evita que qualquer dado de assinatura faça parte do TXID (que agora ficam na testemunha), pois as assinaturas podem ser manipuladas para mudar o TXID depois de uma transação ter sido enviada à rede (o que é raro, mas tornava os TXIDs menos confiáveis).
Esse foi o principal motivo da atualização segregated witness.
Faça você mesmo
Você pode conferir que os dados acima produzem os TXIDs corretos hasheando os mesmos dados manualmente com HASH256 diretamente:
Depois, não esqueça de inverter a ordem dos bytes:
Uso
Como os TXIDs são usados no Bitcoin?
Os TXIDs têm um papel importante na forma como o Bitcoin funciona. Eles são usados nas seguintes situações:
1. Procurar transações
Você normalmente usa TXIDs para procurar transações específicas em um explorador de blocos ou no seu próprio nó local:
$ bitcoin-cli getrawtransaction f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16
0100000001c997a5e56e104102fa209c6a852dd90660a20b2d9c352423edce25857fcd3704000000004847304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901ffffffff0200ca9a3b00000000434104ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84cac00286bee0000000043410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac00000000
# Nota: você precisa definir txindex=1 no bitcoin.conf para procurar todas as transações da blockchain. Isso é útil quando você quer conferir os detalhes de uma transação ou descobrir a sua localização (ou seja, se ela já foi minerada na blockchain ou se ainda está na mempool).
2. Referenciar saídas anteriores para gasto
Você usa TXIDs para referenciar saídas de transações anteriores para usar como entradas ao criar uma transação de bitcoin.
Os TXIDs são únicos, então você pode usá-los em combinação com um VOUT para referenciar qualquer saída específica na blockchain para gasto.
3. Criar uma raiz de Merkle
Os TXIDs são usados para criar a raiz de Merkle do cabeçalho do bloco:
Uma raiz de Merkle é criada basicamente fazendo o hash de todos os TXIDs de um bloco em uma estrutura em árvore. Isso cria uma impressão digital única de todas as transações dentro do bloco, que então é colocada dentro do cabeçalho do bloco para impedir que o conteúdo do bloco seja adulterado depois.
Isso acontece porque qualquer mudança nos dados da transação muda o TXID, e qualquer mudança em um TXID tem um efeito em cascata na raiz de Merkle resultante.
Raiz de Merkle
TXIDs Duplicados
Dois TXIDs podem ser iguais?
Os TXIDs são únicos para cada transação.
Porém, na prática há dois exemplos de TXIDs duplicados aparecendo na blockchain:
- e3bf3d07d4b0375638d5f1db5255fe07ba2c4cb067cd81b84ee974b6585fb468
- d5d27987d2a3dfc724e359870c6644b40e497bdc0589a033220fe15429d88599
Tecnicamente falando, é a mesma transação em cada caso, porque ambas têm os mesmos dados de transação subjacentes. Não é que duas transações completamente diferentes acabaram com o mesmo TXID (ou seja, uma colisão de hash) — é só a mesma transação acabando por aparecer em mais de um bloco.
De qualquer forma, essa situação de TXID duplicado só aconteceu porque são transações coinbase.
Veja bem: os campos TXID e VOUT da entrada de uma transação coinbase são fixos, em vez de dinâmicos como em todas as outras transações. Isso significa que a entrada não é forçada a ser única; então, se você decidir manter a saída exatamente igual também (usando o mesmo script de travamento para reivindicar a mesma recompensa de bloco, que foi o que aconteceu nesses dois exemplos), nada impedia que você criasse transações coinbase duplicadas e as minerasse na blockchain.
Claro, você não quer ter transações duplicadas na blockchain, porque os TXIDs são usados para referenciar transações anteriores. Se você tem várias transações com o mesmo TXID, apenas as saídas não gastas de uma dessas transações poderão ser gastas (a mais recente), porque simplesmente não há como referenciar as outras (as anteriores) de forma única.
As Correções
- BIP 30 (22 de fevereiro de 2012): introduziu uma regra que impede blocos de conterem um TXID que já exista (embora isso só inclua a verificação dos TXIDs dentro do conjunto UTXO).
- BIP 34 (06 de julho de 2012): passou a exigir que as transações coinbase incluíssem a altura do bloco atual nos seus dados, o que faz com que os dados de toda transação coinbase sejam sempre únicos.
Essas correções fazem com que não seja mais possível criar transações coinbase duplicadas.
Porém, foi tarde demais para as duas transações duplicadas acima. Como consequência, apenas a cópia mais recente de cada transação pode ter a sua saída gasta, pois as saídas (50 BTC) das duplicatas mais antigas estão inacessíveis e, portanto, "perdidas" para sempre (digo "perdidas" porque sabemos onde elas estão... só que elas não podem ser acessadas).
De qualquer forma, essas duas transações servem como um artefato interessante na história da blockchain e também dão uma ótima pergunta de quiz de bar.
É importante estar ciente desses TXIDs duplicados se você armazena transações em um banco de dados. É um problema pequeno, mas pode te pegar de surpresa se você está inserindo uma linha e espera que todo TXID ainda não exista. Então você só vai precisar levar em conta esses dois casos extremos para o seu script de importação funcionar.
- handle historic transactions with duplicate IDs.
- What would happened if two transactions have the same hash?
- Two blocks, two transactions, same hash
- Can the outputs of transactions with duplicate hashes be spent?
Obrigado ao DJBunnies por apontar isso.