Script
A mini linguagem de programação que trava e destrava bitcoins
Script é uma mini linguagem de programação usada como mecanismo de travamento das saídas nas transações de bitcoin.
- Um script de travamento (ScriptPubKey) é colocado em toda saída de transação.
- Um script de destravamento (ScriptSig ou Testemunha) precisa ser fornecido para destravar uma saída (ou seja, quando ela é usada como entrada em uma transação).
Se um script completo (destravamento + travamento) é válido, a saída é "destravada" e pode ser gasta.
A Linguagem Script
O que é Script?
Script é uma linguagem de programação bem básica. Ela consiste em duas coisas:
- Opcodes – Funções simples que operam sobre dados.
- Dados – Como chaves públicas e assinaturas.
Aqui está um diagrama simples de um script P2PKH típico usado no Bitcoin:
1. Opcodes
Aqui está uma lista rápida de todos os opcodes disponíveis na linguagem Script (junto com o byte hexadecimal correspondente usado para representar cada um).
| Hex | Opcode |
|---|---|
| 00 | OP_0 |
| 01 | OP_PUSHBYTES_1 |
| 02 | OP_PUSHBYTES_2 |
| 03 | OP_PUSHBYTES_3 |
| 04 | OP_PUSHBYTES_4 |
| 05 | OP_PUSHBYTES_5 |
| 06 | OP_PUSHBYTES_6 |
| 07 | OP_PUSHBYTES_7 |
| 08 | OP_PUSHBYTES_8 |
| 09 | OP_PUSHBYTES_9 |
| 0a | OP_PUSHBYTES_10 |
| 0b | OP_PUSHBYTES_11 |
| 0c | OP_PUSHBYTES_12 |
| 0d | OP_PUSHBYTES_13 |
| 0e | OP_PUSHBYTES_14 |
| 0f | OP_PUSHBYTES_15 |
| 10 | OP_PUSHBYTES_16 |
| 11 | OP_PUSHBYTES_17 |
| 12 | OP_PUSHBYTES_18 |
| 13 | OP_PUSHBYTES_19 |
| 14 | OP_PUSHBYTES_20 |
| 15 | OP_PUSHBYTES_21 |
| 16 | OP_PUSHBYTES_22 |
| 17 | OP_PUSHBYTES_23 |
| 18 | OP_PUSHBYTES_24 |
| 19 | OP_PUSHBYTES_25 |
| 1a | OP_PUSHBYTES_26 |
| 1b | OP_PUSHBYTES_27 |
| 1c | OP_PUSHBYTES_28 |
| 1d | OP_PUSHBYTES_29 |
| 1e | OP_PUSHBYTES_30 |
| 1f | OP_PUSHBYTES_31 |
| 20 | OP_PUSHBYTES_32 |
| 21 | OP_PUSHBYTES_33 |
| 22 | OP_PUSHBYTES_34 |
| 23 | OP_PUSHBYTES_35 |
| 24 | OP_PUSHBYTES_36 |
| 25 | OP_PUSHBYTES_37 |
| 26 | OP_PUSHBYTES_38 |
| 27 | OP_PUSHBYTES_39 |
| 28 | OP_PUSHBYTES_40 |
| 29 | OP_PUSHBYTES_41 |
| 2a | OP_PUSHBYTES_42 |
| 2b | OP_PUSHBYTES_43 |
| 2c | OP_PUSHBYTES_44 |
| 2d | OP_PUSHBYTES_45 |
| 2e | OP_PUSHBYTES_46 |
| 2f | OP_PUSHBYTES_47 |
| 30 | OP_PUSHBYTES_48 |
| 31 | OP_PUSHBYTES_49 |
| 32 | OP_PUSHBYTES_50 |
| 33 | OP_PUSHBYTES_51 |
| 34 | OP_PUSHBYTES_52 |
| 35 | OP_PUSHBYTES_53 |
| 36 | OP_PUSHBYTES_54 |
| 37 | OP_PUSHBYTES_55 |
| 38 | OP_PUSHBYTES_56 |
| 39 | OP_PUSHBYTES_57 |
| 3a | OP_PUSHBYTES_58 |
| 3b | OP_PUSHBYTES_59 |
| 3c | OP_PUSHBYTES_60 |
| 3d | OP_PUSHBYTES_61 |
| 3e | OP_PUSHBYTES_62 |
| 3f | OP_PUSHBYTES_63 |
| 40 | OP_PUSHBYTES_64 |
| 41 | OP_PUSHBYTES_65 |
| 42 | OP_PUSHBYTES_66 |
| 43 | OP_PUSHBYTES_67 |
| 44 | OP_PUSHBYTES_68 |
| 45 | OP_PUSHBYTES_69 |
| 46 | OP_PUSHBYTES_70 |
| 47 | OP_PUSHBYTES_71 |
| 48 | OP_PUSHBYTES_72 |
| 49 | OP_PUSHBYTES_73 |
| 4a | OP_PUSHBYTES_74 |
| 4b | OP_PUSHBYTES_75 |
| 4c | OP_PUSHDATA1 |
| 4d | OP_PUSHDATA2 |
| 4e | OP_PUSHDATA4 |
| 4f | OP_1NEGATE |
| 50 | OP_RESERVED |
| 51 | OP_1 |
| 52 | OP_2 |
| 53 | OP_3 |
| 54 | OP_4 |
| 55 | OP_5 |
| 56 | OP_6 |
| 57 | OP_7 |
| 58 | OP_8 |
| 59 | OP_9 |
| 5a | OP_10 |
| 5b | OP_11 |
| 5c | OP_12 |
| 5d | OP_13 |
| 5e | OP_14 |
| 5f | OP_15 |
| 60 | OP_16 |
| Hex | Opcode |
|---|---|
| 61 | OP_NOP |
| 62 | OP_VER |
| 63 | OP_IF |
| 64 | OP_NOTIF |
| 65 | OP_VERIF |
| 66 | OP_VERNOTIF |
| 67 | OP_ELSE |
| 68 | OP_ENDIF |
| 69 | OP_VERIFY |
| 6a | OP_RETURN |
| Hex | Opcode |
|---|---|
| 6b | OP_TOALTSTACK |
| 6c | OP_FROMALTSTACK |
| 6d | OP_2DROP |
| 6e | OP_2DUP |
| 6f | OP_3DUP |
| 70 | OP_2OVER |
| 71 | OP_2ROT |
| 72 | OP_2SWAP |
| 73 | OP_IFDUP |
| 74 | OP_DEPTH |
| 75 | OP_DROP |
| 76 | OP_DUP |
| 77 | OP_NIP |
| 78 | OP_OVER |
| 79 | OP_PICK |
| 7a | OP_ROLL |
| 7b | OP_ROT |
| 7c | OP_SWAP |
| 7d | OP_TUCK |
| Hex | Opcode |
|---|---|
| 7e | OP_CAT |
| 7f | OP_SUBSTR |
| 80 | OP_LEFT |
| 81 | OP_RIGHT |
| 82 | OP_SIZE |
| Hex | Opcode |
|---|---|
| 83 | OP_INVERT |
| 84 | OP_AND |
| 85 | OP_OR |
| 86 | OP_XOR |
| 87 | OP_EQUAL |
| 88 | OP_EQUALVERIFY |
| 89 | OP_RESERVED1 |
| 8a | OP_RESERVED2 |
| Hex | Opcode |
|---|---|
| 8b | OP_1ADD |
| 8c | OP_1SUB |
| 8d | OP_2MUL |
| 8e | OP_2DIV |
| 8f | OP_NEGATE |
| 90 | OP_ABS |
| 91 | OP_NOT |
| 92 | OP_0NOTEQUAL |
| 93 | OP_ADD |
| 94 | OP_SUB |
| 95 | OP_MUL |
| 96 | OP_DIV |
| 97 | OP_MOD |
| 98 | OP_LSHIFT |
| 99 | OP_RSHIFT |
| 9a | OP_BOOLAND |
| 9b | OP_BOOLOR |
| 9c | OP_NUMEQUAL |
| 9d | OP_NUMEQUALVERIFY |
| 9e | OP_NUMNOTEQUAL |
| 9f | OP_LESSTHAN |
| a0 | OP_GREATERTHAN |
| a1 | OP_LESSTHANOREQUAL |
| a2 | OP_GREATERTHANOREQUAL |
| a3 | OP_MIN |
| a4 | OP_MAX |
| a5 | OP_WITHIN |
| Hex | Opcode |
|---|---|
| a6 | OP_RIPEMD160 |
| a7 | OP_SHA1 |
| a8 | OP_SHA256 |
| a9 | OP_HASH160 |
| aa | OP_HASH256 |
| ab | OP_CODESEPARATOR |
| ac | OP_CHECKSIG |
| ad | OP_CHECKSIGVERIFY |
| ae | OP_CHECKMULTISIG |
| af | OP_CHECKMULTISIGVERIFY |
| Hex | Opcode |
|---|---|
| b0 | OP_NOP1 |
| b1 | OP_CHECKLOCKTIMEVERIFY |
| b2 | OP_CHECKSEQUENCEVERIFY |
| b3 | OP_NOP4 |
| b4 | OP_NOP5 |
| b5 | OP_NOP6 |
| b6 | OP_NOP7 |
| b7 | OP_NOP8 |
| b8 | OP_NOP9 |
| b9 | OP_NOP10 |
| ba | OP_CHECKSIGADD |
| bb | OP_RETURN_187 |
| bc | OP_RETURN_188 |
| bd | OP_RETURN_189 |
| be | OP_RETURN_190 |
| bf | OP_RETURN_191 |
| c0 | OP_RETURN_192 |
| c1 | OP_RETURN_193 |
| c2 | OP_RETURN_194 |
| c3 | OP_RETURN_195 |
| c4 | OP_RETURN_196 |
| c5 | OP_RETURN_197 |
| c6 | OP_RETURN_198 |
| c7 | OP_RETURN_199 |
| c8 | OP_RETURN_200 |
| c9 | OP_RETURN_201 |
| ca | OP_RETURN_202 |
| cb | OP_RETURN_203 |
| cc | OP_RETURN_204 |
| cd | OP_RETURN_205 |
| ce | OP_RETURN_206 |
| cf | OP_RETURN_207 |
| d0 | OP_RETURN_208 |
| d1 | OP_RETURN_209 |
| d2 | OP_RETURN_210 |
| d3 | OP_RETURN_211 |
| d4 | OP_RETURN_212 |
| d5 | OP_RETURN_213 |
| d6 | OP_RETURN_214 |
| d7 | OP_RETURN_215 |
| d8 | OP_RETURN_216 |
| d9 | OP_RETURN_217 |
| da | OP_RETURN_218 |
| db | OP_RETURN_219 |
| dc | OP_RETURN_220 |
| dd | OP_RETURN_221 |
| de | OP_RETURN_222 |
| df | OP_RETURN_223 |
| e0 | OP_RETURN_224 |
| e1 | OP_RETURN_225 |
| e2 | OP_RETURN_226 |
| e3 | OP_RETURN_227 |
| e4 | OP_RETURN_228 |
| e5 | OP_RETURN_229 |
| e6 | OP_RETURN_230 |
| e7 | OP_RETURN_231 |
| e8 | OP_RETURN_232 |
| e9 | OP_RETURN_233 |
| ea | OP_RETURN_234 |
| eb | OP_RETURN_235 |
| ec | OP_RETURN_236 |
| ed | OP_RETURN_237 |
| ee | OP_RETURN_238 |
| ef | OP_RETURN_239 |
| f0 | OP_RETURN_240 |
| f1 | OP_RETURN_241 |
| f2 | OP_RETURN_242 |
| f3 | OP_RETURN_243 |
| f4 | OP_RETURN_244 |
| f5 | OP_RETURN_245 |
| f6 | OP_RETURN_246 |
| f7 | OP_RETURN_247 |
| f8 | OP_RETURN_248 |
| f9 | OP_RETURN_249 |
| fa | OP_RETURN_250 |
| fb | OP_RETURN_251 |
| fc | OP_RETURN_252 |
| fd | OP_RETURN_253 |
| fe | OP_RETURN_254 |
| ff | OP_INVALIDOPCODE |
- Opcodes destacados em vermelho foram desabilitados.
- Veja o Opcode Explained para informações detalhadas sobre o que cada opcode faz.
- Há também uma visão geral útil de todos os opcodes em bitcoin.it/wiki/.
- Não incluí os prefixos
OP_dos opcodes nos diagramas desta página.
2. Dados
Os elementos de dados dentro de um Script (ex.: chaves públicas, assinaturas) precisam ser empurrados manualmente para a pilha usando um opcode.
Há alguns opcodes específicos que você pode escolher para fazer isso, e o que você usa depende de quantos bytes você quer empurrar para a pilha.
OP_0 a OP_16: (único byte representando os números de 0 a 16)
Os bytes 0x00 e 0x51 a 0x60 (representando os números de 0 a 16) receberam os seus próprios opcodes, de OP_0 a OP_16.
Esses bytes são automaticamente empurrados para a pilha, então você não precisa usar nenhuma operação de push explícita antes deles. Por exemplo:
ASM
OP_1 Hex
51 Os bytes usados para representar os opcodes OP_1 a OP_16 não são o equivalente hexadecimal desses números (ou seja, 0x01 a 0x10). Em vez disso, os opcodes para esses números receberam bytes na faixa 0x51 a 0x60. É meio estranho, eu sei, mas foi assim que eles foram atribuídos.
OP_PUSHBYTES_X: 1 a 75 bytes
Os opcodes OP_PUSHBYTES_X (0x01 a 0x4b) são usados para empurrar até 75 bytes para a pilha.
Basta substituir o X pelo número de bytes a seguir que você quer empurrar para a pilha. Por exemplo, aqui estou empurrando 20 bytes para a pilha:
ASM
OP_PUSHBYTES_20
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Hex
14aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Este é o opcode mais comumente usado para empurrar dados para a pilha.
OP_PUSHDATA1: 76 a 255 bytes
O opcode OP_PUSHDATA1 (0x4c) é seguido de 1 byte indicando o número de bytes que você quer empurrar para a pilha, seguido dos bytes em si.
Isso é usado quando você quer empurrar mais dados para a pilha do que consegue com OP_PUSHBYTES_X. Por exemplo, aqui estou empurrando 76 bytes para a pilha:
ASM
OP_PUSHDATA1
4c
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Hex
4c4caaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa OP_PUSHDATA2: 256 a 65535 bytes
O opcode OP_PUSHDATA2 (0x4d) funciona da mesma forma que o OP_PUSHDATA1, exceto que é seguido de 2 bytes para indicar o número de bytes a seguir a serem empurrados para a pilha.
Isso é usado quando você quer empurrar mais dados para a pilha do que consegue com OP_PUSHDATA1. Por exemplo, aqui estou empurrando 256 bytes para a pilha:
ASM
OP_PUSHDATA2
0001
aa... (256 bytes) Hex
4d0001aa... (256 bytes) Os 2 bytes após o OP_PUSHDATA2 estão em ordem de bytes little-endian. Por exemplo, 256 convertido para hexadecimal é 0100, e em little-endian é 0001.
OP_PUSHDATA4: 65536 a 4294967295 bytes
O opcode OP_PUSHDATA4 (0x4e) funciona da mesma forma que o OP_PUSHDATA2, mas é seguido de 4 bytes para indicar o número de bytes a seguir a serem empurrados para a pilha.
Isso é usado quando você quer empurrar mais dados para a pilha do que consegue com OP_PUSHDATA2. Por exemplo, aqui estou empurrando 65536 bytes para a pilha (o empilhamento de dados em si não é mostrado, pois seria bem longo):
ASM
OP_PUSHDATA4 00000100 [65536 bytes] Hex
4e00000100[65536 bytes] Os 4 bytes após o OP_PUSHDATA4 estão em ordem de bytes little-endian. Por exemplo, 65536 convertido para hexadecimal é 00010000, e em little-endian é 00000100.
OP_PUSHDATA4 é bem inútil, porque os empilhamentos de dados em scripts de Bitcoin são limitados a 520 bytes.
Por simplicidade, os diagramas desta página não mostram os opcodes OP_PUSHBYTES_X. Porém, essas operações de push são necessárias para empurrar dados para a pilha.
Operações de push mínimas
Você deve sempre usar a menor operação de push disponível para empurrar dados para a pilha.
Por exemplo, há várias formas de empurrar o número 8 para a pilha:
OP_8
OP_PUSHBYTES_1 08
OP_PUSHDATA1 01 08
OP_PUSHDATA2 0100 08
OP_PUSHDATA4 01000000 08 Da mesma forma, há várias formas de empurrar dois bytes para a pilha:
OP_PUSHBYTES_2 aaaa
OP_PUSHDATA1 02 aaaa
OP_PUSHDATA2 0200 aaaa
OP_PUSHDATA4 02000000 aaaa A primeira operação em ambos os exemplos usa a menor quantidade de bytes para empurrar os dados para a pilha, e você deve sempre usar a opção mais eficiente que puder.
Essa regra foi introduzida no BIP 62 e é imposta pela função CheckMinimalPush() em script.cpp. Essa é uma regra de padronicidade (standardness), então, embora usar uma operação menos eficiente não torne o Script tecnicamente inválido, os nós não aceitarão na sua mempool nenhuma transação que use qualquer coisa diferente das operações de push mínimas.
Execução
Como um script é executado?
Um script completo é executado da esquerda para a direita. Conforme ele roda, faz uso de uma estrutura de dados chamada pilha (stack).
Os dados são empurrados para a pilha.
Os opcodes retiram elementos da pilha, fazem algo com eles e, então, opcionalmente, empurram novos elementos de volta para a pilha.
Validade
Um script completo é determinado como válido ou inválido depois que termina de ser executado.
Um script é válido se há um único* elemento não-zero deixado na pilha (ex.: OP_1).
Um script é inválido se:
- A pilha final está vazia.
- O único elemento deixado na pilha é
OP_0. - Há mais de um elemento* deixado na pilha.
- O script sai prematuramente (ex.: OP_RETURN).
Aqui está um exemplo da execução de um script P2PKH completo:
*Múltiplos elementos deixados na pilha
Scripts Legados
É tecnicamente válido ter múltiplos elementos deixados na pilha após a execução para tipos de script legados, como:
Esses scripts ainda podem ser destravados se o elemento do topo da pilha ao fim da execução for não-zero.
Na verdade, é apenas uma regra de padronicidade (standardness) que impõe que um único elemento não-zero deva ser deixado na pilha.
Exige que apenas um único elemento de pilha permaneça após a avaliação. Isso muda o critério de sucesso de "Pelo menos um elemento de pilha precisa permanecer e, quando interpretado como booleano, precisa ser verdadeiro" para "Exatamente um elemento de pilha precisa permanecer e, quando interpretado como booleano, precisa ser verdadeiro".
Em outras palavras, scripts legados que deixam múltiplos itens na pilha ainda podem ser minerados na blockchain (ou seja, são válidos), mas os nós não os retransmitem entre as suas memory pools (ou seja, são não-padrão).
A razão para essa regra de padronicidade é impedir que a sua transação seja modificada depois de você transmiti-la para a rede:
A regra de padronicidade CLEANSTACK impede adicionar empilhamentos de dados extras no scriptSig de qualquer script, incluindo o P2PKH. Não ter tal regra convidaria à maleabilidade por terceiros: qualquer um na rede poderia modificar a transação em trânsito e adicionar ou remover dados dela, impactando a retransmissão de transações, a retransmissão e reconstrução de blocos, e a estimativa de taxas.
Se você criou uma saída P2SH que acaba deixando mais de um item na pilha, você precisará minerar a transação de gasto você mesmo (ou enviá-la diretamente a um minerador para mineração), pois, do contrário, os nós rejeitarão a transação de gasto da entrada na sua mempool, por ela ser um gasto não-padrão.
Scripts Segwit
O "um elemento deixado na pilha" é uma regra de validade para os tipos de script segwit modernos:
A verificação [do P2WPKH] precisa resultar em um único TRUE na pilha. [...] O script [do P2WSH] não pode falhar e precisa resultar em exatamente um único TRUE na pilha.
Se a execução do [tapscript do P2TR] resultar em qualquer coisa que não seja exatamente um elemento na pilha que avalie como verdadeiro com CastToBool(), falhe.
Portanto, se você usa um script de travamento personalizado dentro de um P2WSH ou P2TR, precisa garantir que apenas um elemento será deixado na pilha ao fim da execução, caso contrário você nunca conseguirá destravá-los.
Resumo
É melhor garantir que quaisquer scripts personalizados que você criar deixem apenas um elemento não-zero na pilha ao fim da execução.
Caso contrário, você ou não conseguirá gastá-los de jeito nenhum, por serem inválidos (ex.: em P2WSH ou P2TR), ou terá uma dor de cabeça tentando gastá-los, por serem não-padrão (ex.: em P2SH).
Não me pergunte como eu sei.
Localização
Onde o Script é usado no Bitcoin?
Um script de travamento (ScriptPubKey) é colocado em toda saída que você cria em uma transação:
Um script de destravamento (ScriptSig ou Testemunha) precisa ser fornecido para toda entrada que você quer gastar em uma transação:
Cada nó então combina e executa esses dois scripts para cada entrada de cada transação que recebe, para se certificar de que validam.
Se os scripts de destravamento das entradas não destravam com sucesso os scripts de travamento das saídas sendo gastas, então a transação é considerada inválida e não será retransmitida (nem minerada em um bloco).
O script de destravamento vem primeiro.
Embora o script de destravamento seja fornecido depois do script de travamento inicial (em termos de como as transações funcionam), na verdade colocamos o script de destravamento primeiro quando executamos o script completo.
Uso
Por que usamos Script no Bitcoin?
Por que usamos uma mini linguagem de programação para travar bitcoins? Por que não usar simplesmente uma comparação de chave pública e assinatura e abandonar todos esses opcodes e pilhas?
Bem, porque, usando Script, você pode criar diferentes tipos de travas usando diferentes combinações de OP_CODES.
Por exemplo, aqui estão alguns scripts de travamento legais que você pode criar:
1. Quebra-cabeça Matemático
Para gastar esta saída, você precisa fornecer dois números que somem 8.
Este pode não ser o script de travamento mais seguro do mundo, já que qualquer um pode descobri-lo e destravá-lo.
2. Quebra-cabeça de Hash
Aqui você só precisa de algo que faça hash com o mesmo resultado que está dentro do script de travamento.
3. Quebra-cabeça de Colisão de Hash
Este é bem legal. Você pode destravá-lo fornecendo duas strings de dados diferentes que produzam o mesmo resultado de hash.
Em outras palavras, ele funciona como um incentivo para encontrar uma "colisão de hash".
Este script de travamento em particular pode ser encontrado nesta saída. Porém, o script foi embrulhado em um script de travamento P2SH, então você não consegue de fato ver o script de travamento original (até que alguém o destrave).
Todos os scripts de travamento acima são não-padrão. Embora esses scripts sejam válidos (e possam ser minerados na blockchain), os nós típicos do Bitcoin Core não os retransmitem das suas memory pools, o que torna difícil que eles sejam minerados em primeiro lugar.
Scripts Padrão
Quais são os padrões de Script mais comuns no Bitcoin?
Apesar de ser possível criar uma variedade de scripts de travamento diferentes com várias combinações de OPCODES, a maioria dos nós só retransmite um punhado de "scripts padrão":
Legados
- P2PK (Pay To Public Key)
- P2PKH (Pay To Public Key Hash)
- P2MS (Pay To Multisig)
- P2SH (Pay To Script Hash)
- OP_RETURN
Esses eram os scripts padrão disponíveis no bitcoin entre 2009 e 2016 (antes da atualização Segwit).
Eles são destravados pelo campo ScriptSig.
Embora não sejam tão usados hoje (em favor dos scripts Segwit mais novos abaixo), eles ainda são perfeitamente válidos e você pode usá-los para travar as suas moedas, se quiser.
Segwit
Esses scripts padrão foram introduzidos após a atualização Segwit em 2016 e a atualização Taproot em 2021. Foram basicamente introduzidos para substituir os scripts de travamento legados P2PKH e P2SH acima.
Eles são destravados pelo campo de Testemunha.
Esses scripts de travamento não usam, de fato, a linguagem Script completa.
Em vez disso, cada script de travamento tem o seu próprio padrão específico, e eles são executados de uma forma fixa internamente ao serem destravados. Então, de certa forma, eles abandonaram a linguagem Script (exceto quando você embrulha um script completo dentro de um P2WSH).
Então, quando eu disse "por que não usar simplesmente uma comparação de chave pública e assinatura e abandonar todos esses opcodes e pilhas?", bem, é exatamente isso que esses scripts fizeram.
Por que os nós não retransmitem scripts não-padrão?
Eu sei, é uma pena.
Porém, nem toda combinação de OP_CODE foi minuciosamente testada. Então, se os nós retransmitissem todo script não-padrão que recebessem, isso introduziria o risco de um ataque de alguém fazendo spam na rede com scripts que demoram muito para verificar. Isso poderia "entupir" os nós e paralisar a rede.
Por outro lado, os scripts padrão foram minuciosamente testados e podem ser validados rapidamente. Então essa história toda de não retransmitir transações não-padrão é apenas uma medida de segurança.
Scripts não-padrão são válidos, eles só não são retransmitidos. Mesmo que uma transação não-padrão não seja retransmitida entre as memory pools, ela ainda pode ser minerada em um bloco. Então, se você quer que uma transação com um script não-padrão seja adicionada à blockchain, você precisa ou enviá-la diretamente a um minerador que a minere para você, ou minerá-la na blockchain você mesmo.
Limites
Qual é o tamanho máximo de um script?
Os scripts no bitcoin têm certos limites no seu tamanho. Há dois tipos de limite:
- Limites de Validade. Qualquer transação que contenha um script que exceda esses limites será considerada inválida. Isso significa que ela será rejeitada pelos nós e não poderá ser minerada na blockchain.
- Limites de Padronicidade. Uma transação pode quebrar esses limites e ainda ser minerada na blockchain, mas os nós a considerarão não-padrão e se recusarão a retransmiti-la entre as memory pools.
1. Limites de Validade
- O tamanho máximo de um script é 10.000 bytes. Um ScriptPubKey + ScriptSig combinados não podem ser maiores que 10.000 bytes.
- O número máximo de OP_CODES é 201. Esse limite não inclui as operações que empurram dados para a pilha.
- O tamanho máximo de um único elemento é 520 bytes. Você não pode empurrar nenhum dado para a pilha que exceda 520 bytes. Esse limite é mais relevante ao construir um Redeem Script para um P2SH, já que um Redeem Script é um empilhamento de dados de um script.
- O número máximo de itens na pilha é 1.000. Um script completo pode conter mais de 1.000 elementos, mas você não pode construir um script que empurre mais de 1.000 itens para a pilha em um dado momento.
Esses limites podem ser encontrados em script.h.
Esses limites só se aplicam durante a execução do script. Então você poderia colocar em uma saída um ScriptPubKey que excedesse esses limites e ele seria minerado. Mas, quando você fosse tentar gastá-lo como entrada (ou seja, quando o script estivesse sendo executado), a transação de gasto seria considerada inválida. Em outras palavras, a saída seria não gastável.
2. Limites de Padronicidade
- O ScriptSig pode ter no máximo 1.650 bytes. Então, se você precisa usar mais de 1.650 bytes de dados e/ou OP_CODES para destravar uma saída, os nós não retransmitirão a sua transação.
- O ScriptPubKey não tem limite (a não ser estar restrito pelo limite de tamanho do bloco). Então é perfeitamente normal criar um ScriptPubKey ridiculamente grande, se você quiser, mas lembre-se de que ele será não gastável se exceder qualquer um dos limites de validade acima.
Então, embora seja válido para uma transação exceder esses limites, será difícil minerá-la na blockchain, a não ser que você consiga minerá-la você mesmo ou que um minerador a adicione à blockchain para você.
Esses limites podem ser encontrados em policy.h.
Resumo
Em poucas palavras
Script é apenas uma mini linguagem de programação usada no Bitcoin para fornecer o mecanismo de travamento das saídas.
- Toda saída recebe um "script de travamento".
- Você precisa então fornecer um "script de destravamento" na transação que quer gastar aquela saída.
Quando um nó recebe a transação de gasto, ele combina esses dois scripts e os executa. Se um OP_1 (e nada além disso) é deixado no topo da pilha após o script terminar de executar, então o script é válido e a saída pode ser gasta.
Os scripts de travamento segwit mais novos se afastaram um pouco do uso do Script tradicional, mas a linguagem Script ainda é usada para os scripts de travamento legados e também pode continuar sendo usada dentro do script de travamento P2WSH mais novo.
O script é, na verdade, um predicado. É só uma equação que avalia como verdadeiro ou falso. "Predicado" é uma palavra longa e pouco familiar, então eu o chamei de script.
Recursos
- Opcode Explained – Um guia completo sobre os opcodes e o que cada um faz.
- bitcoin.it/wiki/Script
- The Bitcoin Script language (pt.1)
- Mastering Bitcoin: Capítulo 7 (Autorização e Autenticação)
- Um script é gastável se múltiplos itens são deixados na pilha?
- Por que transações não-padrão podem ser mineradas mas não retransmitidas?
- isStandard()
- Minsc — Uma ferramenta útil para construir scripts de Bitcoin complexos usando uma linguagem de alto nível baseada em Miniscript.