Pull to refresh

Comments 4

Парсинг, логгинг, мультипроцессинг - код обмазан всем этим, как корпоративная версия FizzBuzz.

Вот простенький однопоточний чисто питоний скрипт, который иллюстрирует, как это можно делать быстро.

from string import digits, ascii_letters, punctuation
from hashlib import sha256
from random import shuffle
from time import time

def helper(data, chars):
    for data[-4] in chars:
        for data[-3] in chars:
            for data[-2] in chars:
                for data[-1] in chars:
                    if sha256(data).hexdigest().startswith("000000"):
                        cnt = 0
                        for i in range(-4, 0):
                            cnt = cnt * len(chars) + chars.index(data[i])
                        return data, cnt
    return "Не шмогла!".encode(), len(chars) ** 4

data = bytearray(("Начальное значение!" + "1234").encode())
chars = list((digits + ascii_letters + punctuation).encode())
shuffle(chars)
t = time()
data, cnt = helper(data, chars)
t = time() - t
print(f"'{data.decode()}'\n'{sha256(data).hexdigest()}'")
print(f"время: {t:5.3f}, hashrate: {cnt / t / 1e3:5.3f} kH/s")

Пояснения:

да, длина суффикса и длина лидирующего цуга нулей захардкожена

я ограничился подбором 6, а не 8 лидирующих нолей - времени жалко )

shuffle(chars) здесь для того, чтоб не казалось, что это чит, т.е. подобраные значения для быстрого выхлопа

не надо каждый раз внутри цикла делать .encode() и конкатенировать строки - это азы

не надо внутри цикла вызывать простенькую функцию, если её можно заинлайнить, вызов функции в питоне - довольно дорогостоящая операция

Да вы правы, в прототипах есть накладные расходы, связанные с конкатенацией строк, преобразованием строки в последовательность байт и вызовом python функции. Но в окончательном варианте всего этого нет. Там используется C функция get_value, вызов которой обходится гораздо дешевле и она меняет строку in place, без дополнительной памяти.

По поводу сложности нахождения хеш суммы с первыми 6 нулями. Вероятность нахождения хеш суммы экспотенциально падает с каждым определенным битом. Окончательный вариант находит первую хеш сумму с 6 нулями за 12.28 секунд:

python blockchain.py -e 000000 -w 4
2022-06-02 07:44:43.640 MSK [INFO    ] blockchain Start
2022-06-02 07:44:43.640 MSK [DEBUG   ] blockchain Start thread 1, round 0
2022-06-02 07:44:43.641 MSK [DEBUG   ] blockchain Start thread 2, round 0
2022-06-02 07:44:43.641 MSK [DEBUG   ] blockchain Start thread 3, round 0
2022-06-02 07:44:43.641 MSK [DEBUG   ] blockchain Start thread 4, round 0
2022-06-02 07:44:55.920 MSK [INFO    ] blockchain Success "Начальное значение!en`#!" hash: 000000370a0f76688fb13e5f2694d7dc571603a281e063640cdeb11a458b0255 Hash rate 6581.497 kH/s

И статья все таки больше, про то как, писать C-extension в Python, а расчет sha256 взят в качестве примера.

nit: вместо вложенных циклов,

for data[-4:] in itertools.combinations_with_replacement(chars, 4):

Оч. хорошо во всех отношениях, кроме скорости (за неё копья ломаем). Хуже того: можно оставить внутренний цикл, а внешние заменить на вот это вот - и всё равно будет ощутимый проигрыш, по крайней мере на моём компе. Должно быть, что-то не помещается в какие-то кэши.

Sign up to leave a comment.