Blog - Jorge Rodriguez Flores
← Volver al blog

Hyperledger Fabric 2.5: Guía Completa para Redes Blockchain Empresariales

hyperledger fabric blockchain chaincode enterprise distribuido
Compartir: X / Twitter LinkedIn
Hyperledger Fabric 2.5: Guía Completa para Redes Blockchain Empresariales

Hyperledger Fabric 2.5 es la versión LTS (Long-Term Support) del framework de blockchain permisionado más utilizado en entornos empresariales. Desarrollado bajo el paraguas de la Linux Foundation, Fabric permite construir redes blockchain donde los participantes son conocidos e identificados, con soporte para contratos inteligentes en múltiples lenguajes y un modelo de privacidad granular mediante canales y colecciones de datos privados.

A diferencia de blockchains públicas como Ethereum o Bitcoin, Hyperledger Fabric está diseñado para casos de uso donde la confidencialidad, el rendimiento y el control de acceso son requisitos no negociables: cadenas de suministro, sistemas financieros interbancarios, gestión de identidades y registros de salud, entre otros.

Arquitectura de Hyperledger Fabric

Fabric adopta una arquitectura modular con separación clara de responsabilidades. Los tres flujos principales son: ejecutar, ordenar y validar — conocido como el modelo execute-order-validate.

Componentes principales

  • Peers — nodos que mantienen el ledger y ejecutan chaincode. Pueden ser endorsing peers (firman transacciones) o committing peers (solo validan y guardan).
  • Ordering Service — agrupa transacciones en bloques y establece el orden canónico. Soporta Raft (desde Fabric 2.x) como algoritmo de consenso distribuido tolerante a fallos.
  • Certificate Authority (CA) — gestiona identidades X.509 para todos los participantes. Fabric CA es la implementación de referencia.
  • Channels — subredes privadas dentro de la red Fabric. Cada canal tiene su propio ledger; solo los miembros del canal ven sus transacciones.
  • Chaincode — los contratos inteligentes de Fabric, desplegables en Go, Node.js o Java.
  • Ledger — combina una blockchain (log inmutable de bloques) con una base de datos de estado (world state) implementada en LevelDB o CouchDB.

Flujo de una transacción

Cliente SDK
  │
  ├─► Endorsing Peers  (ejecutan chaincode, firman propuesta)
  │       │
  │       └─► Devuelven respuestas firmadas al cliente
  │
  ├─► Cliente valida las firmas de endorsement
  │
  ├─► Ordering Service  (ordena, agrupa en bloque)
  │
  └─► Todos los Peers  (validan firmas + política, actualizan world state)

Novedades de Hyperledger Fabric 2.5 LTS

La versión 2.5 consolida las mejoras introducidas en la rama 2.x y añade características clave para producción:

  • Checkpoint y purga del ledger — permite eliminar datos históricos del ledger manteniendo el estado actual, crucial para cumplimiento GDPR y gestión de almacenamiento a largo plazo.
  • Gateway peer simplificado — el nuevo servicio Gateway (introducido en 2.4) es el método recomendado para enviar transacciones; elimina la lógica de descubrimiento del SDK y la delega al peer.
  • Mejoras en el lifecycle del chaincode — el ciclo de vida descentralizado de 2.x (aprobación por organizaciones) está completamente maduro, eliminando el modelo de instanciación centralizado de v1.x.
  • Soporte extendido LTS — parches de seguridad y correcciones de bugs garantizados por un período extendido.
  • Raft hardening — mejoras en la recuperación ante fallos del ordering service basado en Raft.

Instalación del Entorno de Desarrollo

Fabric requiere Docker, Docker Compose y Go. Los scripts oficiales de Fabric Samples son el punto de partida recomendado:

# Dependencias previas
sudo apt-get update && sudo apt-get install -y git curl

# Instalar Go 1.21+
wget https://go.dev/dl/go1.21.0.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.21.0.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin

# Descargar binarios de Fabric 2.5, imágenes Docker y fabric-samples
curl -sSL https://bit.ly/2ysbOFE | bash -s -- 2.5.0 1.5.7

# Verificar instalación
cd fabric-samples/test-network
./network.sh up

El script network.sh levanta una red de prueba con dos organizaciones (Org1, Org2), un ordering service Raft con tres nodos, y CouchDB como base de datos de estado. Es el entorno ideal para desarrollo local.

# Levantar red con CouchDB y crear canal por defecto (mychannel)
./network.sh up createChannel -c mychannel -s couchdb

# Desplegar chaincode de ejemplo (asset-transfer-basic en Go)
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go

# Verificar estado
docker ps --format "table {{.Names}}\t{{.Status}}"

Desarrollo de Chaincode en Go

El chaincode es el corazón de la lógica de negocio en Fabric. Con el SDK de contratos Go, implementar un contrato inteligente requiere implementar la interfaz contractapi.ContractInterface:

package main

import (
    "encoding/json"
    "fmt"
    "github.com/hyperledger/fabric-contract-api-go/contractapi"
)

// Asset representa un activo en el ledger
type Asset struct {
    ID             string `json:"ID"`
    Color          string `json:"color"`
    Size           int    `json:"size"`
    Owner          string `json:"owner"`
    AppraisedValue int    `json:"appraisedValue"`
}

// SmartContract implementa la lógica del chaincode
type SmartContract struct {
    contractapi.Contract
}

// CreateAsset crea un nuevo activo en el world state
func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface,
    id, color string, size int, owner string, appraisedValue int) error {

    exists, err := s.AssetExists(ctx, id)
    if err != nil {
        return err
    }
    if exists {
        return fmt.Errorf("el activo %s ya existe", id)
    }

    asset := Asset{
        ID: id, Color: color, Size: size,
        Owner: owner, AppraisedValue: appraisedValue,
    }
    assetJSON, err := json.Marshal(asset)
    if err != nil {
        return err
    }
    return ctx.GetStub().PutState(id, assetJSON)
}

// ReadAsset recupera un activo por su ID
func (s *SmartContract) ReadAsset(ctx contractapi.TransactionContextInterface,
    id string) (*Asset, error) {

    assetJSON, err := ctx.GetStub().GetState(id)
    if err != nil {
        return nil, fmt.Errorf("error al leer el ledger: %v", err)
    }
    if assetJSON == nil {
        return nil, fmt.Errorf("el activo %s no existe", id)
    }
    var asset Asset
    err = json.Unmarshal(assetJSON, &asset)
    return &asset, err
}

// TransferAsset transfiere la propiedad de un activo
func (s *SmartContract) TransferAsset(ctx contractapi.TransactionContextInterface,
    id, newOwner string) (string, error) {

    asset, err := s.ReadAsset(ctx, id)
    if err != nil {
        return "", err
    }
    oldOwner := asset.Owner
    asset.Owner = newOwner
    assetJSON, err := json.Marshal(asset)
    if err != nil {
        return "", err
    }
    return oldOwner, ctx.GetStub().PutState(id, assetJSON)
}

// AssetExists verifica si un activo existe en el world state
func (s *SmartContract) AssetExists(ctx contractapi.TransactionContextInterface,
    id string) (bool, error) {

    assetJSON, err := ctx.GetStub().GetState(id)
    return assetJSON != nil, err
}

func main() {
    assetChaincode, err := contractapi.NewChaincode(&SmartContract{})
    if err != nil {
        panic(fmt.Sprintf("Error creando chaincode: %v", err))
    }
    if err := assetChaincode.Start(); err != nil {
        panic(fmt.Sprintf("Error iniciando chaincode: %v", err))
    }
}

Ciclo de vida del chaincode en Fabric 2.x

El nuevo lifecycle requiere que cada organización apruebe el chaincode antes de que pueda ser invocado. Esto distribuye el control y elimina la dependencia de un administrador central:

# 1. Empaquetar el chaincode
peer lifecycle chaincode package basic.tar.gz \
  --path ./chaincode-go \
  --lang golang \
  --label basic_1.0

# 2. Instalar en los peers de cada organización
peer lifecycle chaincode install basic.tar.gz

# 3. Obtener el package ID
peer lifecycle chaincode queryinstalled
# Salida: basic_1.0:e492...  ← usar este ID en el siguiente paso

# 4. Aprobar para la organización (repetir para cada org)
peer lifecycle chaincode approveformyorg \
  --channelID mychannel \
  --name basic \
  --version 1.0 \
  --package-id basic_1.0:e492... \
  --sequence 1

# 5. Verificar que las orgs han aprobado
peer lifecycle chaincode checkcommitreadiness \
  --channelID mychannel --name basic --version 1.0 --sequence 1

# 6. Hacer commit del chaincode al canal
peer lifecycle chaincode commit \
  --channelID mychannel \
  --name basic \
  --version 1.0 \
  --sequence 1

# 7. Invocar una función del chaincode
peer chaincode invoke \
  -C mychannel -n basic \
  -c '{"function":"CreateAsset","Args":["asset1","blue","5","Tomoko","300"]}'

# 8. Consultar estado
peer chaincode query -C mychannel -n basic \
  -c '{"Args":["ReadAsset","asset1"]}'

Configuración de Políticas de Endorsement

Las políticas de endorsement definen qué organizaciones deben firmar una transacción para que sea válida. Se especifican usando la sintaxis de política de Fabric:

# Política: mayoría de orgs debe aprobar
peer lifecycle chaincode approveformyorg \
  --channelID mychannel \
  --name basic \
  --version 1.0 \
  --sequence 1 \
  --signature-policy "AND('Org1MSP.peer','Org2MSP.peer')"

# Política con OR: cualquiera de las dos orgs es suficiente
--signature-policy "OR('Org1MSP.peer','Org2MSP.peer')"

# Política de mayoría (más flexible)
--signature-policy "OutOf(2,'Org1MSP.peer','Org2MSP.peer','Org3MSP.peer')"

También se puede usar State-Based Endorsement para aplicar políticas a nivel de clave individual en el world state, lo que permite control granular por activo:

// Establecer política de endorsement para una clave específica
func (s *SmartContract) SetAssetEndorsementPolicy(ctx contractapi.TransactionContextInterface,
    assetID string, orgMSP string) error {

    ep, err := statebased.NewStateEP(nil)
    if err != nil {
        return err
    }
    err = ep.AddOrgs(statebased.RoleTypePeer, orgMSP)
    if err != nil {
        return err
    }
    epBytes, err := ep.Policy()
    if err != nil {
        return err
    }
    return ctx.GetStub().SetStateValidationParameter(assetID, epBytes)
}

Datos Privados y Colecciones

Las colecciones de datos privados (PDC) permiten que un subconjunto de organizaciones en un canal comparta datos que no son visibles para las demás. Solo el hash del dato privado se registra en el ledger público:

[
  {
    "name": "assetCollection",
    "policy": "OR('Org1MSP.member', 'Org2MSP.member')",
    "requiredPeerCount": 1,
    "maxPeerCount": 3,
    "blockToLive": 1000,
    "memberOnlyRead": true,
    "memberOnlyWrite": true,
    "endorsementPolicy": {
      "signaturePolicy": "OR('Org1MSP.member', 'Org2MSP.member')"
    }
  }
]
// Guardar dato privado en la colección
func (s *SmartContract) CreatePrivateAsset(ctx contractapi.TransactionContextInterface) error {
    // Los datos privados llegan en el transient map, no en los args
    transMap, err := ctx.GetStub().GetTransient()
    if err != nil {
        return fmt.Errorf("error obteniendo transient: %v", err)
    }
    assetJSON := transMap["asset_properties"]

    var asset Asset
    if err := json.Unmarshal(assetJSON, &asset); err != nil {
        return err
    }
    return ctx.GetStub().PutPrivateData("assetCollection", asset.ID, assetJSON)
}

Monitoreo y Operaciones en Producción

Para entornos productivos, Fabric expone métricas en formato Prometheus y soporta logging estructurado:

# core.yaml — configuración del peer para métricas
metrics:
  provider: prometheus
  statsd:
    network: udp
    address: 127.0.0.1:8125

operations:
  listenAddress: 0.0.0.0:9443
  tls:
    enabled: true
    cert:
      file: tls/server.crt
    key:
      file: tls/server.key
# Verificar salud del peer via endpoint de operaciones
curl -k https://peer0.org1.example.com:9443/healthz
# {"status":"OK"}

# Obtener métricas Prometheus
curl -k https://peer0.org1.example.com:9443/metrics | grep ledger

# Ver logs del peer con filtro
docker logs peer0.org1.example.com 2>&1 | grep -E "(ERROR|WARN|committed)"

# Consultar información del canal
peer channel getinfo -c mychannel

# Ver lista de chaincodes instalados
peer lifecycle chaincode queryinstalled

# Ver chaincodes comprometidos en el canal
peer lifecycle chaincode querycommitted --channelID mychannel

Purga del ledger (novedad en 2.5)

Una de las características más importantes de Fabric 2.5 es la capacidad de purgar datos históricos manteniendo el estado actual. Esto es esencial para cumplimiento GDPR (derecho al olvido) y control de almacenamiento:

# Crear un checkpoint en el bloque actual
peer snapshot submitrequest \
  --channelID mychannel \
  --peerAddress peer0.org1.example.com:7051 \
  --tlsRootCertFile crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt

# Verificar el snapshot generado
ls channel-artifacts/snapshots/

Hyperledger Fabric 2.5 LTS representa la opción más madura y probada para blockchain empresarial. Su modelo execute-order-validate, el lifecycle de chaincode descentralizado, las colecciones de datos privados y las capacidades de purga del ledger lo convierten en la plataforma preferida por organizaciones que requieren control total sobre su infraestructura blockchain. La curva de aprendizaje es pronunciada, pero la inversión se justifica en casos de uso donde la confidencialidad y el rendimiento son críticos.

Artículos relacionados