Разработка appchain на базе Cosmos SDK
Вопрос "почему не Ethereum L2" возникает первым, и на него нужен честный ответ. Ethereum L2 (Arbitrum, Optimism, zkSync) даёт вам чужую виртуальную машину, чужой gas token, чужой sequencer, чужие правила. Cosmos SDK appchain — это ваш блокчейн: собственный консенсус, собственный gas token, собственная governance, собственные правила валидации. Цена — полная ответственность за безопасность и децентрализацию validator set. Для большинства приложений L2 правильный выбор. Для случаев, где нужен полный контроль над экономикой протокола, суверенитет над данными или специализированные механизмы консенсуса — Cosmos SDK.
Архитектура Cosmos SDK
Модульная структура
Cosmos SDK строится на модулях. Каждый модуль — это изолированный компонент с собственным state (в IAVL дереве), типами сообщений (Msgs), запросами (Queries) и хуками жизненного цикла:
Application
├── x/auth — аккаунты и сигнатуры
├── x/bank — перевод токенов
├── x/staking — validator set, делегирование
├── x/distribution — распределение staking rewards
├── x/gov — on-chain governance
├── x/slashing — штрафы за мисбехейвиор валидаторов
├── x/ibc — IBC протокол
└── x/yourapp — ваша бизнес-логика
Ваш кастомный модуль живёт в x/yourapp. Это где вся ваша логика.
Consensus: CometBFT (бывш. Tendermint)
CometBFT — BFT consensus с instant finality. Это ключевое отличие от PoW: если блок закоммичен — он финальный, без fork risk. Latency финализации: ~1–6 секунд в зависимости от конфигурации и размера validator set.
Ограничения: BFT consensus требует >2/3 голосующего stake для живости. При < 33% онлайн — сеть останавливается (safety over liveness). Это сознательный trade-off.
Максимально практичный validator set: 150–300 валидаторов. Больше — сеть замедляется из-за коммуникационных overhead в BFT round.
Разработка кастомного модуля
Структура модуля
x/
└── mymodule/
├── keeper/
│ ├── keeper.go — бизнес-логика, доступ к state
│ ├── msg_server.go — обработчики транзакций
│ └── query_server.go — обработчики запросов
├── types/
│ ├── msgs.go — типы сообщений
│ ├── genesis.go — начальное состояние
│ └── params.go — параметры модуля (governance-управляемые)
├── module.go — регистрация модуля
└── proto/
└── mymodule/ — Protobuf определения
Keeper и state management
State хранится в IAVL-дереве через KVStore. Keeper — единственная точка доступа к state:
type Keeper struct {
cdc codec.BinaryCodec
storeKey storetypes.StoreKey
bankKeeper types.BankKeeper // зависимость от bank модуля
authKeeper types.AccountKeeper
}
func (k Keeper) SetOrder(ctx sdk.Context, order types.Order) {
store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshal(&order)
store.Set(types.OrderKey(order.Id), bz)
}
func (k Keeper) GetOrder(ctx sdk.Context, id uint64) (types.Order, bool) {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.OrderKey(id))
if bz == nil {
return types.Order{}, false
}
var order types.Order
k.cdc.MustUnmarshal(bz, &order)
return order, true
}
Важно: в Cosmos SDK нет "транзакция не удалась, state откатился" в смысле EVM. Если msg_server вернул ошибку, gas сжигается, но state не изменился. Если вернул nil — state изменился и это финально. Поэтому все проверки должны идти до изменения state.
Msg Server: обработка транзакций
func (k msgServer) CreateOrder(
goCtx context.Context,
msg *types.MsgCreateOrder,
) (*types.MsgCreateOrderResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// 1. Валидация
if msg.Amount.IsZero() {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "amount cannot be zero")
}
// 2. Проверка баланса и лок средств
err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, msg.Creator, types.ModuleName, sdk.NewCoins(msg.Amount))
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInsufficientFunds, err.Error())
}
// 3. Изменение state
order := types.Order{
Id: k.GetNextOrderID(ctx),
Creator: msg.Creator,
Amount: msg.Amount,
CreatedAt: ctx.BlockTime().Unix(),
}
k.SetOrder(ctx, order)
k.IncrementOrderID(ctx)
// 4. Events для клиентов
ctx.EventManager().EmitEvent(sdk.NewEvent(
types.EventTypeCreateOrder,
sdk.NewAttribute(types.AttributeOrderID, fmt.Sprintf("%d", order.Id)),
sdk.NewAttribute(types.AttributeCreator, msg.Creator),
))
return &types.MsgCreateOrderResponse{OrderId: order.Id}, nil
}
BeginBlock / EndBlock хуки
Это мощный механизм: выполнять логику каждый блок без внешнего триггера. Примеры использования:
- Order matching — матчинг ордеров в конце каждого блока (DEX без газа на matching)
- Liquidations — проверка здоровья позиций и ликвидация при необходимости
- Epoch transitions — переход между эпохами стейкинга, распределение наград
- Oracle price updates — агрегация данных от validators
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
keeper.ProcessExpiredOrders(ctx)
keeper.MatchPendingOrders(ctx)
return []abci.ValidatorUpdate{}
}
Это принципиально невозможно в EVM без внешних keeper-ботов — там нет native cron.
IBC: межсетевое взаимодействие
IBC (Inter-Blockchain Communication Protocol) — killer feature Cosmos. Позволяет передавать токены и произвольные данные между chains без моста (trustless, через light client verification).
ICS-20: transfer токенов
Самый простой IBC use case — перевод токенов между chains:
// Отправка токенов из вашей chain в Osmosis
transfer := channeltypes.NewMsgTransfer(
"transfer", // port
"channel-0", // channel к Osmosis
sdk.NewCoin("uatom", amount),
sender,
receiver,
timeoutHeight,
timeoutTimestamp,
"memo",
)
Получатель в Osmosis увидит токен как ibc/HASH — это "wrapped" версия вашего токена. Для "native" представления нужен ICS-20 + custom denom alias.
Custom IBC packets
Для передачи произвольной логики между chains — кастомные IBC пакеты:
// Отправка произвольных данных
packet := channeltypes.NewPacket(
modulePacketData, // ваши данные, сериализованные в protobuf
sequence,
sourcePort, sourceChannel,
destPort, destChannel,
timeoutHeight, timeoutTimestamp,
)
Получающая chain верифицирует Merkle proof что пакет был committed на отправляющей chain — это trustless, никакой оракул не нужен.
Latency IBC: зависит от времён блоков обеих chains и скорости relayer. Обычно 10–30 секунд для Cosmos-to-Cosmos трансфера.
Relayer инфраструктура
IBC пакеты не доставляются сами — нужны relayers. Это off-chain процессы которые читают пакеты из одной chain и submit их в другую.
Два основных реализации: Hermes (Rust, высокая производительность) и Go relayer. Для production — Hermes.
Конфигурация Hermes для вашей chain → Osmosis:
[[chains]]
id = "yourchain-1"
rpc_addr = "http://localhost:26657"
grpc_addr = "http://localhost:9090"
key_name = "relayer"
[[chains]]
id = "osmosis-1"
rpc_addr = "https://osmosis-rpc.polkachu.com"
grpc_addr = "https://osmosis-grpc.polkachu.com:12590"
key_name = "relayer-osmosis"
Relayer должен иметь токены на обеих chains для оплаты газа. Для mainnet — мониторинг баланса и auto-refill критичен.
Governance и параметры
On-chain governance — одна из причин выбрать Cosmos. Изменение параметров протокола через голосование держателей токена:
// Параметры модуля, изменяемые через governance
type Params struct {
MinOrderSize sdk.Coin `json:"min_order_size"`
TradingFeeRate sdk.Dec `json:"trading_fee_rate"`
MaxOrdersPerBlock uint64 `json:"max_orders_per_block"`
}
Proposal → Deposit period → Voting period (обычно 14 дней) → Execution. Если квором проголосовало >50% держателей — параметры меняются автоматически.
Testnet и запуск
Localnet для разработки:
ignite chain serve # Ignite CLI — быстрый старт
# или
./scripts/run_node.sh # кастомный скрипт инициализации
Public testnet:
- Genesis файл с начальными валидаторами
- Faucet для получения тестовых токенов
- Explorer (Mintscan, Ping.pub) для visibility
Mainnet запуск:
- Параметры genesis — обсуждаются публично
- Gentx от начальных валидаторов (каждый создаёт create-validator транзакцию)
- Сбор gentx, формирование genesis.json
- Синхронный запуск нод валидаторами в момент genesis time
Validator onboarding: нужно привлечь достаточно decentralized и надёжных валидаторов. Для серьёзной mainnet — минимум 20–30 независимых валидаторов с geografической и юрисдикционной диверсификацией.
Стек и инструменты
| Компонент | Технология |
|---|---|
| Framework | Cosmos SDK v0.50.x |
| Consensus | CometBFT v0.38.x |
| Язык | Go 1.21+ |
| Scaffolding | Ignite CLI |
| Protobuf | buf + cosmos-proto |
| Testing | Go testing + simapp |
| Explorer | Mintscan (Cosmostation) или собственный |
| Relayer | Hermes (Informal Systems) |
| Monitoring | Prometheus + Grafana + Cosmos-specific дашборды |
Срок разработки кастомного appchain с одним-двумя бизнес-модулями, IBC, governance: 4–7 месяцев до testnet, +2–3 месяца до mainnet.







