George Pashev

Website of George Pashev (Jidai Mirai)

Scientist, Programmer, Data Scientist, Enterpreneur

Въведение в Блокчейн програмирането и Solidity

Въведение в Блокчейн програмирането и Solidity

гл. ас. д-р Георги Пашев http://gpashev.com

Лекция 1: Основи на Блокчейн технологията

1.1 Какво е блокчейн?

Блокчейн е разпределена база данни, която се споделя между възлите на компютърна мрежа. Като база данни, блокчейнът съхранява информация електронно в цифров формат. Блокчейните са най-известни с тяхната ключова роля в криптовалутните системи като Bitcoin за поддържане на сигурен и децентрализиран запис на транзакциите.

1.2 Основни характеристики

  • Децентрализация: Няма централен орган, който контролира мрежата
  • Прозрачност: Всички транзакции са публично видими
  • Неизменност: Веднъж записани, данните не могат да бъдат променени
  • Сигурност: Използва криптография за защита на транзакциите

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

  • Транзакциите се групират в блокове
  • Всеки блок съдържа:
    • Транзакции
    • Timestamp
    • Hash на предишния блок
    • Nonce (използва се за mining)

Лекция 2: Въведение в Smart Contracts

2.1 Какво са Smart Contracts?

Smart Contracts са самоизпълняващи се договори, където условията на споразумението между купувач и продавач са директно записани в програмен код. Кодът и споразуменията съществуват в разпределена, децентрализирана блокчейн мрежа.

2.2 Характеристики на Smart Contracts

  • Автоматично изпълнение
  • Прозрачност
  • Неизменност
  • Точност
  • Бързина
  • Сигурност

Лекция 3: Въведение в Solidity

3.1 Какво е Solidity?

Solidity е обектно-ориентиран програмен език за писане на smart contracts. Той е разработен специално за Ethereum платформата и е основният език за разработка на smart contracts.

3.2 Основна структура на Solidity contract

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract MyFirstContract {
    // Декларация на променливи
    uint public myNumber;
    
    // Конструктор
    constructor() {
        myNumber = 0;
    }
    
    // Функция за промяна на стойността
    function setNumber(uint _newNumber) public {
        myNumber = _newNumber;
    }
    
    // Функция за четене на стойността
    function getNumber() public view returns (uint) {
        return myNumber;
    }
}

3.3 Основи на Solidity

3.3.1 Променливи и типове данни

Стойностни типове (Value Types)
// Булеви
bool isActive = true;

// Цели числа
uint256 maxAmount = 1000;    // Без знак, 256 бита
int8 temperature = -10;      // Със знак, 8 бита
uint8 small = 255;          // 8 бита
uint16 medium = 65535;      // 16 бита

// Адреси
address owner = msg.sender;
address payable recipient;   // Може да получава ETH

// Изброявания
enum Status { Pending, Active, Closed }
Status current = Status.Pending;

// Fixed-point числа
fixed256x18 price = 3.14;   // 256 бита с 18 десетични позиции
Референтни типове (Reference Types)
// Масиви
uint[] numbers;              // Динамичен масив
uint[5] fixedNumbers;        // Фиксиран масив
bytes32 hash;               // Фиксиран bytes масив
bytes data;                 // Динамичен bytes масив

// Структури
struct Person {
    string name;
    uint age;
    address wallet;
}

// Mapping (асоциативни масиви)
mapping(address => uint) public balances;
mapping(uint => mapping(address => bool)) public complexMapping;

3.3.2 Оператори

Аритметични оператори
uint a = 10;
uint b = 5;

uint sum = a + b;        // Събиране
uint diff = a - b;       // Изваждане
uint prod = a * b;       // Умножение
uint quot = a / b;       // Деление
uint rem = a % b;        // Остатък
uint inc = a++;         // Инкрементиране
uint dec = b--;         // Декрементиране
Оператори за сравнение
bool isEqual = a == b;         // Равенство
bool notEqual = a != b;        // Неравенство
bool greater = a > b;          // По-голямо
bool less = a < b;            // По-малко
bool greaterEq = a >= b;      // По-голямо или равно
bool lessEq = a <= b;         // По-малко или равно
Логически оператори
bool result1 = true && false;  // Логическо И
bool result2 = true || false;  // Логическо ИЛИ
bool result3 = !true;          // Логическо НЕ
Побитови оператори
uint c = a & b;    // Побитово И
uint d = a | b;    // Побитово ИЛИ
uint e = a ^ b;    // Побитово изключващо ИЛИ
uint f = ~a;       // Побитово НЕ
uint g = a << 1;   // Побитово изместване наляво
uint h = a >> 1;   // Побитово изместване надясно

3.3.3 Константи и Имутабилни променливи

// Константи - стойността се определя по време на компилация
uint256 constant MAX_UINT = 2**256 - 1;
string constant VERSION = "1.0.0";

// Имутабилни променливи - стойността се определя в конструктора
address immutable owner;
uint256 immutable creationTime;

constructor() {
    owner = msg.sender;
    creationTime = block.timestamp;
}

3.3.4 Специални променливи и функции

Глобални променливи
address sender = msg.sender;          // Адрес на изпращача
uint value = msg.value;               // Изпратени ETH
bytes data = msg.data;                // Данни на съобщението
uint timestamp = block.timestamp;      // Timestamp на блока
uint blockNumber = block.number;       // Номер на блока
address coinbase = block.coinbase;     // Адрес на майнъра
uint difficulty = block.difficulty;    // Трудност на блока
uint gasLimit = block.gaslimit;        // Gas лимит на блока

3.3.5 Видимост на променливите

contract VisibilityExample {
    uint private privateVar;     // Достъпна само в текущия contract
    uint internal internalVar;   // Достъпна в текущия contract и наследниците
    uint public publicVar;       // Достъпна отвсякъде, създава getter
    
    // External не се прилага за променливи
}

3.3.6 Функции

Декларация и видимост
contract FunctionExample {
    // Public функция - достъпна отвсякъде
    function publicFunction() public {
        // код
    }
    
    // Private функция - достъпна само в текущия contract
    function privateFunction() private {
        // код
    }
    
    // Internal функция - достъпна в текущия contract и наследниците
    function internalFunction() internal {
        // код
    }
    
    // External функция - достъпна само отвън
    function externalFunction() external {
        // код
    }
}
Модификатори на функции
contract ModifierExample {
    // View - не променя състоянието
    function viewFunction() public view returns (uint) {
        return someValue;
    }
    
    // Pure - не чете и не променя състоянието
    function pureFunction(uint x) public pure returns (uint) {
        return x * 2;
    }
    
    // Payable - може да получава ETH
    function payableFunction() public payable {
        // код
    }
    
    // Виртуална функция - може да бъде презаписана
    function virtualFunction() public virtual {
        // код
    }
    
    // Презаписана функция
    function overriddenFunction() public override {
        // код
    }
}
Модификатори (Function Modifiers)
contract ModifierPatterns {
    address public owner;
    bool public locked;
    
    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }
    
    modifier noReentrant() {
        require(!locked, "No reentrancy");
        locked = true;
        _;
        locked = false;
    }
    
    // Използване на модификатори
    function sensitiveFunction() 
        public 
        onlyOwner 
        noReentrant 
    {
        // код
    }
}
Events
contract EventExample {
    // Деклариране на event
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 amount
    );
    
    function transfer(address to, uint256 amount) public {
        // Емитиране на event
        emit Transfer(msg.sender, to, amount);
    }
}

Лекция 4: Разработка на Smart Contracts

4.1 Развойна среда

  • Remix IDE: Онлайн среда за разработка
  • Truffle: Развойна рамка
  • Hardhat: Модерна развойна среда
  • Web3.js/Ethers.js: Библиотеки за взаимодействие с блокчейн

4.2 Основни концепции

  • Gas: Такса за изпълнение на транзакции
  • State Variables: Променливи, съхранявани в блокчейна
  • Functions: Видове функции (public, private, internal, external)
  • Events: Механизъм за logging
  • Modifiers: За промяна поведението на функции

4.3 Пример за по-сложен Smart Contract

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Token {
    string public name;
    string public symbol;
    uint8 public decimals;
    uint256 public totalSupply;
    mapping(address => uint256) public balanceOf;
    
    event Transfer(address indexed from, address indexed to, uint256 value);
    
    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
        decimals = 18;
        totalSupply = 1000000 * (10 ** uint256(decimals));
        balanceOf[msg.sender] = totalSupply;
    }
    
    function transfer(address to, uint256 value) public returns (bool success) {
        require(balanceOf[msg.sender] >= value, "Insufficient balance");
        balanceOf[msg.sender] -= value;
        balanceOf[to] += value;
        emit Transfer(msg.sender, to, value);
        return true;
    }
}

Лекция 5: Добри практики и сигурност

5.1 Добри практики

  • Използване на последна версия на Solidity
  • Правилно управление на достъпа
  • Оптимизация на gas
  • Документиране на кода
  • Използване на утвърдени библиотеки (OpenZeppelin)

5.2 Сигурност

  • Reentrancy атаки
  • Integer overflow/underflow
  • Timestamp dependence
  • Front-running
  • Denial of Service (DoS)

5.3 Примери за защита

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SecureContract {
    mapping(address => uint) public balances;
    bool private locked;
    
    modifier noReentrant() {
        require(!locked, "No reentrancy");
        locked = true;
        _;
        locked = false;
    }
    
    function withdraw() public noReentrant {
        uint balance = balances[msg.sender];
        require(balance > 0, "No balance");
        balances[msg.sender] = 0;
        (bool success, ) = msg.sender.call{value: balance}("");
        require(success, "Transfer failed");
    }
}

Заключение

Това въведение в блокчейн програмирането и Solidity покрива основните концепции и практики, необходими за започване на разработка на smart contracts. За да станете успешен блокчейн разработчик, е важно да:

  1. Разбирате основните концепции на блокчейн технологията
  2. Овладеете синтаксиса и особеностите на Solidity
  3. Следвате добрите практики за сигурност
  4. Практикувате чрез създаване на различни проекти
  5. Следите развитието на технологията и новите стандарти

Лекция 6: Интеграция на Python с Smart Contracts

6.1 Настройка на развойната среда

Инсталиране на необходимите инструменти

# Инсталиране на Python пакети
pip install web3
pip install python-dotenv
pip install eth-account

# Инсталиране на Ganache за локална blockchain мрежа
npm install -g ganache-cli

Структура на проекта

my_blockchain_project/
├── contracts/
│   └── MyContract.sol
├── build/
│   └── contracts/
├── scripts/
│   └── deploy.py
│   └── interact.py
├── .env
└── requirements.txt

6.2 Компилиране и деплойване на Smart Contract

Пример за deploy скрипт (deploy.py)

from web3 import Web3
from eth_account import Account
import json
import os
from dotenv import load_dotenv

# Зареждане на environment променливи
load_dotenv()

# Конфигурация
INFURA_URL = os.getenv("INFURA_URL")  # или локален URL за тестване
PRIVATE_KEY = os.getenv("PRIVATE_KEY")

# Свързване към blockchain
w3 = Web3(Web3.HTTPProvider(INFURA_URL))

# Създаване на акаунт от private key
account = Account.from_key(PRIVATE_KEY)

def deploy_contract():
    # Зареждане на компилирания contract
    with open("build/contracts/MyContract.json") as f:
        contract_json = json.load(f)
    
    # Извличане на contract ABI и bytecode
    contract_abi = contract_json['abi']
    contract_bytecode = contract_json['bytecode']
    
    # Създаване на contract обект
    Contract = w3.eth.contract(abi=contract_abi, bytecode=contract_bytecode)
    
    # Изграждане на транзакция
    transaction = Contract.constructor().build_transaction({
        'from': account.address,
        'nonce': w3.eth.get_transaction_count(account.address),
        'gas': 2000000,
        'gasPrice': w3.eth.gas_price
    })
    
    # Подписване на транзакцията
    signed_txn = w3.eth.account.sign_transaction(transaction, PRIVATE_KEY)
    
    # Изпращане на транзакцията
    tx_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)
    
    # Чакане за потвърждение
    tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
    
    return tx_receipt.contractAddress

if __name__ == "__main__":
    contract_address = deploy_contract()
    print(f"Contract deployed at: {contract_address}")

6.3 Взаимодействие със Smart Contract

Пример за interaction скрипт (interact.py)

from web3 import Web3
from eth_account import Account
import json
import os
from dotenv import load_dotenv

load_dotenv()

# Конфигурация
INFURA_URL = os.getenv("INFURA_URL")
PRIVATE_KEY = os.getenv("PRIVATE_KEY")
CONTRACT_ADDRESS = os.getenv("CONTRACT_ADDRESS")

# Свързване към blockchain
w3 = Web3(Web3.HTTPProvider(INFURA_URL))

# Създаване на акаунт
account = Account.from_key(PRIVATE_KEY)

def load_contract():
    # Зареждане на contract ABI
    with open("build/contracts/MyContract.json") as f:
        contract_json = json.load(f)
    contract_abi = contract_json['abi']
    
    # Създаване на contract обект
    contract = w3.eth.contract(
        address=CONTRACT_ADDRESS,
        abi=contract_abi
    )
    return contract

def read_contract_data():
    contract = load_contract()
    
    # Извикване на view функция
    result = contract.functions.getNumber().call()
    return result

def send_transaction():
    contract = load_contract()
    
    # Изграждане на транзакция
    transaction = contract.functions.setNumber(42).build_transaction({
        'from': account.address,
        'nonce': w3.eth.get_transaction_count(account.address),
        'gas': 100000,
        'gasPrice': w3.eth.gas_price
    })
    
    # Подписване и изпращане на транзакцията
    signed_txn = w3.eth.account.sign_transaction(transaction, PRIVATE_KEY)
    tx_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)
    
    # Чакане за потвърждение
    tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
    return tx_receipt

def handle_event(event):
    print(f"New event: {event}")

def listen_for_events():
    contract = load_contract()
    
    # Дефиниране на event filter
    event_filter = contract.events.MyEvent.create_filter(fromBlock='latest')
    
    # Безкраен цикъл за следене на събития
    while True:
        for event in event_filter.get_new_entries():
            handle_event(event)

if __name__ == "__main__":
    # Пример за използване
    current_value = read_contract_data()
    print(f"Current value: {current_value}")
    
    # Изпращане на транзакция
    tx_receipt = send_transaction()
    print(f"Transaction successful: {tx_receipt.transactionHash.hex()}")

6.4 Конфигурационен файл (.env)

# .env file
INFURA_URL=https://mainnet.infura.io/v3/your-project-id
PRIVATE_KEY=your-private-key
CONTRACT_ADDRESS=deployed-contract-address

6.5 Добри практики при Python интеграция

  1. Управление на грешки
from web3.exceptions import ContractLogicError

def safe_contract_call():
    try:
        result = contract.functions.myFunction().call()
        return result
    except ContractLogicError as e:
        print(f"Contract error: {e}")
        return None
    except Exception as e:
        print(f"Unexpected error: {e}")
        return None
  1. Gas оптимизация
def estimate_gas_and_send():
    # Оценка на gas
    gas_estimate = contract.functions.myFunction().estimate_gas()
    
    # Добавяне на buffer
    gas_limit = int(gas_estimate * 1.2)
    
    # Изграждане на транзакция с оптимизиран gas
    transaction = contract.functions.myFunction().build_transaction({
        'from': account.address,
        'gas': gas_limit,
        'gasPrice': w3.eth.gas_price,
        'nonce': w3.eth.get_transaction_count(account.address)
    })
  1. Async операции
import asyncio
from web3.auto import w3

async def async_contract_interaction():
    async for event in contract.events.MyEvent.create_filter(fromBlock='latest').get_all_entries():
        print(f"New event: {event}")

async def main():
    await async_contract_interaction()

if __name__ == "__main__":
    asyncio.run(main())

6.6 Тестване

Пример за unit test с pytest

import pytest
from web3 import Web3
from eth_tester import EthereumTester
from web3.providers.eth_tester import EthereumTesterProvider

@pytest.fixture
def web3_test():
    return Web3(EthereumTesterProvider(EthereumTester()))

@pytest.fixture
def contract(web3_test):
    with open("build/contracts/MyContract.json") as f:
        contract_json = json.load(f)
    
    contract = web3_test.eth.contract(
        abi=contract_json['abi'],
        bytecode=contract_json['bytecode']
    )
    
    tx_hash = contract.constructor().transact()
    tx_receipt = web3_test.eth.wait_for_transaction_receipt(tx_hash)
    
    return web3_test.eth.contract(
        address=tx_receipt.contractAddress,
        abi=contract_json['abi']
    )

def test_contract_function(contract, web3_test):
    # Arrange
    account = web3_test.eth.accounts[0]
    
    # Act
    tx_hash = contract.functions.setNumber(42).transact({'from': account})
    web3_test.eth.wait_for_transaction_receipt(tx_hash)
    
    # Assert
    result = contract.functions.getNumber().call()
    assert result == 42

Полезни ресурси

  • Официална документация на Solidity
  • Web3.py документация
  • OpenZeppelin документация
  • Ethereum Stack Exchange
  • GitHub repositories с примери
  • Online курсове и туториали
fulltext

Keywords

contractuintaddresspublicweb3transactionaccounteventfunctionimportjsonprivateboolcontractsreturnsendersolidityvaluesmartreceipt