P2SH
Pay To Script Hash — travando bitcoins ao hash de um script
O P2SH (Pay To Script Hash) é um script de travamento que permite travar bitcoins ao hash de um script.
Isso permite usar scripts de travamento personalizados para os seus bitcoins, ao mesmo tempo em que permite fornecer ao remetente um endereço para onde enviar os bitcoins (em vez de ele ter que usar o script de travamento personalizado completo).
O script de travamento personalizado completo é chamado de Redeem Script, e é revelado quando você vai gastar os bitcoins mais tarde.
Então, em resumo, o P2SH é uma solução prática para colocar scripts de travamento personalizados em bitcoins. É mais comumente usado para travar bitcoins em scripts de travamento complexos, como o P2MS.
Script legado. Este é um padrão de script legado. Ainda é usado ocasionalmente, mas o P2WSH é agora a escolha preferida (que funciona da mesma forma).
Uso
Como o P2SH funciona?
ScriptPubKey (trava)
O script de travamento P2SH contém o hash de outro script de travamento (o Script Hash), cercado pelos opcodes OP_HASH160 e OP_EQUAL.
Aqui está um exemplo de ScriptPubKey de um P2SH:
ASM
OP_HASH160
OP_PUSHBYTES_20
748284390f9e263a4b766a75d0633c50426eb875
OP_EQUAL Hex
a914748284390f9e263a4b766a75d0633c50426eb87587 Transação: 450c309b70fb3f71b63b10ce60af17499bd21b1db39aa47b19bf22166ee67144 (Saída 1)
Este Script Hash em particular é o HASH160 de um script de travamento P2MS, mas só descobrimos isso quando o Redeem Script é revelado no ScriptSig…
ScriptSig (destrava)
O script de destravamento de um P2SH consiste em duas partes:
- O código de destravamento necessário para destravar o Redeem Script que vem a seguir.
- Um empilhamento de dados (data push) do próprio Redeem Script.
ASM
OP_0
OP_PUSHBYTES_71
3044022100d0ed946330182916da16a6149cd313a4b1a7b41591ee52fb3e79d64e36139d66021f6ccf173040ef24cb45c4db3e9c771c938a1ba2cf8d2404416f70886e360af401
OP_PUSHBYTES_71
5121022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e2103a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c052ae Hex
00473044022100d0ed946330182916da16a6149cd313a4b1a7b41591ee52fb3e79d64e36139d66021f6ccf173040ef24cb45c4db3e9c771c938a1ba2cf8d2404416f70886e360af401475121022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e2103a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c052ae Transação: 30c239f3ae062c5f1151476005fd0057adfa6922de1b38d0f11eb657a8157b30 (Entrada 11)
Então, em outras palavras, o ScriptSig contém o script de destravamento e o script de travamento completos.
No exemplo acima, o Redeem Script é o empilhamento de dados de um script de travamento P2MS. A assinatura que vem antes dele é o que é necessário para destravá-lo.
Você pode inspecionar o Redeem Script para descobrir que ele é, de fato, um P2MS, decodificando-o do hex:
Execução
O P2SH é uma forma especial de script de travamento e é executado de maneira ligeiramente diferente dos scripts "normais".
Um script P2SH é executado em dois passos:
- Passo 1: Execução do Script Padrão — O Redeem Script é hasheado e verificado para ver se é igual ao Script Hash.
- Passo 2: Execução do Redeem Script (parte especial) — O Redeem Script é desserializado e executado como se fosse o script de travamento.
A pilha contendo o ScriptSig é copiada, para que o P2SH possa ser executado em dois passos.
Passo 1: Execução do Script Padrão
O Redeem Script do ScriptSig é hasheado para garantir que corresponda ao Script Hash no ScriptPubKey:
Isto é uma execução de script perfeitamente normal, e é aqui que a execução do script normalmente terminaria.
Porém, como o P2SH é uma forma especial de script de travamento, há um passo adicional…
Passo 2: Execução do Redeem Script (parte especial)
O Redeem Script (que é um empilhamento de dados) é desserializado em suas partes componentes (de opcodes e dados):
Então você poderia pensar no Redeem Script como se tornando o novo script de travamento.
De todo modo, depois que o Redeem Script é desserializado, o script inteiro é executado como qualquer script padrão.
Como o Redeem Script no exemplo acima contém um P2MS, ele é executado como um script P2MS padrão. Mas, claro, essa parte poderia ser executada de forma diferente dependendo do tipo de Redeem Script que você usar.
Redeem Script
O script personalizado
O Redeem Script é um empilhamento de dados da codificação em hex de um script de travamento personalizado. Este é o último item dentro do ScriptSig de um P2SH.
Aqui está um exemplo de ScriptSig:
ASM
OP_0
OP_PUSHBYTES_71
3044022100d0ed946330182916da16a6149cd313a4b1a7b41591ee52fb3e79d64e36139d66021f6ccf173040ef24cb45c4db3e9c771c938a1ba2cf8d2404416f70886e360af401
OP_PUSHBYTES_71
5121022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e2103a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c052ae Hex
00473044022100d0ed946330182916da16a6149cd313a4b1a7b41591ee52fb3e79d64e36139d66021f6ccf173040ef24cb45c4db3e9c771c938a1ba2cf8d2404416f70886e360af401475121022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e2103a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c052ae Transação: 30c239f3ae062c5f1151476005fd0057adfa6922de1b38d0f11eb657a8157b30 (Entrada 11)
Se você decodificar o último item, verá que ele corresponde ao seguinte script (que é um P2MS típico):
ASM
OP_1
OP_PUSHBYTES_33
022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e
OP_PUSHBYTES_33
03a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c0
OP_2
OP_CHECKMULTISIG Hex
5121022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e2103a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c052ae Você pode usar praticamente qualquer script de travamento personalizado que quiser como Redeem Script. E, a partir do Bitcoin 0.10.0, você não está mais limitado a usar apenas scripts padrão:
As regras do IsStandard() foram quase completamente removidas para os redeem scripts de P2SH, permitindo que aplicações façam uso de qualquer tipo de script válido, como "m-de-n OU y", endereços-oráculo com trava de hash etc. Embora o protocolo Bitcoin sempre tenha suportado esses tipos de script, usá-los de fato na mainnet era anteriormente inconveniente, pois os nós padrão do Bitcoin Core não os retransmitiam aos mineradores, nem a maioria dos mineradores os incluía nos blocos que minerava.
Então, se você quer se divertir com os vários OP_CODES, o Redeem Script de um P2SH é onde você pode fazer isso.
Embora um Redeem Script contenha opcodes e dados, ele é, na verdade, a codificação em hex de um script, e é empurrado para a pilha (assim como uma chave pública é em um P2PKH).
O tamanho máximo de um Redeem Script é 520 bytes. Qualquer coisa maior é considerada não padrão e não será retransmitida pelos nós. Em termos práticos, isso significa que você pode usá-lo para um script de travamento no estilo P2MS com até 15 chaves públicas.
Garanta que o seu script não padrão acabe deixando um único OP_1 na pilha ao fim da execução.
Uma vez criei um script que deixava OP_1 OP_1 OP_1 na pilha e, mesmo que o elemento do topo fosse OP_1, recebi um erro de "Extra items left on stack after execution" e a transação não era retransmitida.
Script Hash
O hash do script personalizado
O Script Hash é o HASH160 do Redeem Script. Ele é colocado dentro do ScriptPubKey de um P2SH.
Por exemplo, você pode ver que o Redeem Script é o último empilhamento de dados neste ScriptSig:
ASM
OP_0
OP_PUSHBYTES_71
3044022100d0ed946330182916da16a6149cd313a4b1a7b41591ee52fb3e79d64e36139d66021f6ccf173040ef24cb45c4db3e9c771c938a1ba2cf8d2404416f70886e360af401
OP_PUSHBYTES_71
5121022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e2103a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c052ae Hex
00473044022100d0ed946330182916da16a6149cd313a4b1a7b41591ee52fb3e79d64e36139d66021f6ccf173040ef24cb45c4db3e9c771c938a1ba2cf8d2404416f70886e360af401475121022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e2103a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c052ae Transação: 30c239f3ae062c5f1151476005fd0057adfa6922de1b38d0f11eb657a8157b30 (Entrada 11)
Se você fizer o HASH160 deste Redeem Script, verá que ele é igual ao Script Hash encontrado no ScriptPubKey original:
ASM
OP_HASH160
OP_PUSHBYTES_20
748284390f9e263a4b766a75d0633c50426eb875
OP_EQUAL Hex
a914748284390f9e263a4b766a75d0633c50426eb87587 Transação: 450c309b70fb3f71b63b10ce60af17499bd21b1db39aa47b19bf22166ee67144 (Saída 1)
HASH160
Exemplos
Onde você encontra scripts P2SH?
Aqui estão alguns exemplos de P2SH sendo usado em transações.
Incluí o Redeem Script decodificado de cada ScriptSig, pois essa é a parte mais interessante, porque é onde o script de travamento "personalizado" fica localizado.
Lembre-se de que o Redeem Script é o último empilhamento de dados dentro do ScriptSig e aparece como um monte de bytes em hex, então, para inspecioná-los, você precisará decodificá-los:
Exemplo 1
Esta foi a primeira transação a usar P2SH (e a também ser gasta mais tarde).
- ScriptPubKey: a0f1aaa2fb4582c89e0511df0374a5a2833bf95f7314f4a51b55b7b71e90ce0f (saída 1)
- ScriptSig: 4d8eabfc8e6c266fb0ccd815d37dd69246da634df0effd5a5c922e4ec37880f6 (entrada 2)
O Redeem Script é um script de travamento multisig 1-de-2:
ASM
OP_1
OP_PUSHBYTES_33
022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e
OP_PUSHBYTES_33
03a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c0
OP_2
OP_CHECKMULTISIG Hex
5121022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e2103a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c052ae Exemplo 2
- ScriptPubKey: 40eee3ae1760e3a8532263678cdf64569e6ad06abc133af64f735e52562bccc8 (saída 0)
- ScriptSig: 7edb32d4ffd7a385b763c7a8e56b6358bcd729e747290624e18acdbe6209fc45 (entrada 0)
O Redeem Script é um script de travamento multisig 1-de-1:
ASM
OP_1
OP_PUSHBYTES_65
042f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424ab0d79122a653ad0c7ec9896bdf
OP_1
OP_CHECKMULTISIG Hex
5141042f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424ab0d79122a653ad0c7ec9896bdf51ae Exemplo 3
- ScriptPubKey: 450c309b70fb3f71b63b10ce60af17499bd21b1db39aa47b19bf22166ee67144 (saída 1)
- ScriptSig: 30c239f3ae062c5f1151476005fd0057adfa6922de1b38d0f11eb657a8157b30 (entrada 11)
O Redeem Script é um script de travamento multisig 1-de-2. Ele usa a mesma trava do primeiro exemplo de P2SH acima:
ASM
OP_1
OP_PUSHBYTES_33
022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e
OP_PUSHBYTES_33
03a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c0
OP_2
OP_CHECKMULTISIG Hex
5121022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e2103a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c052ae Exemplo 4
- ScriptPubKey: d3adb18d5e118bb856fbea4b1af936602454b44a98fc6c823aedc858b491fc13 (saída 0)
- ScriptSig: cc11ca9e9dc188663c41eb23b15370f68eded56b7ec54dd5bc4f2d2ae93addb2 (entrada 0)
O Redeem Script é um script de travamento multisig 2-de-3:
ASM
OP_2
OP_PUSHBYTES_65
04f3d35132084eb1b99b6506178c20adb42d26296012e452e392689bdb6553db33ba24b900000892805de1646821c7b0fb50b3d879c26e2b493b7041e6215356a0
OP_PUSHBYTES_65
04ab4ecc9e8ea2da0562af25bcaede00c4d5a00db60edc17672376decf0a35a34fdc9f1ffad1fb74fd7b1b198b9231c25df88e0769bec49975649b4b3f40adafb0
OP_PUSHBYTES_65
04f7149f270717c00f6cc09b9ce3c22791c4aab1af40a5107aacca85b6f644cc0d84459e308f998d801b8d9d355f8ec33b0e41866841e2870754cf667a9821703d
OP_3
OP_CHECKMULTISIG Hex
524104f3d35132084eb1b99b6506178c20adb42d26296012e452e392689bdb6553db33ba24b900000892805de1646821c7b0fb50b3d879c26e2b493b7041e6215356a04104ab4ecc9e8ea2da0562af25bcaede00c4d5a00db60edc17672376decf0a35a34fdc9f1ffad1fb74fd7b1b198b9231c25df88e0769bec49975649b4b3f40adafb04104f7149f270717c00f6cc09b9ce3c22791c4aab1af40a5107aacca85b6f644cc0d84459e308f998d801b8d9d355f8ec33b0e41866841e2870754cf667a9821703d53ae Exemplo 5
- ScriptPubKey: 7d46745463a28049cb93d2c964320912d9c296c1038cb24cc3716255c397a87f (saída 1)
- ScriptSig: 09afa3b1393f99bb01aa754dd4b89293fd8d6c9741488b537d14f7f81de1450e (entrada 0)
O Redeem Script é um script de travamento não padrão contendo um quebra-cabeça matemático:
ASM
OP_3DUP
OP_ADD
OP_9
OP_EQUALVERIFY
OP_ADD
OP_7
OP_EQUALVERIFY
OP_ADD
OP_8
OP_EQUALVERIFY
OP_1 Hex
6f93598893578893588851 Exemplo 6
- ScriptPubKey: 2c6c3a1319c3e42b4801dab62e3d3d59c51c3535b8dad20e9580650f114c7026 (saída 0)
- ScriptSig: 8d31992805518fd62daa3bdd2a5c4fd2cd3054c9b3dca1d78055e9528cff6adc (entrada 4)
O Redeem Script é um script de travamento não padrão contendo o desafio de colisão de hash do Peter Todd, em que você tinha que encontrar dois pedaços de dados diferentes que produzem o mesmo resultado de SHA-1:
ASM
OP_2DUP
OP_EQUAL
OP_NOT
OP_VERIFY
OP_SHA1
OP_SWAP
OP_SHA1
OP_EQUAL Hex
6e879169a77ca787 Como você pode ver, o P2SH é mais comumente usado para travas multisig (P2MS), mas é ocasionalmente usado para scripts de travamento personalizados mais exóticos, por diversão.
Endereço
Como você cria um endereço para um script P2SH?
O padrão de script de travamento P2SH recebeu o seu próprio endereço.
O endereço de um script de travamento P2SH é a codificação Base58Check do Script Hash com um prefixo de 1 byte de 05 (mainnet) ou c4 (testnet).
Um endereço P2SH sempre começa com um 3 (mainnet) ou 2 (testnet).
Quando uma carteira encontra esse tipo de endereço, ela o decodifica de base58 para extrair o Script Hash e, então, usa isso para construir um script de travamento P2SH a ser colocado na saída da transação.
Benefícios
Por que usamos P2SH?
O principal benefício do P2SH é que ele torna mais fácil compartilhar scripts de travamento complexos com outras pessoas.
Antes do P2SH, se você quisesse um script de travamento complexo colocado nos seus bitcoins (ex.: P2MS), você teria que dar à pessoa que está "enviando" esses bitcoins a você o script de travamento inteiro:
Mas, com o P2SH, em vez de dar a alguém um script de travamento inteiro, você pode essencialmente dar a ele apenas um hash do seu script:
Além disso, esse hash de script pode ser convertido em um formato de endereço para tornar ainda mais fácil de compartilhar:
Como resultado, o remetente não fica mais sobrecarregado com o tamanho (ou os detalhes técnicos) do nosso script de travamento, e ele pode simplesmente "enviar" os bitcoins para um endereço padronizado.
Outros benefícios
Há também alguns outros benefícios em usar P2SH:
1. Custos de transação mais baratos para o remetente
Se você quer um script de travamento personalizado nos seus bitcoins, a pessoa que está te enviando os bitcoins tem que colocar esse script na transação que ela cria:
O problema aqui é que esse script de travamento maior aumenta o tamanho dos dados da transação, então o remetente terá que pagar mais em taxas de transação para acomodar o seu script.
Porém, com o P2SH, eles podem criar uma trava usando o hash do seu script, que é muito menor que o script completo:
Como resultado, o fardo dos scripts de travamento grandes não fica mais com o remetente e é transferido para o destinatário. Isso ajuda a evitar uma situação em que o remetente ficaria despreocupado em "enviar" bitcoins para um script de travamento que não é um dos mais simples e baratos (ex.: P2PKH).
2. O P2SH tem um pouco mais de privacidade
Como um script de travamento P2SH apenas contém o hash de outro script de travamento, é impossível saber que tipo de script de travamento aquele hash veio apenas olhando para ele:
Como resultado, ninguém saberia se uma saída "pertence" à chave pública de uma pessoa ou se pertence a múltiplas pessoas.
Até que alguém a gaste e revele o Redeem Script, claro.
3. Um conjunto de UTXOs menor
Para fazer o próprio programa do bitcoin rodar o mais rápido possível, todas as saídas não gastas das transações (UTXOs) são armazenadas na memória RAM do seu computador.
A RAM é menor que o seu disco rígido, mas te dá um acesso muito mais rápido aos dados.
Essas UTXOs também armazenam os scripts de travamento de cada saída, então, ao usar scripts P2SH menores em vez de scripts P2MS maiores, você economiza na quantidade de RAM necessária para guardar o conjunto de UTXOs.
Isso é útil, porque manter o máximo possível do conjunto de UTXOs na RAM torna os nós muito mais rápidos para validar transações.
FAQ
O P2SH não ocupa mais espaço na blockchain no geral?
Sim, ocupa.
Por exemplo, um script multisig 2-de-3 completo usando o padrão P2MS simples ocupa 253 bytes na blockchain:
Por outro lado, um script multisig 2-de-3 completo usando P2SH ocupa 278 bytes na blockchain:
Então o passo extra de travar bitcoins ao hash de um script adiciona 25 bytes a mais ao script no geral.
Porém, não há realmente nenhuma alternativa para conseguir criar endereços para scripts de travamento personalizados, então os 25 bytes extras por essa conveniência são um preço razoável a pagar.