mirror of
https://github.com/ChristopherA/Learning-Bitcoin-from-the-Command-Line.git
synced 2025-06-08 08:26:17 +00:00
Chapter 13 translation finished
This commit is contained in:
parent
bb6dd6cfde
commit
ddc5dae330
21
pt/13_0_Designing_Real_Bitcoin_Scripts.md
Normal file
21
pt/13_0_Designing_Real_Bitcoin_Scripts.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Capítulo 13: Projetando Scripts Reais no Bitcoin
|
||||||
|
|
||||||
|
Nossos scripts do Bitcoin até agora têm sido exemplos teóricos, porque ainda estamos montando as peças do quebra-cabeça. Agora, com o repertório completo do Script do Bitcoin em mãos, estamos prontos para nos aprofundar em vários scripts do mundo real e ver como eles funcionam.
|
||||||
|
|
||||||
|
## Objetivos deste Capítulo
|
||||||
|
|
||||||
|
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
|
||||||
|
|
||||||
|
* Avaliar os scripts do Bitcoin do mundo real;
|
||||||
|
* Criar scripts do Bitcoin no mundo real.
|
||||||
|
|
||||||
|
Os objetivos secundários incluem a capacidade de:
|
||||||
|
|
||||||
|
* Entender os scripts do Bitcoin existentes;
|
||||||
|
* Compreender a importância das assinaturas.
|
||||||
|
|
||||||
|
## Tabela de Conteúdo
|
||||||
|
|
||||||
|
* [Seção 1: Escrevendo Puzzles com Scripts](13_1_Writing_Puzzle_Scripts.md)
|
||||||
|
* [Seção 2: Escrevendo Scripts Multisig Complexos](13_2_Writing_Complex_Multisig_Scripts.md)
|
||||||
|
* [Seção 3: Expandindo o Bitcoin com os Scripts](13_3_Empowering_Bitcoin_with_Scripts.md)
|
512
pt/13_1_Writing_Puzzle_Scripts.md
Normal file
512
pt/13_1_Writing_Puzzle_Scripts.md
Normal file
@ -0,0 +1,512 @@
|
|||||||
|
# 13.1: Escrevendo Puzzles com Scripts
|
||||||
|
|
||||||
|
Os scripts de Bitcoin realmente _não_ precisam depender do conhecimento de uma chave secreta. Ao invés disso, podemos criar puzzles de qualquer tipo.
|
||||||
|
|
||||||
|
## Escrevendo Scripts de Álgebra Simples
|
||||||
|
|
||||||
|
Nosso primeiro script real, da seção [§9.2: Executando um Script no Bitcoin](09_2_Running_a_Bitcoin_Script.md) foi um puzzle simples. Esse script Bitcoin, ```OP_ADD 99 OP_EQUAL```, poderia ter sido descrito da seguinte forma: ```x + y = 99```.
|
||||||
|
|
||||||
|
Esse tipo de script não tem muita aplicabilidade no mundo real, pois é muito fácil reivindicar os fundos. Mas, um quebra-cabeça que distribui pequenos valores em Bitcoin pode ser um entretenimento divertido.
|
||||||
|
|
||||||
|
Mais notavelmente, a criação de puzzles algébricos fornece uma boa compreensão de como funcionam as funções aritméticas no script do Bitcoin.
|
||||||
|
|
||||||
|
### Escrevendo um script multiplicador
|
||||||
|
|
||||||
|
O Script do Bitcoin possui vários opcodes que foram desativados para manter a segurança do sistema. Um deles é o ```OP_MUL```, que teria permitido a multiplicação, mas, está desabilitado.
|
||||||
|
|
||||||
|
Então, como escreveríamos uma função algébrica como ```3x + 7 = 13```?
|
||||||
|
|
||||||
|
A resposta mais óbvia é usando o ```OP_DUP``` o número inserido no script de bloqueio duas vezes. Então podemos colocar o ```7``` e continuar adicionando até obter o total. O script de bloqueio completo ficaria assim: ```OP_DUP OP_DUP 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL```.
|
||||||
|
|
||||||
|
Veja como seria executado o script de desbloqueio correto do ```2```:
|
||||||
|
```
|
||||||
|
Script: 2 OP_DUP OP_DUP 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL
|
||||||
|
Stack: [ ]
|
||||||
|
|
||||||
|
Script: OP_DUP OP_DUP 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL
|
||||||
|
Stack: [ 2 ]
|
||||||
|
|
||||||
|
Script: OP_DUP 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL
|
||||||
|
Running: 2 OP_DUP
|
||||||
|
Stack: [ 2 2 ]
|
||||||
|
|
||||||
|
Script: 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL
|
||||||
|
Running: 2 OP_DUP
|
||||||
|
Stack: [ 2 2 2 ]
|
||||||
|
|
||||||
|
Script: OP_ADD OP_ADD OP_ADD 13 OP_EQUAL
|
||||||
|
Stack: [ 2 2 2 7 ]
|
||||||
|
|
||||||
|
Script: OP_ADD OP_ADD 13 OP_EQUAL
|
||||||
|
Running: 2 7 OP_ADD
|
||||||
|
Stack: [ 2 2 9 ]
|
||||||
|
|
||||||
|
Script: OP_ADD 13 OP_EQUAL
|
||||||
|
Running: 2 9 OP_ADD
|
||||||
|
Stack: [ 2 11 ]
|
||||||
|
|
||||||
|
Script: 13 OP_EQUAL
|
||||||
|
Running: 2 11 OP_ADD
|
||||||
|
Stack: [ 13 ]
|
||||||
|
|
||||||
|
Script: OP_EQUAL
|
||||||
|
Stack: [ 13 13 ]
|
||||||
|
|
||||||
|
Script:
|
||||||
|
Running: 13 13 OP_EQUAL
|
||||||
|
Stack: [ True ]
|
||||||
|
```
|
||||||
|
Ou se você preferir usar o `btcdeb`:
|
||||||
|
```
|
||||||
|
$ btcdeb '[2 OP_DUP OP_DUP 7 OP_ADD OP_ADD OP_ADD 13 OP_EQUAL]'
|
||||||
|
btcdeb 0.2.19 -- type `btcdeb -h` for start up options
|
||||||
|
valid script
|
||||||
|
9 op script loaded. type `help` for usage information
|
||||||
|
script | stack
|
||||||
|
---------+--------
|
||||||
|
2 |
|
||||||
|
OP_DUP |
|
||||||
|
OP_DUP |
|
||||||
|
7 |
|
||||||
|
OP_ADD |
|
||||||
|
OP_ADD |
|
||||||
|
OP_ADD |
|
||||||
|
13 |
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0000 2
|
||||||
|
btcdeb> step
|
||||||
|
<> PUSH stack 02
|
||||||
|
script | stack
|
||||||
|
---------+--------
|
||||||
|
OP_DUP | 02
|
||||||
|
OP_DUP |
|
||||||
|
7 |
|
||||||
|
OP_ADD |
|
||||||
|
OP_ADD |
|
||||||
|
OP_ADD |
|
||||||
|
13 |
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0001 OP_DUP
|
||||||
|
btcdeb> step
|
||||||
|
<> PUSH stack 02
|
||||||
|
script | stack
|
||||||
|
---------+--------
|
||||||
|
OP_DUP | 02
|
||||||
|
7 | 02
|
||||||
|
OP_ADD |
|
||||||
|
OP_ADD |
|
||||||
|
OP_ADD |
|
||||||
|
13 |
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0002 OP_DUP
|
||||||
|
btcdeb> step
|
||||||
|
<> PUSH stack 02
|
||||||
|
script | stack
|
||||||
|
---------+--------
|
||||||
|
7 | 02
|
||||||
|
OP_ADD | 02
|
||||||
|
OP_ADD | 02
|
||||||
|
OP_ADD |
|
||||||
|
13 |
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0003 7
|
||||||
|
btcdeb> step
|
||||||
|
<> PUSH stack 07
|
||||||
|
script | stack
|
||||||
|
---------+--------
|
||||||
|
OP_ADD | 07
|
||||||
|
OP_ADD | 02
|
||||||
|
OP_ADD | 02
|
||||||
|
13 | 02
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0004 OP_ADD
|
||||||
|
btcdeb> step
|
||||||
|
<> POP stack
|
||||||
|
<> POP stack
|
||||||
|
<> PUSH stack 09
|
||||||
|
script | stack
|
||||||
|
---------+--------
|
||||||
|
OP_ADD | 09
|
||||||
|
OP_ADD | 02
|
||||||
|
13 | 02
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0005 OP_ADD
|
||||||
|
btcdeb> step
|
||||||
|
<> POP stack
|
||||||
|
<> POP stack
|
||||||
|
<> PUSH stack 0b
|
||||||
|
script | stack
|
||||||
|
---------+--------
|
||||||
|
OP_ADD | 0b
|
||||||
|
13 | 02
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0006 OP_ADD
|
||||||
|
btcdeb> step
|
||||||
|
<> POP stack
|
||||||
|
<> POP stack
|
||||||
|
<> PUSH stack 0d
|
||||||
|
script | stack
|
||||||
|
---------+--------
|
||||||
|
13 | 0d
|
||||||
|
OP_EQUAL |
|
||||||
|
#0007 13
|
||||||
|
btcdeb> step
|
||||||
|
<> PUSH stack 0d
|
||||||
|
script | stack
|
||||||
|
---------+--------
|
||||||
|
OP_EQUAL | 0d
|
||||||
|
| 0d
|
||||||
|
|
||||||
|
#0008 OP_EQUAL
|
||||||
|
btcdeb> step
|
||||||
|
<> POP stack
|
||||||
|
<> POP stack
|
||||||
|
<> PUSH stack 01
|
||||||
|
script | stack
|
||||||
|
---------+--------
|
||||||
|
| 01
|
||||||
|
```
|
||||||
|
### Escrevendo um Sistema de Equações
|
||||||
|
|
||||||
|
E se quiséssemos escrever um sistema de equações, como ```x + y = 3```,```y + z = 5``` e ```x + z = 4```? A álgebra diz que as respostas resultariam em ```x = 1```,```y = 2``` e ```z = 3```. Mas, como faríamos este script?
|
||||||
|
|
||||||
|
Obviamente, depois que o remetente inserir os três números, precisaremos de duas cópias de cada número, uma vez que cada número entra em duas equações diferentes. O ```OP_3DUP``` cuida disso e resulta em```x y z x y z``` estando na pilha. Tirar dois itens de cada vez resultará em ```y z```,```z x``` e ```x y```. Pronto! Essas são as três equações, então só precisamos adicioná-las e testá-las na ordem correta! Aqui está o script completo: ```OP_3DUP OP_ADD 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL```.
|
||||||
|
|
||||||
|
Veja como funciona com o script de desbloqueio correto de ```1 2 3```:
|
||||||
|
```
|
||||||
|
Script: 1 2 3 OP_3DUP OP_ADD 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
|
||||||
|
Stack: [ ]
|
||||||
|
|
||||||
|
Script: OP_3DUP OP_ADD 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
|
||||||
|
Stack: [ 1 2 3 ]
|
||||||
|
|
||||||
|
Script: OP_ADD 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
|
||||||
|
Running: 1 2 3 OP_3DUP
|
||||||
|
Stack: [ 1 2 3 1 2 3 ]
|
||||||
|
|
||||||
|
Script: 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
|
||||||
|
Running: 2 3 OP_ADD
|
||||||
|
Stack: [ 1 2 3 1 5 ]
|
||||||
|
|
||||||
|
Script: OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
|
||||||
|
Stack: [ 1 2 3 1 5 5 ]
|
||||||
|
|
||||||
|
Script: OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
|
||||||
|
Running: 5 5 OP_EQUALVERIFY
|
||||||
|
Stack: [ 1 2 3 1 ] — Does Not Exit
|
||||||
|
|
||||||
|
Script: 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
|
||||||
|
Running: 3 1 OP_ADD
|
||||||
|
Stack: [ 1 2 4 ]
|
||||||
|
|
||||||
|
Script: OP_EQUALVERIFY OP_ADD 3 OP_EQUAL
|
||||||
|
Stack: [ 1 2 4 4 ]
|
||||||
|
|
||||||
|
Script: OP_ADD 3 OP_EQUAL
|
||||||
|
Running: 4 4 OP_EQUALVERIFY
|
||||||
|
Stack: [ 1 2 ] — Does Not Exit
|
||||||
|
|
||||||
|
Script: 3 OP_EQUAL
|
||||||
|
Running: 1 2 OP_ADD
|
||||||
|
Stack: [ 3 ]
|
||||||
|
|
||||||
|
Script: OP_EQUAL
|
||||||
|
Stack: [ 3 3 ]
|
||||||
|
|
||||||
|
Script:
|
||||||
|
Running: 3 3 OP_EQUAL
|
||||||
|
Stack: [ True ]
|
||||||
|
```
|
||||||
|
Aqui está usando o `btcdeb`:
|
||||||
|
```
|
||||||
|
$ btcdeb '[1 2 3 OP_3DUP OP_ADD 5 OP_EQUALVERIFY OP_ADD 4 OP_EQUALVERIFY OP_ADD 3 OP_EQUAL]'
|
||||||
|
btcdeb 0.2.19 -- type `btcdeb -h` for start up options
|
||||||
|
valid script
|
||||||
|
13 op script loaded. type `help` for usage information
|
||||||
|
script | stack
|
||||||
|
---------------+--------
|
||||||
|
1 |
|
||||||
|
2 |
|
||||||
|
3 |
|
||||||
|
OP_3DUP |
|
||||||
|
OP_ADD |
|
||||||
|
5 |
|
||||||
|
OP_EQUALVERIFY |
|
||||||
|
OP_ADD |
|
||||||
|
4 |
|
||||||
|
OP_EQUALVERIFY |
|
||||||
|
OP_ADD |
|
||||||
|
3 |
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0000 1
|
||||||
|
btcdeb> step
|
||||||
|
<> PUSH stack 01
|
||||||
|
script | stack
|
||||||
|
---------------+--------
|
||||||
|
2 | 01
|
||||||
|
3 |
|
||||||
|
OP_3DUP |
|
||||||
|
OP_ADD |
|
||||||
|
5 |
|
||||||
|
OP_EQUALVERIFY |
|
||||||
|
OP_ADD |
|
||||||
|
4 |
|
||||||
|
OP_EQUALVERIFY |
|
||||||
|
OP_ADD |
|
||||||
|
3 |
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0001 2
|
||||||
|
btcdeb> step
|
||||||
|
<> PUSH stack 02
|
||||||
|
script | stack
|
||||||
|
---------------+--------
|
||||||
|
3 | 02
|
||||||
|
OP_3DUP | 01
|
||||||
|
OP_ADD |
|
||||||
|
5 |
|
||||||
|
OP_EQUALVERIFY |
|
||||||
|
OP_ADD |
|
||||||
|
4 |
|
||||||
|
OP_EQUALVERIFY |
|
||||||
|
OP_ADD |
|
||||||
|
3 |
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0002 3
|
||||||
|
btcdeb> step
|
||||||
|
<> PUSH stack 03
|
||||||
|
script | stack
|
||||||
|
---------------+--------
|
||||||
|
OP_3DUP | 03
|
||||||
|
OP_ADD | 02
|
||||||
|
5 | 01
|
||||||
|
OP_EQUALVERIFY |
|
||||||
|
OP_ADD |
|
||||||
|
4 |
|
||||||
|
OP_EQUALVERIFY |
|
||||||
|
OP_ADD |
|
||||||
|
3 |
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0003 OP_3DUP
|
||||||
|
btcdeb> step
|
||||||
|
<> PUSH stack 01
|
||||||
|
<> PUSH stack 02
|
||||||
|
<> PUSH stack 03
|
||||||
|
script | stack
|
||||||
|
---------------+--------
|
||||||
|
OP_ADD | 03
|
||||||
|
5 | 02
|
||||||
|
OP_EQUALVERIFY | 01
|
||||||
|
OP_ADD | 03
|
||||||
|
4 | 02
|
||||||
|
OP_EQUALVERIFY | 01
|
||||||
|
OP_ADD |
|
||||||
|
3 |
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0004 OP_ADD
|
||||||
|
btcdeb> step
|
||||||
|
<> POP stack
|
||||||
|
<> POP stack
|
||||||
|
<> PUSH stack 05
|
||||||
|
script | stack
|
||||||
|
---------------+--------
|
||||||
|
5 | 05
|
||||||
|
OP_EQUALVERIFY | 01
|
||||||
|
OP_ADD | 03
|
||||||
|
4 | 02
|
||||||
|
OP_EQUALVERIFY | 01
|
||||||
|
OP_ADD |
|
||||||
|
3 |
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0005 5
|
||||||
|
btcdeb> step
|
||||||
|
<> PUSH stack 05
|
||||||
|
script | stack
|
||||||
|
---------------+--------
|
||||||
|
OP_EQUALVERIFY | 05
|
||||||
|
OP_ADD | 05
|
||||||
|
4 | 01
|
||||||
|
OP_EQUALVERIFY | 03
|
||||||
|
OP_ADD | 02
|
||||||
|
3 | 01
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0006 OP_EQUALVERIFY
|
||||||
|
btcdeb> step
|
||||||
|
<> POP stack
|
||||||
|
<> POP stack
|
||||||
|
<> PUSH stack 01
|
||||||
|
<> POP stack
|
||||||
|
script | stack
|
||||||
|
---------------+--------
|
||||||
|
OP_ADD | 01
|
||||||
|
4 | 03
|
||||||
|
OP_EQUALVERIFY | 02
|
||||||
|
OP_ADD | 01
|
||||||
|
3 |
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0007 OP_ADD
|
||||||
|
btcdeb> step
|
||||||
|
<> POP stack
|
||||||
|
<> POP stack
|
||||||
|
<> PUSH stack 04
|
||||||
|
script | stack
|
||||||
|
---------------+--------
|
||||||
|
4 | 04
|
||||||
|
OP_EQUALVERIFY | 02
|
||||||
|
OP_ADD | 01
|
||||||
|
3 |
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0008 4
|
||||||
|
btcdeb> step
|
||||||
|
<> PUSH stack 04
|
||||||
|
script | stack
|
||||||
|
---------------+--------
|
||||||
|
OP_EQUALVERIFY | 04
|
||||||
|
OP_ADD | 04
|
||||||
|
3 | 02
|
||||||
|
OP_EQUAL | 01
|
||||||
|
|
||||||
|
#0009 OP_EQUALVERIFY
|
||||||
|
btcdeb> step
|
||||||
|
<> POP stack
|
||||||
|
<> POP stack
|
||||||
|
<> PUSH stack 01
|
||||||
|
<> POP stack
|
||||||
|
script | stack
|
||||||
|
---------------+--------
|
||||||
|
OP_ADD | 02
|
||||||
|
3 | 01
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0010 OP_ADD
|
||||||
|
btcdeb> step
|
||||||
|
<> POP stack
|
||||||
|
<> POP stack
|
||||||
|
<> PUSH stack 03
|
||||||
|
script | stack
|
||||||
|
---------------+--------
|
||||||
|
3 | 03
|
||||||
|
OP_EQUAL |
|
||||||
|
|
||||||
|
#0011 3
|
||||||
|
btcdeb> step
|
||||||
|
<> PUSH stack 03
|
||||||
|
script | stack
|
||||||
|
---------------+--------
|
||||||
|
OP_EQUAL | 03
|
||||||
|
| 03
|
||||||
|
|
||||||
|
#0012 OP_EQUAL
|
||||||
|
btcdeb> step
|
||||||
|
<> POP stack
|
||||||
|
<> POP stack
|
||||||
|
<> PUSH stack 01
|
||||||
|
script | stack
|
||||||
|
---------------+--------
|
||||||
|
| 01
|
||||||
|
```
|
||||||
|
|
||||||
|
> :warning: **ATENÇÃO** O ```btcdeb``` não é útil apenas para fornecer a visualização desses scripts, mas também para verificar os resultados. Com certeza, erramos na primeira vez, testando as equações na ordem errada. É tão fácil cometer um erro financeiramente fatal em um script Bitcoin, e é por isso que todo script deve ser testado exaustivamente.
|
||||||
|
|
||||||
|
## Escrevendo Scripts Computacionais Simples
|
||||||
|
|
||||||
|
Embora os scripts de puzzle sejam triviais, podem realmente ter utilidade no mundo real se quisermos terceirizar uma computação. Podemos simplesmente criar um script que requer a resposta do cálculo e enviar fundos para o endereço P2SH como recompensa. Assim, a recompensa ficará lá até que alguém dê a resposta.
|
||||||
|
|
||||||
|
Por exemplo, Peter Todd [ofereceu recompensas](https://bitcointalk.org/index.php?topic=293382.0) por resolver equações que demonstram colisões para algoritmos criptográficos padrão. Aqui estava o script para confirmar uma colisão SHA1: ```OP_2DUP OP_EQUAL OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL```. Requer duas entradas, que serão os dois números que colidem.
|
||||||
|
|
||||||
|
Veja como funciona com as respostas corretas.
|
||||||
|
|
||||||
|
Primeiro, preenchemos nossa pilha:
|
||||||
|
```
|
||||||
|
Script: <numA> <numB> OP_2DUP OP_EQUAL OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
|
||||||
|
Stack: [ ]
|
||||||
|
|
||||||
|
Script: OP_2DUP OP_EQUAL OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
|
||||||
|
Stack: [ <numA> <numB> ]
|
||||||
|
|
||||||
|
Script: OP_EQUAL OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
|
||||||
|
Running: <numA> <numB> OP_2DUP
|
||||||
|
Stack: [ <numA> <numB> <numA> <numB> ]
|
||||||
|
```
|
||||||
|
Then, we make sure the two numbers aren't equal, exiting if they are:
|
||||||
|
Em seguida, certificamo-nos de que os dois números não são iguais, saindo se forem:
|
||||||
|
```
|
||||||
|
Script: OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
|
||||||
|
Running: <numA> <numB> OP_EQUAL
|
||||||
|
Stack: [ <numA> <numB> False ]
|
||||||
|
|
||||||
|
Script: OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
|
||||||
|
Running: False OP_NOT
|
||||||
|
Stack: [ <numA> <numB> True ]
|
||||||
|
|
||||||
|
Script: OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL
|
||||||
|
Running: True OP_VERIFY
|
||||||
|
Stack: [ <numA> <numB> ] — Does Not Exit
|
||||||
|
```
|
||||||
|
We now create two SHAs:
|
||||||
|
Agora criamos dois SHAs:
|
||||||
|
```
|
||||||
|
Script: OP_SWAP OP_SHA1 OP_EQUAL
|
||||||
|
Running: <numB> OP_SHA1
|
||||||
|
Stack: [ <numA> <hashB> ]
|
||||||
|
|
||||||
|
Script: OP_SHA1 OP_EQUAL
|
||||||
|
Running: <numA> <hashB> OP_SWAP
|
||||||
|
Stack: [ <hashB> <numA> ]
|
||||||
|
|
||||||
|
Script: OP_EQUAL
|
||||||
|
Running: <numA> OP_SHA1
|
||||||
|
Stack: [ <hashB> <hashA> ]
|
||||||
|
```
|
||||||
|
Finally, we see if they match.
|
||||||
|
Finalmente, vemos se eles combinam.
|
||||||
|
```
|
||||||
|
Script:
|
||||||
|
Running: <hashB> <hashA> OP_EQUAL
|
||||||
|
Stack: [ True ]
|
||||||
|
```
|
||||||
|
Este é um bom script porque mostra o uso cuidadoso da lógica (com o ```OP_NOT``` e o ```OP_VERIFY```) e bom uso das funções de pilha (com o ```OP_SWAP```). Trata-se de um ótimo exemplo de função do mundo real. E isso é muito real. Quando o [SHA-1 foi quebrado](https://shattered.io/), 2,48 BTC foram rapidamente liberados do endereço, com um valor total de cerca de $3.000 na época.
|
||||||
|
|
||||||
|
O ```btcdeb``` pode ser executado para provar a colisão (e o script):
|
||||||
|
```
|
||||||
|
btcdeb $ btcdeb '[255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017f46dc93a6b67e013b029aaa1db2560b45ca67d688c7f84b8c4c791fe02b3df614f86db1690901c56b45c1530afedfb76038e972722fe7ad728f0e4904e046c230570fe9d41398abe12ef5bc942be33542a4802d98b5d70f2a332ec37fac3514e74ddc0f2cc1a874cd0c78305a21566461309789606bd0bf3f98cda8044629a1 255044462d312e330a25e2e3cfd30a0a0a312030206f626a0a3c3c2f57696474682032203020522f4865696768742033203020522f547970652034203020522f537562747970652035203020522f46696c7465722036203020522f436f6c6f7253706163652037203020522f4c656e6774682038203020522f42697473506572436f6d706f6e656e7420383e3e0a73747265616d0affd8fffe00245348412d3120697320646561642121212121852fec092339759c39b1a1c63c4c97e1fffe017346dc9166b67e118f029ab621b2560ff9ca67cca8c7f85ba84c79030c2b3de218f86db3a90901d5df45c14f26fedfb3dc38e96ac22fe7bd728f0e45bce046d23c570feb141398bb552ef5a0a82be331fea48037b8b5d71f0e332edf93ac3500eb4ddc0decc1a864790c782c76215660dd309791d06bd0af3f98cda4bc4629b1 OP_2DUP OP_EQUAL OP_NOT OP_VERIFY OP_SHA1 OP_SWAP OP_SHA1 OP_EQUAL']
|
||||||
|
```
|
||||||
|
|
||||||
|
As outras [recompensas](https://bitcointalk.org/index.php?topic=293382.0) de Peter Todd permanecem intocadas, pelo menos até o momento da redação deste artigo. Elas são todas escritos da mesma maneira que o exemplo SHA-1 acima.
|
||||||
|
|
||||||
|
## Compreendendo as Limitações dos Scripts de Puzzle
|
||||||
|
|
||||||
|
Os scripts de puzzle são ótimos para examinar mais detalhadamente os scripts do Bitcoin, mas só os veremos em uso no mundo real se estiverem mantendo pequenas quantias de fundos ou se forem destinados ao resgate por usuários muito habilidosos. Há uma razão para isso: Eles não são seguros.
|
||||||
|
|
||||||
|
É aqui que a segurança cai:
|
||||||
|
|
||||||
|
Primeiro, qualquer um pode resgatá-los sem saber muito sobre um segredo. Eles precisam ter o ```redeemScript```, que oferece alguma proteção, mas uma vez que consigam, esse é provavelmente o único segredo necessário, a menos que nosso puzzle seja _realmente_ difícil, como um quebra-cabeça computacional.
|
||||||
|
|
||||||
|
Em segundo lugar, o resgate real não é seguro. Normalmente, uma transação de Bitcoin é protegida pela assinatura. Como a assinatura cobre a transação, ninguém na rede pode reescrever essa transação para enviar para o endereço sem invalidar a assinatura (e, portanto, a transação). Isso não é verdade com transações cujas entradas são apenas números. Qualquer um poderia pegar a transação e reescrevê-la para permitir o roubo dos fundos. Se eles conseguirem colocar a transação em um bloco antes da nossa transação, eles ganham e nós não receberemos o dinheiro do puzzle. Existem soluções para isso, mas elas envolvem a mineração do bloco por conta própria ou um pool confiável para minerá-lo, e nenhuma dessas opções é racional para um usuário comum do Bitcoin.
|
||||||
|
|
||||||
|
Ainda assim, as recompensas criptográficas de Peter Todd provam que os scripts de quebra-cabeça têm alguma aplicação no mundo real.
|
||||||
|
|
||||||
|
## Resumo: Escrevendo Puzzles com Scripts
|
||||||
|
|
||||||
|
Os scripts de puzzles são uma ótima introdução aos scripts do Bitcoin mais realistas e complexos. Eles demonstram o poder das funções matemáticas e de pilha no script do Bitcoin e como podem ser cuidadosamente combinadas para criar perguntas que requerem respostas muito específicas. No entanto, o uso no mundo real também é limitado pelos problemas de segurança inerentes às transações Bitcoin não assinadas.
|
||||||
|
|
||||||
|
> :fire: ***Qual é o poder do script de puzzles?*** Apesar das limitações, os scripts de puzzles têm sido usados no mundo real como prêmios para recompensas computacionais. Qualquer pessoa que consiga descobrir um quebra-cabeça complexo, cuja solução provavelmente tenha algum impacto no mundo real, pode ganhar a recompensa. Se vão conseguir sacar para seus endereços, é outra questão.
|
||||||
|
|
||||||
|
## O Que Vem Depois?
|
||||||
|
|
||||||
|
Vamos continuar "Projetando Scripts Reais no Bitcoin" na seção [§13.2: Escrevendo Scripts Multisig Complexos](13_2_Writing_Complex_Multisig_Scripts.md).
|
151
pt/13_2_Writing_Complex_Multisig_Scripts.md
Normal file
151
pt/13_2_Writing_Complex_Multisig_Scripts.md
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
# 13.2: Escrevendo Scripts Multisig Complexos
|
||||||
|
|
||||||
|
Até o momento, os multisigs descritos nesses documentos têm sido inteiramente simples, na forma m-de-n ou n-de-n. No entanto, podemos desejar multisigs mais complexos, onde as pessoas que assinam as transações variam ou onde diferentes opções podem se tornar disponíveis ao longo do tempo.
|
||||||
|
|
||||||
|
## Escrevendo uma Multisig Variável
|
||||||
|
|
||||||
|
Uma multisig variável requer diferentes números de pessoas para assinar, dependendo de quem está assinando.
|
||||||
|
|
||||||
|
### Escrevendo uma Multisig com um único assinante ou com vários assinantes
|
||||||
|
|
||||||
|
Imagine uma empresa em que o presidente ou dois em cada três vice-presidentes concordem com o uso dos fundos.
|
||||||
|
|
||||||
|
Podemos escrever isso criando uma instrução ```IF```/```ELSE```/```ENDIF``` que tem dois blocos, um para o presidente e sua assinatura um-de-um e um para os vice-presidentes e suas dois-de-três assinaturas. Podemos então, determinar qual bloco usar com base em quantas assinaturas estão no script de desbloqueio. Se usarmos ```OP_DEPTH 1 OP_EQUAL``` estaremos dizendo que há um item na pilha, e iremos partir daí.
|
||||||
|
|
||||||
|
O script de bloqueio completo seria ```OP_DEPTH 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF```.
|
||||||
|
|
||||||
|
Se executado pelo presidente, seria assim:
|
||||||
|
```
|
||||||
|
Script: <sigPres> OP_DEPTH 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
|
||||||
|
Stack: [ ]
|
||||||
|
|
||||||
|
Script: OP_DEPTH 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
|
||||||
|
Stack: [ <sigPres> ]
|
||||||
|
|
||||||
|
Script: 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
|
||||||
|
Running: <SigPres> OP_DEPTH
|
||||||
|
Stack: [ <sigPres> 1 ]
|
||||||
|
|
||||||
|
Script: OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
|
||||||
|
Stack: [ <sigPres> 1 1 ]
|
||||||
|
|
||||||
|
Script: IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
|
||||||
|
Running: 1 1 OP_EQUAL
|
||||||
|
Stack: [ <sigPres> True ]
|
||||||
|
```
|
||||||
|
Como o resultado é `True`, o script agora se reduz para a instrução ```IF```:
|
||||||
|
```
|
||||||
|
Script: <pubKeyPres> OP_CHECKSIGNATURE
|
||||||
|
Running: True IF
|
||||||
|
Stack: [ <sigPres> ]
|
||||||
|
|
||||||
|
Script: OP_CHECKSIGNATURE
|
||||||
|
Stack: [ <sigPres> <pubKeyPres> ]
|
||||||
|
|
||||||
|
Script:
|
||||||
|
Running: <sigPres> <pubKeyPres> OP_CHECKSIGNATURE
|
||||||
|
Stack: [ True ]
|
||||||
|
```
|
||||||
|
Se administrado por dois vice-presidentes, ficaria assim:
|
||||||
|
```
|
||||||
|
Script: 0 <sigVPA> <sigVPB> OP_DEPTH 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
|
||||||
|
Stack: [ ]
|
||||||
|
|
||||||
|
Script: OP_DEPTH 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
|
||||||
|
Stack: [ 0 <sigVPA> <sigVPB> ]
|
||||||
|
|
||||||
|
Script: 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
|
||||||
|
Running: 0 <sigVPA> <sigVPB> OP_DEPTH
|
||||||
|
Stack: [ 0 <sigVPA> <sigVPB> 3 ]
|
||||||
|
|
||||||
|
Script: OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
|
||||||
|
Stack: [ 0 <sigVPA> <sigVPB> 3 1 ]
|
||||||
|
|
||||||
|
Script: IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG ENDIF
|
||||||
|
Running: 3 1 OP_EQUAL
|
||||||
|
Stack: [ 0 <sigVPA> <sigVPB> False ]
|
||||||
|
```
|
||||||
|
Como o resultado é `False`, o script agora se reduz à instrução ```ELSE```:
|
||||||
|
```
|
||||||
|
Script: 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG
|
||||||
|
Running: False IF
|
||||||
|
Stack: [ 0 <sigVPA> <sigVPB> ]
|
||||||
|
|
||||||
|
Script: OP_CHECKMULTISIG
|
||||||
|
Stack: [ 0 <sigVPA> <sigVPB> 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 ]
|
||||||
|
|
||||||
|
Script:
|
||||||
|
Running: 0 <sigVPA> <sigVPB> 2 <pubKeyVPA> <pubKeyVPB> <pubKeyVPC> 3 OP_CHECKMULTISIG
|
||||||
|
Stack: [ ]
|
||||||
|
```
|
||||||
|
Podemos notar que a assinatura do presidente usa apenas um simples ```OP_CHECKSIGNATURE``` ao invés do código mais complexo normalmente exigido para um P2PKH. Podemos nos safar incluindo a chave pública no script de bloqueio, evitando um trabalhão padrão, porque é o hash e não será revelado (por meio do ```redeemScript```) até que a transação seja desbloqueada. Isso também permite que todos os possíveis assinantes assinem usando a mesma metodologia.
|
||||||
|
|
||||||
|
O único problema é se o presidente estiver distraído e acidentalmente assinar uma transação com um dos vice-presidentes, porque ele se lembra de ser um multisig 2 de 3. Uma opção é decidir que essa é uma condição de falha aceitável, porque o presidente está usando o multsig incorretamente. Outra opção é transformar o multisig 2 de 3 em um multisig 2 de 4, caso o presidente não tolere falhas: ```OP_DEPTH 1 OP_EQUAL IF <pubKeyPres> OP_CHECKSIGNATURE ELSE 2 <pubKeyVPA> <pubKeyVPB> < pubKeyVPC> <pubKeyPres> 4 OP_CHECKMULTISIG ENDIF```. Isso permitiria ao presidente assinar por engano com qualquer vice-presidente, mas não afetaria as coisas se dois vice-presidentes quisessem assinar (corretamente).
|
||||||
|
|
||||||
|
### Escrevendo um Multisig com um assinante obrigatório
|
||||||
|
|
||||||
|
Outra possibilidade de multisig envolve ter um multisig m-of-n onde um dos assinantes é necessário. Isso geralmente pode ser gerenciado dividindo o multisig em vários m de n-1 multisigs. Por exemplo, um multisig 2 de 3 em que um dos signatários é necessário seria, na verdade, dois multisig 2 de 2, cada um incluindo o signatário necessário.
|
||||||
|
|
||||||
|
Esta é uma maneira simples de criar um script para isso:
|
||||||
|
```
|
||||||
|
OP_3DUP
|
||||||
|
2 <pubKeyRequired> <pubKeyA> 2 OP_CHECKMULTISIG
|
||||||
|
NOTIF
|
||||||
|
2 <pubKeyRequired> <pubKeyB> 2 OP_CHECKMULTISIG
|
||||||
|
ENDIF
|
||||||
|
```
|
||||||
|
O script de desbloqueio seria ```0 <pubKeyRequired> <pubKeyA>``` ou ```0 <pubKeyRequired> <pubKeyB>```.
|
||||||
|
|
||||||
|
Primeiro, o script verifica as assinaturas no ```<pubKeyRequired> <pubKeyA>```. Se falhar, será verificado no ```<pubKeyRequired> <pubKeyB>```.
|
||||||
|
|
||||||
|
O resultado do ```OP_CHECKMULTISIG``` final que foi executado será deixado no topo da pilha (embora haja um resto abaixo dele se o primeiro for bem-sucedido).
|
||||||
|
|
||||||
|
## Escrevendo um Escrow Multisig
|
||||||
|
|
||||||
|
Falamos muito sobre escrows. Os multisigs complexos combinados com timelocks oferecem uma maneira automatizada de criá-los de maneira robusta.
|
||||||
|
|
||||||
|
Imagine a compradora de imóveis Alice e o vendedor de imóveis Bob que estão trabalhando com um agente de garantia. A maneira fácil de fazer o script seria como um multisig onde qualquer uma das três partes poderia liberar o dinheiro: Ou o vendedor e o comprador concordam ou o agente de garantia assume o controle e concorda com uma das partes: ```2 <pubKeyA> <pubKeyB> <pubKeyEscrow> 3 OP_CHECKMULTISG```.
|
||||||
|
|
||||||
|
No entanto, isso enfraquece o poder do agente de garantia e permite que o vendedor e o comprador acidentalmente tomem uma decisão errada entre eles. O que é uma das coisas que um sistema de garantia deve evitar. Portanto, pode ser que o que realmente desejamos seja o sistema que acabamos de criar, onde o agente de custódia é uma parte necessária no multisig 2 de 3: ```OP_3DUP 2 <pubKeyEscrow> <pubKeyA> 2 OP_CHECKMULTISIG NOTIF 2 <pubKeyEscrow > <pubKeyB> 2 OP_CHECKMULTISIG ENDIF```.
|
||||||
|
|
||||||
|
No entanto, isso não passa no teste de entrar na frente de um ônibus. Se o agente de custódia morre ou foge para as Bahamas durante o processo, o comprador e o vendedor ficam sem o dinheiro. É aqui que entra um bloqueio de tempo. Podemos criar um teste adicional que só será executado se tivermos passado o final do nosso período de garantia. Nessa situação, permitimos que o comprador e o vendedor assinem juntos:
|
||||||
|
```
|
||||||
|
OP_3DUP
|
||||||
|
2 <pubKeyEscrow> <pubKeyA> 2 OP_CHECKMULTISIG
|
||||||
|
NOTIF
|
||||||
|
OP_3DUP
|
||||||
|
2 <pubKeyEscrow> <pubKeyB> 2 OP_CHECKMULTISIG
|
||||||
|
NOTIF
|
||||||
|
<+30Days> OP_CHECKSEQUENCEVERIFY OP_DROP
|
||||||
|
2 <pubKeyA> <pubKeyB> 2 OP_CHECKMULTISIG
|
||||||
|
ENDIF
|
||||||
|
ENDIF
|
||||||
|
```
|
||||||
|
Primeiro, testamos uma assinatura para o comprador e o agente de garantia e, em seguida, uma assinatura para o vendedor e o agente de garantia. Se ambos falharem e 30 dias se passaram, também permitimos uma assinatura para o comprador e o vendedor.
|
||||||
|
|
||||||
|
### Escrevendo um Multisig de Compromisso Centrado no Comprador
|
||||||
|
|
||||||
|
O [BIP 112](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki#Escrow_with_Timeout) oferece um exemplo diferente deste tipo de garantia que não tem proteções extras para evitar o agente de garantia, mas que dá a Alice controle total se a garantia falhar.
|
||||||
|
```
|
||||||
|
IF
|
||||||
|
2 <pubKeyA> <pubKeyB> <pubKeyEscrow> 3 OP_CHECKMULTISIG
|
||||||
|
ELSE
|
||||||
|
<+30Days> OP_CHECKSEQUENCEVERIFY OP_DROP
|
||||||
|
<pubKeyA> OP_CHECKSIGNATURE
|
||||||
|
ENDIF
|
||||||
|
```
|
||||||
|
Aqui, qualquer um dos três assinantes pode liberar o dinheiro a qualquer momento, mas depois de 30 dias, Alice pode recuperar o dinheiro por conta própria.
|
||||||
|
|
||||||
|
Observe que este script requer que um ```True``` ou ```False``` seja passado para identificar qual caminho será utilizado. Esta é uma maneira mais simples e menos computacionalmente intensiva de oferecer suporte aos caminhos usando o script de Bitcoin. É algo bem comum.
|
||||||
|
|
||||||
|
No início, o seguinte ```sigScript``` seria permitido: ```0 <signer1> <signer2> True```. Após 30 dias, Alice poderia produzir um ```sigScript``` como este: ```<sigA> False```.
|
||||||
|
|
||||||
|
## Resumo: Escrevendo Scripts Multisig Complexos
|
||||||
|
|
||||||
|
Os multisigs mais complexos podem ser normalmente criados combinando assinaturas ou multi assinaturas com condicionais e testes. Os multisigs resultantes podem ser variáveis, exigindo diferentes números de assinantes com base em quem são e quando estão assinando.
|
||||||
|
|
||||||
|
> :fire: ***Qual é o poder dos scripts complexos com multisigs?*** Mais do que qualquer coisa que vimos até agora, os scripts multisig complexos são contratos realmente inteligentes. Eles podem ser muito precisos sobre quem tem permissão para assinar e quando. Empresas com vários níveis, parcerias e escrows podem utilizar soluções semelhantes. O uso de outros recursos poderosos como os timelocks pode proteger ainda mais esses fundos, permitindo que sejam liberados ou mesmo devolvidos em determinados momentos.
|
||||||
|
|
||||||
|
## O Que Vem Depois?
|
||||||
|
|
||||||
|
Vamos continuar "Projetando Scripts Reais no Bitcoin" na seção [§13.3: Expandindo o Bitcoin com os Scripts] (13_3_Empowering_Bitcoin_with_Scripts.md).
|
276
pt/13_3_Empowering_Bitcoin_with_Scripts.md
Normal file
276
pt/13_3_Empowering_Bitcoin_with_Scripts.md
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
# 13.3: Expandindo o Bitcoin com os Scripts
|
||||||
|
|
||||||
|
Os scripts de Bitcoin podem ir muito além dos instrumentos financeiros relativamente simples detalhados até o momento. Eles também são a base dos usos mais complexos da rede Bitcoin, conforme demonstrado por esses exemplos do mundo real de funcionalidade fora da cadeia (offchain), extraídos dos exemplos da Lightning Network no [BIP 112](https://github.com/bitcoin /bips/blob/master/bip-0112.mediawiki).
|
||||||
|
|
||||||
|
## Bloqueio para a Lightning Network
|
||||||
|
|
||||||
|
A [Lightning Network](https://rusty.ozlabs.org/?p=450) é um canal de pagamento que permite aos usuários retirar fundos offchain e se envolver em várias micro-transações antes de finalizar o canal de pagamento e trazer os fundos de volta para Bitcoin. Os benefícios incluem taxas mais baixas e velocidades de transação mais rápidas. Iremos discutir com riqueza maior de detalhes, com exemplos de como utilizá-la usando a linha de comando, começando no [Capítulo 18](18_0_Understanding_Your_Lightning_Setup.md).
|
||||||
|
|
||||||
|
O [BIP 112](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki) contém alguns exemplos de como essas transações offchain podem ser geradas, usando scripts de bloqueio do Bitcoin.
|
||||||
|
|
||||||
|
### Bloqueio com transações de compromisso revogáveis
|
||||||
|
|
||||||
|
O truque do Lightning é o fato de ele estar fora da blockchain. Para usar a Lightning, os participantes bloqueiam fundos em conjunto na blockchain do Bitcoin com uma transação multisig n-de-n. Em seguida, eles se envolvem em uma série de transações entre si. Cada nova "transação de compromisso" (commitment transaction) divide esses fundos de uma maneira diferente. Essas transações são parcialmente assinadas, mas _não são colocadas na blockchain_.
|
||||||
|
|
||||||
|
Se temos uma massa de transações não publicadas, qualquer uma delas _pode_ ser colocada na Blockchain, portanto, como evitamos que um dos participantes volte a uma transação antiga que é mais benéfica para eles? A resposta é _revogação_. Um exemplo simplificado no BIP 112, que oferece um dos trampolins para o Lightning, mostra o processo. Nós damos ao participante que seria prejudicado pela reversão de uma transação revogada a capacidade de retirar os fundos ele mesmo se o outro participante tentar usar ilegitimamente a transação revogada.
|
||||||
|
|
||||||
|
Por exemplo, suponha que Alice e Bob atualizem a transação de compromisso para dar mais fundos a Bob (Ou seja, Alice enviou fundos a Bob por meio da rede Lightning). Eles assinam parcialmente novas transações, mas cada um também oferece seu próprio ```revokeCode``` para as transações anteriores. Isso efetivamente garante que nenhum deles irão publicar as transações anteriores, porque isso permitiria que a contraparte reivindicasse os fundos anteriores.
|
||||||
|
|
||||||
|
Então, como se parece a transação antiga? Foi uma transação de compromisso mostrando fundos destinados a Alice, antes que ela os desse a Bob. Ele tinha um script de bloqueio da seguinte maneira:
|
||||||
|
```
|
||||||
|
OP_HASH160
|
||||||
|
<revokeHash>
|
||||||
|
OP_EQUAL
|
||||||
|
IF
|
||||||
|
<pubKeyBob>
|
||||||
|
ELSE
|
||||||
|
<+24Hours>
|
||||||
|
OP_CHECKSEQUENCEVERIFY
|
||||||
|
OP_DROP
|
||||||
|
<pubKeyAlice>
|
||||||
|
ENDIF
|
||||||
|
OP_CHECKSIG
|
||||||
|
```
|
||||||
|
O bloco ```ELSE``` é onde Alice conseguiu os fundos, após um atraso de 24 horas. No entanto, agora foi substituído. Afinal, esse é o ponto principal de um canal de pagamento na Lightning. Nesta situação, esta transação nunca deve ser publicada. Bob não tem incentivo para isso porque ele tem uma transação mais recente, que o beneficia mais porque ele recebeu parte dos fundos de Alice. Alice também não tem incentivo, porque ela perde o dinheiro se tentar retirar mais do que deve, por conta do ```revokeCode```. Assim, ninguém coloca a transação na blockchain e as transações offchain continuam.
|
||||||
|
|
||||||
|
Vale a pena explorar como esse script funcionaria em uma variedade de situações, a maioria das quais envolve Alice tentando trapacear, revertendo para a transação mais antiga, que descreve os fundos _antes_ da Alice enviar os satoshis para Bob.
|
||||||
|
|
||||||
|
#### Executando o script de bloqueio para enganar Alice, com código de revogação
|
||||||
|
|
||||||
|
Alice poderia tentar usar o código de revogação que ela deu a Bob para reivindicar imediatamente os fundos. Ela escreve um script de bloqueio de ```<sigAlice> <revokeCode>```:
|
||||||
|
```
|
||||||
|
Script: <sigAlice> <revokeCode> OP_HASH160 <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
|
||||||
|
Stack: [ ]
|
||||||
|
|
||||||
|
Script: OP_HASH160 <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
|
||||||
|
Stack: [ <sigAlice> <revokeCode> ]
|
||||||
|
|
||||||
|
Script: <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
|
||||||
|
Running: <revokeCode> OP_HASH160
|
||||||
|
Stack: [ <sigAlice> <revokeHash> ]
|
||||||
|
|
||||||
|
Script: OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
|
||||||
|
Stack: [ <sigAlice> <revokeHash> <revokeHash> ]
|
||||||
|
|
||||||
|
Script: IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
|
||||||
|
Running: <revokeHash> <revokeHash> OP_EQUAL
|
||||||
|
Stack: [ <sigAlice> True ]
|
||||||
|
```
|
||||||
|
O ```OP_EQUAL``` alimenta a instrução ```IF```. Como Alice usa o ```revokeCode```, ela entra no caminho que permite gatar os fundos imediatamente, reduzindo o resto do script para ```<pubKeyBob>``` (dentro da condicional) e com o ```OP_CHECKSIG``` (depois).
|
||||||
|
```
|
||||||
|
Script: <pubKeyBob> OP_CHECKSIG
|
||||||
|
Running: True IF
|
||||||
|
Stack: [ <sigAlice> ]
|
||||||
|
```
|
||||||
|
Maldição! Apenas Bob pode assinar imediatamente usando o ```redeemCode```!
|
||||||
|
```
|
||||||
|
Script: OP_CHECKSIG
|
||||||
|
Stack: [ <sigAlice> <pubKeyBob> ]
|
||||||
|
|
||||||
|
Script:
|
||||||
|
Running: <sigAlice> <pubKeyBob> OP_CHECKSIG
|
||||||
|
Stack: [ False ]
|
||||||
|
```
|
||||||
|
#### Executando o script de bloqueio para enganar Alice, sem código de revogação
|
||||||
|
|
||||||
|
E daí se Alice tentar usar sua própria assinatura, sem o ```revokeCode```? Ela usa o seguinte script de desbloqueio ```<sigAlice> <notRevokeCode>```.
|
||||||
|
```
|
||||||
|
Script: <sigAlice> 0 OP_HASH160 <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
|
||||||
|
Stack: [ ]
|
||||||
|
|
||||||
|
Script: OP_HASH160 <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
|
||||||
|
Stack: [ <sigAlice> 0 ]
|
||||||
|
|
||||||
|
Script: <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
|
||||||
|
Running: 0 OP_HASH160
|
||||||
|
Stack: [ <sigAlice> <0Hash> ]
|
||||||
|
|
||||||
|
Script: OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
|
||||||
|
Stack: [ <sigAlice> <0Hash> <revokeHash> ]
|
||||||
|
|
||||||
|
Script: IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
|
||||||
|
Running: <0Hash> <revokeHash> OP_EQUAL
|
||||||
|
Stack: [ <sigAlice> False ]
|
||||||
|
```
|
||||||
|
Agora reduzimos para a instrução ```ELSE``` e o que vem depois da condicional:
|
||||||
|
```
|
||||||
|
Script: <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> OP_CHECKSIG
|
||||||
|
Running: False IF
|
||||||
|
Stack: [ <sigAlice> ]
|
||||||
|
|
||||||
|
Script: OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> OP_CHECKSIG
|
||||||
|
Stack: [ <sigAlice> <+24Hours> ]
|
||||||
|
```
|
||||||
|
E então Alice é frustrada de novo porque 24 horas não se passaram!
|
||||||
|
```
|
||||||
|
Script: OP_DROP <pubKeyAlice> OP_CHECKSIG
|
||||||
|
Running: <+24Hours> OP_CHECKSEQUENCEVERIFY
|
||||||
|
Stack: [ <sigAlice> <+24Hours> ] — Script EXITS
|
||||||
|
```
|
||||||
|
#### Executando o script de bloqueio para a vitima, o Bob
|
||||||
|
|
||||||
|
O que isso significa é que Bob tem 24 horas para recuperar os fundos se Alice tentar trapacear, usando o ```<revokeCode>``` e a assinatura como script de desbloqueio:
|
||||||
|
```
|
||||||
|
Script: <SigBob> <revokeCode> OP_HASH160 <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
|
||||||
|
Stack: [ ]
|
||||||
|
|
||||||
|
Script: OP_HASH160 <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
|
||||||
|
Stack: [ <SigBob> <revokeCode> ]
|
||||||
|
|
||||||
|
Script: <revokeHash> OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
|
||||||
|
Running: <revokeCode> OP_HASH160
|
||||||
|
Stack: [ <SigBob> <revokeHash> ]
|
||||||
|
|
||||||
|
Script: OP_EQUAL IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
|
||||||
|
Stack: [ <SigBob> <revokeHash> <revokeHash> ]
|
||||||
|
|
||||||
|
Script: IF <pubKeyBob> ELSE <+24Hours> OP_CHECKSEQUENCEVERIFY OP_DROP <pubKeyAlice> ENDIF OP_CHECKSIG
|
||||||
|
Running: <revokeHash> <revokeHash> OP_EQUAL
|
||||||
|
Stack: [ <SigBob> True ]
|
||||||
|
|
||||||
|
Script: <pubKeyBob> OP_CHECKSIG
|
||||||
|
Running: True IF
|
||||||
|
Stack: [ <SigBob> ]
|
||||||
|
|
||||||
|
Script: OP_CHECKSIG
|
||||||
|
Stack: [ <SigBob> <pubKeyBob> ]
|
||||||
|
|
||||||
|
Script:
|
||||||
|
Running: <SigBob> <pubKeyBob> OP_CHECKSIG
|
||||||
|
Stack: [ True ]
|
||||||
|
```
|
||||||
|
#### Executando o Script de Bloqueio para a Virtuosa Alice
|
||||||
|
|
||||||
|
Todas as transações de confirmação de Alice são bloqueadas com este mesmo script de bloqueio, quer tenham sido revogadas ou não. Isso significa que a transação de confirmação mais recente, que é a válida atualmente, também está bloqueada com ela. Alice nunca enviou uma transação mais recente para Bob e, portanto, nunca enviou a ele o ```revokeCode``` anterior.
|
||||||
|
|
||||||
|
Nessa situação, ela poderia publicar virtuosamente a transação, fechando o canal. Ela coloca a transação na cadeia e espera 24 horas. Bob não pode fazer nada a respeito porque não possui o código de recuperação. Então, após a espera, Alice recupera os fundos. Bob pode fazer a mesma coisa com sua própria transação final.
|
||||||
|
|
||||||
|
### Bloqueando com Contratos de Bloqueio de Tempo com Hash
|
||||||
|
|
||||||
|
As Transações de Compromisso Revogável foram apenas um trampolim para a Lightning. A Lightning Network real usa um mecanismo mais complexo chamado [Contrato de Bloqueio de Tempo com Hash (ou no inglês, Hashed TimeLock Contract)](https://en.bitcoin.it/wiki/Hashed_Timelock_Contracts) ou mais conhecido como HTLC.
|
||||||
|
|
||||||
|
O principal objetivo dos HTLCs é criar uma rede abrangente de participantes. As transações não são mais apenas entre um par de participantes que entraram na rede juntos, mas agora podem ser várias pessoas que não estão associadas diretamente. Quando os fundos são enviados, uma string de transações é criada, cada uma delas bloqueada com um ```secretHash```. Quando o ```secretCode``` correspondente é revelado, toda a sequência de transações pode ser gasta. Isso é o que permite que transações singulares realmente se tornem uma rede.
|
||||||
|
|
||||||
|
Também há um pouco mais de complexidade nos scripts de bloqueio da Lightning Network. Existem bloqueios separados para o remetente e o destinatário de cada transação que são mais amplamente divergentes do que as diferentes transações de compromisso mencionadas na seção anterior. Vamos mostrar os dois, para demonstrar o poder desses scripts de bloqueio, mas não vamos explicar como eles interagem entre si.
|
||||||
|
|
||||||
|
#### Bloqueando a transação do destinatário
|
||||||
|
|
||||||
|
Mais uma vez, vamos começar a olhar para a transação de compromisso da Alice, que mostra os fundos que ela recebeu:
|
||||||
|
```
|
||||||
|
OP_HASH160
|
||||||
|
OP_DUP
|
||||||
|
<secretHash>
|
||||||
|
OP_EQUAL
|
||||||
|
IF
|
||||||
|
<+24Hours>
|
||||||
|
OP_CHECKSEQUENCEVERIFY
|
||||||
|
OP_2DROP
|
||||||
|
<pubKeyAlice>
|
||||||
|
ELSE
|
||||||
|
<revokeHash>
|
||||||
|
OP_EQUAL
|
||||||
|
OP_NOTIF
|
||||||
|
<Date>
|
||||||
|
OP_CHECKLOCKTIMEVERIFY
|
||||||
|
OP_DROP
|
||||||
|
ENDIF
|
||||||
|
<pubKeyBob>
|
||||||
|
ENDIF
|
||||||
|
OP_CHECKSIG
|
||||||
|
```
|
||||||
|
A chave para esses novos HTLCs é o ```secretHash```, que dissemos que é o que permite que uma transação se estenda pela rede. Quando a transação vai do remetente ao destinatário pretendido, o ```secretCode``` é revelado, o que permite que todos os participantes criem um ```secretHash``` e desbloqueiem toda a rede de pagamentos.
|
||||||
|
|
||||||
|
Após o ```secretCode``` ter sido revelado, o caminho do ```IF``` é utilizado. Alice pode reivindicar os fundos 24 horas após a transação ser colocada na rede Bitcoin.
|
||||||
|
|
||||||
|
No entanto, também há a oportunidade de Bob recuperar os fundos, que aparecem no caminho do ```ELSE```. Ele pode fazer isso se a transação foi revogada, mas Alice a coloca na blockchain de qualquer maneira, _ou se_ um tempo limite absoluto ocorrer.
|
||||||
|
|
||||||
|
#### Bloqueando a transação do remetente
|
||||||
|
|
||||||
|
Este é o script de bloqueio de transação de confirmação alternativo usado pelo remetente:
|
||||||
|
```
|
||||||
|
OP_HASH160
|
||||||
|
OP_DUP
|
||||||
|
<secretHash>
|
||||||
|
OP_EQUAL
|
||||||
|
OP_SWAP
|
||||||
|
<revokeHash>
|
||||||
|
OP_EQUAL
|
||||||
|
OP_ADD
|
||||||
|
IF
|
||||||
|
<pubKeyAlice>
|
||||||
|
ELSE
|
||||||
|
<Date>
|
||||||
|
OP_CHECKLOCKTIMEVERIFY
|
||||||
|
<+24Hours>
|
||||||
|
OP_CHECKSEQUENCEVERIFY
|
||||||
|
OP_2DROP
|
||||||
|
<pubKeyBob>
|
||||||
|
ENDIF
|
||||||
|
OP_CHECKSIG
|
||||||
|
```
|
||||||
|
A parte inicial do script é bastante inteligente e vale a pena executá-la:
|
||||||
|
```
|
||||||
|
Initial Script: <suppliedCode> OP_HASH160 OP_DUP <secretHash> OP_EQUAL OP_SWAP <revokeHash> OP_EQUAL OP_ADD
|
||||||
|
Stack: [ ]
|
||||||
|
|
||||||
|
Initial Script: OP_HASH160 OP_DUP <secretHash> OP_EQUAL OP_SWAP <revokeHash> OP_EQUAL OP_ADD
|
||||||
|
Stack: [ <suppliedCode> ]
|
||||||
|
|
||||||
|
Initial Script: OP_DUP <secretHash> OP_EQUAL OP_SWAP <revokeHash> OP_EQUAL OP_ADD
|
||||||
|
Running: <suppliedCode> OP_HASH160
|
||||||
|
Stack: [ <suppliedHash> ]
|
||||||
|
|
||||||
|
Initial Script: <secretHash> OP_EQUAL OP_SWAP <revokeHash> OP_EQUAL OP_ADD
|
||||||
|
Running: <suppliedHash> OP_DUP
|
||||||
|
Stack: [ <suppliedHash> <suppliedHash> ]
|
||||||
|
|
||||||
|
Initial Script: OP_EQUAL OP_SWAP <revokeHash> OP_EQUAL OP_ADD
|
||||||
|
Stack: [ <suppliedHash> <suppliedHash> <secretHash> ]
|
||||||
|
|
||||||
|
Initial Script: OP_SWAP <revokeHash> OP_EQUAL OP_ADD
|
||||||
|
Running: <suppliedHash> <secretHash> OP_EQUAL
|
||||||
|
Stack: [ <suppliedHash> <wasItSecretHash?> ]
|
||||||
|
|
||||||
|
Initial Script: <revokeHash> OP_EQUAL OP_ADD
|
||||||
|
Running: <suppliedHash> <wasItSecretHash?> OP_SWAP
|
||||||
|
Stack: [ <wasItSecretHash?> <suppliedHash> ]
|
||||||
|
|
||||||
|
Initial Script: OP_EQUAL OP_ADD
|
||||||
|
Stack: [ <wasItSecretHash?> <suppliedHash> <revokeHash> ]
|
||||||
|
|
||||||
|
Initial Script: OP_ADD
|
||||||
|
Running: <suppliedHash> <revokeHash> OP_EQUAL
|
||||||
|
Stack: [ <wasItSecretHash?> <wasItRevokeHash?> ]
|
||||||
|
|
||||||
|
Initial Script:
|
||||||
|
Running: <wasItSecretHash?> <wasItRevokeHash?> OP_ADD
|
||||||
|
Stack: [ <wasItSecretOrRevokeHash?> ]
|
||||||
|
```
|
||||||
|
A execução do script revela que as verificações iniciais, acima do ```IF```/```ELSE```/```ENDIF```, determinam se o hash era _tanto_ o ```secretCode``` _ou_ o ```revokeCode```. Nesse caso, Alice pode pegar os fundos no primeiro bloco. Do contrário, Bob pode pegar os fundos, mas somente depois que Alice tiver sua chance e depois que o tempo limite de 24 horas e o tempo limite absoluto tiverem passado.
|
||||||
|
|
||||||
|
#### Compreendendo os HTLCs
|
||||||
|
|
||||||
|
Os HTLCs são bastante complexos e esta seção não tenta explicar todas as suas complexidades. A [visão geral](https://rusty.ozlabs.org/?p=462) escrita por Rusty Russell explica bem mais, e há ainda mais detalhes no seu artigo [Deployable-lightning](https://github.com/ElementsProject/lightning/blob/master/doc/deployable-lightning.pdf). Mas não se preocupe se algumas das complexidades ainda ficarem meio nebulosas para nós, especialmente sobre o funcionamento das inter-relações dos dois scripts.
|
||||||
|
|
||||||
|
Para os fins deste tutorial, existem duas lições importantes em relação aos HTLCs:
|
||||||
|
|
||||||
|
* Entender que uma estrutura muito complexa como um HTLC pode ser criada usando o Script do Bitcoin;
|
||||||
|
* Analisar como executar cada um dos scripts HTLC.
|
||||||
|
|
||||||
|
Vale a pena executar cada um dos dois scripts HTLC em cada uma de permutações, um item da pilha de cada vez.
|
||||||
|
|
||||||
|
## Resumo: Expandindo o Bitcoin com os Scripts
|
||||||
|
|
||||||
|
Estamos encerrando o exame dos scripts do bitcoin com uma visão de como eles podem ser realmente poderosos. Com 20 opcodes ou menos, um script Bitcoin pode formar a base de todo um canal de pagamento fora da blockchain. Da mesma forma, sidechains com conexões bidirecionais são o produto de menos de vinte opcodes, como também observado brevemente em [BIP 112](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki).
|
||||||
|
|
||||||
|
Se já vimos a funcionalidade complexa do Bitcoin ou os sistemas adjacentes ao Bitcoin, eles provavelmente foram construídos em scripts Bitcoin. E agora temos todas as ferramentas para fazer o mesmo.
|
||||||
|
|
||||||
|
## O Que Vem Depois?
|
||||||
|
|
||||||
|
Vamos ficar "Usando o Tor" no [Capítulo 14: Usando o Tor](14_0_Using_Tor.md).
|
||||||
|
|
||||||
|
Ou, se preferir, existem dois caminhos alternativos:
|
||||||
|
|
||||||
|
Se quiser manter o foco no Bitcoin, vá para o "Programando com o RPC" no [Capítulo Quinze: Conversando com Bitcoind usando C](15_0_Talking_to_Bitcoind.md).
|
||||||
|
|
||||||
|
Ou, se quisermos manter o foco na linha de comando porque não somos programadores, podemos pular para o [Capítulo Dezoito: Entendendo Nossa Configuração da Lightning](18_0_Understanding_Your_Lightning_Setup.md) para continuar nossa aula usando a linha de comando com a Lightning Network.
|
Loading…
x
Reference in New Issue
Block a user