Olá pessoal! Meu nome é Ararat e trabalho na QuantNet, que realiza concursos de estratégias algorítmicas. Recentemente, uma tarefa importante surgiu diante de mim - fornecer garantias para a inviolabilidade das datas dos usuários (isso é extremamente importante, pois, para verificar corretamente a eficácia das estratégias, é necessário usar dados dos mercados financeiros globais em tempo real).
Foi aí que me deparei com o conceito de PoE (Prova de Existência). Já foi escrito bastante sobre isso na Internet, mas as especificidades da plataforma me fizeram pensar um pouco. Portanto, decidi escrever este artigo e compartilhar minha experiência na arquitetura e implementação de PoE. Eu acho que será especialmente relevante para os caras da fintech.
Dividi meu artigo em 3 blocos principais:
- O que é PoE e quando pode ser necessário
- Algoritmo de implementação
- A solução para o meu caso específico
Então, o que é Prova de Existência?
A prova de existência (literalmente, prova de existência) ajuda a provar que um documento, arquivo ou dado foi criado em uma data e hora específicas. O maior pedido é o registro de patentes. Mas pelo que vi, na maioria das vezes é aplicado em áreas na interseção entre finanças e TI.
Um exemplo da minha área de negociação algorítmica: você tem um algoritmo que fornece cerca de 70% das previsões corretas de ações para as próximas 2 semanas. Você decide vender suas previsões para outros participantes do mercado. A questão é pequena: convencer o comprador de que suas previsões estão corretas e foram feitas antes dos resultados da licitação, ou seja, garantir sua implementação em um horário específico.
Como isso pode ser garantido? Certo, implemente o PoE.
Algoritmo de implementação de PoE
Primeiro você precisa:
- Prepare o arquivo que você deseja patentear. (Fiz o PDF, mas você pode usar qualquer outro contêiner).
- Obtenha o hash do arquivo fornecido (usei o formato sha256).
Apenas no caso, um hash é uma “impressão digital” individual de um arquivo, garantindo (quase completa) ausência de coincidência com o hash de outro arquivo. Ao receber o hash do arquivo, você precisará gerar apenas uma transação na rede blockchain especificando o hash do documento no corpo da transação.
Só isso. Com o prólogo terminado. Agora passamos ao mais interessante.
(Para maior clareza, criei um código especial (apenas para demonstração). Você pode ver o exemplo do serviço de demonstração
aqui .)
Vamos dar uma olhada em como a demo funciona.
Proponho dividir a implementação em 2 partes:
- Preparação de um contrato inteligente e uma carteira de éter.
- Geração de transação no código Node.js e chave privada.
Vamos em ordem:
Parte 1: Preparando um contrato e uma carteira Ethereum Smart
O próprio PoE foi primeiro associado ao blockchain Bitcoin. Mas eu escolhi o blockchain do éter e os contratos inteligentes para implementação. Contratos inteligentes nos dão flexibilidade, modularidade e escalabilidade no futuro, agindo como um armazenamento para hashes na blockchain.
Eu escolhi um contrato inteligente simples que pode aceitar um hash com uma data apropriada, o formato hash => data, também seria ótimo ter um método que retorne a data do hash quando chamado. Além disso, seria bom garantir que apenas o proprietário do contrato pudesse adicionar novos hashes.
Código do contrato inteligente:
``` pragma solidity 0.5.9; contract Ownable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); constructor () internal { _owner = msg.sender; emit OwnershipTransferred(address(0), _owner); } function owner() public view returns (address) { return _owner; } modifier onlyOwner() { require(isOwner()); _; } function isOwner() public view returns (bool) { return msg.sender == _owner; } function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } function _transferOwnership(address newOwner) internal { require(newOwner != address(0)); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } contract HashStore is Ownable { mapping(bytes32 => uint256) private _hashes; event HashAdded(bytes32 hash); function addHash(bytes32 rootHash) external onlyOwner { require(_hashes[rootHash] == 0, "addHash: this hash was already deployed"); _hashes[rootHash] = block.timestamp; emit HashAdded(rootHash); } function getHashTimestamp(bytes32 rootHash) external view returns (uint256) { return _hashes[rootHash]; } } ```
Como você já percebeu, usamos 2 contratos separados: Próprio e HashStore.
O contrato HashStore é responsável por armazenar hashes e emitir a data do hash, mediante solicitação. O contrato de Propriedade é responsável por verificar se o novo hash foi adicionado exclusivamente pelo proprietário do contrato.
Para adicionar um hash, você precisa chamar o método addHash, passando o valor sha256 como argumento para o nosso arquivo. Se os hashes dentro do contrato corresponderem, a transação será rejeitada. Isso filtra a duplicação indesejada de valores com datas diferentes. É verificado aqui:
require(_hashes[rootHash] == 0, "addHash: this hash was already deployed");
Podemos obter a data da transação do hash usando o método getHashTimestamp, passando o hash com a data da transação desejada como argumento. O método getHashTimestamp retorna a hora no formato UNIX. Você pode traduzir para qualquer formato mais legível.
Então, descobrimos o contrato, agora você precisa implantá-lo na rede. Para fazer isso, precisamos de duas coisas:
- éter para interagir com o blockchain
- algum éter para chamar métodos e implantar contratos.
Para não desperdiçar éter nos testes, podemos usar a rede de testes de ropsten. Saiba mais aqui. Esse endereço é o proprietário do contrato, pois foi o iniciador da implantação e pode adicionar novos hashes no futuro. Depois disso, você precisa salvar este endereço em um local seguro, bem como a chave privada da sua carteira e o endereço do contrato. Todos nós precisaremos disso no futuro.
Parte 2: Geração de transação no Node.js e chave privadaPortanto, neste ponto, já temos uma carteira de éter, sua chave secreta, um contrato na rede de teste e um hash de dados. Resta configurar a interação com o blockchain.
Para fazer isso, usaremos a biblioteca web3.js e criaremos um token para nosso nó. Criei o meu usando o serviço infura.io e ele se parece com isso:
ropsten.infura.io/v3/YOUR_TOKEN_HERE
Para hash, use o pacote sha256. O formato dos dados pode ser qualquer um, mas no exemplo usamos os dados em JSON.
Como resolvi meu caso usando PoE?
Além de ter PoE, era importante para mim não sobrecarregar os usuários com blockchain e taxa de transação, por exemplo, chamar o método addHash (bytes32 rootHash) custa 0,2 finney (0,0002 ETH ou US $ 0,06 à taxa de junho de 2019).

Cerca de 30 conclusões da posição estratégica saiam por dia, ou seja, custa US $ 2,1. Se o número de usuários aumentar 100 vezes e a taxa de Éter aumentar, o custo, é claro, aumentará.
Decidi manter um hash na blockchain por um dia. Esse hash será gerado a partir de hashes de saídas diárias da estratégia e seus identificadores internos.

Temos uma solução que não tem funcionalidade inferior, porém, muito mais barata. Não vemos problemas com escalabilidade, no entanto, você sempre pode dividir a saída de uma posição estratégica em vários blocos e salvar vários hashes na rede blockchain. E um participante pode facilmente verificar um hash separado usando outros hashes vizinhos.
No final
Para verificação, criamos um modelo especial, disponível como um notebook Jupyter. A qualquer momento, o usuário pode baixar o modelo, regenerar tudo e verificar se todas as posições são realmente aquelas que foram criadas e salvas no passado.
``` : 1. API 1. 2. API , 3. , . . ```