Merge pull request #298 from KoreaComK/chapter-08

Chapter 08 - Translated by @koreacomk reviewed by @hgrams
This commit is contained in:
Shannon Appelcline 2021-07-27 08:46:28 -10:00 committed by GitHub
commit ee82235f99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 278 additions and 0 deletions

View File

@ -38,6 +38,7 @@ No entanto, não podemos criar um multisig com os endereços, pois esses são os
Esta informação está disponível facilmente com o comando ```getaddressinfo```.
Na máquina remota, que assumimos aqui que é ```machine2```, podemos obter as informações em uma lista.
```
machine2$ bitcoin-cli -named getaddressinfo address=$address2

View File

@ -0,0 +1,21 @@
# Capítulo 8: Expandindo Transações de Bitcoin de Outras Maneiras
A definição de transações básicas descrita no [Capítulo Seis](06_0_Expanding_Bitcoin_Transactions_Multisigs.md) diz que enviamos os _fundos_ _imediatamente_, mas esses são os dois elementos que podem ser alterados. Esta seção final sobre _Expandindo transações de Bitcoin_ fala sobre como enviar coisas que não sejam moedas e como fazer isso em um momento diferente do atual.
## Objetivos deste Capítulo
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
* Criar transações com Locktimes;
* Criar transações com dados.
Os objetivos secundários incluem a capacidade de:
* Compreender os diferentes tipos de Timelocks;
* Planejar usando o poder do Locktime;
* Planejar usando o poder de OP_RETURN.
## Tabela de conteúdo
* [Seção Um: Enviando uma transação com Locktime](08_1_Sending_a_Transaction_with_a_Locktime.md)
* [Seção Dois: Enviando uma transação com dados](08_2_Sending_a_Transaction_with_Data.md)

View File

@ -0,0 +1,135 @@
# 8.1: Enviando uma transação com Locktime
Os capítulos anteriores mostraram duas maneiras diferentes de enviar fundos de várias máquinas e para vários destinatários. Mas, existem duas outras maneiras de alterar fundamentalmente as transações básicas. A primeira delas é variar o tempo, escolhendo um tempo de bloqueio ou mais conhecido pela expressão em inglês locktime. Isso nos dá a capacidade de enviar transações brutas em algum momento no futuro.
## Entendendo como o Locktime funciona
Ao criar uma transação do tipo locktime, a bloqueamos com um número que representa a altura do bloco (se for um número pequeno) ou um carimbo de data/hora usando o padrão UNIX (se for um número grande). Isso informa à rede Bitcoin que a transação não pode ser colocada no bloco até que o tempo especificado chegue ou a blockchain tenha atingido a altura especificada.
> :book: _O que é a altura do bloco?_ É a contagem total de blocos na blockchain, contado desde o bloco gênese até o último bloco minerado da blockchain do Bitcoin.
Quando uma transação do tipo locktime está esperando para entrar em um bloco, ela pode ser cancelada. Isso significa que ainda não foi atingido a altura ou a data necessária. Na verdade, a capacidade de cancelar é todo o propósito de uma transação do tipo locktime.
> :book: _O que é nLockTime?_ É a mesma coisa que o locktime. Mais especificamente, é como o locktime é chamado internamente no código-fonte do Bitcoin Core.
> :book: _O que é o Timelock?_ O Locktime é apenas uma maneira de bloquear transações Bitcoin até algum ponto no futuro; o coletivo desses métodos são chamados de timelocks. O locktime é o método de timelock mais básico. Ele bloqueia uma transação inteira com um tempo absoluto e está disponível através do ```bitcoin-cli``` (é por isso que é o único timelock coberto nesta seção). Um método paralelo, que bloqueia uma transação com um tempo relativo, é definido no [BIP 68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki) e abordado na seção [§11.3: Usando CSV em Scripts](11_3_Using_CSV_in_Scripts.md).
> O Bitcoin Script capacita ainda mais os dois tipos de timelocks, permitindo o bloqueio de saídas individuais ao invés de toda a transação. Os timelocks absolutos (como Locktime) estão vinculados ao opcode Script OP_CHECKLOCKTIMEVERIFY, que é definido no [BIP 65](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki) e que será estudado na seção [§11.2: Usando CLTV em Scripts](11_2_Using_CLTV_in_Scripts.md), enquanto os timelocks relativos (como o Timelock) estão vinculados ao opcode de Script OP_CHECKSEQUENCEVERIFY, que é definido no [BIP 112](https://github.com/bitcoin/bips /blob/master/bip-0112.mediawiki) e que também será abordado na seção [§11.3](11_3_Using_CSV_in_Scripts.md).
## Criando uma transação de Locktime
Para criar uma transação com locktime, precisamos primeiro determinar como definiremos o tempo.
### Descobrindo nosso tempo de bloqueio usando o carimbo de data/hora do UNIX
Provavelmente, iremos definir com muito mais frequência o nosso tempo de bloqueio usando um carimbo de data/hora do tipo UNIX que representa uma data e hora específica. Podemos calcular um carimbo de data/hora UNIX usando sites que fazem essa conversão, como o [UNIX Time Stamp](http://www.unixtimestamp.com/) ou o [Epoch Convertor](https://www.epochconverter.com/). No entanto, seria melhor [escrevermos nosso próprio script](https://www.epochconverter.com/#code) em nossa máquina local, para que saibamos que o carimbo de data/hora UNIX que recebemos está correto (lembre-se, não confie, verifique). Se não fizermos isso, pelo menos seria interessante verificar em dois sites diferentes para ter a certeza que tudo está correto.
> :book: _Por que iríamos usar um carimbo de data/hora do UNIX?_ O uso de um carimbo de data/hora do UNIX facilita a vinculação definitiva de uma transação a um horário específico, sem se preocupar se a velocidade de criação do bloco mudara drasticamente até lá. Principalmente se estivermos criando um locktime em um futuro distante, é a coisa mais segura a ser feita. Entretanto, utilizar esse método é mais intuitivo, criando uma correlação direta entre alguma data do calendário e a hora em que a transação pode ser colocada na blockchain do Bitcoin.
> :warning: **AVISO:** O Locktime com carimbos de data/hora tem menos flexibilidade, pois a liberação de blocos não é regular e os tempos de bloqueio podem ser duas horas antes do tempo real, então um locktime significa "mais ou menos nesta data e nesta hora".
### Descobrir o locktime usando a altura do bloco
Como alternativa, podemos definir o locktime usando um número menor, que representa a altura de um bloco. Para calcular a altura do bloco futuro, precisamos primeiro saber qual é a altura do bloco atual. O ```bitcoin-cli getblockcount``` nos dirá a altura do bloco atual baseado na blockchain da máquina local. Podemos verificar um explorador do Bitcoin como a [mempool.space](https://mempool.space/).
Depois de descobrir a altura atual, podemos decidir até que ponto no futuro iremos configurar o locktime. É importante lembrar que, em média, um novo bloco será criado a cada 10 minutos. Então, por exemplo, se quisermos definir o tempo de bloqueio para uma semana no futuro, devemos escolher uma altura de bloco que é _6 x 24 x 7 = 1.008 blocos_ depois do atual.
> :book: _Por que eu usaria a altura do bloco?_ Ao contrário dos carimbos de data/hora, não existe confusão nas alturas de bloco. Se definirmos uma altura de bloco de 120.000 para o nosso locktime, não haverá absolutamente nenhuma maneira dele entrar no bloco 119.999. Isso pode tornar o controle no código mais fácil ao manipular nossa transação com locktime. A desvantagem é que não podemos ter certeza de quando exatamente será o locktime.
> :warning: **AVISO:** Se desejamos definir um locktime usando a altura do bloco, devemos definir o tempo de bloqueio para menos de 500 milhões. Se definirmos como sendo 500 milhões ou mais, nosso número será interpretado como um carimbo de data/hora. Como o carimbo de data/hora usando o padrão UNIX com valor de 500 milhões era dia 5 de novembro de 1985, provavelmente significa que nossa transação será permitida a qualquer momento a entrar na blockchain.
## Escrevendo a transação
Depois de descobrir o locktime, tudo o que precisamos fazer é escrever uma transação bruta padrão, com uma terceira variável para o ```locktime```:
```
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.001, "'$changeaddress'": 0.00095 }''' locktime=1774650)
```
Podemos observar que o uso do ```locktime``` está abaixo dos 500 milhões, o que significa que ele define a altura do bloco. Nesse caso, são apenas alguns blocos além da altura do bloco atual no momento em que este livro foi escrito, com o objetivo de exemplificar como o locktime funciona sem ficar sentado por muito tempo para esperar para ver o que acontece.
A transação criada tem mais ou menos essa aparência:
```
$ bitcoin-cli -named decoderawtransaction hexstring=$rawtxhex
{
"txid": "ba440b1dd87a7ccb6a200f087d2265992588284eed0ae455d0672aeb918cf71e",
"hash": "ba440b1dd87a7ccb6a200f087d2265992588284eed0ae455d0672aeb918cf71e",
"version": 2,
"size": 113,
"vsize": 113,
"weight": 452,
"locktime": 1774650,
"vin": [
{
"txid": "0ad9fb6992dfe4ea90236b69852b3605c0175633b32996a486dcd0b2e739e385",
"vout": 1,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967294
}
],
"vout": [
{
"value": 0.00100000,
"n": 0,
"scriptPubKey": {
"asm": "0 f333554cc0830d03a9c1f26758e2e7e0f155539f",
"hex": "0014f333554cc0830d03a9c1f26758e2e7e0f155539f",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1q7ve42nxqsvxs82wp7fn43ch8urc425ul5um4un"
]
}
},
{
"value": 0.00095000,
"n": 1,
"scriptPubKey": {
"asm": "0 a37718a3510958112b6a766e0023ff251b6c2bfb",
"hex": "0014a37718a3510958112b6a766e0023ff251b6c2bfb",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1q5dm33g63p9vpz2m2wehqqglly5dkc2lmtmr98d"
]
}
}
]
}
```
Observe que o número de sequência (```4294967294```) é menor que ```0xffffffff```. Esta é uma sinalização necessária para mostrar que a transação inclui um locktime. Também é feito automaticamente pelo ```bitcoin-cli```. Se o número da sequência for definido como ```0xffffffff```, nosso locktime será ignorado.
> :information_source: **NOTA - SEQUÊNCIA:** Este é o segundo uso do valor ```nSequence``` em Bitcoin. Tal como acontece com o RBF, o ```nSequence``` é novamente usado como um opt-in, desta vez para o uso do locktime. O 0xffffffff-1 (4294967294) é o valor para sinalizar o tempo de bloqueio porque proíbe propositadamente o uso do RBF (que requer uma ```nSequence < 0xffffffff-1```) e do timelock relativo (que requer ```nSequence < 0xf0000000```), os outros dois usos do ```nSequence```. Se definirmos o ```nSequence``` abaixo de ```0xf0000000```, então também teremos um timelock relativo em nossa transação, o que provavelmente não é o desejado.
> :warning: **ATENÇÃO:** Se estivermos criando uma transação bruta com locktime por algum outro meio que não seja o ```bitcoin-cli```, teremos que definir a sequência para um valor menor que ```0xffffffff``` manualmente.
## Enviando a transação
Agora, já estamos familiarizados com a parte final, que é enviar a transação para a rede:
```
$ signedtx=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex | jq -r '.hex')
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
error code: -26
error message:
non-final
```
Eita! Que erro é esse!?
Desde 2013, geralmente não podemos colocar a transação usando um timelock na mempool até que nosso bloqueio tenha expirado. No entanto, ainda podemos guardar nossa transação, ocasionalmente reenviando-a para a rede Bitcoin até que ela seja aceita na mempool. Uma outra opção é enviarmos a transação assinada (```$signedtx```) ao destinatário, para que ele possa colocá-la na mempool quando o tempo de bloqueio expirar.
Assim que o bloqueio de tempo expirar, qualquer pessoa pode enviar a transação assinada para a rede, e o destinatário receberá o saldo como esperado... Desde que a transação não tenha sido cancelada.
## Cancelando uma transação com timelock
Cancelar uma transação de tempo de bloqueio é _muito_ simples: precisamos apenas enviar uma nova transação usando pelo menos um dos UTXOs.
## Resumo: Enviando uma transação com Locktime
O Locktime oferece uma maneira de criar uma transação que _precisa_ esperar e que _não será aceita_ até que um determinado bloco chegue ou um momento pré-definido passe. Enquanto isso, ela pode ser cancelada simplesmente reutilizando um dos UTXO da transação.
> :fire: _Qual é o poder do locktime?_ O poder do locktime pode não ser imediatamente óbvio devido à capacidade de cancelá-lo com facilidade. No entanto, é outra das bases dos Smart Contracts, pois tem muita utilidade em uma variedade de aplicações de custódia ou contratuais. Por exemplo, considere uma situação em que um terceiro está fazendo o hold das nossas moedas. Para garantir a devolução dos nossos bitcoins caso o custodiante algum dia desaparecesse, ele poderia produzir uma transação com timelock para devolver as moedas para nós e, em seguida, atualizar isso de vez em quando com uma transação mais nova, no futuro. Se em algum momento ele não enviar a nova transação, as moedas retornarão para nós quando o timelock mais novo expirar. O timelock pode ser aplicado de forma semelhante a uma rede de pagamento, onde a rede mantém moedas enquanto estão sendo trocadas pelos participantes da rede. Finalmente, os timelocks oferecem um exemplo de contrato mais complexo, em que os pagamentos são enviados a várias pessoas. Esses pagamentos seriam baseados em transações com timelocks e seriam continuamente atualizados enquanto o proprietário continuasse a mostrar sinais de vida. (O fator unificador de todas essas aplicações é, obviamente, a _confiança_. Transações simples usando timelocks só funcionam se o detentor das moedas puder ser confiável para enviá-las sob as condições apropriadas).
## O que vem depois?
Vamos continuar "Expandindo transações de Bitcoin" na seção [§8.2: Enviando uma transação com dados](08_2_Sending_a_Transaction_with_Data.md).

View File

@ -0,0 +1,121 @@
# 8.2: Enviando uma transação com dados
O último jeito de variar a forma como enviamos uma transação simples é usar a transação para enviar dados ao invés de saldos (ou, na prática, enviar algo além dos saldos). Isso nos dá a capacidade de inserir informações na blockchain. Isso é feito através de um comando especial, o ```OP_RETURN```.
A pegadinha? Só podemos armazenar 80 bytes por vez!
## Criando nossos dados
A primeira coisa que precisamos fazer é criar os 80 bytes (ou menos) de dados que iremos gravar no nosso ```OP_RETURN```. Isso pode ser tão simples quanto preparar uma mensagem ou podemos usar o hash dos dados existentes. Por exemplo, o ```sha256sum``` produz 256 bits de dados, que são apenas 32 bytes, bem abaixo do nosso limite:
```
$ sha256sum contract.jpg
b9f81a8919e5aba39aeb86145c684010e6e559b580a85003ae25d78237a12e75 contract.jpg
$ op_return_data="b9f81a8919e5aba39aeb86145c684010e6e559b580a85003ae25d78237a12e75"
```
> :book: _O que é um OP_RETURN?_ Todas as transações Bitcoin são construídas com scripts que iremos ver mais a fundo no próximo capítulo. O ```OP_RETURN``` é um script simples que define o OUTPUT como sendo inválido. A convenção resultou no uso dele para incorporar dados na blockchain.
## Separando algumas moedas
Nosso objetivo ao criar uma transação de dados não é enviar dinheiro para alguém, mas colocar dados dentro da blockchain. No entanto, _devemos_ gastar algumas moedas para fazer isso. Só precisamos usar um endereço de troco como sendo nosso _ único_ destinatário. Em seguida, podemos identificar um UTXO e enviá-lo para nosso endereço de troco, sem esquecer da taxa de transação, ao mesmo tempo que usamos a mesma transação para criar um OP_RETURN.
Esta é a configuração padrão:
```
$ bitcoin-cli listunspent
[
{
"txid": "854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42",
"vout": 0,
"address": "tb1q6kgsjxuqwj3rwhkenpdfcjccalk06st9z0k0kh",
"scriptPubKey": "0014d591091b8074a2375ed9985a9c4b18efecfd4165",
"amount": 0.01463400,
"confirmations": 1392,
"spendable": true,
"solvable": true,
"desc": "wpkh([d6043800/0'/1'/12']02883bb5463e37d55252d8b3d5c2141b007b37c8a7db6211f75c955acc5ea325eb)#cjr03mru",
"safe": true
}
]
$ utxo_txid=$(bitcoin-cli listunspent | jq -r '.[0] | .txid')
$ utxo_vout=$(bitcoin-cli listunspent | jq -r '.[0] | .vout')
$ changeaddress=$(bitcoin-cli getrawchangeaddress)
```
## Escrevendo uma transação bruta
Agora podemos escrever uma nova transação bruta com duas saídas: uma é o nosso endereço de alteração para recuperar (a maior parte) do nosso saldo, a outra é um endereço de dados, que é uma variável ```bitcoin-cli``` para um OP_RETURN.
```
rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "data": "'$op_return_data'", "'$changeaddress'": 0.0146 }''')
```
Esta é a cara da transação:
```
{
"txid": "a600148ac3b05f0c774b8687a71c545077ea5dfb9677e5c6d708215053d892e8",
"hash": "a600148ac3b05f0c774b8687a71c545077ea5dfb9677e5c6d708215053d892e8",
"version": 2,
"size": 125,
"vsize": 125,
"weight": 500,
"locktime": 0,
"vin": [
{
"txid": "854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00000000,
"n": 0,
"scriptPubKey": {
"asm": "OP_RETURN b9f81a8919e5aba39aeb86145c684010e6e559b580a85003ae25d78237a12e75",
"hex": "6a20b9f81a8919e5aba39aeb86145c684010e6e559b580a85003ae25d78237a12e75",
"type": "nulldata"
}
},
{
"value": 0.01460000,
"n": 1,
"scriptPubKey": {
"asm": "0 998a9b0ed076bbdec1d88da4f475b9dde75e3620",
"hex": "0014998a9b0ed076bbdec1d88da4f475b9dde75e3620",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"tb1qnx9fkrksw6aaaswc3kj0gademhn4ud3q7cz4fm"
]
}
}
]
}
```
Como podemos observar, ela envia a maior parte do dinheiro de volta para o endereço de troco (`tb1qnx9fkrksw6aaaswc3kj0gademhn4ud3q7cz4fm`) menos a taxa de transação. Mais importante, a primeira saída mostra um OP_RETURN com os dados (`b9f81a8919e5aba39aeb86145c684010e6e559b580a85003ae25d78237a12e75`) logo depois.
## Enviando uma transação bruta
Assine a transação bruta e envie-a, e logo esse OP_RETURN será incorporado a blockchain!
## Verificando nosso OP_RETURN
Novamente, podemos olhar para essa transação usando um explorador da blockchain:
[https://mempool.space/pt/testnet/tx/a600148ac3b05f0c774b8687a71c545077ea5dfb9677e5c6d708215053d892e8/]
Podemos observar um aviso sobre os dados estarem em um "protocolo desconhecido". Se estivermos projetando algum uso regular dos dados ```OP_RETURN```, provavelmente iremos marcar com um prefixo especial, para marcar esse protocolo. Então, os dados OP_RETURN reais podem ser algo como "CONTRACTS3b110a164aa18d3a5ab064ba93fdce62". Este exemplo não usa um prefixo para evitar qualquer tipo de confusão com os espaços de dados.
## Resumo: Enviando uma transação com dados
Podemos usar o ```OP_RETURN``` para armazenar até 80 bytes de dados na blockchain. Fazemos isso com a palavra-código ```data``` em um ```vout```. Ainda precisaremos enviar alguns satoshinhos, mas basta enviá-lo de volta para um endereço de troco, retirando a taxa de transação.
> :fire: _Qual é o poder do OP_RETURN?_ O OP_RETURN abre novas possibilidades para o blockchain, porque podemos inserir dados que provam que certas coisas aconteceram em determinados momentos. Várias organizações estão pensando em usar os OP_RETURNs como prova de existência, para direitos autorais, para moedas coloridas e [para outros fins](https://en.bitcoin.it/wiki/OP_RETURN). Embora 80 bytes possam não parecer muito, pode ser bastante eficaz se os OP_RETURNs forem usados para armazenar hashes dos dados reais. Então, podemos provar a existência dos nossos dados digitais demonstrando que o hash deles corresponde ao hash na blockchain.
Observe que há alguma controvérsia sobre o uso da blockchain do Bitcoin usando-a para este fim.
## O que vem depois?
Vamos conhecer mais sobre o "Script no Bitcoin" no [Capítulo Nove: Apresentando os Scripts no Bitcoin](09_0_Introducing_Bitcoin_Scripts.md).