Разработка системы трассировки поставок на блокчейне

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка системы трассировки поставок на блокчейне
Сложная
от 1 недели до 3 месяцев
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1221
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1163
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    855
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1056
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    828

Разработка системы прослеживания поставок на блокчейне

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

Но прежде чем проектировать, честный вопрос: нужен ли публичный блокчейн или достаточно permissioned сети? Для корпоративных supply chains с известным кругом участников — Hyperledger Fabric или Besu в IBFT-режиме в большинстве случаев правильнее, чем публичный Ethereum. Для случаев где важна публичная верифицируемость (потребитель сканирует QR-код и видит историю продукта на блокчейне) — публичный L2 или Polygon.

Архитектура данных: что хранить on-chain, что off-chain

Главная ошибка начинающих проектов — пытаться хранить всё on-chain. Результат: дорого, медленно, избыточно. Правило:

On-chain хранится: хеш документа/события, идентификатор актора (адрес), временная метка, статус (enum), merkle root партии данных.

Off-chain хранится: фото, PDF-сертификаты, детальные sensor readings, большие JSON-объекты. Ссылка на хранилище (IPFS CID или URL) + хеш содержимого записываются on-chain.

// Событие трекинга: лёгкое on-chain, детали в IPFS
struct TrackingEvent {
    bytes32 batchId;          // ID партии/лота
    bytes32 dataHash;         // keccak256 от полного JSON события
    string  ipfsCid;          // CID полных данных в IPFS
    address actor;            // кто записывает (верифицированный участник)
    EventType eventType;      // PRODUCED, SHIPPED, RECEIVED, INSPECTED, SOLD
    uint256 timestamp;
    bytes32 locationHash;     // хеш от GPS координат (для приватности)
}

enum EventType { PRODUCED, SHIPPED, RECEIVED, INSPECTED, CERTIFIED, SOLD }

mapping(bytes32 => TrackingEvent[]) public batchHistory;
mapping(bytes32 => bool) public authorizedActors;

event BatchEvent(
    bytes32 indexed batchId,
    EventType indexed eventType,
    address indexed actor,
    bytes32 dataHash,
    string ipfsCid
);

function recordEvent(
    bytes32 batchId,
    bytes32 dataHash,
    string calldata ipfsCid,
    EventType eventType
) external {
    require(authorizedActors[keccak256(abi.encode(msg.sender, eventType))], 
        "Not authorized for this event type");
    
    TrackingEvent memory evt = TrackingEvent({
        batchId: batchId,
        dataHash: dataHash,
        ipfsCid: ipfsCid,
        actor: msg.sender,
        eventType: eventType,
        timestamp: block.timestamp,
        locationHash: bytes32(0)
    });
    
    batchHistory[batchId].push(evt);
    emit BatchEvent(batchId, eventType, msg.sender, dataHash, ipfsCid);
}

Identity и авторизация участников

В supply chain есть несколько типов акторов с разными правами: производитель, логист, таможня, ритейлер, инспектор. Простой Ownable не подходит — нужна ролевая система с делегированием.

Верификация участников через DID

Decentralized Identifiers (DID) — W3C стандарт для децентрализованной идентичности. Каждый участник имеет DID, привязанный к своим смарт-контрактным адресам. Верификация участника (KYB — Know Your Business) происходит off-chain через аккредитованных верификаторов, которые выдают Verifiable Credentials (VC).

// Верификация VC при регистрации участника
import { Resolver } from 'did-resolver'
import { getResolver as ethrResolver } from 'ethr-did-resolver'
import { verifyCredential } from 'did-jwt-vc'

async function verifyParticipantCredential(
  vcJwt: string,
  participantAddress: string
): Promise<boolean> {
  const resolver = new Resolver({
    ...ethrResolver({ infuraProjectId: process.env.INFURA_ID })
  })
  
  const result = await verifyCredential(vcJwt, resolver)
  
  // Проверяем, что VC выдан аккредитованным верификатором
  const trustedIssuers = await getTrustedIssuers()  // из смарт-контракта
  if (!trustedIssuers.includes(result.issuer)) {
    return false
  }
  
  // Проверяем, что VC относится к данному адресу
  return result.verifiableCredential.credentialSubject.ethereumAddress
    .toLowerCase() === participantAddress.toLowerCase()
}

Role-based access с временными окнами

Участник может иметь право записывать события только в определённый период (время в пути груза):

struct ActorPermission {
    bytes32 role;           // PRODUCER_ROLE, SHIPPER_ROLE, etc.
    uint256 validFrom;
    uint256 validUntil;
    bytes32[] allowedBatches;  // пустой массив = все партии
}

mapping(address => ActorPermission[]) public permissions;

function isAuthorized(
    address actor,
    bytes32 role,
    bytes32 batchId
) public view returns (bool) {
    ActorPermission[] storage perms = permissions[actor];
    for (uint i = 0; i < perms.length; i++) {
        if (perms[i].role == role &&
            perms[i].validFrom <= block.timestamp &&
            perms[i].validUntil >= block.timestamp) {
            
            if (perms[i].allowedBatches.length == 0) return true;
            
            for (uint j = 0; j < perms[i].allowedBatches.length; j++) {
                if (perms[i].allowedBatches[j] == batchId) return true;
            }
        }
    }
    return false;
}

IoT интеграция: связь физического мира и блокчейна

Sensor data должен попадать on-chain автоматически и неизменно. Это архитектурная проблема: IoT устройство не может подписывать Ethereum транзакции напрямую (нет RAM, нет battery для криптографии EVM-класса).

Паттерн: Gateway + Oracle

[IoT Sensor] → [Edge Gateway] → [Oracle Service] → [Smart Contract]
                      ↓
               [IPFS / S3] ← полные sensor readings

Edge Gateway (Raspberry Pi, industrial PC):

  • Подписывает данные от сенсоров своим ключом
  • Агрегирует readings за период (например, каждые 5 минут)
  • Публикует агрегат в IPFS
  • Отправляет хеш + CID в oracle service

Oracle Service (off-chain backend):

  • Верифицирует подпись gateway
  • Проверяет данные на аномалии (outlier detection)
  • Инициирует транзакцию в смарт-контракт
# Oracle service: верификация и запись sensor события
from web3 import Web3
from eth_account import Account
import ipfshttpclient

async def process_sensor_reading(gateway_id: str, payload: dict, signature: str):
    # 1. Верифицируем подпись gateway
    message = encode_defunct(text=json.dumps(payload, sort_keys=True))
    recovered = w3.eth.account.recover_message(message, signature=signature)
    
    gateway_address = await get_registered_gateway(gateway_id)
    if recovered.lower() != gateway_address.lower():
        raise ValueError("Invalid gateway signature")
    
    # 2. Публикуем в IPFS
    async with ipfshttpclient.connect() as ipfs:
        cid = ipfs.add_json(payload)
    
    # 3. Записываем on-chain
    data_hash = Web3.keccak(text=json.dumps(payload, sort_keys=True))
    
    tx = tracking_contract.functions.recordSensorEvent(
        payload['batch_id'].encode(),
        data_hash,
        cid,
        EventType.SENSOR_READING
    ).build_transaction({
        'from': oracle_account.address,
        'nonce': w3.eth.get_transaction_count(oracle_account.address),
        'maxFeePerGas': await get_gas_price(),
    })
    
    signed = oracle_account.sign_transaction(tx)
    tx_hash = w3.eth.send_raw_transaction(signed.rawTransaction)
    return tx_hash.hex()

Tamper-evident hardware

Для высоких требований к доверию — Hardware Security Modules (HSM) или Trusted Execution Environment (TEE) прямо в устройстве. Microchip ATECC608 — недорогой чип с ECC ключевой парой, которую нельзя извлечь, хранится в secure element. Устройство подписывает данные ключом, который физически защищён от компрометации.

Реализация трекинга партий: реальный сценарий

Рассмотрим фармацевтическую supply chain (FDA DSCSA compliance требует электронный трекинг):

Событие 1: Производство

  • Производитель записывает: ID серии, дата производства, состав, хеш CoA (Certificate of Analysis)
  • Генерируется QR-код с batchId

Событие 2: Отгрузка

  • Логист сканирует QR, записывает: carrier ID, tracking number, температурный диапазон (для фармы критично)
  • GPS-трекер начинает писать temperature/humidity readings каждые 10 минут

Событие 3: Таможенная очистка

  • Таможенный агент записывает: декларация № , статус (cleared/held), инспектор ID

Событие 4: Получение

  • Получатель записывает: дата, физический осмотр (OK/damaged), расхождение по количеству
  • Верификация: сравниваем hash в блокчейне с hash от скачанного IPFS документа

Событие 5: Продажа потребителю

  • Потребитель сканирует QR → видит полную историю партии
// Верификация продукта потребителем (фронтенд)
async function verifyProduct(batchId: string): Promise<ProductHistory> {
  const history = await trackingContract.getBatchHistory(batchId)
  
  const verified = await Promise.all(history.map(async (event) => {
    // Скачиваем данные из IPFS
    const ipfsData = await fetchFromIPFS(event.ipfsCid)
    
    // Верифицируем хеш
    const computedHash = ethers.keccak256(
      ethers.toUtf8Bytes(JSON.stringify(ipfsData))
    )
    
    return {
      ...event,
      ipfsData,
      dataIntegrity: computedHash === event.dataHash,
      actorName: await getActorName(event.actor),  // из реестра участников
    }
  }))
  
  return verified
}

Выбор сети

Параметр Публичный L2 (Polygon/Base) Hyperledger Fabric Besu (IBFT)
Публичная верифицируемость Да Нет Нет
Стоимость записи ~$0.001–$0.01/tx Почти 0 Почти 0
Скорость финализации 2–5 сек < 1 сек 2–5 сек
Контроль доступа Smart contracts Native channel/MSP Smart contracts
Регуляторные требования Публичный блокчейн Приватная сеть Приватная сеть

Для B2C сценариев (потребитель видит историю) — публичный L2. Для B2B (только участники цепи) — permissioned.

Этапы разработки

Фаза 1 — Design (2–3 нед): анализ бизнес-процессов, определение событий, участников, прав доступа. Data model on/off-chain.

Фаза 2 — Smart contracts (3–4 нед): контракты трекинга, ролевая система, тесты.

Фаза 3 — Oracle + IoT (3–4 нед): gateway integration, oracle service, IPFS pipeline.

Фаза 4 — API & Dashboard (3–4 нед): REST/GraphQL API, admin panel, consumer-facing верификатор.

Фаза 5 — Integration & Pilot (2–4 нед): интеграция с ERP/WMS системами участников, пилот на реальных данных.

Итого: 13–19 недель. Самый трудоёмкий этап — интеграция с legacy ERP-системами участников цепочки, не разработка блокчейн-части.