Testemunha (Witness)
A região da transação usada para destravar entradas segwit
A testemunha (witness) é a região de uma transação usada para destravar entradas segwit.
Ela é usada para destravar saídas que têm novos scripts de travamento segregados ("programas de testemunha"), como P2WPKH, P2WSH e P2TR. Se alguma das entradas de uma transação tem um programa de testemunha segwit, você precisa usar a seção de testemunha para destravá-la.
A área de testemunha é uma atualização usada em preferência aos campos ScriptSig. Mas o ScriptSig ainda é usado para destravar scripts legados (P2PK, P2PKH, P2MS, P2SH).
Witness (testemunha) é só outra palavra para as assinaturas nas transações.
Estrutura
Como você destrava uma entrada usando a testemunha?
A testemunha contém um campo de testemunha para cada entrada da transação.
Cada campo de testemunha começa com um campo de itens da pilha (stack items), indicando o número de itens que ele contém; depois, para cada item, há um campo de tamanho seguido do item em si.
Então, basicamente, cada campo de testemunha contém um monte de elementos de dados necessários para destravar a entrada.
Um campo de testemunha é funcionalmente igual ao campo ScriptSig, mas, em vez de usar OP_CODES para empurrar itens para a pilha, você usa campos compact size antes de cada item. Portanto, você não pode usar nenhum OP_CODE dentro dele para operações lógicas; tudo o que você pode fazer é empurrar dados para a pilha — que é tudo o que é necessário para destravar os tipos de script de travamento mais comuns.
Então os dados de testemunha são uma alternativa simplificada ao Script, que contém apenas dados em vez de opcodes.
A testemunha só pode empurrar dados para a pilha. Por exemplo, no ScriptSig você poderia usar 0x58 (OP_8) para empurrar o número 8 para a pilha; mas, para fazer o mesmo na testemunha, você precisaria usar o byte 0x08 diretamente.
Tabela
| Campo | Exemplo | Tamanho | Formato | Descrição | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Itens da Pilha | 02 | variável | Compact Size | O número de itens a empilhar como parte do código de destravamento. | |||||||||||||||
| Item |
Esta estrutura se repete para cada item de pilha. | ||||||||||||||||||
Esta estrutura se repete para cada entrada.
Se você está destravando entradas legadas e segwit na mesma transação, precisa definir o campo de testemunha das entradas legadas como 00 (nenhum item), pois cada entrada precisa ter o seu próprio campo de testemunha.
Exemplos
Como é um campo de testemunha?
Aqui estão alguns exemplos de campos de testemunha reais sendo usados para destravar entradas na blockchain.
P2WPKH
Hex
024730440220537f470c1a18dc1a9d233c0b6af1d2ce18a07f3b244e4d9d54e0e60c34c55e67022058169cd11ac42374cda217d6e28143abd0e79549f7b84acc6542817466dc9b3001210301c1768b48843933bd7f0e8782716e8439fc44723d3745feefde2d57b761f503 Decodificado
{
"witness": [
{
"stackitems": "02",
"0": { "size": "47", "item": "30440220537f470c...466dc9b3001" },
"1": { "size": "21", "item": "0301c1768b48843933bd7f0e8782716e8439fc44723d3745feefde2d57b761f503" }
}
]
} Transação: 65d8bd45f01bd6209d8695d126ba6bb4f2936501c12b9a1ddc9e38600d35aaa2 (Entrada 0)
Esta transação contém uma entrada que tem uma trava P2WPKH. Para destravá-la, você precisa fornecer uma assinatura seguida de uma chave pública no campo de testemunha.
Esse código de destravamento é funcionalmente igual ao script de destravamento encontrado dentro do ScriptSig de um P2PKH legado. Ou seja, ele apenas contém uma assinatura e uma chave pública.
Porém, enquanto o ScriptSig de um P2PKH usa OP_CODES para empurrar a assinatura e a chave pública para a pilha, a testemunha apenas usa campos compact size para indicar o tamanho da assinatura e da chave pública.
Exemplo de ScriptSig P2PKH
Os campos ScriptSig legados usam os opcodes OP_PUSHBYTES_XX para empurrar dados para a pilha. Mas, como você pode ver, o dado de fato em um campo de testemunha P2WPKH é o mesmo que em um ScriptSig P2PKH:
ASM
OP_PUSHBYTES_72
3045022100c233c3a8a510e03ad18b0a24694ef00c78101bfd5ac075b8c1037952ce26e91e02205aa5f8f88f29bb4ad5808ebc12abfd26bd791256f367b04c6d955f01f28a772401
OP_PUSHBYTES_33
03f0609c81a45f8cab67fc2d050c21b1acd3d37c7acfd54041be6601ab4cef4f31 Hex
483045022100c233c3a8a510e03ad18b0a24694ef00c78101bfd5ac075b8c1037952ce26e91e02205aa5f8f88f29bb4ad5808ebc12abfd26bd791256f367b04c6d955f01f28a7724012103f0609c81a45f8cab67fc2d050c21b1acd3d37c7acfd54041be6601ab4cef4f31 Transação: 40e331b67c0fe7750bb3b1943b378bf702dce86124dc12fa5980f975db7ec930 (Entrada 0)
P2WSH
Hex
04004730440220415899bbee08e42376d06e8f86c92b4987613c2816352fe09cd1479fd639f18c02200db57f508f69e266d76c23891708158bda18690c165a41b0aa88303b97609f780147304402203973de2303e8787767090dd25c8a4dc97ce1aa7eb4c0962f13952ed4e856ff8e02203f1bb425def789eea8be46407d10b3c8730407176aef4dc2c29865eb5e5542bf0169522103848e308569b644372a5eb26665f1a8c34ca393c130b376db2fae75c43500013c2103cec1ee615c17e06d4f4b0a08617dffb8e568936bdff18fb057832a58ad4d1b752103eed7ae80c34d70f5ba93f93965f69f3c691da0f4607f242f4fd6c7a48789233e53ae Decodificado
{
"witness": [
{
"stackitems": "04",
"0": { "size": "00", "item": "" },
"1": { "size": "47", "item": "30440220415899bb...97609f7801" },
"2": { "size": "47", "item": "304402203973de23...5e5542bf01" },
"3": { "size": "69", "item": "522103848e3085...89233e53ae" }
}
]
} Transação: b38a88b073743bcc84170071cff4b68dec6fb5dc0bc8ffcb3d4ca632c2c78255 (Entrada 0)
Esta transação contém uma entrada que tem uma trava P2WSH.
O último item neste campo de testemunha é o Witness Script (equivalente ao Redeem Script em um P2SH), que neste exemplo é um script de travamento P2MS. Você pode conferir isso decodificando os bytes hex do empilhamento de dados final para ver o Script de fato que ele contém:
Script
Todos os itens antes do Witness Script são os elementos de dados necessários para destravá-lo.
Exemplo de ScriptSig P2SH
Novamente, os campos ScriptSig usam os opcodes OP_PUSHBYTES_XX para empurrar dados para a pilha. Este ScriptSig P2SH contém o mesmo tipo de dado que um campo de testemunha P2WSH, embora o P2MS embrulhado dentro deste campo de testemunha exija apenas uma assinatura para ser destravado:
ASM
OP_0
OP_PUSHBYTES_71
3044022100d0ed946330182916da16a6149cd313a4b1a7b41591ee52fb3e79d64e36139d66021f6ccf173040ef24cb45c4db3e9c771c938a1ba2cf8d2404416f70886e360af401
OP_PUSHBYTES_71
5121022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e2103a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c052ae Hex
00473044022100d0ed946330182916da16a6149cd313a4b1a7b41591ee52fb3e79d64e36139d66021f6ccf173040ef24cb45c4db3e9c771c938a1ba2cf8d2404416f70886e360af401475121022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e2103a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c052ae Transação: 30c239f3ae062c5f1151476005fd0057adfa6922de1b38d0f11eb657a8157b30 (Entrada 11)
Embora os dados de testemunha em si não sejam Script, no caso de scripts de travamento P2WSH o item final do campo de testemunha de fato contém Script.
P2WPKH & P2PKH
Hex
024730440220599640d1dba05cba9bf5284cf080171c736a8fef51e8975501abd995744cbc8e02202fcda9a5423cfa3c75aadb0a4a20f57d1e2f041211658bc1793974b41202bc4e01210214a6f6ff714e38376ab3afb8f10965cf1ed7940284a3bff81dc8c0bd656de43300 Decodificado
{
"witness": [
{
"stackitems": "02",
"0": { "size": "47", "item": "30440220599640d1...3974b41202bc4e01" },
"1": { "size": "21", "item": "0214a6f6ff714e38376ab3afb8f10965cf1ed7940284a3bff81dc8c0bd656de433" }
},
{
"stackitems": "00"
}
]
} Transação: 0c722837427b05e718ab8e15fc0f5f0e7011e82f13dc1b48b65107876c265ef5
Esta transação está destravando duas entradas distintas: a primeira tem um script de travamento P2WPKH (programa de testemunha) mais novo, e a segunda tem um script de travamento P2PKH legado.
Como esta transação está destravando uma saída segwit, as duas entradas precisam ter o seu próprio campo de testemunha.
- O primeiro campo de testemunha contém o código de destravamento padrão de um script de travamento P2WPKH. Isso é uma assinatura e uma chave pública.
- O segundo campo de testemunha é
00, pois um script de travamento P2PKH não usa um campo de testemunha para ser destravado.- Nota: o código de destravamento desta entrada pode ser encontrado no ScriptSig.
E, como você pode ver, os campos de testemunha de cada entrada são simplesmente concatenados um após o outro dentro da área de testemunha de uma transação.
É perfeitamente normal combinar entradas legadas e segwit em uma transação. Você só precisa lembrar de definir o campo de testemunha de uma entrada como 00 se ela não exigir o uso de um campo de testemunha para ser destravada.
P2TR
Uma saída P2TR pode ser destravada de duas formas: pelo "caminho da chave" (key path) ou pelo "caminho de script" (script path). A estrutura da testemunha é diferente em cada caso.
1. Gasto pelo Caminho da Chave (Key Path)
Hex
0141b693a0797b24bae12ed0516a2f5ba765618dca89b75e498ba5b745b71644362298a45ca39230d10a02ee6290a91cebf9839600f7e35158a447ea182ea0e022ae01 Decodificado
{
"witness": [
{
"stackitems": "01",
"0": { "size": "41", "item": "b693a0797b24bae1...82ea0e022ae01" }
}
]
} Transação: 091d2aaadc409298fd8353a4cd94c319481a0b4623fb00872fe240448e93fcbe
Em um gasto pelo caminho da chave em P2TR, a testemunha contém um único item de assinatura.
Essa assinatura corresponde à chave pública ajustada (tweaked) colocada no ScriptPubKey do P2TR.
Este é o método "padrão" para destravar uma saída P2TR.
2. Gasto pelo Caminho de Script (Script Path)
Hex
034101769105cbcbdcaaee5e58cd201ba3152477fda31410df8b91b4aee2c4864c7700615efb425e002f146a39ca0a4f2924566762d9213bd33f825fad83977fba7f0122206d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0ac21c0924c163b385af7093440184af6fd6244936d1288cbb41cc3812286d3f83a3329 Decodificado
{
"witness": [
{
"stackitems": "03",
"0": { "size": "41", "item": "01769105cbcbdcaa...77fba7f01" },
"1": { "size": "22", "item": "206d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0ac" },
"2": { "size": "21", "item": "c0924c163b385af7093440184af6fd6244936d1288cbb41cc3812286d3f83a3329" }
}
]
} Transação: 797505b104b5fb840931c115ea35d445eb1f64c9279bf23aa5bb4c3d779da0c2
Em um gasto pelo caminho de script em P2TR, a testemunha contém 2 ou mais itens. Esses itens podem ser divididos em 3 seções:
- Entradas do Script (opcional) — Os itens no início do campo de testemunha são usados para destravar o item de leaf script seguinte. Normalmente é uma única assinatura, mas pode ser composto por vários itens de pilha (dependendo do que for necessário para destravar o leaf script).
- Leaf Script — É o penúltimo item do campo de testemunha e vem depois das entradas do script. É um script de travamento completo que foi usado como uma das travas personalizadas adicionais da saída.
- Control Block — É o último item do campo de testemunha. Ele contém informações que provam que o leaf script fazia parte da árvore de scripts usada para criar a chave pública ajustada colocada no ScriptPubKey original.
Este é o método "secundário" para destravar uma saída P2TR. O método de gasto pelo caminho de script é usado como alternativa ao método de gasto pelo caminho da chave acima.
Esta estrutura de testemunha para um gasto pelo caminho de script em P2TR é igual à estrutura de testemunha de um P2WSH, mas com um control block adicional no fim.
Limites
Qual é o tamanho máximo de um campo de testemunha?
Assim como o Script, os dados de testemunha de uma transação têm certos limites de tamanho para scripts de travamento padrão P2WPKH, P2WSH e P2TR:
- Cada campo de testemunha pode conter no máximo 100 itens de pilha.
- Cada item de pilha pode ter no máximo 80 bytes.
O Witness Script em um P2WSH (o item final da pilha) pode ter até 3.600 bytes. Esse é o empilhamento de dados do script de travamento de fato.
Uma transação pode exceder esses limites e ainda será considerada válida, mas também será considerada não padrão e, portanto, não será retransmitida pelos nós. Esses limites podem ser encontrados em policy.h.
Benefícios
Por que usar a testemunha em vez do ScriptSig?
Há dois benefícios em usar a testemunha em vez do campo ScriptSig para destravar entradas.
1. Os dados de testemunha pesam menos
Cada byte dentro da testemunha carrega menos peso do que cada byte dentro do ScriptSig:
| ScriptSig | 1 byte = 4 unidades de peso |
|---|---|
| Testemunha | 1 byte = 1 unidade de peso |
Ou, em termos de bytes virtuais, isso é:
| ScriptSig | 1 byte = 1 vbyte |
|---|---|
| Testemunha | 1 byte = 0,25 vbytes |
Por exemplo, o código de destravamento típico dentro de um ScriptSig para um P2PKH legado contém 106 bytes, o que é igual a 424 unidades de peso ou 106 vbytes:
47304402205aea7d8d4896c5057a96f1b9fc76dd2b00f30ab0df46149047b5f4294f88796202205ce938d9f14f5238192b369d79861ade5a25884ece7afe9b9dde8a6a683c4af7012102af26f51735ff252de2972f06f2bb47456108c2e8a6554187cf3bb4a0c657590f Transação: 842c4626a8ef8eebe46ed8d591b643c5d7be84ea1aa199fb76e5d78fe8d6819f (Entrada 0)
Porém, o código de destravamento típico dentro de um campo de testemunha para um P2WPKH segwit contém 107 bytes, o que é igual a 107 unidades de peso ou 26,75 vbytes:
0247304402202a11945f55d174686cd48e9b3e0db3bfbe5fb9557a76fa546c6772c434f03f14022010be503e37c1cb6e0519ce9f8532c89fa2cbec6667d93a4f3bdef43fb047dba30121032704e02eb63d8ea323b0386bf3b47c0d9058f36c9c486ac102a34b929d862abb Transação: 7a466b5ed43e5022121918d9e9fdef923a7a5e2d01c9abd6a4998e30e77d2ad3 (Entrada 0)
Como resultado, o código de destravamento de scripts de travamento segwit ocupa menos espaço dentro de um bloco. Isso significa que você não precisa pagar tanto em taxas de transação, em termos de sats por vbyte, para conseguir minerar a transação.
Usar a testemunha dá a você um desconto na quantia que precisa pagar em taxas de transação em comparação com usar o ScriptSig.
2. A testemunha previne a maleabilidade de transações
O campo ScriptSig geralmente contém uma assinatura, e esse campo entra no cálculo do TXID. Porém, a testemunha não faz parte do TXID, então as assinaturas que ficam nela não entram mais no cálculo do TXID.
Isso é importante porque assinaturas podem ser modificadas mantendo a transação válida, o que significava que o TXID de uma transação podia mudar antes de ela ser minerada. Ao usar a testemunha para destravar entradas, você tem a confiança de que o TXID permanecerá o mesmo depois que a transação for enviada à rede. Essa mudança foi a força motriz por trás da atualização Segregated Witness.
Valor Reservado de Testemunha
O espaço para comprometer novos dados ao bloco
A testemunha da entrada de uma transação coinbase contém um valor reservado de testemunha (witness reserved value): um espaço de 32 bytes reservado para um commitment de novos dados em uma futura atualização do bitcoin.
Como a entrada de uma coinbase não referencia nenhuma saída anterior, não há nada a destravar — então os campos de destravamento dessa entrada (ScriptSig e testemunha) ficam "sobrando". Por isso, a testemunha dessa entrada foi reservada como espaço para armazenar dados extras em uma potencial atualização futura: se uma nova atualização adicionasse dados às transações, todos esses dados poderiam ser hasheados e armazenados no valor reservado de testemunha, e qualquer um poderia ver que os dados foram de fato incluídos como parte do bloco.
No momento, o valor reservado de testemunha não é usado, então normalmente fica como um valor vazio de 32 bytes: 0000000000000000000000000000000000000000000000000000000000000000.
Terminologia
Por que se chama testemunha?
O termo "witness" (testemunha) foi cunhado por Pieter Wuille, o desenvolvedor por trás da atualização Segregated Witness:
A única coisa com que nos importamos é que o remetente autorizou [a transação]. Pode haver várias assinaturas possíveis para uma transação, mas só nos importamos que uma delas exista. Isso é algo chamado de Testemunha (Witness) na matemática; você prova que algo existe dando um exemplo.
Então é só um nome técnico chique para a área de "código de destravamento" das saídas segwit.