
Hi% username%!
I will tell and show you how the basis of generating money in cryptocurrency works - mining. How to create the first block, new blocks and how money appears from nowhere.
To make it easier to understand, we will write our improvised miner for the improvised cryptocurrency HabraCoin.
First, a simplified educational program, where without it.
Wallets
Each wallet is a randomly generated pair of keys. Actually, the wallet address is a public key hash. So it can be uniquely identified.
Transaction
This is a record of what wallet for which amount is transferred. And also, the time and date of the operation. This record (its hash) is signed with the private key of the sender and sent to everyone in the district, awaiting confirmation.
')
the confirmation
In order to find out about the transaction and write it down to yourself, you need to confirm it, which is obtained as a result of creating a new block.
Block
This is service data + transaction list + number of the minting wallet +
magic number .
Chain of blocks
The sequence in which each next block includes the previous Id.
Start
So, there is a certain amount of people, one is possible. Let's call him Habrosh. He decides to launch his own HabraCoin cryptocurrency system.
Since there are no dedicated servers for this currency, all its members are equal and must somehow agree on the validity of transactions. That is, we need a mechanism that will provide:
- The inevitability of transactions.
- An opportunity for anyone to check their validity.
To do this, it forms a block of existing at the moment unconfirmed transactions, the number of the previous block, the number of his wallet, etc. For the very first transaction block, we don’t, we don’t have the previous block number, there’s really nothing. Only the address of the Habroshi wallet and the date with time.
Also, the following things are indicated in the HabraCoin algorithm.
- It is desirable that new blocks are created every 10 minutes. If after a while we look, and it turns out that there are more of them than they needed, then calculate the new complexity of generating them every 100 blocks.
- For the fact that someone creates a valid block, he is entitled to a reward of 50 HabraCoins + commission
- The block in which most transactions are “winning”
Speed ​​Limit
As we see, the
very fact of the creation of a block indicates that its creator receives a reward for this . And in order for it to make sense in general, the speed and complexity of creating blocks should be
limited . Otherwise, you know, tons of blocks out of nothing and no sense.
Cryptocurrency uses a method of limiting the complexity, which is the
problem of calculating the hash of a given value . To be precise,
less than a certain value .
If someone doesn’t know, a hash, for example f7c9f52d1ebf8c6aef8986fb127ba1bdeec58521f7eb46f026b708df26a40912, is a number, but a number. In the decimal system, it looks like 112078102004378042284884826242280406284022042488488848628408208468422468268028. That is, hashes can be compared, added, subtracted and all that.
So here.
For everyone to recognize a block as valid, its hash must be less than the maximum possible minus of a value defined by everyone, called complexity .
For example, we have a hash of 4 bytes, the maximum possible value of its FFFFFFFF
16 . And the complexity of, say, 100
10 . Subtract one from the other, it turns out, our hash must be less than FFFFFF9B
16How to achieve this?
If you remember, all blocks consist of several fields. We take these fields, concatenate, we get an
array of bytes from them. This is an array of bytes, we give the hash function, we get the result and see: less what happened with the current complexity, or not?
If not,
change this byte array until we get the desired value . Namely:
In each block there is a field called
nonce . This number is several bytes in size, which you need to increase by one, add to the block and again read from it the hash. Since good hash functions produce more or less equiprobable values, we do not know in advance how many times the process will have to be repeated. Maybe 1-2 times, maybe billions.
The one who managed to get a hash that satisfies the conditions of complexity, sends to all the block with the transactions included in it. In case several people did it at the same time, a condition is introduced that several chains of blocks cannot exist together, and the longest wins. So, if we have two chains:
Block1-> Block2-> Block3
ABlock1-> Block2-> Block3
Bthen the one for which the 4th block will be found ahead of time will win. And the smaller chain is discarded and its transactions are again queued for confirmation.
Commission
Everyone in their wallets saw the “commission” field when making a transaction. This commission goes to the people involved in the generation of blocks. That is, they will first of all choose from all transactions that are pending confirmation, those that contain a commission.
After the formation of the block, it is considered that the entire commission contained in the transaction goes to its (block) creator.That is, when the remuneration for generating a block ends (if it is spelled out in the currency algorithm), only the commission will be left to miners, and free transactions can never be processed.
Let's simulate the situation and help Habrosh to craft some kind of block.
Under the spoiler, a program (in the form of a Junit test), which for the sake of decency generates 2 random pairs of keys, forms some sort of transaction (even signs it, everything is fair!), And then looks for an addition to it so that the first 2 bytes of the hash are zero . Type complexity such. It works for a couple of minutes, and then it really gives out a hash, which you can quickly check by concatenating the transaction and counter bytes.
Program codepackage com.paranoim.money;
import java.math.BigInteger;
import java.util.Arrays;
import junit.framework.TestCase;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.util.Pack;
import org.bouncycastle.math.ec.ECPoint;
import com.paranoim.TestsAll;
import com.paranoim.crypto.assymetric.ECDSA;
import com.paranoim.crypto.digest.SHA3_512;
import com.paranoim.crypto.utils.ByteUtils;
public class MiningTest extends TestCase
{
private byte[] counter = new byte[4];
private byte[] getAddressFromPublicKey(ECPublicKeyParameters publicKey)
{
ECPoint q = publicKey.getQ();
byte[] encoded = q.getEncoded(true);
return SHA3_512.process(encoded); // reciever's address is it's pubkic key hash
}
public void testMining()
{
ECPublicKeyParameters fromKey = (ECPublicKeyParameters) TestsAll.ALICE.getPublic();
ECPublicKeyParameters toKey = (ECPublicKeyParameters) TestsAll.BOB.getPublic();
byte[] from = getAddressFromPublicKey(fromKey);
byte[] to = getAddressFromPublicKey(toKey);
int amount = 100; //100 HabraCoin
long now = System.currentTimeMillis();
//compose the message for signing
byte[] fromTo = ByteUtils.concat(from, to);
byte[] bAmount = Pack.intToBigEndian(amount);
byte[] bTime = Pack.longToBigEndian(now);
byte[] amountAndTime = ByteUtils.concat(bAmount, bTime);
byte[] msg = ByteUtils.concat(fromTo, amountAndTime);
BigInteger[] sigCoords = ECDSA.signDigest(TestsAll.ALICE.getPrivate(), SHA3_512.process(msg));
byte[] signature = ByteUtils.concat(sigCoords[0].toByteArray(), sigCoords[1].toByteArray());
// MSG contains from, to, amount, time and signature
msg = ByteUtils.concat(msg, signature);
ECPublicKeyParameters minersKey = (ECPublicKeyParameters) TestsAll.ALICE1.getPublic();
byte[] bminersKey = getAddressFromPublicKey(minersKey);
//msg = msg + miner's address
msg = ByteUtils.concat(msg, bminersKey);
byte[] hash = doTheMining(msg);
msg = ByteUtils.concat(msg, counter);
assertTrue(Arrays.equals(hash, SHA3_512.process(msg)));
}
private byte[] doTheMining(byte[] msg)
{
byte[] hash = SHA3_512.process(ByteUtils.concat(msg, counter));
while(hash[0] != 0 || hash[1] != 0 )
{
incrementCounter();
hash = SHA3_512.process(ByteUtils.concat(msg, counter));
}
return hash;
}
private void incrementCounter()
{
for (int i = 0; i < counter .length; i++)
{
counter[i]++;
if (counter[i] != 0)
break;
}
}
}
:
1824B9ADF09908222CF65069FDE226D32F165B3CF71B7AA0039FDFEF75EAA61610909EBFFBAC023480FC87FCF640C4A
009B82C4A6D25A0F4B8A732AE54EF733E792681137BA378577DFDC2732D192DAF323966EAD4ADC9635D7A12EDD50E34
9F660622D186AF3C03BF7D265F2AA7EB125056F4BF45BE519E8B22B845B28065110000006400000142E5D667CB01CEE
EDD0AC15EC4C491819A99030BD5FEF7CD2B469F2B90BA13D7981EDCD0708353D13390B8564F496C44FAC2777B0AF79D
C94CBF36D0CC0F047E807889F34C4DC5FEB724699C257391F84F3DDD70B84F841D115F4EFEAF4E58779042F35257E5C
035046037DE740718D199A8F06AD7A58E37CCCD4CC5E95295DCC2C5F3C70847BD59FA57BCC5FF4B208F93948FCFD763
EC1E5C85B61C43EB64B77A9F53B28785D7DE2335333003260A0839D53927976751A8D8967B2BB325909D86E82BC4125
2A28ECF6F0E7476BB99B29585EB0E75410000
:
000008ACF935A8E3E453AC538706F560155943C6B0A77E5F5FCA7939D5FFE589676A6B3CD7AC78845786C50449D1A6F
91003EDCA7B5D8B12AC36CCA36A00844A
. , .