mirror of
https://github.com/ChristopherA/Learning-Bitcoin-from-the-Command-Line.git
synced 2025-06-08 00:16:26 +00:00
Merge branch 'portuguese-translation' into portuguese-translation
This commit is contained in:
commit
bb6dd6cfde
@ -2,7 +2,7 @@
|
||||
|
||||
If your Bitcoin transaction is stuck, and you're the sender, you can resend it using RBF (replace-by-fee). However, that's not all that RBF can do: it's generally a powerful and multipurpose feature that allows Bitcoin senders to recreate transactions for a variety of reasons.
|
||||
|
||||
> :warning: **VERSION WARNING:** This is an innovation from Bitcoin Core v 0.12.0,that reached full maturity in the Bitcoin Core wallet with Bitcoin Core v 0.14.0. Obviously, most people should be using it by now.
|
||||
> :warning: **VERSION WARNING:** This is an innovation from Bitcoin Core v 0.12.0, that reached full maturity in the Bitcoin Core wallet with Bitcoin Core v 0.14.0. Obviously, most people should be using it by now.
|
||||
|
||||
## Opt-In for RBF
|
||||
|
||||
|
@ -12,7 +12,7 @@ Bitcoin Scripts are run from left to right. That sounds easy enough, because it'
|
||||
|
||||
For example, if you were adding together "1" and "2", your Bitcoin Script for that would be `1 2 OP_ADD`, _not_ "1 + 2". Since we know that OP_ADD operator takes two inputs, we know that the two inputs before it are its operands.
|
||||
|
||||
> :warning: **WARNING:** Technically, everything in Bitcoin Script is an opcode, thus it would be most appropriate to record the above example as `OP_1 OP_2 OP_ADD`. In our examples, we don't worry about how the constants will be evaluated, as that's a topic of translation, as is explained in [§8.2: Building the Structure of P2SH](08_2_Building_the_Structure_of_P2SH.md). Some writers prefer to also leave the "OP" prefix off all operators, but we have opted not to.
|
||||
> :warning: **WARNING:** Technically, everything in Bitcoin Script is an opcode, thus it would be most appropriate to record the above example as `OP_1 OP_2 OP_ADD`. In our examples, we don't worry about how the constants will be evaluated, as that's a topic of translation, as is explained in [§8.2: Building the Structure of P2SH](10_2_Building_the_Structure_of_P2SH.md). Some writers prefer to also leave the "OP" prefix off all operators, but we have opted not to.
|
||||
|
||||
### Understand the Stack
|
||||
|
||||
|
@ -273,7 +273,7 @@ You now can sign transaction with the method `signRawTransactionWithKey`. This m
|
||||
Finally, sending requires the `sendRawTransaction` command:
|
||||
```java
|
||||
String sentRawTransactionID = rpcClient.sendRawTransaction(srTx.hex());
|
||||
System.out.println("Sent signedRawTx (txID): " + sentRawTransactionID);```
|
||||
System.out.println("Sent signedRawTx (txID): " + sentRawTransactionID);
|
||||
```
|
||||
|
||||
### Run Your Code
|
||||
|
388
Chapter_word_counts.ipynb
Normal file
388
Chapter_word_counts.ipynb
Normal file
File diff suppressed because one or more lines are too long
109
Chapter_word_counts.md
Normal file
109
Chapter_word_counts.md
Normal file
@ -0,0 +1,109 @@
|
||||
## Translatable word counts by chapter
|
||||
|
||||
Ignores code blocks and other non-translatable characters
|
||||
|
||||
Chapter|Word Count
|
||||
---|---
|
||||
01_0_Introduction.md|1144
|
||||
01_1_Introducing_Bitcoin.md|2735
|
||||
02_0_Setting_Up_a_Bitcoin-Core_VPS.md|226
|
||||
02_1_Setting_Up_a_Bitcoin-Core_VPS_with_StackScript.md|2746
|
||||
02_2_Setting_Up_Bitcoin_Core_Other.md|254
|
||||
03_0_Understanding_Your_Bitcoin_Setup.md|248
|
||||
03_1_Verifying_Your_Bitcoin_Setup.md|773
|
||||
03_2_Knowing_Your_Bitcoin_Setup.md|517
|
||||
03_3_Setting_Up_Your_Wallet.md|1699
|
||||
03_3__Interlude_Using_Command-Line_Variables.md|347
|
||||
03_4_Receiving_a_Transaction.md|1479
|
||||
03_5_Understanding_the_Descriptor.md|1349
|
||||
04_0_Sending_Bitcoin_Transactions.md|176
|
||||
04_1_Sending_Coins_The_Easy_Way.md|1195
|
||||
04_2_Creating_a_Raw_Transaction.md|1720
|
||||
04_2__Interlude_Using_JQ.md|1956
|
||||
04_3_Creating_a_Raw_Transaction_with_Named_Arguments.md|413
|
||||
04_4_Sending_Coins_with_a_Raw_Transaction.md|1024
|
||||
04_4__Interlude_Using_Curl.md|1643
|
||||
04_5_Sending_Coins_with_Automated_Raw_Transactions.md|614
|
||||
04_6_Creating_a_Segwit_Transaction.md|1172
|
||||
05_0_Controlling_Bitcoin_Transactions.md|149
|
||||
05_1_Watching_for_Stuck_Transactions.md|595
|
||||
05_2_Resending_a_Transaction_with_RBF.md|1372
|
||||
05_3_Funding_a_Transaction_with_CPFP.md|827
|
||||
06_0_Expanding_Bitcoin_Transactions_Multisigs.md|155
|
||||
06_1_Sending_a_Transaction_to_a_Multisig.md|1764
|
||||
06_2_Spending_a_Transaction_to_a_Multisig.md|1079
|
||||
06_3_Sending_an_Automated_Multisig.md|613
|
||||
07_0_Expanding_Bitcoin_Transactions_PSBTs.md|169
|
||||
07_1_Creating_a_Partially_Signed_Bitcoin_Transaction.md|1470
|
||||
07_2_Using_a_Partially_Signed_Bitcoin_Transaction.md|1393
|
||||
07_3_Integrating_with_Hardware_Wallets.md|2150
|
||||
08_0_Expanding_Bitcoin_Transactions_Other.md|139
|
||||
08_1_Sending_a_Transaction_with_a_Locktime.md|1483
|
||||
08_2_Sending_a_Transaction_with_Data.md|580
|
||||
09_0_Introducing_Bitcoin_Scripts.md|196
|
||||
09_1_Understanding_the_Foundation_of_Transactions.md|989
|
||||
09_2_Running_a_Bitcoin_Script.md|863
|
||||
09_3_Testing_a_Bitcoin_Script.md|1000
|
||||
09_4_Scripting_a_P2PKH.md|838
|
||||
09_5_Scripting_a_P2WPKH.md|845
|
||||
10_0_Embedding_Bitcoin_Scripts_in_P2SH_Transactions.md|170
|
||||
10_1_Understanding_the_Foundation_of_P2SH.md|1164
|
||||
10_2_Building_the_Structure_of_P2SH.md|1284
|
||||
10_3_Running_a_Bitcoin_Script_with_P2SH.md|323
|
||||
10_4_Scripting_a_Multisig.md|1016
|
||||
10_5_Scripting_a_Segwit_Script.md|750
|
||||
10_6_Spending_a_P2SH_Transaction.md|384
|
||||
11_0_Empowering_Timelock_with_Bitcoin_Scripts.md|108
|
||||
11_1_Understanding_Timelock_Options.md|557
|
||||
11_2_Using_CLTV_in_Scripts.md|1197
|
||||
11_3_Using_CSV_in_Scripts.md|1470
|
||||
12_0_Expanding_Bitcoin_Scripts.md|99
|
||||
12_1_Using_Script_Conditionals.md|1120
|
||||
12_2_Using_Other_Script_Commands.md|407
|
||||
13_0_Designing_Real_Bitcoin_Scripts.md|116
|
||||
13_1_Writing_Puzzle_Scripts.md|998
|
||||
13_2_Writing_Complex_Multisig_Scripts.md|996
|
||||
13_3_Empowering_Bitcoin_with_Scripts.md|1467
|
||||
14_0_Using_Tor.md|116
|
||||
14_1_Verifying_Your_Tor_Setup.md|1568
|
||||
14_2_Changing_Your_Bitcoin_Hidden_Services.md|434
|
||||
14_3_Adding_SSH_Hidden_Services.md|330
|
||||
15_0_Talking_to_Bitcoind.md|254
|
||||
15_1_Accessing_Bitcoind_with_C.md|1238
|
||||
15_2_Programming_Bitcoind_with_C.md|1427
|
||||
15_3_Receiving_Bitcoind_Notifications_with_C.md|650
|
||||
16_0_Programming_with_Libwally.md|333
|
||||
16_1_Setting_Up_Libwally.md|559
|
||||
16_2_Using_BIP39_in_Libwally.md|939
|
||||
16_3_Using_BIP32_in_Libwally.md|959
|
||||
16_4_Using_PSBTs_in_Libwally.md|989
|
||||
16_5_Using_Scripts_in_Libwally.md|785
|
||||
16_6_Using_Other_Functions_in_Libwally.md|655
|
||||
16_7_Integrating_Libwally_and_Bitcoin-CLI.md|1380
|
||||
17_0_Talking_to_Bitcoind_Other.md|286
|
||||
17_1_Accessing_Bitcoind_with_Go.md|547
|
||||
17_2_Accessing_Bitcoind_with_Java.md|821
|
||||
17_3_Accessing_Bitcoind_with_NodeJS.md|393
|
||||
17_4_Accessing_Bitcoind_with_Python.md|1158
|
||||
17_5_Accessing_Bitcoind_with_Rust.md|829
|
||||
17_6_Accessing_Bitcoind_with_Swift.md|1503
|
||||
18_0_Understanding_Your_Lightning_Setup.md|192
|
||||
18_1_Verifying_Your_Lightning_Setup.md|1294
|
||||
18_2_Knowing_Your_lightning_Setup.md|399
|
||||
18_2__Interlude_Accessing_a_Second_Lightning_Node.md|886
|
||||
18_3_Setting_Up_a_Channel.md|1173
|
||||
19_0_Using_Lightning.md|146
|
||||
19_1_Generate_a_Payment_Request.md|968
|
||||
19_2_Paying_a_Invoice.md|604
|
||||
19_3_Closing_a_Channel.md|848
|
||||
19_4_Lightning_Network_Review.md|626
|
||||
A0_Appendices.md|112
|
||||
A1_0_Understanding_Bitcoin_Standup.md|420
|
||||
A2_0_Compiling_Bitcoin_from_Source.md|412
|
||||
A3_0_Using_Bitcoin_Regtest.md|980
|
||||
CLA.md|495
|
||||
CONTRIBUTING.md|529
|
||||
LICENSE-CC-BY-4.0.md|2716
|
||||
README.md|1705
|
||||
TRANSLATING.md|686
|
||||
TOTAL|89069
|
@ -9,6 +9,13 @@ Learning Bitcoin from the Command Line is a tutorial for working with Bitcoin (a
|
||||
|
||||
_This tutorial assumes that you have some minimal background of how to use the command line interface. If not, there are many tutorials available, and I have one for Mac users at https://github.com/ChristopherA/intro-mac-command-line._
|
||||
|
||||
## Translations
|
||||
|
||||
* [Portuguese](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/tree/portuguese-translation/pt) — in process
|
||||
* [Spanish](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/tree/spanish-translation/es) - in process
|
||||
|
||||
If you'd like to make your own translation, please see [Contributing](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/tree/master#contributing), below.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
### PART ONE: PREPARING FOR BITCOIN
|
||||
|
@ -9,13 +9,17 @@ Thank you for your interest in translating Learning Bitcoin from the Command Lin
|
||||
* Choose a [Release](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/releases) as the basis of your translation. We generally suggest the latest release. This will ensure the consistency of all the files in your translation, will insulate you from any changes we make, and will make it easy to see what has changed when we create a new release.
|
||||
* If it looks like there hasn't been a new Release in a while, file an Issue saying you're interested in starting a new translation, and asking if it would make sense for there to be a new Release milestone before you do so. If there's been anything notable, and we're not in the middle of things, we'll likely create a new patch or minor version. If we're in the middle of things, we'll just suggest you use the previous Release.
|
||||
* Label your table of contents and each chapter or section with the release used.
|
||||
1. **Create a Branch.**
|
||||
* All work should be done in a branch, with work being submitted to the `master` branch as PRs.
|
||||
1. **Create a Directory.**
|
||||
* Create a top-level directory for your complete translation using the [ISO 639-1 language code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes), for example `es` (Spanish), `fr` (French), or `pt` (Portuguese).
|
||||
1. **Request a Branch.**
|
||||
* File an [Issue](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/issues) requesting a new branch for your translation
|
||||
* This will be the master place for us to collect work on the translation over time.
|
||||
* We will create a top-level directory for your complete translation using the [ISO 639-1 language code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes), for example `es` (Spanish), `fr` (French), or `pt` (Portuguese). Work should be done in that directory.
|
||||
1. **Fork the Branch.**
|
||||
* Once we've created a translation branch, you'll then want to fork that into your own GitHub account.
|
||||
* Generally, we suggest that you create one working fork for each separate chapter. This will allow you to work through the process of write/review/revise for each individual chapter without it getting tangled up with your new content for future chapters, and will allow us to merge the chapters as they're completed, which is our preference, and will help everyone to keep track of where things our.
|
||||
1. **Submit PRs a Chapter at a Time.**
|
||||
* Submit your PRs for the translation in batches of no more than a single chapter at a time.
|
||||
* Submit your PRs for the translation from your working fork to our translation branch in batches of no more than a single chapter at a time.
|
||||
* Submit in smaller batches if it makes sense, for example because different people are writing different sections.
|
||||
* Again, we suggest that there be a fork for each chapter, so when you submit your PR for one chapter, you'll usually then create a fork for the next chapter.
|
||||
1. **Request Approval from a Native Speaker.**
|
||||
* No one can ever do a great edit of their own work, so we require each section to be approved by someone other than the original translator.
|
||||
* This fundamentally means that any translation team _should_ contain at least two members, either one translator and one editor or else two people who trade off roles of translator and editor. If your team doesn't have a second member, we can put out a call for an editor/approver when you submit a PR, but it's possible that we won't be able to find one, and your hard work will languish, so it's s better to have one up front.
|
||||
@ -23,7 +27,10 @@ Thank you for your interest in translating Learning Bitcoin from the Command Lin
|
||||
* Once a chapter or section has been approved by a native speaker, request approval from someone on the Blockchain Commons team: currently [@shannona](https://github.com/shannona).
|
||||
1. **Continue!**
|
||||
* Continue through the process, no more than one chapter at a time, until you have a full book.
|
||||
* Be aware of the scope of the overall project. As of v2.01, Learning Bitcoin from the Command Line is 120,000 words in length. As a book, that'd be 250-400 pages, depending on the format and layout. (About 80,000 words of that is text to translate, with the remainder being code.) You want to make sure you have the time for that level of commitment before getting started.
|
||||
* Be aware of the scope of the overall project. As of v2.01, Learning Bitcoin from the Command Line is 120,000 words in length. As a book, that'd be 250-400 pages, depending on the format and layout. (About 90,000 words of that is text to translate, with the remainder being code.) You want to make sure you have the time for that level of commitment before getting started.
|
||||
1. **Let Us Know When You're Done.**
|
||||
* When you've completed your translation, file an issue to let us know that the translation branch is ready to be merged into the master.
|
||||
* This will also let us know to announce the completed translation and link it into the master README
|
||||
1. **Update Your Translation with New Releases**
|
||||
* It is our hope that translations will stay up to day with new releases, particularly major and minor releases, which are likely to include new content and updates. Currently, these only occur ever few years
|
||||
* If you have decided to stop updating a translation, please let us know in an Issue, so that we can let the community know that we are looking for a new translator to continue updating a translation.
|
||||
|
64
pt/01_0_Introduction.md
Normal file
64
pt/01_0_Introduction.md
Normal file
@ -0,0 +1,64 @@
|
||||
|
||||
# CAPÍTULO 1: Introdução à Aprendizagem do Bitcoin Core (& Lightning Network) pela linha de comando
|
||||
|
||||
## Introdução
|
||||
|
||||
Os modos como fazemos pagamentos por bens e serviços têm mudado drasticamente nas últimas décadas. Antigamente todas as transações eram realizadas utilizando dinheiro ou cheques, e atualmente os diversos métodos de pagamento eletrônico são à regra. Porém, a maioria dos pagamentos eletrônicos ainda ocorre utilizando sistemas centralizados, onde empresas de cartão de crédito, bancos ou até instituições financeiras baseadas apenas na Internet, como o PayPal, mantêm listas de transações longas e correlacionadas individualmente, tendo o poder de censurar as transações que não gostarem.
|
||||
|
||||
Esses riscos de centralização foram alguns dos catalisadores primordiais para a criação de criptomoedas, sendo a primeira e mais bem sucedida, o Bitcoin. O Bitcoin oferece pseudonímia; torna difícil correlacionar as transações; e torna a censura por entidades individuais, algo próximo do impossível. Essas vantagens fizeram dele uma das moedas mais rápidas do mundo. Esse crescimento, por sua vez, despertou o interesse dos empresários e desenvolvedores, ansiosos para criar novos serviços para a comunidade do Bitcoin.
|
||||
|
||||
Se você é um desses empreendedores ou desenvolvedores, então este curso é para você, porque ele tem tudo o que necessita para aprender a programar no Bitcoin. É um curso introdutório que explica todas as nuances e características do Bitcoin e de tudo o que vem com ele. O curso também oferece algumas coisas mais específicas, como aulas de como utilizar _diretamente_ o Bitcoin Core com o servidor C-Lightning usando suas interfaces RPC.
|
||||
|
||||
Por que não utilizar algumas das bibliotecas mais detalhadas encontradas em várias linguagens de programação? Por que não criar a sua própria do zero? Porque trabalhar com criptomoedas é perigoso. Não há redes de segurança. Se você acidentalmente pagar taxas muito altas ou perder uma chave de assinatura ou criar uma transação inválida ou fazer qualquer outros milhares de erros potenciais, você dará adeus a suas moedas para sempre. Muito dessa responsabilidade, é claro, fica com você como sendo um programador de criptomoedas, mas também pode ser minimizado, trabalhando com as interfaces de criptomoedas mais robustas e seguras que estão disponíveis, as que foram criadas pelas próprias equipes de programação dessas criptomoedas: A ``Bitcoind`` e a ``Lightningd``.
|
||||
|
||||
Grande parte deste livro discute como fazer um script em bitcoin (e na Lightning Network) diretamente pela linha de comando. Alguns capítulos adiantes lidam com linguagens de programação mais sofisticadas, mas novamente continuam a interagir diretamente com o `` Bitcoind`` e a ``Lightningd``, usando o RPC ou interagindo com os arquivos que são criados por eles. Isso permite que você se mantenha no mesmo nível dos gigantes e use a tecnologia confiável para aprender como criar seus próprios sistemas confiáveis.
|
||||
|
||||
## Nível de Habilidade Necessária
|
||||
|
||||
Você não precisa ser particularmente uma pessoa da área técnica para boa parte deste curso. Tudo o que precisará é a confiança para executar comandos básicos pela linha de comando do UNIX. Se você está familiarizado com coisas como ``ssh``, ``cd``, e ``ls``, o curso irá te fornecer o resto.
|
||||
|
||||
Uma minoria deste curso requer conhecimento de programação, e você deve pular essas seções, se necessário, conforme iremos discutir na próxima seção.
|
||||
|
||||
## Resumo dos tópicos
|
||||
|
||||
Este livro é dividido nas seguintes seções:
|
||||
|
||||
| Parte | Descrição | Habilidades |
|
||||
|-------|---------|---------|
|
||||
| **Parte 1: Se preparando para o Bitcoin** | Entendendo os fundamentos do Bitcoin e configurando um servidor para uso. | Linha de Comando |
|
||||
| **Parte 2: Usando o bitcoin-cli** | Usando o Bitcoin-cli para criar transações. | Linha de Comando |
|
||||
| **Parte 3: Fazendo scripts com Bitcoin** | Expandindo seu trabalho no bitcoin com scripts. | Conceitos de Programação |
|
||||
| **Parte 4: Usando o Tor** | Melhorando a segurança do _node_ com tor | Linha de Comando |
|
||||
| **Parte 5: Programando com RPC** | Acessando o RPC com C e outras linguagens. | Programando em C |
|
||||
| **Parte 6: Usando a lightning-cli** | Usando a Lightning-CLI para criar transações. | Linha de Comando |
|
||||
| **Apêndices.** | Utilizando configurações incomuns no Bitcoin. | Linha de Comando |
|
||||
|
||||
## Como Usar Este Curso
|
||||
|
||||
Então, por onde você começa? Este livro é destinado principalmente para ser lido em sequência. Basta seguir o "O que vem depois?" que estarão no final de cada seção e/ou clicar nos links individuais de cada seção em cada página do capítulo. Você conseguirá o melhor entendimento deste curso se realmente se construir um servidor Bitcoin (no capítulo 2) e, em seguida, passar por todos os exemplos que estarão disponíveis ao longo do livro: Testar os exemplos é uma excelente metodologia de aprendizado.
|
||||
|
||||
Se você tem diferentes níveis de habilidade ou se quiser aprender coisas diferentes, poderá pular para algumas partes diferentes do livro:
|
||||
|
||||
* Se você já tem um ambiente pronto do Bitcoin para ser utilizado, vá para o [Capítulo 3: Entendendo sua configuração do Bitcoin](03_0_Understanding_Your_Bitcoin_Setup.md).
|
||||
* Se você só se importa com os Scriptos em Bitcoin, pule para o [Capítulo 9: Apresentando os Scripts no Bitcoin](09_0_Introducing_Bitcoin_Scripts.md).
|
||||
* Se você quiser apenas ler sobre o uso das linguagens de programação, pule para o [Capítulo 15: Falando com o Bitcoin](15_0_Talking_to_Bitcoind.md).
|
||||
* Se não quer programar nada, definitivamente ignore os capítulos 15 ao 17 enquanto estiver lendo, e talvez seja melhor pular os capítulos 9 ao 13. O resto do curso ainda deve fazer sentido sem eles.
|
||||
* Se estiver interessado apenas na Lightning Network, corra para o [Capítulo 18: Entendendo sua configuração da Lightning Network](18_0_Understanding_Your_Lightning_Setup.md).
|
||||
* Se quiser ler o conteúdo novo adicionado na versão 2 do curso (2020), seguido da versão 1 (2017), leia [§3.5: Entendendo o descritor](03_5_Understanding_the_Descriptor.md), [§4.6: Criando uma transação SegWit](04_6_Creating_a_Segwit_Transaction.md), [Capítulo 7: Expandindo o Bitcoin com PSBTs](07_0_Expanding_Bitcoin_Transactions_PSBTs.md), [§9.5: Criando um script P2WPKH](09_5_Scripting_a_P2WPKH.md), [§10.5: Criando um script SegWit](10_5_Scripting_a_Segwit_Script.md), [Capítulo 14: Usando o Tor](14_0_Using_Tor.md), [Capítulo 15: Conversando com o Bitcoin com C](15_0_Talking_to_Bitcoind.md), [Capítulo 16: Programando com Libwally](16_0_Programming_with_Libwally.md), [Capítulo 17: Conversando com o Bitcoind usando outras linguagens](17_0_Talking_to_Bitcoind_Other.md), [Capítulo 18: Entendendo sua configuração da Lightning ](18_0_Understanding_Your_Lightning_Setup.md), e [Capítulo 19: Usando a Lightning](19_0_Using_Lightning.md).
|
||||
|
||||
## Por Que Utilizar Este Curso
|
||||
|
||||
Obviamente, você está querendo fazer este curso porque está interessado no Bitcoin. Além de transmitir o conhecimento básico, também ajudará os leitores a participar (ou criar) projetos open source e obter empregos de cargos júnior na área de programação envolvendo o Bitcoin. Um número de estagiários na Blockchain Commons aprendeu sobre o Bitcoin através deste curso, e muitos dos membros da nossa equipe de programação também.
|
||||
|
||||
## Como Ajudar Este Curso
|
||||
|
||||
* Por favor, use a área de [Issues](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/issues) para quaisquer dúvidas. A Blockchain Commons não tem uma equipe ativa de suporte, e não podemos abordar problemas ou perguntas individuais, mas olharemos iremos tratá-los com o tempo e os usaremos para melhorar nossas futuras iterações no curso.
|
||||
* Por favor, use os [PRs](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/pulls) para quaisquer correções de erros de digitação ou comandos incorretos (ou que foram alterados). Para alterações técnicas ou de linha de comando, é muito útil se você usar também os comentários para explicar por que fez o que você fez, para que não precisemos gastar tempo pesquisando o motivo.
|
||||
* Por favor, use nossa [Área de Discussão da Comunidade](https://github.com/BlockchainCommons/Community/discussions) para falar sobre carreiras e habilidades. A Blockchain Commons ocasionalmente oferece estágios, como falado em nosso repo da comunidade.
|
||||
* Por favor, [torne-se um patrono](https://github.com/sponsors/BlockchainCommons) se achar este curso útil ou se quiser ajudar a educar a próxima geração de programadores da blockchain.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Se você quiser uma introdução básica ao Bitcoin, criptografia de chave pública, ECC, blockchains e Lightning Network, leia o prefácio [Introdução ao Bitcoin](01_1_Introducing_Bitcoin.md).
|
||||
|
||||
Caso contrário, se já estiver pronto para mergulhar de cabeça no curso, vá para [Configurando um Bitcoin-Core no VPS](02_0_Setting_Up_a_Bitcoin-Core_VPS.md).
|
150
pt/01_1_Introducing_Bitcoin.md
Normal file
150
pt/01_1_Introducing_Bitcoin.md
Normal file
@ -0,0 +1,150 @@
|
||||
|
||||
# Prefácio: Apresentando o Bitcoin
|
||||
|
||||
Antes de começar a programar em Bitcoin (e Lightning), você deve ter uma compreensão básica do que são e como funcionam. Esta seção fornece essa visão geral. Várias outras definições irão aparecer mais à frente. O objetivo deste capítulo é apenas dar o conteúdo base.
|
||||
|
||||
## Sobre o Bitcoin
|
||||
|
||||
O Bitcoin é um sistema programável que permite a transferência da moeda bitcoin. Tem como base um sistema descentralizado _peer-to-peer_ (de ponta à ponta) de nodes, que inclui full nodes, carteiras e mineradores. Trabalhando juntos, eles garantem que as transações do bitcoin sejam rápidas e irreversíveis. Graças à natureza descentralizada do sistema, essas transações também são resistentes à censura e podem fornecer outras vantagens, como pseudo-anonimato, caso sejam bem utilizadas.
|
||||
|
||||
Obviamente, Bitcoin é o coração deste livro, mas também é o originador de muitos outros sistemas, incluindo a blockchain e Lightning, que são detalhados neste tutorial, e muitas outras criptomoedas, como Ethereum e Litecoin, que não são.
|
||||
|
||||
**_Como as moedas são transferidas?_** O Bitcoin não possui moedas físicas. Elas são uma série interminável de trocas títulos de propriedade. Quando uma pessoa envia as moedas para outra, essa transferência é armazenada como uma transação. É a transação que realmente registra a propriedade do dinheiro, isso significa que não existe nenhuma moeda que sai da carteira ou da máquina do proprietário.
|
||||
|
||||
**_Para quem você pode enviar as moedas?_** A grande maioria das transações de bitcoin envolvem o envio de moedas para pessoas comuns (ou pelo menos para endereços Bitcoin de pessoas comuns). No entanto, metodologias mais complexas podem ser usadas para enviar bitcoins para um grupo de pessoas ou para scripts. Essas várias metodologias possuem nomes como P2PKH, multisig e P2SH.
|
||||
|
||||
**_Como as transações são armazenadas?_** As transações são combinadas em grandes blocos de dados, que são gravados na _ledger da blockchain_. Um bloco é construído de tal forma que não pode ser substituído ou reescrito, uma vez que vários blocos tenham sido construídos depois dele. Isso é o que torna os bitcoins irreversíveis: Um livro razão (_ledger_) global descentralizado, onde tudo é registrado, é efetivamente um banco de dados permanente e imutável.
|
||||
|
||||
Porém, o processo de construção desses blocos é estocástico: É um tanto aleatório, então não podemos ter certeza se uma transação será colocada em um bloco específico. Também pode haver alterações nos blocos se forem muito recentes, mas apenas se forem _muitíssimo_ recentes. Então, as coisas se tornam irreversíveis (permanentes, imutáveis) depois de um alguns minutos.
|
||||
|
||||
**_Como as transações são protegidas?_** Os fundos contidos em uma transação Bitcoin são assegurados por um quebra-cabeça criptográfico. Esses quebra-cabeças são projetados para que possam ser facilmente resolvidos pela pessoa para quem os fundos foram enviados. Isso é feito usando o poder da criptografia de chave pública. Tecnicamente, uma transação é protegida por uma assinatura que prova que você é o proprietário da chave pública para a qual a transação foi enviada: Essa prova de propriedade é o quebra-cabeça que está sendo resolvido.
|
||||
|
||||
Os fundos são protegidos pelo uso de hashes. As chaves públicas não são realmente armazenadas na blockchain até que os fundos sejam gastos: Apenas os hashes de chave pública são. Isso significa que, mesmo que um computador quântico seja criado, as transações do Bitcoin permaneceriam protegidas por esse segundo nível de criptografia.
|
||||
|
||||
**_Como as transações são criadas?_** O coração de cada transação do Bitcoin é uma linguagem script do tipo FORTH usada para bloquear a transação. Para reenviar o dinheiro, o destinatário fornece informações específicas ao script que prova que ele é o destinatário pretendido.
|
||||
|
||||
No entanto, esses scripts do Bitcoin são o nível mais baixo de funcionalidade deste protocolo. Grande parte do trabalho do Bitcoin é feito através do `bitcoind` do Bitcoin, que é controlado por meio de comandos RPC. Muitas pessoas enviam esses comandos RPC por meio do programa chamado `bitcoin-cli`, que fornece uma interface ainda mais simples. Os não programadores nem mesmo se preocupam com essas minúcias, permitindo o uso de carteiras programáveis com interfaces mais simples.
|
||||
|
||||
### Resumindo o Bitcoin
|
||||
|
||||
Uma maneira de pensar no Bitcoin é como _uma sequência de transações atômicas_. Cada transação é autenticada por um remetente com a solução para um quebra-cabeça criptográfico anterior que foi armazenado como um script. A nova transação é bloqueada para o destinatário com um novo quebra-cabeça criptográfico que também é armazenado como um script. Cada transação é registrada no livro razão global imutável.
|
||||
|
||||
## Sobre criptografia de chave pública
|
||||
|
||||
A criptografia de chave pública é um sistema matemático para proteção de dados e comprovação de propriedade por meio de um par assimétrico de chaves que estão vinculadas entre si: a chave pública e a chave privada.
|
||||
|
||||
É importante para o Bitcoin (e para a maioria dos sistemas que utilizam a blockchain) porque é a base de grande parte da criptografia que protege os fundos das criptomoedas. Uma transação de Bitcoin é normalmente enviada para um endereço que é um hash da chave pública. O destinatário pode então recuperar o dinheiro utilizando a chave pública e a chave privada.
|
||||
|
||||
**_O que é uma chave pública?_** Uma chave pública é a chave fornecida as demais pessoas. Em um sistema de chave pública comum, um usuário gera uma chave pública e uma chave privada e, em seguida, dá a chave pública para as pessoas. Esses destinatários podem criptografar informações com a chave pública, mas não podem ser descriptografadas com a mesma chave devido à assimetria do par de chaves.
|
||||
|
||||
**_O que é uma chave privada?_** Uma chave privada está vinculada a uma chave pública em um par de chaves. Em um sistema de chave pública comum, um usuário mantém sua chave privada segura e a usa para descriptografar as mensagens que foram criptografadas com sua chave pública antes de serem enviadas a ele.
|
||||
|
||||
**_O que é uma assinatura?_** Uma mensagem (ou mais comumente, um hash de uma mensagem) pode ser assinada com uma chave privada, criando uma assinatura. Qualquer pessoa com a chave pública correspondente pode validar a assinatura, o que verifica se o assinante possui a chave privada associada à chave pública em questão. O _SegWit_ é um formato específico para armazenar uma assinatura na rede Bitcoin que falaremos mais especificamente no futuro.
|
||||
|
||||
**_O que é uma função hash?_** Uma função hash é um algoritmo frequentemente usado com a criptografia. É uma maneira de mapear uma grande quantidade arbitrária de dados em uma quantidade pequena e fixa de dados. As funções hash usadas na criptografia são unilaterais e resistentes a colisões, o que significa que um hash pode ser vinculado de forma confiável aos dados originais, mas os dados originais não podem ser regenerados a partir do hash. Assim, os hashes permitem a transmissão de pequenas quantidades de dados para representar grandes quantidades de dados, o que pode ser importante para a eficiência e os requisitos de armazenamento.
|
||||
|
||||
O Bitcoin aproveita a capacidade do hash de disfarçar os dados originais, o que permite ocultar a chave pública real do usuário, tornando as transações resistentes à computação quântica.
|
||||
|
||||
### Resumindo a criptografia de chave pública
|
||||
|
||||
Uma maneira de pensar na criptografia de chave pública é: _um jeito de qualquer pessoa proteger os dados de forma que apenas uma pessoa autorizada possa acessá-los e também possa provar que tem esse acesso._
|
||||
|
||||
## Sobre CCE
|
||||
|
||||
O CCE é um acrônimo para criptografia de curva elíptica. É um ramo específico da criptografia de chave pública que depende de cálculos matemáticos usando curvas elípticas definidas sobre campos finitos. É mais complexo e difícil de explicar do que a criptografia de chave pública clássica (que usava números primos), mas tem algumas vantagens interessantes.
|
||||
|
||||
O CCE não terá tanta atenção neste tutorial. Isso porque falaremos mais sobre a integração com servidores Bitcoin Core e Lightning, que já cuidaram da parte criptografia para você. Na verdade, a intenção deste tutorial é que você não precise se preocupar com a criptografia, porque isso é algo que você _realmente_ deseja que os especialistas lidem.
|
||||
|
||||
**_O que é uma curva elíptica?_** Uma curva elíptica é uma curva geométrica que assume a forma ``y`` <sup>`` 2`` </sup> = ``x`` <sup> ``3`` </sup> `` + ax + b``. Uma curva elíptica específica é escolhida selecionando valores específicos de ``a`` e ``b``. A curva deve ser examinada cuidadosamente para determinar se funciona bem para criptografia. Por exemplo, a curva secp256k1 usada pelo Bitcoin é definida como ``a = 0`` e ``b = 7``.
|
||||
|
||||
Qualquer linha que cruze uma curva elíptica o fará em 1 ou 3 pontos... e essa é a base da criptografia de curva elíptica.
|
||||
|
||||
**_O que são campos finitos?_** Um campo finito é um conjunto finito de números, onde todas as adições, subtrações, multiplicações e divisões são definidas de forma que resultem em outros números que também estarão no mesmo campo finito. Uma maneira simples de criar um campo finito é por meio do uso da aritmética modular.
|
||||
|
||||
**_Como uma curva elíptica é definida sobre um campo finito?_** Uma curva elíptica definida sobre um campo finito tem todos os pontos em sua curva desenhados a partir de um campo finito específico. Ele assume a forma: ``y``<sup>``2``</sup>``% tamanho-do-campo = (x``<sup>``3``</sup>`` + ax + b) % tamanho-do-campo``. O campo finito usado para secp256k1 é ``2``<sup>``256``</sup>``-2``<sup>``32``</sup>``-2``<sup>``9``</sup>``-2``<sup>``8``</sup>``-2``<sup>``7``</sup>``-2``<sup>``6``</sup>``-2``<sup>``4``</sup>``-1``.
|
||||
|
||||
**_Como as curvas elípticas são usadas na criptografia?_** Na criptografia de curva elíptica, um usuário seleciona um número muito grande (256 bits) como sua chave privada. Ele então adiciona um ponto base definido na curva a si mesmo tantas vezes. (Na secp256k1, o ponto de base é ``G = 04 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798 483ADA77 26A3C465 5DA4FBFC 0E1108A8 FD17B448 A6855419 9C47D08F FB10D4B8`` que prefixa as duas partes da tupla com um ``04`` para dizer que o ponto de dados está na forma descompactada. Se você preferir uma definição geométrica direta, é o ponto "0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0x483ADA7726A3C4655DA4FBFC0E1108A8FD0817B07029BFCDB2DCE28D959F2815B16F81798,0x483ADA7726A3C4655DA4FBFC0E1108A8FD0817B44810A"). O número resultante é uma chave pública. Várias fórmulas matemáticas podem então ser usadas para provar a propriedade da chave pública, dada a chave privada. Como acontece com qualquer função criptográfica, esta é uma armadilha: É fácil passar de uma chave privada para uma chave pública e praticamente impossível de passar de uma chave pública para uma chave privada.
|
||||
|
||||
Essa metodologia específica também explica por que os campos finitos são usados em curvas elípticas: Ela garante que a chave privada não ficará muito grande. Observe que o campo finito para secp256k1 é ligeiramente menor que 256 bits, o que significa que todas as chaves públicas terão 256 bits, assim como as chaves privadas.
|
||||
|
||||
**_Quais são as vantagens do CCE?_** A principal vantagem do CCE é que ele permite a mesma segurança da criptografia de chave pública clássica com uma chave muito menor. Uma chave pública de curva elíptica de 256 bits corresponde a uma chave pública tradicional (RSA) de 3072 bits.
|
||||
|
||||
### Resumindo o CCE
|
||||
|
||||
Uma maneira de pensar no CCE é: _Um jeito de permitir a criptografia de chave pública usando chaves muito pequenas e uma matemática bem obscura._
|
||||
|
||||
## Sobre Blockchains
|
||||
|
||||
A blockchain é a generalização da metodologia usada pelo Bitcoin para criar um livro razão distribuído globalmente. O Bitcoin é uma blockchain, assim como qualquer outra moeda alternativa, cada um dos quais vive em sua própria rede e grava em sua própria cadeia de blocos. As sidechains como a _Liquid_ são blockchains também. As blockchains não precisam necessariamente ser relacionadas com finanças. Por exemplo, existem várias discussões para implementar blockchains em soluções para proteger identidades autossoberanas.
|
||||
|
||||
Embora precise entender os fundamentos de como uma blockchain funciona para entender como as transações funcionam no Bitcoin, não é necessário muito mais do que isso. Como as blockchains se tornaram uma ampla categoria de tecnologia, esses conceitos básicos provavelmente serão aplicáveis a muitos outros projetos neste setor de tecnologia em crescimento. Porém, os comandos de programação específicos aprendidos neste livro não serão abrangentes a várias utilizações, já que são específicos para Bitcoin (e para a Lightning).
|
||||
|
||||
**_Por que é chamado de cadeia de blocos?_** Cada bloco na blockchain armazena um hash do bloco anterior. Isso liga o bloco atual de volta ao "bloco de gênese" original por meio de uma cadeia de blocos ininterrupta. É uma forma de criar uma ordem absoluta entre os dados possivelmente conflitantes. Isso também fornece a segurança da blockchain, porque cada bloco é empilhado sobre um antigo tornando mais difícil recriar o bloco antigo devido aos algoritmos de prova de trabalho utilizados na criação do bloco. Depois que vários blocos foram construídos sobre uma cadeia de blocos, ele é essencialmente irreversível.
|
||||
|
||||
**_O que é um fork?_** Ocasionalmente, dois blocos são criados ao mesmo tempo. Isso cria, temporariamente, um fork de um bloco, onde qualquer um dos blocos atuais pode ser o "verdadeiro". De vez em quando, um fork pode se expandir para dois blocos, três blocos ou mesmo quatro blocos de comprimento, mas muito rapidamente um lado da bifurcação é determinado como o verdadeiro e o outro se torna o que chamamos de "órfão". Isso faz parte do processo estocástico de criação de bloco e demonstra por que vários blocos devem ser construídos sobre um bloco antes que ele possa ser considerado verdadeiramente confiável e não rejeitável.
|
||||
|
||||
### Resumindo a blockchain
|
||||
|
||||
Uma maneira de pensar na blockchain é: _Uma série vinculada de blocos de dados imutáveis, até o seu bloco inicial._
|
||||
Outra forma é: _Uma série de blocos vinculados para ordenar dados absolutos que podem ser conflitantes_.
|
||||
|
||||
## A Blockchain é adequada para mim?
|
||||
|
||||
Se você deseja negociar bitcoins, então obviamente a Bitcoin é adequada para você. No entanto, de forma mais ampla, a blockchain se tornou uma cultura pop da atualidade, embora não seja uma solução mágica para todos os problemas técnicos. Dito isso, existem muitas situações específicas em que a blockchain é uma tecnologia superior.
|
||||
|
||||
Blockchains provavelmente _são_ úteis nos seguintes casos:
|
||||
|
||||
* Os usuários não confiam uns nos outros.
|
||||
* Ou: Os usuários estão em diferentes localidades.
|
||||
* Os usuários não confiam nas autoridades centrais.
|
||||
* E: Os usuários desejam controlar seus próprios destinos.
|
||||
* Os usuários desejam uma tecnologia transparente.
|
||||
* Os usuários desejam compartilhar algo.
|
||||
* E: Os usuários desejam que o que é compartilhado seja registrado permanentemente.
|
||||
* Os usuários desejam uma transação final rápida.
|
||||
* Mas: Os usuários não precisam de uma transação final instantânea.
|
||||
|
||||
Blockchains provavelmente _não_ serão úteis caso:
|
||||
|
||||
* Os usuários sejam confiáveis:
|
||||
* Por exemplo: As transações ocorrem dentro de uma empresa ou organização.
|
||||
* Por exemplo: As transações são supervisionadas por uma autoridade central.
|
||||
* O sigilo é obrigatório:
|
||||
* Por exemplo: As informações devem ser secretas.
|
||||
* Por exemplo: As transações devem ser secretas.
|
||||
* Por exemplo: As pessoas que estão transacionando devem ser secretas.
|
||||
* A menos que: uma metodologia para sigilo criptográfico seja cuidadosamente considerada, analisada e testada.
|
||||
* Os usuários precisam de transações finais instantâneas:
|
||||
* Por exemplo: Em menos de 10 minutos em uma rede semelhante a Bitcoin, em menos de 2,5 minutos em uma rede semelhante a Litecoin, em menos de 15 segundos em uma rede semelhante a Ethereum.
|
||||
|
||||
Observe que ainda pode haver soluções para algumas dessas situações dentro do ecossistema Bitcoin. Por exemplo, os canais de pagamento estão lidando rapidamente com questões de liquidez e finalização do pagamento.
|
||||
|
||||
## Sobre a Lightning (Network)
|
||||
|
||||
A lightning é um protocolo de segunda camada que interage com o Bitcoin para permitir que os usuários troquem seus bitcoins "offchain" (fora da blockchain). Possui vantagens e desvantagens em relação ao uso da camada principal do Bitcoin.
|
||||
|
||||
A lightning também é um dos focos deste tutorial. Embora o ponto principal seja sobre a interação direta com o Bitcoin (e o `bitcoind`), vamos falar um pouco sobre a lightning e o porque é uma tecnologia que está prestes a se tornar uma alternativa popular ao Bitcoin, em um futuro próximo. Este livro tem a mesma abordagem para a lightning e para o Bitcoin: Ele ensina como interagir diretamente com a Lightning de maneira confiável à partir da linha de comando.
|
||||
|
||||
Ao contrário do Bitcoin, existem várias variantes da lightning. Este tutorial usa a implementação compatível do padrão [C-lightning](https://github.com/ElementsProject/lightning) como sendo seu servidor lightning confiável.
|
||||
|
||||
**_O que é um protocolo de segunda camada?_** Um protocolo de segunda camada no Bitcoin funciona tendo como base o Bitcoin. Nesse caso, a lightning trabalha em cima do Bitcoin, interagindo com ele por meio de contratos inteligentes.
|
||||
|
||||
**_O que é um canal lightning?_** Um canal Lightning é uma conexão entre dois usuários utilizando a lightning. Cada um dos usuários bloqueia uma quantidade de bitcoins na blockchain do Bitcoin usando uma assinatura multi-sig, criada e assinada por ambos. Os dois usuários podem, então, trocar bitcoins por meio do canal lightning sem precisar gravar nada na blockchain Bitcoin. Somente quando desejam fechar o canal, eles liquidam os bitcoins, com base na divisão no saldo final das partes.
|
||||
|
||||
**_O que é a Lightning Network?_** A junção de todos os canais da lightning criam a Lightning Network. Isso permite que dois usuários que não tenham um canal entre si troquem bitcoins usando Lightning: O protocolo forma uma cadeia de canais entre os dois usuários e, em seguida, troca as moedas através da cadeia usando transações que chamamos de _time-locked transactions_.
|
||||
|
||||
**_Quais são as vantagens da lightning?_** A lightning permite transações mais rápidas com taxas mais baixas. Isso cria a possibilidade real de micropagamentos usando bitcoin. Ela também oferece maior privacidade, uma vez que está fora da rede, com apenas o primeiro e o último estado da transação sendo gravados blockchain do Bitcoin.
|
||||
|
||||
**_Quais são as desvantagens do Lightning?_** A lightning ainda é uma tecnologia muito nova e não foi testada tão exaustivamente quanto o Bitcoin. Isso não é apenas uma questão de implementação tecnológica, mas também se o design que pode ser manipulado de maneiras não pensadas anteriormente.
|
||||
|
||||
### Resumindo a lightning
|
||||
|
||||
Uma maneira de pensar na Lightning é: _Um jeito de transacionar bitcoins usando canais offchain entre duas pessoas, de modo que apenas o primeiro e o último estado precisem ser gravados na blockchain_.
|
||||
|
||||
## Resumo: Apresentando o Bitcoin
|
||||
|
||||
O Bitcoin é um sistema _peer-to-peer_ que permite a transferência de fundos por meio de transações bloqueadas por quebra-cabeças. Esses quebra-cabeças dependem da criptografia de curva elíptica de chave pública. Quando você generaliza as ideias por trás do Bitcoin, encontra-se as blockchains, uma tecnologia que atualmente está crescendo e inovando muitos setores. Quando você expande as ideias por trás do Bitcoin, obtém protocolos de segunda camada, como a lightning, que expandem o potencial da moeda.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Vamos avançar para "se preparar para o Bitcoin" com o [Capítulo Dois: Configurando um Bitcoin-Core no VPS](02_0_Setting_Up_a_Bitcoin-Core_VPS.md).
|
27
pt/02_0_Setting_Up_a_Bitcoin-Core_VPS.md
Normal file
27
pt/02_0_Setting_Up_a_Bitcoin-Core_VPS.md
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
# Capítulo 2: Configurando um Bitcoin-Core no VPS
|
||||
|
||||
Para começar a usar o Bitcoin, primeiro precisamos configurar uma máquina que execute o Bitcoin. Os artigos neste capítulo descrevem como fazer isso, principalmente usando um VPS (Virtual Private Server).
|
||||
|
||||
## Objetivos deste Capítulo
|
||||
|
||||
Depois de passar por este capítulo, um desenvolvedor será capaz de:
|
||||
|
||||
* Decidir entre os cinco principais tipos de nodes de Bitcoin;
|
||||
* Criar um node Bitcoin para desenvolvimento;
|
||||
* Crie uma instância local da Blockchain do Bitcoin.
|
||||
|
||||
Os objetivos secundários incluem a capacidade de:
|
||||
|
||||
* Compreender a configuração da rede básica do VPS;
|
||||
* Decidir quais prioridades de segurança implementar;
|
||||
* Entender a diferença entre os nodes prunados e os não prunados;
|
||||
* Entender a diferença entre nodes Mainnet, Testnet e Regtest;
|
||||
* Interpretar os fundamentos do arquivo de configuração do Bitcoin.
|
||||
|
||||
## Tabela de Conteúdo
|
||||
|
||||
Na verdade, não é preciso ler este capítulo inteiro. Decida se gostaria de executar um StackScript para configurar um node em um VPS Linode (§2.2); Ou você deseja configurar em um ambiente diferente, como em uma máquina AWS ou um Mac (§2.3). Em seguida, vá para a seção mais apropriada. Informações adicionais sobre nossas configurações sugeridas também podem ser encontradas no [Apêndice I](A1_0_Understanding_Bitcoin_Standup.md).
|
||||
|
||||
* [Seção Um: Configurando um Bitcoin Core VPS com Bitcoin Standup](02_1_Setting_Up_a_Bitcoin-Core_VPS_with_StackScript.md)
|
||||
* [Seção Dois: Configurando uma máquina Bitcoin Core usando outros meios](02_2_Setting_Up_Bitcoin_Core_Other.md)
|
31
pt/03_0_Understanding_Your_Bitcoin_Setup.md
Normal file
31
pt/03_0_Understanding_Your_Bitcoin_Setup.md
Normal file
@ -0,0 +1,31 @@
|
||||
# Capítulo 3: Compreendendo a configuração do node Bitcoin
|
||||
|
||||
Agora que estamos prontos para começar a trabalhar com a interface de linha de comando `bitcoin-cli`. Mas isso requer primeiro que entendamos a configuração do Bitcoin e os recursos da carteira, que é o que será explicado neste capítulo.
|
||||
|
||||
Neste e nos próximos capítulos, presumimos que uma VPS com Bitcoin instalado esteja sendo utilizada, e que iremos executar o `bitcoind`. Também presumimos que estamos conectados à testnet, permitindo o acesso a bitcoins sem usar fundos reais. Podemos fazer isso com Bitcoin Standup em linode.com, como vimos na sessão [2.1: Configurando um Bitcoin-Core no VPS c Bitcoin Standup](02_1_Setting_Up_a_Bitcoin-Core_VPS_with_StackScript.md), ou usando os demais métodos, descritos na sessão [2.2: Configurando um node Bitcoin Core por outros métodos](02_2_Setting_Up_Bitcoin_Core_Other.md).
|
||||
|
||||
## Objetivos deste Capítulo
|
||||
|
||||
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
|
||||
|
||||
* Demonstrar que o node Bitcoin está instalado e atualizado;
|
||||
* Criar um endereço para receber bitcoins;
|
||||
* Usar os comandos básicos da carteira;
|
||||
* Criar um endereço a partir de um descritor.
|
||||
|
||||
Os objetivos secundários incluem a capacidade de:
|
||||
|
||||
* Compreender o layout básico do arquivo Bitcoin;
|
||||
* Usar comandos informativos básicos;
|
||||
* Entender o que é um endereço Bitcoin;
|
||||
* Entender o que é uma carteira;
|
||||
* Entender como importar endereços.
|
||||
|
||||
## Tabela de Conteúdo
|
||||
|
||||
* [Seção Um: Verificando a configuração do seu node Bitcoin](03_1_Verifying_Your_Bitcoin_Setup.md)
|
||||
* [Seção Dois: conhecendo a configuração do seu node Bitcoin](03_2_Knowing_Your_Bitcoin_Setup.md)
|
||||
* [Seção Três: Configurando sua carteira](03_3_Setting_Up_Your_Wallet.md)
|
||||
* [Usando variável de linha de comando](03_3__Interlude_Using_Command-Line_Variables.md)
|
||||
* [Seção Quatro: Recebendo uma transação](03_4_Receiving_a_Transaction.md)
|
||||
* [Seção Cinco: Entendendo um descritor](03_5_Understanding_the_Descriptor.md)
|
104
pt/03_1_Verifying_Your_Bitcoin_Setup.md
Normal file
104
pt/03_1_Verifying_Your_Bitcoin_Setup.md
Normal file
@ -0,0 +1,104 @@
|
||||
|
||||
# 3.1: Verificando a configuração do node Bitcoin
|
||||
|
||||
Antes de começarmos a brincar com Bitcoin, devemos nos certificar de que tudo está configurado corretamente.
|
||||
|
||||
## Crie os aliases
|
||||
|
||||
Sugerimos a criação de alguns aliases (um tipo de atalho) para facilitar o uso do Bitcoin.
|
||||
|
||||
Podemos fazer isso colocando-os em nosso `.bash_profile`, `.bashrc` ou no `.profile`.
|
||||
```
|
||||
cat >> ~/.bash_profile <<EOF
|
||||
alias btcdir="cd ~/.bitcoin/" #linux default bitcoind path
|
||||
alias bc="bitcoin-cli"
|
||||
alias bd="bitcoind"
|
||||
alias btcinfo='bitcoin-cli getwalletinfo | egrep "\"balance\""; bitcoin-cli getnetworkinfo | egrep "\"version\"|connections"; bitcoin-cli getmininginfo | egrep "\"blocks\"|errors"'
|
||||
EOF
|
||||
```
|
||||
Depois de inserir os aliases, podemos usar o comando `source .bash_profile` para inseri-los ou apenas efetuar logout/login novamente.
|
||||
|
||||
Observe que os aliases incluem atalhos para executar o `bitcoin-cli`, o `bitcoind` e para ir ao diretório Bitcoin. Esses aliases têm como objetivo principal tornar a nossa vida mais fácil, por isso que damos a sugestão de criar outros apelidos para facilitar o uso de comandos frequentes (e argumentos) e também para minimizar erros. Os aliases desse tipo podem ser ainda mais úteis se tivermos uma configuração complexa onde regularmente executamos comandos associados a Mainnet, com Testnet, _e_ com Regtest, conforme explicaremos mais à frente.
|
||||
|
||||
Dito isso, o uso desses aliases _neste_ documento pode acidentalmente deixar algumas das lições principais onde ensinamos sobre o Bitcoin no escuro, então o único alias que usaremos diretamente aqui é `btcinfo` porque ele encapsula um comando muito mais longo e complexo. Caso contrário, iremos mostrar os comandos completos, por isso, podemos ajustar os aliases para nosso próprio uso conforme apropriado.
|
||||
|
||||
## Executando o Bitcoind
|
||||
|
||||
Começaremos nossa exploração da rede Bitcoin com o comando `bitcoin-cli`. No entanto, o `bitcoind` _deve_ estar em execução para conseguirmos usar o bitcoin-cli, pois ele envia comandos JSON-RPC para o bitcoind. Se estivermos usando a configuração padrão, o bitcoind já deve estar instalado e funcionando. Podemos verificar olhando a tabela de processos.
|
||||
```
|
||||
$ ps auxww | grep bitcoind
|
||||
standup 455 1.3 34.4 3387536 1392904 ? SLsl Jun16 59:30 /usr/local/bin/bitcoind -conf=/home/standup/.bitcoin/bitcoin.conf
|
||||
```
|
||||
|
||||
Se ele não estiver listado, podemos executar o `/usr/local/bin/bitcoind -daemon` manualmente e também colocá-lo em crontab.
|
||||
|
||||
## Verificando os blocos
|
||||
|
||||
Vamos partir do pressuposto que já tenhamos baixado todo o blockchain antes de começarmos a brincar. Basta executar o comando `bitcoin-cli getblockcount` para ver tudo está carregado corretamente.
|
||||
```
|
||||
$ bitcoin-cli getblockcount
|
||||
1772384
|
||||
```
|
||||
Isso indica que está carregado. Precisamos verificar isso em um serviço online que informa a altura atual do bloco.
|
||||
|
||||
> :book: ***O que é a altura do bloco?*** A altura do bloco é a distância que um bloco particular está do bloco de gênese. A altura do bloco atual é a altura do bloco mais recente adicionado a blockchain.
|
||||
|
||||
Podemos fazer isso olhando um explorador, como o [Mempool Space Explorer](https://mempool.space/pt/testnet). É o número mais recente corresponde ao `getblockcount`? Se sim, nossa blockchain está atualizada.
|
||||
|
||||
Se quisermos que um alias veja tudo de uma vez, o código abaixo funciona normalmente no Testnet, mas pode desaparecer em algum momento no futuro:
|
||||
```
|
||||
$ cat >> ~/.bash_profile << EOF
|
||||
alias btcblock="echo \\\`bitcoin-cli getblockcount 2>&1\\\`/\\\`wget -O - https://blockstream.info/testnet/api/blocks/tip/height 2> /dev/null | cut -d : -f2 | rev | cut -c 1- | rev\\\`"
|
||||
EOF
|
||||
$ source .bash_profile
|
||||
$ btcblock
|
||||
1804372/1804372
|
||||
```
|
||||
|
||||
> :link: **TESTNET vs MAINNET:** Lembre-se de que este tutorial geralmente assume que estamos usando a Testnet. Se estivermos usando a mainnet, podemos recuperar a altura do bloco atual usando a seguinte linha de comando: `wget -O - https://mempool.space/testnet/api/blocks/tip/height 2> /dev/ null`. Podemos substituir a última metade do alias `btblock` (após `/`) por isso.
|
||||
|
||||
Se a nossa blockchain não estiver atualizada, mas nosso `getblockcount` estiver aumentando, não há problema. O tempo total de download pode levar de uma a várias horas, dependendo da configuração.
|
||||
|
||||
## Opcional: Conhecendo os tipos de servidores
|
||||
|
||||
> **TESTNET vs MAINNET:** Ao configurar o node Bitcoin, precisamos escolher se vamos criá-lo como sendo um Mainnet, Testnet ou Regtest. Embora este documento presuma uma configuração de Testnet, vale a pena entender como podemos acessar e usar os outros tipos de configuração, inclusive, como ter todos na mesma máquina! Mas, se formos iniciantes, podemos pular isso, pois não é necessário para uma configuração básica.
|
||||
|
||||
O tipo de configuração é controlado principalmente por meio do arquivo `~/.bitcoin/bitcoin.conf`. Se estivermos executando o Testnet, provavelmente teremos a seguinte linha:
|
||||
```
|
||||
testnet=1
|
||||
```
|
||||
Se estivermos executando a Regtest, provavelmente teremos essa linha:
|
||||
```
|
||||
regtest=1
|
||||
```
|
||||
No entanto, se desejarmos executar vários tipos diferentes de nós simultaneamente, devemos deixar o um sinalizador Testnet (ou Regtest) fora do nosso arquivo de configuração. Podemos então escolher se estamos usando a Mainnet, Testnet ou Regtest toda vez que executarmos o bitcoind ou o bitcoin-cli.
|
||||
|
||||
Aqui está um conjunto de aliases que tornariam isso mais fácil, criando um alias específico para iniciar e parar o bitcoind, para ir para o diretório bitcoin e para executar o bitcoin-cli, na Mainnet (que não tem sinalizadores extras), no Testnet (que é -testnet), ou no nosso Regtest (que é -regtest).
|
||||
```
|
||||
cat >> ~/.bash_profile <<EOF
|
||||
alias bcstart="bitcoind -daemon"
|
||||
alias btstart="bitcoind -testnet -daemon"
|
||||
alias brstart="bitcoind -regtest -daemon"
|
||||
|
||||
alias bcstop="bitcoin-cli stop"
|
||||
alias btstop="bitcoin-cli -testnet stop"
|
||||
alias brstop="bitcoin-cli -regtest stop"
|
||||
|
||||
alias bcdir="cd ~/.bitcoin/" #linux default bitcoin path
|
||||
alias btdir="cd ~/.bitcoin/testnet" #linux default bitcoin testnet path
|
||||
alias brdir="cd ~/.bitcoin/regtest" #linux default bitcoin regtest path
|
||||
|
||||
alias bc="bitcoin-cli"
|
||||
alias bt="bitcoin-cli -testnet"
|
||||
alias br="bitcoin-cli -regtest"
|
||||
EOF
|
||||
```
|
||||
Para ainda mais complexidade, podemos fazer com que cada um dos aliases 'start' use o sinalizador -conf para carregar a configuração de um arquivo diferente. Isso vai muito além do escopo deste tutorial, mas o oferecemos como um ponto de partida para quando nossas explorações de Bitcoin atingirem o próximo nível.
|
||||
|
||||
## Resumo do Verificando a configuração do seu node Bitcoin
|
||||
|
||||
Antes de começar a brincar com o Bitcoin, devemos nos certificar de que nossos aliases estão configurados, nosso bitcoind está rodando e os blocos foram baixados. Também podemos querer configurar algum acesso a configurações alternativas de Bitcoin, se formos usuários mais avançados.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Continue "Understanding Your Bitcoin Setup" com [3.2: Knowing Your Bitcoin Setup](03_2_Knowing_Your_Bitcoin_Setup.md).
|
316
pt/03_2_Knowing_Your_Bitcoin_Setup.md
Normal file
316
pt/03_2_Knowing_Your_Bitcoin_Setup.md
Normal file
@ -0,0 +1,316 @@
|
||||
|
||||
# 3.2: Conhecendo a configuração do node Bitcoin
|
||||
|
||||
Antes de começarmos a brincar com Bitcoin, é sempre bom entender melhor nossa configuração.
|
||||
|
||||
## Conhecendo o diretório do Bitcoin
|
||||
|
||||
Para começar, devemos entender onde tudo está guardado: O diretório `~/.bitcoin`.
|
||||
|
||||
O diretório principal contém apenas nosso arquivo de configuração e o diretório Testnet:
|
||||
```
|
||||
$ ls ~/.bitcoin
|
||||
bitcoin.conf testnet3
|
||||
```
|
||||
Os guias de configuração no [Capítulo dois: Criando um VPS Bitcoin-Core](02_0_Setting_Up_a_Bitcoin-Core_VPS.md) estabelecem um arquivo de configuração padronizado. Na sessão [3.1: Verificando a configuração do node Bitcoin](03_1_Verifying_Your_Bitcoin_Setup.md) sugerimos como alterá-la para oferecer suporte a configurações mais avançadas. Se estivermos interessados em aprender ainda mais sobre o arquivo de configuração, podemos consultar o [Gerador de Configuração do Bitcoin Core escrito por Jameson Lopp's](https://jlopp.github.io/bitcoin-core-config-generator/).
|
||||
|
||||
Voltando para o diretório `~/.bitcoin`, iremos descobrir que o diretório testnet3 contém todos os elementos:
|
||||
```
|
||||
$ ls ~/.bitcoin/testnet3
|
||||
banlist.dat blocks debug.log mempool.dat peers.dat
|
||||
bitcoind.pid chainstate fee_estimates.dat onion_private_key wallets
|
||||
```
|
||||
Não deve mexer com a maioria desses arquivos e diretórios, particularmente os diretórios `blocks` e `chainstate` não devem ser tocados, pois contêm todos os dados da blockchain, e as informações do nosso diretório `wallets`, que contém nossa carteira. No entanto, podemos prestar atenção ao arquivo `debug.log`, que devemos consultar se começarmos a ter problemas com nossa configuração.
|
||||
|
||||
> :link: **TESTNET vs MAINNET:** Se estivermos usando a Mainnet, então _tudo_ será colocado no diretório principal `~/.bitcoin`. Então se estivermos usando a Mainnet, Testnet e a Regtest, veremos que o `~/.bitcoin` contém nosso arquivo de configuração e nossos dados da mainnet, o diretório `~/.bitcoin/testnet3` contém nossos dados da Testnet, e o diretório `~/.bitcoin/regtest` contém os dados do regtest.
|
||||
|
||||
## Conhecendo os comandos do Bitcoin-cli
|
||||
|
||||
A maior parte do nosso trabalho inicial será feito com o comando `bitcoin-cli`, que oferece uma interface simples para o `bitcoind`. Se quisermos mais informações sobre como utilizá-lo, basta executá-lo com o argumento `help`. Sem nenhum outro argumento, ele mostrara todos os possíveis comandos:
|
||||
```
|
||||
$ bitcoin-cli help
|
||||
== Blockchain ==
|
||||
getbestblockhash
|
||||
getblock "blockhash" ( verbosity )
|
||||
getblockchaininfo
|
||||
getblockcount
|
||||
getblockfilter "blockhash" ( "filtertype" )
|
||||
getblockhash height
|
||||
getblockheader "blockhash" ( verbose )
|
||||
getblockstats hash_or_height ( stats )
|
||||
getchaintips
|
||||
getchaintxstats ( nblocks "blockhash" )
|
||||
getdifficulty
|
||||
getmempoolancestors "txid" ( verbose )
|
||||
getmempooldescendants "txid" ( verbose )
|
||||
getmempoolentry "txid"
|
||||
getmempoolinfo
|
||||
getrawmempool ( verbose )
|
||||
gettxout "txid" n ( include_mempool )
|
||||
gettxoutproof ["txid",...] ( "blockhash" )
|
||||
gettxoutsetinfo
|
||||
preciousblock "blockhash"
|
||||
pruneblockchain height
|
||||
savemempool
|
||||
scantxoutset "action" ( [scanobjects,...] )
|
||||
verifychain ( checklevel nblocks )
|
||||
verifytxoutproof "proof"
|
||||
|
||||
== Control ==
|
||||
getmemoryinfo ( "mode" )
|
||||
getrpcinfo
|
||||
help ( "command" )
|
||||
logging ( ["include_category",...] ["exclude_category",...] )
|
||||
stop
|
||||
uptime
|
||||
|
||||
== Generating ==
|
||||
generatetoaddress nblocks "address" ( maxtries )
|
||||
generatetodescriptor num_blocks "descriptor" ( maxtries )
|
||||
|
||||
== Mining ==
|
||||
getblocktemplate ( "template_request" )
|
||||
getmininginfo
|
||||
getnetworkhashps ( nblocks height )
|
||||
prioritisetransaction "txid" ( dummy ) fee_delta
|
||||
submitblock "hexdata" ( "dummy" )
|
||||
submitheader "hexdata"
|
||||
|
||||
== Network ==
|
||||
addnode "node" "command"
|
||||
clearbanned
|
||||
disconnectnode ( "address" nodeid )
|
||||
getaddednodeinfo ( "node" )
|
||||
getconnectioncount
|
||||
getnettotals
|
||||
getnetworkinfo
|
||||
getnodeaddresses ( count )
|
||||
getpeerinfo
|
||||
listbanned
|
||||
ping
|
||||
setban "subnet" "command" ( bantime absolute )
|
||||
setnetworkactive state
|
||||
|
||||
== Rawtransactions ==
|
||||
analyzepsbt "psbt"
|
||||
combinepsbt ["psbt",...]
|
||||
combinerawtransaction ["hexstring",...]
|
||||
converttopsbt "hexstring" ( permitsigdata iswitness )
|
||||
createpsbt [{"txid":"hex","vout":n,"sequence":n},...] [{"address":amount},{"data":"hex"},...] ( locktime replaceable )
|
||||
createrawtransaction [{"txid":"hex","vout":n,"sequence":n},...] [{"address":amount},{"data":"hex"},...] ( locktime replaceable )
|
||||
decodepsbt "psbt"
|
||||
decoderawtransaction "hexstring" ( iswitness )
|
||||
decodescript "hexstring"
|
||||
finalizepsbt "psbt" ( extract )
|
||||
fundrawtransaction "hexstring" ( options iswitness )
|
||||
getrawtransaction "txid" ( verbose "blockhash" )
|
||||
joinpsbts ["psbt",...]
|
||||
sendrawtransaction "hexstring" ( maxfeerate )
|
||||
signrawtransactionwithkey "hexstring" ["privatekey",...] ( [{"txid":"hex","vout":n,"scriptPubKey":"hex","redeemScript":"hex","witnessScript":"hex","amount":amount},...] "sighashtype" )
|
||||
testmempoolaccept ["rawtx",...] ( maxfeerate )
|
||||
utxoupdatepsbt "psbt" ( ["",{"desc":"str","range":n or [n,n]},...] )
|
||||
|
||||
== Util ==
|
||||
createmultisig nrequired ["key",...] ( "address_type" )
|
||||
deriveaddresses "descriptor" ( range )
|
||||
estimatesmartfee conf_target ( "estimate_mode" )
|
||||
getdescriptorinfo "descriptor"
|
||||
signmessagewithprivkey "privkey" "message"
|
||||
validateaddress "address"
|
||||
verifymessage "address" "signature" "message"
|
||||
|
||||
== Wallet ==
|
||||
abandontransaction "txid"
|
||||
abortrescan
|
||||
addmultisigaddress nrequired ["key",...] ( "label" "address_type" )
|
||||
backupwallet "destination"
|
||||
bumpfee "txid" ( options )
|
||||
createwallet "wallet_name" ( disable_private_keys blank "passphrase" avoid_reuse )
|
||||
dumpprivkey "address"
|
||||
dumpwallet "filename"
|
||||
encryptwallet "passphrase"
|
||||
getaddressesbylabel "label"
|
||||
getaddressinfo "address"
|
||||
getbalance ( "dummy" minconf include_watchonly avoid_reuse )
|
||||
getbalances
|
||||
getnewaddress ( "label" "address_type" )
|
||||
getrawchangeaddress ( "address_type" )
|
||||
getreceivedbyaddress "address" ( minconf )
|
||||
getreceivedbylabel "label" ( minconf )
|
||||
gettransaction "txid" ( include_watchonly verbose )
|
||||
getunconfirmedbalance
|
||||
getwalletinfo
|
||||
importaddress "address" ( "label" rescan p2sh )
|
||||
importmulti "requests" ( "options" )
|
||||
importprivkey "privkey" ( "label" rescan )
|
||||
importprunedfunds "rawtransaction" "txoutproof"
|
||||
importpubkey "pubkey" ( "label" rescan )
|
||||
importwallet "filename"
|
||||
keypoolrefill ( newsize )
|
||||
listaddressgroupings
|
||||
listlabels ( "purpose" )
|
||||
listlockunspent
|
||||
listreceivedbyaddress ( minconf include_empty include_watchonly "address_filter" )
|
||||
listreceivedbylabel ( minconf include_empty include_watchonly )
|
||||
listsinceblock ( "blockhash" target_confirmations include_watchonly include_removed )
|
||||
listtransactions ( "label" count skip include_watchonly )
|
||||
listunspent ( minconf maxconf ["address",...] include_unsafe query_options )
|
||||
listwalletdir
|
||||
listwallets
|
||||
loadwallet "filename"
|
||||
lockunspent unlock ( [{"txid":"hex","vout":n},...] )
|
||||
removeprunedfunds "txid"
|
||||
rescanblockchain ( start_height stop_height )
|
||||
sendmany "" {"address":amount} ( minconf "comment" ["address",...] replaceable conf_target "estimate_mode" )
|
||||
sendtoaddress "address" amount ( "comment" "comment_to" subtractfeefromamount replaceable conf_target "estimate_mode" avoid_reuse )
|
||||
sethdseed ( newkeypool "seed" )
|
||||
setlabel "address" "label"
|
||||
settxfee amount
|
||||
setwalletflag "flag" ( value )
|
||||
signmessage "address" "message"
|
||||
signrawtransactionwithwallet "hexstring" ( [{"txid":"hex","vout":n,"scriptPubKey":"hex","redeemScript":"hex","witnessScript":"hex","amount":amount},...] "sighashtype" )
|
||||
unloadwallet ( "wallet_name" )
|
||||
walletcreatefundedpsbt [{"txid":"hex","vout":n,"sequence":n},...] [{"address":amount},{"data":"hex"},...] ( locktime options bip32derivs )
|
||||
walletlock
|
||||
walletpassphrase "passphrase" timeout
|
||||
walletpassphrasechange "oldpassphrase" "newpassphrase"
|
||||
walletprocesspsbt "psbt" ( sign "sighashtype" bip32derivs )
|
||||
|
||||
== Zmq ==
|
||||
getzmqnotifications
|
||||
```
|
||||
Podemos digitar também `bitcoin-cli help [command]` para obtermos informações ainda mais detalhadas sobre aquele comando. Por exemplo:
|
||||
```
|
||||
$ bitcoin-cli help getmininginfo
|
||||
...
|
||||
Returns a json object containing mining-related information.
|
||||
Result:
|
||||
{ (json object)
|
||||
"blocks" : n, (numeric) The current block
|
||||
"currentblockweight" : n, (numeric, optional) The block weight of the last assembled block (only present if a block was ever assembled)
|
||||
"currentblocktx" : n, (numeric, optional) The number of block transactions of the last assembled block (only present if a block was ever assembled)
|
||||
"difficulty" : n, (numeric) The current difficulty
|
||||
"networkhashps" : n, (numeric) The network hashes per second
|
||||
"pooledtx" : n, (numeric) The size of the mempool
|
||||
"chain" : "str", (string) current network name (main, test, regtest)
|
||||
"warnings" : "str" (string) any network and blockchain warnings
|
||||
}
|
||||
|
||||
Examples:
|
||||
> bitcoin-cli getmininginfo
|
||||
> curl --user myusername --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getmininginfo", "params": []}' -H 'content-type: text/plain;' http://127.0.0.1:8332/
|
||||
```
|
||||
> :book: ***O que é o RPC?*** O`bitcoin-cli` é apenas uma interface útil que permite enviar comandos para o`bitcoind`. Mais especificamente, é uma interface que permite enviar comandos RPC (Remote Procedure Protocol ou, protocolo de procedimento remoto, no português) para o `bitcoind`. Frequentemente, o comando `bitcoin-cli` e o comando RPC possuem nomes e interfaces idênticos, mas alguns comandos no `bitcoin-cli` fornecem atalhos para solicitações RPC mais complexas. Geralmente, a interface `bitcoin-cli` é muito mais limpa e simples do que tentar enviar comandos RPC manualmente, usando `curl` ou algum outro método. No entanto, ele também tem limitações quanto ao que podemos fazer.
|
||||
|
||||
## Opcional: Conhecendo as informações do node Bitcoin
|
||||
|
||||
Uma variedade de comandos bitcoin-cli podem fornecer informações adicionais sobre nossos node Bitcoin. Os mais comuns são:
|
||||
|
||||
`bitcoin-cli -getinfo` retorna informações do RPCs mais fáceis de serem lidas.
|
||||
|
||||
```diff
|
||||
$ bitcoin-cli -getinfo
|
||||
|
||||
! Chain: test
|
||||
Blocks: 1977694
|
||||
Headers: 1977694
|
||||
Verification progress: 0.9999993275374796
|
||||
Difficulty: 1
|
||||
|
||||
+ Network: in 0, out 8, total 8
|
||||
Version: 219900
|
||||
Time offset (s): 0
|
||||
Proxy: N/A
|
||||
Min tx relay fee rate (BTC/kvB): 0.00001000
|
||||
|
||||
@@ Wallet: ""@@
|
||||
Keypool size: 1000
|
||||
Unlocked until: 0
|
||||
Transaction fee rate (-paytxfee) (BTC/kvB): 0.00000000
|
||||
|
||||
# Balance: 0.02853102
|
||||
|
||||
- Warnings: unknown new rules activated (versionbit 28)
|
||||
|
||||
```
|
||||
|
||||
Abaixo apresentamos outros comandos para obter informações sobre blockchain, mineração, rede, carteira etc.
|
||||
|
||||
```
|
||||
$ bitcoin-cli getblockchaininfo
|
||||
$ bitcoin-cli getmininginfo
|
||||
$ bitcoin-cli getnetworkinfo
|
||||
$ bitcoin-cli getnettotals
|
||||
$ bitcoin-cli getwalletinfo
|
||||
```
|
||||
Por exemplo, `bitcoin-cli getnetworkinfo` fornece uma variedade de informações sobre nossa configuração e nosso acesso a outras redes:
|
||||
```
|
||||
$ bitcoin-cli getnetworkinfo
|
||||
{
|
||||
"version": 200000,
|
||||
"subversion": "/Satoshi:0.20.0/",
|
||||
"protocolversion": 70015,
|
||||
"localservices": "0000000000000408",
|
||||
"localservicesnames": [
|
||||
"WITNESS",
|
||||
"NETWORK_LIMITED"
|
||||
],
|
||||
"localrelay": true,
|
||||
"timeoffset": 0,
|
||||
"networkactive": true,
|
||||
"connections": 10,
|
||||
"networks": [
|
||||
{
|
||||
"name": "ipv4",
|
||||
"limited": false,
|
||||
"reachable": true,
|
||||
"proxy": "",
|
||||
"proxy_randomize_credentials": false
|
||||
},
|
||||
{
|
||||
"name": "ipv6",
|
||||
"limited": false,
|
||||
"reachable": true,
|
||||
"proxy": "",
|
||||
"proxy_randomize_credentials": false
|
||||
},
|
||||
{
|
||||
"name": "onion",
|
||||
"limited": false,
|
||||
"reachable": true,
|
||||
"proxy": "127.0.0.1:9050",
|
||||
"proxy_randomize_credentials": true
|
||||
}
|
||||
],
|
||||
"relayfee": 0.00001000,
|
||||
"incrementalfee": 0.00001000,
|
||||
"localaddresses": [
|
||||
{
|
||||
"address": "45.79.111.171",
|
||||
"port": 18333,
|
||||
"score": 1
|
||||
},
|
||||
{
|
||||
"address": "2600:3c01::f03c:92ff:fecc:fdb7",
|
||||
"port": 18333,
|
||||
"score": 1
|
||||
},
|
||||
{
|
||||
"address": "4wrr3ktm6gl4sojx.onion",
|
||||
"port": 18333,
|
||||
"score": 4
|
||||
}
|
||||
],
|
||||
"warnings": "Warning: unknown new rules activated (versionbit 28)"
|
||||
}
|
||||
```
|
||||
|
||||
Vamos testar à vontade qualquer um deles e usar `bitcoin-cli help` se quisermos saber mais informações sobre o que qualquer um deles faz.
|
||||
|
||||
## Resumo do Conhecendo a configuração do seu node Bitcoin
|
||||
|
||||
O diretório `~/.bitcoin` contém todos os arquivos, enquanto o `bitcoin-cli help` nos retorna uma variedade de informações de comandos que podem ser usados para obter mais informações sobre como nossa configuração e o Bitcoin funcionam.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Vamos continuar "Compreendendo a configuração do node Bitcoin" na sessão [3.3: Configurando nossa carteira](03_3_Setting_Up_Your_Wallet.md).
|
132
pt/03_3_Setting_Up_Your_Wallet.md
Normal file
132
pt/03_3_Setting_Up_Your_Wallet.md
Normal file
@ -0,0 +1,132 @@
|
||||
|
||||
# 3.3: Configurando nossa carteira
|
||||
|
||||
Agora estamos prontos para começar a brincar com o Bitcoin. Para começar, precisaremos criar um endereço para receber fundos.
|
||||
|
||||
## Criando um endereço
|
||||
|
||||
A primeira coisa que precisamos fazer é criar um endereço para recebimento de pagamentos. Podemos fazer isso usando o comando `bitcoin-cli getnewaddress`. Temos que lembrar que se quisermos mais informações sobre este comando, podemos digitar `bitcoin-cli help getnewaddress`. Atualmente, existem três tipos de endereços: Os `legacy` e os dois tipos de endereço SegWit, `p2sh-segwit` e `bech32`. Se não especificarmos qual queremos criar, sempre teremos por padrão o `bech32`.
|
||||
|
||||
No entanto, nas próximas sessões, usaremos endereços `legacy`, porque o `bitcoin-cli` teve alguns problemas com suas versões anteriores usando os endereços SegWit e, porque algumas pessoas podem não ser capazes de enviar seus saldos para endereços `bech32`. É improvável que tudo isso seja um problema para nós neste exato momento, mas vamos começar com exemplos de transações que (na maioria das vezes) temos a garantia que irá funcionar.
|
||||
|
||||
Podemos exigir um endereço `legacy` como segundo argumento para `getnewaddress` ou com o argumento denominado `addresstype`.
|
||||
|
||||
```
|
||||
$ bitcoin-cli getnewaddress -addresstype legacy
|
||||
moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B
|
||||
```
|
||||
|
||||
Observe que este endereço começa com "m" (ou às vezes um "n") para significar um endereço legacy na rede Testnet. Seria um "2" para um endereço P2SH ou um "tb1" para um endereço Bech32.
|
||||
|
||||
> :link: **TESTNET vs MAINNET:** O endereço Mainnet equivalente começaria com "1" (para Legacy), "3" (para P2SH) ou "bc1" (para Bech32).
|
||||
|
||||
Anote cuidadosamente o endereço. Precisaremos utilizá-lo para quando recebermos bitcoins.
|
||||
|
||||
> :book: ***O que é um endereço Bitcoin?*** Um endereço Bitcoin é literalmente onde receberemos as moedas. É como um endereço de e-mail, mas para bitcoin. Tecnicamente, é uma chave pública. No entanto, ao contrário de um endereço de e-mail, um endereço Bitcoin deve ser considerado de uso único: Vamos usar para receber fundos apenas _uma vez_. Quando quisermos receber fundos de outra pessoa ou em algum outro momento, precisaremos gerar um novo endereço. Isso é sugerido em grande parte para melhorar nossa privacidade. Toda a blockchain é imutável, o que significa que os exploradores podem observar longas cadeias de transações ao longo do tempo, tornando possível determinar estatisticamente quem é você e quem são os nossos contatos, não importa o quão cuidadoso sejamos. No entanto, se continuarmos reutilizando o mesmo endereço, isso se tornará ainda mais fácil.
|
||||
|
||||
> :book: ***O que é uma carteira Bitcoin?*** Ao criar nosso primeiro endereço Bitcoin, também começamos a preencher nossa carteira Bitcoin. Mais precisamente, começamos a preencher o arquivo `wallet.dat` no nosso diretório `~/.bitcoin/testnet3/wallets`. O arquivo `wallet.dat` contém dados sobre preferências e transações, mas mais importante, contém todos os pares de chaves que criamos: A chave pública (que é a fonte do endereço onde receberemos as moedas) e a chave privada (que é como gastamos esses fundos). Na maior parte, não teremos que nos preocupar com a chave privada: O `bitcoind` irá usá-la quando for necessário. No entanto, isso torna o arquivo `wallet.dat` extremamente importante: Se o perdermos, perderemos nossas chaves privadas e, se perdermos as chaves privadas, perderemos nossos fundos!
|
||||
|
||||
Com um único endereço em mãos, podemos pular direto para a próxima seção e começar a receber alguns satoshinhos. No entanto, antes de chegarmos lá, vamos discutir brevemente os outros tipos de endereços que encontraremos no futuro e falar sobre alguns outros comandos de carteira que podemos querer usar mais pra frente.
|
||||
|
||||
### Conhecendo os endereços do Bitcoin
|
||||
|
||||
Existem três tipos de endereços Bitcoin que podemos criar com o comando RPC `getnewaddress`. Usaremos um endereço `legacy` (P2PKH) aqui, mas iremos utilizar um endereço SegWit (P2SH-SegWit) ou Bech32 na sessão [4.6: Criação de uma transação Segwit](04_6_Creating_a_Segwit_Transaction.md).
|
||||
|
||||
Conforme observado acima, a base de um endereço de Bitcoin é uma chave pública: Alguém envia fundos para nossa chave pública e usamos a nossa chave privada para resgatá-la. Simples, não? Exceto que colocar nossa chave pública lá não é algo seguro. No momento, se alguém tiver nossa chave pública, não poderemos recuperar nossa chave privada (e, portanto, nossos fundos). Essa é a base da criptografia, que usa uma função de _trapdoor_ para garantir que só possamos passar da chave privada para a pública, e não vice-versa. Mas o problema é que não sabemos o que o futuro pode nos trazer. Exceto que sabemos que os sistemas de criptografia eventualmente são quebrados pelo avanço implacável da tecnologia, então é melhor não colocar chaves públicas brutas na rede, para prepararmos nossas transações para o futuro.
|
||||
|
||||
As transações clássicas do Bitcoin criaram endereços P2PKH que adicionaram uma etapa criptográfica adicional para proteger as chaves públicas.
|
||||
|
||||
> :book: ***O que é um endereço legacy (P2PKH)?*** Este é um endereço legado do tipo usado pela antiga rede Bitcoin. Iremos usá-lo em exemplos nas próximas seções. É chamado de endereço Pay to PubKey Hash (ou P2PKH) porque o endereço é um hash de 160 bits de uma chave pública. Usar um hash de sua chave pública como endereço cria um processo de duas etapas onde para gastar os fundos precisamos revelar a chave privada e a chave pública, aumentando assim a segurança futura. Esse tipo de endereço continua sendo importante para receber fundos de pessoas com softwares desatualizados.
|
||||
|
||||
Conforme descrito mais detalhadamente na sessão [4.6: Criando uma transação Segwit](04_6_Creating_a_Segwit_Transaction.md), a Guerra pelo Tamanho dos Blocos do final dos anos 10 do Bitcoin resultaram em um novo tipo de endereço: O SegWit. Este é o tipo de endereço preferido atualmente e deve estar totalmente integrado ao Bitcoin-Core neste exato momento.
|
||||
|
||||
O SegWit significa simplesmente "Segregated Witness" e é uma maneira de separar as assinaturas da transação do resto dela para reduzir o tamanho da mesma. Alguns endereços SegWit entrarão em alguns de nossos exemplos como endereços de troco, que veremos como endereços que começam com "tb". Isso é bom porque o `bitcoin-cli` suporta inteiramente o seu uso.
|
||||
|
||||
Existem dois endereços desse tipo:
|
||||
|
||||
> :book: ***O que é um endereço P2SH-SegWit (também conhecido como Nested SegWit)?*** Esta é a primeira geração do SegWit. Ele envolve o endereço SegWit em um hash de script para garantir a compatibilidade com versões anteriores. O resultado cria transações que são cerca de 25% menores (com reduções correspondentes nas taxas de transação).
|
||||
|
||||
> :book: ***O que é um endereço Bech32 (também conhecido como SegWit nativo ou como P2WPKH)?*** Esta é a segunda geração do SegWit. Está totalmente descrito em [BIP 173](https://en.bitcoin.it/wiki/BIP_0173). Ele cria transações que são ainda menores, mas mais notavelmente também tem algumas vantagens na criação de endereços que são menos propensos a erro humano e têm algumas correções de erro implícita. Ele _não_ é compatível com versões anteriores como o P2SH-SegWit era e, portanto, algumas pessoas podem não ser capazes de enviar bitcoins para ele.
|
||||
|
||||
Existem outros tipos de endereços de Bitcoin, como P2PK (que paga a uma chave pública simples e está obsoleto devido à sua insegurança futura) e P2SH (que paga a um Hash de script e que é usado pelo SegWit e esta aninhado com a primeira geração endereços. Vamos conhecê-lo mais detalhadamente nos próximos capítulos).
|
||||
|
||||
## Opcional: Assinando uma mensagem
|
||||
|
||||
Às vezes, precisamos provar que controlamos um endereço Bitcoin (ou melhor, que controlamos a chave privada). Isso é importante porque permite que as pessoas saibam que estão enviando fundos para a pessoa certa. Isso pode ser feito criando uma assinatura com o comando `bitcoin-cli signmessage`, na forma `bitcoin-cli signmessage [endereço] [mensagem]`. Por exemplo:
|
||||
|
||||
```
|
||||
$ bitcoin-cli signmessage "moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B" "Hello, World"
|
||||
HyIP0nzdcH12aNbQ2s2rUxLwzG832HxiO1vt8S/jw+W4Ia29lw6hyyaqYOsliYdxne70C6SZ5Utma6QY/trHZBI=
|
||||
```
|
||||
O resultado é uma assinatura como um retorno.
|
||||
|
||||
> :book: ***O que é uma assinatura?*** Uma assinatura digital é uma combinação de uma mensagem e uma chave privada que pode ser desbloqueada com uma chave pública. Como há uma correspondência um-para-um entre os elementos de um par de chaves, o desbloqueio com uma chave pública prova que o assinante controlou a chave privada correspondente.
|
||||
|
||||
Outra pessoa pode usar o comando `bitcoin-cli verifymessage` para verificar a assinatura. Ela insere o endereço em questão, a assinatura e a mensagem:
|
||||
```
|
||||
$ bitcoin-cli verifymessage "moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B" "HyIP0nzdcH12aNbQ2s2rUxLwzG832HxiO1vt8S/jw+W4Ia29lw6hyyaqYOsliYdxne70C6SZ5Utma6QY/trHZBI=" "Hello, World"
|
||||
true
|
||||
```
|
||||
Se todos eles corresponderem, a outra pessoa saberá que pode transferir fundos com segurança para a pessoa que assinou a mensagem enviando para o endereço.
|
||||
|
||||
Se algum golpista estivesse criando assinaturas, isso produziria um erro.
|
||||
```
|
||||
$ bitcoin-cli verifymessage "FAKEV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B" "HyIP0nzdcH12aNbQ2s2rUxLwzG832HxiO1vt8S/jw+W4Ia29lw6hyyaqYOsliYdxne70C6SZ5Utma6QY/trHZBI=" "Hello, World"
|
||||
error code: -3
|
||||
error message:
|
||||
Invalid address
|
||||
```
|
||||
|
||||
## Opcional: Fazendo o dump da nossa carteira
|
||||
|
||||
Pode parecer perigoso ter todas as chaves privadas insubstituíveis em um único arquivo. É para isso que serve o comando `bitcoin-cli dumpwallet`. Ele permite que façamos uma cópia do nosso arquivo `wallet.dat`:
|
||||
```
|
||||
$ bitcoin-cli dumpwallet ~/mywallet.txt
|
||||
```
|
||||
O arquivo `mywallet.txt` em nosso diretório home terá uma longa lista de chaves privadas, endereços e outras informações. Lembre-se, ninguém gostaria de colocar esses dados em um arquivo de texto simples, em uma configuração com saldos reais!
|
||||
|
||||
Podemos então recuperá-los com o `bitcoin-cli importwallet`.
|
||||
```
|
||||
$ bitcoin-cli importwallet ~/mywallet.txt
|
||||
```
|
||||
É importante observar que isso requer um node não prunado.
|
||||
```
|
||||
$ bitcoin-cli importwallet ~/mywallet.txt
|
||||
error code: -4
|
||||
error message:
|
||||
Importing wallets is disabled when blocks are pruned
|
||||
```
|
||||
|
||||
## Opcional: Visualizando as chaves privadas
|
||||
|
||||
Às vezes, podemos querer realmente olhar para as chaves privadas associadas aos nossos endereços Bitcoin. Talvez queremos assinar uma mensagem ou gastar bitcoins em uma máquina diferente. Talvez só estamos querendo fazer backup de algumas chaves privadas importantes. Também pode fazer isso com nosso arquivo criado acima, já que ele pode ser lido por humanos.
|
||||
```
|
||||
$ bitcoin-cli dumpwallet ~/mywallet.txt
|
||||
{
|
||||
"filename": "/home/standup/mywallet.txt"
|
||||
}
|
||||
```
|
||||
Mais provavelmente, desejamos apenas examinar a chave privada associada a um endereço específico. Isso pode ser feito com o comando `bitcoin-cli dumpprivkey`.
|
||||
```
|
||||
$ bitcoin-cli dumpprivkey "moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B"
|
||||
cTv75T4B3NsG92tdSxSfzhuaGrzrmc1rJjLKscoQZXqNRs5tpYhH
|
||||
```
|
||||
Podemos salvar essa chave em um local seguro, de preferência em algum lugar sem conexão com a Internet.
|
||||
|
||||
Também podemos importar qualquer chave privada, de um dump de carteira ou um dump da chave individual, da seguinte maneira:
|
||||
```
|
||||
$ bitcoin-cli importprivkey cW4s4MdW7BkUmqiKgYzSJdmvnzq8QDrf6gszPMC7eLmfcdoRHtHh
|
||||
```
|
||||
Novamente, é esperado que isso exija um node não prunado. Isso provavelmente vai demorar um pouco, já que o `bitcoind` precisa reler todas as transações anteriores, para ver se há alguma nova.
|
||||
|
||||
> :information_source: **NOTA:** Muitas carteiras modernas preferem [códigos mnemônicos](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) para gerar as seeds necessárias para criar as chaves privadas. Esta metodologia não é usada pelo `bitcoin-cli`, então não seremos capazes de gerar listas de palavras para lembrar das nossas chaves privadas.
|
||||
|
||||
_Nós digitamos aquele endereço Bitcoin que gerou, enquanto assinávamos uma mensagem e agora estamos fazendo o dump as chaves. Se por acaso achar que isso é muito complicado, os autores e tradutores também concordam com isso. Também estamos sujeitos a erros, um tópico que abordaremos na próxima sessão._
|
||||
|
||||
## Resumo do Configurando nossa carteira
|
||||
|
||||
Precisamos criar um endereço para receber fundos. Nosso endereço é armazenado em uma carteira, da qual podemos fazer o backup. Podemos fazer muito coisas com nosso endereço, como fazer o dump da nossa chave privada ou usá-la para assinar mensagens. Mas, realmente, criar esse endereço é _tudo_ que precisaremos fazer para receber alguns satoshinhos.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Vamos dar uma pausa no capítulo "Compreendendo a configuração do node Bitcoin" na sessão [Usando variáveis de linha de comando](03_3__Interlude_Using_Command-Line_Variables.md).
|
40
pt/03_3__Interlude_Using_Command-Line_Variables.md
Normal file
40
pt/03_3__Interlude_Using_Command-Line_Variables.md
Normal file
@ -0,0 +1,40 @@
|
||||
# Usando variáveis de linha de comando
|
||||
|
||||
A sessão anterior demonstrou vários comandos de linha de comando usados sem ofuscação ou interferência. No entanto, geralmente essa não é a melhor maneira de executar o Bitcoin usando a linha de comando. Como estamos lidando com variáveis longas, complexas e difíceis de serem lidas, é fácil cometer um erro se estivermos copiando essas variáveis (ou, perder alguns satoshis, se as digitarmos manualmente). Como essas variáveis podem significar a diferença entre receber e perder dinheiro quando usarmos a Mainnet, não _queremos_ cometer erros. Por esses motivos, sugerimos enfaticamente o uso de variáveis de linha de comando para salvar endereços, assinaturas ou outras cadeias de informações longas sempre que isso for razoável.
|
||||
|
||||
Se estiver usando `bash`, podemos salvar as informações em uma variável como esta:
|
||||
```
|
||||
$ VARIABLE=$(command)
|
||||
```
|
||||
|
||||
Esta é uma substituição de um comando simples, o equivalente a `VARIABLE = command`. O comando entre parênteses é executado e, em seguida, atribuído à VARIABLE.
|
||||
|
||||
Para criar um novo endereço, seria assim:
|
||||
```
|
||||
$ unset NEW_ADDRESS_1
|
||||
$ NEW_ADDRESS_1=$(bitcoin-cli getnewaddress "" legacy)
|
||||
```
|
||||
Esses comandos limpam a variável NEW_ADDRESS_1, apenas para ter certeza, e então a preenchem com os resultados do comando `bitcoin-cli getnewaddress`.
|
||||
|
||||
Podemos então usar o comando `echo` do shell para vermos nosso (novo) endereço:
|
||||
```
|
||||
$ echo $NEW_ADDRESS_1
|
||||
mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE
|
||||
```
|
||||
Como nosso endereço está em uma variável, agora podemos assinar facilmente uma mensagem para esse endereço, sem nos preocupar em digitar o endereço incorretamente. É claro que também salvaremos essa assinatura em uma variável!
|
||||
```
|
||||
$ NEW_SIG_1=$(bitcoin-cli signmessage $NEW_ADDRESS_1 "Hello, World")
|
||||
$ echo $NEW_SIG_1
|
||||
IPYIzgj+Rg4bxDwCyoPiFiNNcxWHYxgVcklhmN8aB2XRRJqV731Xu9XkfZ6oxj+QGCRmTe80X81EpXtmGUpXOM4=
|
||||
```
|
||||
O restante deste tutorial usará esse estilo de armazenamento de informações quando for mais prático.
|
||||
|
||||
> :book: ***Quando não é prático usar variáveis de linha de comando?*** Variáveis de linha de comando não são práticas se precisarmos usar as informações em algum lugar diferente da linha de comando. Por exemplo, salvar a assinatura pode não ser útil se tivermos que enviá-la a outra pessoa por e-mail. Além disso, alguns comandos futuros produzirão objetos JSON ao invés de informações simples, e as variáveis não podem ser usadas para capturar essas informações, ao menos não sem um _pouco_ mais de mais trabalho.
|
||||
|
||||
## Resumo do Usando variáveis de linha de comando
|
||||
|
||||
Variáveis de shell podem ser usadas para manter longas strings, minimizando as chances de erros.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Vamos continuar "Compreendendo a configuração do node Bitcoin" na sessão [3.4: Recebendo uma transação](03_4_Receiving_a_Transaction.md).
|
29
pt/04_0_Sending_Bitcoin_Transactions.md
Normal file
29
pt/04_0_Sending_Bitcoin_Transactions.md
Normal file
@ -0,0 +1,29 @@
|
||||
# Capítulo 4: Enviando Transações no Bitcoin
|
||||
|
||||
Este capítulo descreve três métodos diferentes para enviar bitcoins para endereços P2PKH normais à partir da linha de comando, usando apenas o ```bitcoin-cli```.
|
||||
|
||||
## Objetivos deste Capítulo
|
||||
|
||||
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
|
||||
|
||||
* Decidir como enviar dinheiro usando o Bitcoin;
|
||||
* Criar uma transação bruta;
|
||||
* Usar aritmética para calcular as taxas.
|
||||
|
||||
Os objetivos secundários incluem a capacidade de:
|
||||
|
||||
* Compreender transações e taxas de transação;
|
||||
* Entender as transações ```legacy``` e ```SegWit```;
|
||||
* Usar métodos básicos para enviar dinheiro;
|
||||
* Usar métodos de cálculo de taxa automática para enviar dinheiro;
|
||||
* Entender os perigos de transações brutas.
|
||||
|
||||
## Tabela de Conteúdo
|
||||
|
||||
* [Seção 1: Enviando Moedas da Maneira Fácil](04_1_Sending_Coins_The_Easy_Way.md)
|
||||
* [Seção 2: Criando uma Transação Bruta](04_2_Creating_a_Raw_Transaction.md)
|
||||
* [Prefácio: Usando JQ](04_2__Interlude_Using_JQ.md)
|
||||
* [Seção 3: Criando uma Transação Bruta com Argumentos Nomeados](04_3_Creating_a_Raw_Transaction_with_Named_Arguments.md)
|
||||
* [Seção 4: Enviando Moedas com Transações Brutas](04_4_Sending_Coins_with_a_Raw_Transaction.md)
|
||||
* [Seção 5: Enviando Moedas com Transações Brutas Automatizadas](04_5_Sending_Coins_with_Automated_Raw_Transactions.md)
|
||||
* [Seção 6: Criando uma Transação SegWit](04_6_Creating_a_Segwit_Transaction.md)
|
102
pt/04_1_Sending_Coins_The_Easy_Way.md
Normal file
102
pt/04_1_Sending_Coins_The_Easy_Way.md
Normal file
@ -0,0 +1,102 @@
|
||||
# 4.1: Enviando Moedas da Maneira Fácil
|
||||
|
||||
O ```bitcoin-cli``` oferece três principais maneiras de enviar bitcoins: Utilizando um simples comando; Utilizando uma transação bruta e; Utilizando uma transação bruta com cálculos. Cada uma possui seus prós e contras. Este primeiro método de envio será o mais simples.
|
||||
|
||||
## Definindo Sua Taxa de Transação
|
||||
|
||||
Antes de enviar qualquer bitcoin pela rede, devemos pensar sobre as taxas de transação que iremos pagar.
|
||||
|
||||
> :book: ***O que é uma taxa de transação?*** Não existe almoço grátis. Os mineradores adicionam as transações nos blocos porque são pagos para fazer isso. Eles não apenas são pagos pela rede para criar o bloco, mas também são pagos pelas pessoas que realizam as transações para incluí-las na blockchain. Se não pagarmos a taxa, nossa transação pode ficar travada... para sempre (ou, até que seja salva por alguns dos truques que falaremos no [capítulo cinco](05_0_Controlling_Bitcoin_Transactions.md)).
|
||||
|
||||
Ao usar métodos simples e automatizados para criar transações, conforme descrito aqui e na sessão [§4.5: Enviando Moedas com Transações Brutas Automatizadas](04_5_Sending_Coins_with_Automated_Raw_Transactions.md), o Bitcoin calculará as taxas de transação para nós. Isso é feito usando taxas flutuantes, onde o ```bitcoind``` observa quanto tempo as transações estão demorando para confirmar e calcula automaticamente o que devemos gastar.
|
||||
|
||||
Podemos ter um controle dessas informações colocando os valores racionais no nosso arquivo ```~/.bitcoin/bitcoin.conf```. Os valores de baixo custo a seguir garantiríam que houvesse uma taxa de transação mínima de 10.000 satoshis por kByte de dados em nossa transação e solicitaríam que as taxas flutuantes calculassem uma boa quantia para colocar a nossa transação nos próximos seis blocos.
|
||||
```
|
||||
mintxfee=0.0001
|
||||
txconfirmtarget=6
|
||||
```
|
||||
No entanto, como iremos partir do pressuposto que ninguém que esteja fazendo este tutorial queira esperar para as transações serem confirmadas, vamos adotar os seguintes valores:
|
||||
```
|
||||
mintxfee=0.001
|
||||
txconfirmtarget=1
|
||||
```
|
||||
Devemos inserí-los no arquivo ```~/.bitcoin/bitcoin.conf```, na seção principal, no início do arquivo ou se quisermos ter a certeza que nunca iremos utilizá-lo em outro lugar, podemos colocar na seção ```[test]```.
|
||||
|
||||
Para trabalharmos neste tutorial, estamos dispostos a gastar 100.000 satoshis por kB em cada transação, e queremos colocar cada transação no próximo bloco! Para colocar isso em uma perspectiva para melhor entendimento, uma transação simples é executada com um tamanho de 0,25 KB a 1 KB, então estaremos pagando algo em torno de 25 mil a 100 mil satoshis, sendo que atualmente, taxas acima de 10 mil são consideradas altíssimas para transações de quantidade média.
|
||||
|
||||
Depois de editar o arquivo ```bitcoin.conf```, vamos reiniciar o bitcoind usando dois comandos:
|
||||
```
|
||||
$ bitcoin-cli stop
|
||||
$ bitcoind -daemon
|
||||
```
|
||||
|
||||
## Obtendo um Endereço
|
||||
|
||||
Precisamos encontrar algum endereço para qual enviar nossas moedas. Normalmente, alguém nos envia um endereço e talvez nos dê uma assinatura para provar que é o proprietário desse endereço. Como alternativa, podemos fornecer um QR code para que possamos digitalizar, evitando assim possíveis erros de digitação na hora de colocar o endereço no local do destinatário. Em nosso caso, vamos enviar os bitcoins para `n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi`, que é o endereço de retorno de um antigo faucet da rede Testenet.
|
||||
|
||||
> :book: ***O que é um QR code?*** Um QR code é apenas um jeito diferente de passar o endereço Bitcoin. Muitas carteiras geram os QR codes para nós, enquanto alguns sites tentam convertê-los em um endereço usando o QR code. Obviamente, só podemos aceitar um QR code de um site no qual confiamos. Um pagador pode usar um leitor de código de barras para ler o código QR e, em seguida, pagá-lo.
|
||||
|
||||
## Enviando os Bitcoins
|
||||
|
||||
Agora estamos prontos para enviar alguns bitcoins. Na verdade, isso é bastante simples por meio da linha de comando. Basta usar ```bitcoin-cli sendtoaddress [endereço] [quantidade]```. Portanto, para enviar uns satoshinhos para o endereço `n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi`, basta fazer o seguinte:
|
||||
```
|
||||
$ txid=$(bitcoin-cli sendtoaddress n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi 0.001)
|
||||
$ echo $txid
|
||||
93250d0cacb0361b8e21030ac65bc4c2159a53de1075425d800b2d7a8ab13ba8
|
||||
```
|
||||
|
||||
> 🙏 Para ajudar a manter os faucets da rede de testes vivos, tente usar o endereço que nos foi enviado os bitcoins no capítulo anterior, onde falamos sobre os recebimentos de transações.
|
||||
|
||||
Precisamos nos certificar de que o endereço digitado é o lugar para onde desejamos enviá-lo. Por isso, certifique-se _duas vezes_. Se cometermos algum erro no Bitcoin, não há como voltar atrás.
|
||||
|
||||
Iremos receber um txid de retorno quando usarmos este comando.
|
||||
|
||||
> ❕ Você pode acabar com um código de erro se não tivermos bitcoins suficientes na carteira para fazer a transação. Dependendo do nosso saldo atual, que podemos acessar usando o ```bitcoin-cli getbalance```, pode ser necessário ajustar o valor que iremos enviar para que bata com o valor que está sendo enviado, não se esquecendo da taxa de transação no meio deste processo. Se o nosso saldo atual for 0,001, podemos tentar enviar 0,0001. Como alternativa, seria melhor tirar a taxa que esperamos pagar que foi enviada na mensagem de erro do nosso saldo atual. Esta é uma boa prática, pois muitas carteiras esperam que calculemos nosso próprio valor + taxas ao fazermos as transações, mesmo dentre as corretoras mais populares.
|
||||
|
||||
> :warning: **ATENÇÃO:** O comando ```bitcoin-cli``` realmente gera comandos usando o JSON-RPC quando está se comunicando com o bitcoind. Eles podem ser muito exigentes. Este é um exemplo: Se listarmos a quantidade de bitcoin sem o zero à esquerda (ou seja usando ".1" em vez de "0.1"), o ```bitcoin-cli``` irá acusar um erro com uma mensagem misteriosa.
|
||||
|
||||
> :warning: **ATENÇÃO:** Mesmo se formos cuidadosos com nossos dados, é possível que haja este erro: _"Fee estimation failed. Fallbackfee is disabled"_. De maneira geral, isso significa que nosso ```bitcoind``` local não tem informações suficientes para estimar as taxas. Não é para vermos isso se tivermos esperado que nossa blockchain sincronize e configure nosso sistema com o Bitcoin Standup. Mas se não estivermos totalmente sincronizados, podemos nos deparar com este erro. Também pode ser que não estejamos usando um ```bitcoin.conf``` padrão: A informação ```blocksonly = 1``` fará com que nosso ```bitcoind``` não consiga estimar as taxas.
|
||||
|
||||
## Examinando Nossa Transação
|
||||
|
||||
Podemos ver nossa transação usando o ID de transação:
|
||||
```
|
||||
{
|
||||
"amount": -0.00100000,
|
||||
"fee": -0.00022200,
|
||||
"confirmations": 0,
|
||||
"trusted": true,
|
||||
"txid": "93250d0cacb0361b8e21030ac65bc4c2159a53de1075425d800b2d7a8ab13ba8",
|
||||
"walletconflicts": [
|
||||
],
|
||||
"time": 1592604194,
|
||||
"timereceived": 1592604194,
|
||||
"bip125-replaceable": "no",
|
||||
"details": [
|
||||
{
|
||||
"address": "n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi",
|
||||
"category": "send",
|
||||
"amount": -0.00100000,
|
||||
"vout": 1,
|
||||
"fee": -0.00022200,
|
||||
"abandoned": false
|
||||
}
|
||||
],
|
||||
"hex": "0200000001e982921bb0189afc486e20bb05cc5825c71a0ba8868043ed04ece9ab0cb12a8e010000006a47304402200fc493a01c5c9d9574f7c321cee6880f7f1df847be71039e2d996f7f75c17b3d02203057f5baa48745ba7ab5f1d4eed11585bd8beab838b1ca03a4138516fe52b3b8012102fd5740996d853ea51a6904cf03257fc11204b0179f344c49739ec5b20b39c9bafeffffff02e8640d0000000000160014d37b6ae4a917bcc873f6395741155f565e2dc7c4a0860100000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac780b1b00"
|
||||
}
|
||||
```
|
||||
Você pode ver não apenas o valor transferido (0,001 BTC), mas também uma taxa de transação (0,000222 BTC), que é cerca de um quarto da taxa mínima de 0,001 BTC/kB que foi definida, o que sugere que a transação foi de cerca de um quarto de kB de tamanho.
|
||||
|
||||
Enquanto esperamos que ela seja confirmada, podemos notar que o ```bitcoin-cli getbalance``` mostra que nosso dinheiro já foi debitado. Da mesma forma, o ```bitcoin-cli listunspent``` mostrará que uma transação inteira foi perdida, mesmo que fosse mais do que o que queríamos enviar. Há uma razão para isso: Sempre que temos moedas entrando, precisamos enviar _tudo_ junto, e temos que fazer um pouco de malabarismos se quisermos realmente ficar com parte dele! Mais uma vez, o ```sendtoaddress``` cuida de tudo isso para nós, o que significa que não precisamos nos preocupar em fazer qualquer alteração até enviar uma transação bruta. Nesse caso, uma nova transação aparecerá com nossa alteração quando nosso envio for incorporado a um bloco.
|
||||
|
||||
## Resumo: Enviando Moedas da Maneira Fácil
|
||||
|
||||
Para enviar moedas facilmente, precisamos nos certificar de que nossos padrões de transação sejam racionais, obtendo um endereço e enviando as nossas moedas para lá. É por isso que esse modo é o mais fácil deles!
|
||||
|
||||
> :fire: ***Qual é o poder de enviar moedas da maneira fácil?***
|
||||
> _As vantagens._ É fácil. Não precisamos nos preocupar com coisas misteriosas como UTXOs. Não precisamos calcular as taxas de transação manualmente, então, é provável que não iremos cometer erros que custem grandes valores. Se o nosso único objetivo é sentar na frente do computador e enviar alguns bitcoins, este é o caminho certo para fazer isso.
|
||||
> _As desvantagens._ É alto nível. Temos muito pouco controle sobre o que está acontecendo e não podemos fazer nada demais. Se estamos planejando desenvolver um software mais complexo utilizando o Bitcoin ou se desejamos um entendimento mais profundo de como o Bitcoin funciona, então a maneira fácil é apenas um carrossel sem graça antes de chegarmos nas montanhas russas.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Vamos continuar "Enviando Transações no Bitcoin" na sessão [§4.2 Criando Uma Transação Bruta](04_2_Creating_a_Raw_Transaction.md).
|
273
pt/04_2_Creating_a_Raw_Transaction.md
Normal file
273
pt/04_2_Creating_a_Raw_Transaction.md
Normal file
@ -0,0 +1,273 @@
|
||||
# 4.2 Criando uma Transação Bruta
|
||||
|
||||
Agora estamos prontos para criar transações brutas no Bitcoin. Isso permite que enviemos dinheiro, mas que criemos as transações com a precisão desejada. Nesta primeira seção, iremos nos concentrar em uma transação simples de uma entrada e uma saída. Este tipo de transação _não_ é realmente útil, porque raramente vamos querer enviar todo o nosso dinheiro para uma pessoa (a menos que estejamos apenas encaminhando, como se estivesse movendo coisas de uma carteira para outra). Portanto, esse _não é o melhor método_ para enviar dinheiro. É apenas um conteúdo fundamental para _realmente_ enviar dinheiro com uma transação bruta.
|
||||
|
||||
## Compreendendo a Transação no Bitcoin
|
||||
|
||||
Antes de mergulhar na criação de transações brutas, devemos nos certificar de que entendemos como uma transação no Bitcoin funciona. Tudo gira entorno dos UTXOs.
|
||||
|
||||
> :book: ***O que é um UTXO?*** Quando recebemos dinheiro em nossa carteira Bitcoin, ele aparece como uma transação individual. Cada uma dessas transações é chamada de "Saída de Transação Não-Gasta" (Unspent Transaction Output em inglês, mais conhecido como UTXO). Não importa se vários pagamentos foram feitos para o mesmo endereço ou para vários endereços: cada transação recebida permanece distinta na carteira como um UTXO.
|
||||
|
||||
Ao criarmos uma nova transação de saída, reunimos um ou mais UTXOs, cada um representando um pouquinho do dinheiro que recebemos. Nós os usamos como entradas para uma nova transação. Juntos, o valor deles deve ser igual ao que desejamos gastar _ou mais do que o total_. Em seguida, geramos uma ou mais saídas, que dão o dinheiro representado pelas entradas a uma ou mais pessoas. Isso cria novos UTXOs para os destinatários, que podem então usá-los para financiar transações futuras.
|
||||
|
||||
Aqui está o truque: _Todos os UTXOs que coletarmos são gastos na íntegra!_ Isso significa que se quisermos enviar apenas parte do dinheiro em um UTXO para outra pessoa, também precisamos gerar uma saída adicional que envia o resto para nós! Por enquanto, não vamos nos preocupar com isso, mas o uso de um endereço de mudança será vital ao passar da teoria deste capítulo para transações mais práticas.
|
||||
|
||||
## Listando as Transações Não-Gastas
|
||||
|
||||
Para criar uma nova transação bruta, devemos saber quais UTXOs estão disponíveis para gastar. Podemos determinar essas informações com o comando ```bitcoin-cli listunspent```:
|
||||
```
|
||||
$ bitcoin-cli listunspent
|
||||
[
|
||||
{
|
||||
"txid": "ca4898d8f950df03d6bfaa00578bd0305d041d24788b630d0c4a32debcac9f36",
|
||||
"vout": 0,
|
||||
"address": "mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a9141b72503639a13f190bf79acf6d76255d772360b788ac",
|
||||
"amount": 0.00010000,
|
||||
"confirmations": 20,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/1']02fd5740996d853ea51a6904cf03257fc11204b0179f344c49739ec5b20b39c9ba)#62rud39c",
|
||||
"safe": true
|
||||
},
|
||||
{
|
||||
"txid": "61f3b7016bf1ecc3987b8805207e79362e4de8026682e149107999b779426e3a",
|
||||
"vout": 1,
|
||||
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
|
||||
"amount": 0.00050000,
|
||||
"confirmations": 3,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
|
||||
"safe": true
|
||||
},
|
||||
{
|
||||
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
|
||||
"vout": 0,
|
||||
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
|
||||
"amount": 0.00022000,
|
||||
"confirmations": 3,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
|
||||
"safe": true
|
||||
}
|
||||
]
|
||||
|
||||
```
|
||||
Esta lista mostra três UTXOs diferentes, no valor de 0,0001, 0,0005 e 0,00022 BTC. Observe que cada um tem o próprio _txid_ distinto e permanece seperado na carteira, até mesmo os dois últimos, que foram enviados para o mesmo endereço.
|
||||
|
||||
Quando quisermos gastar um UTXO, não é suficiente apenas saber o id da transação. Isso porque cada transação pode ter várias saídas! Lembra daquele primeiro valor que o faucet nos enviou? Na transação, parte do dinheiro foi para nós e parte para outra pessoa. O ```txid``` se refere à transação geral, enquanto um ```vout``` diz qual das múltiplas saídas recebemos. Nesta lista, cada uma dessas transações é a primeira ```vout``` de uma transação anterior, mas _não necessariamente é sempre o caso_.
|
||||
|
||||
Portanto, o txid+vout=UTXO. Essa será a base de qualquer transação bruta.
|
||||
|
||||
## Escrevendo uma Transação Bruta Com Uma Saída
|
||||
|
||||
Agora estamos prontos para escrever um exemplo simples de transação bruta que mostra como enviar um UTXO inteiro para outra pessoa. Conforme falamos anteriormente, este não é um caso muito realista.
|
||||
|
||||
> :warning: **ATENÇÃO:** É muito fácil perder dinheiro com uma transação bruta. Considere que todas as instruções sobre como enviar bitcoins por meio de transações brutas são _muito_, _muito_ perigosas. Sempre que estiver enviando moedas na _mainnet_ para outras pessoas, devemos usar um dos outros métodos explicados neste capítulo. Criar transações brutas é extremamente útil se estivermos escrevendo programas para o bitcoin, mas _só_ neste caso. (Por exemplo: ao escrever este exemplo para uma versão anterior deste tutorial, acidentalmente gastamos a transação errada, embora tivéssemos cerca de 10 vezes mais. Quase tudo isso foi enviado para os mineradores.)
|
||||
|
||||
### Preparando a Transação Bruta
|
||||
|
||||
Para as melhores práticas, iremos começar cada transação registrando cuidadosamente os txids e vouts que iremos gastar.
|
||||
|
||||
Nesse caso, vamos gastar um no valor de 0,00050000 BTC porque é o único com um valor decente.
|
||||
```
|
||||
$ utxo_txid="61f3b7016bf1ecc3987b8805207e79362e4de8026682e149107999b779426e3a"
|
||||
$ utxo_vout="1"
|
||||
```
|
||||
Da mesma forma, devemos registrar o endereço do destinatário para ter certeza de que está correto. No nosso exemplo estamos enviando novamente o saldo de volta para o faucet:
|
||||
```
|
||||
$ recipient="n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi"
|
||||
```
|
||||
Como de prache, vamos verificar as variáveis com cuidado, para ter certeza de que são aquilo que esperamos!
|
||||
```
|
||||
$ echo $utxo_txid
|
||||
61f3b7016bf1ecc3987b8805207e79362e4de8026682e149107999b779426e3a
|
||||
$ echo $utxo_vout
|
||||
1
|
||||
$ echo $recipient
|
||||
n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi
|
||||
```
|
||||
Esse destinatário é particularmente importante, porque se bagunçarmos tudo, nosso dinheiro terá dado _tchau tchau_! E como já vimos, escolher a transação errada pode resultar em perda de dinheiro! Portanto, vamos verificar tudo, pelo menos uma vez mais do que a quantidade de costume.
|
||||
|
||||
### Entendendo a Taxa de Transação
|
||||
|
||||
Cada transação tem uma taxa associada. Ela fica _implícita_ quando enviamos uma transação bruta: O valor que vamos pagar como taxa é sempre igual ao valor de entrada menos o valor de saída. Portanto, temos que diminuir um pouco o valor enviado para ter certeza de que nossa transação será realizada.
|
||||
|
||||
> :warning: **ATENÇÃO:** Esta é a parte muito perigosa das transações brutas!! Como gastamos automaticamente toda a quantidade de UTXOs que tivermos, é extremamente importante certificar-se de que sabemos: (1) precisamente quais UTXOs estamos utilizando; (2) exatamente quanto dinheiro ele possui; (3) exatamente quanto dinheiro estamos enviando; e (4) qual é a diferença que ficará para os mineradores. Se errarmos e, por exemplo, usarmos o UTXO errado (um que tenha mais dinheiro do que pensávamos) ou se enviarmos muito pouco dinheiro, o excesso será perdido. _Para sempre_! Não podemos cometer esse erro! Por isso, é importante sabermos as entradas e saídas com _precisão_. Ou melhor, não utilizarmos as transações brutas, exceto como parte de um programa cuidadosamente considerado e verificado três vezes.
|
||||
|
||||
> :book: ***Quanto devemos gastar com taxas de transação?*** [Bitcoin Fees](https://bitcoinfees.21.co/) tem uma ótima avaliação ao vivo. O site diz que "fastest and cheapest transaction fee is currently XXX satoshis/byte" onde o XXX será a quantidade de satoshis por byte que precisaremos pagar e também, "For the median transaction size of YYY bytes, this results in a fee of ZZ,ZZZ satoshis", onde YYY é o tamanho de uma transação média e ZZ,ZZZ é o resultado da multiplicação entre YYY e XXX. No caso, precisamos apenas observar o valor ZZ,ZZZ descrito no site.
|
||||
|
||||
No momento em que este tutorial está sendo escrito, o _Bitcoin Fees_ sugere uma taxa de transação de cerca de 10.000 satoshis, que é o mesmo que 0,0001 BTC. Obviamente, isso é para a mainnet, não para a testnet, mas queremos testar as coisas de forma realista, então iremos utilizar esta quantidade.
|
||||
|
||||
Nesse caso, isso significa que vamos pegar 0,0005 BTC no UTXO que selecionamos, reduzindo a quantidade de 0,0001 BTC para a taxa de transação e enviar os 0,0004 BTC restantes. (E este é um exemplo do porque os micropagamentos não funcionam na rede principal do Bitcoin, porque uma taxa de transação que consome 20% do valor enviado é muito cara, agora imagina se os valores forem menores do que a taxa de transação. Mas é por isso que temos a Lightning.)
|
||||
|
||||
> :warning: **ATENÇÃO:** Quanto menor for a taxa de transação, mais tempo irá demorar para que nossa transação entre na blockchain. O site _Bitcoin Fees_ lista os tempos que precisaremos esperar em relação a quantidade de satoshi por byte. Como os blocos são construídos em média a cada 10 minutos, a mudança de taxa pode significar uma mudança de espera de minutos para algumas horas ou dias! Portanto, escolha uma taxa de transação apropriada para o que estamos enviando. É importante observar que nunca devemos colocar taxas abaixo da quantidade mínima para transação, que é 0,0001 BTC.
|
||||
|
||||
### Escrevendo a Transação Bruta
|
||||
|
||||
Agora estamos prontos para criar a transação bruta. Usaremos o comando ```createrawtransaction```, que pode parecer um pouco intimidante. Isso porque o comando ```createrawtransaction``` não o protege inteiramente do JSON RPC que o ```bitcoin-cli``` utiliza. Ao invés disso, vamos inserir uma matriz JSON para listar os UTXOs que está gastando e um objeto JSON para listar as saídas.
|
||||
|
||||
Este é o formato padrão:
|
||||
```
|
||||
$ bitcoin-cli createrawtransaction
|
||||
'''[
|
||||
{
|
||||
"txid": "'$your_txid'",
|
||||
"vout": '$your_vout'
|
||||
}
|
||||
]'''
|
||||
'''{
|
||||
"'$your_recipient'": bitcoin_amount
|
||||
}'''
|
||||
```
|
||||
|
||||
Não, não é um erro de digitação. Existem todos os tipos de citações malucas, mas confie que elas farão a coisa certa. Vamos usar `'''` para marcar o início e o fim do array e no objeto JSON. Protegendo as palavras normais como ```"this"```, mas não precisamos proteger os números: ```0```. Se forem variáveis, vamos inserir as aspas simples, como ```"'$this_word'"``` e ```'$this_num'```. (Ufa! Não se preocupe, você pega o jeito).
|
||||
|
||||
Aqui está um comando que cria uma transação bruta para enviar $utxo para o $recipient.
|
||||
```
|
||||
$ rawtxhex=$(bitcoin-cli createrawtransaction '''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' '''{ "'$recipient'": 0.0004 }''')
|
||||
$ echo $rawtxhex
|
||||
02000000013a6e4279b799791049e1826602e84d2e36797e2005887b98c3ecf16b01b7f3610100000000ffffffff01409c0000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac00000000
|
||||
```
|
||||
|
||||
### Verificando a Transação Bruta
|
||||
|
||||
Depois disso, devemos verificar a transação bruta com o comando ```decoderawtransaction``` para ter certeza de que faremos a coisa certa.
|
||||
```
|
||||
$ bitcoin-cli decoderawtransaction $rawtxhex
|
||||
{
|
||||
"txid": "dcd2d8f0ec5581b806a1fbe00325e1680c4da67033761b478a26895380cc1298",
|
||||
"hash": "dcd2d8f0ec5581b806a1fbe00325e1680c4da67033761b478a26895380cc1298",
|
||||
"version": 2,
|
||||
"size": 85,
|
||||
"vsize": 85,
|
||||
"weight": 340,
|
||||
"locktime": 0,
|
||||
"vin": [
|
||||
{
|
||||
"txid": "61f3b7016bf1ecc3987b8805207e79362e4de8026682e149107999b779426e3a",
|
||||
"vout": 1,
|
||||
"scriptSig": {
|
||||
"asm": "",
|
||||
"hex": ""
|
||||
},
|
||||
"sequence": 4294967295
|
||||
}
|
||||
],
|
||||
"vout": [
|
||||
{
|
||||
"value": 0.00040000,
|
||||
"n": 0,
|
||||
"scriptPubKey": {
|
||||
"asm": "OP_DUP OP_HASH160 e7c1345fc8f87c68170b3aa798a956c2fe6a9eff OP_EQUALVERIFY OP_CHECKSIG",
|
||||
"hex": "76a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac",
|
||||
"reqSigs": 1,
|
||||
"type": "pubkeyhash",
|
||||
"addresses": [
|
||||
"n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
É importante verificarmos o ```vin```. Estamos gastando a transação certa? Ela contém a quantia de dinheiro esperada? (Vamos verificar com o comando ```bitcoin-cli gettransaction``` e nos certificar de olhar o ```vout``` se está correto). Além disso, vamos verificar o nosso ```vout```. Estamos enviando a quantidade correta? Está indo para o endereço certo? Finalmente, vamos fazer as contas para ter certeza de que o dinheiro que irá para as taxas está correto. O valor do UTXO menos a quantia que está sendo gasta é igual à taxa da transação esperada?
|
||||
|
||||
> :information_source: **NOTA:** Podemos notar que cada entrada tem um número de sequência, definido aqui como 4294967295, que é 0xFFFFFFFF. Esta é a última fronteira das transações Bitcoin, porque é um campo padrão em transações que foram originalmente planejadas para um propósito específico, mas nunca foram totalmente implementadas. Portanto, agora existe esse inteiro parado em transações que podem ser reaproveitadas para outros usos. E, de fato, tem sido. No momento em que este livro foi escrito, havia três usos diferentes para a variável chamada ```nSequence``` no código Bitcoin Core: Ela habilita a possibilidade de RBF, ```nLockTime``` e timelocks relativos. Se não houver nada de estranho acontecendo, o ```nSequence``` será definido como 4294967295. Ajustar para um valor mais baixo sinaliza que coisas especiais estão acontecendo.
|
||||
|
||||
### Assinando a Transação Bruta
|
||||
|
||||
Até o momento, nossa transação bruta é apenas uma teoria: _Podemos_ enviá-la, mas nada irá acontecer. Precisamos fazer algumas coisas para colocá-la na rede.
|
||||
|
||||
Primeiro, precisamos assinar nossa transação bruta:
|
||||
```
|
||||
|
||||
$ bitcoin-cli signrawtransactionwithwallet $rawtxhex
|
||||
{
|
||||
"hex": "02000000013a6e4279b799791049e1826602e84d2e36797e2005887b98c3ecf16b01b7f361010000006a4730440220335d15a2a2ca3ce6a302ce041686739d4a38eb0599a5ea08305de71965268d05022015f77a33cf7d613015b2aba5beb03088033625505ad5d4d0624defdbea22262b01210278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132ffffffff01409c0000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac00000000",
|
||||
"complete": true
|
||||
}
|
||||
$ signedtx="02000000013a6e4279b799791049e1826602e84d2e36797e2005887b98c3ecf16b01b7f361010000006a4730440220335d15a2a2ca3ce6a302ce041686739d4a38eb0599a5ea08305de71965268d05022015f77a33cf7d613015b2aba5beb03088033625505ad5d4d0624defdbea22262b01210278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132ffffffff01409c0000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac00000000"
|
||||
```
|
||||
Observe que capturamos o hexadecimal assinado manualmente, ao invés de tentar analisá-lo a partir do objeto JSON. Um pacote de software chamado "JQ" poderia ter um desempenho melhor, como explicaremos no próximo prefácio.
|
||||
|
||||
### Enviando a Transação Bruta
|
||||
|
||||
Agora temos uma transação bruta pronta para ser usada, mas nada acontece com ela se não a colocarmos na rede, o que iremos fazer com o comando ```sendrawtransaction```. O retorno dele será uma txid:
|
||||
```
|
||||
$ bitcoin-cli sendrawtransaction $signedtx
|
||||
a1fd550d1de727eccde6108c90d4ffec11ed83691e96e119d842b3f390e2f19a
|
||||
```
|
||||
Iremos observar imediatamente que o UTXO e o as nossas moedas foram removidas da nossa carteira:
|
||||
```
|
||||
$ bitcoin-cli listunspent
|
||||
[
|
||||
{
|
||||
"txid": "ca4898d8f950df03d6bfaa00578bd0305d041d24788b630d0c4a32debcac9f36",
|
||||
"vout": 0,
|
||||
"address": "mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a9141b72503639a13f190bf79acf6d76255d772360b788ac",
|
||||
"amount": 0.00010000,
|
||||
"confirmations": 23,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/1']02fd5740996d853ea51a6904cf03257fc11204b0179f344c49739ec5b20b39c9ba)#62rud39c",
|
||||
"safe": true
|
||||
},
|
||||
{
|
||||
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
|
||||
"vout": 0,
|
||||
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
|
||||
"amount": 0.00022000,
|
||||
"confirmations": 6,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
|
||||
"safe": true
|
||||
}
|
||||
]
|
||||
|
||||
$ bitcoin-cli getbalance
|
||||
0.00032000
|
||||
```
|
||||
Logo o ```listtransactions``` deve mostrar uma transação confirmada da categoria 'send'.
|
||||
```
|
||||
{
|
||||
"address": "n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi",
|
||||
"category": "send",
|
||||
"amount": -0.00040000,
|
||||
"vout": 0,
|
||||
"fee": -0.00010000,
|
||||
"confirmations": 1,
|
||||
"trusted": true,
|
||||
"txid": "a1fd550d1de727eccde6108c90d4ffec11ed83691e96e119d842b3f390e2f19a",
|
||||
"walletconflicts": [
|
||||
],
|
||||
"time": 1592608574,
|
||||
"timereceived": 1592608574,
|
||||
"bip125-replaceable": "no",
|
||||
"abandoned": false
|
||||
}
|
||||
```
|
||||
Podemos observar que ele corresponde aos endereços ```txid``` e ```recipient``` (recebedor). Não só mostra o ```amount``` (montante) enviado, mas também mostra a ```fee``` (taxa) da transação. E, a transação já recebeu uma confirmação, porque oferecemos uma taxa que a faria ser colocada em um bloco rapidamente.
|
||||
|
||||
Parabéns! Estamos um pouco mais pobres agora!
|
||||
|
||||
## Resumo: Criando uma Transação Bruta
|
||||
|
||||
Quando satoshinhos entram na nossa carteira Bitcoin, eles permanecem em quantidades distintas, chamadas de UTXOs. Ao criar uma transação bruta para enviar as moedas, usamos um ou mais UTXOs para financiá-la. Podemos então, criar uma transação bruta, assiná-la e enviá-la pela rede Bitcoin. No entanto, esta é apenas uma base do que realmente acontece: geralmente precisaremos criar uma transação bruta com várias saídas para realmente enviar algo na rede Bitcoin!
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Vamos fazer uma pausa do "Enviando Transações no Bitcoin" para lermos o [Prefácio: Usando JQ](04_2__Interlude_Using_JQ.md).
|
429
pt/04_2__Interlude_Using_JQ.md
Normal file
429
pt/04_2__Interlude_Using_JQ.md
Normal file
@ -0,0 +1,429 @@
|
||||
# Prefácio: Usando JQ
|
||||
|
||||
A criação de uma transação bruta revelou como resultados mais complexos do ```bitcoin-cli``` não podem ser salvos facilmente em variáveis de linha de comando. A resposta para isso é usar o JQ, que permite filtrar elementos individuais de dados JSON mais complexos.
|
||||
|
||||
## Instalando JQ
|
||||
|
||||
O JQ está disponível em um [repositório no Github](https://stedolan.github.io/jq/). Basta fazermos o download para Linux, OS X ou Windows, de acordo com o seu sistema operacional.
|
||||
|
||||
Depois de baixar o binário, podemos instalá-lo em nosso sistema. Se estivermos trabalhando em um VPS Debian, fazendo o passo a passo desse curso, nossa instalação será parecida com esta:
|
||||
```
|
||||
$ mv jq-linux64 jq
|
||||
$ sudo /usr/bin/install -m 0755 -o root -g root -t /usr/local/bin jq
|
||||
```
|
||||
> :book: ***O que é JQ?*** O repositório explica melhor, dizendo "O jq é como o sed para dados JSON - você pode usá-lo para dividir, filtrar, mapear e transformar dados estruturados com a mesma facilidade que o sed, awk, e grep permitem que você brinque com o texto".
|
||||
|
||||
## Usando JQ Para Acessar o Valor de um Objeto JSON Pelo Índice
|
||||
|
||||
**Caso de Uso:** _Capturando o hex de uma transação bruta assinada._
|
||||
|
||||
Na seção anterior, o uso de ```signrawtransaction``` não pareceu ser um bom método devido ao fato de não ser capaz de capturar os dados facilmente em variáveis devido a seu retorno no formato JSON:
|
||||
```
|
||||
$ bitcoin-cli signrawtransactionwithwallet $rawtxhex
|
||||
{
|
||||
"hex": "02000000013a6e4279b799791049e1826602e84d2e36797e2005887b98c3ecf16b01b7f361010000006a4730440220335d15a2a2ca3ce6a302ce041686739d4a38eb0599a5ea08305de71965268d05022015f77a33cf7d613015b2aba5beb03088033625505ad5d4d0624defdbea22262b01210278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132ffffffff01409c0000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac00000000",
|
||||
"complete": true
|
||||
}
|
||||
```
|
||||
Felizmente, o JQ pode facilmente capturar os dados desse tipo!
|
||||
|
||||
Para usar o JQ, vamos executar ```jq``` no backend de um pipe e sempre usar a invocação padrão que é ```jq -r '.'```. O ```-r``` diz ao JQ para produzir uma saída bruta, que funcionará para variáveis de linha de comando, enquanto o ```.``` diz ao JQ para mostrar na tela. Protegemos esse argumento com ```' '``` porque precisaremos dessa proteção mais tarde conforme nossas invocações ```jq``` se tornarem mais complexas.
|
||||
|
||||
Para capturar um valor específico de um objeto JSON, basta listar o índice após o ```.```:
|
||||
```
|
||||
$ bitcoin-cli signrawtransactionwithwallet $rawtxhex | jq -r '.hex'
|
||||
02000000013a6e4279b799791049e1826602e84d2e36797e2005887b98c3ecf16b01b7f361010000006a4730440220335d15a2a2ca3ce6a302ce041686739d4a38eb0599a5ea08305de71965268d05022015f77a33cf7d613015b2aba5beb03088033625505ad5d4d0624defdbea22262b01210278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132ffffffff01409c0000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac00000000
|
||||
```
|
||||
Com essa ferramenta em mãos, podemos capturar as informações de objetos JSON para variáveis na linha de comando:
|
||||
```
|
||||
$ signedtx=$(bitcoin-cli signrawtransactionwithwallet $rawtxhex | jq -r '.hex')
|
||||
$ echo $signedtx
|
||||
02000000013a6e4279b799791049e1826602e84d2e36797e2005887b98c3ecf16b01b7f361010000006a4730440220335d15a2a2ca3ce6a302ce041686739d4a38eb0599a5ea08305de71965268d05022015f77a33cf7d613015b2aba5beb03088033625505ad5d4d0624defdbea22262b01210278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132ffffffff01409c0000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac00000000
|
||||
```
|
||||
Podemos usar então essas variáveis facilmente e sem erros:
|
||||
```
|
||||
$ bitcoin-cli sendrawtransaction $signedtx
|
||||
3f9ccb6e16663e66dc119de1866610cc4f7a83079bfec2abf0598ed3adf10a78
|
||||
```
|
||||
## Usando JQ Para Acessar Valores Únicos de um Objeto JSON em um Array Pelo Índice
|
||||
|
||||
**Caso de Uso:** _Capturando o txid e o vout para um UTXO selecionado._
|
||||
|
||||
Extrair dados de um objeto JSON é fácil, mas e se esse objeto JSON estiver em um array JSON? O comando ```listunspent``` oferece um ótimo exemplo, porque geralmente contém várias transações diferentes. E se quisermos capturar as informações específicas de _um_ deles?
|
||||
|
||||
Ao trabalhar com um array JSON, a primeira coisa que precisamos fazer é informar ao JQ qual índice acessar. Por exemplo, podemos estar olhando nosswas transações no ```listunspent``` e decidimos que queremos trabalhar com a segunda. Podemos usar o ```'. [1]'``` para acessar o primeiro elemento. O ```[]``` diz que estamos referenciando um array JSON e o ```0``` diz que queremos o índice 0.
|
||||
```
|
||||
$ bitcoin-cli listunspent | jq -r '.[1]'
|
||||
{
|
||||
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
|
||||
"vout": 0,
|
||||
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
|
||||
"amount": 0.00022,
|
||||
"confirmations": 9,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
|
||||
"safe": true
|
||||
}
|
||||
```
|
||||
Podemos então capturar um valor individual desse array selecionado (1) usando um pipe _dentro_ dos argumentos JQ; e então (2) solicitando o valor específico posteriormente, como no exemplo anterior. Isso iria capturar o ```txid``` do primeiro objeto JSON no array JSON produzido pelo comando ```listunspent```:
|
||||
```
|
||||
$ bitcoin-cli listunspent | jq -r '.[1] | .txid'
|
||||
91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c
|
||||
```
|
||||
Observe cuidadosamente como os ```' '``` circundam toda a expressão JQ _incluindo_ o pipe.
|
||||
|
||||
Este método pode ser usado para preencher variáveis para um UTXO que desejamos utilizar:
|
||||
```
|
||||
$ newtxid=$(bitcoin-cli listunspent | jq -r '.[1] | .txid')
|
||||
$ newvout=$(bitcoin-cli listunspent | jq -r '.[1] | .vout')
|
||||
$ echo $newtxid
|
||||
91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c
|
||||
$ echo $newvout
|
||||
0
|
||||
```
|
||||
Pronto! Agora podemos criar uma nova transação bruta usando nosso primeiro UTXO como entrada, sem ter que digitar qualquer uma das informações do UTXO manualmente!
|
||||
|
||||
## Usando JQ Para Acessar Valores de Objetos JSON Correspondentes em um Array Por Índices
|
||||
|
||||
**Caso de Uso:** _Listar o valor de todos os UTXOs._
|
||||
|
||||
Ao invés de acessar um único valor específico em um objeto JSON específico, podemos acessar todos os valores específicos em todos os objetos JSON. Isso é feito com ```.[]```, Onde nenhum índice é especificado. Por exemplo, podemos listar todos os saldos não gastos:
|
||||
```
|
||||
$ bitcoin-cli listunspent | jq -r '.[] | .amount'
|
||||
0.0001
|
||||
0.00022
|
||||
```
|
||||
|
||||
## Usando JQ Para Cálculos Simples Por Índices
|
||||
|
||||
**Caso de Uso:** _Adicionando o valor de todos os UTXOs não gastos._
|
||||
|
||||
Neste ponto, podemos começar a usar o retorno do JQ para fazermos uma matemática simples. Por exemplo, somar os valores dessas transações não gastas com um script ```awk``` simples nos daria o equivalente ao ```getbalance```:
|
||||
```
|
||||
$ bitcoin-cli listunspent | jq -r '.[] | .amount' | awk '{s+=$1} END {print s}'
|
||||
0.00032
|
||||
$ bitcoin-cli getbalance
|
||||
0.00032000
|
||||
```
|
||||
|
||||
## Usando JQ Para Exibir Vários Valores de um Objeto JSON em um Array Por Vários Índices
|
||||
|
||||
**Caso de Uso:** _Listar as informações de uso para todos os UTXOs._
|
||||
|
||||
O JQ pode capturar facilmente elementos individuais de objetos JSON e arrays e colocar os elementos em variáveis. Esse será o principal uso que iremos fazer nas seções futuras. No entanto, ele também pode ser usado para reduzir grandes quantidades de informações geradas pelo ```bitcoin-cli``` em quantidades razoáveis de informações.
|
||||
|
||||
Por exemplo, podemos querer ver uma lista de todos os nossos UTXOs (```.[]```) E obter uma lista de todas as informações mais importantes (```.txid, .vout, .amount```):
|
||||
```
|
||||
$ bitcoin-cli listunspent | jq -r '.[] | .txid, .vout, .amount'
|
||||
ca4898d8f950df03d6bfaa00578bd0305d041d24788b630d0c4a32debcac9f36
|
||||
0
|
||||
0.0001
|
||||
91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c
|
||||
0
|
||||
0.00022
|
||||
```
|
||||
Isso torna mais fácil decidir quais UTXOs gastar em uma transação bruta, mas não é muito bonito.
|
||||
|
||||
Felizmente, o JQ também permite que sejamos mais sofisticados. Podemos usar as ```{}``` para criar novos objetos JSON (para análise adicional ou para um retorno mais bonito). Também podemos definir o nome do novo índice para cada um dos valores. A saída resultante deve ser muito mais intuitiva e menos sujeita a erros (embora, menos útil para jogar as informações diretamente nas variáveis).
|
||||
|
||||
O exemplo a seguir mostra exatamente a mesma análise do ```listunspent```, mas com cada objeto JSON antigo reconstruído como um novo objeto JSON abreviado, com todos os novos valores nomeados com os índices antigos:
|
||||
```
|
||||
$ bitcoin-cli listunspent | jq -r '.[] | { txid: .txid, vout: .vout, amount: .amount }'
|
||||
{
|
||||
"txid": "ca4898d8f950df03d6bfaa00578bd0305d041d24788b630d0c4a32debcac9f36",
|
||||
"vout": 0,
|
||||
"amount": 0.0001
|
||||
}
|
||||
{
|
||||
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
|
||||
"vout": 0,
|
||||
"amount": 0.00022
|
||||
}
|
||||
```
|
||||
Podemos, é claro, renomear nossos novos índices conforme acharmos necessário. Não há nada de mágico nos nomes originais:
|
||||
```
|
||||
$ bitcoin-cli listunspent | jq -r '.[] | { tx: .txid, output: .vout, bitcoins: .amount }'
|
||||
{
|
||||
"tx": "ca4898d8f950df03d6bfaa00578bd0305d041d24788b630d0c4a32debcac9f36",
|
||||
"output": 0,
|
||||
"bitcoins": 0.0001
|
||||
}
|
||||
{
|
||||
"tx": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
|
||||
"output": 0,
|
||||
"bitcoins": 0.00022
|
||||
}
|
||||
```
|
||||
## Usando JQ Para Acessar Objetos JSON Por Valor Pesquisado
|
||||
|
||||
**Caso de Uso:** _Pesquisando automaticamente os UTXOs que estão sendo usados em uma transação._
|
||||
|
||||
As pesquisas JQ até agora têm sido bastante simples: Usamos um índice para pesquisar um ou mais valores em um objeto JSON ou no array. Mas e se quisermos pesquisar um valor em um objeto JSON... usando outro valor? Esse tipo de pesquisa indireta tem aplicabilidade real quando estamos trabalhando com transações criadas usando os UTXOs existentes. Por exemplo, podemos calcular o valor da soma dos UTXOs sendo usados em uma transação, algo de vital importância.
|
||||
|
||||
Este exemplo usa a seguinte transação bruta. Podemos observar que esta é uma transação bruta mais complexa com duas entradas e duas saídas. Aprenderemos como fazer isso nas próximas seções, mas por enquanto, é necessário sermos capazes de oferecer exemplos robustos. Observe que, ao contrário dos nossos exemplos anteriores, neste, temos dois objetos em nosso array ```vin``` e dois em nosso array ```vout```.
|
||||
```
|
||||
$ bitcoin-cli decoderawtransaction $rawtxhex
|
||||
{
|
||||
"txid": "6f83a0b78c598de01915554688592da1d7a3047eacacc8a9be39f5396bf0a07e",
|
||||
"hash": "6f83a0b78c598de01915554688592da1d7a3047eacacc8a9be39f5396bf0a07e",
|
||||
"size": 160,
|
||||
"vsize": 160,
|
||||
"version": 2,
|
||||
"locktime": 0,
|
||||
"vin": [
|
||||
{
|
||||
"txid": "d261b9494eb29084f668e1abd75d331fc2d6525dd206b2f5236753b5448ca12c",
|
||||
"vout": 1,
|
||||
"scriptSig": {
|
||||
"asm": "",
|
||||
"hex": ""
|
||||
},
|
||||
"sequence": 4294967295
|
||||
},
|
||||
{
|
||||
"txid": "c7c7f6371ec19330527325908a544bbf8401191645598301d24b54d37e209e7b",
|
||||
"vout": 1,
|
||||
"scriptSig": {
|
||||
"asm": "",
|
||||
"hex": ""
|
||||
},
|
||||
"sequence": 4294967295
|
||||
}
|
||||
],
|
||||
"vout": [
|
||||
{
|
||||
"value": 1.00000000,
|
||||
"n": 0,
|
||||
"scriptPubKey": {
|
||||
"asm": "OP_DUP OP_HASH160 cfc39be7ea3337c450a0c77a839ad0e160739058 OP_EQUALVERIFY OP_CHECKSIG",
|
||||
"hex": "76a914cfc39be7ea3337c450a0c77a839ad0e16073905888ac",
|
||||
"reqSigs": 1,
|
||||
"type": "pubkeyhash",
|
||||
"addresses": [
|
||||
"mzTWVv2QSgBNqXx7RC56zEhaQPve8C8VS9"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"value": 0.04500000,
|
||||
"n": 1,
|
||||
"scriptPubKey": {
|
||||
"asm": "OP_DUP OP_HASH160 166692bda9f25ced145267bb44286e8ee3963d26 OP_EQUALVERIFY OP_CHECKSIG",
|
||||
"hex": "76a914166692bda9f25ced145267bb44286e8ee3963d2688ac",
|
||||
"reqSigs": 1,
|
||||
"type": "pubkeyhash",
|
||||
"addresses": [
|
||||
"mhZQ3Bih6wi7jP1tpFZrCcyr4NsfCapiZP"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Recuperando Valor(es)
|
||||
|
||||
Suponha que saibamos exatamente como essa transação é construída: sabemos que ela usa dois UTXOs como entrada. Para recuperar o txid para os dois UTXOs, poderíamos usar ```jq``` para consultar o valor .vin da transação e, em seguida, fazer referência ao primeiro índice do .vin e, então, ao valor .txid deste array. Posteriormente, poderíamos fazer o mesmo com o primeiro array e, em seguida, o mesmo com os dois valores .vout de .vin. Fácil:
|
||||
```
|
||||
$ usedtxid1=$(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[0] | .txid')
|
||||
$ echo $usedtxid1
|
||||
d261b9494eb29084f668e1abd75d331fc2d6525dd206b2f5236753b5448ca12c
|
||||
$ usedtxid2=$(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[1] | .txid')
|
||||
$ echo $usedtxid2
|
||||
c7c7f6371ec19330527325908a544bbf8401191645598301d24b54d37e209e7b
|
||||
|
||||
$ usedvout1=$(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[0] | .vout')
|
||||
$ echo $usedvout1
|
||||
1
|
||||
$ usedvout2=$(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[1] | .vout')
|
||||
$ echo $usedvout2
|
||||
1
|
||||
```
|
||||
No entanto, seria melhor ter um caso geral que salvasse _automaticamente_ todos os txids de nossos UTXOs.
|
||||
|
||||
Já sabemos que podemos acessar todos os ```.txid``` usando um valor do array ```.[] ```. Podemos usar isso para criar uma pesquisa geral no .txid:
|
||||
```
|
||||
$ usedtxid=($(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[] | .txid'))
|
||||
$ echo ${usedtxid[0]}
|
||||
d261b9494eb29084f668e1abd75d331fc2d6525dd206b2f5236753b5448ca12c
|
||||
$ echo ${usedtxid[1]}
|
||||
c7c7f6371ec19330527325908a544bbf8401191645598301d24b54d37e209e7b
|
||||
|
||||
$ usedvout=($(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[] | .vout'))
|
||||
$ echo ${usedvout[0]}
|
||||
1
|
||||
$ echo ${usedvout[1]}
|
||||
1
|
||||
```
|
||||
O único truque real aqui é como salvamos as informações usando o shell bash. Ao invés de salvar em uma variável com ```$(command)```, nós salvamos em um array com ```($(command))```. Fomos então capazes de acessar os elementos individuais do array bash com uma construção ```${variable [n]}```. Ao invés disso, poderíamos acessar todo o array usando a ```${variable [@]}```. (E antes que diga algo, ninguém nunca disse que o bash ficaria bonito).
|
||||
|
||||
> :warning: **ATENÇÃO:** Lembre-se sempre de que um UTXO é uma transação _mais_ um vout. Perdemos o vout na primeira vez que escrevemos este exemplo JQ, e ele parou de funcionar quando acabamos com uma situação em que dois ```vouts``` foram enviados da mesma transação.
|
||||
|
||||
### Recuperando o(s) Objeto(s) Relacionado(s)
|
||||
|
||||
Agora podemos usar as informações salvas no ```txid``` e no ```vout``` para referenciar os UTXOs no ```listunspent```. Para encontrar as informações sobre os UTXOs usados pela transação bruta, precisamos examinar todo o array JSON (```[]```) com as transações não-gastas. Podemos então escolher (```select```) objetos JSON individuais que incluam (```contains```) os txids. _Então_ selecionamos (```select```) as transações entre aquelas que _também_ contêm (```contain```) o valor correto.
|
||||
|
||||
O uso de outro nível do pipe é a metodologia padrão do JQ: Pegamos um conjunto de dados, depois a reduzimos para todas as transações relevantes e, em seguida, reduzimos para os valores que foram realmente usados nessas transações. No entanto, os argumentos ```select``` e ```contains``` são algo novo. Eles mostram um pouco da complexidade do JSON que vai além do escopo deste tutorial. Por enquanto, saiba apenas que esta invocação em particular funcionará para capturar objetos correspondentes.
|
||||
|
||||
Para começar de forma simples, vamos selecionar os dois UTXOs, um de cada vez:
|
||||
```
|
||||
$ bitcoin-cli listunspent | jq -r '.[] | select (.txid | contains("'${usedtxid[0]}'")) | select(.vout | contains('${usedvout[0]}'))'
|
||||
{
|
||||
"txid": "d261b9494eb29084f668e1abd75d331fc2d6525dd206b2f5236753b5448ca12c",
|
||||
"vout": 1,
|
||||
"address": "miSrC3FvkPPZgqqvCiQycq7io7wTSVsAFH",
|
||||
"scriptPubKey": "76a91420219e4f3c6bc0f6524d538009e980091b3613e888ac",
|
||||
"amount": 0.9,
|
||||
"confirmations": 6,
|
||||
"spendable": true,
|
||||
"solvable": true
|
||||
}
|
||||
$ bitcoin-cli listunspent | jq -r '.[] | select (.txid | contains("'${usedtxid[1]}'")) | select(.vout | contains('${usedvout[1]}'))'
|
||||
{
|
||||
"txid": "c7c7f6371ec19330527325908a544bbf8401191645598301d24b54d37e209e7b",
|
||||
"vout": 1,
|
||||
"address": "mzizSuAy8aL1ytFijds7pm4MuDPx5aYH5Q",
|
||||
"scriptPubKey": "76a914d2b12da30320e81f2dfa416c5d9499d08f778f9888ac",
|
||||
"amount": 0.4,
|
||||
"confirmations": 5,
|
||||
"spendable": true,
|
||||
"solvable": true
|
||||
}
|
||||
```
|
||||
Ao invés disso, um simples bash usando um loop ```for``` poderia nos dar _todos_ os nossos UTXOs:
|
||||
```
|
||||
$ for ((i=0; i<${#usedtxid[*]}; i++)); do txid=${usedtxid[i]}; vout=${usedvout[i]}; bitcoin-cli listunspent | jq -r '.[] | select (.txid | contains("'${txid}'")) | select(.vout | contains('$vout'))'; done;
|
||||
{
|
||||
"txid": "d261b9494eb29084f668e1abd75d331fc2d6525dd206b2f5236753b5448ca12c",
|
||||
"vout": 1,
|
||||
"address": "miSrC3FvkPPZgqqvCiQycq7io7wTSVsAFH",
|
||||
"scriptPubKey": "76a91420219e4f3c6bc0f6524d538009e980091b3613e888ac",
|
||||
"amount": 0.9,
|
||||
"confirmations": 7,
|
||||
"spendable": true,
|
||||
"solvable": true
|
||||
}
|
||||
{
|
||||
"txid": "c7c7f6371ec19330527325908a544bbf8401191645598301d24b54d37e209e7b",
|
||||
"vout": 1,
|
||||
"address": "mzizSuAy8aL1ytFijds7pm4MuDPx5aYH5Q",
|
||||
"scriptPubKey": "76a914d2b12da30320e81f2dfa416c5d9499d08f778f9888ac",
|
||||
"amount": 0.4,
|
||||
"confirmations": 6,
|
||||
"spendable": true,
|
||||
"solvable": true
|
||||
}
|
||||
|
||||
```
|
||||
Observe que estamos deixando um pouquinho mais feio nosso array ```${#usedtxid[*]}``` para determinar o tamanho dele e, em seguida, acessamos cada valor no array ```usedtxid``` e cada valor no array ```usedvout``` em paralelo, colocando-os em variáveis mais simples para termos um acesso menos feio.
|
||||
|
||||
## Usando JSON Para Cálculos Simples Por Valor
|
||||
|
||||
**Caso de Uso:** _Calcular automaticamente o valor dos UTXOs usados em uma transação._
|
||||
|
||||
Agora podemos ir um passo adiante e solicitar o .amount (ou qualquer outro par índice-valor do JSON) dos UTXOs que estamos recuperando.
|
||||
|
||||
Este exemplo repete o uso dos arrays ```$usedtxid``` e ```$usedvout``` definidos da seguinte forma:
|
||||
|
||||
```
|
||||
$ usedtxid=($(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[] | .txid'))
|
||||
$ usedvout=($(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[] | .vout'))
|
||||
```
|
||||
|
||||
O mesmo script ```for``` pode ser usado para percorrer os arrays, mas com um pipe adicionado no JQ que produz o valor ```amount``` para cada um dos UTXOs selecionados.
|
||||
|
||||
```
|
||||
$ for ((i=0; i<${#usedtxid[*]}; i++)); do txid=${usedtxid[i]}; vout=${usedvout[i]}; bitcoin-cli listunspent | jq -r '.[] | select (.txid | contains("'${txid}'")) | select(.vout | contains('$vout')) | .amount'; done;
|
||||
0.9
|
||||
0.4
|
||||
```
|
||||
|
||||
Neste ponto, podemos somar os .amounts com um script ```awk```, para realmente ver quantas moedas estão nos UTXOs gastos na transação:
|
||||
|
||||
```
|
||||
$ for ((i=0; i<${#usedtxid[*]}; i++)); do txid=${usedtxid[i]}; vout=${usedvout[i]}; bitcoin-cli listunspent | jq -r '.[] | select (.txid | contains("'${txid}'")) | select(.vout | contains('$vout')) | .amount'; done | awk '{s+=$1} END {print s}'
|
||||
1.3
|
||||
```
|
||||
|
||||
Ufa!
|
||||
|
||||
## Usando JQ Para Cálculos Complexos
|
||||
|
||||
**Caso de Uso:** _Calcular a taxa de uma transação._
|
||||
|
||||
Descobrir a taxa completa de transação neste ponto requer apenas mais um pouco de matemática: basta determinar quanto dinheiro está passando pelo .vout. Este é um uso simples de JQ onde apenas usamos o ```awk``` para somar o ```value``` de todas as informações do ```vout```:
|
||||
|
||||
```
|
||||
$ bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vout [] | .value' | awk '{s+=$1} END {print s}'
|
||||
1.045
|
||||
```
|
||||
|
||||
Para completar o cálculo da taxa de transação, vamos subtrair o .vout .amount (1.045) do .vin .amount (1.3).
|
||||
Para fazer isso, precisaremos instalar ```bc```:
|
||||
|
||||
```
|
||||
$ sudo apt-get intall bc
|
||||
```
|
||||
|
||||
Se juntarmos tudo, iremos criar uma calculadora completa com apenas um script de cinco linhas:
|
||||
|
||||
```
|
||||
$ usedtxid=($(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[] | .txid'))
|
||||
$ usedvout=($(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[] | .vout'))
|
||||
$ btcin=$(for ((i=0; i<${#usedtxid[*]}; i++)); do txid=${usedtxid[i]}; vout=${usedvout[i]}; bitcoin-cli listunspent | jq -r '.[] | select (.txid | contains("'${txid}'")) | select(.vout | contains('$vout')) | .amount'; done | awk '{s+=$1} END {print s}')
|
||||
$ btcout=$(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vout [] | .value' | awk '{s+=$1} END {print s}')
|
||||
$ echo "$btcin-$btcout"| /usr/bin/bc
|
||||
.255
|
||||
```
|
||||
|
||||
E esse também é um bom exemplo de por que precisamos verificar nossas taxas: pretendíamos enviar uma taxa de transação com 5.000 satoshis, mas invés disso enviamos pagando 255.000 satoshis de taxa. Ops!
|
||||
|
||||
> :warning: **ATENÇÃO:** A primeira vez que escrevemos esta lição, realmente calculamos mal a nossa taxa e não a vimos até que executamos nossa calculadora de taxas. É *tão* fácil, que nosso dinheiro acabou. (O exemplo acima é, na verdade, de nossa segunda iteração da calculadora, e dessa vez cometemos o erro de propósito).
|
||||
|
||||
Para mais magia usando o JQ (e se alguma coisa não estiver clara), leia o [Manual JQ](https://stedolan.github.io/jq/manual/) e o [Livro de Receitas do JQ](https://github.com/stedolan/jq/wiki/Cookbook). Estaremos usando o JQ regularmente nos exemplos futuros.
|
||||
|
||||
## Fazendo Alguns Aliases Novos
|
||||
|
||||
Código em JQ pode ser um pouco pesado, então devemos considerar adicionar algumas invocações mais longas e interessantes ao nosso ```~/.bash_profile```.
|
||||
|
||||
Sempre que estivermos procurando por uma grande massa de informações em uma saída de objeto JSON por um comando ```bitcoin-cli```, precisamos considerar escrever um alias para reduzi-lo exatamente ao que desejamos observar.
|
||||
|
||||
```
|
||||
alias btcunspent="bitcoin-cli listunspent | jq -r '.[] | { txid: .txid, vout: .vout, amount: .amount }'"
|
||||
```
|
||||
|
||||
## Executando o Script de Taxa de Transação
|
||||
|
||||
O [Script de Cálculo de Taxa](src/04_2_i_txfee-calc.sh) está disponível no diretório `src/`. Você pode baixá-lo e salvá-lo como ```txfee-calc.sh```.
|
||||
|
||||
> :warning: **ATENÇÃO:** Este script não foi verificado extensivamente. Se for usá-lo para verificar as taxas de transação reais, só deve fazê-lo depois de fazer uma verificação pessoal dos valores.
|
||||
|
||||
Certifique-se de que as permissões no script estejam corretas:
|
||||
|
||||
```
|
||||
$ chmod 755 txfee-calc.sh
|
||||
```
|
||||
|
||||
Podemos, então, executar o script da seguinte maneira:
|
||||
|
||||
```
|
||||
$ ./txfee-calc.sh $rawtxhex
|
||||
.255
|
||||
```
|
||||
|
||||
Também podemos criar um alias:
|
||||
|
||||
```
|
||||
alias btctxfee="~/txfee-calc.sh"
|
||||
```
|
||||
|
||||
## Resumo: Usando JQ
|
||||
|
||||
O JQ facilita a extração de informações de arrays e objetos JSON. Ele também pode ser usado em scripts shell para cálculos bastante complexos que tornarão nossa vida mais fácil.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Continue "Enviando Transações no Bitcoin" na sessão [§4.3 Criando uma Transação Bruta com Argumentos Nomeados](04_3_Creating_a_Raw_Transaction_with_Named_Arguments.md).
|
97
pt/04_3_Creating_a_Raw_Transaction_with_Named_Arguments.md
Normal file
97
pt/04_3_Creating_a_Raw_Transaction_with_Named_Arguments.md
Normal file
@ -0,0 +1,97 @@
|
||||
# 4.3 Criando uma Transação Bruta com Argumentos Nomeados
|
||||
|
||||
Às vezes, pode ser assustador descobrir a ordem correta dos argumentos para um comando ```bitcoin-cli```. Felizmente, podemos usar _argumentos nomeados_ como alternativa.
|
||||
|
||||
> :warning: **AVISO DE VERSÃO:** Esta é uma inovação do Bitcoin Core v0.14.0. Se usarmos os scripts de configuração do tutorial, o que é importante fazer, precisamos verificar novamente a versão se tiver algum problema. Há também um bug no uso do comando ```createrawtransaction``` usando argumentos nomeados que presumivelmente serão corrigidos na versão 0.14.1.
|
||||
|
||||
## Criando um Alias de Argumento Nomeado
|
||||
|
||||
Para usar um argumento nomeado, devemos executar o ```bitcoin-cli``` com o argumento ```-named```. Se planejamos fazer isso regularmente, provavelmente precisaremos criar um alias:
|
||||
```
|
||||
alias bitcoin-cli="bitcoin-cli -named"
|
||||
```
|
||||
Como de costume, isso é apenas para facilitar o uso, mas continuaremos usando todos os comandos para manter a clareza.
|
||||
|
||||
## Testando um Argumento Nomeado
|
||||
|
||||
Para saber quais são os nomes dos argumentos de um comando, precisamos consultar o ```bitcoin-cli help```. Ele listará os argumentos com a ordem adequada, mas agora também fornecerá nomes para cada um deles.
|
||||
|
||||
Por exemplo, `bitcoin-cli help getbalance` lista estes argumentos:
|
||||
|
||||
1. dummy [costumava ser account]
|
||||
2. minconf
|
||||
3. include_watchonly
|
||||
4. avoid_reuse
|
||||
|
||||
O exemplo seguinte mostra um uso tradicional e não intuitivo do ```getbalance``` usando o argumento de confirmação mínimo:
|
||||
```
|
||||
$ bitcoin-cli getbalance "*" 1
|
||||
```
|
||||
Com argumentos nomeados, podemos esclarecer o que estamos fazendo, o que também minimiza os erros:
|
||||
```
|
||||
$ bitcoin-cli -named getbalance minconf=1
|
||||
```
|
||||
|
||||
## Testando uma Transação Bruta
|
||||
|
||||
Veja como seriam os comandos para enviar uma transação bruta com argumentos nomeados:
|
||||
```
|
||||
$ utxo_txid=$(bitcoin-cli listunspent | jq -r '.[0] | .txid')
|
||||
$ utxo_vout=$(bitcoin-cli listunspent | jq -r '.[0] | .vout')
|
||||
$ recipient="n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi"
|
||||
|
||||
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.00001 }''')
|
||||
$ bitcoin-cli -named decoderawtransaction hexstring=$rawtxhex
|
||||
{
|
||||
"txid": "2b59c31bc232c0399acee4c2a381b564b6fec295c21044fbcbb899ffa56c3da5",
|
||||
"hash": "2b59c31bc232c0399acee4c2a381b564b6fec295c21044fbcbb899ffa56c3da5",
|
||||
"version": 2,
|
||||
"size": 85,
|
||||
"vsize": 85,
|
||||
"weight": 340,
|
||||
"locktime": 0,
|
||||
"vin": [
|
||||
{
|
||||
"txid": "ca4898d8f950df03d6bfaa00578bd0305d041d24788b630d0c4a32debcac9f36",
|
||||
"vout": 0,
|
||||
"scriptSig": {
|
||||
"asm": "",
|
||||
"hex": ""
|
||||
},
|
||||
"sequence": 4294967295
|
||||
}
|
||||
],
|
||||
"vout": [
|
||||
{
|
||||
"value": 0.00001000,
|
||||
"n": 0,
|
||||
"scriptPubKey": {
|
||||
"asm": "OP_DUP OP_HASH160 e7c1345fc8f87c68170b3aa798a956c2fe6a9eff OP_EQUALVERIFY OP_CHECKSIG",
|
||||
"hex": "76a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac",
|
||||
"reqSigs": 1,
|
||||
"type": "pubkeyhash",
|
||||
"addresses": [
|
||||
"n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
$ signedtx=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex | jq -r '.hex')
|
||||
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
|
||||
e70dd2aa13422d12c222481c17ca21a57071f92ff86bdcffd7eaca71772ba172
|
||||
```
|
||||
Pronto! Enviamos outra transação bruta, mas desta vez usando argumentos nomeados para maior clareza e redução de erros.
|
||||
|
||||
> :warning: **AVISO DE VERSÃO:** É aqui que o bug no Bitcoin Core 0.14 aparece: O argumento ```inputs``` no ```createrawtransaction``` tem o nome ```transactions``` incorreto. Portanto, se estiver no Bitcoin Core 0.14.0, substitua o argumento nomeado ```inputs``` por ```transactions``` para este e também para os exemplos futuros. No entanto, a partir do Bitcoin Core 0.14.1, este código deve funcionar normalmente.
|
||||
|
||||
## Resumo: Criando uma Transação Bruta com Argumentos Nomeados
|
||||
|
||||
Executando o ```bitcoin-cli``` com o argumento ```-named``` podemos usar argumentos nomeados ao invés de depender de argumentos ordenados. O comando ```bitcoin-cli help``` sempre mostrará o nome correto para cada argumento. Isso pode resultar em um código mais robusto, mais fácil de ler e menos sujeito a erros.
|
||||
|
||||
_À partir de agora, usaremos argumentos nomeados para todos os exemplos futuros, para maior clareza e para estabelecer as melhores práticas. No entanto, também mostraremos todos os argumentos na ordem correta. Portanto, se preferir não usar os argumentos nomeados, apenas retire o argumento ```-named``` e todos os ```name=``` que os exemplos devem continuar funcionando corretamente._
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Continue "Enviando Transações no Bitcoin" na seção [§4.4: Enviando Moedas com Transações Brutas](04_4_Sending_Coins_with_a_Raw_Transaction.md).
|
187
pt/04_4_Sending_Coins_with_a_Raw_Transaction.md
Normal file
187
pt/04_4_Sending_Coins_with_a_Raw_Transaction.md
Normal file
@ -0,0 +1,187 @@
|
||||
# 4.4: Enviando Moedas com Transações Brutas
|
||||
|
||||
Conforme observado no início deste capítulo, a interface ```bitcoin-cli``` oferece três maneiras principais de enviar moedas. A seção [§4.1](04_1_Sending_Coins_The_Easy_Way.md) falou sobre como enviá-la pela primeira vez, usando o comando ```sendtoaddress```. Desde então, estamos construindo coisas mais detalhadas sobre como enviar moedas de uma segunda maneira, com transações brutas. A seção [§4.2](04_2_Creating_a_Raw_Transaction.md) nos ensinou como criar uma transação bruta, um [Prefácio](04_2__Interlude_Using_JQ.md) explicou JQ e a seção [§4.3](04_3_Creating_a_Raw_Transaction_with_Named_Arguments.md) demonstrou os argumentos nomeados.
|
||||
|
||||
Agora podemos colocá-los juntos e realmente enviar fundos usando uma transação bruta.
|
||||
|
||||
## Criando um Endereço de Troco
|
||||
|
||||
Nosso exemplo de transação bruta na seção §4.2 era simples demais: enviamos um UTXO inteiro para um novo endereço. Com mais frequência, iremos desejar enviar a alguém uma quantia em dinheiro que não corresponda a um UTXO. Mas, devemos nos lembrar que o excesso de dinheiro de um UTXO que não é enviado ao destinatário se torna apenas a taxa de transação. Então, como enviar para alguém apenas uma parte de um UTXO, enquanto guardamos o resto para a gente?
|
||||
|
||||
A solução é _enviar_ o restante dos fundos para um segundo endereço, um endereço de troco que criamos em nossa carteira especificamente para recebê-lo:
|
||||
```
|
||||
$ changeaddress=$(bitcoin-cli getrawchangeaddress legacy)
|
||||
$ echo $changeaddress
|
||||
mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h
|
||||
```
|
||||
Observe que isso usa uma nova função: ```getrawchangeaddress```. É basicamente a mesma coisa que o ```getnewaddress```, mas é otimizado para uso como um endereço de troco em uma transação bruta, portanto, não faz coisas como criar entradas em nossa lista de endereços. Selecionamos novamente o endereço ```legacy```, ao invés de usar o padrão ```bech32```, simplesmente para consistência. Esta é uma situação em que teria sido seguro gerar um endereço Bech32 padrão, apenas usando ```bitcoin-cli getrawchangeaddress```, porque ele seria enviado e recebido por nós em nosso node Bitcoin Core, que tem suporte integral a isso. Mas, estamos adiantando as coisas. Mas vamos mudar para Bech32 na seção [§4.6](04_6_Creating_a_Segwit_Transaction.md).
|
||||
|
||||
Agora temos um endereço adicional em nossa carteira, para que possamos receber o troco de um UTXO! Para usá-lo, precisaremos criar uma transação bruta com duas saídas.
|
||||
|
||||
## Escolhendo UTXOs Suficientes
|
||||
|
||||
Nosso exemplo de transação bruta era simples também de outra maneira: assumia que havia dinheiro suficiente em um único UTXO para cobrir toda a transação. Frequentemente, esse será o caso, mas às vezes desejaremos criar transações que gastem mais dinheiro do que temos em um único UTXO. Para fazer isso, devemos criar uma transação bruta com duas (ou mais) entradas.
|
||||
|
||||
## Escrevendo uma Transação Bruta Real
|
||||
|
||||
Para resumir: a criação de uma transação bruta real para enviar moedas, às vezes, requer múltiplas entradas e, quase sempre, múltiplas saídas, uma das quais é um endereço de troco. Estaremos criando esse tipo de transação mais realista, em um exemplo que mostra um caso de uso da vida real, enviando fundos por meio da segunda metodologia do Bitcoin, as transações brutas.
|
||||
|
||||
Vamos usar nossos UTXOs de índice 0 e 2:
|
||||
```
|
||||
$ bitcoin-cli listunspent
|
||||
[
|
||||
[
|
||||
{
|
||||
"txid": "0619fecf6b2668fab1308fbd7b291ac210932602a6ac6b8cc11c7ae22c43701e",
|
||||
"vout": 1,
|
||||
"address": "mwJL7cRiW2bUnY81r1thSu3D4jtMmwyU6d",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a914ad1ed1c5971b2308f89c1362d4705d020a40e8e788ac",
|
||||
"amount": 0.00899999,
|
||||
"confirmations": 1,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/4']03eae28c93035f95a620dd96e1822f2a96e0357263fa1f87606a5254d5b9e6698f)#wwnfx2sp",
|
||||
"safe": true
|
||||
},
|
||||
{
|
||||
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
|
||||
"vout": 0,
|
||||
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
|
||||
"amount": 0.00022000,
|
||||
"confirmations": 15,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
|
||||
"safe": true
|
||||
},
|
||||
{
|
||||
"txid": "0df23a9dba49e822bbc558f15516f33021a64a5c2e48962cec541e0bcc79854d",
|
||||
"vout": 0,
|
||||
"address": "mwJL7cRiW2bUnY81r1thSu3D4jtMmwyU6d",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a914ad1ed1c5971b2308f89c1362d4705d020a40e8e788ac",
|
||||
"amount": 0.00100000,
|
||||
"confirmations": 1,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/4']03eae28c93035f95a620dd96e1822f2a96e0357263fa1f87606a5254d5b9e6698f)#wwnfx2sp",
|
||||
"safe": true
|
||||
}
|
||||
]
|
||||
|
||||
```
|
||||
Em nosso exemplo, enviaremos 0,009 BTC, que é (um pouco) maior do que qualquer um de nossos UTXOs. Para isso, será necessário que os combinemos e, em seguida, vamos usar nosso endereço de troco para recuperar os fundos não gastos.
|
||||
|
||||
### Configurando as Variáveis
|
||||
|
||||
Já temos as variáveis ```$changeaddress``` e ```$recipient``` dos exemplos anteriores:
|
||||
```
|
||||
$ echo $changeaddress
|
||||
mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h
|
||||
$ echo $recipient
|
||||
n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi
|
||||
```
|
||||
Também precisamos registrar o txid e vout para cada um de nossos dois UTXOs. Tendo identificado os UTXOs que queremos gastar, podemos usar as técnicas do JQ para garantir que o acesso a eles esteja livre de erros:
|
||||
```
|
||||
$ utxo_txid_1=$(bitcoin-cli listunspent | jq -r '.[0] | .txid')
|
||||
$ utxo_vout_1=$(bitcoin-cli listunspent | jq -r '.[0] | .vout')
|
||||
$ utxo_txid_2=$(bitcoin-cli listunspent | jq -r '.[2] | .txid')
|
||||
$ utxo_vout_2=$(bitcoin-cli listunspent | jq -r '.[2] | .vout')
|
||||
```
|
||||
|
||||
### Escrevendo a Transação
|
||||
|
||||
Escrever a transação bruta em si é surpreendentemente simples. Tudo o que precisamos fazer é incluir um objeto JSON adicional separado por vírgula no array JSON de entradas e um par de valores-chave adicional separado por vírgula em um objeto JSON de saída.
|
||||
|
||||
Aqui temos um exemplo. Observe as múltiplas entradas após o argumento ```inputs``` e as múltiplas saídas após o argumento ```outputs```.
|
||||
```
|
||||
$ rawtxhex2=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid_1'", "vout": '$utxo_vout_1' }, { "txid": "'$utxo_txid_2'", "vout": '$utxo_vout_2' } ]''' outputs='''{ "'$recipient'": 0.009, "'$changeaddress'": 0.0009 }''')
|
||||
```
|
||||
Fomos _muito_ cuidadosos em calcular a quantidade. Esses dois UTXOs contêm 0,00999999 BTC. Depois de enviar 0,009 BTC, teremos 0,00099999 BTC restantes. Escolhemos 0,00009999 BTC como a nossa taxa de transação. Para acomodar essa taxa, definimos o troco como sendo 0,0009 BTC. Se não tivéssemos prestado atenção e definido nosso troco como 0,00009 BTC, essa quantidade de BTC adicional seria enviada para os mineradores! Se tivéssemos esquecido de fazer o troco, todo o excesso teria desaparecido. Portanto, novamente, _ tenha cuidado_.
|
||||
|
||||
Felizmente, podemos verificar três vezes com o alias ```btctxfee``` do Prefácio do JQ:
|
||||
```
|
||||
$ ./txfee-calc.sh $rawtxhex2
|
||||
.00009999
|
||||
```
|
||||
|
||||
### Concluindo
|
||||
|
||||
Agora podemos assinar, selar e entregar nossa transação, e ela será sua (e do faucet):
|
||||
```
|
||||
$ signedtx2=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex2 | jq -r '.hex')
|
||||
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx2
|
||||
e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d
|
||||
```
|
||||
|
||||
### Esperando
|
||||
|
||||
Como de costume, nossas moedas estarão no fluxo por um tempo: o troco ficará indisponível até que a transação seja realmente confirmada e um novo UTXO nos seja dado.
|
||||
|
||||
Mas, em 10 minutos ou menos (provavelmente), teremos o dinheiro restante de volta e totalmente utilizável novamente. Por enquanto, ainda precisamos esperar:
|
||||
```
|
||||
$ bitcoin-cli listunspent
|
||||
[
|
||||
{
|
||||
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
|
||||
"vout": 0,
|
||||
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
|
||||
"amount": 0.00022000,
|
||||
"confirmations": 15,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
|
||||
"safe": true
|
||||
}
|
||||
]
|
||||
```
|
||||
E o troco eventualmente voltará para nós:
|
||||
```
|
||||
[
|
||||
{
|
||||
"txid": "e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d",
|
||||
"vout": 1,
|
||||
"address": "mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h",
|
||||
"scriptPubKey": "76a91432db726320e4ad170c9c1ee83cd4d8a243c3435988ac",
|
||||
"amount": 0.00090000,
|
||||
"confirmations": 1,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/1'/2']02881697d252d8bf181d08c58de1f02aec088cd2d468fc5fd888c6e39909f7fabf)#p6k7dptk",
|
||||
"safe": true
|
||||
},
|
||||
{
|
||||
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
|
||||
"vout": 0,
|
||||
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
|
||||
"amount": 0.00022000,
|
||||
"confirmations": 16,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
|
||||
"safe": true
|
||||
}
|
||||
]
|
||||
```
|
||||
Este também pode ser um bom momento para revisitar um explorador de blockchain, para que possamos ver mais intuitivamente como as entradas, saídas e taxas estão dispostas na transação: [e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d](https://mempool.space/pt/testnet/tx/e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d).
|
||||
|
||||
## Resumo: Enviando Moedas com Transações Brutas
|
||||
|
||||
Para enviar moedas usando transações brutas, precisamos criar uma transação bruta com uma ou mais entradas (para ter fundos suficientes) e uma ou mais saídas (para recuperar usando o troco). Então, podemos seguir nosso procedimento normal de usar o ```createrawtransaction``` com argumentos nomeados junto com o JQ, conforme descrito nas seções anteriores.
|
||||
|
||||
> :fire: ***Qual é o poder de enviar moedas com transações brutas?***
|
||||
> _As vantagens._ Oferece maior controle. Se o nosso objetivo é escrever um programa ou script Bitcoin mais complexo, provavelmente usaremos as transações brutas para saber exatamente o que está acontecendo. Essa também é a situação mais _segura_ para usar transações brutas, porque podemos garantir que não cometeremos nenhum erro na parte da programação.
|
||||
> _As desvantagens._ É muito fácil perder dinheiro. Não há avisos, bloqueios e barreiras na programação, a não ser que as criemos. Também é tudo muito misterioso. A formatação é desagradável, mesmo usando a interface ```bitcoin-cli``` que é fácil de usar, e temos que fazer muitas pesquisas e cálculos manualmente.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Veja uma forma alternativa de inserir comandos no [Prefácio: Usando JQ](04_4__Interlude_Using_Curl.md).
|
||||
|
||||
Ou, se preferir pular o que é francamente uma digressão, podemos aprender mais uma forma de enviar transações no Bitcoin na seção [§4.5 Enviando Moedas com Transações Brutas Automatizadas](04_5_Sending_Coins_with_Automated_Raw_Transactions.md).
|
312
pt/04_4__Interlude_Using_Curl.md
Normal file
312
pt/04_4__Interlude_Using_Curl.md
Normal file
@ -0,0 +1,312 @@
|
||||
# Prefácio: Usando Curl
|
||||
|
||||
O ```bitcoin-cli``` é, em última análise, apenas um invólucro. É uma forma de interagir com ```bitcoind``` a partir da linha de comando, fornecendo acesso simplificado aos seus diversos comandos RPC. Mas o RPC pode, é claro, ser acessado diretamente. É disso que iremos falar nessa seção: como nos conectarmos diretamente ao RPC com o comando ```curl```.
|
||||
|
||||
Não será muito usado nos próximos capítulos, mas essas informações serão importantes caso queiramos uma alternativa para acessar o ```bitcoind```.
|
||||
|
||||
## Conhecendo o Curl
|
||||
|
||||
O ```curl```, abreviação de "ver URL" ("see URL" em inglês), é uma ferramenta que nos permite acessar URLs diretamente pela linha de comando. É uma maneira fácil de interagir com servidores como o ```bitcoind```, que ficam ouvindo as portas da internet e conversam utilizando uma variedade de protocolos. O Curl também está disponível como uma biblioteca para muitas linguagens de programação, como C, Java, PHP e Python. Então, depois de saber como trabalhar com o Curl, teremos uma base sólida para usar várias APIs diferentes.
|
||||
|
||||
Para usar o ```curl``` com o ```bitcoind```, devemos saber três coisas: o formato padrão, o nome de usuário e senha e a porta correta.
|
||||
|
||||
### Conhecendo o Formato
|
||||
|
||||
Os comandos ```bitcoin-cli``` estão todos vinculados aos comandos RPC no ```bitcoind```. Isso torna a transição do uso de ```bitcoin-cli``` para o uso do ```curl``` muito simples. Na verdade, se olharmos qualquer uma das páginas de ajuda do ```bitcoin-cli```, veremos que eles listam não apenas os comandos ```bitcoin-cli```, mas também os comandos ```curl``` paralelos. Por exemplo, aqui temos o resultado do comando ```bitcoin-cli help getmininginfo```:
|
||||
```
|
||||
$ bitcoin-cli help getmininginfo
|
||||
getmininginfo
|
||||
|
||||
Returns a json object containing mining-related information.
|
||||
Result:
|
||||
{ (json object)
|
||||
"blocks" : n, (numeric) The current block
|
||||
"currentblockweight" : n, (numeric, optional) The block weight of the last assembled block (only present if a block was ever assembled)
|
||||
"currentblocktx" : n, (numeric, optional) The number of block transactions of the last assembled block (only present if a block was ever assembled)
|
||||
"difficulty" : n, (numeric) The current difficulty
|
||||
"networkhashps" : n, (numeric) The network hashes per second
|
||||
"pooledtx" : n, (numeric) The size of the mempool
|
||||
"chain" : "str", (string) current network name (main, test, regtest)
|
||||
"warnings" : "str" (string) any network and blockchain warnings
|
||||
}
|
||||
|
||||
Examples:
|
||||
> bitcoin-cli getmininginfo
|
||||
> curl --user myusername --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getmininginfo", "params": []}' -H 'content-type: text/plain;' http://127.0.0.1:8332/
|
||||
```
|
||||
E ali está o comando ```curl```, no final da tela de ajuda! Este comando um tanto longo tem quatro partes principais: (1) uma lista do nome de usuário; (2) um sinalizador ```--data-binary```; (3) um objeto JSON que diz ao ```bitcoind``` o que fazer, incluindo um array JSON com os parâmetros e; (4) um cabeçalho HTTP que inclui a URL do ```bitcoind```.
|
||||
|
||||
Quando estamos trabalhando com o ```curl```, muitos desses argumentos do ```curl``` permanecerão os mesmos de um comando para outro, apenas as entradas ```method``` e ```params``` no array JSON normalmente mudam. No entanto, precisaremos saber como preencher o nome do usuário e endereço da URL para que funcione, antes de mais nada!
|
||||
|
||||
_Sempre que não tivermos certeza sobre como usar o curl no RPC, basta usarmos a ajuda do bitcoin-cli e continuar._
|
||||
|
||||
### Descobrindo o Nome de Usuário
|
||||
|
||||
Para falar com a porta do ```bitcoind```, precisamos de um nome de usuário e senha. Eles foram criados como parte da configuração inicial do Bitcoin e podem ser encontrados no arquivo `~/.bitcoin/bitcoin.conf`.
|
||||
|
||||
Por exemplo, aqui está nossa configuração atual:
|
||||
```
|
||||
$ cat ~/.bitcoin/bitcoin.conf
|
||||
server=1
|
||||
dbcache=1536
|
||||
par=1
|
||||
maxuploadtarget=137
|
||||
maxconnections=16
|
||||
rpcuser=StandUp
|
||||
rpcpassword=8eaf562eaf45c33c3328bc66008f2dd1
|
||||
rpcallowip=127.0.0.1
|
||||
debug=tor
|
||||
prune=550
|
||||
testnet=1
|
||||
mintxfee=0.001
|
||||
txconfirmtarget=1
|
||||
[test]
|
||||
rpcbind=127.0.0.1
|
||||
rpcport=18332
|
||||
[main]
|
||||
rpcbind=127.0.0.1
|
||||
rpcport=8332
|
||||
[regtest]
|
||||
rpcbind=127.0.0.1
|
||||
rpcport=18443
|
||||
```
|
||||
Nosso nome de usuário é ```StandUp``` e nossa senha é ```8eaf562eaf45c33c3328bc66008f2dd1```.
|
||||
|
||||
> **ATENÇÃO:** Obviamente, não é muito seguro ter essas informações em um arquivo de texto simples. A partir do Bitcoin Core 0.12, podemos omitir o ```rpcpassword``` do arquivo ```bitcoin.conf``` e fazer com que o ```bitcoind``` gere um novo cookie sempre que iniciarmos o serviço. A desvantagem disso é que torna o uso de comandos RPC por outros aplicativos, como os detalhados neste capítulo, mais difícil. Então, vamos ficar com as informações simples do ```rpcuser``` e ```rpcpassword``` por enquanto, mas para softwares em produção, é importante considerarmos essa alteração para cookies.
|
||||
|
||||
A maneira segura de usar o RPC com ```bitcoind``` é a seguinte:
|
||||
```
|
||||
$ curl --user StandUp --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/
|
||||
Enter host password for user 'bitcoinrpc':
|
||||
```
|
||||
Conforme observado, nossa senha será solicitada.
|
||||
|
||||
> :link: **TESTNET vs MAINNET:** A Testnet usa uma URL com a porta 18332 e a mainnet usa uma URL com a porta 8332. Se tivermos alguma dúvida, basta olharmos nosso ```bitcoin.conf```. As configurações estão todas lá.
|
||||
|
||||
A maneira insegura e errada de fazer isso é a seguinte:
|
||||
```
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/
|
||||
```
|
||||
> **ATENÇÃO:** Digitar a senha na linha de comando pode colocá-la na tabela de processos e/ou salvá-la em um histórico qualquer. Isso é ainda menos recomendado do que colocá-la em um arquivo, exceto para testes utilizando a testnet. Se quisermos fazer em qualquer outro lugar, precisamos nos certificar de saber o que estamos fazendo!
|
||||
|
||||
### Conhecendo os Comandos e os Parâmetros
|
||||
|
||||
Com tudo isso em mãos, estamos prontos para enviar os comandos RPC padrão com o ```curl```, mas ainda precisamos saber como incorporar os dois elementos que tendem a mudar no comando ```curl```.
|
||||
|
||||
O primeiro é o ```method```, que é o método RPC que está sendo utilizado. Isso geralmente deve corresponder aos nomes de comando que alimentamos no ```bitcoin-cli``` por muito tempo.
|
||||
|
||||
O segundo é o ```params```, que é uma array JSON de parâmetros. Eles são iguais aos argumentos (ou argumentos nomeados) que estamos usando. Eles também são a parte mais confusa do ```curl```, em grande parte porque são um array estruturado ao invés de uma simples lista.
|
||||
|
||||
Esta é a aparência de alguns arrays de parâmetros:
|
||||
|
||||
* `[]` — Um array vazio;
|
||||
* `["000b4430a7a2ba60891b01b718747eaf9665cb93fbc0c619c99419b5b5cf3ad2"]` — Um array com dados;
|
||||
* `["'$signedhex'"]` — Um array com uma variável;
|
||||
* `[6, 9999999]` — Uma array com dois parâmetros;
|
||||
* `{}` - Um objeto vazio;
|
||||
* `[''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.298, "'$changeaddress'": 1.0}'']` — Um array com um array contendo um objeto e um objeto vazio.
|
||||
|
||||
## Obtendo Informação
|
||||
|
||||
Agora podemos enviar nosso primeiro comando ```curl``` acessando o RPC ```getmininginfo```:
|
||||
```
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/
|
||||
{"result":{"blocks":1772428,"difficulty":10178811.40698772,"networkhashps":91963587385939.06,"pooledtx":61,"chain":"test","warnings":"Warning: unknown new rules activated (versionbit 28)"},"error":null,"id":"curltest"}```
|
||||
Note that we provided the method, `getmininginfo`, and the parameter, `[]`, but that everything else was the standard `curl` command line.
|
||||
```
|
||||
> **ATENÇÃO:** Se obtivermos como resultado o seguinte erro: "Failed to connect to 127.0.0.1 port 8332: Connection refused", precisamos nos certificar de que uma linha como ```rpcallowip = 127.0.0.1``` esteja configurada no ```~/.bitcoin/bitcoin.conf```. Se ainda não funcionar, precisaremos permitir o acesso à porta 18332 (ou 8332) do nosso host local. Nossa configuração padrão do [Capítulo 2: Configurando um Bitcoin-Core VPS](02_0_Setting_Up_a_Bitcoin-Core_VPS.md) deve fazer tudo isso.
|
||||
|
||||
O resultado é outro array JSON, que infelizmente é ruim de ler se estivermos usando o ```curl``` manualmente. Felizmente, podemos limpá-lo simplesmente usando o ```jq```:
|
||||
```
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
|
||||
% Total % Received % Xferd Average Speed Time Time Time Current
|
||||
Dload Upload Total Spent Left Speed
|
||||
100 295 100 218 100 77 72666 25666 --:--:-- --:--:-- --:--:-- 98333
|
||||
{
|
||||
"result": {
|
||||
"blocks": 1772429,
|
||||
"difficulty": 10178811.40698772,
|
||||
"networkhashps": 90580030969896.44,
|
||||
"pooledtx": 4,
|
||||
"chain": "test",
|
||||
"warnings": "Warning: unknown new rules activated (versionbit 28)"
|
||||
},
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
```
|
||||
Você verá um pouco de relatório de conectividade à medida que os dados são baixados, então, quando os dados chegarem ao ```jq```, tudo será corretamente identado. Estaremos omitindo as informações do download nos próximos exemplos.
|
||||
|
||||
## Manipulando Nossa Carteira
|
||||
|
||||
Embora já estejamos acessando o ```bitcoind``` diretamente, ainda teremos acesso à funcionalidade de carteira, porque ela está amplamente armazenada no próprio ```bitcoind```.
|
||||
|
||||
### Pesquisando Endereços
|
||||
|
||||
Usando o RPC ```getaddressesbylabel``` para listar todos os nossos endereços atuais:
|
||||
```
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getaddressesbylabel", "params": [""] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
|
||||
{
|
||||
"result": {
|
||||
"mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"mwJL7cRiW2bUnY81r1thSu3D4jtMmwyU6d": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"tb1q5gnwrh7ss5mmqt0qfan85jdagmumnatcscwpk6": {
|
||||
"purpose": "receive"
|
||||
},
|
||||
"tb1qmtucvjtga68kgrvkl7q05x4t9lylxhku7kqdpr": {
|
||||
"purpose": "receive"
|
||||
}
|
||||
},
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
```
|
||||
Este é o nosso primeiro exemplo de um parâmetro real, ```" "```. Este é o parâmetro ```label``` obrigatório para o ```getaddressesbylabel```, mas todos os nossos endereços estão sob o rótulo padrão, então nada de especial foi necessário neste momento.
|
||||
|
||||
O resultado é uma lista de todos os endereços que foram usados na nossa carteira. Alguns dos quais presumivelmente possuem saldo.
|
||||
|
||||
### Pesquisando Saldos
|
||||
|
||||
Use o RPC ```listunspent``` para listar os saldos que temos disponíveis:
|
||||
```
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
|
||||
{
|
||||
"result": [
|
||||
{
|
||||
"txid": "e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d",
|
||||
"vout": 1,
|
||||
"address": "mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h",
|
||||
"scriptPubKey": "76a91432db726320e4ad170c9c1ee83cd4d8a243c3435988ac",
|
||||
"amount": 0.0009,
|
||||
"confirmations": 4,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/1'/2']02881697d252d8bf181d08c58de1f02aec088cd2d468fc5fd888c6e39909f7fabf)#p6k7dptk",
|
||||
"safe": true
|
||||
},
|
||||
{
|
||||
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c",
|
||||
"vout": 0,
|
||||
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
|
||||
"label": "",
|
||||
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac",
|
||||
"amount": 0.00022,
|
||||
"confirmations": 19,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y",
|
||||
"safe": true
|
||||
}
|
||||
],
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
```
|
||||
Esta é quase a mesma saída que recebemos quando digitamos ```bitcoin-cli listunspent```, mostrando como as duas interfaces estão intimamente ligadas. Se nenhuma limpeza ou ajuda extra for necessária, então o ```bitcoin-cli``` apenas produzirá o RPC. Simples assim!
|
||||
|
||||
### Criando um Endereço
|
||||
|
||||
Depois de saber onde os saldos estão, a próxima etapa na elaboração de uma transação é obter um endereço de troco. Agora provavelmente já pegamos o jeito e sabemos que para os comandos RPC simples, tudo que precisamos fazer é ajustar o ```method``` no comando ```curl```:
|
||||
```
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": ["legacy"] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
|
||||
{
|
||||
"result": "mrSqN37TPs89GcidSZTvXmMzjxoJZ6RKoz",
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
|
||||
```
|
||||
Neste ponto, podemos até mesmo voltar à nossa prática padrão de salvar os resultados em variáveis com a ajuda adicional do `jq`:
|
||||
```
|
||||
$ changeaddress=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": ["legacy"] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result')
|
||||
$ echo $changeaddress
|
||||
mqdfnjgWr2r3sCCeuTDfe8fJ1CnycF2e6R
|
||||
```
|
||||
Não precisamos nos preocupar com as informações do download. Ele irá para o ```STDERR``` e será exibido em nossa tela, enquanto os resultados irão para o ```STDOUT``` e serão salvos em nossa variável.
|
||||
|
||||
## Criando uma Transação
|
||||
|
||||
Agora estamos prontos para criar uma transação com o ```curl```.
|
||||
|
||||
### Preparando as Variáveis
|
||||
|
||||
Assim como no ```bitcoin-cli```, para criar uma transação usando o Curl com o RPC, devemos primeiro salvar nossas variáveis. A única mudança aqui é que o ```curl``` cria um objeto JSON que inclui um valor-chave ```result```, então sempre precisaremos usar o pipe (```|```) através da tag ```.result``` antes de fazer outra coisa qualquer.
|
||||
|
||||
Este exemplo configura nossas variáveis para usar o BTC de 1.2985 em fundos listados na primeira transação não-gasta acima:
|
||||
```
|
||||
$ utxo_txid=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result | .[0] | .txid')
|
||||
$ utxo_vout=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result | .[0] | .vout')
|
||||
$ recipient=mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf
|
||||
$ changeaddress=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": ["legacy"] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result')
|
||||
|
||||
$ echo $utxo_txid
|
||||
e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d
|
||||
$ echo $utxo_vout
|
||||
1
|
||||
$ echo $recipient
|
||||
mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf
|
||||
$ echo $changeaddress
|
||||
n2jf3MzeFpFGa7wq8rXKVnVuv5FoNSJZ1N
|
||||
```
|
||||
|
||||
### Criando a Transação
|
||||
|
||||
A transação criada com o ```curl``` é muito semelhante à transação criada com o ```bitcoin-cli```, mas com algumas diferenças sutis:
|
||||
```
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.0003, "'$changeaddress'": 0.0005}'']}' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
|
||||
{
|
||||
"result": "02000000010d6acd0356db222ca3a7ee7fa1e3044316223ceec1f64b58aeb2e0de921007e70100000000ffffffff0230750000000000001976a914ac19d3fd17710e6b9a331022fe92c693fdf6659588ac50c30000000000001976a9147021efec134057043386decfaa6a6aa4ee5f19eb88ac00000000",
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
```
|
||||
O coração da transação é, obviamente, o array JSON ```params```, que estamos colocando em uso total pela primeira vez.
|
||||
|
||||
Podemos observar que todos os ```params``` estão alojados nos ```[]``` para marcar o array de parâmetros.
|
||||
|
||||
Nós também variamos as citações de como as coisas funcionavam no ```bitcoin-cli```, para iniciar e terminar cada array e objeto dentro do array ```params``` com ```''``` ao invés do tradicional ```'''```. Isso porque todo o conjunto de argumentos JSON já tem um ```'``` em torno dele. Como de costume, basta dar uma olhada na bizarra citação do shell e se acostumar com isso.
|
||||
|
||||
No entanto, há uma última coisa a ser observada neste exemplo, e pode ser _enlouquecedor_ se não tivermos percebido. Quando executamos um comando ```createrawtransaction``` com ```bitcoin-cli```, o array JSON de entradas e o objeto JSON de saídas eram parâmetros distintos, portanto, foram separados por um espaço. Agora, porque eles são parte do array JSON ```params```, eles são separados por uma vírgula (```,```). Se não tivéssemos percebido isso obteríamos um ```parse error``` sem muitas informações.
|
||||
|
||||
> **ATENÇÃO:** Todo mundo já teve problemas para depurar o ```curl```, não é mesmo? Para resolver isso basta adicionar o argumento ```--trace-ascii/tmp/foo```. Informações completas sobre o que está sendo enviado ao servidor serão salvas em ```/tmp/foo``` (ou qualquer nome de arquivo que quisermos informar).
|
||||
|
||||
Depois de verificarmos se as coisas estão funcionando, provavelmente desejaremos salvar o código hexadecimal em uma variável:
|
||||
```
|
||||
$ hexcode=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.0003, "'$changeaddress'": 0.0005}'']}' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result')
|
||||
```
|
||||
|
||||
### Assinando e Enviando
|
||||
|
||||
Assinar e enviar a nossa transação usando ```curl``` é bem simples, basta usar os seguintes comandos do RPC ```signrawtransactionwithwallet``` e ```sendrawtransaction```:
|
||||
|
||||
```
|
||||
$ signedhex=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "signrawtransactionwithwallet", "params": ["'$hexcode'"] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result | .hex')
|
||||
|
||||
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "sendrawtransaction", "params": ["'$signedhex'"] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
|
||||
{
|
||||
"result": "eb84c5008038d760805d4d9644ace67849542864220cb2685a1ea2c64176b82d",
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
```
|
||||
## Resumo: Acessando o Bitcoind com Curl
|
||||
|
||||
Terminando esta seção, podemos sentir que acessar o ```bitcoind``` através de ```curl``` é muito parecido com acessá-lo através de ```bitcoin-cli```, porém, é mais complicado. E estamos certos. O ```bitcoin-cli``` tem funcionalidade RPC bem completa, então qualquer coisa que fizermos através do ```curl``` provavelmente poderemos fazer através do ```bitcoin-cli```. E é por isso que vamos continuar nos concentrando no ```bitcoin-cli``` após esta digressão.
|
||||
|
||||
Mas ainda há razões para usar ```curl``` ao invés do ```bitcoin-cli```:
|
||||
|
||||
_Qual é o poder do curl?_ Obviamente, o ```curl``` elimina um nível intermediário. Ao invés de trabalhar com o ```bitcoin-cli```, que envia comandos RPC para o ```bitcoind```, estamos enviando esses comandos RPC diretamente para ele. Isso permite uma programação mais robusta, porque não precisamos nos preocupar com as coisas inesperadas que o ```bitcoin-cli``` pode fazer ou como isso pode mudar com o tempo. No entanto, também estamos dando os primeiros passos para usar uma linguagem de programação mais abrangente do que as opções pobres oferecidas por um script de shell. Como veremos nos últimos capítulos deste livro, podemos realmente ver que as bibliotecas curl são outras funções que acessam os comandos RPC em uma variedade de linguagens de programação: mas isso ainda está muito longe.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Aprenda mais uma maneira de enviar transações no Bitcoin com [§4.5 Enviando Moedas com Transações Brutas Automatizadas](04_5_Sending_Coins_with_Automated_Raw_Transactions.md).
|
171
pt/04_5_Sending_Coins_with_Automated_Raw_Transactions.md
Normal file
171
pt/04_5_Sending_Coins_with_Automated_Raw_Transactions.md
Normal file
@ -0,0 +1,171 @@
|
||||
# 4.5: Enviando Moedas com Transações Brutas Automatizadas
|
||||
|
||||
Este capítulo apresenta três maneiras de enviar fundos por meio da interface cli do Bitcoin. A seção [§4.1](04_1_Sending_Coins_The_Easy_Way.md) descreveu como fazer isso com um comando simples e a seção [§4.4](04_4_Sending_Coins_with_a_Raw_Transaction.md) detalhou como usar uma transação bruta mais perigosa. Esta seção fica no meio termo de ambas, mostrando como tornar as transações brutas mais simples e seguras.
|
||||
|
||||
## Deixando o Bitcoin Fazer os Cálculos Para Nós
|
||||
|
||||
A metodologia para transações brutas automatizadas é simples: criamos uma transação bruta, mas usamos o comando ```fundrawtransaction``` para pedir ao bitcoind para executar os cálculos para nós.
|
||||
|
||||
Para usar este comando, precisaremos garantir que nosso arquivo ```~/.bitcoin/bitcoin.conf``` contenha as variáveis racionais para calcular as taxas de transação. Podemos consultar a seção [§4.1: Enviando Moedas da Maneira Fácil](04_1_Sending_Coins_The_Easy_Way.md) para obter mais informações sobre isso.
|
||||
|
||||
Vamos usar números conservadores, por isso sugerimos adicionar o seguinte ao `bitcoin.conf`:
|
||||
```
|
||||
mintxfee=0.0001
|
||||
txconfirmtarget=6
|
||||
```
|
||||
Para manter o tutorial em movimento (e para movimentarmos nosso dinheiro rapidamente), sugerimos o seguinte:
|
||||
```
|
||||
mintxfee=0.001
|
||||
txconfirmtarget=1
|
||||
```
|
||||
|
||||
## Criando uma Transação Bruta
|
||||
|
||||
Para usar o ```fundrawtransaction``` primeiro precisamos criar uma transação bruta básica que liste _nenhuma_ entrada e _nenhuma_ mudança de endereço. Apenas listaremos o nosso destinatário e quanto desejamos enviar, neste caso ```$recipient``` e ```0,0002``` BTC.
|
||||
```
|
||||
$ recipient=n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi
|
||||
$ unfinishedtx=$(bitcoin-cli -named createrawtransaction inputs='''[]''' outputs='''{ "'$recipient'": 0.0002 }''')
|
||||
```
|
||||
|
||||
## Financiando Nossa Transação Bruta
|
||||
|
||||
Dizemos ao ```bitcoin-cli``` para financiar essa transação básica:
|
||||
```
|
||||
$ bitcoin-cli -named fundrawtransaction hexstring=$unfinishedtx
|
||||
{
|
||||
"hex": "02000000012db87641c6a21e5a68b20c226428544978e6ac44964d5d8060d7388000c584eb0100000000feffffff02204e0000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac781e0000000000001600140cc9cdcf45d4ea17f5227a7ead52367aad10a88400000000",
|
||||
"fee": 0.00022200,
|
||||
"changepos": 1
|
||||
}
|
||||
```
|
||||
Isso fornece muitas informações úteis, mas uma vez que tenhamos certeza de como funciona, vamos querer usar o JQ para salvar nosso hex em uma variável, como de costume:
|
||||
```
|
||||
$ rawtxhex3=$(bitcoin-cli -named fundrawtransaction hexstring=$unfinishedtx | jq -r '.hex')
|
||||
```
|
||||
## Verificando Nossa Transação Financiada
|
||||
|
||||
Parece mágica, então nas primeiras vezes que usarmos o ```fundrawtransaction```, provavelmente vamos querer verificá-la.
|
||||
|
||||
Vamos executar o comando ```decoderawtransaction``` para mostrar que a transação bruta agora está disposta corretamente, usando um ou mais dos nossos UTXOs e enviando fundos excedentes de volta para um endereço de troco:
|
||||
```
|
||||
$ bitcoin-cli -named decoderawtransaction hexstring=$rawtxhex3
|
||||
{
|
||||
"txid": "b3b4c2057dbfbef6690e975ede92fde805ddea13c730f58401939a52c9ac1b99",
|
||||
"hash": "b3b4c2057dbfbef6690e975ede92fde805ddea13c730f58401939a52c9ac1b99",
|
||||
"version": 2,
|
||||
"size": 116,
|
||||
"vsize": 116,
|
||||
"weight": 464,
|
||||
"locktime": 0,
|
||||
"vin": [
|
||||
{
|
||||
"txid": "eb84c5008038d760805d4d9644ace67849542864220cb2685a1ea2c64176b82d",
|
||||
"vout": 1,
|
||||
"scriptSig": {
|
||||
"asm": "",
|
||||
"hex": ""
|
||||
},
|
||||
"sequence": 4294967294
|
||||
}
|
||||
],
|
||||
"vout": [
|
||||
{
|
||||
"value": 0.00020000,
|
||||
"n": 0,
|
||||
"scriptPubKey": {
|
||||
"asm": "OP_DUP OP_HASH160 e7c1345fc8f87c68170b3aa798a956c2fe6a9eff OP_EQUALVERIFY OP_CHECKSIG",
|
||||
"hex": "76a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac",
|
||||
"reqSigs": 1,
|
||||
"type": "pubkeyhash",
|
||||
"addresses": [
|
||||
"n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"value": 0.00007800,
|
||||
"n": 1,
|
||||
"scriptPubKey": {
|
||||
"asm": "0 a782f4c6e1e75a5b24f3d675d6f11b5ebf3b2142",
|
||||
"hex": "0014a782f4c6e1e75a5b24f3d675d6f11b5ebf3b2142",
|
||||
"reqSigs": 1,
|
||||
"type": "witness_v0_keyhash",
|
||||
"addresses": [
|
||||
"tb1q57p0f3hpuad9kf8n6e6adugmt6lnkg2zzr592r"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
Uma coisa de interesse aqui é o endereço de troco, que é o segundo ```vout```. Observe que é um endereço ```tb1```, o que significa que é do tipo Bech32. Quando demos ao Bitcoin Core a capacidade total de gerenciar as alterações, ele o fez usando o tipo de endereço padrão, Bech32, e funcionou bem. É por isso que nossa mudança para endereços SegWit na seção [§4.6](04_6_Creating_a_Segwit_Transaction.md) realmente não é um grande negócio, mas existem algumas dicas para uso mais amplo, sobre as quais falaremos lá.
|
||||
|
||||
Embora tenhamos visto a taxa na saída de ```fundrawtransaction```, ela não pode ser visível aqui. No entanto, podemos verificar isso com o script JQ ```txfee-calc.sh``` criado na seção [Prefácio: Usando JQ](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/04_2__Interlude_Using_JQ.md):
|
||||
```
|
||||
$ ~/txfee-calc.sh $rawtxhex3
|
||||
.000222
|
||||
```
|
||||
Finalmente, podemos usar o ```getaddressinfo``` para ver se o endereço de troco gerado realmente nos pertence:
|
||||
```
|
||||
$ bitcoin-cli -named getaddressinfo address=tb1q57p0f3hpuad9kf8n6e6adugmt6lnkg2zzr592r
|
||||
{
|
||||
"address": "tb1q57p0f3hpuad9kf8n6e6adugmt6lnkg2zzr592r",
|
||||
"scriptPubKey": "0014a782f4c6e1e75a5b24f3d675d6f11b5ebf3b2142",
|
||||
"ismine": true,
|
||||
"solvable": true,
|
||||
"desc": "wpkh([d6043800/0'/1'/10']038a2702938e548eaec28feb92c7e4722042cfd1ea16bec9fc274640dc5be05ec5)#zpv26nar",
|
||||
"iswatchonly": false,
|
||||
"isscript": false,
|
||||
"iswitness": true,
|
||||
"witness_version": 0,
|
||||
"witness_program": "a782f4c6e1e75a5b24f3d675d6f11b5ebf3b2142",
|
||||
"pubkey": "038a2702938e548eaec28feb92c7e4722042cfd1ea16bec9fc274640dc5be05ec5",
|
||||
"ischange": true,
|
||||
"timestamp": 1592335137,
|
||||
"hdkeypath": "m/0'/1'/10'",
|
||||
"hdseedid": "fdea8e2630f00d29a9d6ff2af7bf5b358d061078",
|
||||
"hdmasterfingerprint": "d6043800",
|
||||
"labels": [
|
||||
]
|
||||
}
|
||||
```
|
||||
Observe o conteúdo do `ismine`.
|
||||
|
||||
## Enviando a Transação Financiada
|
||||
|
||||
Neste ponto, podemos assinar e enviar a transação normalmente.
|
||||
```
|
||||
$ signedtx3=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex3 | jq -r '.hex')
|
||||
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx3
|
||||
8b9dd66c999966462a3d88d6ac9405d09e2aa409c0aa830bdd08dbcbd34a36fa
|
||||
```
|
||||
Em alguns minutos, teremos o nosso troco de volta:
|
||||
```
|
||||
$ bitcoin-cli listunspent
|
||||
[
|
||||
{
|
||||
"txid": "8b9dd66c999966462a3d88d6ac9405d09e2aa409c0aa830bdd08dbcbd34a36fa",
|
||||
"vout": 1,
|
||||
"address": "tb1q57p0f3hpuad9kf8n6e6adugmt6lnkg2zzr592r",
|
||||
"scriptPubKey": "0014a782f4c6e1e75a5b24f3d675d6f11b5ebf3b2142",
|
||||
"amount": 0.00007800,
|
||||
"confirmations": 1,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "wpkh([d6043800/0'/1'/10']038a2702938e548eaec28feb92c7e4722042cfd1ea16bec9fc274640dc5be05ec5)#zpv26nar",
|
||||
"safe": true
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Resumo: Enviando Moedas com Transações Brutas Automatizadas
|
||||
|
||||
Se formos enviar fundos usando transações brutas, então o ```fundrawtransaction``` oferece uma boa alternativa onde taxas, entradas e saídas são calculadas para nós, para que não percamos acidentalmente muito dinheiro.
|
||||
|
||||
> :fire: ***Qual é o poder de enviar moedas com transações brutas automatizadas?***
|
||||
> _As vantagens._ Proporciona um bom meio termo. Se estamos enviando fundos manualmente e o ```sendtoaddress``` não oferece controle suficiente por qualquer motivo, podemos obter algumas das vantagens das transações brutas sem os perigos dela. Essa metodologia deve ser usada sempre que possível se estivermos enviando transações brutas manualmente.
|
||||
> _As desvantagens._ É uma mistura. Embora existam algumas opções adicionais no ```fundrawtransaction``` que não foram mencionadas aqui, nosso controle ainda é limitado. Provavelmente, nunca desejaríamos usar esse método se formos escrever um programa cujo objetivo é saber exatamente o que está acontecendo.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Vamos concluir o capítulo "Enviando Transações no Bitcoin" com a seção [§4.6: Criando uma Transação SegWit](04_6_Creating_a_Segwit_Transaction.md).
|
288
pt/04_6_Creating_a_Segwit_Transaction.md
Normal file
288
pt/04_6_Creating_a_Segwit_Transaction.md
Normal file
@ -0,0 +1,288 @@
|
||||
# 4.6: Criando uma Transação SegWit
|
||||
|
||||
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um esboço que ainda pode estar aguardando revisão. Portanto, leitor, tenha cuidado.
|
||||
|
||||
Era uma vez, nos céus do Bitcoin, uma guerra entre os tamanhos de blocos. As taxas disparavam e os usuários estavam preocupados se o Bitcoin podia realmente escalar. Os desenvolvedores do Bitcoin Core relutaram em simplesmente aumentar o tamanho do bloco, mas chegaram a um acordo: fizeram o SegWit, que significa Segregated Witness. Segregated Witness é uma maneira elegante de dizer "Assinatura Separada". Ele cria novos tipos de transações que removem assinaturas no final da transação. Ao combinar isso com o aumento dos tamanhos de bloco que são visíveis apenas para nodes atualizados, o SegWit resolveu os problemas de dimensionamento do Bitcoin na época e também resolveu um bug de maleabilidade desagradável, tornando o dimensionamento ainda melhor para protocolos de segunda camada, como a Lightning Network.
|
||||
|
||||
A sacada? O SegWit usa endereços diferentes, alguns dos quais são compatíveis com nodes mais antigos, ao passo que outros não.
|
||||
|
||||
> :warning: **AVISO DE VERSÃO:** O SegWit foi introduzido no BitCoin 0.16.0, que foi descrito na época como tendo "suporte total". Dito isso, havia algumas falhas na integração com o ```bitcoin-cli``` na época, que impediam a assinatura de funcionar corretamente em novos endereços P2SH-SegWit. O endereço Bech32, não compatível com versões anteriores, também foi introduzido no Bitcoin 0.16.0 e se tornou o tipo de endereço padrão no Bitcoin 0.19.0. Toda essa funcionalidade deve estar totalmente funcional em relação às funções ```bitcoin-cli``` (e, portanto, devem funcionar completamente neste tutorial).
|
||||
|
||||
> O problema está em interagir com o mundo. Todos devem ser capazes de enviar para um endereço P2SH-SegWit porque foi construído propositadamente para suportar compatibilidade com as versões anteriores, envolvendo a funcionalidade SegWit em um Script Bitcoin. O mesmo não é verdade para endereços Bech32: Se alguém nos disser que não pode enviar para o nosso endereço Bech32 precisaremos gerar um endereço ```legacy``` ou P2SH-SegWit para fazer a transação. (Muitos sites, principalmente as corretoras, também não podem gerar ou receber em endereços SegWit, particularmente endereços Bech32, mas isso é um problema totalmente diferente e não afeta o uso delas).
|
||||
|
||||
## Compreendendo uma Transação SegWit
|
||||
|
||||
Em transações clássicas, as informações de assinatura (witness) eram armazenadas no meio da transação, enquanto nas transações SegWit, elas ficam na parte inferior. Isso anda de mãos dadas com os aumentos de tamanho do bloco que foram introduzidos na atualização do SegWit. O tamanho do bloco foi aumentado de 1 mega para um valor variável com base em quantas transações SegWit estão em um bloco, começando em 1 mega (sem transações SegWit) e podendo chegar a 4 megas (caso todas as transações sejam SegWit). Este tamanho variável foi criado para acomodar os nodes clássicos, de forma que tudo permaneça compatível com as versões anteriores. Se um node clássico vê uma transação SegWit, ele joga fora as informações da witness (resultando em um bloco de tamanho menor, abaixo do antigo limite de 1 mega), enquanto se um novo node vê uma transação SegWit, ele mantém as informações da witness (resultando em um maior tamanho de bloco, até o novo limite de 4 megas).
|
||||
|
||||
Portanto, acabamos de responder o quê são e como funcionam as transações SegWit. Não que precisemos saber disso para usá-las. A maioria das transações na rede Bitcoin são SegWit. Elas são aquilo que iremos utilizar nativamente para as transações e recebimentos de bitcoins. A este ponto, os detalhes não são mais relevantes do que os detalhes de como grande parte do Bitcoin funciona.
|
||||
|
||||
## Criando um Endereço SegWit
|
||||
|
||||
Criamos um endereço SegWit da mesma maneira que qualquer outro endereço, com os comandos ```getnewaddress``` e ```getrawchangeaddress```.
|
||||
|
||||
Se precisarmos criar um endereço para alguém que não pode enviar para os endereços Bech32 mais recentes, podemos usar um endereço ```p2sh-segwit```:
|
||||
```
|
||||
$ bitcoin-cli -named getnewaddress address_type=p2sh-segwit
|
||||
2N5h2r4karVqN7uFtpcn8xnA3t5cbpszgyN
|
||||
```
|
||||
Se conseguirmos ver um endereço com o prefixo "2" significa que fizemos tudo certo.
|
||||
|
||||
> :link: **TESTNET vs MAINNET:** "3" para a Mainnet.
|
||||
|
||||
No entanto, se a pessoa com quem estamos interagindo tem um node com uma versão mais nova, ela poderá enviar para um endereço Bech32, que criamos usando os comandos da maneira padrão:
|
||||
```
|
||||
$ bitcoin-cli getnewaddress
|
||||
tb1q5gnwrh7ss5mmqt0qfan85jdagmumnatcscwpk6
|
||||
```
|
||||
Como já vimos, os endereços de troco gerados a partir do ```bitcoin-cli``` interagem bem com os endereços Bech32, então não há motivo nenhum para usar o sinalizador ```legacy``` lá também:
|
||||
```
|
||||
$ bitcoin-cli getrawchangeaddress
|
||||
tb1q05wx5tyadm8qe83exdqdyqvqqzjt3m38vfu8ff
|
||||
```
|
||||
|
||||
Aqui, podemos observar que o prefixo "tb1" exclusivo denota que o endereço é um Bech32.
|
||||
|
||||
> :link: **TESTNET vs MAINNET:** "bc1" para a mainnet.
|
||||
|
||||
O bitcoin-cli não se importa com o tipo de endereço que estamos utilizando. Podemos executar um comando como ```listaddressgroupings``` que ele irá misturar os endereços livremente, não importando os tipos:
|
||||
```
|
||||
$ bitcoin-cli listaddressgroupings
|
||||
[
|
||||
[
|
||||
[
|
||||
"mfsiRhxbQxcD7HLS4PiAim99oeGyb9QY7m",
|
||||
0.01000000,
|
||||
""
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE",
|
||||
0.00000000,
|
||||
""
|
||||
],
|
||||
[
|
||||
"tb1q6dak4e9fz77vsulk89t5z92l2e0zm37yvre4gt",
|
||||
0.00000000
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff",
|
||||
0.00022000,
|
||||
""
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h",
|
||||
0.00000000
|
||||
],
|
||||
[
|
||||
"mqjrdY5raxKzXQf5t2VvVvzhvFAgersu9B",
|
||||
0.00000000
|
||||
],
|
||||
[
|
||||
"mwJL7cRiW2bUnY81r1thSu3D4jtMmwyU6d",
|
||||
0.00000000,
|
||||
""
|
||||
],
|
||||
[
|
||||
"tb1q57p0f3hpuad9kf8n6e6adugmt6lnkg2zzr592r",
|
||||
0.00007800
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"mpVLL7iqPr4d7BJkEG54mcdm7WmrAhaW6q",
|
||||
0.01000000,
|
||||
""
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"tb1q5gnwrh7ss5mmqt0qfan85jdagmumnatcscwpk6",
|
||||
0.01000000,
|
||||
""
|
||||
]
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
## Enviando uma Transação SegWit da Maneira Fácil
|
||||
|
||||
Então, como enviamos uma transação Segwit? Exatamente como qualquer outra transação. Não importa se o UTXO é SegWit, o endereço é SegWit ou alguma combinação dos dois. Podemos ter a certeza que o ```bitcoin-cli``` irá fazer a coisa certa. Embora possamos perceber algumas diferenças nos endereços, eles não importam para interagir com as coisas no nível do ```bitcoin-cli``` ou do RPC. (E esta é uma das vantagens de usar a linha de comando e a interface do RPC, conforme sugerido neste tutorial: os especialistas já fizeram o trabalho duro para nós, incluindo coisas como enviar para endereços legacy e Bech32. Acabamos usando essa funcionalidade para nosso próprio benefício).
|
||||
|
||||
Aqui está um exemplo de um envio para um endereço SegWit, da maneira fácil:
|
||||
```
|
||||
$ bitcoin-cli sendtoaddress tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx 0.005
|
||||
854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42
|
||||
```
|
||||
Se olhar para a nossa transação, podemos ver o uso do endereço Bech32:
|
||||
```
|
||||
$ bitcoin-cli gettransaction txid="854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42" verbose=true
|
||||
{
|
||||
"amount": -0.00500000,
|
||||
"fee": -0.00036600,
|
||||
"confirmations": 0,
|
||||
"trusted": true,
|
||||
"txid": "854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42",
|
||||
"walletconflicts": [
|
||||
],
|
||||
"time": 1592948795,
|
||||
"timereceived": 1592948795,
|
||||
"bip125-replaceable": "no",
|
||||
"details": [
|
||||
{
|
||||
"address": "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx",
|
||||
"category": "send",
|
||||
"amount": -0.00500000,
|
||||
"vout": 1,
|
||||
"fee": -0.00036600,
|
||||
"abandoned": false
|
||||
}
|
||||
],
|
||||
"hex": "0200000002114d5a4c3b847bc796b2dc166ca7120607b874aa6904d4a43dd5f9e0ea79d4ba010000006a47304402200a3cc08b9778e7b616340d4cf7841180321d2fa019e43f25e7f710d9a628b55c02200541fc200a07f2eb073ad8554357777d5f1364c5a96afe5e77c6185d66a40fa7012103ee18c598bafc5fbea72d345329803a40ebfcf34014d0e96aac4f504d54e7042dfeffffffa71321e81ef039af490251379143f7247ad91613c26c8f3e3404184218361733000000006a47304402200dd80206b57beb5fa38a3c3578f4b0e40d56d4079116fd2a6fe28e5b8ece72310220298a8c3a1193ea805b27608ff67a2d8b01e347e33a4222edfba499bb1b64a31601210339c001b00dd607eeafd4c117cfcf86be8efbb0ca0a33700cffc0ae0c6ee69d7efeffffff026854160000000000160014d591091b8074a2375ed9985a9c4b18efecfd416520a1070000000000160014751e76e8199196d454941c45d1b3a323f1433bd6c60e1b00",
|
||||
"decoded": {
|
||||
"txid": "854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42",
|
||||
"hash": "854a833b667049ac811b4cf1cad40fa7f8dce8b0f4c1018a58b84559b6e05f42",
|
||||
"version": 2,
|
||||
"size": 366,
|
||||
"vsize": 366,
|
||||
"weight": 1464,
|
||||
"locktime": 1773254,
|
||||
"vin": [
|
||||
{
|
||||
"txid": "bad479eae0f9d53da4d40469aa74b8070612a76c16dcb296c77b843b4c5a4d11",
|
||||
"vout": 1,
|
||||
"scriptSig": {
|
||||
"asm": "304402200a3cc08b9778e7b616340d4cf7841180321d2fa019e43f25e7f710d9a628b55c02200541fc200a07f2eb073ad8554357777d5f1364c5a96afe5e77c6185d66a40fa7[ALL] 03ee18c598bafc5fbea72d345329803a40ebfcf34014d0e96aac4f504d54e7042d",
|
||||
"hex": "47304402200a3cc08b9778e7b616340d4cf7841180321d2fa019e43f25e7f710d9a628b55c02200541fc200a07f2eb073ad8554357777d5f1364c5a96afe5e77c6185d66a40fa7012103ee18c598bafc5fbea72d345329803a40ebfcf34014d0e96aac4f504d54e7042d"
|
||||
},
|
||||
"sequence": 4294967294
|
||||
},
|
||||
{
|
||||
"txid": "33173618421804343e8f6cc21316d97a24f7439137510249af39f01ee82113a7",
|
||||
"vout": 0,
|
||||
"scriptSig": {
|
||||
"asm": "304402200dd80206b57beb5fa38a3c3578f4b0e40d56d4079116fd2a6fe28e5b8ece72310220298a8c3a1193ea805b27608ff67a2d8b01e347e33a4222edfba499bb1b64a316[ALL] 0339c001b00dd607eeafd4c117cfcf86be8efbb0ca0a33700cffc0ae0c6ee69d7e",
|
||||
"hex": "47304402200dd80206b57beb5fa38a3c3578f4b0e40d56d4079116fd2a6fe28e5b8ece72310220298a8c3a1193ea805b27608ff67a2d8b01e347e33a4222edfba499bb1b64a31601210339c001b00dd607eeafd4c117cfcf86be8efbb0ca0a33700cffc0ae0c6ee69d7e"
|
||||
},
|
||||
"sequence": 4294967294
|
||||
}
|
||||
],
|
||||
"vout": [
|
||||
{
|
||||
"value": 0.01463400,
|
||||
"n": 0,
|
||||
"scriptPubKey": {
|
||||
"asm": "0 d591091b8074a2375ed9985a9c4b18efecfd4165",
|
||||
"hex": "0014d591091b8074a2375ed9985a9c4b18efecfd4165",
|
||||
"reqSigs": 1,
|
||||
"type": "witness_v0_keyhash",
|
||||
"addresses": [
|
||||
"tb1q6kgsjxuqwj3rwhkenpdfcjccalk06st9z0k0kh"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"value": 0.00500000,
|
||||
"n": 1,
|
||||
"scriptPubKey": {
|
||||
"asm": "0 751e76e8199196d454941c45d1b3a323f1433bd6",
|
||||
"hex": "0014751e76e8199196d454941c45d1b3a323f1433bd6",
|
||||
"reqSigs": 1,
|
||||
"type": "witness_v0_keyhash",
|
||||
"addresses": [
|
||||
"tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
Na verdade, ambos ```vouts``` usam endereços Bech32: o nosso destinatário e o endereço de troco gerado automaticamente.
|
||||
|
||||
Mas quando retrocedemos nosso ```vin```, descobrimos que veio de um endereço legacy. Porque isso não importa:
|
||||
```
|
||||
$ bitcoin-cli -named gettransaction txid="33173618421804343e8f6cc21316d97a24f7439137510249af39f01ee82113a7"
|
||||
{
|
||||
"amount": 0.01000000,
|
||||
"confirmations": 43,
|
||||
"blockhash": "00000000000000e2365d2f814d1774b063d9a04356f482010cdfdd537b1a24bb",
|
||||
"blockheight": 1773212,
|
||||
"blockindex": 103,
|
||||
"blocktime": 1592937103,
|
||||
"txid": "33173618421804343e8f6cc21316d97a24f7439137510249af39f01ee82113a7",
|
||||
"walletconflicts": [
|
||||
],
|
||||
"time": 1592936845,
|
||||
"timereceived": 1592936845,
|
||||
"bip125-replaceable": "no",
|
||||
"details": [
|
||||
{
|
||||
"address": "mpVLL7iqPr4d7BJkEG54mcdm7WmrAhaW6q",
|
||||
"category": "receive",
|
||||
"amount": 0.01000000,
|
||||
"label": "",
|
||||
"vout": 0
|
||||
}
|
||||
],
|
||||
"hex": "020000000001016a66efa334f06e2c54963e48d049a35d7a1bda44633b7464621cae302f35174a0100000017160014f17b16c6404e85165af6f123173e0705ba31ec25feffffff0240420f00000000001976a914626ab1ca41d98f597d18d1ff8151e31a40d4967288acd2125d000000000017a914d5e76abfe5362704ff6bbb000db9cdfa43cd2881870247304402203b3ba83f51c1895b5f639e9bfc40124715e2495ef2c79d4e49c0f8f70fbf2feb02203d50710abe3cf37df4d2a73680dadf3cecbe4f2b5d0b276dbe7711d0c2fa971a012102e64f83ee1c6548bcf44cb965ffdb803f30224459bd2e57a5df97cb41ba476b119b0e1b00"
|
||||
}
|
||||
```
|
||||
|
||||
## Enviando uma Transação SegWit da Maneira Difícil
|
||||
|
||||
Da mesma forma, podemos financiar uma transação com um endereço Bech32, sem nenhuma diferença em relação às técnicas que aprendemos até agora. Aqui está uma maneira exata de fazer isso com uma transação bruta completa:
|
||||
```
|
||||
$ changeaddress=$(bitcoin-cli getrawchangeaddress)
|
||||
$ echo $changeaddress
|
||||
tb1q4xje3mx9xn7f8khv7p69ekfn0q72kfs8x3ay4j
|
||||
$ bitcoin-cli listunspent
|
||||
[
|
||||
...
|
||||
{
|
||||
"txid": "003bfdca5578c0045a76768281f05d5e6f57774be399a76f387e2a0e99e4e452",
|
||||
"vout": 0,
|
||||
"address": "tb1q5gnwrh7ss5mmqt0qfan85jdagmumnatcscwpk6",
|
||||
"label": "",
|
||||
"scriptPubKey": "0014a226e1dfd08537b02de04f667a49bd46f9b9f578",
|
||||
"amount": 0.01000000,
|
||||
"confirmations": 5,
|
||||
"spendable": true,
|
||||
"solvable": true,
|
||||
"desc": "wpkh([d6043800/0'/0'/5']0327dbe2d58d9ed2dbeca28cd26e18f48aa94c127fa6fb4b60e4188f6360317640)#hd66hknp",
|
||||
"safe": true
|
||||
}
|
||||
]
|
||||
$ recipient=tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx
|
||||
$ utxo_txid=$(bitcoin-cli listunspent | jq -r '.[2] | .txid')
|
||||
$ utxo_vout=$(bitcoin-cli listunspent | jq -r '.[2] | .vout')
|
||||
$ echo $utxo_txid $utxo_vout
|
||||
003bfdca5578c0045a76768281f05d5e6f57774be399a76f387e2a0e99e4e452 0
|
||||
$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.002, "'$changeaddress'": 0.007 }''')
|
||||
$ signedtx=$(bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex | jq -r '.hex')
|
||||
$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
|
||||
e02568b706b21bcb56fcf9c4bb7ba63fdbdec1cf2866168c4f50bc0ad693f26c
|
||||
```
|
||||
Tudo funciona exatamente da mesma forma que outros tipos de transações!
|
||||
|
||||
### Reconhecendo o Novo Descritor
|
||||
|
||||
Se olharmos o campo ```desc```, notaremos que o endereço SegWit tem um descritor de estilo diferente daqueles encontrados na seção [§3.5: Compreendendo o Descritor](03_5_Understanding_the_Descriptor.md). Um descritor legacy descrito nessa seção se parecia com algo assim: `pkh ([d6043800 / 0 '/ 0' / 18 '] 03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388) # 4ahsl9pk`. Nosso novo descritor SegWit se parece mais com isso: `wpkh ([d6043800 / 0 '/ 0' / 5 '] 0327dbe2d58d9ed2dbeca28cd26e18f48aa94c127fa6fb4b60e4188f6360317640) # hd66hknp" `.
|
||||
|
||||
A grande diferença que precisamos notar é que a função mudou. Anteriormente, era ```pkh```, que é um endereço padrão de chave pública com hash P2PKH. Ao invés disso, o endereço SegWit é ```wpkh```, o que significa que é um endereço SegWit P2WPKH nativo. Isto destaca o :fire: ***poder dos descritores***. Eles descrevem como criar um endereço a partir de uma chave ou outra informação, com as funções definindo de forma inequívoca como fazer o endereço com base em seu tipo.
|
||||
|
||||
## Resumo: Criando uma Transação SegWit
|
||||
|
||||
Realmente não há complexidade para criar transações SegWit. Internamente, elas são estruturadas de forma diferente das transações legacy, mas na linha de comando não existe diferença: apenas usamos um endereço com um prefixo diferente. A única coisa a ser observada é que algumas pessoas podem não conseguir enviar para um endereço Bech32 se estiverem usando um software obsoleto.
|
||||
|
||||
> :fire: ***Qual é o poder de enviar transações com SegWit?***
|
||||
> _As vantagens._ As transações SegWit são menores e, portanto, serão mais baratas de serem enviadas do que as transações legacy devido às taxas mais baixas. O Bech32 diminui essa vantagem e também cria endereços que são mais difíceis de errar durante a transcrição, e isso é muito importante, visto que o erro do usuário é uma das maneiras mais prováveis de perderem seus bitcoins.
|
||||
> _As desvantagens._ Os endereços SegWit não tem suporte em nodes Bitcoin obsoletos. Em particular, as pessoas podem não conseguir enviar para o nosso endereço Bech32.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Vamos avançar mais um pouco no "bitcoin-cli" com o [Capítulo 5: Controlando Transações no Bitcoin](05_0_Controlling_Bitcoin_Transactions.md).
|
@ -1,19 +1,19 @@
|
||||
# Capítulo 6: Expandindo as transações de Bitcoin com multisigs
|
||||
# Capítulo 6: Expandindo Transações no Bitcoin com Multisigs
|
||||
|
||||
Transações básicas de Bitcoin: (1) Enviar fundos; (2) Para um único destinatário P2PKH ou SegWit; (3) A partir de uma única máquina; (4) Imediatamente. No entanto, todas essas quatro partes desta definição podem ser expandidas usando transações Bitcoin mais complexas. Este primeiro capítulo sobre "Expansão" mostra como variar os pontos (2) e (3), enviando saldos para um endereço que representa vários destinatários (ou, pelo menos, vários assinantes).
|
||||
Transações básicas no Bitcoin: (1) enviam fundos; (2) para um único destinatário P2PKH ou SegWit; (3) de uma única máquina; (4) imediatamente. No entanto, todas as quatro partes desta definição podem ser expandidas usando transações mais complexas no Bitcoin. Este primeiro capítulo sobre "Expansão" mostra como variar os pontos (2) e (3) enviando saldos para um endereço que representa vários destinatários (ou, pelo menos, vários assinantes).
|
||||
|
||||
## Objetivos deste capítulo
|
||||
|
||||
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
|
||||
* Criar endereços de Bitcoin multi assinados (multisigs) usando os fundamentos do Bitcoin;
|
||||
* Crie endereços de Bitcoin com várias assinaturas (multisigs) usando mecanismos fáceis.
|
||||
|
||||
* Criar endereços de Bitcoin multi-assinatura (multisig) usando os fundamentos do Bitcoin;
|
||||
* Criar endereços de Bitcoin multi-assinatura (multisig) usando mecanismos mais fáceis.
|
||||
|
||||
Os objetivos secundários do capítulo incluem a capacidade de:
|
||||
* Entender como gastar fundos enviados em uma transação multisig;
|
||||
* Planejar para obter o máximo do poder das multisigs.
|
||||
* Entender como gastar fundos enviados para um multisig;
|
||||
* Planejar para obter o máximo do poder dos multisigs.
|
||||
|
||||
## Tabela de Conteúdo
|
||||
|
||||
## Tabela de conteúdo
|
||||
|
||||
* [Seção 1: Enviando uma Transação Multsig](06_1_Sending_a_Transaction_to_a_Multisig.md)
|
||||
* [Seção 2: Gastando uma Transação Multsig](06_2_Spending_a_Transaction_to_a_Multisig.md)
|
||||
* [Seção 3: Enviando e Gastando uma Transação Multisig de Maneira Automatizada](06_3_Sending_an_Automated_Multisig.md)
|
||||
* [Seção 1: Enviando uma Transação com Multsig](06_1_Sending_a_Transaction_to_a_Multisig.md)
|
||||
* [Seção 2: Gastando uma Transação com Multsig](06_2_Spending_a_Transaction_to_a_Multisig.md)
|
||||
* [Seção 3: Enviando e Gastando um Multisig de Maneira Automatizada](06_3_Sending_an_Automated_Multisig.md)
|
@ -1,28 +1,28 @@
|
||||
# 6.1: Enviando uma Transação Multsig
|
||||
# 6.1: Enviando uma Transação com Multisig
|
||||
|
||||
A primeira maneira de variar a forma como enviamos uma transação básica é usando uma multisig. Isso nos dá a capacidade de exigir que várias pessoas (ou, ao menos, várias chaves privadas) autorizem o uso dos fundos.
|
||||
A primeira maneira de variar a forma como enviamos uma transação básica é usando um multisig. Isso nos dá a capacidade de exigir que várias pessoas (ou, ao menos, várias chaves privadas) autorizem o uso dos fundos.
|
||||
|
||||
## Entendendo como funcionam as Multisigs
|
||||
## Entendendo como Funcionam os Multisigs
|
||||
|
||||
Em uma transação P2PKH ou SegWit padrão, os bitcoins são enviados para um endereço baseado na chave pública, o que significa que a chave privada relacionada é necessária para desbloquear a transação, resolvendo o quebra-cabeça criptográfico e permitindo que reutilizemos o saldo. Mas e se pudéssemos bloquear uma transação com _múltiplas_ chaves privadas? Isso efetivamente permitiria que os fundos fossem enviados a um grupo de pessoas, onde todas teriam que concordar em reutilizar o saldo.
|
||||
|
||||
> :book: ***O que é uma multisignature ou multisig?*** Uma _multisignature_ é uma metodologia que permite que mais de uma pessoa crie uma assinatura digital em conjunto. É uma técnica para o uso criptográfico de chaves que vai muito além do Bitcoin.
|
||||
> :book: ***O que é uma multi-assinatura?*** Uma multi-assinatura é uma metodologia que permite que mais de uma pessoa crie uma assinatura digital em conjunto. É uma técnica geral para o uso criptográfico de chaves que vai muito além do Bitcoin.
|
||||
|
||||
Tecnicamente, um quebra-cabeça criptográfico com várias assinaturas é criado pelo Bitcoin usando o comando OP_CHECKMULTISIG e, normalmente, é encapsulado em um endereço P2SH. A seção [§10.4: Fazendo um scripto multisig](10_4_Scripting_a_Multisig.md) irá detalhar como isso funciona com mais precisão. Por enquanto, tudo que precisamos saber é que podemos usar o comando ```bitcoin-cli``` para criar endereços multi assinados. Os fundos podem ser enviados para esses endereços como qualquer endereço P2PKH ou Segwit normal, mas várias chaves privadas serão necessárias para que o saldo seja retirado.
|
||||
Tecnicamente, um quebra-cabeça criptográfico com várias assinaturas é criado pelo Bitcoin usando o comando OP_CHECKMULTISIG e, normalmente, é encapsulado em um endereço P2SH. A seção [§10.4: Programando um Multisig](10_4_Scripting_a_Multisig.md) irá detalhar como isso funciona com mais precisão. Por enquanto, tudo que precisamos saber é que podemos usar o comando ```bitcoin-cli``` para criar endereços multi-assinatura. Os fundos podem ser enviados para esses endereços como qualquer endereço P2PKH ou Segwit normal, mas várias chaves privadas serão necessárias para que o saldo seja resgatado.
|
||||
|
||||
> :book: ***O que é uma transação multisig?*** Uma transação com várias assinaturas é uma transação Bitcoin enviada para um endereço com várias assinaturas, exigindo assim que as pessoas de um grupo com várias assinaturas precisem assinar a transação para poder ter acesso ao saldo.
|
||||
> :book: ***O que é uma transação multisig?*** Uma transação multisig é uma transação no Bitcoin enviada para um endereço com várias assinaturas, exigindo assim que certas pessoas do grupo multi-assinatura precisem assinar a transação para poder reutilizar o saldo.
|
||||
|
||||
As multisigs simples exigem que todos no grupo assinem o UTXO quando for usá-lo. No entanto, há mais complexidade possível. As assinaturas múltiplas são geralmente descritas como sendo "M de N". Isso significa que a transação está presa com um grupo de "N" chaves, mas apenas "M" delas são necessárias para desbloquear a transação.
|
||||
Multisigs simples exigem que todos no grupo assinem o UTXO quando for gasto. No entanto, há mais complexidade possível. Multisigs são geralmente descritos como sendo "m de n". Isso significa que a transação está trancada com um grupo de chaves "n", mas apenas "m" delas são necessárias para desbloquear a transação.
|
||||
|
||||
> :book: ***O que é uma multisg M-de-N? *** Em uma multisig, as assinaturas "M" de um grupo de "N" são necessárias para formar a assinatura, onde "M ≤ N".
|
||||
> :book: ***O que é um multisg m-de-n?*** Em um multisig, "m" assinaturas de um grupo de "n" são necessárias para formar a assinatura, onde "m ≤ n".
|
||||
|
||||
## Criando um Endereço Multisig
|
||||
|
||||
Para bloquear um UTXO com várias chaves privadas, devemos primeiro criar um endereço com várias assinaturas. Os exemplos usados aqui mostram a criação (e uso) de uma multisig 2 de 2 (normalmente é assim que falamos quando nos referimos a um endereço multisg, descrevemos a quantidade de chaves e a quantidade necessária para desbloquear o saldo).
|
||||
Para trancar um UTXO com várias chaves privadas, devemos primeiro criar um endereço multi-assinatura. Os exemplos usados aqui mostram a criação (e uso) de um multisig 2-de-2.
|
||||
|
||||
### Criando os Endereços
|
||||
|
||||
Para criar um endereço multisig, devemos primeiro preparar os endereços que o multisig irá combinar. A prática recomendada sugere que sempre criemos endereços novos. Isso significa que cada participante irá executar o comando ```getnewaddress``` em sua própria máquina:
|
||||
Para criar um endereço multisig, devemos primeiro preparar os endereços que o multisig irá combinar. A prática recomendada sugere que sempre criemos novos endereços. Isso significa que cada participante irá executar o comando ```getnewaddress``` em sua própria máquina:
|
||||
```
|
||||
machine1$ address1=$(bitcoin-cli getnewaddress)
|
||||
```
|
||||
@ -30,15 +30,16 @@ E:
|
||||
```
|
||||
machine2$ address2=$(bitcoin-cli getnewaddress)
|
||||
```
|
||||
Posteriormente, um dos destinatários (ou talvez algum terceiro) precisará combinar ambos os endereços.
|
||||
Posteriormente, um dos destinatários (ou talvez algum terceiro) precisará combinar ambos endereços.
|
||||
|
||||
#### Coletando as Chaves Públicas
|
||||
#### Coletando Chaves Públicas
|
||||
|
||||
No entanto, não podemos criar um multisig com os endereços, pois esses são os hashes das chaves públicas: Ao invés disso, precisamos das próprias chaves públicas.
|
||||
|
||||
Esta informação está disponível facilmente com o comando ```getaddressinfo```.
|
||||
|
||||
Na máquina remota, que assumimos aqui é ```machine2```, podemos obter as informações em uma lista.
|
||||
|
||||
Na máquina remota, que assumimos aqui que é ```machine2```, podemos obter as informações em uma lista.
|
||||
```
|
||||
machine2$ bitcoin-cli -named getaddressinfo address=$address2
|
||||
{
|
||||
@ -65,9 +66,9 @@ machine2$ bitcoin-cli -named getaddressinfo address=$address2
|
||||
```
|
||||
O endereço ```pubkey``` (` 02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3`) é o que precisamos. Vamos copiá-lo para nossa máquina local por qualquer meio que acharmos mais eficiente e _que seja menos sujeito a erros_.
|
||||
|
||||
Este processo precisa ser realizado para _cada_ endereço de uma máquina diferente daquela onde o multisig está sendo construída. Obviamente, se algum terceiro estiver criando o endereço, precisaremos fazer isso para cada endereço.
|
||||
Este processo precisa ser realizado para _cada_ endereço de uma máquina diferente daquela onde o multisig está sendo construído. Obviamente, se algum terceiro estiver criando o endereço, precisaremos fazer isso para cada endereço.
|
||||
|
||||
> :warning: **Atenção:** O uso de hashes de chave pública pelo Bitcoin como endereços, ao invés de chaves públicas, na verdade representa uma camada adicional de segurança. Porém, o envio de uma chave pública aumenta ligeiramente a vulnerabilidade do endereço associado, para alguma possibilidade no futuro distante de um comprometimento devido a curva elíptica. Não devemos nos preocupar em termos que enviar ocasionalmente uma chave pública para um uso como esse, mas devemos estar cientes de que os hashes de chave pública representam segurança e, portanto, as chaves públicas reais não devem ser enviadas de qualquer jeito para qualquer pessoa.
|
||||
> :warning: **ATENÇÃO:** O uso de hashes de chave pública pelo Bitcoin como endereços, ao invés de chaves públicas, na verdade representa uma camada adicional de segurança. Portanto, o envio de uma chave pública aumenta ligeiramente a vulnerabilidade do endereço associado, devido a alguma possibilidade do comprometimento da curva elíptica em um futuro distante. Não devemos nos preocupar em termos que enviar ocasionalmente uma chave pública para um uso como esse, mas devemos estar cientes de que os hashes de chave pública representam segurança e, portanto, as chaves públicas reais não devem ser enviadas de qualquer jeito para qualquer pessoa.
|
||||
|
||||
Se um dos endereços foi criado em nossa máquina local, que assumimos aqui que seja ```machine1```, podemos simplesmente colocar o endereço ```pubkey``` em uma nova variável.
|
||||
```
|
||||
@ -76,7 +77,7 @@ machine1$ pubkey1=$(bitcoin-cli -named getaddressinfo address=$address1 | jq -r
|
||||
|
||||
### Criando o Endereço
|
||||
|
||||
Uma multisig agora pode ser criada com o comando ```createmultisig```:
|
||||
Um multisig agora pode ser criado com o comando ```createmultisig```:
|
||||
```
|
||||
machine1$ bitcoin-cli -named createmultisig nrequired=2 keys='''["'$pubkey1'","02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3"]'''
|
||||
{
|
||||
@ -87,36 +88,36 @@ machine1$ bitcoin-cli -named createmultisig nrequired=2 keys='''["'$pubkey1'","0
|
||||
```
|
||||
> :warning: **AVISO DE VERSÃO:** Algumas versões do ```createmultisig``` permitem a entrada de chaves públicas ou endereços, algumas requerem apenas as chaves públicas. Atualmente, ambas parecem funcionar.
|
||||
|
||||
Ao criar o endereço multisig, listamos quantas assinaturas são necessárias com o argumento ```nrequired``` (que é o "M" quando falamos _uma multisig "M de N"_), então listamos o conjunto total de assinaturas possíveis com a argumento ```keys``` (que é o "N"). Observe que as entradas ```keys``` provavelmente vieram de lugares diferentes. Nesse caso, incluímos ```$pubkey1``` da máquina local e ```02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3``` de uma máquina remota.
|
||||
Ao criar o endereço multisig, listamos quantas assinaturas são necessárias com o argumento ```nrequired``` (que é o "m" em um multisig "m-de-n"), então listamos o conjunto total de assinaturas possíveis com a argumento ```keys``` (que é o "n"). Observe que as entradas ```keys``` provavelmente vieram de lugares diferentes. Nesse caso, incluímos ```$pubkey1``` da máquina local e ```02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3``` de uma máquina remota.
|
||||
|
||||
> :information_source: **NOTA - M de N vs N de N:** Este exemplo mostra a criação de um multisig simples 2 de 2. Se quisermos criar uma assinatura M de N onde "M<N", precisamos apenas ajustar o campo ```nrequired``` e/ou o número de assinaturas ```keys``` no objeto JSON. Para um multisig 1 de 2, seria definido como ```nrequired = 1``` e também listaria duas chaves, enquanto para um multisig 2 de 3, seria necessário um ```nrequired = 2```, mas adicionaria mais uma chave pública à lista de ```keys```.
|
||||
> :information_source: **NOTA –– M-DE-N VS N-DE-N:** Este exemplo mostra a criação de um multisig simples 2-de-2 . Se quisermos criar uma assinatura m-de-n onde "m < n", precisamos apenas ajustar o campo ```nrequired``` e/ou o número de assinaturas ```keys``` no objeto JSON. Para um multisig 1-de-2, seria definido como ```nrequired = 1``` e também listaria duas chaves, enquanto para um multisig 2-de-3, seria necessário um ```nrequired = 2```, mas adicionaria mais uma chave pública à lista de ```keys```.
|
||||
|
||||
Quando usado corretamente, o ```createmultisig``` retorna três resultados, todos criticamente importantes.
|
||||
|
||||
O _endereço_ é o que iremos distribuir para as pessoas que desejam enviar os fundos. Podemos notar que ele tem um novo prefixo ```2```, exatamente como os endereços P2SH-SegWit. Isso porque, como eles, o comando ```createmultisig``` está na verdade criando um tipo de endereço totalmente novo chamado endereço P2SH. Ele funciona exatamente como um endereço P2PKH padrão para envio de fundos, mas como este foi criado para exigir vários endereços, precisaremos trabalhar um pouco mais para utilizá-los.
|
||||
|
||||
> :link: **TESTNET vs MAINNET:** Na Testenet, o prefixo para endereços P2SH é ```2```, enquanto na Mainnet é ```3```.
|
||||
> :link: **TESTNET vs MAINNET:** Na testenet, o prefixo para endereços P2SH é ```2```, enquanto na Mainnet é ```3```.
|
||||
|
||||
O _redeemScript_ é o que precisaremos para resgatar os fundos (junto com as chaves privadas de "M" dos "N" endereços). Este script é outro recurso especial dos endereços P2SH e será explicado com mais detalhes na seção [§8.1: Construindo um Script Bitcoin com P2SH](08_1_Building_a_Bitcoin_Script_with_P2SH.md). Por enquanto, precisamos apenas saber que alguns dados são necessários para podemos gastar nosso dinheiro.
|
||||
O _redeemScript_ é o que precisaremos para resgatar os fundos (junto com as chaves privadas de "m" dos "n" endereços). Este script é outro recurso especial dos endereços P2SH e será explicado com mais detalhes na seção [§10.3: Rodando um Script no Bitcoin com P2SH](10_3_Running_a_Bitcoin_Script_with_P2SH.md). Por enquanto, precisamos apenas saber que alguns dados são necessários para podemos gastar nosso dinheiro.
|
||||
|
||||
O _descritor_ é a descrição padronizada para um endereço que encontramos na seção [§3.5: Compreendendo o descritor](03_5_Understanding_the_Descriptor.md). Ele fornece uma maneira de importar esse endereço de volta para a outra máquina, usando o RPC ```importmulti```.
|
||||
O _descritor_ é a descrição padronizada para um endereço que encontramos na seção [§3.5: Compreendendo o Descritor](03_5_Understanding_the_Descriptor.md). Ele fornece uma maneira de importar esse endereço de volta para a outra máquina, usando o RPC ```importmulti```.
|
||||
|
||||
> :book: ***O que é um endereço P2SH?*** O P2SH significa Pay-To-Script-Hash. É um tipo de destinatário diferente de um endereço P2PKH padrão ou mesmo de um Bech32, usado para fundos cujo resgate é baseado em scripts de Bitcoin mais complexos. O ```bitcoin-cli``` usa o encapsulamento P2SH para ajudar a padronizar e simplificar os multisigs como "multisigs P2SH ", assim como P2SH-SegWit estava usando o P2SH para padronizar os endereços SegWit e torná-los totalmente compatíveis com as versões legadas.
|
||||
> :book: ***O que é um endereço P2SH?*** O P2SH significa Pay-To-Script-Hash. É um tipo de destinatário diferente de um endereço P2PKH padrão ou mesmo de um Bech32, usado para fundos cujo resgate é baseado em scripts de Bitcoin mais complexos. O ```bitcoin-cli``` usa o encapsulamento P2SH para ajudar a padronizar e simplificar os multisigs como "multisigs P2SH", assim como P2SH-SegWit estava usando o P2SH para padronizar os endereços SegWit e torná-los totalmente compatíveis com as versões antigas.
|
||||
|
||||
> :warning: **Atenção:** endereços P2SH multisig, como os criados pelo ```bitcoin-cli```, têm um limite para "M" e "N" nos multisigs com base no tamanho máximo do script de resgate, que atualmente é de 520 bytes. Praticamente, não vamos chegar a isso, a menos que estejamos nos excedendo em algo.
|
||||
> :warning: **ATENÇÃO:** endereços P2SH multisig, como os criados pelo ```bitcoin-cli```, têm um limite para "m" e "n" nos multisigs com base no tamanho máximo do script de resgate, que atualmente é de 520 bytes. Praticamente, não vamos chegar a isso, a menos que estejamos nos excedendo em algo.
|
||||
|
||||
### Salvando Nosso Trabalho
|
||||
|
||||
Aqui está uma informação importante: Nada sobre nosso multisig é salvo em nossa carteira usando essas técnicas básicas. Para resgatar o saldo enviado para este endereço multisig no futuro, precisaremos reter duas informações cruciais:
|
||||
Aqui está uma informação importante: nada sobre nosso multisig é salvo em nossa carteira usando essas técnicas básicas. Para resgatar o saldo enviado para este endereço multisig no futuro, precisaremos reter duas informações cruciais:
|
||||
|
||||
* Uma lista dos endereços Bitcoin usados no multisig, e;
|
||||
* A saída ```redeemScript``` criada pelo comando ```createmultsig```.
|
||||
|
||||
Tecnicamente, o ```redeemScript``` pode ser recriado executando novamente o ```createmultisig``` com a lista completa de chaves públicas _na mesma ordem_ e com a contagem correta de M e de N. Mas, é melhor agarrar-se a ela e evitar qualquer tipo de estresse futuro.
|
||||
Tecnicamente, o ```redeemScript``` pode ser recriado executando novamente o ```createmultisig``` com a lista completa de chaves públicas _na mesma ordem_ e com a contagem m-de-n correta. Mas, é melhor agarrar-se a ela e evitar qualquer tipo de estresse futuro.
|
||||
|
||||
### Observando a Ordem
|
||||
### Observe a Ordem
|
||||
|
||||
Aqui está mais uma coisa que devemos tomar muito cuidado: A _ordem é muito importante_. A ordem das chaves usadas para criar um multisig cria um hash único, ou seja, se colocarmos as chaves em uma ordem diferente, elas irão produzir um endereço diferente, conforme mostrado abaixo:
|
||||
Aqui está mais uma coisa que devemos tomar muito cuidado: _a ordem importa_. A ordem das chaves usadas para criar um multisig cria um hash único, ou seja, se colocarmos as chaves em uma ordem diferente, elas irão produzir um endereço diferente, conforme mostrado abaixo:
|
||||
```
|
||||
$ bitcoin-cli -named createmultisig nrequired=2 keys='''["'$pubkey1'","'$pubkey2'"]'''
|
||||
{
|
||||
@ -131,11 +132,11 @@ standup@btctest20:~$ bitcoin-cli -named createmultisig nrequired=2 keys='''["'$p
|
||||
"descriptor": "sh(multi(2,039cd6842869c1bfec13cfdbb7d8285bc4c501d413e6633e3ff75d9f13424d99b3,0342b306e410283065ffed38c3139a9bb8805b9f9fa6c16386e7ea96b1ba54da03))#audl88kg"
|
||||
}
|
||||
```
|
||||
Mais notavelmente, cada ordem cria um _redeemScript_ diferente. Isso significa que se usamos essas técnicas básicas e não conseguimos salvar o redemScript conforme as instruções, teremos que percorrer um número cada vez maior de variações para encontrar aquela correta quando tentarmos gastar os fundos!
|
||||
Mais notavelmente, cada ordem cria um _redeemScript_ diferente. Isso significa que se usamos essas técnicas básicas e não salvarmos o redemScript conforme as instruções, teremos que percorrer um número cada vez maior de variações para encontrar a correta quando tentarmos gastar os fundos!
|
||||
|
||||
O [BIP67](https://github.com/bitcoin/bips/blob/master/bip-0067.mediawiki) sugere uma maneira de ordenar lexicograficamente as chaves, de modo que sempre gerem as mesmas multisigs. A ColdCard e a Electrum estão entre as carteiras que já possuem suporte a isso. Claro, isso pode causar problemas por si só se não soubermos se um endereço multisig foi criado com chaves classificadas ou não classificadas. Mais uma vez, os [descritores](03_5_Understanding_the_Descriptor.md) vem ao nosso resgate. Se uma multisig não for classificada, ele será construído com a função ```multi``` e se for classificada, será construída com a função ```sortedmulti```.
|
||||
O [BIP67](https://github.com/bitcoin/bips/blob/master/bip-0067.mediawiki) sugere uma maneira de ordenar lexicograficamente as chaves, de modo que sempre gerem as mesmas multisigs. A ColdCard e a Electrum estão entre as carteiras que já possuem suporte a isso. Claro, isso pode causar problemas por si só se não soubermos se um endereço multisig foi criado com chaves classificadas ou não classificadas. Mais uma vez, os [descritores](03_5_Understanding_the_Descriptor.md) vêm ao nosso resgate. Se um multisig não for classificado, ele será construído com a função ```multi```, e se for classificado, será construído com a função ```sortedmulti```.
|
||||
|
||||
Se olharmos o ```desc``` da multisig que criamos acima, veremos que o Bitcoin Core atualmente não classifica os multisigs:
|
||||
Se olharmos o ```desc``` do multisig que criamos acima, veremos que o Bitcoin Core atualmente não classifica os multisigs:
|
||||
```
|
||||
"descriptor": "sh(multi(2,02da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d191,02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3))#0pazcr4y"
|
||||
```
|
||||
@ -143,9 +144,9 @@ Porém, se ele importa um endereço do tipo ```sortedmulti```, ele fará o proce
|
||||
|
||||
> :warning: **AVISO DE VERSÃO:** O Bitcoin Core só entende a função do descritor ```sortedmulti``` após a versão 0.20.0. Podemos tentar acessar o descritor em uma versão anterior do Bitcoin Core e obteremos um erro como ```A function is needed within P2WSH```.
|
||||
|
||||
## Enviando Fundos para um Endereço Multisig
|
||||
## Enviando para um Endereço Multisig
|
||||
|
||||
Se tivermos uma multisig em um formato P2SH conveniente, como o gerado pelo ```bitcoin-cli```, podemos enviar como um endereço normal.
|
||||
Se tivermos um multisig em um formato P2SH conveniente, como o gerado pelo ```bitcoin-cli```, podemos enviar como um endereço normal.
|
||||
```
|
||||
$ utxo_txid=$(bitcoin-cli listunspent | jq -r '.[0] | .txid')
|
||||
$ utxo_vout=$(bitcoin-cli listunspent | jq -r '.[0] | .vout')
|
||||
@ -195,12 +196,12 @@ b164388854f9701051809eed166d9f6cedba92327e4296bf8a265a5da94f6521
|
||||
```
|
||||
Como podemos ver, não houve nada de incomum na criação da transação e ela parece normal, embora com um endereço com um prefixo diferente do normal (```2N8MytPW2ih27LctLjn6LfLFZZb1PFSsqBr```). Sem surpresa, como também não vimos diferença quando enviamos para endereços Bech32 pela primeira vez na seção [§4.6](04_6_Creating_a_Segwit_Transaction.md).
|
||||
|
||||
## Resumo: Enviando uma Transação Multsig
|
||||
## Resumo: Enviando uma Transação Multisig
|
||||
|
||||
Os endereços Multisig bloqueiam os fundos usando várias chaves privadas, possivelmente exigindo todas essas chaves privadas para resgate e, possivelmente, exigindo apenas algumas do conjunto. Eles são fáceis de serem criadas com o ```bitcoin-cli``` e são simples para serem enviadas. Essa facilidade se deve em grande parte ao uso invisível de endereços P2SH (Pay-To-Script-Hash), um tópico extenso que já falamos duas vezes, agora com endereços P2SH-SegWit e multisig, e um outro que receberá mais atenção no futuro.
|
||||
Os endereços multisig trancam os fundos usando várias chaves privadas, possivelmente exigindo todas essas chaves privadas para resgate e, possivelmente, exigindo apenas algumas do conjunto. Eles são fáceis de serem criados com o ```bitcoin-cli``` e são simples para serem enviados. Essa facilidade se deve em grande parte ao uso invisível de endereços P2SH (Pay-To-Script-Hash), um tópico extenso que já falamos duas vezes, com endereços P2SH-SegWit e agora com os multisigs, e um outro que receberá mais atenção no futuro.
|
||||
|
||||
> :fire: ***Qual é o poder das multisigs?*** As multisigs permitem a modelagem de uma variedade de arranjos financeiros, como corporações, parcerias, comitês e outros grupos. Uma multisig 1 de 2 pode ser a conta bancária conjunta de um casal, enquanto uma multisig 2 de 2 pode ser usado para grandes despesas por uma parceria de responsabilidade limitada. As multisigs também constituem uma das bases dos Smart Contracts. Por exemplo, um negócio imobiliário pode ser fechado com um multisig 2 de 3, onde as assinaturas são enviadas pelo comprador, pelo vendedor e por um agente de custódia. Depois que o agente de custódia concorda que todas as condições foram atendidas, ele libera os fundos para o vendedor, ou, alternativamente, o comprador e o vendedor podem liberar os fundos em conjunto.
|
||||
> :fire: ***Qual é o poder das multi-assinaturas?*** As multi-assinaturas permitem a modelagem de uma variedade de arranjos financeiros, como corporações, parcerias, comitês e outros grupos. Um multisig 1-de-2 pode ser a conta bancária conjunta de um casal, enquanto um multisig 2-de-2 pode ser usado para grandes despesas por uma parceria de responsabilidade limitada. Os multisigs também constituem uma das bases dos Smart Contracts. Por exemplo, um negócio imobiliário pode ser fechado com um multisig 2-de-3, onde as assinaturas são enviadas pelo comprador, pelo vendedor e por um agente de custódia. Depois que o agente de custódia concorda que todas as condições foram atendidas, ele libera os fundos para o vendedor, ou, alternativamente, o comprador e o vendedor podem liberar os fundos em conjunto.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Vamos continuar "Expandindo as transações de Bitcoin com multisigs" na seção [§6.2: Gastando uma transação Multsig](06_2_Spending_a_Transaction_to_a_Multisig.md).
|
||||
Vamos continuar "Expandindo Transações no Bitcoin com Multisigs" na seção [§6.2: Gastando uma Transação com Multisig](06_2_Spending_a_Transaction_to_a_Multisig.md).
|
@ -1,8 +1,8 @@
|
||||
# 6.2: Gastando uma Transação Multsig
|
||||
# 6.2: Gastando uma Transação com Multsig
|
||||
|
||||
A maneira clássica e complexa de gastar fundos enviados para um endereço com várias assinaturas usando o ```bitcoin-cli``` requer que suemos bastante a camisa.
|
||||
|
||||
## Encontrando os fundos
|
||||
## Encontrando os Fundos
|
||||
|
||||
Para começar, precisamos encontrar nossos fundos. Nosso computador não sabe procurá-los, porque não estão associados a nenhum endereço da nossa carteira. Podemos alertar o ```bitcoind``` para fazer isso usando o comando ```importaddress```:
|
||||
```
|
||||
@ -93,25 +93,25 @@ $ bitcoin-cli -named gettransaction txid=b164388854f9701051809eed166d9f6cedba923
|
||||
}
|
||||
```
|
||||
|
||||
## Configurando as nossas variáveis
|
||||
## Configurando as Nossas Variáveis
|
||||
|
||||
Quando estivermos prontos para gastar os fundos recebidos por um endereço multisig, precisaremos coletar _muitos_ dados: Muito mais do que precisamos quando fazemos uma transação usando um UTXO de um P2PKH normal ou SegWit. Isso ocorre em parte porque as informações sobre o endereço multisig não estão em nossa posse e em parte porque estamos gastando dinheiro que foi enviado para um endereço P2SH (Pay-To-Script-Hash) e isso é muito mais exigente.
|
||||
Quando estivermos prontos para gastar os fundos recebidos por um endereço multisig, precisaremos coletar _muitos_ dados: muito mais do que precisamos quando fazemos uma transação usando um UTXO de um P2PKH normal ou SegWit. Isso ocorre em parte porque as informações sobre o endereço multisig não estão em nossa posse e em parte porque estamos gastando dinheiro que foi enviado para um endereço P2SH (Pay-To-Script-Hash) e isso é muito mais exigente.
|
||||
|
||||
No total, precisaremos coletar três coisas: Informações estendidas sobre o UTXO; O redemScript; e todas as chaves privadas envolvidas. Obviamente, também iremos precisar de um novo endereço de destinatário. As chaves privadas precisam aguardar a etapa de assinatura, mas tudo pode ser feito agora.
|
||||
No total, precisaremos coletar três coisas: informações estendidas sobre o UTXO; o redemScript e; todas as chaves privadas envolvidas. Obviamente, também iremos precisar de um novo endereço de destinatário. As chaves privadas precisam aguardar a etapa de assinatura, mas tudo pode ser feito agora.
|
||||
|
||||
### Acessando as informações do UTXO
|
||||
### Acessando as Informações do UTXO
|
||||
|
||||
Para começar, vamos pegar o ```txid``` e o ```vout``` para a transação que desejamos gastar, como de costume. Nesse caso, os dados foram recuperados das informações ```gettransaction``` acima:
|
||||
```
|
||||
$ utxo_txid=b164388854f9701051809eed166d9f6cedba92327e4296bf8a265a5da94f6521
|
||||
$ utxo_vout=0
|
||||
```
|
||||
No entanto, precisamos também acessar um terceiro bit de informação sobre o UTXO, nosso ```scriptPubKey```/```hex```, que é o script que travamos a transação. Novamente, podemos fazer isso observando os detalhes da transação:
|
||||
No entanto, precisamos também acessar um terceiro pedaço de informação sobre o UTXO, nosso ```scriptPubKey```/```hex```, que é o script que travou a transação. Novamente, podemos fazer isso observando os detalhes da transação:
|
||||
```
|
||||
$ utxo_spk=a914a5d106eb8ee51b23cf60d8bd98bc285695f233f387
|
||||
```
|
||||
|
||||
### Gravando o script de resgate
|
||||
### Gravando o Script de Resgate
|
||||
|
||||
Felizmente, salvamos nosso ```redeemScript```. Agora devemos registrá-lo em uma variável.
|
||||
|
||||
@ -119,13 +119,13 @@ O valor foi extraído da criação de endereço na seção anterior.
|
||||
```
|
||||
redeem_script="522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352ae"
|
||||
```
|
||||
### Decidindo o destinatário
|
||||
### Decidindo o Destinatário
|
||||
|
||||
Vamos apenas enviar o dinheiro de volta para nós mesmos. Isso é útil porque libera os fundos do multisig, convertendo-os em uma transação P2PKH normal que pode ser posteriormente confirmada por uma única chave privada:
|
||||
```
|
||||
$ recipient=$(bitcoin-cli getrawchangeaddress)
|
||||
```
|
||||
## Criando nossa transação
|
||||
## Criando Nossa Transação
|
||||
|
||||
Agora podemos criar nossa transação. Essa parte é parecida com as transações normais.
|
||||
```
|
||||
@ -134,22 +134,22 @@ $ echo $rawtxhex
|
||||
020000000121654fa95d5a268abf96427e3292baed6c9f6d16ed9e80511070f954883864b10000000000ffffffff0188130000000000001600142c48d3401f6abed74f52df3f795c644b4398844600000000
|
||||
```
|
||||
|
||||
## Assinando a nossa transação
|
||||
## Assinando Nossa Transação
|
||||
|
||||
Agora estamos prontos para assinar a transação. Este é um processo de várias etapas porque precisaremos fazer em várias máquinas, cada uma das quais contribuirá com suas próprias chaves privadas.
|
||||
|
||||
### Carregando a primeira chave privada
|
||||
### Carregando a Primeira Chave Privada
|
||||
|
||||
Como essa transação não está fazendo uso total da nossa carteira, precisaremos acessar diretamente as chaves privadas. Começando com a ```máquina1```, onde devemos recuperar qualquer uma das chaves privadas do usuário que estavam envolvidas no multisig:
|
||||
```
|
||||
machine1$ bitcoin-cli -named dumpprivkey address=$address1
|
||||
cNPhhGjatADfhLD5gLfrR2JZKDE99Mn26NCbERsvnr24B3PcSbtR
|
||||
```
|
||||
> :warning: **Atenção:** Acessar diretamente as chaves privadas do shell é um comportamento muito perigoso e deve ser feito com extremo cuidado se estivermos em um ambiente produtivo. No mínimo, é importante não salvar as informações em uma variável que possa ser acessada pela nossa máquina. Remover o histórico do shell é outro grande passo. No máximo, podemos evitar de fazer isso.
|
||||
> :warning: **ATENÇÃO:** Acessar diretamente as chaves privadas do shell é um comportamento muito perigoso e deve ser feito com extremo cuidado se estivermos usando dinheiro de verdade. No mínimo, é importante não salvar as informações em uma variável que possa ser acessada pela nossa máquina. Remover o histórico do shell é outro grande passo. No máximo, podemos evitar de fazer isso.
|
||||
|
||||
### Fazendo a nossa primeira assinatura
|
||||
### Fazendo Nossa Primeira Assinatura
|
||||
|
||||
Agora podemos fazer nossa primeira assinatura com o comando ```signrawtransactionwithkey```. É aqui que as coisas ficam diferentes das normais: Precisaremos treinar o comando sobre como assinar. Podemos fazer isso adicionando as seguintes informações novas:
|
||||
Agora podemos fazer nossa primeira assinatura com o comando ```signrawtransactionwithkey```. É aqui que as coisas ficam diferentes: precisaremos treinar o comando sobre como assinar. Podemos fazer isso adicionando as seguintes informações novas:
|
||||
|
||||
* Incluir um argumento ```prevtxs``` que tenha o ```txid```, o ```vout```, o ```scriptPubKey``` e o ```redeemScript``` que gravamos, cada um deles um par individual do valor-chave no objeto JSON.
|
||||
* Incluir um argumento ```privkeys``` que lista as chaves privadas que pegamos nesta máquina.
|
||||
@ -175,18 +175,18 @@ machine1$ bitcoin-cli -named signrawtransactionwithkey hexstring=$rawtxhex prevt
|
||||
```
|
||||
Isso produz erros assustadores e mostra um status de ```failing```. Tudo bem. Podemos ver que a assinatura foi parcialmente bem-sucedida porque o ```hex``` ficou mais longo. Embora a transação tenha sido parcialmente assinada, ela não foi concluída porque precisa de mais assinaturas.
|
||||
|
||||
### Repetindo para os outros assinantes
|
||||
### Repetindo para os Outros Assinantes
|
||||
|
||||
Agora podemos passar a transação adiante, para ser assinada novamente por nós, que temos a outra parte da multisig. Eles fazem isso executando o mesmo comando de assinatura que fizemos, porém: (1) com o ```hex``` maior que produzimos anteriormente (```bitcoin-cli -named signrawtransactionwithkey hexstring = $ rawtxhex prevtxs = '' '[{"txid": " '$ utxo_txid'", "vout": '$ utxo_vout', "scriptPubKey": " '$ utxo_spk'", "redeemScript": " '$ redeem_script'"}] '' 'privkeys =' [ "cMgb3KM8hPATCtgMKarKMiFesLft6eEw3DY6BB8d97fkeXeqQagw"] '| jq -r'. | .hex'```) e; (2) com nossa própria chave privada.
|
||||
Agora podemos passar a transação adiante, para ser assinada novamente por outros exigidos pelo multisig. Eles fazem isso executando o mesmo comando de assinatura que fizemos, porém: (1) com o ```hex``` maior que produzimos anteriormente (```bitcoin-cli -named signrawtransactionwithkey hexstring = $ rawtxhex prevtxs = '' '[{"txid": " '$ utxo_txid'", "vout": '$ utxo_vout', "scriptPubKey": " '$ utxo_spk'", "redeemScript": " '$ redeem_script'"}] '' 'privkeys =' [ "cMgb3KM8hPATCtgMKarKMiFesLft6eEw3DY6BB8d97fkeXeqQagw"] '| jq -r'. | .hex'```) e; (2) com sua própria chave privada.
|
||||
|
||||
> :information_source: **NOTA - M de N vs N de N:** Obviamente, se tivermos uma assinatura N de N (como a multisig 2 de 2 do exemplo), todas as partes precisarão assinar, mas se tivermos uma multisig M de N onde "M <N", a assinatura estará completa quando apenas alguns ("M") tiverem assinado.
|
||||
> :information_source: **NOTA - M-DE-N VS N-DE-N:** Obviamente, se tivermos uma assinatura N de N (como a multisig 2-de-2 do exemplo), todas as partes precisarão assinar, mas se tivermos uma multi-assinatura m-de-n onde "m < n", a assinatura estará completa quando apenas alguns ("m") tiverem assinado.
|
||||
|
||||
Para fazer isso, primeiro acessamos as chaves privadas:
|
||||
Para fazer isso, primeiro eles acessam suas chaves privadas:
|
||||
```
|
||||
machine2$ bitcoin-cli -named dumpprivkey address=$address2
|
||||
cVhqpKhx2jgfLUWmyR22JnichoctJCHPtPERm11a2yxnVFKWEKyz
|
||||
```
|
||||
Depois, assinamos o novo ```hex``` usando os mesmos valores ```prevtxs```:
|
||||
Depois, assinam o novo ```hex``` usando os mesmos valores ```prevtxs```:
|
||||
```
|
||||
machine1$ bitcoin-cli -named signrawtransactionwithkey hexstring=020000000121654fa95d5a268abf96427e3292baed6c9f6d16ed9e80511070f954883864b100000000920047304402201c97b48215f261055e41b765ab025e77a849b349698ed742b305f2c845c69b3f022013a5142ef61db1ff425fbdcdeb3ea370aaff5265eee0956cff9aa97ad9a357e3010047522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352aeffffffff0188130000000000001600142c48d3401f6abed74f52df3f795c644b4398844600000000 prevtxs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout', "scriptPubKey": "'$utxo_spk'", "redeemScript": "'$redeem_script'" } ]''' privkeys='["cVhqpKhx2jgfLUWmyR22JnichoctJCHPtPERm11a2yxnVFKWEKyz"]'
|
||||
{
|
||||
@ -194,11 +194,11 @@ machine1$ bitcoin-cli -named signrawtransactionwithkey hexstring=02000000012165
|
||||
"complete": true
|
||||
}
|
||||
```
|
||||
Por fim, podemos precisar enviar uma ```hexstring``` ainda mais longa que produzem para assinaturas adicionais.
|
||||
Por fim, podem precisar enviar uma ```hexstring``` ainda mais longa que eles tenham produzido para assinantes adicionais.
|
||||
|
||||
Mas, neste caso, podemos ver que a assinatura está `complete`!
|
||||
|
||||
## Enviando nossa transação
|
||||
## Enviando Nossa Transação
|
||||
|
||||
Quando terminarmos, devemos recorrer à metodologia ```JQ``` padrão para salvar nossa ```hexstring``` e, em seguida, enviá-la:
|
||||
```
|
||||
@ -207,9 +207,9 @@ $ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
|
||||
99d2b5717fed8875a1ed3b2827dd60ae3089f9caa7c7c23d47635f6f5b397c04
|
||||
```
|
||||
|
||||
## Compreendendo a importância desta metodologia de assinatura expandida
|
||||
## Compreendendo a Importância Desta Metodologia de Assinatura Expandida
|
||||
|
||||
Isso deu um belo trabalho e, como logo iremos aprender, existe uma tolice ao utilizar as chaves privadas, o redeem script e com a scriptpubkey pois eles não são realmente necessários para resgatar os endereços de multisg usando versões mais recentes do Bitcoin Core. Então qual era a questão?
|
||||
Isto deu um belo trabalho e, como logo iremos aprender, existe uma tolice ao utilizar as chaves privadas, o redeem script e com a scriptpubkey pois eles não são realmente necessários para resgatar os endereços de multisg usando versões mais recentes do Bitcoin Core. Então, qual foi o ponto?
|
||||
|
||||
Esta metodologia de resgate mostra uma maneira padrão de assinar e reutilizar transações P2SH. Em suma, para resgatar fundos P2SH, uma ```signrawtransactionwithkey``` precisa:
|
||||
|
||||
@ -220,10 +220,10 @@ Esta metodologia de resgate mostra uma maneira padrão de assinar e reutilizar t
|
||||
|
||||
Aqui, vimos essa metodologia usada para resgatar os fundos multisig. No futuro, também podemos usá-la para resgatar os fundos que foram trancados com outros scripts P2SH mais complexos, conforme explicado no Capítulo 9.
|
||||
|
||||
## Resumo: Gastando uma Transação Multsig
|
||||
## Resumo: Gastando uma Transação com Multisig
|
||||
|
||||
Acontece que gastar dinheiro enviado para um endereço multisig pode dar um pouco de trabalho. Mas, contanto que tenhamos os endereços originais e nosso redemScript, podemos fazer isso assinando uma transação bruta com cada endereço diferente e fornecendo mais algumas informações ao longo do caminho.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Vamos continuar "Expandindo as transações de Bitcoin com multisigs" na seção [§6.3: Enviando e Gastando uma Transação Multisig de Maneira Automatizada](06_3_Sending_an_Automated_Multisig.md).
|
||||
Vamos continuar "Expandindo Transações no Bitcoin com Multisigs" na seção [§6.3: Enviando & Gastando um Multisig Automatizado](06_3_Sending_an_Automated_Multisig.md).
|
@ -1,14 +1,14 @@
|
||||
# 6.3: Enviando e Gastando uma Transação Multisig de Maneira Automatizada
|
||||
# 6.3: Enviando & Gastando um Multisig Automatizado
|
||||
|
||||
A técnica padrão para criar endereços com várias assinaturas e gastar os fundos é complexa, mas é um exercício interessante para entender um pouco mais como funcionam e como podemos manipulá-los em um nível relativamente baixo. No entanto, o Bitcoin Core tornou os multisigs mais fáceis de serem manipulados nas novas versões.
|
||||
A técnica padrão para criar endereços multi-assinatura e gastar os fundos é complexa, mas é um exercício interessante para entender um pouco mais como funcionam e como podemos manipulá-los em um nível relativamente baixo. No entanto, o Bitcoin Core tornou os multisigs mais fáceis de serem manipulados nas novas versões.
|
||||
|
||||
> :warning: **AVISO DE VERSÃO:** O comando ```addmultisigaddress``` está disponível no Bitcoin Core v0.10 ou superior.
|
||||
|
||||
## Criando um endereço Multisig em nossa carteira
|
||||
## Criando um Endereço Multisig em Nossa Carteira
|
||||
|
||||
Para tornar os fundos enviados para endereços multisig mais fáceis de serem gastos, só precisamos fazer algumas pré-configurações usando o comando ```addmultisigaddress```. Não é o que gostaríamos de fazer se estivéssemos escrevendo programas de carteiras que utilizam multisig, mas se estivesse apenas tentando receber alguns fundos, isso poderia evitar alguns problemas.
|
||||
|
||||
### Coletando as chaves
|
||||
### Coletando as Chaves
|
||||
|
||||
Vamos começar criando os endereços P2PKH e recuperando as chaves públicas, como de costume, para cada usuário que fará parte do multisig:
|
||||
```
|
||||
@ -25,9 +25,9 @@ machine2$ bitcoin-cli -named getaddressinfo address=$address4 | jq -r '. | .pubk
|
||||
02a0d96e16458ff0c90db4826f86408f2cfa0e960514c0db547ff152d3e567738f
|
||||
```
|
||||
|
||||
### Criando o endereço Multisig em qualquer lugar
|
||||
### Criando o Endereço Multisig em Todos os Lugares
|
||||
|
||||
Em seguida, vamos criar o multisig em _cada máquina que contribuiu com as assinaturas_ usando um novo comando, ```addmultisigaddress```, ao invés de ```createmultisig```. Este novo comando guarda algumas das informações da nossa carteira, tornando muito mais fácil gastar o dinheiro no futuro.
|
||||
Em seguida, vamos criar o multisig em _cada máquina que contribuiu com assinaturas_ usando um novo comando, ```addmultisigaddress```, ao invés de ```createmultisig```. Este novo comando salva algumas das informações na nossa carteira, tornando muito mais fácil gastar o dinheiro no futuro.
|
||||
```
|
||||
machine1$ bitcoin-cli -named addmultisigaddress nrequired=2 keys='''["'$address3'","02a0d96e16458ff0c90db4826f86408f2cfa0e960514c0db547ff152d3e567738f"]'''
|
||||
{
|
||||
@ -43,9 +43,9 @@ machine2$ bitcoin-cli -named addmultisigaddress nrequired=2 keys='''["0297e681bf
|
||||
"descriptor": "wsh(multi(2,[ae42a66f]0297e681bff16cd4600138449e2527db4b2f83955c691a1b84254ecffddb9bfbfc,[fe6f2292/0'/0'/2']02a0d96e16458ff0c90db4826f86408f2cfa0e960514c0db547ff152d3e567738f))#cc96c5n6"
|
||||
}
|
||||
```
|
||||
Conforme observado na seção anterior, atualmente não importa se usamos endereços ou chaves públicas, então mostramos o outro mecanismo aqui, misturando os dois. Iremos obter o mesmo endereço multisig de qualquer maneira. No entanto, _devemos usar a mesma ordem sempre_. Portanto, é melhor que os membros do multisig verifiquem entre si a ordem dos dados para ter certeza de que todos obtiveram o mesmo resultado.
|
||||
Conforme observado na seção anterior, atualmente não importa se usamos endereços ou chaves públicas, então temos mostrado o outro mecanismo aqui, misturando os dois. Iremos obter o mesmo endereço multisig de qualquer maneira. No entanto, _devemos usar a mesma ordem sempre_. Portanto, é melhor que os membros do multisig verifiquem entre si a ordem dos dados para ter certeza de que todos obtiveram o mesmo resultado.
|
||||
|
||||
### Esperando para receber os fundos
|
||||
### Atente-se aos Fundos
|
||||
|
||||
Depois disso, os membros do multisig ainda precisarão executar o comando ```importaddress``` para observar os fundos recebidos no endereço multisig:
|
||||
```
|
||||
@ -54,9 +54,9 @@ machine1$ bitcoin-cli -named importaddress address=2Mzw7WBvh9RAQ4ssKqxyNyP7L9NAo
|
||||
machine2$ bitcoin-cli -named importaddress address=2Mzw7WBvh9RAQ4ssKqxyNyP7L9NAojLqSW8 rescan="false"
|
||||
```
|
||||
|
||||
## Gastando novamente com uma transação automatizada
|
||||
## Gastando Novamente com uma Transação Automatizada
|
||||
|
||||
Posteriormente, podemos receber os fundos no endereço com várias assinaturas sem nenhum problema. O uso do ```addmultisigaddress``` é simplesmente uma questão burocrática por parte dos destinatários: Um pouco de contabilidade para facilitar a vida deles quando desejarem gastar os saldos.
|
||||
Posteriormente, poderemos receber os fundos no endereço multisig normalmente. O uso do ```addmultisigaddress``` é simplesmente uma questão burocrática por parte dos destinatários: um pouco de contabilidade para facilitar a vida deles quando desejarem gastar os saldos.
|
||||
|
||||
Mas, isso torna a vida muito mais fácil. Como as informações foram salvas na carteira, os assinantes poderão gastar os fundos enviados para o endereço com várias assinaturas exatamente como qualquer outro endereço, ao invés de assinar sempre em várias máquinas diferentes.
|
||||
|
||||
@ -68,11 +68,11 @@ machine1$ utxo_txid=b9f3c4756ef8159d6a66414a4317f865882ee04beb57a0f8349dafcc98f5
|
||||
machine1$ utxo_vout=0
|
||||
machine1$ recipient=$(bitcoin-cli getrawchangeaddress)
|
||||
```
|
||||
Vamos criar uma transação bruta:
|
||||
Criamos uma transação bruta:
|
||||
```
|
||||
machine1$ rawtxhex=$(bitcoin-cli -named createrawtransaction inputs='''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]''' outputs='''{ "'$recipient'": 0.00005}''')
|
||||
```
|
||||
E depois, assiná-la:
|
||||
E depois, a assinamos:
|
||||
```
|
||||
machine1$ bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex
|
||||
{
|
||||
@ -96,9 +96,9 @@ machine1$ bitcoin-cli -named signrawtransactionwithwallet hexstring=$rawtxhex
|
||||
}
|
||||
|
||||
```
|
||||
Observe que não precisamos mais da ajuda extra do comando ```signrawtransactionwithkey```, porque todas essas informações já estão em nossa carteira. Mais importante, não tornamos nossas chaves privadas vulneráveis ao manipulá-las diretamente. Ao invés disso, o processo é _exatamente_ o mesmo que gastar um UTXO normal, exceto que a transação não foi totalmente assinada no final.
|
||||
Observe que não precisamos mais dar ajuda extra ao comando ```signrawtransactionwithkey```, porque todas as informações extras já estavam em nossa carteira. Mais importante, não tornamos nossas chaves privadas vulneráveis ao manipulá-las diretamente. Ao invés disso, o processo é _exatamente_ o mesmo que gastar um UTXO normal, exceto que a transação não foi totalmente assinada no final.
|
||||
|
||||
### Assinando em outras máquinas
|
||||
### Assinando em Outras Máquinas
|
||||
|
||||
A etapa final é exportar o ```hex``` parcialmente assinado para a outra máquina e assinar a transação novamente:
|
||||
```
|
||||
@ -111,10 +111,10 @@ machine2$ bitcoin-cli -named sendrawtransaction hexstring=$signedtx
|
||||
```
|
||||
Tal como acontece com o atalho discutido na seção [§4.5: Enviando Moedas com Transações Brutas Automatizadas](04_5_Sending_Coins_with_Automated_Raw_Transactions.md), o resultado é muito mais fácil, mas perdemos certo controle no processo.
|
||||
|
||||
## Resumo: Enviando e Gastando uma Transação Multisig de Maneira Automatizada
|
||||
## Resumo: Enviando & Gastando um Multisig Automatizado
|
||||
|
||||
Existe uma maneira mais fácil de gastar fundos enviados para os nossos endereços multisig que simplesmente requerem o uso do comando ```addmultisigaddress``` quando criamos nosso endereço. Ele não demonstra os meandros do gasto do P2SH e não nos dará um controle abrangente, mas se queremos apenas receber nossas moedas, este pode ser o melhor caminho.
|
||||
Existe uma maneira mais fácil de gastar fundos enviados para os nossos endereços multisig que simplesmente requerem o uso do comando ```addmultisigaddress``` quando criamos nosso endereço. Ele não demonstra as complexidades do gasto do P2SH e não nos dará um controle abrangente, mas se queremos apenas receber nossas moedas, este pode ser o melhor caminho.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Saiba mais sobre "Expandindo as transações de Bitcoin com multisigs" no [Capítulo 7: Expandindo as transações do Bitcoin com PSBTs](07_0_Expanding_Bitcoin_Transactions_PSBTs.md).
|
||||
Saiba mais sobre "Expandindo Transações no Bitcoin com Multisigs" no [Capítulo 7: Expandindo Transações no Bitcoin com PSBTs](07_0_Expanding_Bitcoin_Transactions_PSBTs.md).
|
27
pt/15_0_Talking_to_Bitcoind.md
Normal file
27
pt/15_0_Talking_to_Bitcoind.md
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
# Capítulo 15: Conversando com Bitcoind usando C
|
||||
|
||||
Enquanto trabalhamos com Bitcoin Scripts, atingimos os limites do que era possível com o `bitcoin-cli`: Atualmente, ele não pode ser usado para gerar transações contendo scripts incomuns. Os scripts shell também não são bons para algumas coisas, como criar programas de escuta que estão constantemente em polling. Felizmente, existem outras maneiras de acessar a rede Bitcoin: Através de APIs programáveis.
|
||||
|
||||
Esta seção se concentra em três diferentes bibliotecas que podem ser usadas como base de programação C sofisticada: Uma biblioteca RPC e uma biblioteca JSON que juntas permitem recriar muito do que fazemos nos scripts de shell, porém, usando C; enquanto uma biblioteca ZMQ nos conecta a notificações, algo que não conseguiríamos acessar até agora. (O próximo capítulo cobrirá uma biblioteca ainda mais sofisticada chamada Libwally, para finalizar esta introdução à programação do Bitcoin com C).
|
||||
|
||||
## Objetivos deste capítulo
|
||||
|
||||
Depois de trabalhar neste capítulo, um desenvolvedor será capaz de:
|
||||
|
||||
* Criar programas C que usam RPC para conversar com o Bitcoind;
|
||||
* Criar programas C que usam ZMQ para conversar com o Bitcoind.
|
||||
|
||||
Os objetivos secundários do capítulo incluem a capacidade de:
|
||||
|
||||
* Entender como usar uma biblioteca RPC;
|
||||
* Entender como usar uma biblioteca JSON;
|
||||
* Compreender as capacidades do ZMQ;
|
||||
* Entender como usar uma biblioteca ZMQ.
|
||||
|
||||
## Tabela de conteúdo
|
||||
|
||||
* [Seção 1: Acessando o Bitcoind usando C com Bibliotecas RPC](15_1_Accessing_Bitcoind_with_C.md)
|
||||
* [Seção 2: Programando o Bitcoind usando C com Bibliotecas RPC](15_2_Programming_Bitcoind_with_C.md)
|
||||
* [Seção 3: Recebendo notificações usando C com bibliotecas ZMQ](15_3_Receiving_Bitcoind_Notifications_with_C.md)
|
||||
|
294
pt/15_1_Accessing_Bitcoind_with_C.md
Normal file
294
pt/15_1_Accessing_Bitcoind_with_C.md
Normal file
@ -0,0 +1,294 @@
|
||||
|
||||
# 15.1: Acessando o Bitcoind usando C com bibliotecas RPC
|
||||
|
||||
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um esboço que ainda pode estar aguardando revisão. Portanto, leitor, tenha cuidado.
|
||||
|
||||
Você já viu uma maneira alternativa de acessar as portas RPC do Bitcoind: Usando o ``curl``, que cobrimos no [Capítulo 4 Prefácio](04_4__interlude_using_curl.md). Interagir com o ``Bitcoind`` através de uma biblioteca de RPC usando C não é diferente do que já vimos, só precisamos de boas bibliotecas para nos auxiliar. Esta seção introduz um pacote chamado ``libbitcoinrpc``, que permite acessar a porta JSON-RPC do ``bitcoind``. Ele usa uma biblioteca ``curl`` para acessar os dados e usa a biblioteca ``jansson`` para codificar e decodificar o JSON.
|
||||
|
||||
## Configurando o libbitcoinrpc
|
||||
|
||||
Para usar o ``libbitcoinrpc``, precisaremos instalar uma configuração básica C e os pacotes dependentes, que são ``libcurl``, ``libjansson``, e ``libuuid``. Depois faremos isso no seu servidor Standup Bitcoin (ou em qualquer outro servidor Ubuntu).
|
||||
|
||||
```
|
||||
$ sudo apt-get install make gcc libcurl4-openssl-dev libjansson-dev uuid-dev
|
||||
Suggested packages:
|
||||
libcurl4-doc libidn11-dev libkrb5-dev libldap2-dev librtmp-dev libssh2-1-dev
|
||||
The following NEW packages will be installed:
|
||||
libcurl4-openssl-dev libjansson-dev uuid-dev
|
||||
0 upgraded, 3 newly installed, 0 to remove and 4 not upgraded.
|
||||
Need to get 358 kB of archives.
|
||||
After this operation, 1.696 kB of additional disk space will be used.
|
||||
Do you want to continue? [Y/n] y
|
||||
```
|
||||
Agora, podemos baixar o [libbitcoinrpc no github](https://github.com/gitmarek/libbitcoinrpc/blob/master/readme.md). Vamos clonar ou pegar um arquivo zip, do jeito que preferir.
|
||||
|
||||
```
|
||||
$ sudo apt-get install git
|
||||
$ git clone https://github.com/gitmarek/libbitcoinrpc
|
||||
```
|
||||
|
||||
> :warning: **ATENÇÃO** Uma alteração no RPC "signrawtransaction" causou uma assinatura com ``libbitcoinrpc`` para o segfault no Bitcoin 0.17 ou superior. O [Pull Request foi submetido](https://github.com/gitmarek/libbitcoinrpc/pull/1/commits) para resolver o problema, mas se ainda não tiver sido feito o merge, podemos simplesmente fazer uma simples mudança no código-fonte para ``src/bitcoinrpc_method.c`` antes de compilarmos.
|
||||
|
||||
### Compilando o libbitcoinrpc.
|
||||
|
||||
Antes de compilarmos e instalarmos o pacote, provavelmente precisaremos ajustar nosso ``$PATH``, para que possamos acessar o ``/sbin/ldconfig``:
|
||||
```
|
||||
$ PATH="/sbin:$PATH"
|
||||
```
|
||||
|
||||
Para o Ubuntu, também precisaremos ajustar o ``install_libpath`` no ``makefile`` do ``libbitcoinrpc`` para instalar no ``/usr/lib`` ao invés do ``/usr/local/lib``:
|
||||
|
||||
```
|
||||
$ emacs ~/libbitcoinrpc/Makefile
|
||||
...
|
||||
INSTALL_LIBPATH := $(INSTALL_PREFIX)/usr/lib
|
||||
```
|
||||
|
||||
(Se preferir não usar o ``/usr/lib``, precisará alterar o ``etc/ld.so.conf`` ou os arquivos dependentes de maneira apropriada... Porém, para uma configuração de teste em uma máquina de teste, acredito que isso não seja um problema).
|
||||
|
||||
Da mesma forma, vamos precisar ajustar o ``install_headerpath`` no ``Makefile`` do ``libbitcoinrpc`` para instalar no caminho ``/usr/include`` ao invés do ``/usr/local/inclusve``:
|
||||
|
||||
```
|
||||
...
|
||||
INSTALL_HEADERPATH := $(INSTALL_PREFIX)/usr/include
|
||||
```
|
||||
|
||||
Agora, podemos compilar:
|
||||
```
|
||||
$ cd libbitcoinrpc
|
||||
~/libbitcoinrpc$ make
|
||||
|
||||
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc_err.o -c src/bitcoinrpc_err.c
|
||||
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc_global.o -c src/bitcoinrpc_global.c
|
||||
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc.o -c src/bitcoinrpc.c
|
||||
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc_resp.o -c src/bitcoinrpc_resp.c
|
||||
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc_cl.o -c src/bitcoinrpc_cl.c
|
||||
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -o src/bitcoinrpc_method.o -c src/bitcoinrpc_method.c
|
||||
gcc -fPIC -O3 -g -Wall -Werror -Wextra -std=c99 -D VERSION=\"0.2\" -shared -Wl,-soname,libbitcoinrpc.so.0 \
|
||||
src/bitcoinrpc_err.o src/bitcoinrpc_global.o src/bitcoinrpc.o src/bitcoinrpc_resp.o src/bitcoinrpc_cl.o src/bitcoinrpc_method.o \
|
||||
-o .lib/libbitcoinrpc.so.0.2 \
|
||||
-Wl,--copy-dt-needed-entries -luuid -ljansson -lcurl
|
||||
ldconfig -v -n .lib
|
||||
.lib:
|
||||
libbitcoinrpc.so.0 -> libbitcoinrpc.so.0.2 (changed)
|
||||
ln -fs libbitcoinrpc.so.0 .lib/libbitcoinrpc.so
|
||||
```
|
||||
Se tudo correr bem, podemos instalar o pacote:
|
||||
```
|
||||
$ sudo make install
|
||||
Installing to
|
||||
install .lib/libbitcoinrpc.so.0.2 /usr/local/lib
|
||||
ldconfig -n /usr/local/lib
|
||||
ln -fs libbitcoinrpc.so.0 /usr/local/lib/libbitcoinrpc.so
|
||||
install -m 644 src/bitcoinrpc.h /usr/local/include
|
||||
Installing docs to /usr/share/doc/bitcoinrpc
|
||||
mkdir -p /usr/share/doc/bitcoinrpc
|
||||
install -m 644 doc/*.md /usr/share/doc/bitcoinrpc
|
||||
install -m 644 CREDITS /usr/share/doc/bitcoinrpc
|
||||
install -m 644 LICENSE /usr/share/doc/bitcoinrpc
|
||||
install -m 644 Changelog.md /usr/share/doc/bitcoinrpc
|
||||
Installing man pages
|
||||
install -m 644 doc/man3/bitcoinrpc*.gz /usr/local/man/man3
|
||||
```
|
||||
|
||||
## Preparando o código
|
||||
|
||||
``libbitcoinrpc`` tem métodos simples e bem estruturados para conectar-se ao nosso `bitcoind`, executando chamadas RPC e decodificando a resposta.
|
||||
|
||||
Para usar o ``libbitcoinrpc``, é importante certificar de que nossos arquivos do código incluam os cabeçalhos apropriados:
|
||||
``` c
|
||||
#include <jansson.h>
|
||||
#include <bitcoinrpc.h>
|
||||
```
|
||||
|
||||
Precisaremos também vincular as bibliotecas apropriadas sempre que possamos compilar:
|
||||
|
||||
```
|
||||
$ cc yourcode.c -lbitcoinrpc -ljansson -o yourcode
|
||||
```
|
||||
|
||||
## Construindo a conexão
|
||||
|
||||
Para construir a conexão com o servidor ``bitcoind`` é necessário alguns simples passos.
|
||||
|
||||
Primeiro, inicialize a biblioteca:
|
||||
```
|
||||
bitcoinrpc_global_init();
|
||||
```
|
||||
Em seguida, vamos conectar ao ``Bitcoind`` com ``bitcoinrpc_cl_init_params``. Os quatro argumentos necessários para o ``bitcoinrpc_cl_init_params`` são o nome de usuário, a senha, o endereço IP e a porta. A esta altura, você deve saber todas essas informações, já que foram necessárias para realizar o trabalho com o [curl](04_4__interlude_using_curl.md). Apenas para recordar, o endereço de IP é 127.0.0.1 e a porta 18332 devem estar corretos para a configuração padrão da testenet descrita neste documento, enquanto podemos encontrar o usuário e a senha no arquivo ``~/.bitcoin/bitcoin.conf``.
|
||||
```
|
||||
$ cat bitcoin.conf
|
||||
server=1
|
||||
dbcache=1536
|
||||
par=1
|
||||
maxuploadtarget=137
|
||||
maxconnections=16
|
||||
rpcuser=StandUp
|
||||
rpcpassword=6305f1b2dbb3bc5a16cd0f4aac7e1eba
|
||||
rpcallowip=127.0.0.1
|
||||
debug=tor
|
||||
prune=550
|
||||
testnet=1
|
||||
[test]
|
||||
rpcbind=127.0.0.1
|
||||
rpcport=18332
|
||||
[main]
|
||||
rpcbind=127.0.0.1
|
||||
rpcport=8332
|
||||
[regtest]
|
||||
rpcbind=127.0.0.1
|
||||
rpcport=18443
|
||||
```
|
||||
Com essas informações, vamos colocá-las no ``bitcoinrpc_cl_init_params``:
|
||||
``` c
|
||||
bitcoinrpc_cl_t *rpc_client;
|
||||
rpc_client = bitcoinrpc_cl_init_params("StandUp", "6305f1b2dbb3bc5a16cd0f4aac7e1eba", "127.0.0.1", 18332);
|
||||
```
|
||||
|
||||
> **MAINNET VS TESTNET:** A porta seria a 8332 caso estivéssemos usando a configuração da rede principal.
|
||||
|
||||
Se o ``rpc_client`` for inicializado com sucesso, poderemos enviar os comandos do RPC.
|
||||
|
||||
Mais tarde, quando tivermos feito com a conexão de ``bitcoind``, poderemos fechar da seguinte maneira:
|
||||
``` c
|
||||
bitcoinrpc_global_cleanup();
|
||||
```
|
||||
|
||||
### Testando o código de teste
|
||||
|
||||
O código de teste pode ser encontrado [no diretório src com o nome 15_1_testbitcoin.c](src/15_1_testbitcoin.c). Vamos fazer o download para a nossa máquina TestNet e depois inserir a senha correta do RPC (e alterar o usuário RPC se não tivermos criado o servidor com StandUp).
|
||||
|
||||
Podemos compilar e executar o código da seguinte maneira:
|
||||
```
|
||||
$ cc testbitcoin.c -lbitcoinrpc -ljansson -o testbitcoin
|
||||
$ ./testbitcoin
|
||||
Successfully connected to server!
|
||||
```
|
||||
|
||||
> :warning: **ATENÇÃO:** Se esquecermos de inserir a senha RPC nesta ou em qualquer outro código que possuem dependências do RPC, receberemos um misterioso ``ERROR CODE 5``.
|
||||
|
||||
## Fazendo uma chamada ao RPC
|
||||
|
||||
Para usarmos um método RPC usando ``libbitcoinrpc``, devemos inicializar uma variável do tipo ``bitcoinrpc_method_t``. Podemos fazer com o valor apropriado para o método que desejamos utilizar, que estão todos listados na [Referências do BitcoinRPC](https://github.com/gitmarek/libbitcoinrpc/blob/master/doc/reference.md).
|
||||
``` c
|
||||
bitcoinrpc_method_t *getmininginfo = NULL;
|
||||
getmininginfo = bitcoinrpc_method_init(BITCOINRPC_METHOD_GETMININGINFO);
|
||||
```
|
||||
Normalmente definiríamos os parâmetros em seguida, mas o ``GetMiningInfo`` não requer parâmetros, por isso podemos pular essa parte.
|
||||
|
||||
Também devemos criar outros dois objetos, um "objeto de resposta" e um "objeto de erro". Eles podem ser inicializados da seguinte forma:
|
||||
``` c
|
||||
bitcoinrpc_resp_t *btcresponse = NULL;
|
||||
btcresponse = bitcoinrpc_resp_init();
|
||||
|
||||
bitcoinrpc_err_t btcerror;
|
||||
```
|
||||
Vamos usar a variável ``rpc_client`` que aprendemos no teste anterior e vamos adicionar nosso método ``getmininginfo`` e os outros dois objetos:
|
||||
``` c
|
||||
bitcoinrpc_call(rpc_client, getmininginfo, btcresponse, &btcerror);
|
||||
```
|
||||
|
||||
### Mostrando o retorno da chamada
|
||||
|
||||
Com certeza iremos querer saber o que a RPC retornou. Para fazermos isso, vamos recuperar a saída da nossa chamada como sendo um objeto JSON com ``bitcoinrpc_resp_get`` e vamos salvá-la em um objeto padrão ``jansson``, do tipo ``json_t``:
|
||||
``` c
|
||||
json_t *jsonresponse = NULL;
|
||||
jsonresponse = bitcoinrpc_resp_get(btcresponse);
|
||||
```
|
||||
Se quisermos gerar os resultados completos da chamada RPC no JSON, podemos fazer com uma simples invocação do ``json_dumps``, da biblioteca ``jansson``:
|
||||
``` c
|
||||
printf("%s\n", json_dumps(j, JSON_INDENT(2)));
|
||||
```
|
||||
No entanto, como agora estamos escrevendo programas completos, provavelmente iremos querer fazer um trabalho mais sutil, como retirar valores individuais do JSON para algum uso específico. A [Referência do Jansson](https6//jansson.readthedocs.Io/en/2.10/apiref.html) traz detalhes de como fazer.
|
||||
|
||||
Assim como estávamos usando o [curl](04_4__interlude_using_curl.md), descobrimos que o RPC retorna um objeto JSON contendo um ``ID``, um ``error`` e, mais importante, um objeto JSON do tipo ``result``.
|
||||
|
||||
A função ``json_object_get`` permite recuperar um valor (como o ``result``) de um objeto JSON usando chaves:
|
||||
``` c
|
||||
json_t *jsonresult = NULL;
|
||||
jsonresult = json_object_get(jsonresponse,"result");
|
||||
printf("%s\n", json_dumps(jsonresult, JSON_INDENT(2)));
|
||||
```
|
||||
|
||||
No entanto, provavelmente iremos querer analisar informações ainda mais profundas, para obter uma variável específica. Depois de recuperar o valor apropriado, precisaremos convertê-lo em um objeto C padrão usando a função ``JSON_*_value``. Por exemplo, para acessar um integer usamos o ``json_integer_value``:
|
||||
``` c
|
||||
json_t *jsonblocks = NULL;
|
||||
jsonblocks = json_object_get(jsonresult,"blocks");
|
||||
|
||||
int blocks;
|
||||
blocks = json_integer_value(jsonblocks);
|
||||
printf("Block Count: %d\n",blocks);
|
||||
```
|
||||
|
||||
> :warning: **ATENÇÃO:** É extremamente fácil ocasionar erros de segmentação no código C quando estivermos trabalhando com os objetos ``jansson`` caso fiquemos confusos com que tipo de objeto estamos recuperando. Por isso, precisamos fazer isso com cuidado usando o ``bitcoin-cli help`` para saber o que devemos esperar, e se tivermos uma falha de segmentação, primeiro precisamos analisar se nossas funções de recuperação JSON estão corretas.
|
||||
|
||||
### Testando o código de informação
|
||||
|
||||
Vamos recuperar o código de teste que está no [diretório src](15_1_GetMiningInfo.c).
|
||||
```
|
||||
$ cc getmininginfo.c -lbitcoinrpc -ljansson -o getmininginfo
|
||||
$ ./getmininginfo
|
||||
Full Response: {
|
||||
"result": {
|
||||
"blocks": 1804406,
|
||||
"difficulty": 4194304,
|
||||
"networkhashps": 54842097951591.781,
|
||||
"pooledtx": 127,
|
||||
"chain": "test",
|
||||
"warnings": "Warning: unknown new rules activated (versionbit 28)"
|
||||
},
|
||||
"error": null,
|
||||
"id": "474ccddd-ef8c-4e3f-93f7-fde72fc08154"
|
||||
}
|
||||
|
||||
Just the Result: {
|
||||
"blocks": 1804406,
|
||||
"difficulty": 4194304,
|
||||
"networkhashps": 54842097951591.781,
|
||||
"pooledtx": 127,
|
||||
"chain": "test",
|
||||
"warnings": "Warning: unknown new rules activated (versionbit 28)"
|
||||
}
|
||||
|
||||
Block Count: 1804406
|
||||
```
|
||||
|
||||
## Fazendo uma chamada RPC usando argumentos
|
||||
|
||||
Mas e se a sua chamada RPC tiver argumentos?
|
||||
|
||||
### Criando uma matriz JSON
|
||||
|
||||
Para enviar parâmetros para a nossa chamada RPC usando ``libbitcoinrpc`` teremos que envolvê-los em uma matriz json. Como uma matriz é apenas uma simples listagem de valores, tudo o que precisamos fazer é codificar os parâmetros como elementos ordenados na matriz.
|
||||
|
||||
Vamos criar a matriz JSON usando a função ``json_array do`` do ``jansson``:
|
||||
``` c
|
||||
json_t *params = NULL;
|
||||
params = json_array();
|
||||
```
|
||||
Vamos fazer o processo inverso que fizemos para acessar valores do JSON: Vamos converter objetos no C para objetos no JSON usando as funções ``JSON_*``. Depois, vamos anexar tudo à matriz:
|
||||
``` c
|
||||
json_array_append_new(params,json_string(tx_rawhex));
|
||||
```
|
||||
|
||||
Observe que existem duas variantes para o comando de anexação: ``json_array_apend_new``, que acrescenta uma variável recém-criada, e ``json_array_apend``, que anexa uma variável existente.
|
||||
|
||||
Esta metodologia simples ``json_array_apend_new`` servirá para a maioria dos comandos RPC com parâmetros, mas alguns dos comandos RPC exigem entradas mais complexas. Nesses casos, precisaremos criar objetos JSON ou arrays em JSON, que anexaremos ao parâmetros de array como de costume. A próxima seção contém um exemplo de como fazer isso usando o ``CrayAwTransaction``, que contém uma matriz JSON de objetos JSON para as entradas, um objeto JSON para as saídas e o parâmetro ``locktime``.
|
||||
|
||||
### Atribuindo os parâmetros
|
||||
|
||||
Quando criamos o parâmetro array no JSON, simplesmente o atribuímos depois de inicializar o método RPC, da seguinte maneira:
|
||||
``` c
|
||||
bitcoinrpc_method_set_params(rpc_method, params)
|
||||
```
|
||||
Esta seção não inclui uma amostra abrangente dessa metodologia mais complexa, mas vamos vê-la em ação várias vezes no nosso primeiro programa C mais abrangente usando o RPC, na próxima seção.
|
||||
|
||||
## Resumo do capítulo Acessando o Bitcoind usando C com bibliotecas RPC
|
||||
|
||||
Ao vincular às bibliotecas ``BitcoinRPC`` do RPC e as bibliotecas ``jansson`` do JSON, podemos acessar facilmente o ``bitcoind`` usando chamadas RPC de uma biblioteca C. Para fazer isso, criamos uma conexão RPC, que faz as chamadas individuais de RPC, algumas delas passando alguns parâmetros. O ``jansson`` permite decodificar as respostas no formato JSON. A próxima seção demonstrará como isso pode ser usado para um programa de uso do mundo real.
|
||||
|
||||
* :fire: ***Qual é o poder de C?*** O C permite que façamos o próximo passo muito além do script shell, permitindo a criação de programas mais complexos e robustos.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Vamos falar mais um pouco no "Conversando com o Bitcoind usando C" no capítulo [15.2: Programando o Bitcoind usando C com bibliotecas RPC](15_2_Programming_bitcoind_with_c.md).
|
354
pt/15_2_Programming_Bitcoind_with_C.md
Normal file
354
pt/15_2_Programming_Bitcoind_with_C.md
Normal file
@ -0,0 +1,354 @@
|
||||
|
||||
# 15.2: Programando o Bitcoind usando C com bibliotecas RPC
|
||||
|
||||
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho que pode estar aguardando revisão. Portanto, leitor, tenha cuidado.
|
||||
|
||||
A sessão [§15.1](15_1_Accessing_Bitcoind_with_C.md) apresentou a metodologia para a criação de programas C usando bibliotecas RPC e JSON. Agora vamos mostrar o potencial dessas bibliotecas C fazendo algumas coisas um pouco mais avançadas usando o programa real do Bitcoin.
|
||||
|
||||
## Planejando o código
|
||||
|
||||
Esta seção irá criar uma versão simples do ``sendtoaddress``, permitindo ao usuário enviar as moedas para um endereço, desde que tenha um UTXO grande o suficiente para isso. Aqui está o que precisamos fazer:
|
||||
|
||||
1. Solicitar um endereço e uma quantia;
|
||||
2. Definir uma taxa arbitrária;
|
||||
3. Preparar nosso RPC;
|
||||
4. Encontrar um UTXO que seja grande o suficiente para pagar o valor + a taxa;
|
||||
5. Criar uma mudança de endereço;
|
||||
6. Criar uma transação bruta que envie o UTXO para o endereço e altere o endereço;
|
||||
7. Assinar a transação;
|
||||
8. Enviar a transação.
|
||||
|
||||
### Planejando para o futuro
|
||||
|
||||
Como este é o nosso primeiro programa C funcional, vamos mantê-lo simples (ou seja, vamos usar a filosofia, _Keep it Simple_ ou também conhecida como KISS). Se estivéssemos produzindo um programa para estar em produção, desejaríamos pelo menos os seguintes passos:
|
||||
|
||||
1. Testar e/ou higienizar as entradas;
|
||||
2. Calcular uma taxa automaticamente;
|
||||
3. Pensar logicamente sobre qual UTXO seria válido utilizar;
|
||||
4. Combinar vários UTXOs, caso seja necessário;
|
||||
5. Ficar atento a mais erros nos comandos ``libbitcoinrpc`` ou no ``jansson``;
|
||||
6. Observar se há erros nas respostas RPC.
|
||||
|
||||
Se deseja continuar a expandir este exemplo, seria ótimo começar a lidar com as inadequações do programa.
|
||||
|
||||
## Escrevendo o sistema de transação
|
||||
|
||||
Agora estamos prontos para realizar o passo a passo do nosso plano
|
||||
|
||||
### Etapa 1: Solicitando um endereço e uma quantia
|
||||
|
||||
Inserir as informações é bem simples se usarmos os argumentos na linha de comando:
|
||||
``` c
|
||||
if(argc != 3) {
|
||||
|
||||
printf("ERROR: Only %i arguments! Correct usage is '%s [recipient] [amount]'\n",argc-1,argv[0]);
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
char *tx_recipient = argv[1];
|
||||
float tx_amount = atof(argv[2]);
|
||||
|
||||
printf("Sending %4.8f BTC to %s\n",tx_amount,tx_recipient);
|
||||
```
|
||||
|
||||
> :aviso: **ATENÇÃO:** Um programa real precisaria de uma higienização muito melhor dessas variáveis.
|
||||
|
||||
### Etapa 2: Definindo uma taxa arbitrária
|
||||
|
||||
Este exemplo colocamos uma taxa arbitrária de 0.0005 BTC para garantir que as transações do teste sejam processadas rapidamente:
|
||||
|
||||
``` c
|
||||
float tx_fee = 0.0005;
|
||||
float tx_total = tx_amount + tx_fee;
|
||||
```
|
||||
|
||||
> :warning: **ATENÇÃO:** Um programa real calcularia uma taxa que minimizasse o custo, garantindo que a velocidade fosse aquela que o remetente estivesse disposto a utilizar.
|
||||
|
||||
### Etapa 3: Preparando nosso RPC
|
||||
|
||||
Obviamente, precisaremos preparar todas as nossas variáveis novamente, conforme discutido na sessão [§15.1: Acessando o Bitcoind usando C](15_1_Accessing_Bitcoind_with_C.md). Também precisaremos inicializar a nossa biblioteca, conectar o cliente RPC e preparar nosso objeto de resposta:
|
||||
``` c
|
||||
bitcoinrpc_global_init();
|
||||
rpc_client = bitcoinrpc_cl_init_params("bitcoinrpc", "YOUR-RPC-PASSWD", "127.0.0.1", 18332);
|
||||
btcresponse = bitcoinrpc_resp_init();
|
||||
```
|
||||
|
||||
### Etapa 4: Encontrando um UTXO
|
||||
|
||||
Para encontrar um UTXO, precisaremos chamar a função RPC ``listunspent``:
|
||||
``` c
|
||||
rpc_method = bitcoinrpc_method_init(BITCOINRPC_METHOD_LISTUNSPENT);
|
||||
bitcoinrpc_call(rpc_client, rpc_method, btcresponse, &btcerror);
|
||||
```
|
||||
|
||||
No entanto, o verdadeiro trabalho consiste em decodificar a resposta. Na seção anterior vimos que a biblioteca ``jansson`` era "um tanto quanto desajeitada" e esta é a razão: Precisamos criar (e limpar) um conjunto muito grande de objetos ``json_t`` para descobrir o que queremos.
|
||||
|
||||
Primeiro, precisamos nos recuperar o campo ``result`` do JSON:
|
||||
``` c
|
||||
json_t *lu_response = NULL;
|
||||
json_t *lu_result = NULL;
|
||||
|
||||
lu_response = bitcoinrpc_resp_get(btcresponse);
|
||||
lu_result = json_object_get(lu_response,"result");
|
||||
```
|
||||
|
||||
> :warning: **ATENÇÃO:** Só obteremos um resultado se não houver nenhum erro. Aqui temos um momento para melhorar nossa verificação de erros no código que iremos colocar em produção.
|
||||
|
||||
Em seguida, vamos fazer um laço, examinando cada transação que não foi gasta, que aparece como um elemento em sua matriz do resultado JSON:
|
||||
``` c
|
||||
int i;
|
||||
|
||||
const char *tx_id = 0;
|
||||
int tx_vout = 0;
|
||||
double tx_value = 0.0;
|
||||
|
||||
for(i = 0 ; i < json_array_size(lu_result) ; i++) {
|
||||
|
||||
json_t *lu_data = NULL;
|
||||
lu_data = json_array_get(lu_result, i);
|
||||
|
||||
json_t *lu_value = NULL;
|
||||
lu_value = json_object_get(lu_data,"amount");
|
||||
tx_value = json_real_value(lu_value);
|
||||
```
|
||||
|
||||
O UTXO é grande o suficiente para pagar sua transação? Se sim, pegue-o!
|
||||
|
||||
> :warning: **ATENÇÃO:** Um programa em produção pensaria com mais cuidado sobre qual UTXO utilizar, com base no tamanho e em outros fatores. Provavelmente não pegaria apenas o primeiro mais simples e pronto.
|
||||
|
||||
``` c
|
||||
if(tx_value > tx_total) {
|
||||
|
||||
json_t *lu_txid = NULL;
|
||||
lu_txid = json_object_get(lu_data,"txid");
|
||||
tx_id = strdup(json_string_value(lu_txid));
|
||||
|
||||
json_t *lu_vout = NULL;
|
||||
lu_vout = json_object_get(lu_data,"vout");
|
||||
tx_vout = json_integer_value(lu_vout);
|
||||
|
||||
json_decref(lu_value);
|
||||
json_decref(lu_txid);
|
||||
json_decref(lu_vout);
|
||||
json_decref(lu_data);
|
||||
break;
|
||||
|
||||
}
|
||||
```
|
||||
Você também deve limpar os principais elementos do JSON:
|
||||
``` c
|
||||
}
|
||||
|
||||
json_decref(lu_result);
|
||||
json_decref(lu_response);
|
||||
```
|
||||
|
||||
> :warning: **ATENÇÃO:** Um programa em produção também se certificaria de que os UTXOs são passíveis de serem `gastos`.
|
||||
|
||||
Se não encontramos nenhum UTXOs grande o suficiente, teremos que relatar este infortúnio ao usuário... E talvez, sugerir que ele deva usar um programa melhor, que irá mesclar os UTXOs de maneira correta.
|
||||
``` c
|
||||
if(!tx_id) {
|
||||
|
||||
printf("Very Sad: You don't have any UTXOs larger than %f\n",tx_total);
|
||||
exit(-1);
|
||||
}
|
||||
```
|
||||
|
||||
> **ATENÇÃO** Um programa em produção usaria sub-rotinas para este tipo de pesquisa, de forma que pudéssemos chamar vários RPCs de uma biblioteca de funções C. Vamos apenas colocar tudo em um `main` como parte da nossa filosofia KISS.
|
||||
|
||||
### Etapa 5: Criando um endereço de troco
|
||||
|
||||
Repita a metodologia padrão de pesquisa RPC para obter um endereço de troco:
|
||||
``` c
|
||||
rpc_method = bitcoinrpc_method_init(BITCOINRPC_METHOD_GETRAWCHANGEADDRESS);
|
||||
|
||||
if(!rpc_method) {
|
||||
|
||||
printf("ERROR: Unable to initialize listunspent method!\n");
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
bitcoinrpc_call(rpc_client, rpc_method, btcresponse, &btcerror);
|
||||
|
||||
if(btcerror.code != BITCOINRPCE_OK) {
|
||||
|
||||
printf("Error: listunspent error code %d [%s]\n", btcerror.code,btcerror.msg);
|
||||
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
lu_response = bitcoinrpc_resp_get(btcresponse);
|
||||
lu_result = json_object_get(lu_response,"result");
|
||||
char *changeaddress = strdup(json_string_value(lu_result));
|
||||
```
|
||||
A única diferença é quais informações específicas são extraídas do objeto JSON.
|
||||
|
||||
> :warning: **ATENÇÃO:** Aqui temos uma sub-rotina que seria bem legal: Abstrair toda a inicialização e chamada do método RPC.
|
||||
|
||||
### Etapa 6: Criando uma transação bruta
|
||||
|
||||
Criar a transação bruta real é outra parte complicada da programação da substituição do ``sendtoaddress``. Isso porque requer a criação de um objeto JSON complexo como parâmetro.
|
||||
|
||||
Para criarmos esses parâmetros corretamente, precisaremos revisar o que o RPC ``createrawtransaction`` espera que passemos como argumento. Felizmente, isso é fácil de determinar usando a funcionalidade ``bitcoin-cli help``:
|
||||
```
|
||||
$ bitcoin-cli help createrawtransaction
|
||||
createrawtransaction [{"txid":"id","vout":n},...] {"address":amount,"data":"hex",...} ( locktime )
|
||||
```
|
||||
|
||||
Para relembrar, as entradas serão uma matriz JSON contendo um objeto JSON para cada UTXO. Então, as saídas estarão todas em um objeto JSON. É mais fácil criar esses elementos JSON de dentro para fora, usando os comandos ``jansson``.
|
||||
|
||||
#### Etapa 6.1: Criando os parâmetros de entrada
|
||||
|
||||
Para criar o objeto de entrada para nosso UTXO, vamos usar o ``json_object`` e preencher com os valores-chave usando ``json_object_set_new`` (para referências recém-criadas) ou ``json_object_set`` (para referências já existentes):
|
||||
``` c
|
||||
json_t *inputtxid = NULL;
|
||||
inputtxid = json_object();
|
||||
|
||||
json_object_set_new(inputtxid,"txid",json_string(tx_id));
|
||||
json_object_set_new(inputtxid,"vout",json_integer(tx_vout));
|
||||
```
|
||||
|
||||
Pode-se notar que teremos que traduzir novamente cada tipo de variável C em um tipo de variável JSON usando a função apropriada, como ``json_string`` ou ``json_integer``.
|
||||
|
||||
Para criar o array de entrada para todos os UTXOs, vamos usar o ``json_array`` e, em seguida, preenchê-lo com os objetos usando o ``json_array_append``:
|
||||
``` c
|
||||
json_t *inputparams = NULL;
|
||||
inputparams = json_array();
|
||||
json_array_append(inputparams,inputtxid);
|
||||
```
|
||||
|
||||
#### Etapa 6.2: Criando os parâmetros de saída
|
||||
|
||||
Para criar a matriz de saída para a transação, vamos seguir o mesmo processo, criando um objeto JSON com ``json_object`` e, em seguida, vamos preenchê-lo com o ``json_object_set``:
|
||||
``` c
|
||||
json_t *outputparams = NULL;
|
||||
outputparams = json_object();
|
||||
|
||||
char tx_amount_string[32];
|
||||
sprintf(tx_amount_string,"%.8f",tx_amount);
|
||||
char tx_change_string[32];
|
||||
sprintf(tx_change_string,"%.8f",tx_value - tx_total);
|
||||
|
||||
json_object_set(outputparams, tx_recipient, json_string(tx_amount_string));
|
||||
json_object_set(outputparams, changeaddress, json_string(tx_change_string));
|
||||
```
|
||||
|
||||
> :warning: **ATENÇÃO:** É possível pensar que teremos que inserir os valores do Bitcoin como sendo números, usando a função ``json_real``. Infelizmente, isso expõe um dos maiores problemas com a integração da biblioteca ``jansson`` e o Bitcoin. O Bitcoin só é válido até oito dígitos depois da casa decimal. Devemos nos lembrar que 0,00000001 BTC é um satoshi, e essa é a menor divisão possível de um Bitcoin. O tipo ``double`` no C oferecem mais dígitos do que precisamos, embora sejam frequentemente imprecisos depois das oito casas decimais. Se tentarmos convertê-los diretamente do nosso valor ``double`` no C (ou de um tipo ``float``, neste caso) para um valor Bitcoin, a imprecisão frequentemente criará um valor Bitcoin com mais de oito dígitos. Antes da versão Bitcoin Core 0.12, isso não era problema, e podíamos usar a função ``json_real``. Mas à partir dessa versão, se tentarmos usar a função ``createrawtransaction`` com mais do que oito dígitos, obteremos um erro e a transação não será criada. Como resultado, se o valor do Bitcoin _sempre_ se tornar um ``double`` ou ``float``, devemos deixar com apenas oito casas decimais antes de transformá-lo em uma ``string``. Obviamente, isso é um erro, portanto, certifique-se disso para que o código continue funcionando nas versões mais novas do Bitcoin Core.
|
||||
|
||||
#### Etapa 6.3: Criando a Matriz de Parâmetros
|
||||
|
||||
Para terminarmos de criar os parâmetros, só precisaremos agrupá-los em uma matriz JSON:
|
||||
``` c
|
||||
json_t *params = NULL;
|
||||
params = json_array();
|
||||
json_array_append(params,inputparams);
|
||||
json_array_append(params,outputparams);
|
||||
```
|
||||
|
||||
#### Etapa 6.4: Fazendo a chamada ao RPC
|
||||
|
||||
Vamos usar o método normal para criar uma chamada ao RPC:
|
||||
``` c
|
||||
rpc_method = bitcoinrpc_method_init(BITCOINRPC_METHOD_CREATERAWTRANSACTION);
|
||||
```
|
||||
Agora, porém, devemos adicionar os nossos parâmetros. Isso pode ser feito facilmente com a função ``bitcoinrpc_method_set_params``:
|
||||
``` c
|
||||
if(bitcoinrpc_method_set_params(rpc_method, params) != BITCOINRPCE_OK) {
|
||||
|
||||
fprintf(stderr, "Error: Could not set params for createrawtransaction");
|
||||
|
||||
}
|
||||
```
|
||||
Depois, é só executar o RPC e obter os resultados:
|
||||
``` c
|
||||
bitcoinrpc_call(rpc_client, rpc_method, btcresponse, &btcerror);
|
||||
|
||||
lu_response = bitcoinrpc_resp_get(btcresponse);
|
||||
lu_result = json_object_get(lu_response,"result");
|
||||
|
||||
char *tx_rawhex = strdup(json_string_value(lu_result));
|
||||
```
|
||||
### Etapa 7. Assinando a transação
|
||||
|
||||
É muito mais fácil atribuir um parâmetro simples a uma função. Basta criar uma matriz JSON e, em seguida, atribuir o parâmetro à matriz:
|
||||
``` c
|
||||
params = json_array();
|
||||
json_array_append_new(params,json_string(tx_rawhex));
|
||||
```
|
||||
Por fim, vamos assinar a transação seguindo o rigamarole típico para criar uma chamada RPC:
|
||||
``` c
|
||||
rpc_method = bitcoinrpc_method_init(BITCOINRPC_METHOD_SIGNRAWTRANSACTION);
|
||||
if(bitcoinrpc_method_set_params(rpc_method, params) != BITCOINRPCE_OK) {
|
||||
|
||||
fprintf(stderr, "Error: Could not set params for signrawtransaction");
|
||||
|
||||
}
|
||||
|
||||
json_decref(params);
|
||||
|
||||
bitcoinrpc_call(rpc_client, rpc_method, btcresponse, &btcerror);
|
||||
lu_response = bitcoinrpc_resp_get(btcresponse);
|
||||
```
|
||||
Novamente, usar a função ``jansson`` para acessar a saída pode ser complicado. Devemos lembrar que ``hex`` é parte de um objeto JSON, não um resultado independente, como era quando criamos a transação bruta. Claro, sempre podemos acessar essas informações a partir da ajuda da linha de comando: ``bitcoin-cli help signrawtransaction``
|
||||
``` c
|
||||
lu_result = json_object_get(lu_response,"result");
|
||||
json_t *lu_signature = json_object_get(lu_result,"hex");
|
||||
char *tx_signrawhex = strdup(json_string_value(lu_signature));
|
||||
json_decref(lu_signature);
|
||||
```
|
||||
> :warning: ***ATENÇÃO:*** Um programa em produção obviamente iria testar cuidadosamente a resposta de cada comando RPC para se certificar de que não teria erros. Isso é ainda mais verdadeiro para a função ``signrawtransaction``, porque podemos acabar com uma transação parcialmente assinada. Ou ainda pior, se não verificarmos os erros no objeto JSON, veremos apenas o ``hex`` e não iremos saber que ele não está assinado ou se está parcialmente assinado.
|
||||
|
||||
### Etapa 8. Enviando a transação
|
||||
|
||||
Agora podemos enviar a transação, usando todas as técnicas aprendidas anteriormente:
|
||||
``` c
|
||||
params = json_array();
|
||||
json_array_append_new(params,json_string(tx_signrawhex));
|
||||
|
||||
rpc_method = bitcoinrpc_method_init(BITCOINRPC_METHOD_SENDRAWTRANSACTION);
|
||||
|
||||
if(bitcoinrpc_method_set_params(rpc_method, params) != BITCOINRPCE_OK) {
|
||||
|
||||
fprintf(stderr, "Error: Could not set params for sendrawtransaction");
|
||||
|
||||
}
|
||||
|
||||
json_decref(params);
|
||||
|
||||
bitcoinrpc_call(rpc_client, rpc_method, btcresponse, &btcerror);
|
||||
lu_response = bitcoinrpc_resp_get(btcresponse);
|
||||
lu_result = json_object_get(lu_response,"result");
|
||||
|
||||
char *tx_newid = strdup(json_string_value(lu_result));
|
||||
|
||||
printf("Txid: %s\n",tx_newid);
|
||||
```
|
||||
|
||||
O código inteiro, com um _pouco_ mais verificação de erros, está disponível no Apêndice.
|
||||
|
||||
## Testando o código
|
||||
|
||||
O código completo pode ser encontrado no [diretório src/](src/15_2_sendtoaddress.c).
|
||||
|
||||
Compile-o como de costume:
|
||||
```
|
||||
$ cc sendtoaddress.c -lbitcoinrpc -ljansson -o sendtoaddress
|
||||
```
|
||||
Agora, é possível utilizá-lo para enviar fundos para um endereço:
|
||||
|
||||
```
|
||||
./sendtoaddress tb1qynx7f8ulv4sxj3zw5gqpe56wxleh5dp9kts7ns .001
|
||||
Txid: b93b19396f8baa37f5f701c7ca59d3128144c943af5294aeb48e3eb4c30fa9d2
|
||||
```
|
||||
Você pode ver as informações sobre esta transação que enviamos clicando [aqui](https://mempool.space/pt/testnet/tx/b93b19396f8baa37f5f701c7ca59d3128144c943af5294aeb48e3eb4c30fa9d2/).
|
||||
|
||||
## Resumo do Programando o Bitcoind usando C com bibliotecas RPC
|
||||
|
||||
Com acesso a uma biblioteca C, podemos criar programas com muito mais recursos quando comparados aos scripts no shell. Mas isso pode dar muito trabalho! Mesmo com 316 linhas de código, o ``sendtoaddress.c`` não cobre todos os detalhes necessários para transacionar bitcoins de forma segura e inteligente.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Aprenda mais sobre "Programando o Bitcoind usando C" na próxima sessão [15.3: Recebendo notificações usando C com a biblioteca ZMQ](15_3_Receiving_Bitcoind_Notifications_with_C.md).
|
155
pt/15_3_Receiving_Bitcoind_Notifications_with_C.md
Normal file
155
pt/15_3_Receiving_Bitcoind_Notifications_with_C.md
Normal file
@ -0,0 +1,155 @@
|
||||
|
||||
# 15.3 Recebendo notificações usando C com a biblioteca ZMQ
|
||||
|
||||
> :information_source: **NOTA:** Esta seção foi adicionada recentemente ao curso e é um rascunho que pode estar aguardando revisão. Portanto, leitor, tenha cuidado.
|
||||
|
||||
As sessões [§15.1](15_1_Accessing_Bitcoind_with_C.md) e [§15.2](15_2_Programming_Bitcoind_with_C.md) introduziram as bibliotecas RPC e JSON no C e, também mostrou uma das vantagens de acessar os comandos RPC do Bitcoin por meio de uma linguagem de programação: A capacidade de criar programas razoavelmente complexos. Este capítulo apresenta uma terceira biblioteca, a [ZMQ](http://zeromq.org/) e, ao fazer isso, revela outra vantagem: A capacidade de monitorar as notificações. Iremos usá-la para codificar para ouvirmos a blockchain.
|
||||
|
||||
> :book: ***O que é ZMQ?*** O ZeroMQ (ZMQ) é uma biblioteca de mensagens assíncronas de alto desempenho que fornece uma fila de mensagens. A biblioteca oferece suporte a padrões de mensagens comuns (pub/sub, request/reply, client/server e outros) em uma variedade de transportes (TCP, in-process, inter-process, multicast, WebSocket e mais), tornando mensagens entre processos tão simples quanto mensagens entre threads. Podemos encontrar mais detalhes sobre as notificações do ZMQ e outros tipos de mensagens [neste repositório](https://github.com/Actinium-project/ChainTools/blob/master/docs/chainlistener.md).
|
||||
|
||||
## Configurando o ZMQ
|
||||
|
||||
Antes de podemos ouvir a blockchain, precisaremos configurar o ``bitcoind`` para permitir as notificações ZMQ. Por isso, precisamos instalar a biblioteca ZMQ para tirar proveito dessas notificações.
|
||||
|
||||
### Configurando o ``bitcoind`` para usar o ZMQ
|
||||
|
||||
O Bitcoin Core está pronto para ZMQ, mas devemos especificar os endpoints do ZMQ. O ZeroMQ publish-sockets prefixa cada item de dados com um prefixo de tópico arbitrário que permite aos clientes assinantes solicitarem apenas os itens com um prefixo correspondente. Existem atualmente quatro tópicos suportados pelo ``bitcoind``:
|
||||
```
|
||||
$ bitcoind --help | grep zmq | grep address
|
||||
-zmqpubhashblock=<address>
|
||||
-zmqpubhashtx=<address>
|
||||
-zmqpubrawblock=<address>
|
||||
-zmqpubrawtx=<address>
|
||||
```
|
||||
|
||||
Podemos executar o ``bitcoind`` com argumentos de linha de comando para endpoints ZMQ, como mostrado acima, mas também podemos criar um endpoint acessível adicionando linhas apropriadas ao nosso arquivo ``~/.bitcoin/bitcoin.conf`` e reiniciando o sistema.
|
||||
|
||||
```
|
||||
zmqpubrawblock=tcp://127.0.0.1:28332
|
||||
zmqpubrawtx=tcp://127.0.0.1:28333
|
||||
```
|
||||
Podemos então testar se os nossos endpoints estão funcionando usando o RPC ``getzmqnotifications``:
|
||||
|
||||
```
|
||||
$ bitcoin-cli getzmqnotifications
|
||||
[
|
||||
{
|
||||
"type": "pubrawblock",
|
||||
"address": "tcp://127.0.0.1:28332",
|
||||
"hwm": 1000
|
||||
},
|
||||
{
|
||||
"type": "pubrawtx",
|
||||
"address": "tcp://127.0.0.1:28333",
|
||||
"hwm": 1000
|
||||
}
|
||||
]
|
||||
```
|
||||
Nosso ``bitcoind`` agora irá emitir as notificações ZMQ
|
||||
|
||||
### Instalando o ZMQ
|
||||
|
||||
Para aproveitar essas notificações, precisamos de uma biblioteca ZMQ para usar com o C, portanto, estaremos usando uma nova biblioteca ZMQ ao invés da biblioteca ``libbitcoinrpc`` nesta seção, mas no futuro, podemos combinar ambas.
|
||||
|
||||
Felizmente, as bibliotecas ZMQ estão disponíveis por meio de pacotes Debian padrão:
|
||||
```
|
||||
$ sudo apt-get install libzmq3-dev
|
||||
$ sudo apt-get install libczmq-dev
|
||||
```
|
||||
Agora estamos pronto para escrever o código!
|
||||
|
||||
## Escrevendo o programa de notificação
|
||||
|
||||
O programa C à seguir é um cliente simples que se inscreve em um ponto da conexão ZMQ servido pelo ``bitcoind`` e lê as mensagens recebidas.
|
||||
|
||||
O programa requer dois parâmetros: O primeiro é o "servidor", que é o ponto de conexão TCP exposto pelo ``bitcoind``. O segundo é o "tópico", que atualmente é o ``zmqpubhashblock``,``zmqpubhashtx``, ``zmqpubrawblock`` ou ``zmqpubrawtx``. O tópico precisa ter suporte do ``bitcoin.conf`` e o endereço IP e a porta do servidor devem corresponder ao que está definido no arquivo de configuração.
|
||||
|
||||
``` c
|
||||
#include <czmq.h>
|
||||
int main(int argc, char ** argv) {
|
||||
|
||||
char *zmqserver;
|
||||
char *topic;
|
||||
|
||||
if(argc < 3) {
|
||||
printf("\nUSAGE:\nchainlistener <tcp://localhost:port> <topic>\n\n");
|
||||
return 0;
|
||||
} else {
|
||||
zmqserver = argv[1];
|
||||
topic = argv[2];
|
||||
}
|
||||
```
|
||||
Abriremos um soquete ZMQ para o servidor e para o tópico definido:
|
||||
``` c
|
||||
zsock_t *socket = zsock_new_sub(zmqserver, topic);
|
||||
assert(socket);
|
||||
```
|
||||
Depois, vamos esperar:
|
||||
``` c
|
||||
while(1) {
|
||||
zmsg_t *msg;
|
||||
int rc = zsock_recv(socket, "m", &msg);
|
||||
assert(rc == 0);
|
||||
|
||||
char *header = zmsg_popstr(msg);
|
||||
zframe_t *zdata = zmsg_pop(msg);
|
||||
unsigned int *no = (unsigned int*)zmsg_popstr(msg);
|
||||
|
||||
char *data = zframe_strhex(zdata);
|
||||
int len = zframe_size(zdata);
|
||||
printf("Size: %d\n", len);
|
||||
printf("Data: %s", data);
|
||||
printf("\nNo: %d\n", *no);
|
||||
|
||||
free(header);
|
||||
free(data);
|
||||
free(no);
|
||||
free(zdata);
|
||||
zmsg_destroy(&msg);
|
||||
sleep(1);
|
||||
}
|
||||
```
|
||||
Enquanto esperamos, observamos as mensagens no soquete ZMQ. Sempre que recebermos uma mensagem, iremos retirá-la da pilha, relatando o número, comprimento e, o os dados que foram importante para nós.
|
||||
|
||||
É isso!
|
||||
|
||||
Claro, quando terminar o processo, precisamos limpar tudo:
|
||||
``` c
|
||||
zsock_destroy(&socket);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Testando o código de notificação
|
||||
|
||||
O código-fonte completo está no [diretório src/](src/15_3_chainlistener.c) como de costume. Precisamos compilá-lo:
|
||||
```
|
||||
$ cc -o chainlistener chainlistener.c -I/usr/local/include -L/usr/local/lib -lzmq -lczmq
|
||||
```
|
||||
Depois, podemos executá-lo com os tópicos e endereços que definimos no nosso ``bitcoin.conf``:
|
||||
```
|
||||
$ ./chainlistener tcp://127.0.0.1:28333 rawtx
|
||||
Size: 250
|
||||
Data: 02000000000101F5BD2032E5A9E6650D4E411AD272E391F26AFC3C9102B7C0C7444F8F74AE86010000000017160014AE9D51ADEEE8F46ED2017F41CD631D210F2ED9C5FEFFFFFF0203A732000000000017A9147231060F1CDF34B522E9DB650F44EDC6C0714E4C8710270000000000001976A914262437B129CF8592AB2EDC59C07D19C57729F72888AC02483045022100AE316D5F21657E3525271DE39EB285D8A0E89A20AB6413824E88CE47DCD0EFE702202F61E10C2A8F4A7125D5EB63AEF883D8E3584A0ECED0D349283AABB6CA5E066D0121035A77FE575A9005E3D3FF0682E189E753E82FA8BFF0A20F8C45F06DC6EBE3421079111B00
|
||||
No: 67
|
||||
Size: 249
|
||||
Data: 0200000000010165C986992F7DAD22BBCE3FCF0BF546EDBC3C599618B04CFA22D9E64EF0CE4C030000000017160014B58E0A5CD68B249F1C407E9AAE9CD0332AAA3067FEFFFFFF02637932000000000017A914CCC47261489036CB6B9AA610857793FF5752E5378710270000000000001976A914262437B129CF8592AB2EDC59C07D19C57729F72888AC0247304402206CCC3F3B4BE01D4E532A01C2DC6BC3B53E4FFB6B494C8B87DD603EFC648A159902201653841E8B16A814DC375129189BB7CF01CFF7D269E91178645B6A97F5C7F4F10121030E20F3D2F172281B8DC747F007DF24B352248AC09E48CA64016942A8F01D317079111B00
|
||||
No: 68
|
||||
Size: 250
|
||||
Data: 02000000000101E889CFC1FFE127BA49F6C1011388606A194109AE1EDAAB9BEE215E123C14A7920000000017160014577B0B3C2BF91B33B5BD70AE9E8BD8144F4B87E7FEFFFFFF02C34B32000000000017A914A9F1440402B46235822639C4FD2F78A31E8D269E8710270000000000001976A914262437B129CF8592AB2EDC59C07D19C57729F72888AC02483045022100B46318F53E1DCE63E7109DB4FA54AF40AADFC2FEB0E08263756BC3B7A6A744CB02200851982AF87DBABDC3DFC3362016ECE96AECFF50E24D9DCF264AE8966A5646FE0121039C90FCB46AEA1530E5667F8FF15CB36169D2AD81247472F236E3A3022F39917079111B00
|
||||
No: 69
|
||||
Size: 250
|
||||
Data: 0200000000010137527957C9AD6CFF0C9A74597E6EFCD7E1EBD53E942AB2FA34A831046CA11488000000001716001429BFF05B3CD79E9CCEFDB5AE82139F72EB3E9DB0FEFFFFFF0210270000000000001976A914262437B129CF8592AB2EDC59C07D19C57729F72888AC231E32000000000017A9146C8D5FE29BFDDABCED0D6F4D8E82DCBFD9D34A8B8702483045022100F259846BAE29EB2C7A4AD711A3BC6109DE69AE91E35B14CA2742157894DD9760022021464E09C00ABA486AEAA0C49FEE12D2850DC03F57F04A1A9E2CC4D0F4F1459C012102899F24A9D60132F4DD1A5BA6DCD1E4E4B6C728927BA482C2C4E511679F60CA5779111B00
|
||||
No: 70
|
||||
.......
|
||||
```
|
||||
|
||||
### Resumo do capítulo Recebendo Notificações Usando C com a Biblioteca ZMQ
|
||||
|
||||
Ao usar a estrutura ZMQ, podemos receber notificações facilmente, inscrevendo-as em um ponto de conexão exposto pelo ``bitcoind`` através do nosso arquivo de configuração.
|
||||
|
||||
> :fire: ***Qual é o poder das notificações?*** Com as notificações, não dependemos mais dos usuários para emitir os comandos. Ou seja, podemos criar programas que monitoram o blockchain do Bitcoin e tomar as ações apropriadas quando certas coisas ocorrem. Isso, por sua vez, pode ser utilizado juntamente com os comandos RPC que programamos nas seções anteriores. Este também é um grande passo além do que poderíamos fazer com os scripts shell: Certamente, podemos criar scripts shell que fica ouvindo infinitamente, mas existem outras linguagens de programação que possuem ferramentas melhores para isso.
|
||||
|
||||
## O Que Vem Depois?
|
||||
|
||||
Saiba mais sobre "como Programar com RPC" no [Capítulo 16: Programando Bitcoin com Libwally](16_0_Programming_with_Libwally.md).
|
223
pt/README.md
223
pt/README.md
@ -1 +1,222 @@
|
||||
_directory for the Portuguese translation._
|
||||
# Aprendendo Bitcoin pela Linha de Comando 2.0.1
|
||||
### _por Christopher Allen e Shannon Appelcline_
|
||||
|
||||

|
||||
|
||||
"Aprendendo Bitcoin pela Linha de Comando", esta é a versão em português de [Learning Bitcoin from the Command Line](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line), um tutorial para trabalhar com Bitcoin (e Lightning) que ensina a interação direta com os servidores da maneira mais robusta e segura, para começar a trabalhar com criptomoedas.
|
||||
|
||||
> NOTA: Este é um rascunho em progresso, para que eu possa receber algum feedback de revisores iniciais. Ainda não está pronto para uso.
|
||||
|
||||
_Este tutorial assume que você tenha um mínimo de background em como utilizar a linha de comando. Caso contrário, a vários tutoriais que estão disponíveis na internet, e eu possui um curso para usuários de Mac em: https://github.com/ChristopherA/intro-mac-command-line._
|
||||
|
||||
## Traduções
|
||||
|
||||
* [Espanhol](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/tree/spanish-translation/es) - em progresso
|
||||
|
||||
Se você gostaria de fazer a sua própria tradução, por favor veja [Contribuindo](https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/tree/master#contributing) abaixo.
|
||||
|
||||
## Índice
|
||||
|
||||
### PARTE UM: SE PREPARANDO PARA O BITCOIN
|
||||
|
||||
**Estado**: Finalizado. Atualizado para 0.20.
|
||||
|
||||
* [1.0: Introdução à Programação com Bitcoin Core e Lightning](01_0_Introduction.md)
|
||||
* [Prefácio: Introduzindo o Bitcoin](01_1_Introducing_Bitcoin.md)
|
||||
* [2.0: Configurando um Bitcoin-Core VPS](02_0_Setting_Up_a_Bitcoin-Core_VPS.md)
|
||||
* [2.1: Configurando um Bitcoin-Core VPS com Bitcoin Standup](02_1_Setting_Up_a_Bitcoin-Core_VPS_with_StackScript.md)
|
||||
* [2.2: Configurando uma Máquina Bitcoin-Core de Outras Formas](02_2_Setting_Up_Bitcoin_Core_Other.md)
|
||||
|
||||
### PARTE DOIS: USANDO BITCOIN-CLI
|
||||
|
||||
**Estado:** Finalizado. Atualizado para 0.20.
|
||||
|
||||
* [3.0: Compreendendo Sua Configuração do Bitcoin](03_0_Understanding_Your_Bitcoin_Setup.md)
|
||||
* [3.1: Verificando Sua Configuração do Bitcoin](03_1_Verifying_Your_Bitcoin_Setup.md)
|
||||
* [3.2: Conhecendo Sua Configuração do Bitcoin](03_2_Knowing_Your_Bitcoin_Setup.md)
|
||||
* [3.3: Configurando Sua Carteira](03_3_Setting_Up_Your_Wallet.md)
|
||||
* [Prefácio: Usando Variáveis de Linha de Comando](03_3__Interlude_Using_Command-Line_Variables.md)
|
||||
* [3.4: Recebendo uma Transação](03_4_Receiving_a_Transaction.md)
|
||||
* [3.5: Compreendendo o Descritor](03_5_Understanding_the_Descriptor.md)
|
||||
* [4.0: Enviando Transações no Bitcoin](04_0_Sending_Bitcoin_Transactions.md)
|
||||
* [4.1: Enviando Moedas da Maneira Fácil](04_1_Sending_Coins_The_Easy_Way.md)
|
||||
* [4.2: Criando uma Transação Bruta](04_2_Creating_a_Raw_Transaction.md)
|
||||
* [Prefácio: Usando JQ](04_2__Interlude_Using_JQ.md)
|
||||
* [4.3: Criando uma Transação Bruta com Argumentos Nomeados](04_3_Creating_a_Raw_Transaction_with_Named_Arguments.md)
|
||||
* [4.4: Enviando Moedas com Transações Brutas](04_4_Sending_Coins_with_a_Raw_Transaction.md)
|
||||
* [Prefácio: Usando Curl](04_4__Interlude_Using_Curl.md)
|
||||
* [4.5: Enviando Moedas com Transações Brutas Automatizadas](04_5_Sending_Coins_with_Automated_Raw_Transactions.md)
|
||||
* [4.6: Criando uma Transação SegWit](04_6_Creating_a_Segwit_Transaction.md)
|
||||
* [5.0: Controlando Transações no Bitcoin](05_0_Controlling_Bitcoin_Transactions.md)
|
||||
* [5.1 Atentando-se para Transações Presas](05_1_Watching_for_Stuck_Transactions.md)
|
||||
* [5.2: Re-enviando uma Transação com RBF](05_2_Resending_a_Transaction_with_RBF.md)
|
||||
* [5.3: Financiando uma Transação com CPFP](05_3_Funding_a_Transaction_with_CPFP.md)
|
||||
* [6.0: Expandindo Transações no Bitcoin com Multisigs](06_0_Expanding_Bitcoin_Transactions_Multisigs.md)
|
||||
* [6.1: Enviando uma Transação com Multisig](06_1_Sending_a_Transaction_to_a_Multisig.md)
|
||||
* [6.2: Gastando uma Transação com Multisig](06_2_Spending_a_Transaction_to_a_Multisig.md)
|
||||
* [6.3: Enviando & Gastando um Multisig Automatizado](06_3_Sending_an_Automated_Multisig.md)
|
||||
* [7.0: Expandindo Transações no Bitcoin com PSBTs](07_0_Expanding_Bitcoin_Transactions_PSBTs.md)
|
||||
* [7.1: Criando uma Transação Parcialmente Assinada no Bitcoin (PSBT)](07_1_Creating_a_Partially_Signed_Bitcoin_Transaction.md)
|
||||
* [7.2: Usando uma Transação Parcialmente Assinada no Bitcoin (PSBT)](07_2_Using_a_Partially_Signed_Bitcoin_Transaction.md)
|
||||
* [7.3: Integrando com Carteiras de Hardware](07_3_Integrating_with_Hardware_Wallets.md)
|
||||
* [8.0: Expandindo Transações no Bitcoin de Outras Maneiras](08_0_Expanding_Bitcoin_Transactions_Other.md)
|
||||
* [8.1: Enviando uma Transação com um Locktime](08_1_Sending_a_Transaction_with_a_Locktime.md)
|
||||
* [8.2: Enviando uma Transação com Dados](08_2_Sending_a_Transaction_with_Data.md)
|
||||
|
||||
### PARTE TRÊS: PROGRAMANDO NO BITCOIN
|
||||
|
||||
**Estado:** Finalizado. Atualizado para 0.20 e btcdeb.
|
||||
|
||||
* [9.0: Introduzindo Scripts no Bitcoin](09_0_Introducing_Bitcoin_Scripts.md)
|
||||
* [9.1: Compreendendo a Fundação de Transações](09_1_Understanding_the_Foundation_of_Transactions.md)
|
||||
* [9.2: Rodando um Script no Bitcoin](09_2_Running_a_Bitcoin_Script.md)
|
||||
* [9.3: Testando um Script no Bitcoin](09_3_Testing_a_Bitcoin_Script.md)
|
||||
* [9.4: Programando um P2PKH](09_4_Scripting_a_P2PKH.md)
|
||||
* [9.5: Programando um P2WPKH](09_5_Scripting_a_P2WPKH.md)
|
||||
* [10.0: Embutindo Scripts em Transações P2SH no Bitcoin](10_0_Embedding_Bitcoin_Scripts_in_P2SH_Transactions.md)
|
||||
* [10.1: Compreendendo a Fundação do P2SH](10_1_Understanding_the_Foundation_of_P2SH.md)
|
||||
* [10.2: Construindo a Estrutura do P2SH](10_2_Building_the_Structure_of_P2SH.md)
|
||||
* [10.3: Rodando um Script no Bitcoin com P2SH](10_3_Running_a_Bitcoin_Script_with_P2SH.md)
|
||||
* [10.4: Programando um Multisig](10_4_Scripting_a_Multisig.md)
|
||||
* [10.5: Programando um Script Segwit](10_5_Scripting_a_Segwit_Script.md)
|
||||
* [10.6: Gastando uma Transação P2SH](10_6_Spending_a_P2SH_Transaction.md)
|
||||
* [11.0: Capacitando Timelock com Scripts no Bitcoin](11_0_Empowering_Timelock_with_Bitcoin_Scripts.md)
|
||||
* [11.1: Compreendendo Opções de Timelock](11_1_Understanding_Timelock_Options.md)
|
||||
* [11.2: Usando CLTV em Scripts](11_2_Using_CLTV_in_Scripts.md)
|
||||
* [11.3: Usando CSV em Scripts](11_3_Using_CSV_in_Scripts.md)
|
||||
* [12.0: Expandindo Scripts no Bitcoin](12_0_Expanding_Bitcoin_Scripts.md)
|
||||
* [12.1: Usando Condicionais de Script](12_1_Using_Script_Conditionals.md)
|
||||
* [12.2: Usando Outros Comandos de Script](12_2_Using_Other_Script_Commands.md)
|
||||
* [13.0: Projetando Scripts Reais no Bitcoin](13_0_Designing_Real_Bitcoin_Scripts.md)
|
||||
* [13.1: Escrevendo Scripts de Quebra-Cabeças](13_1_Writing_Puzzle_Scripts.md)
|
||||
* [13.2: Escrevendo Scripts Complexos de Multisig](13_2_Writing_Complex_Multisig_Scripts.md)
|
||||
* [13.3: Capacitando o Bitcoin com Scripts](13_3_Empowering_Bitcoin_with_Scripts.md)
|
||||
|
||||
### PARTE QUATRO: USANDO TOR
|
||||
|
||||
**Estado:** Finalizado.
|
||||
|
||||
* [14.0: Usando Tor](14_0_Using_Tor.md)
|
||||
* [14.1: Verificando Sua Configuração do Tor](14_1_Verifying_Your_Tor_Setup.md)
|
||||
* [14.2: Mudando Seus Serviços Ocultos do Bitcoin](14_2_Changing_Your_Bitcoin_Hidden_Services.md)
|
||||
* [14.3: Adicionando SSH aos Seus Serviços Ocultos](14_3_Adding_SSH_Hidden_Services.md)
|
||||
|
||||
### PARTE CINCO: PROGRAMANDO COM RPC
|
||||
|
||||
**Estado:** Finalizado.
|
||||
|
||||
* [15.0: Conversando com o Bitcoind com C](15_0_Talking_to_Bitcoind.md)
|
||||
* [15.1: Acessando o Bitcoind em C com Livrarias RPC](15_1_Accessing_Bitcoind_with_C.md)
|
||||
* [15.2: Programando o Bitcoind em C com Livrarias RPC](15_2_Programming_Bitcoind_with_C.md)
|
||||
* [15.3: Recebendo Notificações em C com Livrarias ZMQ](15_3_Receiving_Bitcoind_Notifications_with_C.md)
|
||||
* [16.0: Programando Bitcoin com Libwally](16_0_Programming_with_Libwally.md)
|
||||
* [16.1: Configurando a Libwally](16_1_Setting_Up_Libwally.md)
|
||||
* [16.2: Usando BIP39 na Libwally](16_2_Using_BIP39_in_Libwally.md)
|
||||
* [16.3: Usando BIP32 na Libwally](16_3_Using_BIP32_in_Libwally.md)
|
||||
* [16.4: Usando PSBTs na Libwally](16_4_Using_PSBTs_in_Libwally.md)
|
||||
* [16.5: Usando Scripts na Libwally](16_5_Using_Scripts_in_Libwally.md)
|
||||
* [16.6: Usando Outras Funções na Libwally](16_6_Using_Other_Functions_in_Libwally.md)
|
||||
* [16.7: Integrando Libwally e Bitcoin-CLI](16_7_Integrating_Libwally_and_Bitcoin-CLI.md)
|
||||
* [17.0: Conversando com o Bitcoind com Outras Linguagens](17_0_Talking_to_Bitcoind_Other.md)
|
||||
* [17.1: Acessando o Bitcoind com Go](17_1_Accessing_Bitcoind_with_Go.md)
|
||||
* [17.2: Acessando o Bitcoind com Java](17_2_Accessing_Bitcoind_with_Java.md)
|
||||
* [17.3: Acessando o Bitcoind com Node JS](17_3_Accessing_Bitcoind_with_NodeJS.md)
|
||||
* [17.4: Acessando o Bitcoind com Python](17_4_Accessing_Bitcoind_with_Python.md)
|
||||
* [17.5: Acessando o Bitcoind com Rust](17_5_Accessing_Bitcoind_with_Rust.md)
|
||||
* [17.6: Acessando o Bitcoind com Swift](17_6_Accessing_Bitcoind_with_Swift.md)
|
||||
|
||||
### PARTE SEIS: USANDO LIGHTNING-CLI
|
||||
|
||||
**Estado:** Finalizado.
|
||||
|
||||
* [18.0: Compreendendo Sua Configuração Lightning](18_0_Understanding_Your_Lightning_Setup.md)
|
||||
* [18.1: Verificando Sua Configuração c-lightning](18_1_Verifying_Your_Lightning_Setup.md)
|
||||
* [18.2: Conhecendo Sua Configuração c-lightning](18_2_Knowing_Your_lightning_Setup.md)
|
||||
* [Prefácio: Acessando um Segundo Node Lightning](18_2__Interlude_Accessing_a_Second_Lightning_Node.md)
|
||||
* [18.3: Criando um Canal Lightning](18_3_Setting_Up_a_Channel.md)
|
||||
* [19.0: Usando Lightning](19_0_Using_Lightning.md)
|
||||
* [19.1: Gerando um Pedido de Pagamento](19_1_Generate_a_Payment_Request.md)
|
||||
* [19.2: Pagando uma Fatura](19_2_Paying_a_Invoice.md)
|
||||
* [19.3: Fechando um Canal Lighnting]((19_3_Closing_a_Channel.md))
|
||||
* [19.4: Expandindo a Rede Lightning](19_4_Lightning_Network_Review.md)
|
||||
|
||||
### APÊNDICES
|
||||
|
||||
**Estado:** Finalizado.
|
||||
|
||||
* [Apêndices](A0_Appendices.md)
|
||||
* [Apêndice I: Compreendendo o Bitcoin Standup](A1_0_Understanding_Bitcoin_Standup.md)
|
||||
* [Apêndice II: Compilando Bitcoin da Fonte](A2_0_Compiling_Bitcoin_from_Source.md)
|
||||
* [Apêndice III: Usando o Regtest do Bitcoin](A3_0_Using_Bitcoin_Regtest.md)
|
||||
|
||||
## Estado - Beta
|
||||
|
||||
v2.0.1 do **Aprendendo Bitcoin pela Linha de Comando** é uma beta. Pode ainda estar sendo sujeito a revisões ou edições de terceiros, mas já pode ser utilizado para o aprendizado.
|
||||
|
||||
Nós também estamos considerando o que poderíamos incluir em uma [v3.0](TODO-30.md) do curso. Se você gostaria de apoiar um trabalho desse tipo, torne-se um [Patrocinador no GitHub](https://github.com/sponsors/BlockchainCommons) ou nos apoie pelo nosso [Servidor BTCPay](https://btcpay.blockchaincommons.com/), e nos informe que **Aprendendo Bitcoin** foi o motivo.
|
||||
|
||||
## Origem, Autores, Copyright & Licenças
|
||||
|
||||
A não ser que indicado o contrário (ou neste [/README.md](./README.md) ou nos comentários nos cabeçalhos dos aquivos), os conteúdos deste repositório são Copyright © 2020 por Blockchain Commons, LLC, e licenciados sob [CC-BY](./LICENSE-CC-BY-4.0.md).
|
||||
|
||||
## Apoio Financeiro
|
||||
|
||||
*Aprendendo Bitcoin pela Linha de Comando* é um projeto da [Blockchain Commons](https://www.blockchaincommons.com/). Nós somos, com orgulho, uma organização de benefício social sem fins lucrativos comprometida ao desenvolvimento aberto e open source. O nosso trabalho é financiado inteiramente por doações e parcerias colaborativas com pessoas como você. Toda contribuição será gasta na construção de ferramenta abertas, tecnologias e técnicas que sustentam e avançam segurança do blockchain e da internet e promovem uma rede aberta.
|
||||
|
||||
Para apoiar financeiramente o desenvolvimento futuro de `$projectname` e outros projetos, por favor considere se tornar um Patrocinador da Blockchain Commons por meio de patrocínios mensais contínuos como um [Patrocinador no GitHub](https://github.com/sponsors/BlockchainCommons). Você também pode apoiar a Blockchain Commons com bitcoins através do nosso [Servidor BTCPay](https://btcpay.blockchaincommons.com/).
|
||||
|
||||
## Contribuindo
|
||||
|
||||
Nós encorajamos contribuições públicas por meio de issues e pull requests! Por favor revise [CONTRIBUTING.md](./CONTRIBUTING.md) para detalhes sobre o nosso processo de desenvolvimento. Todas as contribuições para este repositório requerem um [Contrato de Licença do Contribuidor](./CLA.md) assinado por GPG.
|
||||
|
||||
Se você gostaria de providenciar uma tradução de Aprendendo Bitcoin para outra língua, por favor veja também [TRANSLATING.md](./TRANSLATING.md).
|
||||
|
||||
### Discussões
|
||||
|
||||
O melhor lugar para conversar sobre a Blockchain Commons e seus projetos é na nossa área de Discussões no GitHub.
|
||||
|
||||
[**Discussões Sobre Blockchain Commons**](https://github.com/BlockchainCommons/Community/discussions). Para desenvolvedores, estagiários a patrocinadores da Blockchain Commons, por favor utilize a área de discussões do [repositório da Comunidade](https://github.com/BlockchainCommons/Community) para falar sobre questões gerais da Blockchain Commons, o programa de estágio ou outros tópicos que não sejam o [Gordian System](https://github.com/BlockchainCommons/Gordian/discussions) ou os [padrões de carteira](https://github.com/BlockchainCommons/AirgappedSigning/discussions), pois cada um destes tem sua área de discussão própria.
|
||||
|
||||
### Outras Questões & Problemas
|
||||
|
||||
Como uma comunidade open-source e de desenvolvimento aberto, a Blockchain Commons não tem os recursos para fornecer apoio direto dos nossos projetos. Por favor considere a área de discussões como um local onde você pode receber respostas a perguntas. Alternativamente, por favor use o campo de [issues](./issues) deste repositório. Infelizmente, não podemos fazer promessas em relação ao tempo de resposta.
|
||||
|
||||
Se a sua empresa requer apoio para usar os nossos projetos, por favor nos contacte diretamente para opcões. Nós podemos ser capazes de te oferecer um contrato para apoio por um de nossos contribuidores, ou poderemos te indicar outra entidade que possa oferecer o apoio contratual que você precisa.
|
||||
|
||||
### Créditos
|
||||
|
||||
As pessoas a seguir contribuíram diretamente para este repositório. Você pode adicionar o seu nome aqui ao se envolver. O primeiro passo é aprender como contribuir por meio da nossa documentação em [CONTRIBUTING.md](./CONTRIBUTING.md).
|
||||
|
||||
|
||||
| Nome | Função | Github | Email | GPG Fingerprint |
|
||||
| ----------------- | ------------------- | ------------------------------------------------- | ------------------------------------- | -------------------------------------------------- |
|
||||
| Christopher Allen | Autor Líder | [@ChristopherA](https://github.com/ChristopherA) | \<ChristopherA@LifeWithAlacrity.com\> | FDFE 14A5 4ECB 30FC 5D22 74EF F8D3 6C91 3574 05ED |
|
||||
| Shannon Appelcline | Autor Líder | [@shannona](https://github.com/shannona) | \<shannon.appelcline@gmail.com\> | 7EC6 B928 606F 27AD |
|
||||
|
||||
|
||||
Contribuições adicionais estão listadas abaixo:
|
||||
|
||||
| Função | Nomes |
|
||||
| ------------------- | ---------------------------------------- |
|
||||
| ***Contribuidores:*** | [gg2001](https://github.com/gg2001) (seções Go, Node.js), [gorazdko](https://github.com/gorazdko) (seção Rust), [Javier Vargas](https://github.com/javiervargas) (seções C, Java, Lightning, Tor), [jodobear](https://github.com/jodobear) (Apêndice: Compilando Bitcoin, seção Python) |
|
||||
| ***Revisores:*** | Glen Willem [@gwillem](https://github.com/gwillem) |
|
||||
| ***Patrocinadores:*** | Blockstream Corporation |
|
||||
|
||||
|
||||
## Revelação Responsável
|
||||
|
||||
Nós queremos manter todo o nosso software seguro para todos. Se você descobriu uma vulnerabilidade de segurança, nós agradeceríamos a sua ajuda em nos revelá-la de forma responsável. Infelizmente, nós não conseguimos oferecer programas de recompensa (bug bounty) no momento.
|
||||
|
||||
Nós pedimos que você seja honesto e que, ao melhor de sua capacidade, não vaze informações ou prejudique qualquer usuário, seus dados, ou a comunidade de desenvolvedores. Por favor nos dê uma quantidade de tempo razoável para consertar o problema antes de publicá-lo. Não defraude nossos usuários ou nós mesmos no processo de descoberta. Nós prometemos não entrar com um processo contra pesquisadores que apontem um problema, dado que dêem o seu melhor para seguir estas diretrizes.
|
||||
|
||||
### Reportando uma Vulnerabilidade
|
||||
|
||||
Por favor reporte suspeitas de vulnerabilidades de segurança em um email privado para ChristopherA@BlockchainCommons.com (não utilize esse email para suporte). Por favor NÃO crie issues públicos para suspeitas de vulnerabilidades de segurança.
|
||||
|
||||
As seguintes chaves podem ser utilizadas para comunicar informação confidencial para desenvolvedores:
|
||||
|
||||
| Nome | Fingerprint |
|
||||
| ----------------- | -------------------------------------------------- |
|
||||
| Christopher Allen | FDFE 14A5 4ECB 30FC 5D22 74EF F8D3 6C91 3574 05ED |
|
||||
|
||||
Você pode importar uma chave rodando o seguinte comando com a fingerprint daquele indivíduo: `gpg --recv-keys "<fingerprint>"` Se certifique de colocar o fingerprint entre aspas caso o mesmo contenha espaços.
|
@ -0,0 +1,75 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA512
|
||||
|
||||
|
||||
# Contributor License Agreement
|
||||
|
||||
Version 1.0
|
||||
|
||||
Name: `KoreaComK`
|
||||
|
||||
E-Mail: `koreacomk@protonmail.com`
|
||||
|
||||
Legal Jurisdiction: Wyoming, United States of America
|
||||
|
||||
Project: https://github.com/BlockchainCommons/bc-lethe-kit
|
||||
|
||||
Date: `2021-06-16`
|
||||
|
||||
## Purpose
|
||||
|
||||
This agreement gives Blockchain Commons, LLC the permission it needs in order to accept my contributions into its open software project and to manage the intellectual property in that project over time.
|
||||
|
||||
## License
|
||||
|
||||
I hereby license Blockchain Commons, LLC to:
|
||||
|
||||
1. do anything with my contributions that would otherwise infringe my copyright in them
|
||||
|
||||
2. do anything with my contributions that would otherwise infringe patents that I can or become able to license
|
||||
|
||||
3. sublicense these rights to others on any terms they like
|
||||
|
||||
## Reliability
|
||||
|
||||
I understand that Blockchain Commons will rely on this license. I may not revoke this license.
|
||||
|
||||
## Awareness
|
||||
|
||||
I promise that I am familiar with legal rules, like ["work made for hire" rules](http://worksmadeforhire.com), that can give employers and clients ownership of intellectual property in work that I do. I am also aware that legal agreements I might sign, like confidential information and invention assignment agreements, will usually give ownership of intellectual property in my work to employers, clients, and companies that I found. If someone else owns intellectual property in my work, I need their permission to license it.
|
||||
|
||||
## Copyright Guarantee
|
||||
|
||||
I promise not to offer contributions to the project that contain copyrighted work that I do not have legally binding permission to contribute under these terms. When I offer a contribution with permission, I promise to document in the contribution who owns copyright in what work, and how they gave permission to contribute it. If I later become aware that one of my contributions may have copyrighted work of others that I did not have permission to contribute, I will notify Blockchain Commons, in confidence, immediately.
|
||||
|
||||
## Patent Guarantee
|
||||
|
||||
I promise not to offer contributions to the project that I know infringe patents of others that I do not have permission to contribute under these terms.
|
||||
|
||||
## Open Source Guarantee
|
||||
|
||||
I promise not to offer contributions that contain or depend on the work of others, unless that work is available under a license that [Blue Oak Council rates bronze or better](https://blueoakconcil.org/list), such as the MIT License, two- or three-clause BSD License, the Apache License Version 2.0, or the Blue Oak Model License 1.0.0. When I offer a contribution containing or depending on others' work, I promise to document in the contribution who licenses that work, along with copies of their license terms.
|
||||
|
||||
## Disclaimers
|
||||
|
||||
***As far as the law allows, my contributions come as is, without any warranty or condition. Other than under [Copyright Guarantee](#copyright-guarantee), [Patent Guarantee](#patent-guarantee), or [Open Source Guarantee](#open-source-guarantee), I will not be liable to anyone for any damages related to my contributions or this contributor license agreement, under any kind of legal claim.***
|
||||
|
||||
- ---
|
||||
|
||||
To sign this Contributor License Agreement, fill in `KoreaComK`, `koreacomk@protonmail.com`, and `2021-06-16` above. Then sign using GPG using the following command `gpg --armor --clearsign --output ./signed-cla/CLA.YOURGITHUBNAME.YOURGPGFINGERPRINT.asc CLA.md`, then either submit your signed Contributor License Agreement to this repo as a GPG signed Pull Request or email it to [ChristopherA@BlockchainCommons.com](mailto:ChristopherA@BlockchainCommons.com).
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAEBCgAdFiEE8r1q2MBC7W6cWiMvO5CXZfvqezAFAmDKToEACgkQO5CXZfvq
|
||||
ezCpJg/8DuIIHflWCcNSHljnOQgQfW/Qzys6axIB0FAO5E7VqZHD5tUzwThgxuU0
|
||||
BbniGNiqascqcMkTRWfOOXyx/Nef5bTt2CUqRU6k/3sK1VlXnWGB/zSikYeDWCUT
|
||||
rggzQ052cBm103yiaOMg2Hx0Y4qTtcN/vJyXg0aESUXz+drMItKEaQBsF2fkwtPr
|
||||
pGv7hqyu2O/u+9pMtZg8+lvHEPBdGfOVaCynrNLFTUE4+NSRNriPG/l5CTG8oEAC
|
||||
h+e7HcZDiDVK2uQvhrPJLYhXWjiUqJ0MYpI9EKA88wkotUtilNsGKC8NqU724xIu
|
||||
80hG+BeN9JWAR0wGPweVBtjkj1+hWNRbrm7ESK3gw53mfQBnAbpf23Rvk+tv24kG
|
||||
/is8dAiHGHpLxBlD4DfGeyeKReXGjWhzaOkzJSBqXC0UBq3nyqcRQtbLd2hn0zpF
|
||||
zm8/PwmB+PRGQ8TeRUa2j1o5ZUYyRCKtTARB68CrF0D26dpmtSheCGAqwp5mQqN2
|
||||
SBIHnFnFUTFJ3CEZJ4LVVGsHwfBt9BZL5D67grVJ9h19PLZsq9t4iEZLX47p8gP0
|
||||
Cp8YorqkelFZ/u+7VP1bJiZlX5E0Q/aGdLKemtSA5vbo4ua59fSw1bNWO9x19yt+
|
||||
u6u/PT8G5OoUhLldj4L8G3BFBXllb29nphtAVjh/PWxJj0dcupA=
|
||||
=o+hW
|
||||
-----END PGP SIGNATURE-----
|
@ -0,0 +1,69 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA256
|
||||
|
||||
# Contributor License Agreement
|
||||
|
||||
Version 1.0
|
||||
|
||||
Name: Namcios
|
||||
|
||||
E-Mail: namcios@protonmail.com
|
||||
|
||||
Legal Jurisdiction: Wyoming, United States of America
|
||||
|
||||
Project: https://github.com/BlockchainCommons/bc-lethe-kit
|
||||
|
||||
Date: 06/23/2021
|
||||
|
||||
## Purpose
|
||||
|
||||
This agreement gives Blockchain Commons, LLC the permission it needs in order to accept my contributions into its open software project and to manage the intellectual property in that project over time.
|
||||
|
||||
## License
|
||||
|
||||
I hereby license Blockchain Commons, LLC to:
|
||||
|
||||
1. do anything with my contributions that would otherwise infringe my copyright in them
|
||||
|
||||
2. do anything with my contributions that would otherwise infringe patents that I can or become able to license
|
||||
|
||||
3. sublicense these rights to others on any terms they like
|
||||
|
||||
## Reliability
|
||||
|
||||
I understand that Blockchain Commons will rely on this license. I may not revoke this license.
|
||||
|
||||
## Awareness
|
||||
|
||||
I promise that I am familiar with legal rules, like ["work made for hire" rules](http://worksmadeforhire.com), that can give employers and clients ownership of intellectual property in work that I do. I am also aware that legal agreements I might sign, like confidential information and invention assignment agreements, will usually give ownership of intellectual property in my work to employers, clients, and companies that I found. If someone else owns intellectual property in my work, I need their permission to license it.
|
||||
|
||||
## Copyright Guarantee
|
||||
|
||||
I promise not to offer contributions to the project that contain copyrighted work that I do not have legally binding permission to contribute under these terms. When I offer a contribution with permission, I promise to document in the contribution who owns copyright in what work, and how they gave permission to contribute it. If I later become aware that one of my contributions may have copyrighted work of others that I did not have permission to contribute, I will notify Blockchain Commons, in confidence, immediately.
|
||||
|
||||
## Patent Guarantee
|
||||
|
||||
I promise not to offer contributions to the project that I know infringe patents of others that I do not have permission to contribute under these terms.
|
||||
|
||||
## Open Source Guarantee
|
||||
|
||||
I promise not to offer contributions that contain or depend on the work of others, unless that work is available under a license that [Blue Oak Council rates bronze or better](https://blueoakconcil.org/list), such as the MIT License, two- or three-clause BSD License, the Apache License Version 2.0, or the Blue Oak Model License 1.0.0. When I offer a contribution containing or depending on others' work, I promise to document in the contribution who licenses that work, along with copies of their license terms.
|
||||
|
||||
## Disclaimers
|
||||
|
||||
***As far as the law allows, my contributions come as is, without any warranty or condition. Other than under [Copyright Guarantee](#copyright-guarantee), [Patent Guarantee](#patent-guarantee), or [Open Source Guarantee](#open-source-guarantee), I will not be liable to anyone for any damages related to my contributions or this contributor license agreement, under any kind of legal claim.***
|
||||
|
||||
- ---
|
||||
|
||||
To sign this Contributor License Agreement, fill in `$name`, `$email`, and `$date` above. Then sign using GPG using the following command `gpg --armor --clearsign --output ./signed-cla/CLA.YOURGITHUBNAME.YOURGPGFINGERPRINT.asc CLA.md`, then either submit your signed Contributor License Agreement to this repo as a GPG signed Pull Request or email it to [ChristopherA@BlockchainCommons.com](mailto:ChristopherA@BlockchainCommons.com).
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQEzBAEBCAAdFiEEVaJL4K7l20FSxqQQjjo2gxcmmrQFAmDTgZ4ACgkQjjo2gxcm
|
||||
mrRTpQgAoFpCTvov11jIeyu4kNTbFy/lxdx5vXViWSvsPa2I/Q8TgTgWoAcBw84H
|
||||
lqCDweT9dFFf3XXh2NTpgpAZ+TYbzBQgC3lNMc9BhKfgUOHnR+UFwAj7HyD2fPiE
|
||||
e92BCLEmuSxk4ls8KFZ0wLySXNZGSehOb/K0EdYbw1szPQGEVmOvZq+vTkPfEDqO
|
||||
XK3T81r5+YCwazQHNXbOwnpbVryqi700ndF8R7MTZ6Z1LqOKQCfXBLSBiDhQ8Wk6
|
||||
BhYbpXpJFGzlSrlfBG1jvQdUq2grAQ8CEhMprNJXPt294a6RAHMZ4bNz65OiAM4e
|
||||
d/AaQ/DlwNvVZM7ARxorsucuqYkQUA==
|
||||
=sF7Q
|
||||
-----END PGP SIGNATURE-----
|
Loading…
x
Reference in New Issue
Block a user