Доказателство за работа (Proof of work)
Биткойн протоколът определя параметри за вида на хеша на хедъра на всеки блок. Неговият хеш трябва да бъде по-малък от предварително зададено число. Казано по друг начин, въпросният хеш трябва да започва с определен брой нули. Примерно един валиден хеш може да изглежда така:
000000000000002e9067f1cf7252333f7aeb619c89d220985a70ac0e015248e0
Всеки блок, чийто хеш в хедъра не започва с указания брой нули, ще бъде отхвърлен от мрежата. Броят на нулите се променя динамично от протокола на всеки две седмици в опит да поддържа средно време за откриване на блок от 10 минути. От тук идва и терминът „трудност на мрежата“: колкото повече нули се изискват, толкова по-висока е трудността за копаене.
Така, да преговорим как създаваме валиден блок като копачи: проверили сме за достоверност всички получени от нас транзакции, подредили сме ги в Merkle Tree, открили сте Root Hash-а на това дърво, добавили сме го в хедъра на блока, заедно с хеша на предишния блок и Nonce число. Хешираме последните три, но… полученият хеш не започва с необходимия брой нули….! Както се вика „Shit“… Какво правим?
Тук идва ролята на въпросното число – Nonce. В случая то е просто случайно число, добавено в главната част на блока, с цел да увеличаваме неговата стойност в опит да открием валиден хеш, започващ с определения брой нули. Ако първият опит за създаване на валиден хеш се провали, просто добавяме единица към него и създаваме нов хеш, като отново проверяваме дали той е валиден. Да предположим например, че искаме да намерим хеш-а на “Hello, world!” така, че той да съдържа най-малко три нули в началото. Ако получим хеш, който не отговаря на условието, добавяме единица към стойността на Nonce и хешираме отново.
„Hello, world!0“ => 1312af178c253f84028d480a6adc1e25e81caa44c749ec81976192e2ec934c64
„Hello, world!1“ => e9afc424b79e4f6ab42d99c81156d3a17228d6e1eef4139be78e948a9332a7d8
„Hello, world!2“ => ae37343a357a8297591625e7134cbea22f5928be8ca2a32aa475cf05fd4266b7
…
„Hello, world!4248“ => 6e110d98b388e77e9c6f042ac6b497cec46660deef75a55ebc7cfdf65cc0b965
„Hello, world!4249“ => c004190b822f1669cac8dc37e761cb73652e7832fb814565702245cf26ebb9e6
„Hello, world!4250“ => 0000c3af42fc31103f1fdc0151fa747ff87349a4714df7cc52ea464e12dcd4e9
Този пример ни отне 4251 опита в търсенето на такава стойност на Nonce, която присъединена към “Hello, world!” да върне изходящ низ, започващ най-малко с три нули. Обърнете внимание, че целият блок с транзакциите не се пресмята отново с всеки опит. Това е съществено за Биткойн копаенето – хешираме само хедъра на блока, отново и отново, докато някой миньор в мрежата успее да създаде валиден хеш, започващ с толкова нули, колкото изисква трудността на мрежата към този момент.
Когато успее, той вика „Бинго“! Всъщност копачките едва ли имат говорители, така че просто предават блока на всеки от останалите пиъри в мрежата. Всички останали миньори проверяват работата му, за да се уверят, че тя е валидна. Ако нямат забележки, те добавят новия блок в локалното си копие на публичната книга (блок-веригата) и започват да приемат транзакции за съставянето на следващия блок и да се състезават с надеждата, този път те да имат късмета да намерят заветния хеш първи.
В зората на Биткойн миньорите са извършвали изчисленията на базата на SHA256-алгоритъма посредством процесорите на техните компютри. Колкото повече хешове в секунда можете да изчислите, толкова по-голям е шансът да “изкопаете” блок и да спечелите съответната награда. Копаенето с процесори бързо отстъпи място на това с видеокарти, които се оказаха доста по-ефективни в изчисленията. Съвременните миньори използват специализиран хардуер – ASICs (application specific integrated circuits), за да копаят биткойни. Тези устройства представляват създадени специално за целта компютърни чипове, които са проектирани да изпълняват SHA256 изчисления и нищо друго. Не е рядкост да видите миньор, който притежава изчислителна мощ от над един трилион хеша в секунда (един терахеш – 1 TH/s). Към момента (02.2014) общата изчислителна мощ на мрежата е 2.61 петахеша в секунда (2.61 PH/s).
Значението на Coinbase транзакцията
Първата транзакция във всеки блок се нарича “coinbase” транзакция. Това е транзакция, при която миньорът изпраща на себе си 25 биткойна, създадени “от нищото”. Тъй като всеки миньор прави това към собствения си адрес, първата транзакция във всеки блок ще се различава за всеки миньор. Припомнете си характеристиките на криптографската хеш-функция: най-малката промяна във входящия масив води до напълно различен хеш. Тъй като хешът на “coinbase” транзакцията в основата на Merkle trees е различен за всеки миньор, следователно и цялото Merkle tree, включително и Root Hash-а ще бъде различен за всеки миньор. Това значи, че стойността на Nonce, необходима за пресмятането на валиден блок, също ще бъде различна за всеки миньор. Така всеки спокойно може да почне с nonce=1 и да го увеличава, като знае, че математически не губи нищо спрямо другите. Ако даден компютър прави два пъти повече операции в секунда от друг, то вероятността той да намери първи хеш на блока с определения брой нули, е два пъти по-голяма.
Смисълът на Merkle Tree
Каква е идеята зад Merkle Tree? Хедъра на дървото случи като уникален подпис на всички съдържащи се транзакции в него. Би било възможност да се търси хеш на всички транзакции плюс nonce плюс хеша от предния блок, но това би било огромно количество данни за изчисляване на всеки хеш. Тъй като хедъра на Меркле дървото играе ролята на уникален идентификатор на транзакциите в него, се изпозлва само хедъра за входящ параметър, който да представя всички транзакции. Разбира се, когато някой изкопае блок и го предостави на другите в мрежата, всеки един проверява, дали новото дърво е конструирано правилно според принципите на Merkle.
Хеш верига
Хешът на един блок е включен в главната част на всеки следващ. Схематично това изглежда така:
Ако злонамерен потребител иска да подправи или премахне транзакция, която вече е в блок-веригата, промяната ще доведе до това, че хешът на транзакцията ще създаде промени по целия път нагоре до Merkle Root-a. Практически е невъзможно ново-полученият хедър да създаде валиден хеш (доказателство за работа). От тук следва, че нападателят ще има нужда да пресъздаде (изчисли хешовете) на целия главен блок и да изгуби огромно количество време, за да открие точната стойност на Nonce. Но нека предположим, че това се случи. Може ли той обаче да излъчи подправения блок в мрежата и да се надява, че миньорите ще заместят стария такъв с новия, или че новите потребители ще изтеглят подправения блок? Отговорът е не. Причината за това е, че хешът на всеки блок е включен в главната част на следващия. Ако нападателят промени блок номер 100, това ще доведе до промяна в главната част на блок 101, което от своя страна ще доведе до промяна на главната част на блок 102 и т.н., по целия път на блок-веригата. Всеки опит за промяна на съществуваща транзакция в блок-веригата изисква не просто промяна на блока, съдържащ транзакцията, но и промяна на всички следващи блокове. В зависимост от това, колко назад във веригата е една сделка, това може да отнеме на атакуващия седмици, месеци или дори години, за да промени цялата останала част от блок-веригата. Както споменах и в първата част, докато нападателят не контролира по-голямата част от изчислителната мощ на мрежата, останалата част от нея ще добавя нови блокове в основната верига по-бързо, отколкото той ще може да добавя в подправената верига. Това гарантира, че легитимната верига остава най-дълга, а веригата на нападателя се игнорира.
В последната част на тази статия, ще разгледаме значението на вездесъщите шест потвърждения в блок веригата.