Целью обычно является так называемый "красивый" 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; // проверка не пройдена }
Комментариев нет:
Отправить комментарий