Развёртывание блокчейна на 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 conflict и транзакция будет 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 месяца.







