PoA 模块 API 文档

概述

Proof of Authority(PoA)许可型共识模块为 Cosmos SDK 区块链中的验证者管理提供了一套治理机制。与传统的 Proof of Stake 不同,PoA 允许指定的管理员控制验证者集合成员资格以及投票权分配。 包: cosmos.poa.v1 Go 导入: github.com/cosmos/cosmos-sdk/enterprise/poa/types

核心概念

  • 管理员控制: 单一管理员地址拥有管理验证者和模块参数的独占权限
  • 验证者管理: 创建验证者、更新投票权,并管理活跃验证者集合
  • 费用分配: 验证者会累积费用,其操作员可将其提取
  • 动态更新: 对验证者集合的更改可在不停链的情况下生效

数据类型

Validator

表示 PoA 系统中的一个验证者。
message Validator {
  google.protobuf.Any pub_key = 1;
  int64 power = 2;
  ValidatorMetadata metadata = 3;
  repeated cosmos.base.v1beta1.DecCoin allocated_fees = 4;
}
字段:
  • pub_key (Any):验证者的共识公钥(通常为 /cosmos.crypto.ed25519.PubKey)
  • power (int64):该验证者的投票权(使用 0 可移除验证者)
  • metadata (ValidatorMetadata):附加的验证者信息
  • allocated_fees (DecCoin[]):分配给该验证者的累计费用
示例:
{
  "pub_key": {
    "@type": "/cosmos.crypto.ed25519.PubKey",
    "key": "YUzyiqZzKN8BmLbl75gdXfbxQ2QtSYpPSwA85bZ3xuE="
  },
  "power": "10000",
  "metadata": {
    "moniker": "validator-1",
    "description": "First validator node",
    "operator_address": "cosmos1x0mm8rws8lm46xay3zyyznzr6lvu5um3kht0x7"
  },
  "allocated_fees": []
}

ValidatorMetadata

验证者的元数据信息。
message ValidatorMetadata {
  string moniker = 3;
  string description = 4;
  string operator_address = 5;
}
字段:
  • moniker (string):验证者的人类可读名称
  • description (string):验证者的可选描述
  • operator_address (string):运行该验证者的 Cosmos SDK 地址

Params

模块参数。
message Params {
  string admin = 1;
}
字段:
  • admin (string):具有管理权限的 Cosmos SDK 地址

ValidatorFees

表示某个验证者操作员的费用分配。
message ValidatorFees {
  repeated cosmos.base.v1beta1.DecCoin fees = 1;
}
字段:
  • fees (DecCoin[]):表示已分配费用的代币列表

查询 API

Query 服务提供对 PoA 模块状态的只读访问。

Params

获取模块参数。 gRPC: cosmos.poa.v1.Query/Params REST: GET /cosmos/poa/v1/params 请求:
message QueryParamsRequest {}
响应:
message QueryParamsResponse {
  Params params = 1;
}
CLI:
simd q poa params
响应示例:
{
  "params": {
    "admin": "cosmos1x0mm8rws8lm46xay3zyyznzr6lvu5um3kht0x7"
  }
}

Validator

按地址查询单个验证者。 gRPC: cosmos.poa.v1.Query/Validator REST: GET /cosmos/poa/v1/validator/{address} 请求:
message QueryValidatorRequest {
  string address = 1;  // Consensus or operator address
}
响应:
message QueryValidatorResponse {
  Validator validator = 1;
}
CLI:
simd q poa validator <address>
说明:
  • address 可以是共识地址,也可以是操作员地址

Validators

列出系统中的所有验证者。 gRPC: cosmos.poa.v1.Query/Validators REST: GET /cosmos/poa/v1/validators 请求:
message QueryValidatorsRequest {
  cosmos.base.query.v1beta1.PageRequest pagination = 2;
}
响应:
message QueryValidatorsResponse {
  repeated Validator validators = 1;
  cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
CLI:
simd q poa validators
说明:
  • 结果始终按投票权降序返回
  • 对大型验证者集合支持分页
响应示例:
{
  "validators": [
    {
      "pub_key": {
        "@type": "/cosmos.crypto.ed25519.PubKey",
        "key": "YUzyiqZzKN8BmLbl75gdXfbxQ2QtSYpPSwA85bZ3xuE="
      },
      "power": "10000",
      "metadata": {
        "moniker": "validator-1",
        "operator_address": "cosmos1..."
      }
    }
  ]
}

WithdrawableFees

查询验证者操作员可提取的费用。 gRPC: cosmos.poa.v1.Query/WithdrawableFees REST: GET /cosmos/poa/v1/allocated_fees/{operator_address} 请求:
message QueryWithdrawableFeesRequest {
  string operator_address = 1;
}
响应:
message QueryWithdrawableFeesResponse {
  ValidatorFees fees = 1;
}
CLI:
simd q poa allocated-fees <operator-address>
响应示例:
{
  "fees": {
    "fees": [
      {
        "denom": "token",
        "amount": "1000.500000000000000000"
      }
    ]
  }
}

TotalPower

获取所有验证者的总投票权。 gRPC: cosmos.poa.v1.Query/TotalPower REST: GET /cosmos/poa/v1/total_power 请求:
message QueryTotalPowerRequest {}
响应:
message QueryTotalPowerResponse {
  int64 total_power = 1;
}
CLI:
simd q poa total-power
响应示例:
{
  "total_power": "50000"
}

交易消息(Msg 服务)

Msg 服务处理会变更状态的操作。

UpdateParams

更新模块参数(仅管理员可执行)。 gRPC: cosmos.poa.v1.Msg/UpdateParams 消息:
message MsgUpdateParams {
  Params params = 1;
  string admin = 2;  // Signer must be current admin
}
响应:
message MsgUpdateParamsResponse {}
CLI:
simd tx poa update-params \
  --admin <new-admin-address> \
  --from <current-admin> \
  --keyring-backend test \
  --chain-id <chain-id> \
  -y
授权: 只有当前管理员才能执行该交易。

CreateValidator

创建一个投票权为零的新验证者(由操作员发起,需管理员激活)。 gRPC: cosmos.poa.v1.Msg/CreateValidator 消息:
message MsgCreateValidator {
  google.protobuf.Any pub_key = 1;
  string moniker = 2;
  string description = 3;
  string operator_address = 4;  // Signer
}
响应:
message MsgCreateValidatorResponse {}
CLI:
simd tx poa create-validator \
  --pubkey <validator-pubkey> \
  --moniker "my-validator" \
  --description "Validator description" \
  --from <operator-account> \
  --keyring-backend test \
  --chain-id <chain-id> \
  -y
授权: 任何账户都可以创建验证者,但其初始 power=0。 说明:
  • 在管理员将其投票权更新为非零值之前,该验证者不会参与共识
  • 公钥必须是有效的共识公钥(通常为 Ed25519)

UpdateValidators

更新验证者集合(仅管理员可执行)。这是管理验证者的主要机制。 gRPC: cosmos.poa.v1.Msg/UpdateValidators 消息:
message MsgUpdateValidators {
  repeated Validator validators = 1;
  string admin = 2;  // Signer must be admin
}
响应:
message MsgUpdateValidatorsResponse {}
CLI(内联):
simd tx poa update-validators \
  --validator '{
    "pub_key": {
      "@type": "/cosmos.crypto.ed25519.PubKey",
      "key": "YUzyiqZzKN8BmLbl75gdXfbxQ2QtSYpPSwA85bZ3xuE="
    },
    "power": 10000
  }' \
  --validator '{
    "pub_key": {
      "@type": "/cosmos.crypto.ed25519.PubKey",
      "key": "lSR1GEByJtzgiuCevrWgcyBWjhQXjycsuzzIdf56Oa4="
    },
    "power": 0
  }' \
  --from account \
  --keyring-backend test \
  --chain-id <chain-id> \
  -y
CLI(从文件):
simd tx poa update-validators validators.json \
  --from account \
  --keyring-backend test \
  --chain-id <chain-id> \
  -y
文件格式(validators.json):
[
  {
    "pub_key": {
      "@type": "/cosmos.crypto.ed25519.PubKey",
      "key": "YUzyiqZzKN8BmLbl75gdXfbxQ2QtSYpPSwA85bZ3xuE="
    },
    "power": 10000,
    "metadata": {
      "moniker": "validator-1",
      "description": "First validator",
      "operator_address": "cosmos1x0mm8rws8lm46xay3zyyznzr6lvu5um3kht0x7"
    }
  },
  {
    "pub_key": {
      "@type": "/cosmos.crypto.ed25519.PubKey",
      "key": "lSR1GEByJtzgiuCevrWgcyBWjhQXjycsuzzIdf56Oa4="
    },
    "power": 0
  }
]
授权: 只有管理员才能执行该交易。 说明:
  • 可在一笔交易中更新多个验证者
  • 设置 power: 0 会将验证者从活跃集合中移除
  • 更改会在下一个区块传播到 CometBFT 共识
  • 元数据中缺失的字段会保留现有状态中的值

WithdrawFees

将累计费用提取到操作员账户。 gRPC: cosmos.poa.v1.Msg/WithdrawFees 消息:
message MsgWithdrawFees {
  string operator = 1;  // Signer
}
响应:
message MsgWithdrawFeesResponse {}
CLI:
simd tx poa withdraw-fees \
  --from <operator-account> \
  --keyring-backend test \
  --chain-id <chain-id> \
  -y
授权: 必须由验证者的操作员地址签名。 说明:
  • 会将所有累计费用转入操作员账户
  • 费用以链的原生代币计价

常见使用场景

1. 查询当前管理员

simd q poa params

2. 列出所有活跃验证者

simd q poa validators

3. 添加新验证者

步骤 1: 操作员创建验证者:
simd tx poa create-validator \
  --pubkey <pubkey> \
  --moniker "new-validator" \
  --from operator-account \
  --keyring-backend test \
  -y
步骤 2: 管理员设置投票权并激活:
simd tx poa update-validators \
  --validator '{
    "pub_key": {"@type": "/cosmos.crypto.ed25519.PubKey", "key": "..."},
    "power": 10000
  }' \
  --from admin \
  --keyring-backend test \
  -y

4. 修改验证者投票权

simd tx poa update-validators \
  --validator '{
    "pub_key": {"@type": "/cosmos.crypto.ed25519.PubKey", "key": "..."},
    "power": 20000
  }' \
  --from admin \
  --keyring-backend test \
  -y

5. 移除验证者

simd tx poa update-validators \
  --validator '{
    "pub_key": {"@type": "/cosmos.crypto.ed25519.PubKey", "key": "..."},
    "power": 0
  }' \
  --from admin \
  --keyring-backend test \
  -y

6. 提取验证者费用

simd tx poa withdraw-fees \
  --from validator-operator \
  --keyring-backend test \
  -y

7. 转移管理员权限

simd tx poa update-params \
  --admin cosmos1newadminaddress... \
  --from current-admin \
  --keyring-backend test \
  -y

REST API 端点

所有查询端点都可通过 REST 访问:
方法端点说明
GET/cosmos/poa/v1/params获取模块参数
GET/cosmos/poa/v1/validator/{address}获取单个验证者
GET/cosmos/poa/v1/validators列出所有验证者
GET/cosmos/poa/v1/allocated_fees/{operator_address}获取可提取费用
GET/cosmos/poa/v1/total_power获取总投票权
REST 查询示例:
curl http://localhost:1317/cosmos/poa/v1/validators

错误处理

常见错误场景:

未授权的管理员操作

错误: 交易被拒绝 原因: 非管理员尝试调用仅管理员可用的函数 解决方案: 确保交易由管理员账户签名

无效的公钥

错误: 验证者公钥无效 原因: 公钥格式错误或类型不正确 解决方案: 使用格式正确的 Ed25519 公钥

未找到验证者

错误: 验证者不存在 原因: 查询了不存在的验证者 解决方案: 验证验证者地址/公钥

手续费不足

错误: 没有可提取的手续费 原因: 验证者尚未累计手续费 解决方案: 等待区块奖励累计产生手续费

集成示例

JavaScript/TypeScript(CosmJS)

import { SigningStargateClient } from "@cosmjs/stargate";

// Query validators
const client = await StargateClient.connect("http://localhost:26657");
const response = await client.queryContractSmart(
  "cosmos.poa.v1.Query/Validators",
  {}
);

// Update validators (requires signing)
const signingClient = await SigningStargateClient.connectWithSigner(
  "http://localhost:26657",
  wallet
);

const msg = {
  typeUrl: "/cosmos.poa.v1.MsgUpdateValidators",
  value: {
    validators: [{
      pubKey: { typeUrl: "/cosmos.crypto.ed25519.PubKey", value: ... },
      power: 10000,
      metadata: { moniker: "validator-1", operatorAddress: "cosmos1..." }
    }],
    admin: "cosmos1adminaddress..."
  }
};

const result = await signingClient.signAndBroadcast(
  adminAddress,
  [msg],
  "auto"
);

Python(cosmpy)

from cosmpy.aerial.client import LedgerClient, NetworkConfig
from cosmpy.aerial.wallet import LocalWallet


# Create client
client = LedgerClient(NetworkConfig.fetchai_mainnet())


# Query validators
response = client.query_contract(
    "cosmos.poa.v1.Query/Validators",
    {}
)

print(response)

Go

import (
    "context"
    poatypes "github.com/cosmos/cosmos-sdk/enterprise/poa/types"
    "google.golang.org/grpc"
)

// Query client
conn, _ := grpc.Dial("localhost:9090", grpc.WithInsecure())
queryClient := poatypes.NewQueryClient(conn)

// Get validators
resp, err := queryClient.Validators(context.Background(), &poatypes.QueryValidatorsRequest{})
if err != nil {
    panic(err)
}

for _, val := range resp.Validators {
    fmt.Printf("Validator: %s, Power: %d\n", val.Metadata.Moniker, val.Power)
}

安全注意事项

  1. 管理员密钥安全: 管理员私钥对验证者集合拥有完全控制权。请使用硬件钱包或安全的密钥管理系统。
  2. 验证者公钥: 确保验证者公钥已正确生成并安全存储。
  3. 权重分布: 考虑权重集中带来的安全影响。避免将总权重的 67% 以上分配给单个验证者。
  4. 操作员角色隔离: 为操作员和管理员角色使用不同账户,以限制风险暴露。
  5. 手续费提取: 操作员应定期提取手续费,避免其在模块中持续累积。

附录

公钥格式

Ed25519 公钥应使用 base64 编码:
{
  "@type": "/cosmos.crypto.ed25519.PubKey",
  "key": "YUzyiqZzKN8BmLbl75gdXfbxQ2QtSYpPSwA85bZ3xuE="
}

地址格式

  • 操作员地址: 标准 Cosmos SDK bech32 地址(例如:cosmos1...)
  • 共识地址: 可由公钥推导,或在查询时使用操作员地址

权重单位

  • 投票权重使用 int64 表示
  • 总权重会影响区块签名要求(通常需要超过总权重的 2/3 才能达成共识)
  • 零权重实际上会将验证者从活跃集合中移除 s

PoA Module API Documentation

Overview

The Proof of Authority (PoA) permissioned consensus module provides a governance mechanism for managing validators in a Cosmos SDK blockchain. Unlike traditional Proof of Stake, PoA allows a designated admin to control validator set membership and voting power distribution. Package: cosmos.poa.v1 Go Import: github.com/cosmos/cosmos-sdk/enterprise/poa/types

Core Concepts

  • Admin Control: A single admin address has exclusive authority to manage validators and module parameters
  • Validator Management: Create validators, update voting power, and manage the active validator set
  • Fee Distribution: Validators accumulate fees that can be withdrawn by their operators
  • Dynamic Updates: Changes to the validator set are applied without stopping the chain

Data Types

Validator

Represents a validator in the PoA system.
message Validator {
  google.protobuf.Any pub_key = 1;
  int64 power = 2;
  ValidatorMetadata metadata = 3;
  repeated cosmos.base.v1beta1.DecCoin allocated_fees = 4;
}
Fields:
  • pub_key (Any): The validator’s consensus public key (typically /cosmos.crypto.ed25519.PubKey)
  • power (int64): Voting power for this validator (use 0 to remove a validator)
  • metadata (ValidatorMetadata): Additional validator information
  • allocated_fees (DecCoin[]): Accumulated fees allocated to this validator
Example:
{
  "pub_key": {
    "@type": "/cosmos.crypto.ed25519.PubKey",
    "key": "YUzyiqZzKN8BmLbl75gdXfbxQ2QtSYpPSwA85bZ3xuE="
  },
  "power": "10000",
  "metadata": {
    "moniker": "validator-1",
    "description": "First validator node",
    "operator_address": "cosmos1x0mm8rws8lm46xay3zyyznzr6lvu5um3kht0x7"
  },
  "allocated_fees": []
}

ValidatorMetadata

Metadata information about a validator.
message ValidatorMetadata {
  string moniker = 3;
  string description = 4;
  string operator_address = 5;
}
Fields:
  • moniker (string): Human-readable name for the validator
  • description (string): Optional description of the validator
  • operator_address (string): Cosmos SDK address that operates this validator

Params

Module parameters.
message Params {
  string admin = 1;
}
Fields:
  • admin (string): Cosmos SDK address with administrative privileges

ValidatorFees

Represents fee allocations for a validator operator.
message ValidatorFees {
  repeated cosmos.base.v1beta1.DecCoin fees = 1;
}
Fields:
  • fees (DecCoin[]): List of coins representing allocated fees

Query API

The Query service provides read-only access to PoA module state.

Params

Get module parameters. gRPC: cosmos.poa.v1.Query/Params REST: GET /cosmos/poa/v1/params Request:
message QueryParamsRequest {}
Response:
message QueryParamsResponse {
  Params params = 1;
}
CLI:
simd q poa params
Example Response:
{
  "params": {
    "admin": "cosmos1x0mm8rws8lm46xay3zyyznzr6lvu5um3kht0x7"
  }
}

Validator

Query a single validator by address. gRPC: cosmos.poa.v1.Query/Validator REST: GET /cosmos/poa/v1/validator/{address} Request:
message QueryValidatorRequest {
  string address = 1;  // Consensus or operator address
}
Response:
message QueryValidatorResponse {
  Validator validator = 1;
}
CLI:
simd q poa validator <address>
Notes:
  • address can be either a consensus address or operator address

Validators

List all validators in the system. gRPC: cosmos.poa.v1.Query/Validators REST: GET /cosmos/poa/v1/validators Request:
message QueryValidatorsRequest {
  cosmos.base.query.v1beta1.PageRequest pagination = 2;
}
Response:
message QueryValidatorsResponse {
  repeated Validator validators = 1;
  cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
CLI:
simd q poa validators
Notes:
  • Results are always returned in descending order by voting power
  • Supports pagination for large validator sets
Example Response:
{
  "validators": [
    {
      "pub_key": {
        "@type": "/cosmos.crypto.ed25519.PubKey",
        "key": "YUzyiqZzKN8BmLbl75gdXfbxQ2QtSYpPSwA85bZ3xuE="
      },
      "power": "10000",
      "metadata": {
        "moniker": "validator-1",
        "operator_address": "cosmos1..."
      }
    }
  ]
}

WithdrawableFees

Query fees available for withdrawal by a validator operator. gRPC: cosmos.poa.v1.Query/WithdrawableFees REST: GET /cosmos/poa/v1/allocated_fees/{operator_address} Request:
message QueryWithdrawableFeesRequest {
  string operator_address = 1;
}
Response:
message QueryWithdrawableFeesResponse {
  ValidatorFees fees = 1;
}
CLI:
simd q poa allocated-fees <operator-address>
Example Response:
{
  "fees": {
    "fees": [
      {
        "denom": "token",
        "amount": "1000.500000000000000000"
      }
    ]
  }
}

TotalPower

Get the total voting power across all validators. gRPC: cosmos.poa.v1.Query/TotalPower REST: GET /cosmos/poa/v1/total_power Request:
message QueryTotalPowerRequest {}
Response:
message QueryTotalPowerResponse {
  int64 total_power = 1;
}
CLI:
simd q poa total-power
Example Response:
{
  "total_power": "50000"
}

Transaction Messages (Msg Service)

The Msg service handles state-changing operations.

UpdateParams

Update module parameters (admin only). gRPC: cosmos.poa.v1.Msg/UpdateParams Message:
message MsgUpdateParams {
  Params params = 1;
  string admin = 2;  // Signer must be current admin
}
Response:
message MsgUpdateParamsResponse {}
CLI:
simd tx poa update-params \
  --admin <new-admin-address> \
  --from <current-admin> \
  --keyring-backend test \
  --chain-id <chain-id> \
  -y
Authorization: Only the current admin can execute this transaction.

CreateValidator

Create a new validator with zero voting power (operator initiates, admin must activate). gRPC: cosmos.poa.v1.Msg/CreateValidator Message:
message MsgCreateValidator {
  google.protobuf.Any pub_key = 1;
  string moniker = 2;
  string description = 3;
  string operator_address = 4;  // Signer
}
Response:
message MsgCreateValidatorResponse {}
CLI:
simd tx poa create-validator \
  --pubkey <validator-pubkey> \
  --moniker "my-validator" \
  --description "Validator description" \
  --from <operator-account> \
  --keyring-backend test \
  --chain-id <chain-id> \
  -y
Authorization: Any account can create a validator, but it starts with power=0. Notes:
  • The validator will not participate in consensus until the admin updates its power to a non-zero value
  • Public key must be a valid consensus public key (typically Ed25519)

UpdateValidators

Update validator set (admin only). This is the primary mechanism for managing validators. gRPC: cosmos.poa.v1.Msg/UpdateValidators Message:
message MsgUpdateValidators {
  repeated Validator validators = 1;
  string admin = 2;  // Signer must be admin
}
Response:
message MsgUpdateValidatorsResponse {}
CLI (inline):
simd tx poa update-validators \
  --validator '{
    "pub_key": {
      "@type": "/cosmos.crypto.ed25519.PubKey",
      "key": "YUzyiqZzKN8BmLbl75gdXfbxQ2QtSYpPSwA85bZ3xuE="
    },
    "power": 10000
  }' \
  --validator '{
    "pub_key": {
      "@type": "/cosmos.crypto.ed25519.PubKey",
      "key": "lSR1GEByJtzgiuCevrWgcyBWjhQXjycsuzzIdf56Oa4="
    },
    "power": 0
  }' \
  --from account \
  --keyring-backend test \
  --chain-id <chain-id> \
  -y
CLI (from file):
simd tx poa update-validators validators.json \
  --from account \
  --keyring-backend test \
  --chain-id <chain-id> \
  -y
File Format (validators.json):
[
  {
    "pub_key": {
      "@type": "/cosmos.crypto.ed25519.PubKey",
      "key": "YUzyiqZzKN8BmLbl75gdXfbxQ2QtSYpPSwA85bZ3xuE="
    },
    "power": 10000,
    "metadata": {
      "moniker": "validator-1",
      "description": "First validator",
      "operator_address": "cosmos1x0mm8rws8lm46xay3zyyznzr6lvu5um3kht0x7"
    }
  },
  {
    "pub_key": {
      "@type": "/cosmos.crypto.ed25519.PubKey",
      "key": "lSR1GEByJtzgiuCevrWgcyBWjhQXjycsuzzIdf56Oa4="
    },
    "power": 0
  }
]
Authorization: Only the admin can execute this transaction. Notes:
  • Can update multiple validators in a single transaction
  • Setting power: 0 removes a validator from the active set
  • Changes propagate to CometBFT consensus in the next block
  • Missing fields in metadata are preserved from existing state

WithdrawFees

Withdraw accumulated fees to the operator’s account. gRPC: cosmos.poa.v1.Msg/WithdrawFees Message:
message MsgWithdrawFees {
  string operator = 1;  // Signer
}
Response:
message MsgWithdrawFeesResponse {}
CLI:
simd tx poa withdraw-fees \
  --from <operator-account> \
  --keyring-backend test \
  --chain-id <chain-id> \
  -y
Authorization: Must be signed by the validator’s operator address. Notes:
  • Transfers all accumulated fees to the operator’s account
  • Fees are denominated in the chain’s native token(s)

Common Use Cases

1. Query Current Admin

simd q poa params

2. List All Active Validators

simd q poa validators

3. Add a New Validator

Step 1: Operator creates the validator:
simd tx poa create-validator \
  --pubkey <pubkey> \
  --moniker "new-validator" \
  --from operator-account \
  --keyring-backend test \
  -y
Step 2: Admin activates with voting power:
simd tx poa update-validators \
  --validator '{
    "pub_key": {"@type": "/cosmos.crypto.ed25519.PubKey", "key": "..."},
    "power": 10000
  }' \
  --from admin \
  --keyring-backend test \
  -y

4. Change Validator Voting Power

simd tx poa update-validators \
  --validator '{
    "pub_key": {"@type": "/cosmos.crypto.ed25519.PubKey", "key": "..."},
    "power": 20000
  }' \
  --from admin \
  --keyring-backend test \
  -y

5. Remove a Validator

simd tx poa update-validators \
  --validator '{
    "pub_key": {"@type": "/cosmos.crypto.ed25519.PubKey", "key": "..."},
    "power": 0
  }' \
  --from admin \
  --keyring-backend test \
  -y

6. Withdraw Validator Fees

simd tx poa withdraw-fees \
  --from validator-operator \
  --keyring-backend test \
  -y

7. Transfer Admin Rights

simd tx poa update-params \
  --admin cosmos1newadminaddress... \
  --from current-admin \
  --keyring-backend test \
  -y

REST API Endpoints

All query endpoints are available via REST:
MethodEndpointDescription
GET/cosmos/poa/v1/paramsGet module parameters
GET/cosmos/poa/v1/validator/{address}Get single validator
GET/cosmos/poa/v1/validatorsList all validators
GET/cosmos/poa/v1/allocated_fees/{operator_address}Get withdrawable fees
GET/cosmos/poa/v1/total_powerGet total voting power
Example REST Query:
curl http://localhost:1317/cosmos/poa/v1/validators

Error Handling

Common error scenarios:

Unauthorized Admin Action

Error: Transaction rejected Cause: Non-admin attempted to call admin-only function Solution: Ensure transaction is signed by the admin account

Invalid Public Key

Error: Invalid validator public key Cause: Malformed or wrong type of public key Solution: Use Ed25519 public key in correct format

Validator Not Found

Error: Validator does not exist Cause: Querying non-existent validator Solution: Verify validator address/public key

Insufficient Fees

Error: No fees to withdraw Cause: Validator has no accumulated fees Solution: Wait for fees to accumulate from block rewards

Integration Examples

JavaScript/TypeScript (CosmJS)

import { SigningStargateClient } from "@cosmjs/stargate";

// Query validators
const client = await StargateClient.connect("http://localhost:26657");
const response = await client.queryContractSmart(
  "cosmos.poa.v1.Query/Validators",
  {}
);

// Update validators (requires signing)
const signingClient = await SigningStargateClient.connectWithSigner(
  "http://localhost:26657",
  wallet
);

const msg = {
  typeUrl: "/cosmos.poa.v1.MsgUpdateValidators",
  value: {
    validators: [{
      pubKey: { typeUrl: "/cosmos.crypto.ed25519.PubKey", value: ... },
      power: 10000,
      metadata: { moniker: "validator-1", operatorAddress: "cosmos1..." }
    }],
    admin: "cosmos1adminaddress..."
  }
};

const result = await signingClient.signAndBroadcast(
  adminAddress,
  [msg],
  "auto"
);

Python (cosmpy)

from cosmpy.aerial.client import LedgerClient, NetworkConfig
from cosmpy.aerial.wallet import LocalWallet

# Create client
client = LedgerClient(NetworkConfig.fetchai_mainnet())

# Query validators
response = client.query_contract(
    "cosmos.poa.v1.Query/Validators",
    {}
)

print(response)

Go

import (
    "context"
    poatypes "github.com/cosmos/cosmos-sdk/enterprise/poa/types"
    "google.golang.org/grpc"
)

// Query client
conn, _ := grpc.Dial("localhost:9090", grpc.WithInsecure())
queryClient := poatypes.NewQueryClient(conn)

// Get validators
resp, err := queryClient.Validators(context.Background(), &poatypes.QueryValidatorsRequest{})
if err != nil {
    panic(err)
}

for _, val := range resp.Validators {
    fmt.Printf("Validator: %s, Power: %d\n", val.Metadata.Moniker, val.Power)
}

Security Considerations

  1. Admin Key Security: The admin private key has complete control over the validator set. Use hardware wallets or secure key management systems.
  2. Validator Public Keys: Ensure validator public keys are correctly generated and stored securely.
  3. Power Distribution: Consider the security implications of power concentration. Avoid giving a single validator >67% of total power.
  4. Operator Separation: Use separate accounts for operator and admin roles to limit exposure.
  5. Fee Withdrawal: Operators should regularly withdraw fees to prevent accumulation in the module.

Appendix

Public Key Formats

Ed25519 public keys should be base64-encoded:
{
  "@type": "/cosmos.crypto.ed25519.PubKey",
  "key": "YUzyiqZzKN8BmLbl75gdXfbxQ2QtSYpPSwA85bZ3xuE="
}

Address Formats

  • Operator Address: Standard Cosmos SDK bech32 address (e.g., cosmos1...)
  • Consensus Address: Can be derived from public key or use operator address for queries

Power Units

  • Voting power is represented as int64
  • Total power affects block signing requirements (typically need >2/3 of total power for consensus)
  • Zero power effectively removes a validator from the active set s