Как Сделать Свой Собственный Блокчейн. Часть 1. Создание, Хранение, Синхронизация, Отображение, Майнинг И Доказательство Работы

Всем привет! Здесь мы потихоньку начали изучать совершенно новое для нас направление обучения — блокчейны — и нашли то, что оказалось интересным в рамках нашего курса по Питон , включая.

Чем, собственно, и хотим с вами поделиться.



Как сделать свой собственный блокчейн.
</p><p>
 Часть 1. Создание, хранение, синхронизация, отображение, майнинг и доказательство работы

Я могу узнать, когда я получил свой первый биткойн, из истории кошелька в моей учетной записи Coinbase — входящая транзакция в 2012 году в качестве подарка за регистрацию.

Биткойн в то время стоил около $6,50. Если бы я сохранил эти 0,1 BTC на момент написания статьи, они бы уже стоили более 500 долларов.

Если кому-то интересно, я продал их, когда биткойн стоил 2000 долларов.

Таким образом, я получил только 200 долларов вместо возможных сейчас 550 долларов.

Не нужно было спешить.

Я знал о существовании Биткойна, но особо не интересовался.

Я видел, как курс доллара к BTC рос и падал.

Я видел, как люди говорили, что за этим будущее, и видел статьи о его полной бессмысленности.

Но у меня не было личного мнения – я просто наблюдал со стороны.

Точно так же я не особо слежу за блокчейнами.

Но в последнее время мой отец несколько раз упомянул, что CNBC и Bloomberg, которые он смотрит по утрам, часто говорят о блокчейнах, а он понятия не имеет, что это такое.

И тут я вдруг понял, что мне нужно разобраться в этой теме немного глубже.

И начал я с «исследований» — прочитал в Интернете огромное количество статей, объясняющих их суть.

Некоторые были хорошими, некоторые плохими, некоторые глубокими, а некоторые очень поверхностными.

Чтения было недостаточно, и если я что-то и знаю наверняка, так это то, что чтение не объяснит и сотой доли того, что может программирование.

И вот я понял, что стоит написать свой локальный блокчейн.

Необходимо учитывать, что существует большая разница между базовым блокчейном, который я описываю, и «профессиональным» блокчейном.

Эта цепочка не будет создавать криптовалюту.

Блокчейны не требуют производства монет, которые можно продать и обменять на физические деньги.

Блокчейны используются для хранения и проверки информации.

Монеты поощряют узлы участвовать в валидации, но их присутствие не является обязательным.

Пишу пост по нескольким причинам: 1) Чтобы люди, которые его читают, могли больше узнать о блокчейнах; 2) Чтобы я мог понять больше, объясняя код, а не просто написав его.

В этом посте я покажу метод хранения данных блокчейна и генерации начального блока, синхронизации узла с локальными данными блокчейна, сопоставления блокчейна (который позже будет использоваться для синхронизации с другими узлами), а затем майнинга и создания действительных новых блоки.

Других узлов в первом посте не будет. Никаких кошельков, пиров, важных данных.

О них мы поговорим позже.

В двух словах Если вы не хотите вдаваться в подробности и читать код или наткнулись на этот пост, ожидая статьи, которая объяснит блокчейны понятным языком, я попытаюсь кратко изложить, как они работают. На самом высоком уровне блокчейн — это база данных, в которой каждый участник блокчейна может хранить, просматривать, проверять и никогда не удалять данные.

На более низком уровне данные в этих блоках могут быть любыми, если это позволяет конкретный блокчейн.

Например, данные в блокчейне Биткойн представляют собой исключительно транзакции Биткойн между учетными записями.

Блокчейн Ethereum допускает как транзакции, подобные Ether, так и транзакции, используемые для запуска кода.

Прежде чем блок будет создан и объединен с блокчейном, он подтверждается большинством людей, работающих над блокчейном — их называют узлами.

Настоящий блокчейн — это цепочка, состоящая из огромного количества блоков, подтвержденная большинством узлов.

Таким образом, если узел попытается изменить данные предыдущего блока, новые блоки не будут действительными, и узлы не будут доверять данным из недействительного блока.

Не волнуйтесь, если это сбивает с толку.

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

Если вы хотите узнать код, посмотрите ветку часть 1 на Гитхабе.

Не стесняйтесь присылать мне любые вопросы, комментарии, правки или похвалы (если вы настроены на что-то особенно приятное) или просто пишите мне в Твиттере.

Шаг 1 — Классы и файлы Первый шаг — написать класс, который обрабатывает блоки при запуске узлов.

Я назову этот класс Block. Честно говоря, вам не нужно много делать.

В функции __init__ будем верить, что вся необходимая информация уже предоставлена в словаре.

Для производственного блокчейна это не самое мудрое решение, но в качестве примера подойдет, потому что код пишу только я.

Я также напишу метод, который упаковывает важную информацию о блоке в словарь, а затем создам более удобный способ отображения информации о блоке при ее печати на терминале.

  
  
  
  
  
  
  
  
  
   

class Block(object): def __init__(self, dictionary): ''' We're looking for index, timestamp, data, prev_hash, nonce ''' for k, v in dictionary.items(): setattr(self, k, v) if not hasattr(self, 'hash'): #in creating the first block, needs to be removed in future self.hash = self.create_self_hash() def __dict__(self): info = {} info['index'] = str(self.index) info['timestamp'] = str(self.timestamp) info['prev_hash'] = str(self.prev_hash) info['hash'] = str(self.hash) info['data'] = str(self.data) return info def __str__(self): return "Block<prev_hash: %s,hash: %s>" % (self.prev_hash, self.hash)

Чтобы создать первый блок, давайте запустим этот простой код:

def create_first_block(): # index zero and arbitrary previous hash block_data = {} block_data['index'] = 0 block_data['timestamp'] = date.datetime.now() block_data['data'] = 'First block data' block_data['prev_hash'] = None block = Block(block_data) return block

Большой.

Последний вопрос в этой части — где хранить данные в файловой системе.

Это необходимо, если мы не хотим потерять данные локального блока при отключении узла.

Я назову папку данных «chaindata», что в некоторой степени имитирует схему папок Etherium Mist. Каждому блоку теперь присвоен отдельный файл, названный по его индексу.

Вам необходимо убедиться, что имена файлов содержат достаточное количество начальных нулей, чтобы блоки были перечислены по порядку.

Учитывая приведенный выше код, для создания первого блока нужно написать следующее:

#check if chaindata folder exists. chaindata_dir = 'chaindata' if not os.path.exists(chaindata_dir): #make chaindata dir os.mkdir(chaindata_dir) #check if dir is empty from just creation, or empty before if os.listdir(chaindata_dir) == []: #create first block first_block = create_first_block() first_block.self_save()

Шаг 2 — Синхронизация блокчейна, локально Прежде чем вы сможете начать добычу, интерпретацию данных или отправку/создание новых данных в цепочку, узел должен быть синхронизирован.

В нашем случае других узлов нет, поэтому я говорю только о чтении блоков из локальных файлов.

В будущем частью синхронизации будет не только чтение файлов, но и общение с узлами для сбора блоков, сгенерированных, пока ваш узел не работал.



def sync(): node_blocks = [] #We're assuming that the folder and at least initial block exists chaindata_dir = 'chaindata' if os.path.exists(chaindata_dir): for filename in os.listdir(chaindata_dir): if filename.endswith('.

json'): #.

DS_Store sometimes screws things up filepath = '%s/%s' % (chaindata_dir, filename) with open(filepath, 'r') as block_file: block_info = json.load(block_file) block_object = Block(block_info) #since we can init a Block object with just a dict node_blocks.append(block_object) return node_blocks

Пока все просто и красиво.

Чтение строк из файлов и загрузка их в структуры данных не требует слишком сложного кода.

Пока это работает. Но в будущих постах, где я буду писать о коммуникационных возможностях разных узлов, эта функция синхронизации станет гораздо сложнее.

Шаг 3 — Отображение блокчейна Теперь наш блокчейн находится в памяти, и я хочу отобразить цепочку в браузере.

Есть две причины сделать это сейчас.

Сначала вам необходимо подтвердить в браузере, что изменения произошли.

Во-вторых, я буду использовать браузер в будущем для просмотра и выполнения любых транзакций, связанных с блокчейном.

Например, отправка транзакций или управление кошельком.

Для этого я использую Flask — у него низкий барьер входа, и я решил, что для наших целей он подходит. Ниже приведен код для отображения json блокчейна.

Я проигнорирую импорт, чтобы сэкономить место.



node = Flask(__name__) node_blocks = sync.sync() #inital blocks that are synced @node.route('/blockchain.json', methods=['GET']) def blockchain(): ''' Shoots back the blockchain, which in our case, is a json list of hashes with the block information which is: index timestamp data hash prev_hash ''' node_blocks = sync.sync() #regrab the nodes if they've changed # Convert our blocks into dictionaries # so we can send them as json objects later python_blocks = [] for block in node_blocks: python_blocks.append(block.__dict__()) json_blocks = json.dumps(python_blocks) return json_blocks if __name__ == '__main__': node.run()

Запустите этот код, перейдите по адресу localhost:3000/blockchain.json и просмотрите текущий блок.

Шаг 4 – «Майнинг», также известный как создание блока На данный момент существует только исходный блок, но если у нас есть больше данных, которые необходимо хранить и распространять, нам нужен способ включить их в новый блок.

Вопрос в том, как создать новый блок и подключить его к предыдущему.

Сатоши описывает это в официальном документе Биткойна.

Обратите внимание, что «сервер меток времени» называется «узлом».

«Начнем описание нашего решения с временной метки сервера.

Его задача — хешировать блок данных, которому необходимо поставить метку времени, и публично опубликовать этот хеш.

Временная метка показывает, что в тот момент конкретные данные существовали и поэтому попали в хэш блока.

Каждый хеш включает в себя предыдущую временную метку: так строится цепочка, в которой следующее звено усиливает все предыдущие».

Скриншот изображения прикреплен под описанием:

Как сделать свой собственный блокчейн.
</p><p>
 Часть 1. Создание, хранение, синхронизация, отображение, майнинг и доказательство работы

Основная идея раздела заключается в том, что когда нам нужно соединить блоки, мы создаем хеш информации о новом блоке, включая время создания блока, хеш предыдущего блока и информацию в самом блоке.

.

Всю эту информацию я назову «заголовком» блока.

Таким образом, мы можем проверить корректность блока, посчитав все хеши перед ним, подтверждая последовательность.

В этом случае заголовок, который я создаю, объединяет значения строки в одну огромную строку.

Я включил следующие данные:

  1. Индекс, показывающий, какой это блок;
  2. Хэш предыдущего блока;
  3. Данные представляют собой просто случайные строки.

    Для биткойна они называются корнями Меркла и содержат информацию о транзакциях;

  4. Временная метка майнинга этого блока.



def generate_header(index, prev_hash, data, timestamp): return str(index) + prev_hash + data + str(timestamp)

Уточню один момент – для создания заголовка не обязательно объединять строки информации.

Требование состоит в том, чтобы каждый знал, как генерировать заголовок блока и хеш предыдущего блока внутри него.

Это сделано для того, чтобы каждый мог проверить правильность хеша в новом блоке и подтвердить связь между двумя блоками.

Биткойн-заголовок гораздо сложнее, чем конкатенация строк.

Он использует хэши данных и времени и привязан к тому, как данные расположены в памяти.

Но в нашем случае достаточно объединения строк.

Теперь у нас есть заголовок, и мы можем вычислить достоверность хеша.

Я буду использовать другой метод, чем Биткойн, но все равно буду запускать заголовок блока через функцию sha256.

def calculate_hash(index, prev_hash, data, timestamp, nonce): header_string = generate_header(index, prev_hash, data, timestamp, nonce) sha = hashlib.sha256() sha.update(header_string) return sha.hexdigest()

Чтобы добыть блок, мы используем приведенную выше функцию, чтобы получить хеш, поместить его в новый блок и сохранить этот блок в каталоге Chaindata.

node_blocks = sync.sync() def mine(last_block): index = int(last_block.index) + 1 timestamp = date.datetime.now() data = "I block #%s" % (int(last_block.index) + 1) #random string for now, not transactions prev_hash = last_block.hash block_hash = calculate_hash(index, prev_hash, data, timestamp) block_data = {} block_data['index'] = int(last_block.index) + 1 block_data['timestamp'] = date.datetime.now() block_data['data'] = "I block #%s" % last_block.index block_data['prev_hash'] = last_block.hash block_data['hash'] = block_hash return Block(block_data) def save_block(block): chaindata_dir = 'chaindata' filename = '%s/%s.json' % (chaindata_dir, block.index) with open(filename, 'w') as block_file: print new_block.__dict__() json.dump(block.__dict__(), block_file) if __name__ == '__main__': last_block = node_blocks[-1] new_block = mine(last_block) save_block(new_block)

Готовый! Но при таком типе создания блоков любой, у кого самый быстрый процессор, сможет создавать самые длинные цепочки, которые другие узлы сочтут действительными.

Нам нужен способ снизить скорость создания и подтверждения блока перед переходом к следующему блоку.

Шаг 5 — Доказательство работы Чтобы снизить скорость, я использую Proof of Work, как и Биткойн.

Подтверждение права собственности — это еще один метод, используемый в блокчейнах для достижения консенсуса, но в данном случае я воспользуюсь работой.

Способ сделать это — установить требования к хэш-структуре блока.

Как и в случае с биткойнами, вам необходимо убедиться, что хеш начинается с определенного количества нулей, прежде чем переходить к следующему.

А для этого нужно добавить в заголовок дополнительную информацию — случайно выбранное число (nonce).



def generate_header(index, prev_hash, data, timestamp, nonce): return str(index) + prev_hash + data + str(timestamp) + str(nonce)

Теперь функция майнинга настроена на создание хеша, но если хеш блока не содержит достаточного количества нулей, мы увеличиваем значение nonce, создаем новый заголовок, вычисляем новый хеш и проверяем, достаточно ли нулей.



NUM_ZEROS = 4 def mine(last_block): index = int(last_block.index) + 1 timestamp = date.datetime.now() data = "I block #%s" % (int(last_block.index) + 1) #random string for now, not transactions prev_hash = last_block.hash nonce = 0 block_hash = calculate_hash(index, prev_hash, data, timestamp, nonce) while str(block_hash[0:NUM_ZEROS]) != '0' * NUM_ZEROS: nonce += 1 block_hash = calculate_hash(index, prev_hash, data, timestamp, nonce) block_data = {} block_data['index'] = int(last_block.index) + 1 block_data['timestamp'] = date.datetime.now() block_data['data'] = "I block #%s" % last_block.index block_data['prev_hash'] = last_block.hash block_data['hash'] = block_hash block_data['nonce'] = nonce return Block(block_data)

Большой.

Новый блок содержит действительный одноразовый номер, чтобы другие узлы могли подтвердить хэш.

Мы можем генерировать, хранить и распространять новый блок среди других.

Заключение Вот и все! На данный момент. В блокчейнах еще есть много вопросов и особенностей, которые я не объяснил.

Например, как задействовать другие узлы? Как узлы передают данные, включенные в блок? Существуют ли другие способы хранения данных, кроме огромных строк данных? На эти вопросы будут даны ответы в будущих частях этой серии постов, когда я сам найду ответы.

Вы можете написать мне в Твиттере, в комментарии к посту или через форму обратной связи! Спасибо моей сестре Саре за разъяснения вопросов о блокчейнах и помощь в редактировании поста! КОНЕЦ Комментарии и вопросы, как всегда, приветствуются как здесь, так и на день открытых дверей.

Теги: #blockchain #python #blockchain

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.