Як зробити blockchain

Скільки коштує створити блокчейн?

Скільки коштує створення блокчейн-додаток

СтадіяОцінка в годинникуприблизна вартість
Аналіз бізнес логіки проекту40 годин50 000 руб.
UI/UX дизайн211 годин598000 руб.
Стадія розробки програми1305 годин4036500 руб.
Тестування630 годин777 000 руб.

Що потрібно, щоб стати Blockchain розробником?

Щоб претендувати на посаду блокчейн-розробника, потрібно вміти програмувати (і не обов'язково йти з головою у full-stack — достатньо однієї зі згаданих мов), розбиратися в архітектурі, знати технології, що лежать в основі блокчейну та мати практичний кейс розробки смарт-контрактів (дуже бажано).

Як створюється блок у блокчейні?

Блоки в блокчейні, наприклад, при випуску криптовалют, створюються за допомогою процедури майнінгу. Створенням блоків у великих мережах займаються спеціальні особи – майнери.

http://book. itep. ru – ІТЕФ
4.6.6 Технологія blockchain [1]

Як зробити свій блокчейн. Частина 1 — Створення, Зберігання, Синхронізація, Відображення, Майнінг та Доказова робота

Доброго всім! Ми тут потихеньку почали досліджувати новий для нас напрям для навчання — блокчейни і знайшли те, що виявилося цікавим у рамках нашого курсу з Python, у тому числі. Чим, власне, хочемо поділитися з вами.

Я можу дізнатися, коли у мене з'явився перший Bitcoin, з історії гаманця в моєму обліковому записі на Coinbase — транзакція, що входить у 2012 році в подарунок за реєстрацію. Bitcoin тоді коштував близько 6.50$. Якби я зберіг ті 0.1 BTC, на момент написання статті це вже коштувало б більше 500$. Якщо комусь цікаво, я продав їх, коли Bitcoin коштував 2000 $. Так що я отримав лише 200$ замість нині можливих 550$. Не варто було поспішати.

Про існування Bitcoin я знав, але особливо не цікавився. Я бачив злети та падіння курсу $/BTC.Я бачив, як люди кажуть, що за ним майбутнє, а бачив статті про його повну безглуздість. Але особистої думки у мене не було – просто спостерігав із боку.
Так само я майже не стежив за блокчейнами. Але останнім часом мій батько кілька разів згадував, що на CNBC і Bloomberg, які він дивиться вранці, часто розповідають про блокчейни, і він гадки не має, що це.

І тоді я раптово зрозумів, що треба трохи глибше розібратися у цій темі. І почав із “дослідження” — прочитав величезну кількість статей в інтернеті, що пояснює їхню суть. Деякі були хороші, деякі погані, деякі глибокі, деякі дуже поверхові.

Читання виявилося недостатньо, а якщо існує одна річ, яку я знаю напевно, то це те, що читання не пояснить і сотої частки того, що пояснить програмування. І так я зрозумів, що варто написати власний локальний блокчейн.

Потрібно враховувати, що є велика різниця між базовим блокчейном, який я описую та “професійним” блокчейном. Цей ланцюг не створить криптовалюту. Блокчейни не вимагають виробництва монет, які можна продавати та міняти на фізичні гроші.
Блокчейни використовуються для зберігання та підтвердження інформації. Монети спонукають вузли брати участь у валідації, та їх наявність необов'язково.

Я пишу пост з кількох причин: 1) Щоб люди, які прочитали його, змогли дізнатися більше про блокчейни; 2) Щоб я зміг зрозуміти більше, пояснивши код, а не просто написавши його.
У цьому пості я покажу спосіб зберігання даних блокчейна та генерації початкового блоку, синхронізацію вузла з локальними даними блокчейна, відображення блокчейна (що згодом буде використовуватися для синхронізації з іншими вузлами), а потім, майнінг та створення нових валідних блоків. У першому пості не буде жодних інших вузлів. Жодних гаманців, бенкетів, важливих даних. Про них поговоримо пізніше.

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

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

На нижчому рівні дані в цих блоках можуть бути чим завгодно, поки це дозволяє конкретний блокчейн. Наприклад, дані в Bitcoin блокчейні – виключно транзакції Bitcoin між обліковими записами. Ethereum блокчейн дозволяє як аналогічні транзакції Ether, і транзакції, що використовуються запуску коду.

Перш ніж блок буде створено та об'єднано в блокчейн, він підтверджується більшістю людей, які працюють над блокчейном — їх називають вузлами. Справжній блокчейн – ланцюг, що складається з величезної кількості блоків, підтверджених більшістю вузлів. Таким чином, якщо вузол спробує змінити дані попереднього блоку, нові блоки не будуть валідними, і вузли не довірятимуть даними з некоректного блоку.

Не хвилюйтеся, якщо це збиває з пантелику. Мені знадобився час, щоб самому вникнути в це, і ще більше часу на написання такого посту, щоб моя сестра (яка нічого не знає про блокчейни) змогла зрозуміти.

Якщо хочете вивчити код, перегляньте гілку part 1 на Github. Сміливо надсилайте мені будь-які питання, коментарі, редагування та похвали (якщо ви в настрої зробити щось особливо гарне), або просто пишіть у твіттер.

Крок 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, необхідно до removed в майбутньому 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" % (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) : #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): для filename в 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

Поки що просто і красиво. Читання рядків із файлів їх завантаження в структури даних не вимагають надмірно складного коду. Поки що це працює. Але в майбутніх постах, де я писатиму про можливості комунікації різних вузлів, ця функція sync стане значно складнішою.

Крок 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, який у нашому випадку, є json list hashes with block information which is: index timestamp data hash prev_hash ''' node_blocks = sync.sync() #regrab the nodes if they've change # Convert our blocks into dictiona # 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_b__s =: ()

Запустіть цей код, зайдіть на localhost:3000/blockchain.json та побачите поточний блок.

Крок 4 – "Майнінг", також відомий як створення блоку

Зараз є тільки генезис-блок, але якщо у нас з'явиться більше даних, які необхідно зберігати і розподіляти, потрібен спосіб включити це в новий блок. Питання — як створити новий блок та поєднати його з попереднім.

Сатоші описує це так у Bitcoin whitepaper. Зауважте, що “timestamp сервер” названий “вузлом”.

“Почнемо опис нашого рішення з timestamp сервера. Його робота полягає в хешуванні блоку даних, на який потрібно поставити timestamp, і відкритої публікації цього хеш… Timestamp показує, що в даний момент конкретні дані існували і тому потрапили в хеш блоку. Кожен хеш включає попередній timestamp: так вибудовується ланцюг, де чергова ланка зміцнює всі попередні.”

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

Основна ідея розділу – при необхідності з'єднати блоки, ми створюємо хеш інформації про новий блок, включаючи час створення блоку, хеш попереднього блоку та інформацію в блоці. Я називатиму всю цю інформацію "хедером" блоку. Таким чином ми можемо перевірити коректність блоку, порахувавши всі хеші перед ним, підтвердивши послідовність.

У цьому випадку хедер, який я створюю, поєднує значення рядка в один величезний рядок.Я включив такі дані:

  1. Індекс, що показує яким за рахунком є ​​блок;
  2. Хеш попереднього блоку;
  3. Дані просто випадкові рядки. Для bitcoin вони називаються Merkle root і містять інформацію про транзакції;
  4. Timestamp майнінг цього блоку.
def generate_header(index, prev_hash, data, timestamp): return str(index) + prev_hash + data + str(timestamp)

Поясню один момент — об'єднання рядків інформації не є обов'язковим до створення хедера. Вимога полягає в тому, щоб кожен знав, як генерувати хедер блоку та хеш попереднього блоку всередині нього. Робиться це для того, щоб кожен міг переконатися в коректності хеша у новому блоці та підтвердити зв'язок між двома блоками.

Хедер Bitcoin значно складніший за об'єднання рядків. Він використовує хеш даних і часу і зав'язаний на те, як дані розташовані в пам'яті. Але в нашому випадку об'єднання рядків достатньо.

Тепер ми маємо хедер і можна обчислити валідність хеша. Я використовуватиму метод, що відрізняється від методу Bitcoin, але все одно запущу хедер блоку через функцію 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, no 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 '] = 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) з Open(filename, 'w') як 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)

Готово! Але при такому типі створення блоку будь-хто з найшвидшим CPU зможе створювати найдовші ланцюги, які інші вузли вважають коректними. Потрібний спосіб знизити швидкість створення блоку та підтвердження до переходу до наступного блоку.

Крок 5 – Доказ виконання роботи

Для зниження швидкості я використовую Доказ виконання роботи, як і Bitcoin. Доказ частки володіння – інший спосіб, який використовується в блокчейнах для досягнення консенсусу, але в цьому випадку я скористаюся роботою.

Спосіб зробити це встановити вимоги до структури хеша блоку. Як і у випадку з bitcoin, необхідно переконатися, що хеш починається з певної кількості нулів перед тим, як перейти до наступного. А для цього потрібно додати в хедер додаткову інформацію — число, що випадково перебирається (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, no 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: 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)

Чудово. Новий блок містить валідне значення nonce, тому інші вузли можуть підтвердити хеш. Ми можемо згенерувати, зберегти та розподілити новий блок іншим.

На цьому все! Поки що. Залишилося ще багато питань та фічів у блокчейнах, які я не пояснив.

Наприклад, як задіяти інші вузли? Як вузли передають дані, коли вмикаються в блок? Чи існують інші методи зберігання даних крім великих рядків даних?
Відповіді на ці запитання можна буде знайти в наступних частинах цієї серії постів, як тільки я знайду на них відповіді. Побажання щодо змісту можна писати мені в твіттер, коментарі до посту або через форму зворотного зв'язку!

Дякую моїй сестрі Сарі за уточнюючі питання про блокчейни та допомогу в редагуванні посту!

Коментарі, питання, як завжди, вітаються і тут, і на дні відчинених дверей.

Як з нуля побудувати свою блокчейну мережу

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

Які завдання вирішує блокчейн

Технологію активно впроваджують, бо вона вирішує кілька завдань:

  • захист конфіденційності — якщо банки та платіжні системи знають суму угоди, як звати відправників та одержувачів, то блокчейн зберігає анонімність. Це пов'язано з тим, що з проведення операції необхідно знати лише публічні і приватні ключі гаманців;
  • забезпечення безпеки – дані зберігаються на всіх блоках у ланцюзі, тому повністю видалити або змінити будь-який запис у системі неможливо;
  • безперебійна робота – мережа функціонує завдяки групі учасників, які займаються майнінгом. Якщо центральний сервер через технічні роботи або проблеми з електрикою може тимчасово вийти з ладу, то блокчейн працюватиме завжди. А при збільшенні навантаження система здатна масштабуватись.

Крім того, блокчейн гарантує прозорість угод завдяки смарт-контрактам. Це програмний код, в якому зафіксовані умови, наприклад, якщо користувач А відправить 100 монет Б, то Б передасть NFT-картинку. Він дозволяє відмовитись від зайвих посередників, які стягують комісії. Смарт-контракт неможливо змінити, а операція виконується автоматично.

Як самостійно зробити блокчейн

Щоб розробити власний блокчейн, знадобиться:

Пишемо скелет

Почати роботу можна у будь-якому сумісному з Python редакторі, тобто. Integrated Development Environment, наприклад: PyCharm, PyDev, WingWare, Komodo IDE. Створимо файл під назвою "Blockchain", щоб потім не втратити код.

Спочатку необхідно прописати клас блокчейна, конструктор якого зробить 2 порожні листи для зберігання вихідного коду та інформації про транзакції.

class Blockchain(object): def __init__(self): self.chain = [] self.current_transactions = [] def new_block(self): pass def new_transaction(self): pass @staticmethod def hash(block): pass @property def last_block(self): pass

Цей клас блокчейна керує ланцюгом, тобто він зберігатиме інформацію і матиме кілька методів внесення нових блоків у систему.

Створюємо перший блок

Перший блок у ланцюзі називають Genesis block. У ньому зберігається інформація, яка є фундаментом для всіх наступних елементів системи. Генезис необхідний для зв'язку блоків між собою та перевірки транзакцій, оскільки переклад не буде завершено, доки майнер не порівнятиме дані в новому блоці з попередніми.

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

Щоб розробити перший блок, потрібно запустити наступний програмний код:

def create_first_block(): 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

Тепер варто додати функцію, яка дозволяє зберігати інформацію про транзакції на локальному диску. Вона зробить систему безпечнішою, оскільки у разі відключення вузла дані не загубляться.

Назвемо нову папку «blockchaindata» та допишемо програмний код:

chaindata_dir = 'chaindata' if not os.path.exists(blockchaindata_dir): os.mkdir(blockchaindata_dir) if os.listdir(blockchaindata_dir) == []: first_block = create_first_block() first_blocksel.

Тепер кожен блок має окремий файл, названий за його унікальним ідентифікатором. Варто перевірити, чи містять імена файлів кілька нулів на початку, щоб вони відображалися строго по порядку і не перемішалися при першому навантаженні на мережу.

Синхронізуємо блокчейн

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

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

def sync(): node_blocks = [] chaindata_dir = 'chaindata' if os.path.exists(blocchaindata_dir): для filename в os.listdir(blockchaindata_dir): if filename.endswith('.json'): filepath = '%s /%s % (blockchaindata_dir, filename) with open(filepath, 'r') as block_file: block_info = json.load(block_file) block_object = Block(block_info) node_blocks.append(block_object) return node_blocks

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

Прописуємо відображення через браузер

Поки блокчейн просто знаходиться в пам'яті, з ним проблематично працювати, тому ланцюжок варто відобразити у браузері. Веб-браузер можна використовувати для перегляду та здійснення операцій, таких як надсилання цифрових активів або контроль криптогаманця.

Для створення веб-застосунку варто скористатися фреймворком Flask. Це легкий та зрозумілий софт, що має всі необхідні функції для роботи. Flask відрізняється тим, що дозволяє швидко розробити програму, використовуючи лише один файл Python. Також підійдуть Django, CherryPy, Pyramid, TurboGears.

Код для відображення блокчейна:

node = Flask(__name__) node_blocks = sync.sync() #inital blocks that are synced @node.route('/blockchain.json', methods=['GET']) def blockchain(): node_blocks = sync.sync( ) #regrab the nodes if they've changed python_blocks = [] for block in node_blocks: python_blocks.append(block.__dict__()) json_blocks = json.dumps(python_blocks) return json_blocks =: ()

Проігноруємо імпорти для економії місця.

Тепер ви можете переглянути наявний блок, запустивши програмний код і перейшовши до localhost:3000/blockchain.json .

Створення ланцюжка блоків

Зараз до мережі підключено лише genesis block, маючи який вже можна працювати з блокчейном, але з обробкою великого обсягу даних він не впорається. Рекомендується ще до запуску проекту продумати, як створюватимуться нові елементи ланцюга і як вони з'єднуватимуться один з одним.

Сатоші Накамото, який створив Bitcoin, придумав, яким має бути ланцюжок у блокчейні: timestamp-сервер (вузол) хешує блок даних і показує, що інформація існувала і тому збереглася. Кожен хеш складається не лише з нових даних, а й попередніх. Таким чином, утворюється ланцюг, у якому нові ланки зміцнюють попередні.

Завдяки зв'язку всіх блоків система може перевірити коректність нового, визначивши всі хеші та підтвердивши порядок. У нашому випадку інформація нового і попереднього блоків об'єднуватиметься в один величезний рядок, до якого включено:

Для цього потрібно прописати команду:

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()

Для майнінгу нових блоків можна впровадити цю функцію.Вона допоможе отримати хеш, покласти його в новий блок і зберегти останній у директорії blockchaindata.

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, no 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 '] = 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) з Open(filename, 'w') як 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)

Тепер майнери можуть підключатися до пам'ятника і обробляти інформацію. Пристрої дізнаються про транзакцію, вивчать її, запишуть у блок, порахують хеш, за що їхні власники отримуватимуть винагороду. Однак за такого типу блокчейна комп'ютери з найпотужнішим CPU створюватимуть довгі ланцюги, які інші вузли визначають як коректні.

Налаштування алгоритму підтвердження

Для підтвердження дійсності переказів, зафіксованих у блокчейні, розробники використовують кілька механізмів консенсусу. Найбільш популярними є:

  • Proof of Work (PoW) – підтвердження роботи;
  • Proof of Stake (PoS) – доказ частки володіння.

Перший варіант вважають безпечнішим з точки зору вразливості, проте актуальність питання децентралізації для PoW блокчейнів щороку зростає. Поступово майнути стає складніше, тому користувачі об'єднуються у пули.У 2021 році було зафіксовано, що 50% потужності мережі Bitcoin належить 4 пулам, тобто поступово відбувається стягування всіх процесів до кількох великих серверів.

Proof of Stake з'явився пізніше. Нині його переважно використовують у проектах альткоїнів. Його особливість у тому, що користувачам не потрібні величезні потужності, оскільки PoS не має на увазі майнінг. Пріоритети учасників залежать від кількості криптовалют, що зберігається на балансі.

Щоб отримати право перевірити блок, користувач має заблокувати монети за допомогою смарт-контракту. Цей процес називають стейкінгом. Потім алгоритми блокчейну вибирають, хто займеться валідацією наступного блоку.

Розглянемо всі суттєві відмінності механізмів:

Хто бере участь у майнінгу/валідації

Власники комп'ютерів із найбільшою обчислювальною потужністю

Користувачі з великою кількістю заблокованих монет

Устаткування, заточене під видобуток криптовалюти

Будь-який пристрій з постійним виходом в інтернет

Їх забирають користувачі, які здобули блок першими

Валідатору виплачують частину комісії за перекази, які збираються з підтвердженого блоку

Чим більше хеш, тим захищеніша система

Смарт-контракти блокують валюту учасників

У нашому випадку використано Proof of Work, як у Біткоіна. Щоб налаштувати механізм, потрібно поставити вимоги до структури хеша.

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, no 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: 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)

Коли блок отримає валідне значення nonce, інші вузли зможуть підтвердити хеш.

Як створити пару ключів

Щоб зашифрувати дані, варто використовувати RSA. В результаті ви отримаєте пару ключів: публічний та приватний.

з Crypto.PublicKey import RSA code = 'nooneknows' key = RSA.generate(2048) encrypted_key = key.exportKey( passphrase=code, pkcs=8, protection="scryptAndAES128-CBC" ) with open('my_prite. 'wb') as f: f.write(encrypted_key) with open('my_rsa_public.pem', 'wb') as f: f.write(key.publickey().exportKey())

Спочатку потрібно імпортувати RSA з Crypto.PublicKey, а потім створити простий код доступу та згенерувати ключ RSA на 2048 бітів. Щоб створити приватний ключ, необхідно викликати метод exportKey та віддати йому код доступу. Останній буде використаний стандартом PKCS, схема шифрування якого підходить для захисту конфіденційної інформації.

Отриманий файл слід записати на диск. Залишається створити приватний ключ через метод publickey, зв'язавши його з викликом exportkey.

Реалізація підписів

Переклад необхідно підписати, оскільки це єдиний спосіб гарантувати його надійність. Якщо підпис виявиться недійсним, то і транзакція не додасться до ланцюжка.Враховуючи, що транзакції відкривають попередні виходи, розподіляють їх значення, а потім блокують нові виходи, необхідно підписати:

  • хеші відкритих ключів у розблокованих виходах, щоб ідентифікувати відправника;
  • хеші відкритих ключів у нових виходах для підтвердження одержувача;
  • значення нових виходів

Перед надсиланням файлів учасник мережі генерує цифровий підпис, використовуючи закритий ключ облікового запису. А підписання може здійснюватися кількома способами, наприклад, клієнта блокчейн-платформи.

Алгоритм перевірки транзакції:

  1. Отримання інформації та ЕЦП із нової транзакції.
  1. Збір хеш.
  1. Розшифровка підпису та відкритого ключа за допомогою RSA Decode.
  1. Порівняння хешів, одержаних на другому та третьому етапі.

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

Тепер у вас є працюючий блокчейн. Ми не задіяли ще багато функцій, проте його вже можна використовувати для обміну інформацією у невеликій компанії або між друзями.