<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Blockchain - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Aprenda a codificar - de graça. Tutoriais de programação em Python, JavaScript, Linux e muito mais. ]]>
        </description>
        <link>https://www.freecodecamp.org/portuguese/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Blockchain - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/portuguese/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 22 May 2026 15:17:00 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/portuguese/news/tag/blockchain/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Uma introdução detalhada aos sistemas distribuídos ]]>
                </title>
                <description>
                    <![CDATA[ Escrito por: Stanislav Kozlovski O que é um sistema distribuído e por que é tão complicado? Com a expansão tecnológica cada vez maior do mundo, os sistemas distribuídos estão se tornando cada vez mais difundidos. Eles são um vasto e complexo campo de estudo em ciência da computação.  Este ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/uma-introducao-detalhada-aos-sistemas-distribuidos/</link>
                <guid isPermaLink="false">64bc0806b04bf0067ce24c53</guid>
                
                    <category>
                        <![CDATA[ Blockchain ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marcelo Pena ]]>
                </dc:creator>
                <pubDate>Sun, 23 Jun 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/1_iyQPowJqG7o492vz5kNmXw.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/a-thorough-introduction-to-distributed-systems-3b91562c9b3c/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">A Thorough Introduction to Distributed Systems</a>
      </p><p>Escrito por: Stanislav Kozlovski</p><h2 id="o-que-um-sistema-distribu-do-e-por-que-t-o-complicado">O que é um sistema distribuído e por que é tão complicado?</h2><p>Com a expansão tecnológica cada vez maior do mundo, os sistemas distribuídos estão se tornando cada vez mais difundidos. Eles são um vasto e complexo campo de estudo em ciência da computação. </p><p>Este artigo tem como objetivo apresentar a você os sistemas distribuídos de maneira básica, dando uma ideia das diferentes categorias desses sistemas, sem mergulhar profundamente nos detalhes.</p><h2 id="o-que-um-sistema-distribu-do"><strong>O que é um sistema distribuído<strong>?</strong></strong></h2><p>Em sua definição mais simples, um sistema distribuído é um grupo de computadores trabalhando juntos de modo a parecer como um único computador para o usuário final.</p><p>Essas máquinas possuem um estado compartilhado, operam de maneira concorrente e podem falhar independentemente sem afetar o tempo de atividade de todo o sistema.</p><p>Proponho que trabalhemos gradualmente através de um exemplo de distribuição de um sistema para que você possa ter uma melhor compreensão de tudo isso.</p><p>Vamos usar um banco de dados como exemplo! Bancos de dados tradicionais são armazenados no sistema de arquivos de uma única máquina. Sempre que você deseja buscar/inserir informações nele, você se comunica diretamente com aquela máquina.</p><p>Para distribuir esse sistema de banco de dados, precisaríamos fazer com que esse banco de dados fosse executado em várias máquinas ao mesmo tempo. O usuário deve ser capaz de se comunicar com qualquer máquina que ele escolha e não deve ser capaz de perceber que não está falando com uma única máquina – se ele insere um registro no nó nº 1, o nó nº 3 deve ser capaz de retornar esse registro.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/1_n-3Db0bssxh7B-A0Jndx0A.png" class="kg-image" alt="1_n-3Db0bssxh7B-A0Jndx0A" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/06/1_n-3Db0bssxh7B-A0Jndx0A.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/06/1_n-3Db0bssxh7B-A0Jndx0A.png 675w" width="675" height="697" loading="lazy"><figcaption>Uma arquitetura que pode ser considerada distribuída</figcaption></figure><h2 id="por-que-distribuir-um-sistema"><strong>Por que distribuir um sistema<strong>?</strong></strong></h2><p>Os sistemas são sempre distribuídos por necessidade. A verdade é que gerenciar sistemas distribuídos é um tópico complexo, repleto de armadilhas e desafios. É uma dor de cabeça implantar, manter e depurar sistemas distribuídos. Então, por que seguir por esse caminho afinal?</p><p>O que um sistema distribuído possibilita é a <strong>escalabilidade horizontal</strong>. Voltando ao nosso exemplo anterior do servidor de banco de dados único, a única maneira de lidar com mais tráfego seria atualizar o hardware em que o banco de dados está sendo executado. Isso é chamado de <strong>escalonamento vertical</strong>.</p><p>O escalonamento vertical é válido até certo ponto, mas, após um determinado ponto, você verá que mesmo o melhor hardware não é suficiente para lidar com volume suficiente de tráfego, sem mencionar o fato de que é impraticável para hospedar.</p><p>O <strong>escalonamento horizontal</strong>, por sua vez, significa simplesmente adicionar mais computadores em vez de atualizar o hardware de um único computador.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/07/image-6.png" class="kg-image" alt="image-6" width="400" height="389" loading="lazy"><figcaption>O escalonamento horizontal se torna <strong>muito mais barato</strong> após um certo limite.</figcaption></figure><p>É significativamente mais barato do que o escalonamento vertical após um certo limite, mas esse não é o principal motivo de preferência.</p><p>O escalonamento vertical só pode melhorar o desempenho até as capacidades do hardware mais recente. Essas capacidades acabam sendo <strong>insuficientes</strong> para empresas tecnológicas com cargas de trabalho moderadas a grandes.</p><p>A melhor coisa sobre o escalonamento horizontal é que não há limite para o quanto você pode escalar – sempre que o desempenho se degrada, basta adicionar outra máquina, potencialmente até o infinito.</p><p>A facilidade de escalonamento não é o único benefício que você obtém com sistemas distribuídos. <strong>Tolerância a falhas</strong> e <strong>baixa latência</strong> também são igualmente importantes.</p><p><strong><em>Tolerância a falhas</em></strong> – um cluster de dez máquinas em dois <em>data centers</em> é intrinsecamente mais tolerante a falhas do que uma única máquina. Mesmo que um <em>data center</em> pegue fogo, sua aplicação ainda funcionaria.</p><p><em><strong>Baixa latência</strong></em> – o tempo para um pacote de rede viajar pelo mundo é fisicamente limitado pela velocidade da luz. Por exemplo, o tempo mais curto possível para o <strong>tempo de ida e volta</strong> de uma solicitação (ou seja, ir e voltar) em um cabo de fibra óptica entre Nova York e Sydney é de <a href="https://www.oreilly.com/learning/primer-on-latency-and-bandwidth">160 ms</a> (texto em inglês). Sistemas distribuídos permitem que você tenha um nó em ambas as cidades, permitindo que o tráfego atinja o nó mais próximo.</p><p>No entanto, para que um sistema distribuído funcione, é necessário que o software em execução nessas máquinas seja projetado especificamente para ser executado em vários computadores ao mesmo tempo e que lide com os problemas que surgem com isso. Isso acaba sendo uma tarefa complicada.</p><h2 id="escalonando-nosso-banco-de-dados">Escalonando nosso banco de dados</h2><p>Imagine que nossa aplicação para a web se tornou extremamente popular. Imagine também que nosso banco de dados começou a receber o dobro de consultas por segundo do que ele pode lidar. Essa aplicação começaria imediatamente a perder desempenho e isso seria percebido por nossos usuários.</p><p>Vamos trabalhar juntos e fazer com que nosso banco de dados aumente sua capacidade para atender essas altas demandas.</p><p>Em uma aplicação para a web típica, geralmente se lê informações com muito mais frequência do que se insere novas informações ou se modifica as antigas.</p><p>Existe uma maneira de aumentar o desempenho de leitura e é chamada de estratégia <strong><em>p<strong>rimary-</strong>r<strong>eplica </strong>r<strong>eplication</strong></em></strong> (replicação entre mestre-escravo). Você cria dois servidores de banco de dados que sincronizam com o servidor principal. A pegadinha é que você <strong>só pode fazer leituras</strong> dessas novas instâncias.</p><p>Sempre que você inserir ou modificar informações, você se comunica com o banco de dados principal. Ele, por sua vez, informa as réplicas assincronamente sobre a mudança e elas também a salvam.</p><p>Parabéns, agora você pode executar três vezes mais consultas de leitura! Não é ótimo?</p><h3 id="armadilha"><strong>Armadilha</strong></h3><p><strong>Peguei vocês<strong>!</strong></strong> Perdemos imediatamente o "C" nas garantias <strong><a href="https://en.wikipedia.org/wiki/ACID">ACID</a></strong> (texto em inglês) de nosso banco de dados relacional, a Consistência.</p><p>Perceba que, agora, existe a possibilidade de inserirmos um novo registro no banco de dados e, imediatamente após, realizarmos uma consulta de leitura para esse registro e não obtermos nenhuma resposta de volta, como se ele não existisse!</p><p>A propagação de novas informações do primário para a réplica não acontece instantaneamente. Na verdade, existe uma janela de tempo em que você pode obter informações desatualizadas. Se não fosse assim, o desempenho da gravação seria prejudicado, pois teria que aguardar sincronamente a propagação dos dados.</p><p>Sistemas distribuídos envolvem algumas escolhas e renúncias (<em>trade-offs</em> em inglês). Essa questão em particular é algo com que você terá que conviver se quiser escalar adequadamente.</p><h3 id="continuando-a-escalonar">Continuando a Escalonar</h3><p>Utilizando a abordagem do banco de dados replicado, podemos escalonar horizontalmente nosso tráfego de leitura até certo ponto. Isso é ótimo, mas encontramos um obstáculo em relação ao nosso tráfego de escrita — ele ainda está todo em um único servidor!</p><p>Não temos muitas opções aqui. Simplesmente precisamos dividir nosso tráfego de escrita entre vários servidores, já que um não é capaz de lidar com isso.</p><p>Uma maneira é adotar uma <a href="https://en.wikipedia.org/wiki/Multi-master_replication">estratégia de replicação multi-primária</a> (texto em inglês). Nesse caso, em vez de réplicas as quais você só pode ler, você tem vários nós primários que suportam leitura e escrita. Infelizmente, isso se torna complicado rapidamente, pois você agora tem a capacidade de <a href="http://datacharmer.blogspot.bg/2013/03/multi-master-data-conflicts-part-1.html">criar conflitos</a> (por exemplo, inserir dois registros com o mesmo ID – texto em inglês).</p><p>Vamos adotar outra técnica chamada <a href="https://medium.com/@jeeyoungk/how-sharding-works-b4dec46b3f6"><em><strong>fragmentação</strong></em></a> (também chamada de <strong><em>particionamento</em></strong> – texto em inglês).</p><p>Com a fragmentação, você divide o seu servidor em vários servidores menores, chamados de <strong><em>fragmentos</em></strong> (<em>shards</em>, em inglês) Esses fragmentos contêm registros diferentes — você cria uma regra para determinar que tipo de registros é armazenado em cada fragmento. É muito importante criar a regra de tal maneira que os dados sejam distribuídos <strong>de modo uniforme</strong>.</p><p>Uma abordagem possível para isso é definir intervalos de acordo com alguma informação sobre um registro (por exemplo, usuários com nomes de A a D).</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/image-1.png" class="kg-image" alt="image-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/06/image-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/06/image-1.png 800w" sizes="(min-width: 720px) 720px" width="800" height="610" loading="lazy"></figure><p>Essa abordagem de fragmentação deve ser escolhida com muito cuidado, pois a carga nem sempre é igual com base em colunas arbitrárias. (por exemplo, mais pessoas têm nomes que começam com C em vez de Z). Um único fragmento que recebe mais solicitações do que outros é chamado de <strong><em>hot spot</em></strong> (ponto de acesso) e deve ser evitado. Depois de divididos, a nova fragmentação dos dados torna-se incrivelmente cara e pode causar um significativo tempo de indisponibilidade, como foi o infame caso das <a href="https://mashable.com/2010/10/05/foursquare-downtime-post-mortem/#qyp__Q9UDkqW">11 horas de indisponibilidade do Foursquare</a> (texto em inglês).</p><p>Para manter nosso exemplo simples, suponha que nosso <em>client</em> (a aplicação em Rails) saiba qual banco de dados usar para cada registro. Também vale ressaltar que existem muitas estratégias para o particionamento e esse é um exemplo simples para ilustrar o conceito.</p><p>No momento, já obtivemos bastante sucesso – podemos aumentar nosso tráfego de gravação <strong><em>N</em></strong> vezes, onde <strong><em>N</em></strong> é o número de fragmentos. Isso praticamente nos deixa quase sem limites – imagine o nível de granularidade que podemos ter com essa divisão.</p><h3 id="armadilha-1"><strong>Armadilha</strong></h3><p>Tudo na Engenharia de Software é mais ou menos escolhas e renúncias (<em>trade-offs</em> em inglês), e isso não é uma exceção. O particionamento não é uma tarefa simples e é melhor evitá-lo até que seja <a href="https://www.percona.com/blog/2009/08/06/why-you-dont-want-to-shard/">realmente necessário</a> (texto em inglês).</p><p>Agora, tornamos as consultas por chaves <strong>diferentes das chaves particionadas</strong> incrivelmente ineficientes (elas precisam passar por todos os fragmentos). As consultas de SQL <code>JOIN</code> são ainda piores e complexas, tornam-se praticamente inutilizáveis.</p><h3 id="decentralizado-x-distribu-do">Decentralizado x distribuído</h3><p>Antes de prosseguirmos, gostaria de fazer uma distinção entre esses dois termos.</p><p>Embora as palavras soem semelhantes e possam ser concluídas como significando o mesmo logicamente, suas diferenças têm um impacto tecnológico e político significativo.</p><p><em><strong>Descentralizado</strong></em> ainda é <em><strong>distribuído</strong></em> no sentido técnico, mas todo o sistema descentralizado não é de propriedade de um único ator. Nenhuma empresa pode possuir um sistema descentralizado. Caso contrário, ele deixaria de ser descentralizado.</p><p>Isso significa que a maioria dos sistemas que discutiremos hoje pode ser considerada como <em><strong>sistemas centralizados distribuídos</strong></em> – e é isso que eles foram projetados para ser.</p><p>Se você pensar a respeito, é mais difícil criar um sistema descentralizado porque é preciso lidar com a situação em que alguns dos participantes são mal-intencionados. Isso não ocorre com sistemas distribuídos normais, pois você sabe que é o proprietário de todos os nós.</p><p><em>Observação: essa definição tem sido bastante <a href="https://github.com/WebOfTrustInfo/rebooting-the-web-of-trust/issues/50#issuecomment-154995201">debatida</a> (texto em inglês) e pode ser confundida com outras (peer-to-peer, federado). </em><a href="https://ethereum.stackexchange.com/a/7829"><em>Em literatura mais antiga, também foi definida de maneira diferente</em></a><em> (texto em inglês). Independentemente disso, o que forneci como definição é o que considero ser o mais amplamente utilizado agora, especialmente após a popularização dos termos blockchain e criptomoedas.</em></p><h3 id="categorias-de-sistemas-distribu-dos">Categorias de sistemas distribuídos</h3><p>Agora vamos explorar algumas categorias de sistemas distribuídos e listar seus maiores usos conhecidos publicamente. Tenha em mente que a maioria dos números apresentados está desatualizada e, provavelmente, é significativamente maior no momento em que você está lendo isso.</p><h3 id="armazenamento-distribu-dos-de-dados">Armazenamento distribuídos de dados</h3><p>Os armazenamentos distribuídos de dados são mais amplamente utilizados e reconhecidos como bancos de dados distribuídos. A maioria dos bancos de dados distribuídos são <a href="https://en.wikipedia.org/wiki/NoSQL">NoSQL</a> (texto em inglês), ou seja, bancos de dados não relacionais, limitados à semântica chave-valor. Eles oferecem desempenho e escalabilidade incríveis, mas isso ocorre às custas da consistência ou disponibilidade.</p><blockquote><strong>Escala conhecida</strong> – <a href="http://cassandra.apache.org/">a Apple é conhecida por utilizar 75.000 nós do Apache Cassandra, armazenando mais de 10 petabytes de dados</a> (texto em inglês).</blockquote><p>Não podemos entrar em discussões sobre armazenamento distribuído de dados sem primeiro introduzir o <strong>Teorema CAP</strong>.</p><p><strong>Teorema <strong>CAP</strong></strong></p><p><a href="https://mwhittaker.github.io/blog/an_illustrated_proof_of_the_cap_theorem/">Comprovado pela primeira vez em 2002</a> (texto em inglês), o Teorema CAP (sigla em inglês para <em><strong>C</strong>onsistency</em>, <em><strong>A</strong>vailability</em> e <em><strong>P</strong>artition Tolerance</em>) estabelece que um sistema de armazenamento de dados distribuído não pode simultaneamente manter consistência, estar sempre disponível e ser tolerante a partições.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/01/CAP-VENN.png" class="kg-image" alt="1*hIUyhmHbihiiMRP7hWgBSw" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/01/CAP-VENN.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/01/CAP-VENN.png 800w" sizes="(min-width: 720px) 720px" width="800" height="600" loading="lazy"><figcaption>Escolha 2 entre 3 (mas não Consistência e Disponibilidade).</figcaption></figure><p>Algumas definições rápidas:</p><ul><li><strong>Consistência </strong>—<strong> </strong>o que você lê e escreve sequencialmente é o que é esperado (lembre-se da situação complicada com a replicação do banco de dados mencionada alguns parágrafos atrás?).</li><li><strong>Disponibilidade</strong> — o sistema como um todo não falha — todo nó não defeituoso sempre retorna uma resposta.</li><li><strong>Tolerância a partições</strong> — o sistema continua a funcionar e manter suas garantias de consistência/disponibilidade apesar das <a href="https://www.symantec.com/security_response/glossary/define.jsp?letter=n&amp;word=network-partition">partições na rede</a> (texto em inglês).</li></ul><p>Na realidade, a tolerância a partições deve ser uma premissa para qualquer armazenamento de dados distribuído. Conforme mencionado em vários lugares, <a href="https://codahale.com/you-cant-sacrifice-partition-tolerance/">como citado neste ótimo artigo</a> (texto em inglês), não é possível ter consistência e disponibilidade sem tolerância a partições.</p><p>Reflexão: se você tiver dois nós que aceitam informações e a conexão entre eles for interrompida, como ambos poderão estar disponíveis e fornecer consistência ao mesmo tempo? Eles não têm conhecimento do que o outro nó está fazendo, podendo assim ficar <em>off-line </em>(indisponíveis) ou operar com informações desatualizadas (inconsistentes).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-4.png" class="kg-image" alt="image-4" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-4.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-4.png 800w" sizes="(min-width: 720px) 720px" width="800" height="529" loading="lazy"><figcaption>O que fazemos?</figcaption></figure><p>No final, você precisa escolher se deseja que seu sistema seja fortemente consistente ou altamente disponível <strong><em>em caso de uma partição de rede</em></strong>.</p><p>A prática mostra que a maioria das aplicações valoriza mais a disponibilidade. Você nem sempre precisa necessariamente de uma consistência forte. Mesmo assim, essa compensação não é necessariamente feita porque você precisa da garantia de 100% de disponibilidade, mas sim porque a latência da rede pode ser um problema quando é necessário sincronizar máquinas para obter uma consistência forte. Esses e outros fatores fazem com que as aplicações normalmente optem por soluções que ofereçam alta disponibilidade.</p><p>Esses bancos de dados se contentam com o modelo de consistência mais fraco – <em><strong>consistência eventual</strong></em> (<em><a href="https://hackernoon.com/eventual-vs-strong-consistency-in-distributed-databases-282fdad37cf7">explicação de consistência forte versus consistência eventual</a> – texto em inglês</em>). Esse modelo garante que se nenhuma nova atualização for feita em um determinado item, <strong>eventualmente</strong> todos os acessos a esse item retornarão o último valor atualizado.</p><p>Esses sistemas fornecem propriedades <strong>BASE</strong> (em oposição ao ACID dos bancos de dados tradicionais):</p><ul><li><strong><strong>B</strong></strong>asically <strong><strong>A</strong></strong>vailable — basicamente disponível — o sistema sempre retorna uma resposta</li><li><strong><strong>S</strong></strong>oft state — estado suave — o sistema pode mudar com o tempo, mesmo durante períodos sem entrada (devido a eventual consistência)</li><li><strong><strong>E</strong></strong>ventual consistency — consistência eventual — na ausência de entrada, os dados se espalharão para todos os nós, mais cedo ou mais tarde — tornando-se assim consistentes</li></ul><p>Exemplos de tais bancos de dados distribuídos disponíveis — <a href="http://cassandra.apache.org/" rel="noopener">Cassandra</a>, <a href="http://basho.com/products/riak-kv/" rel="noopener">Riak</a>, <a href="http://www.project-voldemort.com/voldemort/" rel="noopener">Voldemort</a> (texto em inglês)</p><p>Claro, existem outros armazenamentos de dados que preferem consistência mais forte — <a href="https://hbase.apache.org/" rel="noopener">HBase</a>, <a href="https://www.couchbase.com/" rel="noopener">Couchbase</a>, <a href="https://redis.io/" rel="noopener">Redis,</a> <a href="https://zookeeper.apache.org/" rel="noopener">Zookeeper</a> (texto em inglês)</p><p>O teorema CAP é digno de vários artigos por si só – alguns sobre como você pode <a href="http://www.goland.org/blockchain_and_cap/">ajustar as propriedades CAP de um sistema dependendo de como o <em>client</em> se comporta</a> (texto em inglês) e outros sobre <a href="https://martin.kleppmann.com/2015/05/11/please-stop-calling-databases-cp-or-ap.html">como ele não é compreendido corretamente</a> (texto em inglês).</p><p><strong><strong>Cassandra</strong></strong></p><p>Cassandra, como mencionado acima, é um banco de dados No-SQL distribuído que prefere as propriedades do AP fora do CAP, estabelecendo-se com consistência eventual. Devo admitir que isso pode ser um pouco enganador, já que o Cassandra é altamente configurável — você também pode fazer com que ele forneça uma consistência forte em detrimento da disponibilidade, mas esse não é seu caso de uso comum.</p><p>Cassandra utiliza <a href="https://en.wikipedia.org/wiki/Consistent_hashing">hashing consistente</a> (texto em inglês) para determinar quais nós do seu cluster devem gerenciar os dados que você está passando. Você define um <strong>fator de replicação</strong>, que basicamente indica para quantos nós você deseja replicar seus dados.</p><p>Ao ler, você lerá apenas desses nós.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-15.png" class="kg-image" alt="image-15" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-15.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-15.png 800w" sizes="(min-width: 720px) 720px" width="800" height="666" loading="lazy"></figure><p>Cassandra é altamente escalável, proporcionando uma taxa de transferência de escrita absurdamente alta.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-6.png" class="kg-image" alt="image-6" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-6.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-6.png 800w" sizes="(min-width: 720px) 720px" width="800" height="677" loading="lazy"><figcaption>Diagrama possivelmente tendencioso, mostrando teste de desempenho de gravações por segundo.</figcaption></figure><p>Mesmo que esse diagrama possa ser tendencioso e pareça que compara Cassandra a bancos de dados configurados para fornecer consistência forte (caso contrário, não consigo ver por que o MongoDB diminuiria o desempenho quando atualizado de 4 para 8 nós), isso ainda deve mostrar o que é configurado corretamente até o cluster Cassandra é capaz.</p><p>Independentemente disso, no <em>trade-off</em> de sistemas distribuídos que permite escalabilidade horizontal e rendimento incrivelmente alto, o Cassandra não fornece alguns recursos fundamentais dos bancos de dados ACID – ou seja, transações.</p><h3 id="consenso"><strong><strong>Consens</strong>o</strong></h3><p>As transações de banco de dados são difíceis de implementar em sistemas distribuídos, pois exigem que cada nó concorde sobre a ação correta a ser tomada (abortar ou confirmar). Isso é conhecido como <strong>consenso</strong> e é um problema fundamental em sistemas distribuídos.</p><p>Alcançar o tipo de acordo necessário para o problema de "confirmação de transação" é simples se os processos participantes e a rede forem completamente confiáveis. No entanto, os sistemas reais estão sujeitos a uma série de falhas possíveis, como falhas de processos, particionamento de rede e mensagens perdidas, distorcidas ou duplicadas.</p><p>Isto levanta um problema: <a href="http://the-paper-trail.org/blog/a-brief-tour-of-flp-impossibility/">provou-se ser impossível</a> (texto em inglês) garantir que um consenso correto seja alcançado dentro de um prazo limitado em uma rede não confiável.</p><p>Na prática, porém, existem algoritmos que chegam rapidamente a um consenso em uma rede não confiável. Na verdade, Cassandra fornece <a href="https://www.beyondthelines.net/databases/cassandra-lightweight-transactions/">transações leves</a> por meio do uso do algoritmo <a href="https://en.wikipedia.org/wiki/Paxos_(computer_science)">Paxos</a> para consenso distribuído.</p><h2 id="computa-o-distribu-da"><strong>Computação distribuída</strong></h2><p>A computação distribuída é a chave para o fluxo de processamento de Big Data que temos visto nos últimos anos. É a técnica de dividir uma tarefa enorme (por exemplo, agregar 100 bilhões de registos), que nenhum computador é capaz de executar praticamente por si só, em muitas tarefas mais pequenas, cada uma das quais pode caber numa única máquina comum. Você divide sua enorme tarefa em muitas tarefas menores, executa-as em muitas máquinas em paralelo, agrega os dados adequadamente e resolve seu problema inicial. Essa abordagem novamente permite escalar horizontalmente – quando você tem uma tarefa maior, basta incluir mais nós no cálculo.</p><blockquote><a href="https://en.wikipedia.org/wiki/Folding@home" rel="noopener">Folding@Home</a> &nbsp;<a href="https://www.webcitation.org/6CWRdkzP0?url=http://fah-web.stanford.edu/cgi-bin/main.py?qtype=osstats2">160 mil máquinas ativas em 2012</a> (texto em inglês)</blockquote><p>Um dos primeiros inovadores neste espaço foi o Google, que devido à necessidade de suas grandes quantidades de dados teve que inventar um novo paradigma para computação distribuída – MapReduce. Eles publicaram um <a href="http://static.googleusercontent.com/media/research.google.com/en/us/archive/mapreduce-osdi04.pdf">artigo sobre isso em 2004</a> (texto em inglês) e a comunidade de código aberto mais tarde criou o <a href="https://hadoop.apache.org/">Apache Hadoop</a> (texto em inglês) baseado nele.</p><p><strong><strong>MapReduce</strong></strong></p><p>MapReduce pode ser definido simplesmente como duas etapas – <a href="https://en.wikipedia.org/wiki/Map_(higher-order_function)">mapear os dados</a> (Map) e <a href="https://en.wikipedia.org/wiki/Fold_(higher-order_function)">reduzi-los</a> a algo significativo (Reduce).</p><p>Vamos ver um exemplo novamente:</p><p>Digamos que somos a <a href="https://medium.com/">Medium</a> (Plataforma de publicação de artigos) e armazenamos nossas enormes informações em um banco de dados secundário distribuído para fins de armazenamento. Queremos buscar dados que representem o número de palmas enviadas todos os dias durante o mês de abril de 2017 (um ano antes da edição original deste artigo).</p><p>Este exemplo é o mais curto, claro e simples possível, mas imagine que estamos trabalhando com muitos dados (por exemplo, analisando bilhões de aplausos). Obviamente, não armazenaremos todas essas informações em uma máquina e não analisaremos tudo isso em apenas uma máquina. Também não consultaremos o banco de dados de produção, mas algum banco de dados de "armazém" construído especificamente para trabalhos <em>off-line</em> de baixa prioridade.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/1_eOJWeVtD769sSOCynpFWAA.png" class="kg-image" alt="1_eOJWeVtD769sSOCynpFWAA" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/06/1_eOJWeVtD769sSOCynpFWAA.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/06/1_eOJWeVtD769sSOCynpFWAA.png 800w" sizes="(min-width: 720px) 720px" width="800" height="421" loading="lazy"></figure><p>Cada trabalho <em>Map</em> é um nó separado que transforma o máximo de dados possível. Cada trabalho percorre todos os dados em um determinado nó de armazenamento e os mapeia para uma tupla simples da data e do número um. Em seguida, são realizadas três etapas intermediárias (<em>das quais ninguém fala</em>) – <em>Shuffle</em>, <em>Sort</em> e <em>Partition</em>. Elas basicamente organizam ainda mais os dados e os excluem para o trabalho de redução apropriado. Como estamos lidando com Big Data, separamos cada trabalho de <em>Reduce</em> para funcionar apenas em uma única data.</p><p>Esse é um bom paradigma e surpreendentemente permite que você faça muitas coisas com ele — você pode encadear vários trabalhos MapReduce, por exemplo.</p><p><strong>Melhores técnicas</strong></p><p>O MapReduce é um tanto legado nos dias de hoje e traz alguns problemas consigo. Por trabalhar em lotes (<em>jobs</em>), surge um problema onde, se o seu <em>job </em>falhar, você precisa reiniciar tudo do zero. Um <em>job</em> de 2 horas falhando pode realmente retardar todo o seu <em>pipeline </em>de processamento de dados e você definitivamente não quer isso, especialmente nas horas de pico.</p><p>Outra questão é o tempo que você espera até receber os resultados. Em sistemas analíticos em tempo real (onde todos têm <em>big data</em> e, portanto, usam computação distribuída), é importante que os seus dados mais recentes estejam o mais novos possível e certamente não sejam de algumas horas atrás.</p><p>Como resultado, <a href="https://www.talend.com/blog/2017/08/28/lambda-kappa-real-time-big-data-architectures/">surgiram outras arquiteturas</a> (texto em inglês) que abordam esses problemas. Nomeadamente, a <a href="https://en.wikipedia.org/wiki/Lambda_architecture">arquitetura Lambda</a> (uma mistura de processamento em lote e processamento em fluxo – texto em inglês) e a <a href="http://milinda.pathirage.org/kappa-architecture.com/">arquitetura Kappa</a> (apenas processamento em fluxo – texto em inglês). Esses avanços no campo trouxeram novas ferramentas que os possibilitam — <a href="https://kafka.apache.org/documentation/streams/">Kafka Streams</a>, <a href="https://spark.apache.org/">Apache Spark</a>, <a href="http://storm.apache.org/">Apache Storm</a>, <a href="http://samza.apache.org/">Apache Samza</a>.</p><h3 id="sistemas-de-arquivos-distribu-dos"><strong>Sistemas de arquivos distribuídos</strong></h3><p>Os sistemas de arquivos distribuídos podem ser considerados como armazenamentos de dados distribuídos. São a mesma coisa como conceito — armazenar e acessar uma grande quantidade de dados em um <em>cluster </em>de máquinas, todas aparecendo como uma só. Eles geralmente andam de mãos dadas com a Computação Distribuída.</p><blockquote>Escala conhecida – <a href="https://www.slideshare.net/Hadoop_Summit/what-it-takes-to-run-hadoop-at-scale-yahoo-perspectives">O Yahoo é conhecido por executar o HDFS em mais de 42.000 nós para armazenamento de 600 Petabytes de dados, lá em 2011</a></blockquote><p>A diferença é que os sistemas de arquivos distribuídos permitem que os arquivos sejam acessados usando as mesmas interfaces e semânticas que os arquivos locais, e não por meio de uma API personalizada como a Cassandra Query Language (<a href="https://docs.datastax.com/en/cql/3.3/cql/cqlIntro.html">CQL</a>).</p><p><strong><strong>HDFS</strong></strong></p><p>O <em>Hadoop Distributed File System</em> (HDFS) é o sistema de arquivos distribuídos usado para computação distribuída através do framework Hadoop. Com ampla adoção, é utilizado para armazenar e replicar grandes arquivos (de GB ou TB em tamanho) em muitas máquinas.</p><p>Sua arquitetura consiste principalmente em <strong><em>NameNodes</em></strong> e <strong><em>DataNodes</em></strong>. Os NameNodes são responsáveis por manter o <em>metadata</em> sobre o <em>cluster</em>, como qual nó contém quais blocos de arquivos. Eles atuam como coordenadores da rede, determinando onde é melhor armazenar e replicar arquivos, além de monitorar a saúde do sistema. Os DataNodes simplesmente armazenam arquivos e executam comandos como replicar um arquivo, escrever um novo entre outros.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-16.png" class="kg-image" alt="image-16" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-16.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-16.png 800w" sizes="(min-width: 720px) 720px" width="800" height="351" loading="lazy"></figure><p>Não surpreendentemente, o HDFS é melhor utilizado com o Hadoop para computação, pois fornece consciência de dados para os <em>jobs </em>de computação. Esses <em>jobs</em> são então executados nos nós que armazenam os dados. Isso aproveita a localidade dos dados — otimizando as computações e reduzindo a quantidade de tráfego na rede.</p><h4 id="ipfs"><strong><strong>IPFS</strong></strong></h4><p>O <a href="https://ipfs.io/"><em>Interplanetary File System</em></a> (IPFS – texto em inglês), sistema de arquivos interplanetário, é um novo e empolgante protocolo de rede <em>peer-to-peer</em> para um sistema de arquivos distribuídos. Aproveitando a tecnologia <a href="https://en.wikipedia.org/wiki/Blockchain">Blockchain</a> (texto em inglês), ele possui uma arquitetura completamente descentralizada, sem um único proprietário ou ponto de falha.</p><p>O IPFS oferece um sistema de nomes (semelhante ao DNS) chamado IPNS e permite que os usuários acessem facilmente informações. Ele armazena arquivos por meio de versionamento histórico, semelhante ao que o <a href="https://en.wikipedia.org/wiki/Git">Git</a> (texto em inglês) faz. Isso permite o acesso a todos os estados anteriores de um arquivo.</p><p>Ainda está passando por um desenvolvimento intenso (versão 0.4 no momento desta edição), mas já viu projetos interessados em construir sobre ele (<a href="https://filecoin.io/">FileCoin</a>, texto em inglês).</p><h3 id="messageria-distribu-da"><strong><strong>Messa</strong>geria distribuída</strong></h3><p>Sistemas de mensageria fornecem um local central para armazenamento e propagação de mensagens/eventos dentro do seu sistema geral. Eles permitem que você desacople a lógica de sua aplicação de falar diretamente com seus outros sistemas.</p><blockquote>Escala conhecida – <a href="https://engineering.linkedin.com/apache-kafka/how-we_re-improving-and-advancing-kafka-linkedin">o cluster Kafka do LinkedIn processou 1 trilhão de mensagens por dia, com picos de 4,5 milhões de mensagens por segundo</a> (texto em inglês).</blockquote><p>Simplificando, uma plataforma de mensagens funciona da seguinte maneira: </p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-21.png" class="kg-image" alt="image-21" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-21.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-21.png 800w" sizes="(min-width: 720px) 720px" width="800" height="1144" loading="lazy"></figure><p>Uma mensagem é transmitida a partir da aplicação que a potencialmente cria (chamada de <strong>produtor</strong>), entra na plataforma e é lida por potencialmente múltiplas aplicações que têm interesse nela (chamadas de <strong>consumidor</strong>es).</p><p>Se você precisa salvar um determinado evento em vários lugares (por exemplo, criação de usuário no banco de dados, <em>data warehouse</em>, serviço de envio de e-mails e qualquer outra coisa que você possa imaginar), uma plataforma de mensageria é a maneira mais limpa de disseminar essa mensagem.</p><p>Os consumidores podem tanto extrair informações dos <em>brokers</em> (modelo <em>pull</em>) quanto ter os <em>brokers </em>enviando informações diretamente para os consumidores (modelo <em>push</em>).</p><p>Existem algumas plataformas de mensagens populares e de alta qualidade:</p><p><a href="https://www.rabbitmq.com/">RabbitMQ</a> (texto em inglês) — <em>broker </em>de mensagens que permite um controle mais detalhado das trajetórias das mensagens através de regras de roteamento e outras configurações facilmente ajustáveis. Pode ser chamado de <em>broker </em>inteligente, pois possui muita lógica embutida e acompanha rigorosamente as mensagens que passam por ele. Oferece configurações tanto para <strong>AP</strong> quanto para <strong>CP</strong> do teorema <strong>CAP</strong>. Utiliza um modelo <em>push </em>para notificar os consumidores.</p><p><a href="https://kafka.apache.org/">Kafka</a> (texto em inglês) — <em>broker </em>de mensagens (e uma plataforma completa) que é um pouco mais de baixo nível, pois não acompanha quais mensagens foram lidas e não permite uma lógica de roteamento complexa. Isso ajuda a alcançar um desempenho incrível. Na minha opinião, esse é o maior prospecto nesse espaço, com desenvolvimento ativo da comunidade de código aberto e suporte da <a href="https://www.confluent.io/blog">equipe Confluent</a> (texto em inglês). O Kafka, indiscutivelmente, é o mais amplamente utilizado pelas principais empresas de tecnologia. <a href="https://hackernoon.com/thorough-introduction-to-apache-kafka-6fbf2989bbc1">Escrevi uma introdução detalhada sobre isso, onde explico em detalhes todas as suas vantagens</a> (texto em inglês).</p><p><a href="http://activemq.apache.org/">Apache ActiveMQ</a> (texto em inglês) — o mais antigo do grupo, datando de 2004. Usa a API JMS, o que significa que é voltado para aplicativos Java EE. Foi reescrito como <a href="https://activemq.apache.org/artemis/">ActiveMQ Artemis</a> (texto em inglês), que oferece um desempenho excepcional comparável ao Kafka.</p><p><a href="https://aws.amazon.com/sqs/">Amazon SQS</a> (texto em inglês) — um serviço de mensageria fornecido pela AWS. Permite que você integre rapidamente com aplicações existentes e elimina a necessidade de lidar com sua própria infraestrutura, o que pode ser um grande benefício, já que sistemas como o Kafka são notoriamente difíceis de configurar. A Amazon também oferece dois serviços semelhantes — <a href="https://aws.amazon.com/sns/">SNS</a> (texto em inglês) e <a href="https://aws.amazon.com/amazon-mq/">MQ</a> (texto em inglês), este último é basicamente o ActiveMQ, mas gerenciado pela Amazon.</p><h3 id="aplica-es-distribu-das"><strong>Aplicações distribuídas</strong></h3><p>Se você agrupar 5 servidores de Rails atrás de um único balanceador de carga, todos conectados a um banco de dados, poderia chamar isso de aplicação distribuída? Lembre-se da minha definição lá em cima:</p><blockquote>Um sistema distribuído é um grupo de computadores trabalhando juntos para parecer como se fosse um único computador para o usuário final. Essas máquinas têm um estado compartilhado, operam de maneira concorrente e podem falhar independentemente sem afetar o tempo de atividade do sistema como um todo.</blockquote><p>Se você considerar o banco de dados como um estado compartilhado, poderia argumentar que isso pode ser classificado como um sistema distribuído — mas você estaria errado, pois você ignorou a parte "<em>trabalhando juntos</em>" da definição.</p><p>Um sistema é distribuído apenas se os nós se comunicarem entre si para coordenar suas ações. </p><p>Portanto, algo como uma aplicação que executa seu código de <em>back-end</em> em uma <a href="https://en.wikipedia.org/wiki/Peer-to-peer">rede peer-to-peer</a> (texto em inglês) pode ser melhor classificado como uma aplicação distribuída. Independentemente disso, toda essa classificação desnecessária não serve para nada além de ilustrar como somos detalhistas sobre agrupar coisas juntas. </p><blockquote>Escala conhecida – Por exemplo, o enxame BitTorrent de 193.000 nós para um episódio de Game of Thrones, em abril de 2014.</blockquote><h4 id="m-quina-virtual-com-erlang"><strong>Máquina virtual com <strong>Erlang</strong></strong></h4><p>Erlang é uma linguagem funcional que possui ótimas semânticas para concorrência, distribuição e tolerância a falhas. A própria máquina virtual com Erlang lida com a distribuição de uma aplicação do Erlang.</p><p>Seu modelo funciona tendo muitos <a href="https://en.wikipedia.org/wiki/Light-weight_process">processos leves</a> (texto em inglês) e <strong>isolados</strong>, todos com a capacidade de se comunicar entre si por meio de um sistema integrado de passagem de mensagens. Isso é chamado de <a href="http://berb.github.io/diploma-thesis/original/054_actors.html"><strong>Modelo de Ator</strong></a> (texto em inglês) e as bibliotecas Erlang OTP podem ser consideradas como um <em>framework </em>de atores distribuídos (similar ao <a href="https://akka.io/">Akka</a> para a JVM).</p><p>O modelo é o que ajuda a alcançar uma ótima concorrência de maneira bastante simples — os processos são distribuídos pelos núcleos disponíveis do sistema que os executa. Uma vez que isso é indistinguível de um ambiente de rede (exceto pela capacidade de descartar mensagens), a máquina virtual do Erlang pode se conectar a outras máquinas virtuais do Erlang em execução no mesmo <em>data center</em> ou até mesmo em outro continente. Esse conjunto de máquinas virtuais executa uma única aplicação e lida com falhas de máquina por meio de <em>takeover </em>(outro nó é escalonado para executar).</p><p>De fato, a camada distribuída da linguagem foi adicionada para fornecer tolerância a falhas. Software em execução em uma única máquina está sempre em risco de ter essa única máquina falhando e tirando sua aplicação do ar. O software em execução em muitos nós permite um manuseio mais fácil de falhas de hardware, desde que a aplicação tenha sido construída com isso em mente.</p><h4 id="bittorrent"><strong><strong>BitTorrent</strong></strong></h4><p>O BitTorrent é um dos protocolos mais amplamente utilizados para transferir arquivos grandes pela web por meio de <em>torrents</em>. A ideia principal é facilitar a transferência de arquivos entre diferentes pares na rede sem precisar passar por um servidor central.</p><p>Usando um <em>client</em> do BitTorrent, você se conecta a vários computadores ao redor do mundo para baixar um arquivo. Quando você abre um arquivo .torrent, você se conecta a um chamado <a href="https://en.wikipedia.org/wiki/BitTorrent_tracker"><strong><em>tracker</em></strong></a><em> (rastreador)</em>, que é uma máquina que age como coordenador. Ele ajuda na descoberta de pares, mostrando os nós na rede que têm o arquivo que você deseja.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-22.png" class="kg-image" alt="image-22" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-22.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-22.png 800w" sizes="(min-width: 720px) 720px" width="800" height="561" loading="lazy"><figcaption>Exemplo de uma rede</figcaption></figure><p>Você tem as noções de dois tipos de usuário, um <strong><em>leecher</em></strong> e um <strong><em>seeder</em></strong>. Um <em>leecher </em>é o usuário que está baixando um arquivo e um <em>seeder </em>é o usuário que está enviando esse arquivo.</p><p>O interessante sobre redes <em>peer-to-peer</em> é que você, como usuário comum, tem a capacidade de se juntar e contribuir para a rede. </p><p>O BitTorrent e seus precursores (<a href="https://en.wikipedia.org/wiki/Gnutella">Gnutella</a>, <a href="https://computer.howstuffworks.com/napster2.htm">Napster</a> – textos em inglês) permitem que você hospede arquivos voluntariamente e os envie para outros usuários que os desejam. A razão pela qual o BitTorrent é tão popular é que ele foi o primeiro de seu tipo a fornecer incentivos para contribuir com a rede. O problema do <strong><em>Freeriding</em></strong>, onde um usuário apenas baixava arquivos sem contribuir com <em>uploads</em>, era um desafio para os protocolos de compartilhamento de arquivos anteriores.</p><p>O BitTorrent resolveu o freeriding até certo ponto, fazendo com que os <em>seeders </em>enviassem mais para aqueles que fornecem as melhores taxas de download. Ele funciona incentivando você a fazer upload enquanto baixa um arquivo. Infelizmente, depois que você termina, nada o obriga a permanecer ativo na rede. Isso causa uma falta de seeders na rede que têm o arquivo completo e, como o protocolo depende fortemente de tais usuários, soluções como <a href="https://www.reddit.com/r/torrents/comments/2413bo/how_and_why_do_private_trackers_exist/ch2o1bo/">rastreadores privados</a> (texto em inglês) surgiram. Rastreadores privados exigem que você seja membro de uma comunidade (geralmente apenas por convite) para participar da rede distribuída.</p><p>Após avanços na área, <em>torrents </em>sem rastreadores foram inventados. Essa foi uma atualização para o protocolo BitTorrent que não dependia de rastreadores centralizados para reunir metadados e encontrar pares, mas usava novos algoritmos. Um exemplo disso é o <a href="https://en.wikipedia.org/wiki/Kademlia">Kademlia</a> (<a href="https://en.wikipedia.org/wiki/Mainline_DHT">Mainline DHT</a>) (textos em inglês), uma tabela de <em>hash </em>distribuída (DHT) que permite encontrar pares através de outros pares. Na prática, cada usuário desempenha as funções de um rastreador.</p><h3 id="registros-distribu-dos">Registros<strong> d<strong>istribuí</strong>dos</strong></h3><p>Um registro distribuído pode ser pensado como um banco de dados imutável, de apenas anexação, que é replicado, sincronizado e compartilhado entre todos os nós na rede distribuída.</p><blockquote>Escala conhecida – <a href="https://etherscan.io/chart/tx">a Rede Ethereum teve um pico de 1,3 milhão de transações por dia em 4 de janeiro de 2018</a></blockquote><p>Eles aproveitam o padrão de <a href="https://martinfowler.com/eaaDev/EventSourcing.html">Event Sourcing</a> (texto em inglês), permitindo que você reconstrua o estado do registro em qualquer momento de sua história.</p><h4 id="blockchain"><strong><strong>Blockchain</strong></strong></h4><p>A tecnologia Blockchain é atualmente usada para os registros distribuídos e, na verdade, marcou seu início. Essa mais recente e revolucionária inovação no espaço distribuído possibilitou a criação do primeiro protocolo de pagamento verdadeiramente distribuído – o Bitcoin.</p><p>Blockchain é um registro distribuído que carrega uma lista ordenada de todas as transações que já ocorreram em sua rede. As transações são agrupadas e armazenadas em blocos. O blockchain inteiro é essencialmente uma <a href="https://www.andrew.cmu.edu/course/15-121/lectures/Linked%20Lists/linked%20lists.html">lista encadeada</a> (texto em inglês) de blocos (daí o nome). Esses blocos são computacionalmente caros de serem criados e estão intimamente ligados entre si por meio de criptografia.</p><p>Dito de maneira simples, cada bloco contém um <em>hash </em>especial (que começa com uma quantidade X de zeros) do conteúdo do bloco atual (na forma de uma Árvore de Merkle) mais o <em>hash </em>do bloco anterior. Esse <em>hash </em>requer muita potência de CPU para ser produzido porque a única maneira de obtê-lo é através de força bruta.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-26.png" class="kg-image" alt="image-26" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/05/image-26.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/05/image-26.png 800w" sizes="(min-width: 720px) 720px" width="800" height="545" loading="lazy"><figcaption>Blockchain simplificado</figcaption></figure><p>Os <em><strong>miners</strong> </em>(mineradores) são os nós que tentam calcular o <em>hash </em>(via força bruta). Os <em>miners </em>competem entre si para ver quem consegue encontrar uma string aleatória (chamada de <strong>nonce</strong>) que, quando combinada com o conteúdo, produz o <em>hash </em>mencionado anteriormente. Uma vez que alguém encontre o nonce correto, ele o transmite para toda a rede. Essa string é então verificada por cada nó individualmente e aceita em sua cadeia.</p><p>Isso se traduz em um sistema onde é absurdamente caro modificar o blockchain e absurdamente fácil verificar se ele não foi adulterado.</p><p>É caro alterar o conteúdo de um bloco porque isso produziria um <em>hash </em>diferente. Lembre-se de que o <em>hash </em>de cada bloco subsequente depende dele. Se você mudasse uma transação no primeiro bloco da imagem acima, você mudaria a Raiz de Merkle. Isso, por sua vez, mudaria o <em>hash </em>do bloco (provavelmente sem os zeros iniciais necessários) — isso mudaria o <em>hash </em>do bloco nº 2 e assim por diante. Isso significa que você precisaria forçar um novo nonce para cada bloco após aquele que você acabou de modificar.</p><p>A rede sempre confia e replica a cadeia válida mais longa. Para trapacear o sistema e <strong>eventualmente</strong> produzir uma cadeia mais longa, você precisaria de mais de 50% do poder total de processamento da CPU usado por todos os nós.</p><p>O blockchain pode ser pensado como um mecanismo distribuído para o <em><strong>consenso emergente</strong></em>. O consenso não é alcançado explicitamente — não há eleição ou momento fixo em que o consenso ocorre. Em vez disso, o consenso é um produto <strong>emergente</strong> da interação assíncrona de milhares de nós independentes, todos seguindo regras de protocolo.</p><p>Essa inovação sem precedentes recentemente se tornou um boom no espaço tecnológico, com pessoas prevendo que marcará a criação da <a href="https://medium.com/@matteozago/why-the-web-3-0-matters-and-you-should-know-about-it-a5851d63c949">Web 3.0</a> (texto em inglês). É definitivamente o espaço mais emocionante no mundo da engenharia de software no momento, repleto de problemas extremamente desafiadores e interessantes esperando para serem resolvidos.</p><p><strong><strong>Bitcoin</strong></strong></p><p>O que os protocolos de pagamento distribuídos anteriores não tinham era uma maneira de prevenir de maneira prática o <a href="https://en.wikipedia.org/wiki/Double-spending">problema de gasto duplo</a> (texto em inglês) em tempo real e de maneira distribuída. Pesquisas produziram propostas interessantes[1], mas o Bitcoin foi o primeiro a implementar uma solução prática com vantagens claras sobre os outros. </p><p>O problema de gasto duplo afirma que um ator (por exemplo, Bob) não pode gastar seu único recurso em dois lugares. Se Bob tem $1, ele não deveria poder entregá-lo tanto para Alice quanto para Zack — é apenas um recurso, não pode ser duplicado. Acontece que é realmente difícil alcançar verdadeiramente essa garantia em um sistema distribuído. Existem <a href="https://arxiv.org/abs/0802.0832v1">algumas abordagens de mitigação interessantes</a> (texto em inglês) anteriores ao blockchain, mas elas não resolvem completamente o problema de maneira prática. </p><p>O problema de gasto duplo é facilmente resolvido pelo Bitcoin, pois apenas um bloco é adicionado à cadeia de cada vez. O gasto duplo é impossível dentro de um único bloco, portanto, mesmo que dois blocos sejam criados ao mesmo tempo — apenas um virá a fazer parte da cadeia mais longa eventualmente.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/1_Q7OSbezEhFEUXjhQ4mrVDg.jpeg" class="kg-image" alt="1_Q7OSbezEhFEUXjhQ4mrVDg" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/06/1_Q7OSbezEhFEUXjhQ4mrVDg.jpeg 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/06/1_Q7OSbezEhFEUXjhQ4mrVDg.jpeg 800w" sizes="(min-width: 720px) 720px" width="800" height="600" loading="lazy"></figure><p>O Bitcoin depende da dificuldade de acumular poder de processamento da CPU.</p><p>Enquanto em um sistema de votação um atacante só precisa adicionar nós à rede (o que é fácil, já que o acesso gratuito à rede é uma meta de projeto), em um esquema baseado em poder de CPU, um atacante enfrenta uma limitação física: obter acesso a hardware cada vez mais poderoso.</p><p>Essa também é a razão pela qual grupos maliciosos de nós precisam controlar mais de 50% do poder computacional da rede para realmente realizar qualquer ataque bem-sucedido. Menos do que isso, e o restante da rede criará um blockchain mais longo mais rapidamente.</p><h4 id="ethereum"><strong><strong>Ethereum</strong></strong></h4><p>Ethereum pode ser considerado como uma plataforma de software baseada em blockchain programável. Ele tem sua própria criptomoeda (Ether), que alimenta a implementação de <strong><em>contratos inteligentes</em></strong> em seu blockchain. </p><p>Contratos inteligentes são um pedaço de código armazenado como uma única transação no blockchain do Ethereum. Para executar o código, tudo o que você precisa fazer é emitir uma transação com um contrato inteligente como seu destino. Isso, por sua vez, faz com que os nós mineradores executem o código e quaisquer mudanças que ele incorra. O código é executado dentro da Máquina Virtual Ethereum.</p><p><strong><em>Solidity</em></strong>, a linguagem de programação nativa do Ethereum, é o que é usado para escrever contratos inteligentes. É uma linguagem de programação completa de Turing que interage diretamente com o blockchain do Ethereum, permitindo que você consulte o estado, como saldos ou outros resultados de contratos inteligentes. Para evitar loops infinitos, executar o código requer uma certa quantidade de Ether.</p><p>Como o blockchain pode ser interpretado como uma série de <strong><em>mudanças de estado</em></strong>, muitas aplicações distribuídas (<a href="https://medium.com/the-mission/2018-the-year-of-dapps-dbe108860bcb">DApps</a>; texto em inglês) foram construídas em cima do Ethereum e plataformas similares.</p><h3 id="outros-usos-de-registros-distribu-dos">Outros usos de registros distribuídos</h3><p><em><strong><a href="https://en.wikipedia.org/wiki/Proof_of_Existence">Prova de Existência</a></strong></em> (texto em inglês) — um serviço para armazenar de maneira anônima e segura a prova de que um determinado documento digital existia em algum momento no tempo. Útil para garantir a integridade do documento, propriedade e registro de data e hora.</p><p><a href="https://en.wikipedia.org/wiki/Decentralized_autonomous_organization"><strong><em>Organizações autônomas descentralizadas</em></strong></a> (DAO; texto em inglês) — organizações que utilizam blockchain como meio de alcançar consenso sobre as proposições de melhoria da organização. Exemplos são o <a href="https://www.dash.org/governance/">sistema de governança da Dash</a> e o <a href="https://smartcash.readthedocs.io/en/latest/">projeto SmartCash</a> (textos em inglês).</p><p><em><strong>Autenticação descentralizada</strong></em> — armazene sua identidade no blockchain, permitindo que você use <a href="https://en.wikipedia.org/wiki/Single_sign-on">logins únicos</a> em todos os lugares (<em>single sign-on</em>; SSO). Exemplos são <a href="https://sovrin.org/">Sovrin</a> e <a href="https://www.civic.com/products/secure-identity-platform">Civic</a> (textos em inglês).</p><p><em>Há muitos, muitos outros. A tecnologia de registro distribuído realmente abriu possibilidades infinitas. Alguns, provavelmente, estão sendo inventados enquanto falamos!</em></p><p><strong>Resumo</strong></p><p>No curto espaço deste artigo, conseguimos definir o que é um sistema distribuído, por que você usaria um e passamos brevemente por cada categoria. Algumas coisas importantes para lembrar são:</p><ul><li>Sistemas distribuídos são complexos </li><li>São escolhidos pela necessidade de escala e preço </li><li>São mais difíceis de trabalhar</li><li>Teorema CAP — escolha entre Consistência e Disponibilidade</li><li>Eles têm 6 categorias — armazenamento de dados, computação, sistemas de arquivos, sistemas de mensagens, registros, aplicações</li></ul><p>Para ser sincero, mal arranhamos a superfície dos sistemas distribuídos. Não tive a chance de abordar minuciosamente e explicar problemas fundamentais como <a href="https://www.cs.rutgers.edu/~pxk/417/notes/content/consensus.html">consenso</a>, <a href="http://www.cloudbus.org/papers/DataReplicationInDSChapter2006.pdf">estratégias de replicação</a>, <a href="https://swizec.com/blog/week-7-time-clocks-and-ordering-of-events-in-a-distributed-system/swizec/6444">ordenação de eventos e tempo</a>, <a href="http://blog.empathybox.com/post/19574936361/getting-real-about-distributed-system-reliability">tolerância a falhas</a>, <a href="https://www.distributed-systems.net/my-data/papers/2007.osr.pdf">transmissão de mensagens pela rede</a> e <a href="http://the-paper-trail.org/blog/distributed-systems-theory-for-the-distributed-systems-engineer/">outros</a> (textos em inglês).</p><h2 id="aten-o">Atenção</h2><p>Deixe-me compartilhar com você um aviso final:</p><p>Você deve evitar os sistemas distribuídos o máximo possível. A sobrecarga de complexidade que eles trazem consigo não vale o esforço se você puder evitar o problema resolvendo-o de uma maneira diferente ou por meio de alguma outra solução criativa.</p><p><em><em><strong><strong>[1]</strong></strong></em></em><br><a href="https://ieeexplore.ieee.org/document/4268195/">Combate ao duplo gasto usando sistemas P2P cooperativos</a> (texto em inglês), 25 a 27 de junho de 2007 — uma solução proposta na qual cada 'moeda' pode expirar e é atribuído um testemunho (validador) a ela ao ser gasta.</p><p><a href="http://web.archive.org/web/20060329122942/http://unenumerated.blogspot.com/2005/12/bit-gold.html">Bitgold</a> (texto em inglês), dezembro de 2005 — uma visão geral de alto nível de um protocolo extremamente semelhante ao do Bitcoin. Diz-se que ele é o precursor do Bitcoin.</p><p><strong>Leituras adicionais sobre sistemas distribuídos<strong>:</strong></strong></p><p><a href="https://dataintensive.net/">Designing Data-Intensive Applications, Martin Kleppmann</a> — um ótimo livro que aborda tudo sobre sistemas distribuídos e muito mais (em inglês).</p><p><a href="https://www.coursera.org/specializations/cloud-computing">Especialização em computação em nuvem, Universidade de Illinois, Coursera</a> — uma série de cursos (6) que aborda conceitos de sistemas distribuídos e suas aplicações.</p><p><a href="https://aphyr.com/tags/Jepsen">Jepsen</a> — blog que explica muitas tecnologias distribuídas (ElasticSearch, Redis, MongoDB etc).</p><p>Obrigado por dedicar seu tempo para ler este longo artigo (mais de 6.700 palavras)!</p><p>Se, por acaso, você achou este artigo informativo ou considerou que ele proporcionou valor a você, por favor, considere compartilhá-lo com um amigo que possa se beneficiar de uma introdução a esse maravilhoso campo de estudo.</p><h3 id="sobre-stanislav-kozlovski">Sobre Stanislav Kozlovski</h3><p>O autor, atualmente, trabalha na <a href="http://confluent.io/">Confluent</a>. Confluent é uma empresa de Big Data fundada pelos próprios criadores do <a href="https://hackernoon.com/thorough-introduction-to-apache-kafka-6fbf2989bbc1">Apache Kafka</a>! Ele se diz imensamente grato pela oportunidade que lhe deram – atualmente, ele trabalha no próprio Kafka, o que considera incrível! Na Confluent, eles ajudam a moldar todo o ecossistema Kafka de código aberto, incluindo uma nova oferta gerenciada de nuvem Kafka como serviço.</p><p>A Confluent contrata para vários cargos (especialmente SRE/Engenheiros de Software) na Europa e nos EUA! Se você estiver interessado em trabalhar no próprio Kafka, em busca de novas oportunidades ou simplesmente curioso – envie para o autor uma mensagem no <a href="https://twitter.com/StanKozlovski">Twitter</a> e ele se oferece a compartilhar todas as grandes vantagens de se trabalhar por lá.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Como criar uma blockchain do zero com Go ]]>
                </title>
                <description>
                    <![CDATA[ Introdução Com a Web 3.0 e a blockchain se tornando mais comuns a cada dia, você sabe o que é blockchain? Você conhece suas vantagens técnicas e seus casos de uso? O objetivo deste tutorial é introduzir a tecnologia de blockchain a partir de uma perspectiva técnica, construindo uma a ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-criar-uma-blockchain-do-zero-com-go/</link>
                <guid isPermaLink="false">63ec8bb558018c06027beeb0</guid>
                
                    <category>
                        <![CDATA[ Blockchain ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Elizabete Nakamura ]]>
                </dc:creator>
                <pubDate>Wed, 24 May 2023 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/blockchain-bar.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/build-a-blockchain-in-golang-from-scratch/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Build a Blockchain from Scratch with Go</a>
      </p><h2 id="introdu-o"><strong>Introdução</strong></h2><p>Com a Web 3.0 e a <em>blockchain</em> se tornando mais comuns a cada dia, você sabe o que é <em>blockchain</em>? Você conhece suas vantagens técnicas e seus casos de uso?</p><p><strong>O objetivo deste tutorial é introduzir a tecnologia de <em>blockchain</em> a partir de uma perspectiva técnica, construindo uma a partir do zero.</strong></p><p>Esqueça tudo o que você já ouviu sobre <em>blockchain</em> nas redes sociais. Agora, você construirá um sistema de <em>blockchain</em> do zero para entender realmente as entradas e saídas dessa tecnologia distribuída <em>peer-to-peer</em>.</p><p>Depois disso, decida sobre seu futuro e suas vantagens. Alerta de <em>spoiler</em>: você vai se apaixonar pelo software de programação de <em>blockchain</em>.</p><h3 id="como"><strong>Como<strong>?</strong></strong></h3><p>Você seguirá a história de um desenvolvedor de software que está procurando revolucionar seu bar local, através da implementação da tecnologia de <em>blockchain</em> para seu sistema de pagamento.</p><p>Embora a <em>blockchain</em> tenha vários casos de uso inegáveis, no momento, a aplicação número um são os pagamentos. Isto ocorre porque os bancos ainda estão funcionando em uma infraestrutura ineficiente, com 40 anos de idade, alimentada por arquivos CSV e FTP.</p><p>A história vem com muitos fatos engraçados e intrigantes sobre o ecossistema geral da <em>blockchain </em>e diferentes protocolos, como Bitcoin, Ethereum e XRP.</p><h2 id="o-que-voc-vai-criar-aprender-e-fazer-neste-tutorial"><strong>O que você vai criar, aprender e fazer neste tutorial?</strong></h2><ul><li>Você vai configurar um projeto na linguagem Go em sua máquina local sem qualquer experiência prévia com GoLang</li><li>Você gerará e distribuirá seus primeiros <em>tokens </em>(ativos digitais) de <em>blockchain</em>.</li><li>Você desenvolverá um banco de dados controlado pela CLI em Go a partir do zero</li><li>Você descobrirá como poucos usuários possuem direitos em suas aplicações favoritas</li><li>Você descobrirá a principal proposta de valor da <em>blockchain</em></li><li>Você tornará seu BD imutável usando uma função de <em>hash</em> criptográfico segura</li></ul><p>Por isso, vamos começar a nossa história.</p><h2 id="-conhe-a-o-protagonista-andrej-"><strong><strong>⭐</strong> </strong>Conheça o protagonista,<strong><strong> Andrej.</strong></strong></h2><p>Andrej é dono de um bar à noite e desenvolvedor de software de dia em uma pequena cidade eslovaca chamada Bardejov.</p><p>Andrej está cansado de:</p><ul><li><strong>Programação de aplicações sólidas e à moda antiga com PHP/Java/Javascript</strong></li><li>Esquecer quanto dinheiro seus amigos e clientes lhe devem por todos os <em>shots </em>de vodka não pagos de sexta-feira à noite</li><li>Passar tempo coletando e contando moedas, devolvendo troco e geralmente tocando cédulas expostas à COVID-19</li><li>Fazer a manutenção de diferentes fichas plásticas para pebolim, dardos, bilhar e pôquer</li></ul><p>Andrej adoraria:</p><ul><li><strong>Ter um histórico auditável perfeito das atividades</strong> e vendas do bar para tornar seu bar compatível com as normas fiscais</li><li><strong>Transformar seu bar em um ambiente autônomo, eficiente, descentralizado e seguro, no qual seus clientes possam confiar e apenas se divertir</strong></li></ul><p>Seu objetivo é escrever um programa simples e manter todos os saldos de seus clientes de modo virtual.</p><p>Andrej compartilha suas ideias aqui:</p><p>"Cada novo cliente me dará dinheiro, e<strong> eu creditarei para eles uma quantidade equivalente dos meus <em>tokens</em> (moedas/moeda criptográfica)</strong>". Os <em>tokens</em> representarão uma unidade monetária dentro e fora do bar.</p><p>As pessoas usarão os <em>tokens</em> para todas as funcionalidades do bar, desde pagar bebidas, pedir emprestado e emprestar a seus amigos, até jogar tênis de mesa, pôquer e pebolim.</p><p>Ter um bar administrado por meio de <em>tokens</em> gerará um valor imenso para meus clientes. Ao contrário da minha concorrência e de outros bares nesta rua, onde os clientes só gastam dinheiro e conseguem uma ressaca em troca, <strong>os clientes que tiverem fichas do meu bar terão direito de acionistas.</strong></p><p>Semelhante a possuir uma grande parte das ações de uma empresa, como a Apple ou a Microsoft, os clientes que possuem esses <em>tokens</em> de bar poderão decidir como o bar funcionará através de votação e decisão sobre:</p><ul><li>preços das bebidas</li><li>horário de funcionamento</li><li>novas funcionalidades (TV, <em>jukebox</em>...)</li><li>design interior e exterior </li><li>alocação de lucros</li><li>etc.</li></ul><p>Ah, isso será um sonho para programação!</p><p>Chamarei os <em>tokens</em> de: <em>tokens</em> do bar das <em>blockchain</em>, ou <strong>TBB</strong>!"</p><p>Agora que Andrej compartilhou seu sonho, vamos começar.</p><h2 id="sum-rio"><strong>Sumário</strong></h2><ul><li><a href="https://www.freecodecamp.org/portuguese/news/como-criar-uma-blockchain-do-zero-com-go/#requisitos">Requisitos</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/como-criar-uma-blockchain-do-zero-com-go/#configurar-o-projeto">Configurar o projeto</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/ghost/#\30%201-o-banco-de-dados-mvp">01 | O banco de dados MVP</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/como-criar-uma-blockchain-do-zero-com-go/#\30%202-alterando-o-estado-global-do-bd">02 | Alterando o estado global do BD</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/como-criar-uma-blockchain-do-zero-com-go/#\30%203-evento-monol-tico-x-transa-o">03 | Evento monolítico x transação</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/como-criar-uma-blockchain-do-zero-com-go/#\30%204-os-humanos-s-o-gananciosos">04 | Os seres humanos são gananciosos</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/como-criar-uma-blockchain-do-zero-com-go/#\30%205-por-que-precisamos-da-blockchain">05 | Por que precisamos da blockchain</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/como-criar-uma-blockchain-do-zero-com-go/#\30%206-o-hash-imut-vel">06 | O hash imutável</a></li><li><a href="https://www.freecodecamp.org/portuguese/news/como-criar-uma-blockchain-do-zero-com-go/#-pr-ximos-passos">Próximos passos</a></li></ul><h2 id="requisitos"><strong><strong>Requi</strong>sitos</strong></h2><p>Vamos nos aprofundar em nosso tutorial. Recomendo mais de 2 anos de experiência em programação em Java/PHP/Javascript ou outra linguagem similar à Go.</p><p>Se você quiser ter uma boa introdução rápida para começar, <a href="https://www.youtube.com/watch?v=YS4e4q9oBaU">aqui está um curso gratuito</a> (em inglês) que ajudará você.</p><p>Você também pode completar as 17 aulas oficiais de <a href="https://go-tour-br.appspot.com/basics/1">Um tour por Go</a> para se familiarizar com a sintaxe do idioma e conceitos básicos (cerca de 20 minutos).</p><h3 id="por-que-go"><strong>Por que<strong> Go?</strong></strong></h3><p>Porque, assim como a <em>blockchain</em>, é uma tecnologia fantástica para toda a sua carreira de programação. Go é uma linguagem da moda e desenvolvedores de Go são mais bem pagos do que a média das posições em Java/PHP/Javascript.</p><p>Go é otimizado para a arquitetura de CPUs <em>multi-core</em>. Você pode gerar milhares de <em>threads</em> leves (rotinas do Go) sem problemas. É extremamente prático para software paralelos e simultâneos, tais como redes de <em>blockchain</em>.</p><p>Ao escrever seu software em Go, você atinge um nível semelhante ao do C++ em termos de desempenho, desde o início, sem se matar por ter esquecido de liberar a memória.</p><p>Go também compila para binário, o que o torna muito portátil.</p><h2 id="configurar-o-projeto">Configurar o projeto</h2><p>Este artigo tem um repositório dedicado e de código aberto no Github, com o código-fonte completo para que você possa compilar o código e executar o programa em sua própria máquina local.</p><p>Se você ficar preso em qualquer capítulo ou em uma linha de código em particular, crie uma <em>issue </em>no Github do repositório descrevendo seu problema e eu o ajudarei o quanto antes!</p><p>Visite o <a href="https://github.com/web3coach/the-blockchain-bar-newsletter-edition/">repositório no Github</a> e siga as instruções de instalação.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/54218031.png" class="kg-image" alt="54218031" width="400" height="400" loading="lazy"></figure><h2 id="01-o-banco-de-dados-mvp"><strong>01 | O banco de dados MVP</strong></h2><p>✍ <code>git checkout c1_genesis_json</code></p><p>Andrej dominou os bancos de dados relacionais em SQL nos anos 90. Ele sabe como fazer modelos de dados avançados e como otimizar as consultas em SQL.</p><p>Chegou a hora de Andrej alcançar a inovação e começar a criar software para a web 3.0.</p><p>Por sorte, após ler o livro "The Lean Startup" na semana passada, Andrej percebe que ainda não deveria projetar demais a solução. Assim, ele escolhe um arquivo JSON simples, mas eficaz, para ser o banco de dados e o <a href="https://pt.wikipedia.org/wiki/Produto_vi%C3%A1vel_m%C3%ADnimo">produto viável mínimo</a>, ou MVP (do inglês, <em>minimum viable product</em>), do bar.</p><p>No início, havia um banco de dados centralizado primitivo.</p><h3 id="resumo-"><strong>Resumo:</strong></h3><p><strong>A <em>blockchain<strong> </strong></em>é um banco de dado</strong>s<strong><strong>.</strong></strong></p><h3 id="usu-rio-1-andrej"><strong><strong>Us</strong>uário<strong> 1, Andrej</strong></strong></h3><p><em>Segunda-feira, 18 de março.</em></p><p>Andrej gera 1 milhão de <em>tokens</em> de utilidade.</p><p>No mundo da <em>blockchain</em>, os <em>tokens</em> são unidades dentro do banco de dados da <em>blockchain</em>. Seu valor real em espécie flutua com base em sua demanda e popularidade.</p><p>Cada <em>blockchain</em> tem um arquivo "<strong>Genesis</strong>". O arquivo "Genesis" é usado para distribuir os primeiros <em>tokens</em> aos participantes iniciais da <em>blockchain</em>.</p><p>Tudo começa com um simples <strong><strong>genesis.json</strong></strong> de teste.</p><p>Andrej cria o arquivo <code>./database/genesis.json</code>, onde ele define que o banco de dados do bar da <em>blockchain</em> terá 1 milhão de <em>tokens</em> e que todas elas pertencerão a Andrej:</p><pre><code class="language-json">{
  "genesis_horario": "2019-03-18T00:00:00.000000000Z",
  "chain_id": "the-blockchain-bar-ledger",
  "saldo": {
      "andrej": 1000000
  }
}
</code></pre><p>Os <em>tokens</em> precisam ter uma "utilidade" real, ou seja, um caso de uso. Os usuários devem ser capazes de pagar com eles a partir do primeiro dia!</p><p>Andrej deve estar em conformidade com as regulamentações da lei. É ilegal a emissão de valores não registrados. Por outro lado, os <em>tokens</em> de utilidade estão em conformidade, então ele imprime e cola imediatamente um novo cartaz com os preços na porta do bar.</p><p>Andrej atribui um valor monetário inicial a seus <em>tokens</em> para poder trocá-los por euro, dólar ou outra moeda.</p><pre><code class="language-json">1 token TBB = 1€

| Item                      	 | Preco   |
| ------------------------------ | ------- |
| Dose de vodka                	 | 1   TBB |
| Suco de laranja           	 | 5   TBB |
| Hamburguer                	 | 2   TBB |
| Garrafa de vodka Crystal Head  | 950 TBB |
</code></pre><p>Andrej também decide <strong>que deve receber 100 </strong><em><strong>tokens</strong></em><strong> por dia</strong> para manter o banco de dados e por ter tido uma ideia tão brilhante e disruptiva.</p><h3 id="fatos-interessantes">Fatos interessantes</h3><blockquote>A primeira genesis Ether (ETH) sobre a blockchain Ethereum foi criada e distribuída aos primeiros investidores e desenvolvedores da mesma maneira que o <em>token</em> de utilidade de Andrej.</blockquote><blockquote>Em 2017, durante um boom das ofertas iniciais de moedas (do inglês, Initial Coin Offers, ou ICO) na rede de blockchain Ethereum, os fundadores do projeto escreveram e apresentaram whitepapers aos investidores. Um whitepaper é um documento técnico que esboça uma questão complexa e uma possível solução, destinada a educar e esclarecer sobre um assunto específico. No mundo da blockchain, um whitepaper serve para delinear as especificações de como essa blockchain em particular será e se comportará uma vez desenvolvida.</blockquote><blockquote>Os projetos de blockchain aumentaram entre 10 e 300 milhões de euros por ideia de <strong>whitepaper</strong>.</blockquote><blockquote>Em troca de dinheiro (o "financiamento" das ICOs), os nomes dos investidores seriam incluídos nos "balanços de genesis" iniciais, semelhante ao que Andrej fez. As esperanças dos investidores em uma ICO estão no fato de que as moedas de genesis subam de valor e que as equipes entreguem a blockchain delineada.</blockquote><blockquote>Naturalmente, nem todas as ideias de whitepaper se concretizam. Investimentos massivos perdidos por ideias pouco claras ou incompletas são a razão pela qual a blockchain recebeu cobertura negativa na mídia através dessas ICOs e para alguns ainda a considerarem uma modinha. A tecnologia da blockchain subjacente, porém, é fantástica e útil, como você aprenderá mais neste artigo. Ela tem sido abusada por alguns maus atores.</blockquote><h3 id="resumo--1"><strong>Resumo:</strong></h3><p>A <em>blockchain </em>é um banco de dados.</p><p>O fornecimento de <em>tokens</em>, o balanço inicial do usuário e as configurações globais da <em>blockchain </em>são definidas em um arquivo genesis.</p><h2 id="02-alterando-o-estado-global-do-bd"><strong><strong>02 | </strong>Alterando o estado global do BD</strong></h2><p>✍ <code>git checkout c2_db_changes_txt</code></p><h2 id="festa-chata"><strong>Festa chata</strong></h2><p><em>Segunda-feira<em>, </em> 25 de <em>Mar</em>ço<em>.</em></em></p><p>Após uma semana de trabalho, as instalações do bar estão prontas para aceitar os <em>tokens</em>. Infelizmente, ninguém aparece. Então, Andrej pede três doses de vodka para si mesmo e escreve as mudanças no banco de dados em um pedaço de papel:</p><pre><code class="language-text">andrej-3;   // 3 doses de vodka
andrej+3;   // tecnicamente comprando de seu próprio bar
andrej+700; // Recompensa por uma semana de trabalho (7x100 por dia)
</code></pre><p>Para evitar recalcular o estado mais recente do saldo de cada cliente, Andrej cria um arquivo <code>./database/state.json</code>, que armazena os saldos em um formato agregado.</p><p>Novo estado do BD:</p><pre><code class="language-json">{
  "saldo": {
      "andrej": 1000700
  }
}
</code></pre><h3 id="b-nus-para-babayaga"><strong>Bônus para BabaYaga</strong></h3><p><em><em>T</em>erça-feira<em>, </em>26 de <em>Mar</em>ço<em>.</em></em></p><p>Para trazer o público até seu bar, Andrej anuncia um bônus exclusivo de 100% para todos que adquirirem os <em>tokens</em> TBB nas próximas 24 horas.</p><p>Ele recebe sua primeira cliente, chamada <strong>BabaYaga</strong>. BabaYaga pré-compra mil euros em <em>tokens</em> e, para comemorar, gasta imediatamente 1 TBB para uma dose de vodka. Ela tem um problema com a bebida.</p><p>Transações do BD escritas em um pedaço de papel:</p><pre><code class="language-text">andrej-2000;   // transfererência para BabaYaga
babayaga+2000; // pré-compra com 100% bônus
babayaga-1;
andrej+1;
andrej+100;    // 1 dia de sol nascendo
</code></pre><p>Novo estado do BD:</p><pre><code class="language-json">{
  "saldo": {
      "andrej": 998801,
      "babayaga": 1999
  }
}
</code></pre><h3 id="fatos-interessantes-1">Fatos interessantes</h3><blockquote>Os projetos de ICO (ofertas iniciais de moedas, baseadas em whitepaper) de blockhain frequentemente distribuem os <em>tokens</em> de genesis com diferentes bônus, dependendo de quantos deles você compra e de você ter feito isso rapidamente. As equipes oferecem, em média, 10-40% de bônus aos "participantes" iniciais.</blockquote><blockquote>A palavra "investidor" é evitada, de modo que os reguladores legais não considerarão os <em>tokens</em> como um valor não registrado. Os projetos argumentariam que seu produto principal, <em>tokens</em> de blockchain, funcionam como "milhas de vôo ou pontos de fidelidade".</blockquote><blockquote>Os "participantes", mais tarde, fazem até 1.000% de seu investimento vendendo ao público através de um intercâmbio vários meses depois.</blockquote><h3 id="resumo--2"><strong>Resumo:</strong></h3><p>A <em>blockchain</em> é um banco de dados.</p><p>O fornecimento de <em>tokens</em>, o balanço inicial do usuário e as configurações globais da <em>blockchain</em>, você define em um arquivo Genesis.</p><p><strong>Os balanços de Genesis indicam qual era o estado original da <em>blockchain</em> e nunca são atualizados depois.</strong></p><p><strong>As mudanças de estado do banco de dados são chamadas de transações (TX).</strong></p><h2 id="03-evento-monol-tico-x-transa-o"><strong><strong>03 | </strong></strong>Evento monolítico x transação</h2><p>✍ <code>git checkout c3_state_blockchain_component</code></p><p>Os desenvolvedores acostumados à arquitetura de fornecimento de eventos devem ter reconhecido imediatamente os princípios familiares por trás das transações. Eles estão corretos.</p><p>As transações das <em>blockchain </em>representam uma série de eventos. O banco de dados é um estado final agregado, calculado após a repetição de todas as transações em uma sequência específica</p><h3 id="andrej-programando"><strong>Andrej programando</strong></h3><p><em>Terça-feira à noite, 26 de março.</em></p><p>É uma noite relaxante de terça-feira para Andrej. Comemorando seu primeiro cliente, ele decide jogar <a href="https://www.youtube.com/watch?v=Ff4VIghrTMg&amp;feature=youtu.be&amp;t=516">Starcraft</a> e limpar sua máquina de desenvolvimento local, removendo algumas fotos antigas.</p><p>Infelizmente, ele pressionou prematuramente a tecla Enter ao digitar um comando de comando de remoção no terminal, <code>sudo rm -rf /</code>. Xiiii!</p><p>Todos os seus arquivos, incluindo os arquivos <code>genesis.json</code> e <code>state.json</code> do bar, desapareceram.</p><p>Andrej, sendo um desenvolvedor sênior, gritou repetidamente algumas palavras bem alto por alguns segundos, mas não entrou em pânico!</p><p>Embora ele não tivesse um back-up, ele tinha algo melhor – um pedaço de papel com todas as transações do banco de dados. A única coisa que ele precisa fazer é reproduzir todas as transações uma a uma e o estado de seu banco de dados será recuperado.</p><p>Impressionado com as vantagens da arquitetura baseada em eventos, ele decide ampliar sua solução de banco de dados MVP. Cada atividade do bar, como a compra individual de bebidas, DEVE ser registrada dentro do banco de dados da <em>blockchain</em>.</p><p>Cada <strong>consumidor</strong> será representado no BD utilizando uma estrutura de <strong>conta</strong>:</p><pre><code class="language-go">type Conta string
</code></pre><p>Cada <strong>Transação</strong> (TX – uma mudança de banco de dados) terá os quatro atributos seguintes: <strong>de, para, valor</strong> e <strong>dados</strong>.</p><p>O atributo de <strong>dados</strong> com um valor possível (<strong>recompensa</strong>) captura o bônus de Andrej por inventar a <em>blockchain</em> e aumenta artificialmente a oferta total inicial de <em>tokens</em> TBB (inflação).</p><pre><code class="language-go">type Tx struct {
   De  Account `json:"de"`
   Para    Account `json:"para"`
   Valor uint    `json:"valor"`
   Dado  string  `json:"dado"`
}

func (t Tx) IsReward() bool {
   return t.Dado == "recompensa"
}
</code></pre><p>O<strong> BD de Genesis</strong> permanecerá com um arquivo JSON:</p><pre><code class="language-json">{
  "genesis_horario": "2019-03-18T00:00:00.000000000Z",
  "chain_id": "the-blockchain-bar-ledger",
  "saldo": {
      "andrej": 1000000
  }
}</code></pre><p>Todas as transações, previamente escritas em um pedaço de papel, serão armazenadas em um banco de dados local de arquivos de texto chamado <strong>tx.db</strong>, serializado em formato JSON e separado por caracteres de quebra de linha:</p><pre><code class="language-json">{"de":"andrej","para":"andrej","valor":3,"dado":""}
{"de":"andrej","para":"andrej","valor":700,"dado":"recompensa"}
{"de":"andrej","para":"babayaga","valor":2000,"dado":""}
{"de":"andrej","para":"andrej","valor":100,"dado":"recompensa"}
{"de":"babayaga","para":"andrej","valor":1,"dado":""}
</code></pre><p>O componente mais crucial do banco de dados, que encapsula toda a lógica comercial será o <strong>Estado</strong>:</p><pre><code class="language-go">type Estado struct {
   Saldos   map[Conta]uint
   txMempool []Tx

   dbFile *os.File
}
</code></pre><p>A estrutura do Estado saberá sobre todos os saldos de usuários, quem transferiu os <em>tokens</em> TBB para quem e quantos foram transferidos.</p><p>É construído através da leitura do saldo inicial de usuários do arquivo <code>genesis.json</code>:</p><pre><code class="language-go">func NewStateFromDisk() (*Estado, error) {
   // Obter o diretorio de trabalho atual
   cwd, err := os.Getwd()
   if err != nil {
      return nil, err
   }

   genFilePath := filepath.Join(cwd, "database", "genesis.json")
   gen, err := loadGenesis(genFilePath)
   if err != nil {
      return nil, err
   }

   saldo := make(map[Conta]uint)
   for conta, saldo := range gen.Saldos {
      saldos[conta] = saldo
   }
</code></pre><p>Em seguida, os balanços do Estado de <code>genesis</code> são atualizados através da reprodução sequencial de todos os eventos do banco de dados do tx.db:</p><pre><code class="language-go">   txDbFilePath := filepath.Join(cwd, "database", "tx.db")
   f, err := os.OpenFile(txDbFilePath, os.O_APPEND|os.O_RDWR, 0600)
   if err != nil {
      return nil, err
   }

   scanner := bufio.NewScanner(f)
   estado := &amp;Estado{saldos, make([]Tx, 0), f}

   // Iterar sobre cada linha do arquivo tx.db
   for scanner.Scan() {
      if err := scanner.Err(); err != nil {
         return nil, err
      }

      // Converter TX codificado pelo JSON em um objeto (estrutura)
      var tx Tx
      json.Unmarshal(scanner.Bytes(), &amp;tx)

      // Reconstruir o Estado (saldos de usuários),
      // como uma série de eventos
      if err := estado.apply(tx); err != nil {
         return nil, err
      }
   }

   return estado, nil
}
</code></pre><p>O componente Estado é responsável por:</p><ul><li><strong>Adicionar</strong> novas transações ao <strong>Mempool</strong></li><li><strong>Validar</strong> as transações contra o Estado atual (saldo suficiente do remetente)</li><li><strong>Mudar</strong> o estado</li><li>Salvar transações <strong>persistentes</strong> em disco</li><li><strong>Calcular os</strong> saldos de contas através da repetição de todas as transações desde Genesis em uma seqüência</li></ul><p><strong>Adicionar</strong> novas transações ao Mempool:</p><pre><code class="language-go">func (s *Estado) Add(tx Tx) error {
   if err := s.apply(tx); err != nil {
      return err
   }

   s.txMempool = append(s.txMempool, tx)

   return nil
}
</code></pre><p><strong>Persistir</strong> as transações em disco:</p><pre><code class="language-go">func (s *Estado) Persist() error {
   // Faça uma cópia do mempool porque o s.txMempool será modificado
   // no laço abaixo
   mempool := make([]Tx, len(s.txMempool))
   copy(mempool, s.txMempool)

   for i := 0; i &lt; len(mempool); i++ {
      txJson, err := json.Marshal(mempool[i])
      if err != nil {
         return err
      }

      if _, err = s.dbFile.Write(append(txJson, '\n')); err != nil {
         return err
      }

      // Remover o TX escrito em um arquivo do mempool
      s.txMempool = s.txMempool[1:]
   }

   return nil
}</code></pre><p><strong>Mudar</strong>, <strong>validar</strong> o estado:</p><pre><code class="language-go">func (s *Estado) apply(tx Tx) error {
   if tx.IsReward() {
      s.Saldos[tx.To] += tx.Valor
      return nil
   }

   if tx.Valor &gt; s.Saldos[tx.De] {
      return fmt.Errorf("saldo insuficiente")
   }

   s.Saldos[tx.De] -= tx.Valor
   s.Saldos[tx.Para] += tx.Valor

   return nil
}
</code></pre><h3 id="construir-uma-interface-de-linha-de-comando-cli-">Construir uma interface de linha de comando<strong><strong> (CLI)</strong></strong></h3><p><em>Terça-feira à noite, 26 de março.</em></p><p>Andrej quer ter uma maneira conveniente de adicionar novas transações ao seu banco de dados e listar os últimos saldos de seus clientes. Como os programas Go compilam para binário, ele faz uma CLI para seu programa.</p><p>A maneira mais fácil de desenvolver programas baseados em CLI em Go é usando a biblioteca de terceiros <code>github.com/spf13/cobra</code>.</p><p>Andrej inicializa o gerenciador de dependências de Go para seu projeto, chamado <code>go modules</code>:</p><p>✍ <code>cd $GOPATH/src/github.com/web3coach/the-blockchain-way-of-programming-newsletter-edition</code></p><p>✍ <code>go mod init github.com/web3coach/the-blockchain-way-of-programming-newsletter-edition</code></p><p>O comando <code>Go modules</code> buscará automaticamente qualquer biblioteca a que você se referir dentro de seus arquivos Go.</p><p>Andrej cria um diretório chamado <code>cmd</code>, com um subdiretório <code>tbb</code>:</p><p>✍<code>mkdir -p ./cmd/tbb</code></p><p>Dentro, ele cria um arquivo <code>main.go</code>, servindo como o ponto de entrada da CLI do programa:</p><pre><code class="language-go">package main

import (
    "github.com/spf13/cobra"
    "os"
    "fmt"
)

func main() {
    var tbbCmd = &amp;cobra.Command{
        Use:   "tbb",
        Short: "The Blockchain Bar CLI",
        Run: func(cmd *cobra.Command, args []string) {
        },
    }
    
    err := tbbCmd.Execute()
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
}
</code></pre><p>Os programas Go são compilados usando o comando <code>install</code>:<br><br>✍ <code>go install ./cmd/tbb/...</code></p><pre><code class="language-text">go: finding github.com/spf13/cobra v1.0.0
go: downloading github.com/spf13/cobra v1.0.0
go: extracting github.com/spf13/cobra v1.0.0</code></pre><p>O Go detectará as bibliotecas ausentes e as buscará automaticamente antes de compilar o programa. Dependendo de seu $GOPATH, o programa resultante será salvo na pasta <code>$GOPATH/bin</code>.</p><p>✍<code>echo $GOPATH</code></p><pre><code class="language-text">/home/web3coach/go</code></pre><p>✍<code>which tbb</code></p><pre><code class="language-text">/home/web3coach/go/bin/tbb</code></pre><p>Você pode executar o tbb de seu terminal agora, mas ele não fará nada porque a função <code>Run</code> dentro do arquivo <code>main.go</code> está vazia.</p><p>A primeira coisa que Andrej precisa é de suporte de versão para seu programa <code>tbb</code> da CLI.</p><p>Ao lado do arquivo <code>main.go</code>, ele cria um comando <code>version.go</code>:</p><pre><code class="language-go">package main

import (
    "fmt"
    "github.com/spf13/cobra"
)

const Major = "0"
const Minor = "1"
const Fix = "0"
const Verbal = "Adicionar TX e listar saldos"

var versionCmd = &amp;cobra.Command{
    Use:   "versão",
    Short: "Descreve a versão.",
    Run: func(cmd *cobra.Command, args []string) {
        fmt.Printf("Versão: %s.%s.%s-beta %s", Major, Minor, Fix, Verbal)
    },
}
</code></pre><p>Ele compila o programa e o executa:<br>✍ <code>go install ./cmd/tbb/...</code><br>✍ <code>tbb version</code></p><p><code>Versão: 0.1.0-beta Adicionar TX e listar saldos</code></p><p>Perfeito.</p><p>De modo idêntico ao arquivo <code>version.go</code>, ele cria um arquivo <code>balance.go</code>:</p><pre><code class="language-go">func saldosCmd() *cobra.Command {
    var saldosCmd = &amp;cobra.Command{
        Use:   "saldos",
        Short: "Interage com saldos (lista...).",
        PreRunE: func(cmd *cobra.Command, args []string) error {
            return incorrectUsageErr()
        },
        Run: func(cmd *cobra.Command, args []string) {
        },
    }

    saldosCmd.AddCommand(saldosListaCmd)

    return saldosCmd
}
</code></pre><p>O comando <code>saldos</code> será responsável por carregar o último estado do BD e imprimi-lo para a saída padrão:</p><pre><code class="language-go">var saldosListaCmd = &amp;cobra.Command{
    Use:   "list",
    Short: "Lista todos os saldos.",
    Run: func(cmd *cobra.Command, args []string) {
        estado, err := database.NewStateFromDisk()
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(1)
        }
        defer estado.Close()

        fmt.Println("Saldos das contas:")
        fmt.Println("__________________")
        fmt.Println("")
        for conta, saldo := range estado.Saldos {
            fmt.Println(fmt.Sprintf("%s: %d", conta, saldo))
        }
    },
}
</code></pre><p>Andrej verifica se o comando funciona como esperado. Ele deve imprimir os saldos exatos definidos no arquivo Genesis porque o arquivo <code>tx.db</code> ainda está vazio.</p><p>✍ <code>go install ./cmd/tbb/...</code></p><p>✍ <code>tbb saldos list</code></p><pre><code>Saldos das contas:
__________________
andrej: 1000000
</code></pre><p>Funciona bem! Agora, ele só precisa de um comando para registrar a atividade do bar.</p><p>Andrej cria o comando <code>./cmd/tbb/tx.go</code>:</p><pre><code class="language-go">func txCmd() *cobra.Command {
    var txsCmd = &amp;cobra.Command{
        Use:   "tx",
        Short: "Interage com as txs (adicionar...).",
        PreRunE: func(cmd *cobra.Command, args []string) error {
            return incorrectUsageErr()
        },
        Run: func(cmd *cobra.Command, args []string) {
        },
    }

    txsCmd.AddCommand(txAddCmd())

    return txsCmd
}
</code></pre><p>O comando <code>tbb tx add</code> utiliza a função <code>Estado.Adicionar(tx)</code> para a persistência dos eventos do bar no sistema de arquivos:</p><pre><code class="language-go">func txAddCmd() *cobra.Command {
    var cmd = &amp;cobra.Command{
        Use:   "add",
        Short: "Adiciona novo TX ao banco de dados.",
        Run: func(cmd *cobra.Command, args []string) {
            de, _ := cmd.Flags().GetString(flagDe)
            para, _ := cmd.Flags().GetString(flagPara)
            valor, _ := cmd.Flags().GetUint(flagValor)

            deConta := database.NewAccount(de)
            paraConta := database.NewAccount(para)
            
            tx := database.NewTx(deConta, paraConta, valor, "")

            estado, err := database.NewStateFromDisk()
            if err != nil {
                fmt.Fprintln(os.Stderr, err)
                os.Exit(1)
            }
            
            // Deferir ao final da execução dessa função
            // A executação da seguinte declaração (fechar o arquivo DB com todos os TXs)
            defer estado.Close()
            
            // Adicionar o TX a um array em memória (pool)
            err = estado.Add(tx)
            if err != nil {
                fmt.Fprintln(os.Stderr, err)
                os.Exit(1)
            }
            
            // Limpa os TXs do mempool para o disco
            err = estado.Persist()
            if err != nil {
                fmt.Fprintln(os.Stderr, err)
                os.Exit(1)
            }

            fmt.Println("TX adicionada com sucesso ao ledger.")
        },
    }
</code></pre><p>O comando <code>tbb tx add</code> tem 3 <em>flags </em>obrigatórias: <code>--de</code>, <code>--para</code> e <code>--valor</code>.</p><pre><code class="language-go">cmd.Flags().String(flagDe, "", "De que conta enviar os tokens")
cmd.MarkFlagRequired(flagDe)

cmd.Flags().String(flagPara, "", "Para que conta enviar os tokens")
cmd.MarkFlagRequired(flagPara)

cmd.Flags().Uint(flagValor, 0, "Quantos tokens enviar")
cmd.MarkFlagRequired(flagValor)

return cmd
</code></pre><p>A CLI está feita!</p><p>Andrej migra todas as transações do papel para o novo BD:</p><p>✍ <code>tbb tx add --de=andrej --para=andrej --valor=3</code></p><p>✍<code>tbb tx add --de=andrej --para=andrej --valor=700</code></p><p>✍<code>tbb tx add --de=babayaga --para=andrej --valor=2000</code></p><p>✍<code>tbb tx add --de=andrej --para=andrej --valor=100 --dado=recompensa</code></p><p>✍<code>tbb tx add --de=babayaga --para=andrej --valor=1</code></p><p>Leia todos os TXs a partir do disco e calcule o estado mais recente:</p><p>✍ <code>tbb saldos list</code></p><pre><code>Saldos das contas:
__________________
andrej: 998801
babayaga: 1999
</code></pre><p>Dados do bar restaurados com sucesso! Ufa! Que noite!</p><h3 id="sobre-a-biblioteca-cobra-cli"><strong>Sobre a biblioteca Cobra CLI</strong></h3><p>O bom da biblioteca Cobra para a programação da CLI está nas características adicionais que ela traz consigo. Por exemplo, agora, você pode executar o comando <code>tbb help</code> e imprimirá todos os subcomandos registrados na TBB com instruções sobre como usá-los.</p><pre><code class="language-bash"> tbb help

The Blockchain Bar CLI

Usage:
  tbb [flags]
  tbb [command]

Available Commands:
  balances    Interage com balanços (list...).
  help        Ajuda sobre qualquer comando
  tx          Interage com txs (add...).
  version     Descreve a versão.

Flags:
  -h, --help   ajuda para tbb

Use "tbb [comando] --help" para mais informações sobre um comando.
</code></pre><h3 id="fatos-interessantes-2">Fatos interessantes</h3><blockquote>A perda acidental de dados dos clientes é normal no mundo corporativo nos dias de hoje. A blockchain corrige isso descentralizando o armazenamento de dados.</blockquote><blockquote>Há um truque que Andrej introduziu no programa ao pular a verificação de saldos para os TX marcados como "recompensas". <strong>Bitcoin e Ethereum funcionam da mesma forma.</strong> O saldo da Conta que <strong>minerou um bloco</strong> aumenta do nada como um assunto de inflação total de fornecimento dos tokens, que afeta toda a cadeia. O fornecimento total de bitcoins é limitado a 21M BTC. Você aprenderá mais sobre "mineração" e "blocos" posteriormente.</blockquote><blockquote>Os componentes <strong>State</strong> (estado) e <strong>Mempool</strong> não são exclusivos deste programa. Andrej escolheu os nomes e designs para combinar com um modelo simplificado da <a href="https://github.com/ethereum/go-ethereum/blob/7b32d2a47017570c44cd7f8a83612a29656c9857/core/tx_pool.go#L211">go-Ethereum</a>, para que você tenha uma ideia do código fonte central do Ethereum.</blockquote><h3 id="resumo--3"><strong>Resumo:</strong></h3><p>A <em>blockchain</em> é um banco de dados.</p><p>O fornecimento de <em>tokens</em>, os balanços iniciais dos usuários e as configurações globais da <em>blockchain </em>são definidos em um arquivo Genesis.</p><p>Os balanços de Genesis indicam qual era o estado original da <em>blockchain </em>e nunca são atualizados depois.</p><p>As mudanças de estado do banco de dados são chamadas Transações (TX).</p><p><strong>As transações são eventos ao estilo antigo, que representam ações dentro do sistema.</strong></p><h3 id="-c-digo-de-estudo"><strong><strong>⚒ </strong></strong>Código de estudo</h3><p>Commit: <a href="https://github.com/web3coach/the-blockchain-way-of-programming-newsletter-edition/commit/5d4b0b6a001e616109da732fdaf7094f1e1acf85">5d4b0b</a></p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/unlock_blockchain_components_state.png" class="kg-image" alt="unlock_blockchain_components_state" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/05/unlock_blockchain_components_state.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2023/05/unlock_blockchain_components_state.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2023/05/unlock_blockchain_components_state.png 1600w" sizes="(min-width: 720px) 720px" width="1600" height="2500" loading="lazy"></figure><p>Vamos falar sobre a ganância.</p><h2 id="04-os-humanos-s-o-gananciosos"><strong><strong>04 | </strong></strong>Os humanos são gananciosos</h2><p>✍ <code>git checkout c4_caesar_transfer</code></p><h3 id="a-gan-ncia-t-pica-dos-neg-cios"><strong>A ganância típica dos negócios</strong></h3><p>Quarta-feira, 27 de março.</p><p>BabaYaga investiu um pouco demais. Ela esqueceu que o pagamento do aluguel do apartamento estava chegando e, agora, não tem o dinheiro. BabaYaga chama o proprietário de seu apartamento, <strong>César</strong>.</p><p><strong>BabaYaga</strong>: Ei, César, sinto muito, mas não tenho dinheiro para pagar o aluguel este mês...</p><p><strong><strong>Caesar:</strong></strong> Por que não?</p><p><strong><strong>BabaYaga:</strong></strong> O ICO do Blockchain Bar ofereceu um bônus enorme e eu comprei 2000 <em>tokens</em> no valor de apenas mil euros. Foi um grande negócio!</p><p><strong><strong>C</strong>é<strong>sar:</strong></strong> Do que você está falando? O que é um ICO? O que são <em>tokens</em>? Você pode me pagar de algum outro modo?</p><p><strong><strong>BabaYaga:</strong></strong> Ah, outra vez, não. Eu posso dar mil <em>tokens</em> TBB, que valem mil euros, e você pode usá-los no bar para pagar suas bebidas! Deixe-me ligar para o dono do bar, Andrej, e fazer a transferência!</p><p><strong><strong>C</strong>é<strong>sar:</strong></strong> Muito bem... eu vou aceitar.</p><p>Andrej realiza a transferência, <strong>mas decide cobrar mais 50 </strong><em><strong>tokens</strong></em><strong> de TBB por ter de fazer os procedimentos.</strong> Ele não quer, MAS os acionistas do bar que investiram nele há alguns anos estão forçando-o a gerar lucro o mais rápido possível.</p><p>BabaYaga não vai ter problemas com esta taxa relativamente pequena, muito provavelmente, diz Andrej a si mesmo. No final, somente ele tem o acesso ao BD.</p><p>// Pagamento do aluguel</p><p>✍<code>tbb tx add --de=babayaga --para=cesar --valor=1000</code></p><p>// Cobrança de taxa oculta</p><p>✍ <code>tbb tx add --de=babayaga --para=andrej --valor=50</code></p><p>// Nova recompensa por mais um dia de manutenção do BD</p><p>✍ <code>tbb tx add --de=andrej --para=andrej --valor=100 --dado=recompensa</code></p><h3 id="fatos-interessantes-3">Fatos interessantes</h3><blockquote>O caso de uso número um da blockchain é o bancário. Muitos projetos de blockchain visam otimizar o câmbio nacional e internacional de dinheiro através de diferentes canais de moedas (XRP).</blockquote><blockquote>Outros projetos enfocam a liberdade e a identidade própria (SSI, do inglês, Self-sovereign identity) – um movimento digital que reconhece que um indivíduo deve possuir e controlar sua identidade e dinheiro sem as autoridades administrativas intervenientes ou outros intermediários centralizados. A SSI permite que as pessoas interajam no mundo digital com a mesma liberdade e capacidade de confiança que interagem no mundo off-line. (Bitcoin / Ethereum)</blockquote><blockquote>Aqui estão alguns fatos interessantes que explicam o porquê de a blockchain ser um ajuste perfeito para substituir a infraestrutura bancária atual de seu banco.</blockquote><blockquote>O bom dos <em>tokens</em> é sua fungibilidade - ou seja, sua capacidade de serem comercializados, com cada unidade sendo tão utilizável quanto a próxima. A realização de uma transferência de conta para conta pode ser feita simplesmente mudando o estado do banco de dados. As moedas criptográficas são negociáveis 24 horas por dia, 7 dias por semana.</blockquote><blockquote>Você não pode negociar ações diretamente. Você precisa passar por um corretor que participa de uma porcentagem da transação total como taxa (1-3% a 7% do lucro médio anual).</blockquote><blockquote>Uma transferência bancária internacional leva entre 3-10 dias úteis e pode custar até 5% do valor transferido! Se você estiver enviando $10.000, poderá ter que pagar até $500. A tecnologia por trás disso nos últimos 40 anos? FTP + arquivos CSV.</blockquote><blockquote>Você acha que o mercado de ações é justo? Os bancos, índices e ações são altamente centralizados e controlados por governos e grupos privados de Wall Street. O mercado livre? Wall Street controla o quanto os preços podem saltar/cair em um único dia.</blockquote><blockquote>Como exemplo, Wall Street suspendeu a negociação do "Índice S&amp;P 500" após uma queda de 7% para proteger seus investidores e fundos especulativos de perder dinheiro das pessoas que venderam suas ações durante março de 2020, após as notícias da COVID. Posteriormente, o FED imprimiu trilhões de dólares para eles mesmos para apoiar o preço das ações. Se você é um desenvolvedor que gosta de economizar dinheiro e evitar dívidas, suas economias acabarão perdendo valor de um dia para o outro por uma porcentagem ainda desconhecida.</blockquote><blockquote>Muitos países estão entrando em rendimentos negativos, um território inexplorado com consequências desconhecidas. O que isto significa? Em breve você terá que pagar ao banco para manter suas economias. Inflação no seu melhor. Você está sendo obrigado a gastar seu dinheiro para apoiar um sistema que você não controla.</blockquote><h3 id="-c-digo-de-estudo-1"><strong><strong>⚒ </strong></strong>Código de estudo</h3><p>Commit: <a href="https://github.com/web3coach/the-blockchain-way-of-programming-newsletter-edition/commit/00d6ede25b1e54ceb30c0a0314ef99a612db01de">00d6ed</a></p><h2 id="05-por-que-precisamos-da-blockchain"><strong><strong>05 | </strong></strong>Por que precisamos da blockchain</h2><p>✍ <code>git checkout c5_broken_trust</code></p><h3 id="babayaga-busca-justi-a"><strong>BabaYaga busca justiça</strong></h3><p>Quinta-feira, 28 de março.</p><p><strong>BabaYaga</strong> entra no bar para seu aniversário.</p><p><strong><strong>BabaYaga:</strong></strong> Ei, Andrej! Hoje é meu aniversário! Traga-me sua garrafa mais cara!</p><p><strong><strong>Andrej:</strong></strong> Feliz aniversário! Aqui está: Vodka Crystal Head. Mas você precisa comprar um <em>token</em> TBB adicional. A garrafa custa 950 <em>tokens</em>, e seu saldo é de 949.</p><p><strong><strong>BabaYaga:</strong></strong> O quê?! Meu saldo deveria ser de 999 TBB!</p><p><strong><strong>Andrej:</strong></strong> A transferência de fundos para César que você solicitou na semana passada custou 50 <em>tokens</em>.</p><p><strong><strong>BabaYaga:</strong></strong> Isto é inaceitável! Eu nunca concordaria com uma taxa tão alta. Você não pode fazer isto, Andrej. Confiei em seu sistema, mas você é tão pouco confiável quanto qualquer outro proprietário de empresa. As coisas devem mudar!</p><p><strong><strong>Andrej:</strong></strong> Muito bem, veja. Você é minha cliente mais fiel e eu não queria cobrar de você, mas meus acionistas me obrigaram.</p><p><strong>Deixe-me reprogramar meu sistema e torná-lo completamente transparente e descentralizado.</strong> Afinal, se todos fossem capazes de interagir com o bar sem passar por mim, isso melhoraria significativamente a eficiência do bar e equilibraria o nível de confiança!</p><ul><li>Pedir bebidas levaria segundos ao invés de minutos</li><li>Os clientes que esqueceram suas carteiras em casa poderiam pedir emprestado ou emprestar <em>tokens</em> um ao outro</li><li>Eu não teria que me preocupar em perder os dados dos clientes (novamente), pois todos teriam uma cópia dos mesmos</li><li><strong>O banco de dados seria imutável, portanto, uma vez que todos estivessem de acordo sobre um estado específico, ninguém mais poderia mudá-lo ou modificar maliciosamente a história.</strong> A imutabilidade também ajudaria nas auditorias fiscais anuais!</li><li>Se os acionistas quisessem introduzir novas taxas ou aumentar as taxas atuais, todos os envolvidos no sistema de blockchain notariam e teriam que concordar com ele. Os usuários e proprietários de empresas teriam até mesmo que se engajar em algum sistema de governança descentralizada em conjunto, baseado na votação, provavelmente. Em caso de desacordo, os usuários se afastam com todos os seus dados!</li></ul><p><strong><strong>BabaYaga:</strong></strong> Bem, certamente soa bem, mas será que isso é mesmo possível?</p><p><strong><strong>Andrej:</strong></strong> Sim, eu acho que sim. Com um pouco de <strong>hashing</strong>, <strong>listas vinculadas</strong>, <strong>estrutura de dados imutável</strong>, <strong>replicação</strong> <strong>distribuída</strong> e <strong>criptografia assimétrica!</strong></p><p><strong><strong>BabaYaga:</strong></strong> Não faço ideia do que você acabou de dizer, mas vá em frente e faça suas nerdices, Andrej!</p><h3 id="fatos-interessantes-4">Fatos interessantes</h3><blockquote>Os mineradores Bitcoin e Ethereum também recebem recompensas a cada 15 minutos, aproximadamente, por executar os servidores da blockchain (os nós) e validar as transações.</blockquote><blockquote>A cada 15 minutos, um minerador de Bitcoins recebe 12,5 BTC ($100 mil no momento em que este artigo foi escrito) para cobrir o custo de seus servidores + obter algum lucro.</blockquote><blockquote>A rede das Bitcoins consome tanta eletricidade quanto o país inteiro da Áustria. Ela é responsável por 0,29% do consumo anual de eletricidade mundial.</blockquote><blockquote>Anualmente, ela consome 76,84 TWh, produzindo 36,50 Mt de rastro de carbono de CO2 (Nova Zelândia). <a href="https://digiconomist.net/bitcoin-energy-consumption">Fonte</a>.</blockquote><blockquote>Por quê? Você aprenderá mais tarde onde você programará um algoritmo de mineração de Bitcoin a partir do zero!</blockquote><blockquote>Observação: nosso algoritmo consumirá um pouco menos de eletricidade🙂</blockquote><h3 id="resumo--4"><strong>Resumo:</strong></h3><p>O software, quando não é de código aberto, dá acesso centralizado aos dados privados, o que permite que apenas um punhado de pessoas tenha muito poder. Os usuários não têm escolha, e os acionistas estão no negócio para ganhar dinheiro.</p><p><strong>Os desenvolvedores da <em>blockchain</em> visam desenvolver protocolos onde os empresários e usuários das aplicações se sinergizem em uma relação transparente e auditável. As especificações do sistema da blockchain devem ser bem definidas desde o início e só devem mudar se seus usuários o apoiarem.</strong></p><p>A <em>blockchain</em> é um banco de dados. O fornecimento de <em>tokens</em>, os saldos iniciais de usuários e as configurações globais da <em>blockchain </em>são definidos em um arquivo Genesis. Os balanços Genesis indicam qual era o estado original da <em>blockchain </em>e nunca são atualizados posteriormente.</p><p>As mudanças de estado do banco de dados são chamadas Transações (TX). Transações são eventos à moda antiga que representam ações dentro do sistema.</p><h3 id="-c-digo-de-estudo-2">⚒<strong> Código de estudo</strong></h3><p>Commit: <a href="https://github.com/web3coach/the-blockchain-way-of-programming-newsletter-edition/commit/64204512f2173eb3f3e136e7e2674a2c456d351f">642045</a></p><h2 id="06-o-hash-imut-vel"><strong><strong>06 | </strong></strong>O hash imutável</h2><p>✍ <code>git checkout c6_immutable_hash</code></p><p><em>A dificuldade técnica começa com esta seção! Os conceitos só vão ficar mais desafiadores mas, ao mesmo tempo, muito empolgantes. Apertem os cintos 😀</em></p><h3 id="como-programar-um-banco-de-dados-imut-vel"><strong>Como programar um banco de dados imutável?</strong></h3><p><em>Sexta-feira, 29 de março.</em></p><p>Se Andrej quer descobrir como programar um BD imutável, ele tem que entender porque outros sistemas de banco de dados são mutáveis por padrão.</p><p>Ele decide analisar uma tabela poderosa do BD do MySQL:</p><pre><code class="language-text">| id | nome     | saldo   |
| -- | -------- | ------- |
| 1  | Andrej   | 998951  |
| 2  | BabaYaga | 949     | 
| 3  | Caesar   | 1000    |</code></pre><p>No BD MySQL, qualquer pessoa com acesso e uma razão suficientemente boa pode realizar uma atualização de tabela como, por exemplo:</p><pre><code class="language-mysql">UPDATE saldo_usuario SET saldo = saldo + 100 WHERE id &gt; 1
</code></pre><p>A atualização de valores através de diferentes linhas é possível porque as linhas da tabela são independentes, mutáveis e o estado mais recente não é aparente.</p><p>Qual é a última mudança no BD? A última coluna mudou? Qual é a última linha inserida? Como Andrej pode saber qual linha foi apagada recentemente? Se as linhas e o estado da tabela estivessem firmemente unidos, dependentes, a atualização da linha 1 geraria uma tabela completamente nova e diferente. Andrej conseguiria sua imutabilidade.</p><blockquote>Como você pode saber se algum byte em um banco de dados mudou?</blockquote><h3 id="imutabilidade-via-fun-es-de-hash"><strong>Imutabilidade via funções de hash</strong></h3><p><em>Hashing </em>é o processo de tomar uma string de entrada de comprimento arbitrário e produzir uma string de hash de comprimento fixo. Qualquer mudança na entrada, resultará em um <em>hash</em> novo e diferente.</p><pre><code class="language-go">package main

import (
	"crypto/sha256"
	"fmt"
)

func main() {
	saldosHash := sha256.Sum256([]byte("| 1 | Andrej | 99895 |"))
	fmt.Printf("%x\n", saldosHash)
	// Output: 6a04bd8e2...f70a3902374f21e089ae7cc3b200751
	
	// Mudar o saldo de 99895 -&gt; 99896
	
	saldosHashDiff := sha256.Sum256([]byte("| 1 | Andrej | 99896 |"))
	fmt.Printf("%x\n", saldosHashDiff)
	// Saída: d04279207...ec6d280f6c7b3e2285758030292d5e1
}
</code></pre><p>Experimente: <a href="https://play.golang.org/p/FTPUa7IhOCE">https://play.golang.org/p/FTPUa7IhOCE</a></p><p>Andrej também requer algum nível de segurança para seu banco de dados. Por isso, ele decide por uma <strong>função de hash criptográfico</strong> com as seguintes propriedades:</p><ul><li>é <a href="https://en.wikipedia.org/wiki/Deterministic_algorithm">determinista</a> – a mesma mensagem resulta sempre no mesmo hash</li><li>é rápida para calcular o valor de hash para qualquer mensagem dada</li><li>é inviável gerar uma mensagem a partir de seu valor hash, exceto tentando todas as mensagens possíveis</li><li>uma pequena mudança em uma mensagem deve mudar o valor de hash tão extensivamente que o novo valor de hash pareça não estar relacionado com o antigo valor de hash</li><li>é <a href="https://en.wikipedia.org/wiki/Computational_complexity_theory#Intractability">inviável</a> (texto em inglês) encontrar duas mensagens diferentes com o mesmo valor de hash</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/hash_fruit.png" class="kg-image" alt="hash_fruit" width="298" height="200" loading="lazy"><figcaption>Exemplo de hashing com frutas – <a href="https://twitter.com/cybergibbons/status/1203291585473110016">fonte da imagem</a></figcaption></figure><h3 id="implementando-o-hashing-do-conte-do-do-bd"><strong>Implementando o hashing do conteúdo do BD</strong></h3><p><em>Sábado à noite, 30 de março.</em></p><p>Andrej modifica a função <code>Persist()</code> para devolver um novo hash de conteúdo, <code>Snapshot</code>, toda vez que uma nova transação é persistida.</p><pre><code class="language-go">type Snapshot [32]byte
</code></pre><p>O Snapshot é produzido por esta nova função de <em>hashing </em>seguro sha256:</p><pre><code class="language-go">func (s *Estado) doSnapshot() error {
   // Lê novamente todo o arquivo desde o primeiro byte
   _, err := s.dbFile.Seek(0, 0)
   if err != nil {
      return err
   }

   txsData, err := ioutil.ReadAll(s.dbFile)
   if err != nil {
      return err
   }
   s.snapshot = sha256.Sum256(txsData)

   return nil
}
</code></pre><p>A função <code>doSnapshot()</code> é chamada pela função <code>Persist()</code> modificada. Quando uma nova transação é escrita no arquivo <code>tx.db</code>, <code>Persist()</code> faz o <em>hash</em> de todo o conteúdo do arquivo e retorna seu <em>hash</em> uma "impressão digital" de 32 bytes.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/persist_function.png" class="kg-image" alt="persist_function" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2023/05/persist_function.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2023/05/persist_function.png 800w" sizes="(min-width: 720px) 720px" width="800" height="690" loading="lazy"><figcaption>Persist() faz o hash do arquivo tx.db inteiro</figcaption></figure><p>A partir deste momento, todos podem se referir com 100% de confiança e segurança a qualquer estado particular do banco de dados (conjunto de dados) com um <em>hash</em> específico.</p><h3 id="-hora-da-pr-tica"><strong><strong>⚓</strong>Hora da prática</strong></h3><p><strong>1/4</strong> Execute o comando da lista de saldos e verifique se os balanços estão de acordo.</p><p>✍ <code>tbb saldos list</code></p><pre><code class="language-text">Saldos das contas em 7d4a360f465d...

| id | nome     | saldo   |
| -- | -------- | ------- |
| 1  | Andrej   | 999251  |
| 2  | BabaYaga | 949     | 
| 3  | Cesar    | 1000    |</code></pre><p><strong><strong>2/4</strong></strong> Remova as 2 últimas filas de <code>./database/tx.db</code> e verifique novamente os saldos.</p><p>✍ <code>tbb saldos list</code></p><pre><code class="language-bash">Saldos das contas 841770dcd3...

| id | nome     | saldo   |
| -- | -------- | ------- |
| 1  | Andrej   | 999051  |
| 2  | BabaYaga | 949     | 
| 3  | Cesar    | 1000    |
</code></pre><p><strong><strong>3/4</strong></strong> Recompense Andrej pelos últimos 2 dias (de 28 a 30 de março):</p><p>Transação de recompensa 1:</p><p>✍ <code>tbb tx add --de=andrej --para=andrej --valor=100 --dado=recompensa</code></p><pre><code class="language-bash">Persisting new TX to disk:
       {"de":"andrej","para":"andrej","valor":100,"dado":"recompensa"}
       
New DB Snapshot: ff2470c7043f5a34169b5dd38921ba6825b03b3facb83e426
TX persistida com sucesso no ledger.
</code></pre><p>Transação de recompensa 2:</p><p>✍ <code>tbb tx add --de=andrej --para=andrej --valor=100 --dado=recompensa</code></p><pre><code class="language-bash">Persisting new TX to disk:
       {"from":"andrej","to":"andrej","value":100,"data":"reward"}
       
New DB Snapshot: 7d4a360f468b837b662816bcdc52c1869f99327d53ab4a9ca
TX persistida com sucesso no ledger.
</code></pre><p><strong><strong>4/4</strong></strong> Execute o comando da lista de saldos de tbb e garanta que os balanços e o hash do snapshot sejam os mesmos do início.</p><p>✍ <code>tbb saldos list</code></p><pre><code class="language-bash">Saldos das contas em 7d4a360f465d...

| id | nome     | saldo   |
| -- | -------- | ------- |
| 1  | Andrej   | 999251  |
| 2  | BabaYaga | 949     | 
| 3  | Cesar    | 1000    |
</code></pre><p><strong>Pronto!</strong></p><p>Como a função criptográfica de hash <strong>sha256</strong> produz a mesma saída (dadas as mesmas entradas, a <code>tx.db</code> atual e 2x <code>tbb tx add</code>), se você seguir os passos exatos em seu próprio computador, você gerará exatamente o mesmo estado e hashes do banco de dados!</p><h3 id="resumo--5"><strong>Resumo:</strong></h3><p>O software fechado com acesso centralizado aos dados privados coloca apenas algumas poucas pessoas na posição de poder. Os usuários não têm escolha, e os acionistas estão no negócio para ganhar dinheiro.</p><p>Os desenvolvedores da <em>blockchain </em>visam desenvolver protocolos onde os empresários e usuários das aplicações se sinergizem em uma relação transparente e auditável. As especificações da <em>blockchain</em> devem ser bem definidas desde o início e só devem mudar se seus usuários o apoiarem.</p><p>A<em> blockchain </em>é um banco de dados <strong>imutável</strong>. O fornecimento de <em>tokens</em>, os saldos iniciais de usuários e as configurações globais da <em>blockchain </em>que você define em um arquivo Genesis. Os balanços Genesis indicam qual era o estado original da <em>blockchain </em>e nunca são atualizados depois.</p><p>As mudanças de estado do banco de dados são chamadas Transações (TX). Transações são eventos à moda antiga que representam ações dentro do sistema.</p><p><strong>O conteúdo do banco de dados é passado por uma função de hash criptográfico segura. Os participantes da <em>blockchain </em>usam o hash resultante para referenciar um estado específico do banco de dados.</strong></p><h3 id="-c-digo-de-estudo-3"><strong><strong>⚒ </strong>Código de estudo</strong></h3><p>Commit: <a href="https://github.com/web3coach/the-blockchain-way-of-programming-newsletter-edition/commit/b99e5191b19bc076b98a3869289e4788d0a4a77b">b99e51</a></p><h2 id="-pr-ximos-passos"><strong><strong><strong><strong>⭐</strong></strong></strong>Próximos passos</strong></h2><p>Você terminou os primeiros capítulos! Parabéns!</p><p>█▒▒▒▒▒▒▒▒▒ 10%</p><p>Este, porém, foi apenas um aquecimento rápido. A <em>blockchain </em>é uma tecnologia muito desafiadora e extensa. Você precisaria de um livro inteiro explicando como construir o sistema completo e todos os seus componentes a partir do zero. Por isso, escrevi um.</p><p>Você pode continuar lendo o próximo capítulo gratuito no eBook com minha versão da <em>newsletter </em>"The Blockchain Way of Programming".</p><p><strong>07 | O Modelo de programação da blockchain</strong></p><ul><li>Melhorando o desempenho de um BD imutável</li><li>Batch + Hash + Lista vinculadas ⇒ Blocos</li><li>Migrando de TX.db para BLOCKS.db</li></ul><p><strong>Aprendizagem</strong>: você redesenha e refatora seu banco de dados MVP e o transforma em uma arquitetura de <em>blockchain</em>.</p><h3 id="continua-o-do-tutorial-https-web3-coach-book">Continuação do tutorial<strong><strong><strong><strong>: </strong></strong></strong></strong><a href="https://web3.coach/#book" rel="nofollow"><strong><strong><strong><strong>https://web3.coach#book</strong></strong></strong></strong></a></h3><p>Obrigado por leitura!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Como fazer um NFT em 14 linhas de código ]]>
                </title>
                <description>
                    <![CDATA[ Se você é um desenvolvedor interessado no desenvolvimento de blockchains, deve saber algo sobre NFTs, ou tokens não fungíveis. Portanto, neste artigo, aprenderemos sobre a engenharia por trás deles para que você possa começar a construir o seu próprio blockchain. No final do projeto, você terá sua própria carteira Ethereum, ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-fazer-um-nft-com-14-linhas-de-codigo/</link>
                <guid isPermaLink="false">62f627eb714c9406b6625afb</guid>
                
                    <category>
                        <![CDATA[ Blockchain ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Paula Flávia Pagotto Simionato ]]>
                </dc:creator>
                <pubDate>Sun, 18 Sep 2022 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/nft.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/how-to-make-an-nft/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Make an NFT in 14 Lines of Code</a>
      </p><p>Se você é um desenvolvedor interessado no desenvolvimento de blockchains, deve saber algo sobre NFTs, ou tokens não fungíveis. Portanto, neste artigo, aprenderemos sobre a engenharia por trás deles para que você possa começar a construir o seu próprio blockchain.</p><p>No final do projeto, você terá sua própria carteira Ethereum, com um novo NFT dentro dela. Este tutorial é amigável para iniciantes e não requer nenhum conhecimento prévio da rede Ethereum ou de contratos inteligentes (em inglês, <em>smart contracts</em>).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/image-46.png" class="kg-image" alt="image-46" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/image-46.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/09/image-46.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/image-46.png 1112w" sizes="(min-width: 720px) 720px" width="1112" height="884" loading="lazy"><figcaption>O contrato do NFT tem apenas 14 linhas de código</figcaption></figure><h2 id="o-que-um-nft"><strong>O que é um NFT?</strong></h2><p>NFT significa token não fungível. <a href="https://ethereum.org/en/nft/">Esta citação da ethereum.org</a> explica bem:<br></p><blockquote><em><em>NFTs </em></em>são tokens que podemos usar para representar a propriedade de itens exclusivos. Eles nos permitem tokenizar coisas como arte, colecionáveis e até imóveis. Eles só podem ter um proprietário oficial de cada vez e são protegidos pelo blockchain Ethereum – ninguém pode modificar o registro de propriedade ou copiar/colar um novo NFT para fazê-lo existir.</blockquote><h2 id="o-que-um-nft-padr-o-ou-erc-721"><strong>O que é um<strong> NFT </strong>padrão<strong> o</strong>u<strong> ERC-721?</strong></strong></h2><p>O ERC-721 é o padrão NFT mais comum. Se o seu contrato inteligente implementar determinados métodos de API padronizados, ele poderá ser chamado de contrato de token não fungível ERC-721.<br>Esses métodos são especificados no <a href="https://eips.ethereum.org/EIPS/eip-721">EIP-721</a>. Projetos de código aberto, como o OpenZeppelin, simplificaram o processo de desenvolvimento ao implementar os padrões ERC mais comuns como uma biblioteca reutilizável.</p><h2 id="o-que-cunhar-um-nft">O que é cunhar um NFT?</h2><p>Ao cunhar um NFT, você publica um token exclusivo em um blockchain. Este token é uma instância do seu contrato inteligente.</p><p>Cada token tem um tokenURI exclusivo, que contém metadados de seu ativo em um arquivo JSON em conformidade com determinado esquema. Os metadados são onde você armazena informações sobre seu NFT, como nome, imagem, descrição e outros atributos.</p><p>Um exemplo de arquivo JSON para o "ERC721 Metadata Schema" se parece com este:</p><pre><code class="language-json">{
	"attributes": [
		{
			"trait_type": "Shape",
			"value": "Circle"
		},
		{
			"trait_type": "Mood",
			"value": "Sad"
		}
	],
	"description": "A sad circle.",
	"image": "https://i.imgur.com/Qkw9N0A.jpeg",
	"name": "Sad Circle"
}</code></pre><h2 id="como-armazeno-os-metadados-do-meu-nft"><strong>C<strong>o</strong>mo armazeno os metadados do meu<strong> NFT?</strong></strong></h2><p>Existem três maneiras principais de armazenar os metadados de um NFT.</p><p>Primeiro, você pode armazenar as informações on-chain (em cadeia). Em outras palavras, você pode estender seu ERC-721 e armazenar os metadados no blockchain, o que pode ser caro.</p><p>O segundo método é usar <a href="https://docs.ipfs.io/concepts/what-is-ipfs/">IPFS</a>. A terceira maneira é simplesmente fazer com que sua API retorne o arquivo JSON.</p><p>O primeiro e o segundo métodos geralmente são os preferidos, pois você não pode modificar o arquivo JSON subjacente. Para o escopo deste projeto, optaremos pelo terceiro método.</p><p>Para um bom tutorial sobre como usar NFTs com IPFS, leia &nbsp;<a href="https://docs.alchemy.com/alchemy/tutorials/how-to-create-an-nft/how-to-mint-a-nft#step-4-configure-the-metadata-for-your-nft-using-ipfs">este artigo</a> da equipe Alchemy.</p><h2 id="o-que-vamos-construir">O que vamos construir</h2><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/emotionalshapes.png" class="kg-image" alt="emotionalshapes" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/emotionalshapes.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/09/emotionalshapes.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/emotionalshapes.png 1284w" sizes="(min-width: 720px) 720px" width="1284" height="1847" loading="lazy"></figure><p>Neste tutorial, criaremos e cunharemos nosso próprio NFT. O tutorial é simples para iniciantes e não requer nenhum conhecimento prévio da rede Ethereum ou de contratos inteligentes. Ainda assim, ter uma boa compreensão desses conceitos ajudará você a entender o que está acontecendo nos bastidores.</p><p>Em um próximo tutorial, construiremos um aplicativo em React para a web totalmente funcional, onde você poderá exibir e vender seus NFTs.</p><p><br>Se você está apenas começando com o desenvolvimento de dApps, comece lendo os <a href="https://ethereum.org/en/developers/docs/intro-to-ethereum/">tópicos principais</a> e assista a <a href="https://www.youtube.com/watch?v=M576WGiDBdQ">este curso incrível</a> de Patrick Collins.</p><p><em>Este projeto foi escrito intencionalmente com código de fácil compreensão e não é adequado para uso em produção.</em></p><h2 id="pr-requisitos">Pré-requisitos</h2><h3 id="metamask"><strong><strong>Metamask</strong></strong></h3><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/image-32.png" class="kg-image" alt="image-32" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/image-32.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/09/image-32.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2022/09/image-32.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/image-32.png 1990w" sizes="(min-width: 720px) 720px" width="1990" height="1364" loading="lazy"></figure><p>Precisamos de um endereço Ethereum para interagir com nosso contrato inteligente. Usaremos o <a href="https://metamask.io/">Metamask</a> como nossa carteira. É uma carteira virtual gratuita que gerencia seus endereços Ethereum. Vamos precisar dele para enviar e receber transações (leia mais sobre isso <a href="https://ethereum.org/en/developers/docs/transactions/">aqui</a>). Por exemplo, cunhar um NFT é uma transação.</p><p>Faça o download da extensão do Chrome e do aplicativo para dispositivos móveis. Precisaremos de ambos, pois a extensão do Chrome não exibe seus NFTs.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/image-34.png" class="kg-image" alt="image-34" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/image-34.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/image-34.png 680w" width="680" height="712" loading="lazy"></figure><p>Certifique-se de alterar a rede para "Ropsten Test Network" para fins de desenvolvimento. Você precisará de algum Eth para cobrir as taxas de implantação e cunhagem de seu NFT. Vá para o <a href="https://faucet.ropsten.be/">Ropsten Ethereum Faucet</a> e digite seu endereço. Você logo deverá ver alguns Eth de teste em sua conta do Metamask.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/image-35.png" class="kg-image" alt="image-35" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/image-35.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/09/image-35.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2022/09/image-35.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/image-35.png 2000w" sizes="(min-width: 720px) 720px" width="2000" height="554" loading="lazy"></figure><h3 id="alchemy"><strong><strong>Alchemy</strong></strong></h3><p>Para interagir com a rede Ethereum, você precisará estar conectado a um Ethereum Node.</p><p>Executar seu próprio Node e manter a infraestrutura é um projeto à parte. Felizmente, existem provedores do tipo <em>node-as-a-service </em> que hospedam a infraestrutura para você<strong>.</strong> Existem muitas opções, como Infura, BlockDaemon e Moralis. Usaremos a <a href="https://www.alchemy.com/">Alchemy</a> como nosso provedor de nodes.</p><p>Vá até o site deles, crie uma conta, escolha Ethereum como sua rede e crie seu aplicativo. Escolha Ropsten como sua rede.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/image-36.png" class="kg-image" alt="image-36" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/image-36.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/09/image-36.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2022/09/image-36.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/image-36.png 2000w" sizes="(min-width: 720px) 720px" width="2000" height="1012" loading="lazy"></figure><p>No seu painel, clique em "ver detalhes" no seu aplicativo e, em seguida, clique em "ver chave". Salve sua chave http em algum lugar, pois precisaremos disso mais tarde.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/image-38.png" class="kg-image" alt="image-38" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/image-38.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/09/image-38.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2022/09/image-38.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/image-38.png 2000w" sizes="(min-width: 720px) 720px" width="2000" height="643" loading="lazy"></figure><h3 id="nodejs-npm"><strong><strong>NodeJS/NPM</strong></strong></h3><p>Usaremos NodeJS para o projeto. Se você não o tiver instalado, siga este <a href="https://www.freecodecamp.org/news/how-to-install-node-in-your-machines-macos-linux-windows/">tutorial</a> simples do freeCodeCamp (texto em inglês).</p><h2 id="inicialize-o-projeto"><strong><strong>Ini</strong>c<strong>ialize </strong>o<strong> projet</strong>o</strong></h2><p>No seu terminal, execute este comando para criar um novo diretório para seu projeto:</p><pre><code>mkdir nft-project
cd nft-project</code></pre><p>Agora, vamos criar outro diretório, ethereum/, dentro de nft-project/ e inicializá-lo com o <a href="https://hardhat.org/getting-started/">Hardhat</a>. O Hardhat é uma ferramenta de desenvolvimento que facilita a implantação e o teste do seu software Ethereum.</p><pre><code>mkdir ethereum
cd ethereum
npm init
</code></pre><p>Responda as perguntas como quiser. Em seguida, execute esses comandos para criar um projeto Hardhat:</p><pre><code>npm install --save-dev hardhat
npx hardhat</code></pre><p>Você verá este prompt:</p><pre><code>888    888                      888 888               888
888    888                      888 888               888
888    888                      888 888               888
8888888888  8888b.  888d888 .d88888 88888b.   8888b.  888888
888    888     "88b 888P"  d88" 888 888 "88b     "88b 888
888    888 .d888888 888    888  888 888  888 .d888888 888
888    888 888  888 888    Y88b 888 888  888 888  888 Y88b.
888    888 "Y888888 888     "Y88888 888  888 "Y888888  "Y888

Welcome to Hardhat v2.0.8

? What do you want to do? …
  Create a sample project
❯ Create an empty hardhat.config.js
  Quit</code></pre><p>Selecione <em>Create an empty hardhat.config.js</em>. Isso gerará um arquivo vazio <code>hardhat.config.js</code> que atualizaremos posteriormente.</p><p>Para a aplicação da web, usaremos o Next.js para inicializar uma aplicação da web totalmente funcional. Volte para o diretório raiz <code>nft-project/</code> e inicialize um <em>boilerplate</em> do Next.js app, chamado <code>web</code>:</p><pre><code>cd ..
mkdir web
cd web
npx create-next-app@latest</code></pre><p>Seu projeto, agora, tem esta aparência:</p><pre><code>nft-project/
	ethereum/
	web/</code></pre><p>Ótimo! Estamos prontos para entrar na parte da programação de verdade.</p><h2 id="como-definir-nossas-vari-veis-env"><strong>Como definir nossas variáveis<strong> .env </strong></strong></h2><p>Você se lembra da chave de Alchemy que pegamos em nosso projeto de teste anterior? Nós a usaremos junto com as chaves públicas e privadas da nossa conta Metamask para interagir com o blockchain.</p><p>Execute os comandos a seguir, crie um arquivo chamado<code>.env</code> &nbsp;dentro do seu diretório <code>ethereum/</code>, e instale o <a href="https://www.npmjs.com/package/dotenv">dotenv</a>. Vamos usá-los mais tarde.</p><pre><code>cd ..
cd ethereum
touch .env
npm install dotenv --save</code></pre><p>Para o seu arquivo <code>.env</code>, &nbsp;coloque a chave que você exportou do Alchemy e <a href="https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key">siga estas instruções</a> para pegar a chave privada do seu Metamask.</p><p>Aqui está seu arquivo .env :</p><pre><code>DEV_API_URL = YOUR_ALCHEMY_KEY
PRIVATE_KEY = YOUR_METAMASK_PRIVATE_KEY
PUBLIC_KEY = YOUR_METAMASK_ADDRESS</code></pre><h2 id="o-smart-contract-para-nft">O Smart Contract para NFT</h2><p>Na pasta <code>ethereum/</code> crie mais dois diretórios: <code>contracts</code> e <code>scripts</code>. Um projeto hardhat simples contém essas pastas. </p><ul><li><code>contracts/</code> contém os arquivos de origem de seus contratos</li><li><code>scripts/</code> contém os scripts para implantar e cunhar nossos NFTs</li></ul><pre><code>mkdir contracts
mkdir scripts
</code></pre><p>Então, instale o OpenZeppelin. O <a href="https://docs.openzeppelin.com/contracts/4.x/">OpenZeppelin Contract</a> é uma biblioteca de código aberto com código reutilizável pré-testado para facilitar o desenvolvimento dos Smart Contracts (contratos inteligentes).</p><pre><code>npm install @openzeppelin/contracts</code></pre><p>Por fim, escreveremos o Smart Contract para o nosso NFT. Navegue até o diretório de contratos e crie um arquivo intitulado <code>EmotionalShapes.sol</code>. &nbsp;Você pode nomear seus NFTs como achar melhor.</p><p>A extensão <code>.sol</code> &nbsp;refere-se à linguagem Solidity, que usaremos para programar nosso Smart Contract. Escreveremos apenas 14 linhas de código com o Solidity. Então, não se preocupe se você ainda não viu isso antes.<br>Comece com <a href="https://ethereum.org/en/developers/docs/smart-contracts/languages/">este artigo</a> para saber mais sobre as linguagens de<strong> </strong>Smart Contract<strong>.</strong> Você também pode pular diretamente <a href="https://reference.auditless.com/cheatsheet/">para esta ficha informativa</a> do Solidity, que contém a sintaxe principal.</p><pre><code>cd contracts
touch EmotionalShapes.sol</code></pre><p>Este é o nosso Smart Contract:</p><pre><code class="language-solidity">// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract EmotionalShapes is ERC721 {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIdCounter;

    constructor() ERC721("EmotionalShapes", "ESS") {}

    function _baseURI() internal pure override returns (string memory) {
        return "YOUR_API_URL/api/erc721/";
    }

    function mint(address to)
        public returns (uint256)
    {
        require(_tokenIdCounter.current() &lt; 3); 
        _tokenIdCounter.increment();
        _safeMint(to, _tokenIdCounter.current());

        return _tokenIdCounter.current();
    }
}
</code></pre><p>Vamos passar pelo código e entender o que está acontecendo.</p><ol><li>Na parte superior do arquivo, especificamos qual módulo do OpenZeppelin importar. Precisamos do contrato ERC721, pois é a 'base' do nosso Smart Contract. Ele já implementou todos os métodos especificados no <a href="https://eips.ethereum.org/EIPS/eip-721">EIP-721</a> para que possamos usá-lo com segurança.</li><li>Um contador é útil para gerar ids incrementais para nossos NFTs. Nós nomeamos a variável <code>_tokenIdCounter</code></li><li>No construtor, inicializamos nosso ERC721 com seu nome e seu símbolo. Eu escolhi EmotionalShapes e ESS.</li><li>Substituímos a função padrão <em><code>baseURI</code>, </em>retornando a nossa. Vamos começar a construir isso logo após. Em resumo, é o URL que será adicionado como 'prefixo' a todos os nossos tokenURIs. No exemplo acima, os metadados de nossos NFTs ficarão em um arquivo JSON em<em> </em><code>URL_DA_SUA_API/<a href="https://e110-99-121-58-31.ngrok.io/api/erc721/">api/erc721/</a>1</code>. &nbsp;</li><li>Implementamos a função 'mint'. É a função que permite publicar uma instância desse Smart Contract no blockchain. Eu exigi que a variável <code>_tokenIdCounter</code> fosse menor que 3, pois criarei apenas três instâncias do meu NFT. Você pode remover isso se quiser cunhar mais.</li><li>Finalmente, dentro da função mint, incrementamos a variável <code>_tokenIdCounter</code> em 1. Então, nosso id será 1, seguido de 2, depois de 3. Então, chamamos a função fornecida pelo OpenZeppelin <code>_safeMint</code> para publicar o token.</li></ol><p>Não se preocupe se você se sentir perdido. Você pode participar de um workshop liderado por voluntários do freeCodeCamp, onde convidamos desenvolvedores de níveis de habilidade semelhantes para construir coisas juntos, incluindo esse projeto de NFT.</p><p>Os eventos são gratuitos e remotos, então você pode tirar qualquer dúvida diretamente. Você pode se registrar <a href="https://equia.io/">aqui</a>. As vagas são limitadas, então você será convidado para os próximos eventos disponíveis.</p><h2 id="como-criar-os-metadados-para-nosso-nft"><strong>Como criar os<strong> </strong>m<strong>etada</strong>dos<strong> </strong>para nosso<strong> NFT</strong></strong></h2><p>Como mencionado anteriormente, existem três maneiras principais de armazenar seu tokenURI. Construiremos um endpoint de API simples <strong>que resolve as informações do nosso NFT como JSON.</strong></p><p>Nosso projeto do Next.js nos oferece uma maneira prática de desenvolver rotas de API. Vá para a pasta <code>web/</code>, encontre a pasta <code>api/</code> dentro da pasta <code>pages/</code> &nbsp;e faça nossa rota dinâmica <code>[id].js</code> em uma pasta <code>erc721/</code> &nbsp;(leia mais sobre roteamento &nbsp;<a href="https://www.freecodecamp.org/news/p/18513919-9e93-4ab3-9f52-2448aafa8835/develop%20API%20routes">aqui</a>):</p><pre><code class="language-javascript">// web/pages/api/erc721/[id].js

const metadata = {
  1: {
    attributes: [
      {
        trait_type: "Shape",
        value: "Circle",
      },
      {
        trait_type: "Mood",
        value: "Sad",
      },
    ],
    description: "A sad circle.",
    image: "https://i.imgur.com/Qkw9N0A.jpeg",
    name: "Sad Circle",
  },
  2: {
    attributes: [
      {
        trait_type: "Shape",
        value: "Rectangle",
      },
      {
        trait_type: "Mood",
        value: "Angry",
      },
    ],
    description: "An angry rectangle.",
    image: "https://i.imgur.com/SMneO6k.jpeg",
    name: "Angry Rectangle",
  },
  3: {
    attributes: [
      {
        trait_type: "Shape",
        value: "Triangle",
      },
      {
        trait_type: "Mood",
        value: "Bored",
      },
    ],
    description: "An bored triangle.",
    image: "https://i.imgur.com/hMVRFoJ.jpeg",
    name: "Bored Triangle",
  },
};

export default function handler(req, res) {
  res.status(200).json(metadata[req.query.id] || {});
}</code></pre><p>Para fins deste projeto, tornei o código o mais fácil de entender possível. Isso definitivamente não é adequado para produção (por favor, não use um URL do Imgur para o seu NFT). Certifique-se de definir os metadados para todos os NFTs que você pretende cunhar.</p><p>Agora, vá para o diretório da web e inicie seu aplicativo Next.js com este comando:</p><pre><code>npm run dev</code></pre><p>Sua aplicação deve ser executada no localhost:3000. Para garantir que nosso endpoint funcione, vá para <a href="http://localhost:3000/api/erc721/1">http://localhost:3000/api/erc721/1</a> e ele deve ser resolvido com um objeto JSON dos metadados do seu primeiro NFT.</p><h2 id="como-expor-os-metadados-para-nosso-nft">Como expor os metadados para nosso NFT</h2><p>Como nossa aplicação está hospedada localmente, outras aplicações não podem acessá-la. Usando uma ferramenta como o <a href="https://ngrok.com/">ngrok</a>, podemos expor nosso host local a um URL acessível publicamente.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/image-39.png" class="kg-image" alt="image-39" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/image-39.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/09/image-39.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2022/09/image-39.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/image-39.png 2000w" sizes="(min-width: 720px) 720px" width="2000" height="1057" loading="lazy"></figure><ol><li>Vá para <a href="https://ngrok.com/">ngrok.com</a> e complete o processo de registro</li><li>Descompacte o pacote baixado</li><li>No seu terminal, certifique-se que você executou o comando <code>cd</code> na pasta que você descomprimiu seu pacote do ngrok</li><li>Siga as instruções do painel de controle e execute </li></ol><pre><code>./ngrok authtoken SEU_TOKEN_DE_AUTENTICACAO</code></pre><p>5. &nbsp;Então, execute este comando para criar um túnel para sua aplicação da web, hospedada em localhost:3000</p><pre><code>./ngrok http 3000</code></pre><p>6. &nbsp;Você está quase lá! Em seu terminal, você deverá ver algo como isto:</p><pre><code>ngrok by @inconshreveable                                                                            (Ctrl+C to quit)
                                                                                                                     
Session Status                online                                                                                 
Account                       YOUR_ACCOUNT (Plan: Free)                                                                       
Version                       2.3.40                                                                                 
Region                        United States (us)                                                                     
Web Interface                 http://127.0.0.1:4040                                                                  
Forwarding                    http://SEU_ENDERECO_DO_NGROK -&gt; http://localhost:3000                             
Forwarding                    https://SEU_ENDERECO_DO_NGROK -&gt; http://localhost:3000                             </code></pre><p>Vá para &nbsp;<code>SEU_ENDERECO_DO_NGROK/api/erc721/1</code> para ter certeza que o endpoint funciona corretamente.</p><h2 id="como-fazer-o-deploy-de-nosso-nft"><strong>Como fazer o d<strong>eploy </strong>de nosso<strong> NFT</strong></strong></h2><p>Agora que fizemos todo o trabalho de base (ufa), vamos voltar para nossa pasta e &nbsp;<code>ethereum/</code> e nos preparar para implantar nosso &nbsp;NFT.</p><p>Mude a função <code>_baseURI</code> no seu arquivo <code>ethreum/contracts/NOME_DO_SEU_NFT.sol</code> para retornar ao seu endereço do ngrok.</p><pre><code>// ethereum/conrtacts/EmotionalShapes.sol

contract EmotionalShapes is ERC721 {
...
	function _baseURI() internal pure override returns (string memory) {
		return "https://SEU_ENDERECO_DO_NGROK/api/erc721/";
	}
...
}</code></pre><p>Para fazer o deploy do nosso NFT, precisamos primeiro <a href="https://hardhat.org/guides/compile-contracts.html">compilá-lo usando Hardhat</a>. Para que o processo seja mais fácil, instalaremos o <a href="https://docs.ethers.io/v5/">ethers.js</a>.</p><pre><code>npm install @nomiclabs/hardhat-ethers --save-dev</code></pre><p>Vamos atualizar nosso hardhat.config.js:</p><pre><code>require("dotenv").config();
require("@nomiclabs/hardhat-ethers");

module.exports = {
  solidity: "0.8.0",
  defaultNetwork: "ropsten",
  networks: {
    hardhat: {},
    ropsten: {
      url: process.env.DEV_API_URL,
      accounts: [`0x${process.env.PRIVATE_KEY}`],
    },
  },
};
</code></pre><p>Para saber mais sobre a configuração do arquivo hardhat dê uma olhada na sua &nbsp;<a href="https://hardhat.org/config/">documentação</a>. Configuramos a rede ropsten com nosso URL do Alchemy e fornecemos a chave privada de sua conta do metamask.</p><p>Finalmente, execute:</p><pre><code>npx hardhat compile</code></pre><p>Isto permite que o hardhat gere dois arquivos por contrato compilado. Devemos ver uma pasta recém-criada <code>artifacts/</code>, que contém seus contratos compilados na pasta <code>contracts/</code>. Para saber mais sobre como isso funciona, leia <a href="https://hardhat.org/guides/compile-contracts.html">este tutorial</a> da equipe do Hardhat.</p><p>Agora, vamos escrever um script para finalmente implantar nosso NFT na rede de teste. Na pasta <code>scripts/</code> , crie um arquivo chamado <code>deploy.js</code>.</p><pre><code class="language-javascript">// ethereum/scripts/deploy.js

async function main() {
  const EmotionalShapes = await ethers.getContractFactory("EmotionalShapes");
  const emotionalShapes = await EmotionalShapes.deploy();

  console.log("EmotionalShapes deployed:", emotionalShapes.address);
}

main()
  .then(() =&gt; process.exit(0))
  .catch((error) =&gt; {
    console.error(error);
    process.exit(1);
  });
</code></pre><p>Este código é &nbsp;inspirado pelo <a href="https://hardhat.org/guides/deploying.html">tutorial de deploy do hardhat</a>.</p><blockquote>Uma <code>ContractFactory</code> em ethers.js é uma abstração usada para implantar novos contratos inteligentes, então <code>EmotionalShapes</code> aqui é uma factory para instâncias do nosso contrato de token. Invocar <code>deploy()</code> na <code>ContractFactory</code> iniciará o deploy e retornará uma <code>Promise</code> que então é resolvida para <code>Contract</code>. Este é o objeto que possui um método para cada uma de suas funções de contrato inteligente.</blockquote><h3 id="como-visualizar-o-nft-no-blockchain">Como visualizar o NFT no blockchain</h3><p>Execute o script de deploy:</p><pre><code>node ./scripts/deploy.js</code></pre><p>Você deverá ver em seu terminal <code>EmotionalShapes deployed: UM_ENDERECO</code>. Este é o endereço onde seu Smart Contract está implantado na rede de teste ropsten.</p><p>Se você for para <code>https://ropsten.etherscan.io/address/UM_ENDERECO</code>, você deve ver seu NFT recém-implantado. Sim! Você conseguiu!</p><p>Se você estiver confuso em algum ponto do tutorial ou se sentindo perdido, novamente, pode <a href="https://equia.io/">participar de nossos workshops ao vivo</a>, onde construiremos este projeto juntos em uma chamada de Zoom.</p><h2 id="como-cunhar-seu-nft">Como cunhar seu NFT</h2><p>Agora que você fez o deploy do seu NFT, é hora de cunhá-lo para você! Crie um novo arquivo chamado <code>mint.js</code> na sua pasta <code>scripts/</code>.Usaremos o ethers.js para nos auxiliar.</p><p>Comece adicionando o pacote <code>ethers.js</code> :</p><pre><code>npm install --save ethers</code></pre><p>Em seguida, preencha o arquivo <code>mint.js</code> :</p><pre><code class="language-javascript">require("dotenv").config();
const { ethers } = require("ethers");

const contract = require("../artifacts/contracts/EmotionalShapes.sol/EmotionalShapes.json");
const contractInterface = contract.abi;

// https://docs.ethers.io/v5/api/providers
const provider = ethers.getDefaultProvider("ropsten", {
  alchemy: process.env.DEV_API_URL,
});

// https://docs.ethers.io/v5/api/signer/#Wallet
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);

//https://docs.ethers.io/v5/api/contract/contract
const emotionalShapes = new ethers.Contract(
  YOUR_NFT_ADDRESS,
  contractInterface,
  wallet
);

const main = () =&gt; {
  emotionalShapes
    .mint(process.env.PUBLIC_KEY)
    .then((transaction) =&gt; console.log(transaction))
    .catch((e) =&gt; console.log("something went wrong", e));
};

main();
</code></pre><p>Eu deixei comentários para onde você pode encontrar mais informações sobre os diferentes métodos. Primeiro, pegamos a interface do contrato (ABI). Na ethereum.org, vemos que:</p><blockquote>Uma interface binária de aplicativo, ou ABI, é a maneira padrão de interagir com contratos no ecossistema Ethereum, tanto de fora do blockchain quanto para interações contrato a contrato.</blockquote><p>Sua ABI define como os outros interagem com seu contrato. Então, criamos nosso provedor com Alchemy (lembre-se dos node-as-a-service). Por fim, inicializamos nossa carteira com nossa chave privada.</p><p>A função &nbsp;<code>main()</code> executa o método <code>mint</code> no Smart Contract que acabamos de implementar. O método <code>mint</code> recebe apenas um parâmetro, <code>to</code>, que indica o receptor do token. Como estamos cunhando para nós mesmos, colocamos o endereço público da nossa conta Metamask.</p><p>Se tudo correr bem, você deverá ver a transação registrada em seu terminal. Pegue a propriedade <code>hash</code> vá para <code>https://ropsten.etherscan.io/tx/SEU_HASH</code>. Você deve ver a transação de cunhagem lá!</p><h2 id="como-visualizar-o-nft-em-sua-carteira-metamask">Como visualizar o NFT em sua carteira Metamask</h2><p>Você precisa começar baixando a versão móvel do Metamask. Em seguida, faça login na sua conta.</p><p>Você deve ver uma guia de NFTs junto com um botão <em>Add NFT</em>. Clique no botão e insira o endereço do seu Smart Contract junto com os ids que você cunhou. Se você seguiu o tutorial, você deve começar com um id de <code>1</code>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/IMG_0376.jpeg" class="kg-image" alt="IMG_0376" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/IMG_0376.jpeg 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/09/IMG_0376.jpeg 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/IMG_0376.jpeg 1284w" sizes="(min-width: 720px) 720px" width="1284" height="2778" loading="lazy"><figcaption>Veja os NFTs em sua carteira do Metamask</figcaption></figure><h2 id="conclus-o"><strong><strong>Conclus</strong>ão</strong></h2><p>Parabéns! Você acabou de cunhar seu próprio NFT. Na próxima parte do projeto, construiremos o aplicativo em React para o front-end que interaja com nosso contrato. O objetivo final é construir um aplicativo da web totalmente funcional onde você possa vender seus próprios NFTs.</p><p>Por fim, você pode &nbsp;<a href="https://equia.io/">participar de nossos workshops</a> ao vivo com voluntários do freeCodeCamp, onde construiremos este projeto junto com outros.</p><p>Os eventos são gratuitos para todos em qualquer lugar do mundo e os convites são enviados por ordem de chegada. Se você gostaria de liderar os workshops, envie uma mensagem <a href="https://twitter.com/aly4alyssa">no Twitter</a>, adoraríamos contar com você! Também organizamos outros tipos de eventos como feiras de contratação e encontros sociais.</p><p>Gostaria de saber o que você quer criar. Os NFTs ainda estão em seus estágios iniciais e novas ideias são mais do que bem-vindas. Mal posso esperar para ver que ideia maluca você tem!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Como criar um NFT e renderizá-lo no Marketplace da OpenSea ]]>
                </title>
                <description>
                    <![CDATA[ Neste artigo, eu vou mostrar para você como fazer um NFT sem nenhuma habilidade em engenharia de software. Depois, vamos aprender como fazer NFTs customizáveis ilimitados com o Brownie [https://eth-brownie.readthedocs.io/en/stable/], Python [https://www.python.org/] e o Chainlink [https://docs.chain.link/docs] (todos os links em inglês). Então, veremos como renderizar e vender nossa criação no ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-criar-um-nft-e-renderiza-lo-no-marketplace-da-opensea/</link>
                <guid isPermaLink="false">61fbd7f753557304fa19e91b</guid>
                
                    <category>
                        <![CDATA[ Blockchain ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Gabriel Lima ]]>
                </dc:creator>
                <pubDate>Sat, 09 Apr 2022 15:06:09 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2022/04/Advanced-NFT-Deployment---1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/how-to-make-an-nft-and-render-on-opensea-marketplace/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Make an NFT and Render it on the OpenSea Marketplace</a>
      </p><p>Neste artigo, eu vou mostrar para você como fazer um NFT sem nenhuma habilidade em engenharia de software. Depois, vamos aprender como fazer NFTs customizáveis ilimitados com o <a href="https://eth-brownie.readthedocs.io/en/stable/">Brownie</a>, <a href="https://www.python.org/">Python</a> e o <a href="https://docs.chain.link/docs">Chainlink</a> (todos os links em inglês). Então, veremos como renderizar e vender nossa criação no Marketplace de NFTs da <a href="https://opensea.io/">OpenSea</a>.</p><p>Se estiver procurando por um tutorial que use o Truffle, JavaScript e alguns personagens medievais legais, dê uma olhada em como <a href="https://blog.chain.link/build-deploy-and-sell-your-own-dynamic-nft/">Construir, Implantar e Vender seu NFT aqui</a> (em inglês).</p><h2 id="o-que-um-nft"><strong>O que é um NFT?</strong></h2><p><a href="https://eips.ethereum.org/EIPS/eip-721" rel="noopener">NFTs</a> (do inglês <em>non-fungible tokens</em>, ou &nbsp;"tokens não fungíveis") podem ser resumidos em uma palavra: "únicos". &nbsp;Eles são contratos inteligentes implantados em uma <em>blockchain</em> que representam algo único.</p><h3 id="erc20-x-erc721"><strong>ERC20 x ERC721</strong></h3><p>NFTs são tokens padrão de <em>blockchain,</em> similares ao <a href="https://www.investopedia.com/news/what-erc20-and-what-does-it-mean-ethereum/">ERC20</a> (em inglês), como AAVE, SNC e LINK (tecnicamente, um ERC677). ERC20s são tokens "fungíveis" o que significa que são "substituíveis" ou "intercambiáveis".</p><p>Por exemplo, a nota de dez reais vai valer R$ 10,00, não importando qual nota você use, desde que ela seja <em>uma nota</em> de dez reais. O código na nota pode até ser diferente, mas as notas são intercambiáveis e elas vão valer dez reais independentemente de outras coisas.</p><p>NFTs, por outro lado, são "não fungíveis". Eles seguem seu próprio padrão de token, o <a href="https://eips.ethereum.org/EIPS/eip-721">ERC721</a>. Por exemplo, a Mona Lisa é "não fungível". Mesmo que alguém faça uma cópia dela, sempre vai haver apenas uma Mona Lisa. Se a Mona Lisa tivesse sido criada em uma <em>blockchain</em>, ela seria um NFT.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/04/image-145-1.png" class="kg-image" alt="image-145-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/04/image-145-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/04/image-145-1.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/04/image-145-1.png 1200w" sizes="(min-width: 720px) 720px" width="1200" height="1788" loading="lazy"><figcaption>Imagem original retirada da <a href="https://pt.wikipedia.org/wiki/Mona_Lisa">Wikipédia</a></figcaption></figure><h2 id="para-que-serve-um-nft"><strong>Para que serve um NFT?</strong></h2><p>NFTs agregam valor para os criadores, artistas, designers de jogos e outros por terem um histórico permanente de implantação armazenado <em>on-chain.</em></p><p>Você sempre saberá quem criou o NFT, quem o comprou, de onde ele veio e mais, o que dá a eles muito valor, mais do que arte tradicional. Na arte tradicional, pode ser bem difícil discernir o que é falso, enquanto um histórico <em>on-chain</em> é facilmente rastreável.</p><p>Como os contratos inteligentes e os NFTs são 100% programáveis, NFTs podem também ter <em>royalties</em> e qualquer outra funcionalidade embutida. Recompensar os artistas sempre foi um problema, dado que um trabalho artístico geralmente é apresentado sem nenhuma atribuição, como ouvir uma música no parque.</p><p>Mais e mais artistas e engenheiros estão aproveitando desse valor agregado, porque finalmente é uma boa maneira de recompensar os artistas por seu trabalho. Mais que isso, os NFTs são maneiras divertidas de botar para quebrar com sua criatividade e se tornar um colecionador em um mundo digital.</p><h3 id="o-valor-dos-nfts"><strong>O valor dos NFTs</strong></h3><p><br>Os NFTs percorreram um longo caminho e continuamos vendo recordes de vendas de NFTs, como "Everydays: The First 5.000 Days" sendo vendido por US$ 69,3 milhões.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/04/Screen-Shot-2021-03-31-at-9.48.19-AM.png" class="kg-image" alt="Screen-Shot-2021-03-31-at-9.48.19-AM" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/04/Screen-Shot-2021-03-31-at-9.48.19-AM.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/04/Screen-Shot-2021-03-31-at-9.48.19-AM.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/04/Screen-Shot-2021-03-31-at-9.48.19-AM.png 1190w" sizes="(min-width: 720px) 720px" width="1190" height="998" loading="lazy"><figcaption>Imagem retirada do <a href="https://twitter.com/ChristiesInc/status/1361670588608176128">Twitter</a></figcaption></figure><p>Então, existe um grande valor aqui, além de ser divertido, dinâmico e uma forma engajadora de criar arte em um mundo digital e aprender sobre criação de um contrato inteligente. Agora, eu vou ensinar a você tudo o que precisa saber sobre criar NFTs.</p><h2 id="como-criar-um-nft"><strong>Como criar um NFT</strong></h2><h3 id="o-que-n-o-vamos-ensinar"><strong>O que não vamos ensinar</strong></h3><p>A maneira mais fácil de fazer um NFT é ir a uma plataforma, como a <a href="https://opensea.io">Opensea</a>, a <a href="https://rarible.com">Rarible</a> ou a <a href="https://mintable.app/">Mintible</a>, e seguir o seu passo a passo para a implantação na plataforma escolhida.</p><p>Você pode seguir por esse caminho. No entanto, você pode acabar ligado à plataforma de alguma forma e ficará preso na funcionalidade que a plataforma tiver. Desse modo, você não poderá alcançar a personalização ilimitada nem utilizar realmente qualquer uma das vantagens que os NFTs têm. Mas se você for um engenheiro de software principiante, ou se não for muito técnico, esse caminho servirá para você.</p><p>Se você procura se tornar um engenheiro de software melhor, aprender um pouco sobre Solidity e ter o poder de criar algo com criatividade ilimitada, siga com a leitura!</p><p>Se você é novo com Solidity, não se preocupe. Também passaremos pelo básico.</p><h2 id="como-criar-um-nft-com-customiza-o-ilimitada"><strong>Como criar um NFT com customização Ilimitada</strong></h2><p>Vamos começar com o <a href="https://github.com/PatrickAlphaC/nft-mix">NFT Brownie Mix</a>. Esse é um repositório em desenvolvimento com muito código <em>boilerplate.</em></p><h3 id="pr-requisitos"><strong>Pré-requisitos</strong></h3><p>Precisaremos de alguns programas instalados antes de começar</p><ul><li><a href="https://www.python.org/downloads/">Python</a></li><li><a href="https://nodejs.org/pt-br/download/">Nodejs</a> e npm</li><li><a href="https://metamask.io/">Metamask</a></li></ul><p>Se você não está familiarizado com o Metamask, você pode seguir <a href="https://docs.chain.link/docs/deploy-your-first-contract/#install-and-fund-your-metamask-wallet">esse tutorial</a> (em inglês) para configurá-lo.</p><h3 id="rinkeby-testnet-eth-e-link"><strong>Rinkeby Testnet ETH e LINK</strong></h3><p>Estaremos trabalhando também com o Rinkeby Ethereum Testnet para realizar a implantação dos nossos contratos em uma blockchain real, de graça!</p><p><em>Testnets</em> são formas excelentes de testar como os contratos se comportam no mundo real.</p><p>Precisaremos do <em>Rinkeby ETH</em> e do <em>Rinkeby LINK</em>, que conseguimos gratuitamente nos links da <a href="https://docs.chain.link/docs/link-token-contracts/#rinkeby">documentação do Chainlink</a> (em inglês)</p><p>Também precisaremos adicionar o token do <em>Rinkeby LINK</em> na nossa <em>metamask, o </em>que podemos fazer seguindo a <a href="https://docs.chain.link/docs/acquire-link/">documentação de como conseguir o LINK</a> (em inglês).</p><p>Se você continuar confuso, <a href="https://www.youtube.com/watch?v=4ZgFijd02Jo">você pode usar este vídeo como guia</a> (em inglês), apenas certifique-se de usar o <em>Rinkerby</em> ao invés do Ropsten.</p><p>Quando trabalhamos com uma plataforma de contratos inteligentes, como a Ethereum, precisamos pagar um pouco de ETH. Quando retiramos dados <em>off-chain</em> precisamos pagar com um pouco de LINK. Por este motivo, nós precisamos dos testnets Link e ETH.</p><p>Maravilha, agora vamos mergulhar. <a href="https://testnets.opensea.io/assets/0x8acb7ca932892eb83e4411b59309d44dddbc4cdf/0">Este é o NFT que vamos implantar na OpenSea.</a></p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/04/Screen-Shot-2021-03-31-at-10.58.35-AM.png" class="kg-image" alt="Screen-Shot-2021-03-31-at-10.58.35-AM" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/04/Screen-Shot-2021-03-31-at-10.58.35-AM.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/04/Screen-Shot-2021-03-31-at-10.58.35-AM.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2022/04/Screen-Shot-2021-03-31-at-10.58.35-AM.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/04/Screen-Shot-2021-03-31-at-10.58.35-AM.png 2000w" sizes="(min-width: 1200px) 1200px" width="2000" height="1063" loading="lazy"></figure><h3 id="come-ando"><strong>Começando</strong></h3><pre><code class="language-bash">git clone https://github.com/PatrickAlphaC/nft-mix
cd nft-mix</code></pre><p>Ótimo! Agora, precisamos instalar o <code>ganache-cli</code> e o <code>eth-brownie</code>.</p><pre><code>pip install eth-brownie
npm install -g ganache-cli</code></pre><p>Então, podemos <a href="https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html">configurar nossas variáveis de ambiente</a> (em inglês). Se você não é familiarizado com variáveis de ambiente, pode apenas adicioná-las no seu arquivo <code>.env</code> e executar:</p><p><code>source .env</code></p><p>Deve existir um arquivo <code>.env</code> no repositório que você acabou de clonar com as variáveis de ambiente comentadas. Retire-as dos comentários para usá-las!</p><p>Você vai precisar de um <code>WEB3_INFURA_PROJECT_ID</code> e de uma <code>PRIVATE_KEY</code>. O <code>WEB3_INFURA_PROJECT_ID</code> pode ser encontrado ao se cadastrar com uma conta gratuita no <a href="https://infura.io">Infura</a>. Assim, teremos uma maneira de enviar as transações para a <em>blockchain</em>.</p><p>Também vamos precisar de uma <em>private key</em>, que você consegue pegar em sua Metamask. Clique nos 3 pontinhos, vá em <code>Account Details</code> e depois em <code>Export Private Key</code>. NÃO compartilhe essa chave com ninguém se você colocar dinheiro de verdade nela!</p><figure class="kg-card kg-code-card"><pre><code>export PRIVATE_KEY=YOUR_KEY_HERE
export WEB3_INFURA_PROJECT_ID=YOUR_PROJECT_ID_HERE</code></pre><figcaption>.env</figcaption></figure><p>Agora, podemos implantar nosso contrato NFT e criar nosso primeiro colecionável com os dois comandos a seguir.</p><pre><code>brownie run scripts/simple_collectible/deploy_simple.py --network rinkeby
brownie run scripts/simple_collectible/create_collectible.py --network rinkeby</code></pre><p>O primeiro script implanta nosso contrato NFT na <em>blockchain</em> da <em>Rinkerby, </em>e o segundo cria nosso colecionável.</p><p>Você acabou de implantar seu primeiro contrato inteligente!</p><p>Por enquanto, ele não faz muita coisa, mas não se preocupe – vou mostrar para você como renderizá-lo na OpenSea na parte avançada desse tutorial. Mas, antes, vamos olhar para o padrão de token ERC721.</p><h2 id="o-padr-o-de-token-erc721"><strong>O padrão de token ERC721</strong></h2><p>Vamos dar uma olhada no contrato que acabamos de implantar no arquivo <code>SimpleCollectible.sol</code>.</p><pre><code class="language-javascript">// SPDX-License-Identifier: MIT
pragma solidity 0.6.6;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

contract SimpleCollectible is ERC721 {
    uint256 public tokenCounter;
    constructor () public ERC721 ("Dogie", "DOG"){
        tokenCounter = 0;
    }

    function createCollectible(string memory tokenURI) public returns (uint256) {
        uint256 newItemId = tokenCounter;
        _safeMint(msg.sender, newItemId);
        _setTokenURI(newItemId, tokenURI);
        tokenCounter = tokenCounter + 1;
        return newItemId;
    }

}
</code></pre><p>Estamos usando o pacote <a href="https://github.com/OpenZeppelin/openzeppelin-contracts">OpenZeppelin</a> (em inglês) para o token ERC721. Esse pacote que importamos nos permite usar todas as funções típicas de um token ERC721. Isso define todas as funcionalidades que nossos tokens vão ter, como <code>transfer</code>, que move tokens para novos usuários, <code>safeMint</code> que cria novos tokens e mais.</p><p>Você pode encontrar todas as funções que são fornecidas ao nosso contrato lendo o <a href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol">Contrato de Token ERC721 OpenZeppelin.</a> Nosso contrato herda essas funções nessa linha:</p><pre><code>contract SimpleCollectible is ERC721 {</code></pre><p>É assim que a <em>Solidity</em> trabalha com herança. Quando nós implantamos um contrato, o <code>constructor</code> é automaticamente chamado e recebe alguns parâmetros.</p><pre><code>constructor () public ERC721 ("Dogie", "DOG"){
        tokenCounter = 0;
    }</code></pre><p>Também usamos o construtor do <code>ERC721</code> no nosso construtor. Temos que dar a ele um nome e um símbolo. No nosso caso, é "Dogie"e "DOG". Isso significa que todos os NFTS criados serão do tipo Dogie/DOG.</p><p>É como todos os Pokémons nas cartas de pokémons. Eles no final são pokémons, ou todo jogador de baseball nas cartas colecionáveis (trading cards) continuam jogadores de baseball. Cada jogador é único, mas eles continuam sendo jogadores de baseball. Nós estamos apenas usando o tipo <code>DOG</code>.</p><p>Nós temos um <code>tokenCounter</code> no topo que conta quantos NFTs já criamos daquele tipo. Cada novo token ganha um <code>tokenId</code> baseado no <code>tokenCounter</code> atual.</p><p>Atualmente, nós podemos criar um NFT com a função <code>createCollectible</code>. É ela que chamamos no nosso script <code>create_collectible.py</code>.</p><pre><code>function createCollectible(string memory tokenURI) public returns (uint256) {
        uint256 newItemId = tokenCounter;
        _safeMint(msg.sender, newItemId);
        _setTokenURI(newItemId, tokenURI);
        tokenCounter = tokenCounter + 1;
        return newItemId;
    }</code></pre><p>A função <code>_safeMint</code> cria o novo NFT e o atribui a quem chamou <code>createdCollectible</code>, também conhecido como<code>msg.sender</code>, com um <code>newItemId</code> derivado de <code>tokenCounter</code>. É assim que podemos acompanhar quem é proprietário de quê, verificando o proprietário do <code>tokenId</code>.</p><p>Você vai perceber que também chamamos a função <code>_setTokenURI</code>. Vamos conversar sobre ela.</p><h2 id="o-que-s-o-metadados-de-nft-e-tokenuri"><strong>O que são metadados de NFT e tokenURI?</strong></h2><p>Quando os contratos inteligentes estavam sendo criados e os NFTs estavam sendo criados, as pessoas rapidamente perceberam que é beeeeeem caro implantar muitos dados na <em>blockchain</em>. Imagens pequenas de um KB podem facilmente <a href="https://ethereum.stackexchange.com/questions/872/what-is-the-cost-to-store-1kb-10kb-100kb-worth-of-data-into-the-ethereum-block/896#896">custar mais de 1 milhão de dólares para guardar</a> (em inglês).</p><p>Isso é claramente um problema para os NFTs, já que, ao ser o proprietário de arte criativa, você tem que guardar essa informação em algum lugar. Eles também queriam uma maneira mais leve de guardar os atributos sobre NFTs – e é aqui que &nbsp;os metadados e o tokenURI entram em ação.</p><h3 id="tokenuri"><strong>TokenURI</strong></h3><p>O <code>tokenURI</code> em um NFT é um identificador único da "aparência" daquele token. Um URI pode ser uma chamada HTTPS para uma API, um hash IPFS, ou <a href="https://danielmiessler.com/study/difference-between-uri-url/">qualquer outra coisa</a> exclusiva.</p><p>Eles seguem um padrão de mostrar os metadados que têm essa aparência:</p><pre><code class="language-json">{
    "name": "name",
    "description": "description",
    "image": "https://ipfs.io/ipfs/QmTgqnhFBMkfT9s8PHKcdXBn1f5bG3Q5hmBaR4U6hoTvb1?filename=Chainlink_Elf.png",
    "attributes": [
        {
            "trait_type": "trait",
            "value": 100
        }
    ]
}</code></pre><p>Eles mostram como um NFT é e seus atributos. O atributo <code>image</code> aponta para outro URI da aparência do NFT. Isso facilita para as plataformas de NFT como a Opensea, Rarible e Mintable renderizar NFTs nas suas plataformas, já que todos estão esperando receber esses metadados.</p><h3 id="metadados-off-chain-x-metadados-on-chain">Metadados off-chain x metadados on-chain</h3><p>Agora, você pode estar pensando "Peraí... se os metadados não estão on-chain, significa que o meu NFT pode sumir em algum momento"? E você não poderia estar mais correto.</p><p>Você também estaria correto em pensar que metadados off-chain significam que você não pode usá-los para que seus contratos inteligentes interajam um com o outro.</p><p>Esse é o motivo pelo qual nós queremos focar nos metadados on-chain, para que assim possamos programar nossos NFTs para interagir uns com os outros.</p><p>No entanto, ainda precisamos da parte da imagem (<code>image</code>) dos metadados off-chain, pois não temos uma maneira otimizada de armazenar imagens grandes on-chain. Mas não se preocupe. Podemos fazer isso gratuitamente em uma rede descentralizada ainda usando <a href="https://ipfs.io/">IPFS</a>.</p><p>Aqui está um exemplo de um imageURI do IPFS que mostra o <a href="https://opensea.io/assets/0x8d78277bc2c63f07efc2c0c8a8512de4ad459a05/1">Chainlink Elf</a> criado no tutorial <a href="https://blog.chain.link/build-deploy-and-sell-your-own-dynamic-nft/">Dungeons and Dragons</a> (em inglês).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/04/Screen-Shot-2021-03-31-at-12.15.22-PM.png" class="kg-image" alt="Screen-Shot-2021-03-31-at-12.15.22-PM" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/04/Screen-Shot-2021-03-31-at-12.15.22-PM.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/04/Screen-Shot-2021-03-31-at-12.15.22-PM.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/04/Screen-Shot-2021-03-31-at-12.15.22-PM.png 1030w" sizes="(min-width: 720px) 720px" width="1030" height="1356" loading="lazy"><figcaption>Chainlink Elf</figcaption></figure><p>Não definimos um tokenURI para o NFT simplesmente porque queríamos apenas mostrar um exemplo básico.<br>Vamos pular para o NFT avançado agora, para que possamos ver alguns dos recursos incríveis que podemos fazer com metadados on-chain, para que o NFT seja renderizado na Opensea, e colocar nosso Dogie no ar!</p><p>Se você quiser um vídeo para refrescar sua memória sobre o que acabamos de ver na seção anterior, acompanhe esse <a href="https://www.youtube.com/watch?v=ZH_7nEIJDUY">vídeo sobre a implantação de um NFT simples</a>.</p><h2 id="nfts-din-micos-e-avan-ados"><strong>NFTs dinâmicos e avançados</strong></h2><p><a href="https://blog.chain.link/build-deploy-and-sell-your-own-dynamic-nft/">NFTs dinâmicos</a> são NFTs que podem mudar com o tempo ou ter funcionalidades on-chain que podem ser usadas para interagir umas com as outras. Esses são as NFTs que tem customizações ilimitadas. Assim, podemos criar jogos inteiros, mundos ou algum tipo de arte interativa.<br>Vamos nos aprofundar na parte avançada desse tutorial.</p><h3 id="in-cio-r-pido-avan-ado"><strong>Início rápido avançado</strong></h3><p>Certifique-se de ter as testnets ETH e LINK, bem como o suficiente na sua metamask, e então execute o comando a seguir:</p><pre><code>brownie run scripts/advanced_collectible/deploy_advanced.py --network rinkeby
brownie run scripts/advanced_collectible/create_collectible.py --network rinkeby</code></pre><p>Nosso <em>collectible</em> aqui é uma reprodução de raças de cachorros aleatória retornada do <a href="https://docs.chain.link/docs/chainlink-vrf/">Chainlink VRF</a> (em inglês). Chainlink VRF é uma maneira de obter números aleatórios comprováveis e, portanto, realmente em falta em nossos NFTs. Em seguida, vamos criar seus metadados.</p><pre><code>brownie run scripts/advanced_collectible/create_metadata.py --network rinkeby</code></pre><p>Podemos, então, como opção, fazer upload desses dados para o IPFS para que possamos ter um tokenURI. Eu vou mostrar para você como fazer isso mais tarde. Por enquanto, vamos usar apenas o tokenURI de exemplo de:</p><pre><code>https://ipfs.io/ipfs/Qmd9MCGtdVz2miNumBHDbvj8bigSgTwnr4SbyH6DNnpWdt?filename=1-PUG.json</code></pre><p>Se você fizer o download do <a href="https://chrome.google.com/webstore/detail/ipfs-companion/nibjojkomfdiaoajekhjakgkdhaomnch?hl=en">IPFS Companion</a> no seu navegador, poderá usar aquele URL para ver o que o URI retorna. Ficará parecido com isso:</p><pre><code class="language-json">{
    "name": "PUG",
    "description": "An adorable PUG pup!",
    "image": "https://ipfs.io/ipfs/QmSsYRx3LpDAb1GZQm7zZ1AuHZjfbPkD6J7s9r41xu1mf8?filename=pug.png",
    "attributes": [
        {
            "trait_type": "cuteness",
            "value": 100
        }
    ]
}</code></pre><p>Então, podemos executar nosso script <code>set_tokenuri.py</code>:</p><pre><code>brownie run scripts/advanced_collectible/set_tokenuri.py --network rinkeby</code></pre><p>Teremos, então, uma saída como esta:</p><pre><code>Running 'scripts/advanced_collectible/set_tokenuri.py::main'...
Working on rinkeby
Transaction sent: 0x8a83a446c306d6255952880c0ca35fa420248a84ba7484c3798d8bbad421f88e
  Gas price: 1.0 gwei   Gas limit: 44601   Nonce: 354
  AdvancedCollectible.setTokenURI confirmed - Block: 8331653   Gas used: 40547 (90.91%)

Awesome! You can view your NFT at https://testnets.opensea.io/assets/0x679c5f9adC630663a6e63Fa27153B215fe021b34/0
Please give up to 20 minutes, and hit the "refresh metadata" button</code></pre><p>E podemos clicar no link que nos foi dado para ver como ficou no Opensea! Talvez você tenha que clicar no botão <code>refresh metadata</code> e esperar alguns minutos.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/04/Screen-Shot-2021-03-31-at-12.33.42-PM.png" class="kg-image" alt="Screen-Shot-2021-03-31-at-12.33.42-PM" width="498" height="286" loading="lazy"><figcaption>Atualizar os metadados</figcaption></figure><h2 id="as-ra-as-aleat-rias"><strong>As raças aleatórias</strong></h2><p>Vamos falar sobre o que acabamos de fazer. Aqui está nossa <code>AdvancedCollectible.sol</code>:</p><pre><code>pragma solidity 0.6.6;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";

contract AdvancedCollectible is ERC721, VRFConsumerBase {
    uint256 public tokenCounter;
    enum Breed{PUG, SHIBA_INU, BRENARD}
    // add other things
    mapping(bytes32 =&gt; address) public requestIdToSender;
    mapping(bytes32 =&gt; string) public requestIdToTokenURI;
    mapping(uint256 =&gt; Breed) public tokenIdToBreed;
    mapping(bytes32 =&gt; uint256) public requestIdToTokenId;
    event requestedCollectible(bytes32 indexed requestId); 


    bytes32 internal keyHash;
    uint256 internal fee;
    uint256 public randomResult;
    constructor(address _VRFCoordinator, address _LinkToken, bytes32 _keyhash)
    public 
    VRFConsumerBase(_VRFCoordinator, _LinkToken)
    ERC721("Dogie", "DOG")
    {
        tokenCounter = 0;
        keyHash = _keyhash;
        fee = 0.1 * 10 ** 18;
    }

    function createCollectible(string memory tokenURI, uint256 userProvidedSeed) 
        public returns (bytes32){
            bytes32 requestId = requestRandomness(keyHash, fee, userProvidedSeed);
            requestIdToSender[requestId] = msg.sender;
            requestIdToTokenURI[requestId] = tokenURI;
            emit requestedCollectible(requestId);
    }

    function fulfillRandomness(bytes32 requestId, uint256 randomNumber) internal override {
        address dogOwner = requestIdToSender[requestId];
        string memory tokenURI = requestIdToTokenURI[requestId];
        uint256 newItemId = tokenCounter;
        _safeMint(dogOwner, newItemId);
        _setTokenURI(newItemId, tokenURI);
        Breed breed = Breed(randomNumber % 3); 
        tokenIdToBreed[newItemId] = breed;
        requestIdToTokenId[requestId] = newItemId;
        tokenCounter = tokenCounter + 1;
    }

    function setTokenURI(uint256 tokenId, string memory _tokenURI) public {
        require(
            _isApprovedOrOwner(_msgSender(), tokenId),
            "ERC721: transfer caller is not owner nor approved"
        );
        _setTokenURI(tokenId, _tokenURI);
    }
}
</code></pre><p>Usamos o Chainlink VRF para criar uma raça aleatória de uma lista de <code>PUG, SHIBA_INU, BERNARD</code>. Quando chamamos a <code>createCollectible</code> desta vez, na verdade ,iniciamos uma solicitação para o nó Chainlink VRF off-chain e retornamos com um número aleatório para criar o NFT com uma dessas 3 raças.</p><p>Usar aleatoriedade verdadeira em seus NFTs é uma ótima maneira de criar escassez verdadeira e usar um número aleatório do oráculo Chainlink significa que seu número é comprovadamente aleatório, não podendo ser influenciado pelos mineradores.</p><p>Você pode aprender mais sobre isso <a href="https://docs.chain.link/docs/chainlink-vrf">na documentação do Chainlink VRF</a>(em inglês).</p><p>O nó Chainlink responde chamando a função <code>fulfillRandomness</code> e cria o <em>collectible</em> com base no número aleatório. Ainda temos que chamar <code>_setTokenURI</code> para dar ao nosso NFT a aparência que ele precisa.<br><br>Nós não demos nossos atributos do NFT aqui, mas os atributos são uma ótima maneira de fazer com que nossos NFTs batalhem e interajam. Você pode ver um ótimo exemplo de NFTs com atributos <a href="https://github.com/PatrickAlphaC/dungeons-and-dragons-nft">neste exemplo de Dungeons and Dragons</a> (em inglês).</p><h3 id="metadados-do-ipfs"><strong>Metadados do IPFS</strong></h3><p>Estamos usando o IPFS para guardar dois arquivos:</p><ol><li>A imagem do NFT (a imagem do pug)</li><li>O arquivo tokenURI (o arquivo JSON que também inclui o link da imagem)</li></ol><p>Nós usamos o IPFS por ser uma plataforma grátis e descentralizada. Também podemos adicionar nossos tokenURIs e imagens no IPFS fazendo download do <a href="https://docs.ipfs.io/install/ipfs-desktop/">IPFS desktop</a> (em inglês), clicando no botão <code>import</code>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/04/Screen-Shot-2021-03-31-at-12.43.13-PM.png" class="kg-image" alt="Screen-Shot-2021-03-31-at-12.43.13-PM" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/04/Screen-Shot-2021-03-31-at-12.43.13-PM.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/04/Screen-Shot-2021-03-31-at-12.43.13-PM.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1600/2022/04/Screen-Shot-2021-03-31-at-12.43.13-PM.png 1600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/04/Screen-Shot-2021-03-31-at-12.43.13-PM.png 2120w" sizes="(min-width: 720px) 720px" width="2120" height="1320" loading="lazy"><figcaption>Adicione um arquivo IFPS</figcaption></figure><p>Agora, podemos compartilhar o URI clicando nos três pontos ao lado do arquivo que queremos compartilhar, clicando em <code>share link</code> e copiando o link fornecido. Podemos adicionar esse link no nosso arquivo <code>set_tokenuri.py</code> para mudar o URI do token que queremos usar.</p><h3 id="persist-ncia"><strong>Persistência</strong></h3><p>No entanto, se o tokenURI estiver apenas em nosso <em>node</em>, isso significa que, quando nosso <em>node</em> estiver inativo, ninguém mais poderá visualizá-lo. Então, queremos que outros façam o <code>pin</code> do nosso NFT. Podemos usar um serviço que realiza o <code>pin</code> como o <a href="https://www.pinata.cloud">Pinata</a> para ajudar a manter nossos dados ativos mesmo quando nosso <em>node</em> no IPFS estiver inativo.<br><br>Imagino que, no futuro, mais e mais metadados serão armazenados em IPFS e plataformas de armazenamento serão descentralizadas. Servidores centralizados podem ficar inativos, e isso significaria que a arte dos NFTs nesses servidores seria perdida para sempre. Certifique-se de verificar onde está localizado o tokenURI do NFT que você usa!<br>Também espero que mais pessoas usem plataformas dStorage como <a href="https://docs.filecoin.io">Filecoin</a>, pois usar um serviço de pinning também não é tão descentralizado quanto deveria ser.</p><h2 id="indo-al-m"><strong>Indo além</strong></h2><p>Se você quiser ver um passo a passo em vídeo do NFT avançado que acabamos de fazer, <a href="https://www.youtube.com/watch?v=tCR7b9p9GiM">assista ao vídeo sobre NFT avançado</a>.<br><br>Agora, você tem as habilidades para criar NFTs lindos, divertidos, personalizados e interativos e renderizá-los em um marketplace.<br><br>NFTs são maneiras divertidas e poderosas de compensar os artistas com precisão por todo o trabalho duro que eles fazem. Boa sorte e lembre-se de se divertir!</p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
