вторник, 22 августа 2017 г.

Цель!

   В прошлой статье обсудили как используется алгоритм Proof of work, который необходим для препятствования подделки блоков. Теперь поговорим о такой вещи, о которой я упоминал в прошлой статье, как target или Цель. Цель необходима для того, что бы было с чем сравнивать результат работы.

   Целью обычно является так называемый "красивый" hash, например c 3мя нулями в начале ну или с 6!
Вот этот хеш будет красивым:
000009dc579e44af002d37461102d9c62d6516c4ab21753454acc8a9ec4727dd

   Теперь как получить красивый hash , для этого нужна цель, ниже которой будут возникать нули в начале hash строки, цель обычно указывается в виде 16ричного числа в отдельном поле блока под названием bits - например 1e0fffff и в зависимости от цели при помощи алгоритма регулируется сложность, которая влияет на время нахождения красивого hash. Так как hash с 3 нулями на насколько порядков легче найти чем hash с 8ю нулями в начале.
 
   Собственно алгоритм вычисления цели выглядит следующим образом:
target = mantissa * 2^(8 * exponent - 3))
Число которое пишется в блок в виде цели, это 2 числа, для приведенного выше:
1e - это экспонента
0fffff - это мантиса
Ну и по формуле высчитываем, что получится. В 16 ричном формате target выглядит вот так:
00000fffff000000000000000000000000000000000000000000000000000000

Hash хоть и выглядит устрашающе в 16ричном формате, но это всетаки число и его можно сравнить с целю, в случае если hash меньше target то значит мы нашли этот хеш который нам нужен и nonce в блоке верный.
Добавляем его к блоку и обретаем щасте!
Проверить собственно легко, берем хеш всего блока(кроме заголовка в виде hash) и высчитываем хеш, должен получиться точно такойже как в заголовке блока. Nonce у нас уже будет в блоке и его считать не надо. После чего берем цель и сравниваем ее с тем что получилось, если hash блока меньше чем цель, то значит все правильно и блок валидный, если нет, то его можно отбросить.

   Но чаще всего случается такое, что красивый hash невозможно найти, даже перебрав всевозможные nonce, что в этом случае делать? Для этого сделали дырку в виде supernonce в призовой транзакции, но об этом будет в статье про транзакции.

А теперь получение цели в псевдокоде и проверка блока:

public BigInteger calculateTarget(String strtarget) {
        BigInteger trg = new BigInteger(Hex.decode(strtarget)); // переводим строку в число
        BigInteger exp = trg.shiftRight(24); // получаем экспоненту при помощи сдвига
        BigInteger mantis = trg.and(BigInteger.valueOf(0xffffff)); // получаем экспоненту при помощи логического and
        BigInteger t1 = BigInteger.valueOf(8).multiply(exp.subtract(BigInteger.valueOf(3))); // вычисляем правую часть в скобках
        BigInteger t2 = BigInteger.valueOf(1).shiftLeft(t1.intValue()); // вычисляем левую часть уровнения
        BigInteger target = mantis.multiply(t2); // перемножаем

        return target;

}

А теперь проверка:

public boolean checkBlock(ArrayList<Block> blockChain, Block block) {
       if(blockChain.size() != 0) { // если размер blockchain не равен нулю то проверяем совпдаения хеша с предыдущим
            if(!blockChain.get(blockChain.size()-1).getHash().equals(block.getPreviousHash())) {
                return false;
            }
        }
       byte[] hash = sha256(createHashForBlock(block)); // получаем хеш из новой функции в которой мы складываем все поля блока

       BigInteger target = calculateTarget(block.getTarget()); // получаем target
       BigInteger hashready = new BigInteger(1,hash); // переводим из массива байтов в число
     if(target.compareTo(hashready) == 1) { // если цель больше hash то все хорошо
        
            if(blockhash.equals(block.getHash())) { // hash посчитаный должен совпадать с хешем записанном в блоке
                return true; // проверка пройдена
            }
        }
        return false; // проверка не пройдена
}
После этой проверки можно добавлять блок в blockchain и записывать на диск.

Комментариев нет:

Отправить комментарий