BTQ Docs
Concepts

BTQ Architecture

How BTQ Core is built: a Bitcoin fork with Dilithium signatures, 8MB blocks, 1-minute block times, and the OP_CHECKSIGDILITHIUM opcodes.

BTQ Architecture

BTQ is built on Bitcoin Core's architecture with modifications for quantum-resistant cryptography. This page provides a technical overview.

Codebase Foundation

BTQ is a fork of Bitcoin Core, inheriting:

  • 1M+ lines of battle-tested C++ code
  • 15+ years of security hardening
  • Comprehensive test suite (unit, functional, fuzz)
  • Cross-platform support (Linux, macOS, Windows)

What Changed

ComponentBitcoinBTQChange
SignaturesECDSAECDSA + DilithiumAdded
Script treesTaproot (v1)Taproot (v1) + P2MR (v2)Extended
Block size1MB/4MW8MB/8MWIncreased
Script opcodesStandard+ OP_CHECKSIGDILITHIUMAdded
Addressesbc1...qbtc1..., D...New prefixes
NetworkPort 8333Port 9333Changed
GenesisBitcoinBTQ-specificNew

What Stayed the Same

  • Consensus: Proof of Work (SHA-256)
  • Block time: ~1 minute (changed from Bitcoin's ~10 minutes)
  • Supply: 21 million maximum
  • Halving: Every 2,100,000 blocks (~4 years)
  • UTXO model: Transaction structure
  • P2P protocol: Network communication

Network Parameters

Chain Identity

// BTQ Genesis Block
nTime = 1771804800;
nNonce = 184980;
hashGenesisBlock = 0x0000ca45ea08433961609b50cd0c3f76d14589f8f61973ebbc344c3a160f7cdd

Network Magic Bytes

pchMessageStart[0] = 0xf1;
pchMessageStart[1] = 0xb2;
pchMessageStart[2] = 0xa3;
pchMessageStart[3] = 0xd4;

These bytes identify BTQ network traffic and prevent cross-chain confusion.

Ports

NetworkP2P PortRPC PortOnion Port
Mainnet933383328334
Testnet193331833218334
Signet383333833238334
Regtest194441844318445
  • P2P: Port for peer-to-peer node communication
  • RPC: Port for JSON-RPC API access (btq-cli, applications)
  • Onion: Target port for incoming Tor connections

Consensus Rules

Block Parameters

// Maximum block sizes
static const unsigned int MAX_BLOCK_SERIALIZED_SIZE = 8000000;  // 8MB
static const unsigned int MAX_BLOCK_WEIGHT = 8000000;           // 8MW
static const unsigned int MAX_BLOCK_SIGOPS_COST = 80000;        // 4x Bitcoin

// Transaction limits (increased for Dilithium)
static const unsigned int MAX_STANDARD_TX_WEIGHT = 400000;

Why Larger Blocks?

Dilithium signatures are significantly larger:

ComponentECDSADilithiumIncrease
Signature~71 bytes2,420 bytes34x
Public Key33 bytes1,312 bytes40x
Typical Tx~250 bytes~3,800 bytes15x

Without larger blocks, Dilithium transactions would severely limit throughput.

Cryptographic Modules

Directory Structure

src/crypto/
├── dilithium/           # Dilithium reference implementation
│   ├── api.h
│   ├── params.h
│   ├── sign.c
│   ├── packing.c
│   ├── polyvec.c
│   └── ...
├── dilithium_key.h      # C++ key wrapper
├── dilithium_key.cpp
├── dilithium_wrapper.h  # C/C++ interface
├── dilithium_wrapper.c
├── sha256.cpp           # Existing Bitcoin crypto
├── ripemd160.cpp
└── ...

Key Classes

// Private key wrapper
class CDilithiumKey {
    std::vector<unsigned char> keydata;  // 2,560 bytes
    
    void MakeNewKey();                    // Generate keypair
    bool Sign(const uint256& hash, 
              std::vector<unsigned char>& sig);
    CDilithiumPubKey GetPubKey() const;
    bool IsValid() const;
};

// Public key wrapper
class CDilithiumPubKey {
    std::vector<unsigned char> keydata;  // 1,312 bytes
    
    bool Verify(const uint256& hash,
                const std::vector<unsigned char>& sig);
    CKeyID GetID() const;  // RIPEMD160(SHA256(pubkey))
};

Script System

New Opcodes

// Added for Dilithium verification
OP_CHECKSIGDILITHIUM     // Verify Dilithium signature
OP_DILITHIUM_PUBKEY      // Mark Dilithium script

Script Patterns

P2DPK (Pay-to-Dilithium-Public-Key):

<1312-byte pubkey> OP_CHECKSIGDILITHIUM

P2DWPKH (Pay-to-Dilithium-Witness-Public-Key-Hash):

scriptPubKey: OP_0 <20-byte hash>
witness:      <2421-byte sig> <1312-byte pubkey>

BIP360 P2MR (Pay-to-Merkle-Root, witness v2):

scriptPubKey: OP_2 <32-byte merkle_root>
witness:      <stack args...> <leaf script> <control block>

P2MR uses script-path spending only. There is no key-path spend and no internal key tweak.

For complete protocol semantics and wallet-lifecycle behavior, see:

Auto-Detection

The script interpreter automatically detects Dilithium vs ECDSA:

// In interpreter.cpp
bool is_dilithium = (pubkey.size() > 100);  // 1312 vs 33

if (is_dilithium) {
    // Use OP_CHECKSIGDILITHIUM
} else {
    // Use OP_CHECKSIG (ECDSA)
}

Wallet Architecture

Key Storage

// Wallet database records
DILITHIUM_KEY          // Unencrypted Dilithium key
DILITHIUM_CRYPTED_KEY  // Encrypted Dilithium key

Storage format:

Key:   (DILITHIUM_KEY, KeyID)
Value: 2560-byte raw private key

Key:   (DILITHIUM_CRYPTED_KEY, KeyID)  
Value: AES-256-CBC encrypted key

Key Derivation

Key ID is computed consistently with Bitcoin:

CKeyID GetID() const {
    uint256 hash;
    SHA256(pubkey.data(), pubkey.size(), hash.data());
    
    CKeyID id;
    RIPEMD160(hash.data(), 32, id.data());
    return id;  // 20 bytes
}

Address System

Base58 Prefixes

// Mainnet
base58Prefixes[PUBKEY_ADDRESS] = {75};     // B...
base58Prefixes[DILITHIUM_PUBKEY] = {76};   // D...
base58Prefixes[SCRIPT_ADDRESS] = {135};    // Q...
base58Prefixes[DILITHIUM_SCRIPT] = {136};  // R...

// Bech32 Human-Readable Part
bech32_hrp = "qbtc";  // qbtc1q...

Address Derivation

┌─────────────────┐
│ Dilithium       │
│ Public Key      │
│ (1,312 bytes)   │
└────────┬────────┘
         │
         ▼
    SHA-256 Hash
         │
         ▼
  RIPEMD-160 Hash
         │
         ▼
┌─────────────────┐
│ Public Key Hash │
│ (20 bytes)      │
└────────┬────────┘
         │
    ┌────┴────┐
    ▼         ▼
Base58      Bech32m
  X...     qbtc1z...
(historical) (P2MR, current)

RPC Interface

Dilithium-Specific Commands

// Address generation
"getnewdilithiumaddress"
    -> Generate new Dilithium address

// Message signing
"signmessagewithdilithium"
    -> Sign message with Dilithium key
"verifydilithiumsignature"
    -> Verify Dilithium signature

// Transaction signing
"signtransactionwithdilithium"
    -> Sign transaction with Dilithium

// Key management
"importdilithiumkey"
    -> Import Dilithium private key

Standard Bitcoin RPCs

All standard Bitcoin RPCs work:

  • getblockchaininfo, getblock, getblockhash
  • createwallet, loadwallet, unloadwallet
  • getnewaddress, getbalance, listunspent
  • createrawtransaction, sendrawtransaction
  • getmempoolinfo, getrawmempool

Transaction Flow

Creation

1. Select UTXOs (listunspent)
2. Build transaction (createrawtransaction)
3. Sign with Dilithium (signtransactionwithdilithium)
4. Broadcast (sendrawtransaction)

Validation

// For each input:
1. Check UTXO exists and is unspent
2. Determine signature type (size-based)
3. If Dilithium:
   a. Extract 2421-byte signature from witness
   b. Extract 1312-byte pubkey from witness
   c. Compute sighash (BIP-143 style)
   d. Verify: Dilithium2.Verify(pubkey, sighash, sig)
4. Check amounts (inputs >= outputs + fees)
5. Accept to mempool

P2P Network

Message Types

Standard Bitcoin messages with BTQ magic bytes:

MessagePurpose
versionProtocol negotiation
verackVersion acknowledgment
addrPeer addresses
invInventory announcement
getdataRequest data
txTransaction
blockBlock
ping/pongKeepalive

Transaction Propagation

┌──────────┐    inv(txid)    ┌──────────┐
│  Node A  │ ───────────────▶│  Node B  │
│          │◀─────────────── │          │
│          │   getdata(txid) │          │
│          │ ───────────────▶│          │
│          │     tx(data)    │          │
└──────────┘                 └──────────┘

Testing Infrastructure

Unit Tests

# Run all unit tests
make check

# Run specific Dilithium tests
./src/test/test_btq --run_test=dilithium_key_tests
./src/test/test_btq --run_test=dilithium_address_script_tests
./src/test/test_btq --run_test=dilithium_wallet_tests
./src/test/test_btq --run_test=dilithium_descriptor_tests

Functional Tests

# Run all functional tests
./test/functional/test_runner.py

# Run BTQ-specific tests
./test/functional/btq_regtest_mining.py
./test/functional/btq_chain_identity.py

Test Coverage

AreaTests
Key generationUnit
Signature creationUnit
Signature verificationUnit
Address encodingUnit + Functional
Wallet operationsUnit + Functional
Transaction signingFunctional
Block validationFunctional

Build System

Dependencies

# Core dependencies
build-essential, libtool, autotools-dev, automake
pkg-config, bsdmainutils, python3

# Crypto/network
libevent-dev, libboost-dev, libsqlite3-dev

# Optional
libqt5-dev (GUI), libdb-dev (legacy wallet)

Build Commands

./autogen.sh
./configure [options]
make -j$(nproc)
make check  # Run tests

Security Model

Threat Mitigation

ThreatBitcoinBTQ
Classical attacksSecureSecure
Quantum (signatures)VulnerableProtected
Quantum (mining)WeakenedWeakened
51% attackPoW costPoW cost
Double spendConfirmationsConfirmations

Defense in Depth

  1. Cryptographic: Dilithium + SHA-256
  2. Economic: Mining cost, fee market
  3. Network: Decentralized validation
  4. Protocol: Confirmation depth

Future Roadmap

Short Term

  • Complete Phase 4 (block validation)
  • Mainnet launch
  • Wallet improvements

Medium Term

  • Additional post-quantum algorithms (Falcon, SPHINCS+)
  • Hybrid signatures (ECDSA + Dilithium)
  • Performance optimizations

Long Term

  • HD wallet derivation for Dilithium
  • Hardware wallet support
  • Layer 2 solutions

On this page