Engee documentation
Notebook

Implementation of a simple blockchain in Julia language

In this example, we implement a simplified algorithm for blockchain, the technology underlying cryptocurrencies, distributed ledgers, and data security.

Introduction

A blockchain is a distributed database consisting of interconnected blocks. Each block contains data, a timestamp, and a cryptographic hash of the previous block. This makes the structure protected from fakes and changes: if someone tries to change the data in one of the blocks, they will change its hash, which will affect all subsequent blocks.

In this example, we implement:

  • the block structure,
  • block hash generation,
  • building a block chain,
  • checking the integrity of the chain.

This is a simplified version of the blockchain, but it shows the key principles of its operation.

The main part

Installing and connecting the necessary packages

Installing the SHA package needed to calculate hashes

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

Connecting the SHA package, which allows you to calculate SHA-256 hashes

In [ ]:
using SHA

Defining the block structure

Data structure Block it represents a single block in the blockchain.
Contains:

  • index: block number in the chain
  • timestamp: block creation time
  • data: data stored in the block
  • previous_hash: hash of the previous block
  • hash: custom block hash
In [ ]:
struct Block
    index::Int
    timestamp::Float64
    data::String
    previous_hash::String
    hash::String
end
Out[0]:
Block

A function for generating a block hash

Function calculate_hash generates a SHA-256 hash based on the block data.
Parameters:

  • index: block number
  • timestamp: creation time
  • data: content of the block
  • previous_hash: hash of the previous block
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

Generation of the first (zero) block — genesis block

Function create_genesis_block creates the first block in the chain — the "genesis block".
It doesn't have a previous hash, so we use an empty string.

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

Creating a new block

Function create_next_block creates a new block based on the previous one.
Parameters:

  • previous_block: the previous block in the chain
  • data: data for the new block
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

Chain Integrity Check

Function is_chain_valid checks whether the integrity of the blockchain has been violated.
For this:

  1. Checks whether each hash matches its own data.
  2. Checks whether the correct address is specified previous_hash for each block.
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

Block Chain creation and testing

Creating a block chain

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

Adding the genesis block

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

Adding several blocks

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

Displaying information about the blocks

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

We check the integrity of the chain

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

Conclusion

In this example, we implemented a simple version of the blockchain in the Julia language.:

  • we have determined the block structure,
  • implemented the generation of SHA-256 hashes,
  • created the genesis block — the beginning of the chain,
  • we learned how to add new blocks,
  • we wrote an integrity check for the entire chain.

This helps to understand the basic principles of blockchain technology: how data is interconnected, why it is protected from changes, and how the system can independently verify its correctness.

Such code can be useful for learning the basics of cryptography, distributed systems, and preparing for more complex projects such as creating cryptocurrencies or smart contracts.