Architecture
BKC is one binary, BKCd, assembled from four codebases:
| Component | Repository | What BKC changes |
|---|---|---|
| Application | bkc-chain | The chain itself: the x/bkc module, ML-DSA-only transaction policy, wrapped EVM calls, genesis allocation and staking-reward emission |
| Cosmos SDK | bkc-cosmos-sdk (fork) | ML-DSA-65 consensus keys in staking, mempool and proposal fixes |
| CometBFT | bkc-cometbft (fork) | ML-DSA-65 validator keys, votes and the tendermint.crypto.PublicKey oneof |
| EVM | bkc-cosmos-evm (fork of cosmos/evm) | Synthetic receipts for wrapped calls, fee reporting |
| ML-DSA-65 backend | bkc-mldsa65v3 | The pq-crystals C implementation linked through cgo, with an AVX2 build |
text
┌──────────────────────────── BKCd ────────────────────────────┐
P2P 26656 ───▶│ CometBFT (fork) ML-DSA-65 votes, ~1 s blocks │
│ │ ABCI │
│ Cosmos SDK (fork) auth · bank · staking · gov · distribution │
│ │ x/bkc: ML-DSA policy, MsgExecuteEvmCall, │
│ │ staking-reward emission │
│ cosmos/evm (fork) EVM · feemarket · precompiles (0x…0900) │
└──────────────────────────────────────────────────────────────┘
JSON-RPC 8545 · WS 8546 · CometBFT RPC 26657 · REST 1317 · gRPC 9090One account, two views
The Cosmos side and the EVM see the same account. A BKC address is 20 bytes; bkc1… is its bech32 spelling and 0x… its hex spelling. Native BKC is one balance whether you query it through the bank module (/cosmos/bank/v1beta1/balances/bkc1…) or the EVM (eth_getBalance(0x…)). The bank denom bkc has 18 decimals, so 1 BKC = 10¹⁸ bkc = 10¹⁸ wei.
How a write reaches the EVM
text
your code (ethers / Hardhat)
│ eth_sendTransaction-shaped request
▼
BKC signer (SDK or Hardhat plugin)
│ builds /bkc.bkc.v1.MsgExecuteEvmCall, signs it with ML-DSA-65 (SIGN_MODE_DIRECT)
▼
CometBFT RPC broadcast_tx_sync
│
ante handler ML-DSA-only policy · fee · sequence
│
x/bkc call_nonce == sequence − 1 · gas limit ≤ Cosmos gas
│
cosmos/evm executes the call, emits ethereum_tx event + logs
▼
JSON-RPC eth_getTransactionReceipt(<EVM hash>) → status, logs, contractAddressReads skip all of this: eth_call, eth_getLogs, eth_getBalance go straight to the EVM JSON-RPC.
Consensus
- CometBFT BFT consensus: a block commits when validators holding more than 2/3 of the voting power sign it. With three equally weighted validators, all three must be online; four tolerate one failure.
- Each vote carries a 3,309-byte ML-DSA-65 signature, so a commit is roughly 3.4 KB per validator.
timeout_commitis 0.5 s; blocks land about once a second under load.
Node roles
| Role | Signs blocks | Serves public RPC | Typical config |
|---|---|---|---|
| Validator | yes | no — RPC bound to 127.0.0.1 | indexer off, only P2P exposed |
| Full node (RPC) | no | yes | indexer kv, JSON-RPC/REST/gRPC on 0.0.0.0, CORS open |
Keeping public RPC off validators matters on BKC: query load competes for the same CPU that builds and verifies ML-DSA-heavy blocks.
