This article is a continuation of the cycle on writing smart contracts on the Ethereum platform. In the first part, I promised to show how to create a new cryptocurrency for Solidity (in the blockchain world, this is something like the analogue "Hello, world!"). But in fact, this does not make sense, since several good articles have already been written about this ( an example from the Solidity docks , an example from the Ethereum main page ).
So I thought a little and found another use case for smart contracts. In this article, I will show how, theoretically, the author of a Trojan-cryptographer can monetize his brainchild by selling keys for decryption using smart contracts.
BTW everything written below is purely educational in nature.
Cipher operators did not appear yesterday and have a more or less similar pattern of work. And as a rule, in this scheme there are steps of the form
We will try to transfer these three fragments of the system to the blockchain.
Our project will consist of two parts - the administration module and the "store" module. We will make admin panel as a separate contract, and we will inherit the contract from the store. Generally speaking, in Ethereum, you can interact between two different contracts in the blockchain; you just need to know their addresses and the names of the functions that interest us, but I will demonstrate this some time next.
We will write on Solidity version 0.4.2 (current version is October 26, 2016). As a development environment, you can use the online compiler or the newly released online platform Ethereum studio. The latter is made on the basis of c9.io , but with features for development under Ethereum. I didn’t use it myself, as it was just released, but it looks pretty, although its creators hide documentation, probably, on purpose.
We take Mist as a wallet client, and since we are doing just PoC, we’ll run all contracts on our private blockchain (I’ve told how to do this here ). So it will be easier, cheaper (in the sense of free) and faster.
First, create an administration module. In it, we add functionality for adding and removing administrators, withdrawing money and "killing a contract." First we define all the necessary variables and the constructor function. It should be called the same as the contract itself and is called only once (automatically) - when the contract is loaded into the blockchain.
pragma solidity ^0.4.2; // - , 0.4.2 0.5 contract admin { // VARIABLES struct user { address addr; string name; // '$uPeR_p0wner_1999' string desc; // 'CEO & CTO' } user owner; mapping (address => user) adminInfo; mapping (address => bool) isAdmin; function admin (string _name, string _desc) { owner = user({ addr : msg.sender, // msg - name : _name, // . msg.sender - desc : _desc // msg.value - wei, .. }); isAdmin[msg.sender] = true; adminInfo[msg.sender] = owner; } }
The code itself is simple and straightforward, since the syntax is similar to C ++, JS, C, etc. Just in case, let me remind you that the struct statement allows you to create custom data types from existing ones . Mapping, as you might guess, implements an associative array (dict in Python, map in C ++).
Here we have created the variable owner, in which we use the struct to store the address, name, and some description for the contract creator. Contracts in Ethereum have a so-called state, that is, in the future, when someone calls a contract, we can use this variable.
Next, we add the functions responsible for adding / deleting an administrator, withdrawing money and destroying a contract. Here, everything is generally trivial, except for one thing - the event operator. This is a very nice, from the point of view of UI and usability in general, the operator that allows you to implement something like push notifications inside the contract. Just below there will be a screenshot from which it is clear how this looks in practice.
// EVENTS event adminAdded(address _address, string _name, string _desc); event adminRemoved(address _address, string _name, string _desc); event moneySend(address _address, uint _amount); // FUNCTIONS function addAdmin (address _address, string _name, string _desc) { if (owner.addr != msg.sender || isAdmin[_address]) throw; // / isAdmin[_address] = true; adminInfo[_address] = user({addr : _address, name : _name, desc : _desc}); adminAdded( _address, _name, _desc ); // Call event } function removeAdmin (address _address) { if (owner.addr != msg.sender || !isAdmin[_address]) throw; isAdmin[_address] = false; adminRemoved( _address, adminInfo[_address].name, adminInfo[_address].desc ); // Call event delete adminInfo[_address]; } function getMoneyOut(address _receiver, uint _amount) { if (owner.addr != msg.sender || _amount <= 0 || this.balance < _amount) throw; // , // - if (_receiver.send(_amount)) moneySend(_receiver, _amount); // - event } function killContract () { if (owner.addr != msg.sender) throw; selfdestruct(owner.addr); // }
All this code is simply added inside the contract admin {...} after it has already been written and our administration module is ready.
This step is described in some detail in the first part; I will not dwell on it. I will attach only a few screenshots of the work with a ready-made contract. This is how, for example, in Mist, the function call admin add looks like
And here is what the promised event looks like:
First, the point: we just make a queue of already paid applications for a key. In our case, administrators will rake this pile with their hands (you can automate, but again - sometime next time) and add a key for each application to the improvised database (let's make a map like _id → _key). ID, for simplicity, we will have a natural number, and the key will be a string (for example, a link to pastebin).
The code itself fit in 85 lines, here it is:
contract shop is admin { // VARIABLES uint[] orders; // uint currentOrder = 0; // mapping (uint => string) keys; // ID - // EVENTS event keyAdded(uint _ID, string _name, string _desc); event keyBought(address _address, uint _ID); // FUNCTIONS function buyKey(uint _ID) payable { // payable if (msg.value < 15000000000000000000) throw; // , 15 orders.push(_ID); // keyBought( msg.sender, _ID ); } function getKeyByID(uint _ID) returns (string) { // , return keys[_ID]; // ID , } function getLastOrder() returns (uint) { if (!isAdmin[msg.sender]) throw; return orders[currentOrder]; // ID currentOrder += 1; } function addKey(uint _ID, string _key) { if (!isAdmin[msg.sender]) throw; // - ID keys[_ID] = _key; keyAdded( _ID, adminInfo[msg.sender].name, adminInfo[msg.sender].desc ); } }
Once again, what is written here is a prototype with a bunch of errors and deficiencies. A simple example - in our case, the array of applications is not cleaned in any way and is only gaining in size. Because of this, someday the cost of calling the buyKey function will rise to the value of the key itself, which is somehow wrong.
Another more complicated point is that in order to store the sequence number of the last order processed, we use the variable currentOrder. And now let's imagine a situation - there are two administrators: Vasya in Beijing and Peter in New York. At one point in time, they called the getLastOrder function and both got some number - let it be 23412. Then each of them called the addKey function and added the key for this order to the “base”, and with it the name and desc were saved. As a result, when miners begin to perform these actions, those that are closer to Beijing, Vasin will fulfill the request more quickly and the state will have one look, and those that are closer to New York - Petin and the state will turn out to be different. As a result, some kind of merge conflict.
In any case, I hope that I was able to demonstrate what fantastic possibilities the blockchain technology offers us. Even this simple contract will give hackers the opportunity to monetize the malware an order of magnitude easier and safer compared to the usual schemes.
In the next article, I’ll most likely write how to attach interfaces other than Mist to contracts (for example, interaction via a regular site), or how to work with Ethereum in conjunction with some programming language, for example Python. But if there are any suggestions - be sure to write in the comments.
Source: https://habr.com/ru/post/313710/
All Articles