
Hi%username%!
暗号通貨でお金を生み出すための基礎がどのように機能するのか、つまりマイニングについて説明します。 最初のブロックの作成方法、新しいブロック、およびお金がどこからともなく現れる様子。
わかりやすくするために、即興暗号通貨HabraCoinの即興マイナーを作成します。
まず、それがない場合の単純化された教育プログラム。
財布
各ウォレットは、ランダムに生成されたキーペアです。 実際、ウォレットのアドレスは公開鍵からのハッシュです。 そのため、一意に識別できます。
取引
これは、どのウォレットにどの金額が転送されるかの記録です。 また、操作の日時。 このレコード(ハッシュ)は、送信者の秘密キーによって署名され、確認を見越して地区の全員に送信されます。
確認
トランザクションとそれを記録する全員について学習するには、新しいブロックを作成して取得したトランザクションを確認する必要があります。
ブロックする
これは、サービスデータ+トランザクションリスト+マイナーのウォレット番号+
マジック番号です。
ブロックチェーン
後続の各ブロックが前のブロックのIDを含むシーケンス。
開始する
だから、一定の数の人がいます。 彼をハブロシュと呼びましょう。 彼はHabraCoin暗号通貨システムを立ち上げることにしました。
この通貨には専用サーバーがないため、すべての参加者は等しく、トランザクションの有効性について何らかの形で同意する必要があります。 つまり、次の機能を提供するメカニズムが必要です。
- トランザクションの必然性。
- 誰でも有効性を検証する能力。
これを行うために、彼は現在存在する未確認のトランザクション、前のブロックの番号、ウォレットの番号などからブロックを形成します。 最初のブロックのトランザクションはなく、前のブロックの番号もありません。実際には何もありません。 Habroshiウォレットの住所と日時のみ。
また、HabraCoinアルゴリズムには次のことが示されています。
- 10分ごとに新しいブロックを作成することをお勧めします。 しばらくして、必要以上のものがあることが判明した場合、100ブロックごとに世代の新しい複雑さを計算します
- 有効なブロックを作成した人には、50 HabraCoins + 手数料の報酬が与えられます
- 「勝者」は、ほとんどのトランザクションが
制限速度
ご覧のとおり
、ブロックを作成するという事実は、その作成者がこれに対する報酬を受け取ることを示しています。 そして、これがまったく意味をなすためには、ブロックを作成する速度と複雑さを
制限する必要があります。 そうでなければ、あなたはあなた自身が理解します。
暗号通貨では、複雑さを制限する方法が使用さ
れます 。これ
は、特定の値のハッシュを計算する問題に含まれます 。 より正確には
、特定の値未満です 。
誰かが知らない場合、ハッシュ、たとえばf7c9f52d1ebf8c6aef8986fb127ba1bdeec58521f7eb46f026b708df26a40912はそれが何であるか、しかし数字です。 10進法では、112078102004378042284884826242280406284022042488488848628408208468422468268028のようになります。つまり、ハッシュを比較、追加、減算、その他すべてできます。
だからここに。
全員がブロックを有効であると認識するために、そのハッシュは、可能な最大値から全員が定義した値( complexity)を引いた値より小さくなければなりません 。
たとえば、4バイトのハッシュがあり、そのFFFFFFFFの可能な最大値は
16です。 そして、例えば、複雑さは100
10です。 一方から他方を引くと、ハッシュはFFFFFF9B
16未満でなければならないことがわかります
16これを達成する方法は?
覚えていれば、すべてのブロックはいくつかのフィールドで構成されています。 これらのフィールドを取得し、連結して、それらから
バイトの配列を取得します。 これはバイトの配列です。関数のハッシュを与え、結果を取得して見てください:現在の複雑さを考慮して起こったことは少ないですか?
そうでない場合は、
目的の値を取得するまでこのバイト配列を変更します 。 すなわち:
各ブロックには
nonceというフィールドがあります。 これは数バイトのサイズであり、1バイト増やしてブロックに追加し、再びそこからハッシュを読み取る必要があります。 優れたハッシュ関数は、ほぼ同じ確率の値を生成するため、プロセスを繰り返す必要がある回数を事前に知りません。 たぶん1-2回、おそらく数十億回。
複雑さの条件を満たすハッシュの取得に成功した人はだれでも、トランザクションが含まれるブロックを全員に送信します。 複数の人が同時にこれを行った場合、いくつかのブロックのチェーンが一緒に存在することはできませんが、最も長いものが勝つという条件が導入されます。 したがって、2つのチェーンがある場合:
Block1-> Block2-> Block3
ABlock1-> Block2-> Block3
B次に、4番目のブロックが事前に見つかったものが勝ちます。 小さいチェーンがスローされ、そのトランザクションは確認のために再びキューに入れられます。
委員会
ウォレットの誰もが、取引を行う際に「委託」フィールドを見ました。 この委員会は、ブロックの生成に関与する人々を対象としています。 つまり、彼らはまず、確認を待っているすべてのトランザクションから、コミッションを含むトランザクションを選択します。
ブロックの形成後、トランザクションに含まれる手数料全体がその(ブロック)作成者に送られると見なされます。つまり、ブロック生成の報酬が終了すると(通貨アルゴリズムで規定されている場合)、鉱夫は手数料のみを持ち、無料のトランザクションは処理されません。
状況をシミュレートして、Habroshが何らかのブロックを作成できるようにしましょう。
ネタバレの下で、プログラム(Junitテストの形式)は、良識のために、2つのランダムなキーペアを生成し、何らかのトランザクションを形成します(すべて正直に署名します!)そして、ハッシュの最初の2バイトがゼロになるように追加を探します。 そのような複雑さです。 数分間動作し、実際にハッシュを生成します。ハッシュは、トランザクションのバイトとカウンターを連結することですばやく確認できます。
プログラムコードpackage 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
. , .