Что можно сделать в этом случае?
Ну самый простой вариант - сделать распределенную сеть и разослать целиком цепочку при помощи p2p всем кто захочет ее хранить. В этом случае если злоумышленник перепишет цепочку и попытается ее подменить, разослав кому либо, то остальные не примут ее, так как у большинства blockchain будет отличаться от неправильной. Но опять же, злоумышленник достаточно могуществен и может сделать узлов которые будут отсылать неправильную цепочку больше чем те кто хранит правильную, таким образом неправильная цепочка будет иметь больший вес и в итоге заменить правильную. Это называется атака 51% на сеть.
Для того чтобы усложнить обсчет ввели такое понятие как доказательство работы или Proof of Work(PoW).
Смысл PoW заключается в том, что-бы перед добавлением блока в blochain была выполнена некая продолжительная работа, как пример - было вычитано некое огромное число подходящие под определенные требования и это занимало некоторое количество времени.
Тем самым замедлится образование блоков и всю цепочку нельзя будет так быстро перестроить с новыми данными. Но это работает только в том случае, если цепочка продолжает строиться то есть является динамической и продолжает расти или сложность вычисления превышает все мыслимые пределы.
Теперь рассмотрим следующий пример для понимания всего выше написанного.
Допустим для того чтобы нельзя было перестроить всю цепочку моментально, мы ввели параметр, что для построения нового блока необходимо 10 минут высчитывать некое число по алгоритму. То есть если мы хотим добавить блок к цепочке, нам нужно 10 минут греть воздух считая данные и получив некий результат этих вычислений. Результат должен быть такой, чтобы его сложно было вычислить, но вычислив - легко проверить. После получения этого результата он записывается в блок и остальные кто участвует в хранении blockchain могут легко проверить, результат вычислен правильно или нет, если результат правильный, то все кто хранит цепочку добавляют этот блок, если нет - то просто откидывают. Теперь возникает проблема у злоумышленника, если он хочет поменять 6 блок от вершины blockhain(а блокчеин растет вверх, по этому последний блок является самым верхним) то ему придется пересчитать все 6 блоков, а это займет уже 60 минут, в тоже время, образование нового блока занимает 10 минут и злоумышленник никак не сможет изменить цепочку, так как у него будет постоянно отставание в 6 блоков.
Ок, допустим кто то настолько могуществен и ставит 6 компов чтобы искать в 6 раз быстрее и таким образом он сможет искать блок в 6 раз быстрее, не 10 минут, а приблизительно за 1.5, в этом случае существует механизм изменения сложности поиска блока, который автоматически увеличивает сложность в 6 раз и тем самым увеличивая мощность распределенной сети, которая ищет значение подходящее для Proof fo work увеличивается и сложность поиска бока, если вычислительная мощность сети уменьшается то и сложность поиска блока автоматически уменьшается.
Почему я написал, что blockchain не должен быть заброшен, если никто кроме злоумышленника не ведет поиск блоков, то в итоге со временем он перепишет всю цепочку, если параллельно с ним ведется также поиск блока, то сложность подмены начинает возрастать многократно.
Теперь распишу самый постой алгоритм Proof of Work:
В прошлой статье был образован hash в который входит hash предыдущего блока и данных в текущем блоке и этот hash записывается в текущий блок.
А что если мы попробуем найти какой нить красивый(золотой) hash, например с 3мя нулями перед ним.А для этого возьмем простой перебор будем к текущему hash строчке прибавлять 0, потом 1, потом 2 и т.п. после чего создаем новый хеш и так пока не найдем любой хеш который начинается с трех нулей. Вот это число(а оно по науке называется nonce), которое добавляем и является тем уникальным числом которое является Proof of work.
Дальше добавляем его в блок, чтобы движок blockchain мог проверить и если все правильно, то блок будет добавлен в цепочку.
Про понятие targer(цель) и динамическое изменение цели, будет в следующей статье.
Теперь немного кода, как это может выглядеть:
Для начала модифицируем вид блока, теперь он будет выглядеть вот так:
class Block { byte[] hash; // хеш текущего блока BigInteger nonce; // число которое необходимо найти byte[] target; // цель String data; // данные }
Ну а теперь собственно сделаем функцию которая будет искать число nonce(некоторые проверки опущены, ибо код тогда станет слишком большим, главное же идея!):
public BigInteger proofOfWork(byte[] target, Block block) { BigInteger nonce = BigInteger.valueOf(0); // задаем стартовое значение nonce while(true) { String stringforpow = block.getHash() + nonce.toString(); // добавили nonce к строчке byte[] newhash = sha256(stringforpow); //получаем хеш if (newhash <= target) { // если новый hash меньше цели или равен цели мы нашли значение nonce для PoW
return nonce; // значение нашли - выходим из цикла { }
return -1; }
Добавление в цепочку с проверкой теперь выглядит следующим образом:
public boolean addBlockToChain(ArrayList<Block> blockchain, String data) { Block currentblock; // инициируем блок currentblock.hash = CreateHash(blockchain.get(blockchain.size()-1).hash, data); // создаем хеш из предыдущего хеша и данных currentblock.data = data; // добавляем данные в блок currentblock.target = new String("000fff...ffff").toByteArray; // заполняем цель BigInteger nonce = proofOfWork(currentblock.target, currentblock); // высчитываем nonce if(nonce != -1) { currentblock.nonce = nonce; // нашли, заполняем поле nonce return true; } return false; }
И наконец проверка блока в цепочке, это совсем просто:
public boolean checkNonce(Block block) { String stringforpow = block.hash + block.nonce; // создаем строчку для проверки byte[] hashforcheck = sha256(stringforpow); // получаем новый хеш для проверки if (hashforcheck <= target) { // если новый hash меньше цели return true; // nonce валидный { } return false; // ытаются обмануть }
Вот так в принципе используется проверка Proof of work.
Комментариев нет:
Отправить комментарий