Comment mettre en œuvre indépendamment (preuve d'existence) en 2 étapes

Bonjour à tous! Je m'appelle Ararat et je travaille pour QuantNet, qui organise des concours de stratégies algorithmiques. Récemment, une tâche importante s'est présentée à moi - fournir des garanties d'inviolabilité des dates des utilisateurs (c'est extrêmement important, car pour vérifier correctement l'efficacité des stratégies, il est nécessaire d'utiliser les données des marchés financiers mondiaux en temps réel).

C'est là que je suis tombé sur le concept de PoE (Proof of Existence). On en a assez écrit à ce sujet sur Internet, mais les spécificités de la plate-forme m'ont un peu brisé l'esprit. J'ai donc décidé d'écrire cet article et de partager mon expérience dans l'architecture et la mise en œuvre de PoE. Je pense que ce sera particulièrement pertinent pour les gars de la fintech.

J'ai divisé mon article en 3 blocs principaux:

  • Qu'est-ce que le PoE et quand peut-il être nécessaire
  • Algorithme d'implémentation
  • La solution à mon cas spécifique

Alors, quelle est la preuve d'existence?


La preuve d'existence (littéralement, preuve d'existence) permet de prouver qu'un document, un fichier ou des données ont été créés à une date et une heure spécifiques. L'enregistrement de brevet est la demande la plus importante. Mais d'après ce que j'ai vu, il est le plus souvent appliqué dans des domaines à l'intersection de la finance et de l'informatique.

Un exemple de mon domaine de trading algorithmique: vous avez un algorithme qui donne environ 70% de prévisions correctes pour les actions pour les 2 prochaines semaines. Vous décidez de vendre vos prévisions à d'autres acteurs du marché. Le point est petit - pour convaincre l'acheteur que vos prévisions sont correctes et ont été faites avant les résultats des enchères, c'est-à-dire garantir leur mise en œuvre à un moment précis.

Comment cela peut-il être garanti? À droite, implémentez PoE.

Algorithme de mise en œuvre PoE


Vous avez d'abord besoin:

  1. Préparez le fichier que vous souhaitez breveter. (J'ai fait le PDF, mais vous pouvez utiliser n'importe quel autre conteneur).
  2. Obtenez le hachage du fichier donné (j'ai utilisé le format sha256).

Au cas où, un hachage est une «empreinte digitale» individuelle d'un fichier, garantissant (presque complètement) l'absence de coïncidence avec le hachage d'un autre fichier. Lorsque vous recevez le hachage du fichier, vous n'aurez qu'à générer une transaction sur le réseau de la chaîne de blocs, indiquant le hachage du document dans le corps de la transaction.

C’est tout. Le prologue terminé. Passons maintenant au plus intéressant.

(Pour plus de clarté, j'ai créé un code spécial (uniquement pour la démonstration). Vous pouvez voir l'exemple de démonstration du service ici .)

Examinons de plus près comment fonctionne la démo.

Je propose de diviser la mise en œuvre en 2 parties:

  1. Préparation d'un contrat intelligent et d'un portefeuille en éther.
  2. Génération de transactions en code Node.js et clé privée.

Allons dans l'ordre:

Partie 1: Préparation d'un contrat et d'un portefeuille intelligents Ethereum

PoE lui-même a d'abord été associé à la blockchain Bitcoin. Mais j'ai choisi la blockchain éther et les contrats intelligents pour la mise en œuvre. Les contrats intelligents nous donnent la flexibilité, la modularité et l'évolutivité à l'avenir, agissant comme un stockage pour les hachages dans la blockchain.

J'ai choisi un simple contrat intelligent qui peut accepter un hachage avec une date appropriée, format hash => date, il serait également super d'avoir une méthode qui retourne la date de hachage lors de l'appel. De plus, il serait bon de veiller à ce que seul le propriétaire du contrat puisse ajouter de nouveaux hachages.

Code de contrat intelligent:

``` pragma solidity 0.5.9; /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". */ contract Ownable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ constructor () internal { _owner = msg.sender; emit OwnershipTransferred(address(0), _owner); } /** * @return the address of the owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner()); _; } /** * @return true if `msg.sender` is the owner of the contract. */ function isOwner() public view returns (bool) { return msg.sender == _owner; } /** * @dev Allows the current owner to transfer control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0)); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } /** * @title HashStore * @dev The contract store the hashes and returns date by hash * Only the owner can add new hashes */ 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]; } } ``` 

Comme vous l'avez déjà remarqué, nous avons utilisé 2 contrats distincts: Ownable et HashStore.
Le contrat HashStore est responsable du stockage des hachages et de l'émission de la date de hachage sur demande. Le contrat propriétaire est chargé de vérifier que le nouveau hachage a été ajouté exclusivement par le propriétaire du contrat.

Pour ajouter un hachage, vous devez appeler la méthode addHash, en passant la valeur sha256 comme argument à notre fichier. Si les hachages à l'intérieur du contrat correspondent, la transaction sera rejetée. Cela filtre la duplication indésirable de valeurs avec des dates différentes. Il est vérifié ici:

 require(_hashes[rootHash] == 0, "addHash: this hash was already deployed"); 

Nous pouvons obtenir la date de transaction de hachage en utilisant la méthode getHashTimestamp, en passant le hachage avec la date de transaction souhaitée comme argument. La méthode getHashTimestamp renvoie l'heure au format UNIX. Vous pouvez traduire dans n'importe quel format plus lisible.

Nous avons donc compris le contrat, vous devez maintenant le déployer sur le réseau. Pour ce faire, nous avons besoin de deux choses:

  1. adresse éther pour interagir avec la blockchain
  2. un peu d'éther pour appeler des méthodes et déployer des contrats.

Afin de ne pas gaspiller de l'éther lors des tests, nous pouvons utiliser le réseau de test ropsten. Apprenez-en plus ici. Cette adresse est le propriétaire du contrat, car il était l'initiateur du déploiement et pourrait ajouter de nouveaux hachages à l'avenir. Après cela, vous devez enregistrer cette adresse dans un endroit sûr, ainsi que la clé privée de votre portefeuille et l'adresse du contrat. Nous en aurons tous besoin à l'avenir.

Partie 2: génération de transactions dans Node.js et clé privée

Donc, à ce stade, nous avons déjà un portefeuille éther, sa clé secrète, un contrat dans le réseau de test et un hachage de données. Il reste à configurer l'interaction avec la blockchain.

Pour ce faire, nous utiliserons la bibliothèque web3.js et créerons un jeton pour notre nœud. J'ai créé le mien en utilisant le service infura.io et il ressemble à ceci:

 ropsten.infura.io/v3/YOUR_TOKEN_HERE 

Pour le hachage, utilisez le package sha256. Le format des données peut être n'importe lequel, mais dans l'exemple, nous utilisons les données en JSON.

Comment ai-je résolu mon cas en utilisant PoE?


En plus d'avoir PoE, il était important pour moi de ne pas surcharger les utilisateurs avec la blockchain et les frais de transaction, par exemple, appeler la méthode addHash (bytes32 rootHash) coûte 0,2 finney (0,0002 ETH ou 0,06 $ au taux de juin 2019).



Une trentaine de conclusions de la position stratégique sont publiées par jour, c'est-à-dire que cela nous coûte 2,1 $. Si le nombre d'utilisateurs augmente 100 fois et que le taux d'Ether augmente, le coût augmentera bien sûr.

J'ai décidé de garder un hachage sur la blockchain pendant une journée. Ce hachage sera généré à partir des hachages des sorties de stratégie quotidiennes et de leurs identifiants internes.



Nous obtenons une solution qui n'est pas inférieure en fonctionnalités, cependant, beaucoup moins cher. Nous ne voyons pas de problèmes d'évolutivité, cependant, vous pouvez toujours diviser la sortie d'une position de stratégie en plusieurs blocs et enregistrer plusieurs hachages sur le réseau de la chaîne de blocs. Et un participant peut facilement vérifier un hachage séparé en utilisant d'autres hachages voisins.

En fin de compte


Pour vérification, nous avons créé un modèle spécial, qui est disponible sous forme de cahier Jupyter. À tout moment, l'utilisateur peut télécharger le modèle, tout régénérer et vérifier que toutes les positions sont bien celles qui ont été créées et enregistrées dans le passé.

 ```   : 1.    API       1.     2.    API  ,         3.          ,              .          . ``` 

Source: https://habr.com/ru/post/fr459046/


All Articles