Сообщество Engee

Как работает блокчейн

Автор
avatar-maximsidorovmaximsidorov
Notebook

Реализация простого блокчейна на языке Julia

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

Введение

Блокчейн — это распределённая база данных, состоящая из связанных между собой блоков. Каждый блок содержит данные, временную метку и криптографический хэш предыдущего блока. Это делает структуру защищённой от подделок и изменений: если кто-то попытается изменить данные в одном из блоков, он изменит его хэш, что повлияет на все последующие блоки.

В данном примере мы реализуем:

  • структуру блока,
  • генерацию хэша блока,
  • построение цепочки блоков,
  • проверку целостности цепочки.

Это упрощённая версия блокчейна, но она показывает ключевые принципы его работы.

Основная часть

Установка и подключение необходимых пакетов

Установка пакета SHA, необходимого для вычисления хэшей

In [ ]:
import Pkg; Pkg.add("SHA")
   Resolving package versions...
    Updating `~/.project/Project.toml`
  [ea8e919c] + SHA v0.7.0
    Updating `~/.project/Manifest.toml`
  [ea8e919c] + SHA v0.7.0

Подключение пакета SHA, позволяющего вычислять SHA-256 хэши

In [ ]:
using SHA

Определение структуры блока

Структура данных Block представляет собой один блок в блокчейне.
Содержит:

  • index: номер блока в цепочке
  • timestamp: время создания блока
  • data: данные, хранимые в блоке
  • previous_hash: хэш предыдущего блока
  • hash: собственный хэш блока
In [ ]:
struct Block
    index::Int
    timestamp::Float64
    data::String
    previous_hash::String
    hash::String
end
Out[0]:
Block

Функция для генерации хэша блока

Функция calculate_hash генерирует SHA-256 хэш на основе данных блока.
Параметры:

  • index: номер блока
  • timestamp: время создания
  • data: содержимое блока
  • previous_hash: хэш предыдущего блока
In [ ]:
function calculate_hash(index, timestamp, data, previous_hash)
    # Комбинируем данные блока в одну строку
    block_data = string(index, timestamp, data, previous_hash)
    # Вычисляем и возвращаем хэш SHA-256
    return bytes2hex(sha256(block_data))
end
Out[0]:
calculate_hash

Генерация первого (нулевого) блока — генезис-блока

Функция create_genesis_block создаёт первый блок в цепочке — "генезис-блок".
У него нет предыдущего хэша, поэтому мы используем пустую строку.

In [ ]:
function create_genesis_block()
    index = 0
    timestamp = time() # текущее время
    data = "Genesis Block"
    previous_hash = "0" # нет предыдущего блока

    hash = calculate_hash(index, timestamp, data, previous_hash)
    return Block(index, timestamp, data, previous_hash, hash)
end
Out[0]:
create_genesis_block

Создание нового блока

Функция create_next_block создаёт новый блок на основе предыдущего.
Параметры:

  • previous_block: предыдущий блок в цепочке
  • data: данные для нового блока
In [ ]:
function create_next_block(previous_block, data)
    index = previous_block.index + 1
    timestamp = time()
    previous_hash = previous_block.hash

    hash = calculate_hash(index, timestamp, data, previous_hash)
    return Block(index, timestamp, data, previous_hash, hash)
end
Out[0]:
create_next_block

Проверка целостности цепочки

Функция is_chain_valid проверяет, не нарушена ли целостность блокчейна.
Для этого:

  1. Проверяет, соответствует ли каждый хэш своим данным.
  2. Проверяет, правильно ли указан previous_hash у каждого блока.
In [ ]:
function is_chain_valid(chain::Vector{Block})
    for i in 2:length(chain)
        current_block = chain[i]
        previous_block = chain[i-1]

        # Проверяем, соответствует ли хэш блока пересчитанному значению
        expected_hash = calculate_hash(
            current_block.index,
            current_block.timestamp,
            current_block.data,
            current_block.previous_hash
        )

        if current_block.hash != expected_hash
            println("Нарушена целостность: хэш блока $(current_block.index) не совпадает")
            return false
        end

        # Проверяем, правильно ли указан previous_hash
        if current_block.previous_hash != previous_block.hash
            println("Нарушена последовательность: предыдущий хэш блока $(current_block.index) не совпадает")
            return false
        end
    end
    return true
end
Out[0]:
is_chain_valid

Создание цепочки блоков и тестирование

Создаём цепочку блоков

In [ ]:
blockchain = Vector{Block}()
Out[0]:
Block[]

Добавляем генезис-блок

In [ ]:
push!(blockchain, create_genesis_block())
Out[0]:
1-element Vector{Block}:
 Block(0, 1.757418165732052e9, "Genesis Block", "0", "89e9605fd77a7c1580679c91026c7c522e4ca2543a54d8b68ae9099769648fe5")

Добавляем несколько блоков

In [ ]:
push!(blockchain, create_next_block(blockchain[end], "Первая транзакция"))
push!(blockchain, create_next_block(blockchain[end], "Вторая транзакция"))
push!(blockchain, create_next_block(blockchain[end], "Третья транзакция"))
Out[0]:
4-element Vector{Block}:
 Block(0, 1.757418165732052e9, "Genesis Block", "0", "89e9605fd77a7c1580679c91026c7c522e4ca2543a54d8b68ae9099769648fe5")
 Block(1, 1.757418165985186e9, "Первая транзакция", "89e9605fd77a7c1580679c91026c7c522e4ca2543a54d8b68ae9099769648fe5", "5795b75b3f1c46ff0a77c54f91f84bb8702b0d047e81fdc259e2db71c1a87fcd")
 Block(2, 1.757418165985377e9, "Вторая транзакция", "5795b75b3f1c46ff0a77c54f91f84bb8702b0d047e81fdc259e2db71c1a87fcd", "d3113ceee60fdd38051311f312fb1e5579305cbff648fa81f9d2c11f4c7f7b89")
 Block(3, 1.757418165985547e9, "Третья транзакция", "d3113ceee60fdd38051311f312fb1e5579305cbff648fa81f9d2c11f4c7f7b89", "8d4083d1c8c42de81a7d8be592a77e77faa98ab01db0e838f18415d6afa760c0")

Выводим информацию о блоках

In [ ]:
println("Цепочка блоков:")
for block in blockchain
    println("Индекс: $(block.index), Данные: $(block.data), Хэш: $(block.hash), Предыдущий хэш: $(block.previous_hash)")
end
Цепочка блоков:
Индекс: 0, Данные: Genesis Block, Хэш: 89e9605fd77a7c1580679c91026c7c522e4ca2543a54d8b68ae9099769648fe5, Предыдущий хэш: 0
Индекс: 1, Данные: Первая транзакция, Хэш: 5795b75b3f1c46ff0a77c54f91f84bb8702b0d047e81fdc259e2db71c1a87fcd, Предыдущий хэш: 89e9605fd77a7c1580679c91026c7c522e4ca2543a54d8b68ae9099769648fe5
Индекс: 2, Данные: Вторая транзакция, Хэш: d3113ceee60fdd38051311f312fb1e5579305cbff648fa81f9d2c11f4c7f7b89, Предыдущий хэш: 5795b75b3f1c46ff0a77c54f91f84bb8702b0d047e81fdc259e2db71c1a87fcd
Индекс: 3, Данные: Третья транзакция, Хэш: 8d4083d1c8c42de81a7d8be592a77e77faa98ab01db0e838f18415d6afa760c0, Предыдущий хэш: d3113ceee60fdd38051311f312fb1e5579305cbff648fa81f9d2c11f4c7f7b89

Проверяем целостность цепочки

In [ ]:
println("\nПроверка целостности цепочки: ", is_chain_valid(blockchain) ? "OK" : "Ошибка")
Проверка целостности цепочки: OK

Заключение

В этом примере мы реализовали простую версию блокчейна на языке Julia:

  • мы определили структуру блока,
  • реализовали генерацию SHA-256 хэшей,
  • создали генезис-блок — начало цепочки,
  • научились добавлять новые блоки,
  • написали проверку целостности всей цепочки.

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

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