Розгортування блокчейну на Hyperledger Fabric
Hyperledger Fabric — це не публічний блокчейн. Це permissioned distributed ledger framework для корпоративних консорціумів, де учасники відомі і ідентифіковані. Якщо ваше завдання — "запустити свій блокчейн для бізнесу" без публічної криптовалюти і з контролем над учасниками, Fabric — правильний вибір. Якщо потрібен токен — це не та технологія.
Архітектура Fabric: ключові концепції
Перед розгортуванням потрібно зрозуміти специфіку, яка радикально відрізняється від Ethereum:
Organizations (Організації) — учасники мережі. Кожна org має свій Certificate Authority (CA) і MSP (Membership Service Provider). Транзакції підписуються сертифікатами від конкретних CA. Немає анонімності — кожен учасник ідентифікований.
Peers — ноди організацій. Зберігають ledger і chaincode. Два типи: endorsing peers (виконують chaincode і підписують результат) і committing peers (тільки валідують і записують блоки).
Orderer — сервіс упорядкування транзакцій. Відділений від peers. Consensus відбувається тут. Типи: Solo (для розробки, один узел), Raft (production, кілька узлів з Byzantine fault tolerance).
Channels — ізольовані ledger'и всередині однієї мережі. Організації A і B можуть мати приватний канал, недоступний організації C, навіть якщо всі три в одній Fabric мережі.
Chaincode — смарт-контракти на Go, Java або Node.js. Виконуються в Docker-контейнерах на endorsing peers.
Модель транзакції (Execute-Order-Validate)
Це фундаментальне відмінність від Ethereum. Транзакція в Fabric проходить три фази:
- Execute: клієнт відправляє proposal на endorsing peers. Peers симулюють виконання chaincode, повертають read/write sets і свої підписи.
- Order: клієнт збирає endorsements (мають задовольняти endorsement policy) і відправляє в orderer. Orderer формує блок.
- Validate: кожен peer валідує транзакції в блоці (endorsement policy, MVCC конфлікти) і записує в ledger.
MVCC (Multi-Version Concurrency Control) — важна деталь. Якщо два клієнти одночасно читають і пишуть один ключ, один отримає MVCC конфлікт і транзакція буде invalidated. Потрібно проектувати chaincode з урахуванням цього.
Підготовка інфраструктури
Інструменти
# Встановлення Fabric binaries і Docker images
curl -sSL https://bit.ly/2ysbOFE | bash -s -- 2.5.6 1.5.9
# Додаємо в PATH
export PATH=$PATH:$(pwd)/fabric-samples/bin
Binaries: cryptogen, configtxgen, peer, orderer, fabric-ca-client.
Структура конфігурації
Типова структура директорій для двохорганізаційної мережі:
my-fabric-network/
├── config/
│ ├── configtx.yaml # Channel і genesis block конфігурація
│ └── crypto-config.yaml # Топологія організацій
├── docker/
│ └── docker-compose.yaml
├── chaincode/
│ └── my-contract/
└── scripts/
├── network.sh
└── deploy-chaincode.sh
Генерація криптографічних матеріалів
# crypto-config.yaml
OrdererOrgs:
- Name: Orderer
Domain: orderer.example.com
Specs:
- Hostname: orderer
PeerOrgs:
- Name: Org1
Domain: org1.example.com
Template:
Count: 2 # два peer
Users:
Count: 1 # один application user
- Name: Org2
Domain: org2.example.com
Template:
Count: 2
Users:
Count: 1
cryptogen generate --config=./config/crypto-config.yaml --output="crypto-material"
Генерує повну PKI: root CA, intermediate CA, TLS сертифікати, ключи для peers, orderers, admins.
Конфігурація канала й genesis block
# configtx.yaml (скорочено)
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: crypto-material/ordererOrganizations/orderer.example.com/msp
Policies:
Readers: { Type: Signature, Rule: "OR('OrdererMSP.member')" }
Writers: { Type: Signature, Rule: "OR('OrdererMSP.member')" }
Admins: { Type: Signature, Rule: "OR('OrdererMSP.admin')" }
- &Org1
Name: Org1MSP
ID: Org1MSP
MSPDir: crypto-material/peerOrganizations/org1.example.com/msp
AnchorPeers:
- Host: peer0.org1.example.com
Port: 7051
Capabilities:
Channel: &ChannelCapabilities
V2_0: true
Orderer: &OrdererCapabilities
V2_0: true
Application: &ApplicationCapabilities
V2_5: true
Profiles:
TwoOrgsOrdererGenesis:
Orderer:
OrdererType: etcdraft
Addresses: [orderer.example.com:7050]
EtcdRaft:
Consenters:
- Host: orderer.example.com
Port: 7050
ClientTLSCert: crypto-material/ordererOrganizations/.../tls/server.crt
ServerTLSCert: crypto-material/ordererOrganizations/.../tls/server.crt
BatchTimeout: 2s
BatchSize:
MaxMessageCount: 500
AbsoluteMaxBytes: 10 MB
PreferredMaxBytes: 2 MB
# Genesis block для orderer
configtxgen -profile TwoOrgsOrdererGenesis -channelID system-channel \
-outputBlock ./system-genesis-block/genesis.block
# Channel creation transaction
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx \
./channel-artifacts/mychannel.tx -channelID mychannel
Docker Compose для production-like мережі
# docker-compose.yaml (ключові сервіси)
services:
orderer.example.com:
image: hyperledger/fabric-orderer:2.5.6
environment:
- ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
- ORDERER_GENERAL_BOOTSTRAPMETHOD=file
- ORDERER_GENERAL_BOOTSTRAPFILE=/var/hyperledger/orderer/genesis.block
- ORDERER_GENERAL_LOCALMSPID=OrdererMSP
- ORDERER_GENERAL_TLS_ENABLED=true
volumes:
- ./system-genesis-block/genesis.block:/var/hyperledger/orderer/genesis.block
- ./crypto-material/ordererOrganizations/orderer.example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp
- ./crypto-material/ordererOrganizations/orderer.example.com/orderers/orderer.example.com/tls:/var/hyperledger/orderer/tls
ports: ["7050:7050"]
peer0.org1.example.com:
image: hyperledger/fabric-peer:2.5.6
environment:
- CORE_PEER_ID=peer0.org1.example.com
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_TLS_ENABLED=true
- CORE_LEDGER_STATE_STATEDATABASE=CouchDB
- CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb0:5984
depends_on: [couchdb0]
ports: ["7051:7051"]
couchdb0:
image: couchdb:3.3.2
environment:
- COUCHDB_USER=admin
- COUCHDB_PASSWORD=adminpw
ports: ["5984:5984"]
CouchDB vs LevelDB: CouchDB рекомендується для production — підтримує rich queries (JSON) через Mango Query, індекси, що критично для складного chaincode. LevelDB — тільки key-value lookup.
Деплой chaincode
Lifecycle chaincode в Fabric 2.x — двошаговий процес з обов'язковим approvalом від організацій:
# 1. Package
peer lifecycle chaincode package my-contract.tar.gz \
--path ./chaincode/my-contract \
--lang golang \
--label my-contract_1.0
# 2. Install на кожен endorsing peer кожної org
peer lifecycle chaincode install my-contract.tar.gz
# 3. Query package ID
peer lifecycle chaincode queryinstalled
# 4. Approve від кожної організації
peer lifecycle chaincode approveformyorg \
--channelID mychannel \
--name my-contract \
--version 1.0 \
--package-id <PACKAGE_ID> \
--sequence 1 \
--tls --cafile $ORDERER_CA
# 5. Check commit readiness
peer lifecycle chaincode checkcommitreadiness \
--channelID mychannel --name my-contract --version 1.0 --sequence 1
# 6. Commit (коли всі потрібні org approved)
peer lifecycle chaincode commit \
--channelID mychannel --name my-contract \
--version 1.0 --sequence 1 \
--peerAddresses peer0.org1.example.com:7051 \
--peerAddresses peer0.org2.example.com:9051 \
--tls --cafile $ORDERER_CA
Кожен апгрейд chaincode — інкремент --sequence. Всі учасуючі org мають approve нову версію.
Chaincode на Go: ключові паттерни
package chaincode
import (
"encoding/json"
"fmt"
"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
type SmartContract struct {
contractapi.Contract
}
type Asset struct {
ID string `json:"id"`
Owner string `json:"owner"`
Value int `json:"value"`
}
func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface,
id string, owner string, value int) error {
exists, err := s.AssetExists(ctx, id)
if err != nil { return err }
if exists { return fmt.Errorf("asset %s already exists", id) }
asset := Asset{ID: id, Owner: owner, Value: value}
assetJSON, err := json.Marshal(asset)
if err != nil { return err }
return ctx.GetStub().PutState(id, assetJSON)
}
// Rich query (тільки CouchDB)
func (s *SmartContract) GetAssetsByOwner(ctx contractapi.TransactionContextInterface,
owner string) ([]*Asset, error) {
queryString := fmt.Sprintf(`{"selector":{"owner":"%s"}}`, owner)
resultsIterator, err := ctx.GetStub().GetQueryResult(queryString)
// ...
}
Private Data Collections
Fabric підтримує приватні дані — дані, які видні тільки subset організацій, але хеш яких фіксується в публічному ledger:
# collections_config.json
[{
"name": "assetPrivateDetails",
"policy": "OR('Org1MSP.member', 'Org2MSP.member')",
"requiredPeerCount": 1,
"maxPeerCount": 3,
"blockToLive": 0,
"memberOnlyRead": true,
"memberOnlyWrite": true
}]
Потужна фіча для B2B сценаріїв: дві компанії бачать деталі угоди, третя — тільки факт її існування.
Операційні аспекти
Оновлення політик каналу: зміна endorsement policy або додавання нової організації — операція через configtxlator з підписами від поточних admin'ів. Нетривіальна процедура, вимагає coordination між org.
Моніторинг: Prometheus експортер доступний для peer і orderer через --metrics.provider=prometheus. Grafana dashboards від Hyperledger community.
Backup: snapshot state database (CouchDB) + архив блоків. Fabric підтримує peer snapshot команду для створення снапшотів з певного блока.
Терміни розгортування
| Фаза | Термін |
|---|---|
| Проектування мережі (організації, канали, політики) | 3–5 днів |
| Настройка інфраструктури й генерація PKI | 3–5 днів |
| Деплой і конфігурація мережі | 3–5 днів |
| Розробка chaincode | 1–4 нед (залежить від складності) |
| Інтеграція клієнтських SDK | 1–2 нед |
| Тестування й hardening | 1–2 нед |
Реалістичний термін від початку до production-ready мережі з простим chaincode: 6–8 тижнів. Для складного chaincode з багатою бізнес-логікою, кількома каналами та enterprise інтеграціями — 2–3 місяці.







