P2SH

Pay To Script Hash — travando bitcoins ao hash de um script

BIP 16: Pay to Script Hash

Diagrama mostrando a estrutura de um P2SH.

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:

  1. O código de destravamento necessário para destravar o Redeem Script que vem a seguir.
  2. 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:

Interpretador de Script

Execute um script passo a passo e veja a pilha mudar a cada opcode. O ScriptSig roda primeiro, depois o ScriptPubKey.

    Execução

    Diagrama mostrando a montagem de um P2SH antes da execução do script.

    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:

    1. Passo 1: Execução do Script Padrão — O Redeem Script é hasheado e verificado para ver se é igual ao Script Hash.
    2. Passo 2: Execução do Redeem Script (parte especial) — O Redeem Script é desserializado e executado como se fosse o script de travamento.
    Animação mostrando a execução de um script P2SH completo.

    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:

    Diagrama mostrando o primeiro passo da execução de um P2SH.

    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):

    Animação mostrando o Redeem Script sendo desserializado para o segundo passo da execução do script.

    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

    Diagrama mostrando a localização do Redeem Script em um script de travamento P2SH.

    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

    Interpretador de Script

    Execute um script passo a passo e veja a pilha mudar a cada opcode. O ScriptSig roda primeiro, depois o ScriptPubKey.

      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.
      Notas de Lançamento do Bitcoin 0.10.0

      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

      Diagrama mostrando a localização do Script Hash em um script de travamento P2SH.

      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)

      Interpretador de Script

      Execute um script passo a passo e veja a pilha mudar a cada opcode. O ScriptSig roda primeiro, depois o ScriptPubKey.

        Ícone Ferramenta HASH160

        HASH160

        SHA-256 + RIPEMD-160. Usado para encurtar uma chave pública ou script antes de converter em um endereço.

        Uma chave pública ou script, por exemplo

        0 bytes
        SHA-256
        RIPEMD-160

        RIPEMD-160(SHA-256(dados))

        0 bytes

        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:

        Interpretador de Script

        Execute um script passo a passo e veja a pilha mudar a cada opcode. O ScriptSig roda primeiro, depois o ScriptPubKey.

          Exemplo 1

          Esta foi a primeira transação a usar P2SH (e a também ser gasta mais tarde).

          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

          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

          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

          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

          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

          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?

          Diagrama mostrando como codificar um script P2SH em um endereço.

          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).

          Endereço (Base58)

          Codifique el hash160 de una clave pública o script en una dirección heredada.

          1 byte
          0 bytes
          0 bytes
          Tipo de dirección

          Codificación Base58 de los datos anteriores

          0 caracteres

          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.

          Diagrama mostrando como decodificar um endereço em um script P2SH.

          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:

          Diagrama mostrando um script de travamento completo sendo compartilhado com alguém.

          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:

          Diagrama mostrando o hash de um script sendo compartilhado com alguém em vez do script de travamento completo.

          Além disso, esse hash de script pode ser convertido em um formato de endereço para tornar ainda mais fácil de compartilhar:

          Diagrama mostrando um endereço (formado a partir do hash de um script) sendo compartilhado com alguém.

          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:

          Diagrama mostrando um P2MS sendo usado como script de travamento em uma saída e o seu tamanho nos dados brutos da transação.

          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:

          Diagrama mostrando um P2SH sendo usado como script de travamento em uma saída e o seu tamanho nos dados brutos da transação.

          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:

          Diagrama mostrando o hash de um script colocado dentro da trava de uma transação, sem ser possível determinar o script original.

          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.

          Diagrama mostrando as UTXOs sendo armazenadas na RAM.

          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:

          Diagrama mostrando o tamanho de um script P2MS completo.

          Por outro lado, um script multisig 2-de-3 completo usando P2SH ocupa 278 bytes na blockchain:

          Diagrama mostrando o tamanho de um script P2SH completo.

          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.

          Recursos