Cosmos Substreams Type Glossary

Block

pub struct Block {
    pub hash: Vec<u8>,
    pub height: i64,
    pub time: Option<Timestamp>,
    pub header: Option<Header>,
    pub misbehavior: Vec<Misbehavior>,
    pub events: Vec<Event>,
    pub txs: Vec<Vec<u8>>,
    pub tx_results: Vec<TxResults>,
    pub validator_updates: Vec<ValidatorUpdate>,
    pub consensus_param_updates: Option<ConsensusParams>,
}

Fields and Use Cases

hash

  • Description: The unique identifier of the block
  • Use Case: Reference and verify block identity in the chain

height

  • Description: The sequential block number in the chain
  • Use Case: Track blockchain progression and determine block order

time

  • Description: Timestamp when the block was created
  • Use Case: Temporal ordering of blocks and time-based queries
  • Description: Contains block metadata and cryptographic commitments
  • Use Case: Verify block integrity and chain consistency

misbehavior

  • Description: List of reported validator misbehavior in the block
  • Use Case: Track and handle validator protocol violations

events

  • Description: List of events emitted during block execution
  • Use Case: Monitor state changes and track application-level events

txs

  • Description: Raw transaction bytes included in the block
  • Use Case: Access and process individual transactions

tx_results

  • Description: Execution results for each transaction
  • Use Case: Determine transaction success/failure and effects

validator_updates

  • Description: Changes to the validator set
  • Use Case: Track validator set evolution and voting power changes

consensus_param_updates

  • Description: Updates to consensus parameters
  • Use Case: Monitor and verify changes to network consensus rules

Important Notes

  • The Block struct represents the fundamental unit of the Cosmos blockchain
  • It combines both the block data (transactions, events) and metadata (header, time)
  • Validator updates and misbehavior reports are crucial for proof-of-stake mechanics
  • The structure supports the Cosmos SDK’s application-specific blockchain model

Example Use Case: Block Analysis

fn analyze_cosmos_block(block: &Block) {
    println!("Block Analysis:");
    println!("Height: {}", block.height);
    println!("Hash: 0x{}", hex::encode(&block.hash));
    
    if let Some(time) = &block.time {
        println!("Timestamp: {}", time.to_string());
    }
    
    println!("Transaction Count: {}", block.txs.len());
    println!("Event Count: {}", block.events.len());
    
    // Analyze transaction results
    for (idx, result) in block.tx_results.iter().enumerate() {
        println!("Transaction {} Result:", idx);
        println!("  Code: {} ({})", result.code, if result.code == 0 { "Success" } else { "Failed" });
        println!("  Gas Used: {}", result.gas_used);
    }
    
    // Check for validator updates
    if !block.validator_updates.is_empty() {
        println!("Validator Updates:");
        for update in &block.validator_updates {
            println!("  Power Change: {}", update.power);
        }
    }
    
    // Check for misbehavior reports
    if !block.misbehavior.is_empty() {
        println!("Misbehavior Reports: {}", block.misbehavior.len());
    }
}

Header

pub struct Header {
    pub version: Option<Consensus>,
    pub chain_id: String,
    pub height: i64,
    pub time: Option<Timestamp>,
    pub last_block_id: Option<BlockId>,
    pub last_commit_hash: Vec<u8>,
    pub data_hash: Vec<u8>,
    pub validators_hash: Vec<u8>,
    pub next_validators_hash: Vec<u8>,
    pub consensus_hash: Vec<u8>,
    pub app_hash: Vec<u8>,
    pub last_results_hash: Vec<u8>,
    pub evidence_hash: Vec<u8>,
    pub proposer_address: Vec<u8>,
}

Fields and Use Cases

version

  • Description: Version information for block and application
  • Use Case: Ensure compatibility and track protocol upgrades

chain_id

  • Description: Unique identifier of the blockchain network
  • Use Case: Distinguish between different Cosmos chains and environments

height

  • Description: Block number in the chain
  • Use Case: Track block sequence and chain progression

time

  • Description: Block creation timestamp
  • Use Case: Temporal ordering and time-based validation

last_block_id

  • Description: Reference to the previous block
  • Use Case: Maintain chain continuity and verify block sequence

last_commit_hash

  • Description: Hash of validator signatures from the previous block
  • Use Case: Verify validator consensus and block finality

data_hash

  • Description: Merkle root of the block’s transactions
  • Use Case: Verify transaction integrity and inclusion

validators_hash

  • Description: Hash of the current validator set
  • Use Case: Track and verify validator set membership

next_validators_hash

  • Description: Hash of the next block’s validator set
  • Use Case: Prepare for validator set transitions

consensus_hash

  • Description: Hash of the consensus parameters
  • Use Case: Verify consensus rule consistency

app_hash

  • Description: State root hash after applying transactions
  • Use Case: Verify application state integrity

last_results_hash

  • Description: Hash of the previous block’s transaction results
  • Use Case: Verify transaction execution outcomes

evidence_hash

  • Description: Hash of included evidence of validator misbehavior
  • Use Case: Track and verify validator misconduct

proposer_address

  • Description: Address of the validator that proposed this block
  • Use Case: Identify block proposer and verify proposer selection

Important Notes

  • The Header struct contains crucial cryptographic commitments that ensure chain integrity
  • Multiple hash fields create a web of cryptographic commitments that secure different aspects of the chain
  • The structure supports Cosmos’s proof-of-stake and validator set mechanics
  • Headers play a key role in light client validation and inter-chain communication

Example Use Case: Header Verification and Analysis

fn analyze_block_header(header: &Header) {
    println!("Header Analysis:");
    println!("Chain ID: {}", header.chain_id);
    println!("Height: {}", header.height);
    
    if let Some(time) = &header.time {
        println!("Block Time: {}", time.to_string());
    }
    
    println!("Cryptographic Commitments:");
    println!("  Last Commit Hash: 0x{}", hex::encode(&header.last_commit_hash));
    println!("  Data Hash: 0x{}", hex::encode(&header.data_hash));
    println!("  Validators Hash: 0x{}", hex::encode(&header.validators_hash));
    println!("  Next Validators Hash: 0x{}", hex::encode(&header.next_validators_hash));
    println!("  App Hash: 0x{}", hex::encode(&header.app_hash));
    
    println!("Proposer: 0x{}", hex::encode(&header.proposer_address));
    
    // Check for version information
    if let Some(version) = &header.version {
        println!("Version Info:");
        println!("  Block Protocol: {}", version.block);
        println!("  App Protocol: {}", version.app);
    }
    
    // Verify if this is a validator set change block
    if header.validators_hash != header.next_validators_hash {
        println!("Notice: This block includes validator set changes");
    }
}

Consensus

pub struct Consensus {
    pub block: u64,
    pub app: u64,
}

Fields and Use Cases

block

  • Description: Version number of the block protocol
  • Use Case: Track and validate block structure changes and protocol upgrades

app

  • Description: Version number of the application protocol
  • Use Case: Ensure compatibility between nodes and handle application-level upgrades

Important Notes

  • The Consensus struct manages version compatibility at both the block and application levels
  • Version numbers help coordinate network upgrades and prevent incompatible nodes from participating
  • Block version relates to the core consensus protocol
  • App version relates to the specific Cosmos SDK application being run

Example Use Case: Version Compatibility Check

fn check_version_compatibility(consensus: &Consensus, min_block_version: u64, min_app_version: u64) {
    println!("Version Analysis:");
    println!("Block Protocol Version: {}", consensus.block);
    println!("App Protocol Version: {}", consensus.app);
    
    // Check block protocol compatibility
    if consensus.block < min_block_version {
        println!("Warning: Block protocol version {} is below minimum required version {}", 
            consensus.block, min_block_version);
    }
    
    // Check app protocol compatibility
    if consensus.app < min_app_version {
        println!("Warning: App protocol version {} is below minimum required version {}", 
            consensus.app, min_app_version);
    }
    
    // Example: Handle different version ranges
    match consensus.block {
        0 => println!("Original protocol version"),
        1..=2 => println!("Early protocol version with basic features"),
        3..=5 => println!("Protocol version with advanced features"),
        _ => println!("Future protocol version"),
    }
    
    // Example: Check for specific app version features
    let supports_ibc = consensus.app >= 1;
    let supports_governance = consensus.app >= 2;
    
    println!("Feature Support:");
    println!("  IBC: {}", supports_ibc);
    println!("  Governance: {}", supports_governance);
}

Additional Context

  • Version numbers are crucial for coordinating network upgrades in a distributed system
  • Different versions may support different features or have different consensus rules
  • Version checks help prevent network splits and ensure consistent behavior across all nodes
  • The separation of block and app versions allows for independent evolution of the consensus layer and application layer

BlockId

pub struct BlockId {
    pub hash: Vec<u8>,
    pub part_set_header: Option<PartSetHeader>,
}

Fields and Use Cases

hash

  • Description: The unique cryptographic hash identifier of the block
  • Use Case: Uniquely identify and verify blocks in the chain

part_set_header

  • Description: Header information about the block parts for block propagation
  • Use Case: Support efficient block transmission and verification in a distributed network

Important Notes

  • BlockId is used to uniquely identify blocks in the Cosmos network
  • The combination of hash and part set header enables efficient block propagation
  • Part sets allow blocks to be split into smaller pieces for transmission
  • This structure is crucial for the consensus mechanism and block synchronization

Example Use Case: Block Identification and Verification

fn analyze_block_id(block_id: &BlockId) {
    println!("Block Identifier Analysis:");
    println!("Block Hash: 0x{}", hex::encode(&block_id.hash));
    
    if let Some(part_set) = &block_id.part_set_header {
        println!("Part Set Information:");
        println!("  Total Parts: {}", part_set.total);
        println!("  Part Set Hash: 0x{}", hex::encode(&part_set.hash));
        
        // Example: Verify if block is complete
        if part_set.total > 0 {
            println!("  Status: Block has {} parts", part_set.total);
        } else {
            println!("  Status: Block has no parts");
        }
    } else {
        println!("No part set information available");
    }
    
    // Example: Basic block hash validation
    if block_id.hash.is_empty() {
        println!("Warning: Empty block hash detected");
    } else {
        println!("Hash length: {} bytes", block_id.hash.len());
    }
}

Additional Context

  • BlockId is fundamental to the Tendermint consensus protocol used in Cosmos
  • The part set mechanism allows for efficient block propagation in large networks
  • Block hashes are used for chain verification and preventing block forgery
  • The structure supports both full nodes and light clients in block verification

PartSetHeader

pub struct PartSetHeader {
    pub total: u32,
    pub hash: Vec<u8>,
}

Fields and Use Cases

total

  • Description: The total number of parts the block has been split into
  • Use Case: Track and verify block completeness during block propagation

hash

  • Description: Merkle hash of all parts of the block
  • Use Case: Verify the integrity of received block parts

Important Notes

  • PartSetHeader is used to manage block propagation in the Cosmos network
  • It enables efficient transmission of large blocks by splitting them into smaller parts
  • The hash field provides cryptographic verification of the complete set of parts

Example Use Case: Part Set Verification and Management

fn verify_part_set(header: &PartSetHeader, received_parts: u32) {
    println!("Part Set Analysis:");
    println!("Total Parts Expected: {}", header.total);
    println!("Part Set Hash: 0x{}", hex::encode(&header.hash));
    
    // Example: Check completion status
    let completion_percentage = (received_parts as f64 / header.total as f64) * 100.0;
    println!("Download Progress: {:.2}%", completion_percentage);
    
    // Example: Determine part set status
    match received_parts {
        0 => println!("Status: No parts received"),
        n if n < header.total => println!("Status: Incomplete ({}/{} parts)", n, header.total),
        n if n == header.total => println!("Status: Complete"),
        _ => println!("Status: Error - received more parts than expected"),
    }
    
    // Example: Estimate remaining work
    if received_parts < header.total {
        let remaining_parts = header.total - received_parts;
        println!("Remaining Parts: {}", remaining_parts);
    }
    
    // Example: Basic validation
    if header.total == 0 {
        println!("Warning: Invalid part set - total parts cannot be zero");
    }
    if header.hash.is_empty() {
        println!("Warning: Invalid part set - hash cannot be empty");
    }
}

Misbehavior

pub struct Misbehavior {
    pub r#type: i32,
    pub validator: Option<Validator>,
    pub height: i64,
    pub time: Option<Timestamp>,
    pub total_voting_power: i64,
}
pub enum MisbehaviorType {
    Unknown = 0,
    DuplicateVote = 1,
    LightClientAttack = 2,
}

Fields and Use Cases

r#type

  • Description: The type of misbehavior detected (UNKNOWN = 0, DUPLICATE_VOTE = 1, LIGHT_CLIENT_ATTACK = 2)
  • Use Case: Identify and handle different types of validator misconduct

validator

  • Description: Information about the validator that misbehaved
  • Use Case: Track and penalize misbehaving validators

height

  • Description: The block height at which the misbehavior occurred
  • Use Case: Temporal tracking of validator misconduct

time

  • Description: Timestamp when the misbehavior was detected
  • Use Case: Time-based analysis and evidence expiration

total_voting_power

  • Description: Total voting power of the validator set when the misbehavior occurred
  • Use Case: Assess the potential impact of the misbehavior on consensus

Important Notes

  • Misbehavior tracking is crucial for maintaining network security and validator accountability
  • Different types of misbehavior may result in different penalties
  • The structure supports Cosmos’s proof-of-stake security model
  • Evidence of misbehavior must be submitted within a specific time window

Example Use Case: Misbehavior Analysis and Handling

fn analyze_misbehavior(misbehavior: &Misbehavior) {
    println!("Misbehavior Analysis:");
    
    // Analyze misbehavior type
    let behavior_type = match misbehavior.r#type {
        0 => "Unknown",
        1 => "Duplicate Vote",
        2 => "Light Client Attack",
        _ => "Unrecognized",
    };
    println!("Type: {}", behavior_type);
    
    // Analyze validator information
    if let Some(validator) = &misbehavior.validator {
        println!("Validator:");
        println!("  Address: 0x{}", hex::encode(&validator.address));
        println!("  Voting Power: {}", validator.power);
    }
    
    println!("Block Height: {}", misbehavior.height);
    
    if let Some(time) = &misbehavior.time {
        println!("Detection Time: {}", time.to_string());
    }
    
    println!("Total Voting Power: {}", misbehavior.total_voting_power);
    
    // Example: Calculate severity based on validator's voting power
    if let Some(validator) = &misbehavior.validator {
        let power_percentage = (validator.power as f64 / misbehavior.total_voting_power as f64) * 100.0;
        println!("Validator Power Percentage: {:.2}%", power_percentage);
        
        // Example: Risk assessment
        let risk_level = match power_percentage {
            p if p > 33.33 => "Critical - Above 1/3 voting power",
            p if p > 10.0 => "High",
            p if p > 1.0 => "Medium",
            _ => "Low",
        };
        println!("Risk Level: {}", risk_level);
    }
}

Validator

pub struct Validator {
    pub address: Vec<u8>,
    pub power: i64,
}

Fields and Use Cases

address

  • Description: The validator’s address (first 20 bytes of SHA256(public key))
  • Use Case: Uniquely identify validators in the network
  • Example: 0x1234...abcd

power

  • Description: The validator’s voting power in the consensus mechanism
  • Use Case: Determine validator’s influence in consensus and governance
  • Example: A power of 1000 represents 1000 voting units

Important Notes

  • Validators are key participants in the Cosmos proof-of-stake consensus mechanism
  • Voting power is proportional to the amount of tokens staked
  • The address is derived from the validator’s public key for consistent identification
  • Validator power directly influences their role in block production and validation

Example Use Case: Validator Analysis and Power Distribution

fn analyze_validator(validator: &Validator, total_power: i64) {
    println!("Validator Analysis:");
    println!("Address: 0x{}", hex::encode(&validator.address));
    println!("Voting Power: {}", validator.power);
    
    // Calculate voting power percentage
    let power_percentage = (validator.power as f64 / total_power as f64) * 100.0;
    println!("Voting Power Percentage: {:.2}%", power_percentage);
    
    // Analyze validator influence
    println!("Validator Status:");
    match power_percentage {
        p if p >= 33.34 => println!("  WARNING: Validator has veto power (>33.33%)"),
        p if p >= 20.0 => println!("  High Influence Validator (>20%)"),
        p if p >= 10.0 => println!("  Medium Influence Validator (>10%)"),
        p if p >= 5.0 => println!("  Regular Validator (>5%)"),
        _ => println!("  Small Validator (<5%)"),
    }
    
    // Check for minimum power requirements
    if validator.power <= 0 {
        println!("Warning: Invalid voting power - must be positive");
    }
    
    // Example: Security considerations
    if power_percentage > 33.33 {
        println!("Security Risk: Validator has enough power to halt consensus");
    }
}
 
// Example: Analyze validator set distribution
fn analyze_validator_set(validators: &[Validator]) {
    let total_power: i64 = validators.iter().map(|v| v.power).sum();
    let validator_count = validators.len();
    
    println!("Validator Set Analysis:");
    println!("Total Validators: {}", validator_count);
    println!("Total Voting Power: {}", total_power);
    
    // Sort validators by power
    let mut sorted_validators = validators.to_vec();
    sorted_validators.sort_by_key(|v| -v.power);
    
    // Analyze top validators
    println!("\nTop 5 Validators by Power:");
    for (i, v) in sorted_validators.iter().take(5).enumerate() {
        let percentage = (v.power as f64 / total_power as f64) * 100.0;
        println!("{}. Address: 0x{} - Power: {} ({:.2}%)",
            i + 1,
            hex::encode(&v.address),
            v.power,
            percentage
        );
    }
}

Event

pub struct Event {
    pub r#type: String,
    pub attributes: Vec<EventAttribute>,
}

Fields and Use Cases

r#type

  • Description: The classification or category of the event
  • Use Case: Filter and categorize different types of chain events
  • Examples:
    • "transfer"
    • "message"
    • "delegate"
    • "withdraw_rewards"

attributes

  • Description: List of key-value pairs containing event details
  • Use Case: Store specific event data and parameters
  • Examples:
    • {"sender": "cosmos1..."}
    • {"recipient": "cosmos1..."}
    • {"amount": "100uatom"}

Important Notes

  • Events are the primary mechanism for tracking state changes in Cosmos chains
  • Events are emitted during transaction execution
  • Events are crucial for indexing and querying blockchain data
  • The type field enables efficient filtering and categorization
  • Attributes provide detailed information about the event

Example Use Case: Event Processing and Analysis

fn process_cosmos_event(event: &Event) {
    println!("Event Analysis:");
    println!("Type: {}", event.r#type);
    
    // Process attributes
    println!("Attributes:");
    for (index, attr) in event.attributes.iter().enumerate() {
        println!("  {}: {} = {}", index, attr.key, attr.value);
    }
    
    // Example: Handle specific event types
    match event.r#type.as_str() {
        "transfer" => {
            let mut sender = "";
            let mut recipient = "";
            let mut amount = "";
            
            for attr in &event.attributes {
                match attr.key.as_str() {
                    "sender" => sender = &attr.value,
                    "recipient" => recipient = &attr.value,
                    "amount" => amount = &attr.value,
                    _ => {}
                }
            }
            
            println!("Transfer Details:");
            println!("  From: {}", sender);
            println!("  To: {}", recipient);
            println!("  Amount: {}", amount);
        },
        
        "delegate" => {
            println!("Delegation Event:");
            for attr in &event.attributes {
                match attr.key.as_str() {
                    "validator" => println!("  Validator: {}", attr.value),
                    "amount" => println!("  Amount: {}", attr.value),
                    "new_shares" => println!("  New Shares: {}", attr.value),
                    _ => {}
                }
            }
        },
        
        "withdraw_rewards" => {
            println!("Reward Withdrawal Event:");
            for attr in &event.attributes {
                if attr.key == "amount" {
                    println!("  Withdrawn Amount: {}", attr.value);
                }
            }
        },
        
        _ => println!("Unhandled event type: {}", event.r#type),
    }
}
 
// Example: Event filtering and aggregation
fn aggregate_events(events: &[Event]) {
    let mut transfer_count = 0;
    let mut delegate_count = 0;
    let mut other_count = 0;
    
    for event in events {
        match event.r#type.as_str() {
            "transfer" => transfer_count += 1,
            "delegate" => delegate_count += 1,
            _ => other_count += 1,
        }
    }
    
    println!("Event Summary:");
    println!("  Transfers: {}", transfer_count);
    println!("  Delegations: {}", delegate_count);
    println!("  Other Events: {}", other_count);
}

Additional Context

  • Events can be used to track various chain activities:
    • Token transfers
    • Staking operations
    • Governance actions
    • IBC (Inter-Blockchain Communication) operations

EventAttribute

pub struct EventAttribute {
    pub key: String,
    pub value: String,
}

Fields and Use Cases

key

  • Description: The identifier or name of the attribute
  • Use Case: Label and identify different pieces of event data
  • Examples:
    • "sender"
    • "recipient"
    • "amount"
    • "validator"
    • "action"

value

  • Description: The corresponding value for the attribute key
  • Use Case: Store the actual data or parameter value
  • Examples:
    • "cosmos1abc..."
    • "100uatom"
    • "delegate"
    • "complete"

Important Notes

  • EventAttributes are key-value pairs that provide detailed information about events
  • Keys are typically standardized within each event type
  • Values can contain addresses, amounts, status codes, or other relevant data
fn process_event_attributes(attributes: &[EventAttribute]) {
    println!("Event Attribute Analysis:");
    
    // Basic attribute processing
    for (index, attr) in attributes.iter().enumerate() {
        println!("Attribute {}:", index);
        println!("  Key: {}", attr.key);
        println!("  Value: {}", attr.value);
    }
    
    // Example: Process common attribute patterns
    let mut known_attributes = std::collections::HashMap::new();
    for attr in attributes {
        known_attributes.insert(&attr.key, &attr.value);
    }
    
    // Check for common patterns
    if let Some(action) = known_attributes.get("action") {
        println!("\nAction Type: {}", action);
    }
    
    // Example: Handle financial attributes
    if let Some(amount) = known_attributes.get("amount") {
        if let Some(denom) = parse_coin_value(amount) {
            println!("Financial Transaction:");
            println!("  Amount: {}", amount);
            println!("  Denomination: {}", denom);
        }
    }
    
    // Example: Address validation
    for (key, value) in known_attributes.iter() {
        if ["sender", "recipient", "validator"].contains(key) {
            if value.starts_with("cosmos1") {
                println!("Valid Cosmos address found for {}: {}", key, value);
            }
        }
    }
}
 
// Helper function to parse coin values
fn parse_coin_value(value: &str) -> Option<&str> {
    // Find denomination in strings like "100uatom"
    if let Some(pos) = value.find(|c: char| c.is_alphabetic()) {
        Some(&value[pos..])
    } else {
        None
    }
}
 
// Example: Attribute grouping and analysis
fn analyze_attribute_patterns(events: &[Event]) {
    let mut key_frequency = std::collections::HashMap::new();
    
    for event in events {
        for attr in &event.attributes {
            *key_frequency.entry(attr.key.clone()).or_insert(0) += 1;
        }
    }
    
    println!("\nAttribute Key Analysis:");
    for (key, count) in key_frequency.iter() {
        println!("  {}: {} occurrences", key, count);
    }
}

Additional Context

  • EventAttributes are fundamental for event indexing and querying
  • Common attribute patterns emerge based on event types:
    • Transfer events typically include sender, recipient, and amount
    • Staking events include validator and amount
    • Governance events include proposal_id and voter
  • Attributes can be used to reconstruct transaction effects and state changes

EventBytes

pub struct EventBytes {
    pub r#type: String,
    pub attributes: Vec<EventAttributeBytes>,
}

Fields and Use Cases

r#type

  • Description: The classification or category of the event in string format
  • Use Case: Identify and categorize events while maintaining raw byte data
  • Examples:
    • "transfer"
    • "message"
    • "raw_data"

attributes

  • Description: List of key-value pairs containing event details in raw byte format
  • Use Case: Store and process binary event data that may not be UTF-8 encoded
  • Examples:
    • Raw transaction hashes
    • Binary contract data
    • Protocol buffers

Important Notes

  • EventBytes is similar to Event but handles raw byte data instead of decoded strings
  • Useful for handling binary data that may not be valid UTF-8
  • Provides more flexibility in data encoding and representation
  • Commonly used for low-level protocol operations and custom binary formats

Example Use Case: Binary Event Processing

fn process_event_bytes(event: &EventBytes) {
    println!("Binary Event Analysis:");
    println!("Event Type: {}", event.r#type);
    
    // Process binary attributes
    println!("Attributes:");
    for (index, attr) in event.attributes.iter().enumerate() {
        println!("Attribute {}:", index);
        println!("  Key (hex): 0x{}", hex::encode(&attr.key));
        println!("  Value (hex): 0x{}", hex::encode(&attr.value));
        
        // Attempt UTF-8 conversion for readable data
        if let Ok(key_str) = String::from_utf8(attr.key.clone()) {
            println!("  Key (utf8): {}", key_str);
        }
        
        if let Ok(value_str) = String::from_utf8(attr.value.clone()) {
            println!("  Value (utf8): {}", value_str);
        }
    }
}
 
// Example: Handle different binary data formats
fn analyze_binary_data(event: &EventBytes) {
    for attr in &event.attributes {
        match event.r#type.as_str() {
            "protobuf" => {
                println!("Protobuf Data:");
                println!("  Length: {} bytes", attr.value.len());
                // Process protobuf data...
            },
            
            "hash" => {
                if attr.value.len() == 32 {
                    println!("Hash Data (SHA256):");
                    println!("  {}", hex::encode(&attr.value));
                }
            },
            
            "signature" => {
                println!("Signature Data:");
                println!("  Length: {} bytes", attr.value.len());
                println!("  Raw: 0x{}", hex::encode(&attr.value));
            },
            
            _ => {
                println!("Unknown binary format:");
                println!("  Type: {}", event.r#type);
                println!("  Data length: {} bytes", attr.value.len());
            }
        }
    }
}
 
// Example: Binary data validation
fn validate_and_process_binary_event(event: &EventBytes) -> bool {
    for attr in &event.attributes {
        // Check minimum length requirements
        if attr.key.is_empty() || attr.value.is_empty() {
            println!("Warning: Empty key or value found");
            return false;
        }
        
        // Validate specific data formats
        match event.r#type.as_str() {
            "hash" => {
                if attr.value.len() != 32 {
                    println!("Invalid hash length: {}", attr.value.len());
                    return false;
                }
            },
            "address" => {
                if attr.value.len() != 20 {
                    println!("Invalid address length: {}", attr.value.len());
                    return false;
                }
            },
            _ => {}
        }
    }
    true
}

Additional Context

  • The structure maintains the event type as a string for easy categorization
  • Binary attributes allow for efficient storage and processing of non-text data
  • Important for handling low-level blockchain operations and custom protocols
  • Useful when working with cross-chain communication and custom encodings

EventAttributeBytes

pub struct EventAttributeBytes {
    pub key: Vec<u8>,
    pub value: Vec<u8>,
}

Fields and Use Cases

key

  • Description: Raw byte representation of the attribute key
  • Use Case: Store attribute identifiers in binary format
  • Examples:
    • Raw protocol identifiers
    • Binary-encoded keys
    • Custom encoding formats

value

  • Description: Raw byte representation of the attribute value
  • Use Case: Store attribute values in binary format
  • Examples:
    • Cryptographic hashes
    • Serialized data structures
    • Raw transaction data

Important Notes

  • EventAttributeBytes stores data in raw byte format without string encoding constraints
  • Useful for handling non-UTF8 data or custom binary formats

Example Use Case: Binary Attribute Processing

fn process_attribute_bytes(attr: &EventAttributeBytes) {
    println!("Binary Attribute Analysis:");
    
    // Basic byte analysis
    println!("Key:");
    println!("  Length: {} bytes", attr.key.len());
    println!("  Hex: 0x{}", hex::encode(&attr.key));
    
    println!("Value:");
    println!("  Length: {} bytes", attr.value.len());
    println!("  Hex: 0x{}", hex::encode(&attr.value));
    
    // Attempt UTF-8 interpretation
    match (String::from_utf8(attr.key.clone()), String::from_utf8(attr.value.clone())) {
        (Ok(key), Ok(value)) => {
            println!("UTF-8 Interpretation:");
            println!("  Key: {}", key);
            println!("  Value: {}", value);
        },
        _ => println!("Data contains non-UTF8 bytes")
    }
}
 
// Example: Handle different binary formats
fn analyze_binary_attribute(attr: &EventAttributeBytes) {
    // Detect common binary patterns
    match attr.value.len() {
        32 => {
            println!("Possible 256-bit hash or key:");
            println!("  {}", hex::encode(&attr.value));
        },
        20 => {
            println!("Possible address:");
            println!("  {}", hex::encode(&attr.value));
        },
        64 => {
            println!("Possible signature:");
            println!("  {}", hex::encode(&attr.value));
        },
        _ => {
            println!("Custom binary format:");
            println!("  Length: {} bytes", attr.value.len());
            println!("  First 8 bytes: {:?}", &attr.value.get(..8.min(attr.value.len())));
        }
    }
}
 
// Example: Binary attribute validation and processing
fn validate_and_process_attribute(attr: &EventAttributeBytes) -> Result<(), &'static str> {
    // Validate key
    if attr.key.is_empty() {
        return Err("Empty key not allowed");
    }
    
    // Process based on key pattern
    if attr.key.starts_with(b"tx.") {
        println!("Transaction-related attribute");
        // Process transaction data...
    } else if attr.key.starts_with(b"msg.") {
        println!("Message-related attribute");
        // Process message data...
    }
    
    // Example: Handle specific binary formats
    match attr.key.as_slice() {
        b"hash" => {
            if attr.value.len() != 32 {
                return Err("Invalid hash length");
            }
            println!("Valid hash: 0x{}", hex::encode(&attr.value));
        },
        b"pubkey" => {
            println!("Public key data: 0x{}", hex::encode(&attr.value));
            // Validate public key format...
        },
        _ => {
            println!("Generic binary data");
        }
    }
    
    Ok(())
}

TxResults

pub struct TxResults {
    pub code: u32,
    pub data: Vec<u8>,
    pub log: String,
    pub info: String,
    pub gas_wanted: i64,
    pub gas_used: i64,
    pub events: Vec<Event>,
    pub codespace: String,
}

Fields and Use Cases

code

  • Description: Result code of the transaction (0 = success, other values = various error conditions)
  • Use Case: Determine transaction success or failure
  • Examples:
    • 0: Success
    • 1: Error
    • 2: Invalid sequence
    • 11: Insufficient funds

data

  • Description: Raw result data from the transaction execution
  • Use Case: Store transaction-specific result data
  • Examples:
    • Contract return data
    • Operation results
    • Custom response data

log

  • Description: Human-readable log message of the transaction execution
  • Use Case: Debugging and monitoring transaction execution
  • Examples:
    • "transferred 100 tokens"
    • "message executed successfully"

info

  • Description: Additional information about the transaction execution
  • Use Case: Provide extra context about the transaction
  • Examples:
    • "processed by module: bank"
    • "contract execution details"

gas_wanted

  • Description: Amount of gas requested by the transaction
  • Use Case: Track gas limits set by users

gas_used

  • Description: Actual amount of gas consumed by the transaction
  • Use Case: Calculate transaction fees and monitor resource usage

events

  • Description: List of events emitted during transaction execution
  • Use Case: Track state changes and transaction effects

codespace

  • Description: Namespace for the result code
  • Use Case: Identify which module returned the result code

Example Use Case: Transaction Result Analysis

fn analyze_tx_result(result: &TxResults) {
    println!("Transaction Result Analysis:");
    
    // Check transaction status
    println!("Status: {}", match result.code {
        0 => "Success",
        1 => "Generic Error",
        2 => "Invalid Sequence",
        11 => "Insufficient Funds",
        _ => "Unknown Error",
    });
    
    // Analyze gas usage
    println!("Gas Analysis:");
    println!("  Wanted: {}", result.gas_wanted);
    println!("  Used: {}", result.gas_used);
    
    let gas_efficiency = (result.gas_used as f64 / result.gas_wanted as f64) * 100.0;
    println!("  Efficiency: {:.2}%", gas_efficiency);
    
    // Process logs and info
    if !result.log.is_empty() {
        println!("Log Message: {}", result.log);
    }
    
    if !result.info.is_empty() {
        println!("Additional Info: {}", result.info);
    }
    
    // Analyze events
    println!("Events Emitted: {}", result.events.len());
    for (i, event) in result.events.iter().enumerate() {
        println!("Event {}:", i + 1);
        println!("  Type: {}", event.r#type);
        println!("  Attributes: {}", event.attributes.len());
    }
    
    // Check for specific conditions
    if result.code != 0 {
        println!("Error Details:");
        println!("  Code: {}", result.code);
        println!("  Codespace: {}", result.codespace);
    }
}
 
// Example: Gas usage analysis
fn analyze_gas_usage(results: &[TxResults]) {
    let mut total_gas_wanted = 0i64;
    let mut total_gas_used = 0i64;
    let mut successful_txs = 0;
    
    for result in results {
        total_gas_wanted += result.gas_wanted;
        total_gas_used += result.gas_used;
        if result.code == 0 {
            successful_txs += 1;
        }
    }
    
    println!("Gas Usage Analysis:");
    println!("Total Transactions: {}", results.len());
    println!("Successful Transactions: {}", successful_txs);
    println!("Average Gas Wanted: {}", total_gas_wanted / results.len() as i64);
    println!("Average Gas Used: {}", total_gas_used / results.len() as i64);
}

ValidatorUpdate

pub struct ValidatorUpdate {
    pub pub_key: Option<PublicKey>,
    pub power: i64,
}

Fields and Use Cases

pub_key

  • Description: The validator’s public key (Optional, supports Ed25519 or Secp256k1)
  • Use Case: Identify and verify validator signatures
  • Examples:
    • Ed25519 public key
    • Secp256k1 public key

power

  • Description: The new voting power for the validator
  • Use Case: Update validator’s influence in consensus
  • Examples:
    • 0: Remove validator
    • 100: Set voting power to 100
    • 1000: Increase validator influence

Important Notes

  • ValidatorUpdate is used to modify the validator set
  • Setting power to 0 removes the validator from the active set
  • The public key identifies the validator being updated

Example Use Case: Validator Update Processing

fn process_validator_update(update: &ValidatorUpdate, total_power: i64) {
    println!("Validator Update Analysis:");
    
    // Analyze public key
    if let Some(pub_key) = &update.pub_key {
        match &pub_key.sum {
            Some(public_key::Sum::Ed25519(key)) => {
                println!("Ed25519 Public Key: 0x{}", hex::encode(key));
            },
            Some(public_key::Sum::Secp256k1(key)) => {
                println!("Secp256k1 Public Key: 0x{}", hex::encode(key));
            },
            None => println!("No public key provided"),
        }
    }
    
    // Analyze power change
    println!("Power Update: {}", update.power);
    
    // Calculate percentage of total power
    let power_percentage = (update.power as f64 / total_power as f64) * 100.0;
    println!("Percentage of Total Power: {:.2}%", power_percentage);
    
    // Analyze update type
    match update.power {
        0 => println!("Action: Removing validator from active set"),
        p if p > 0 => println!("Action: Updating validator power to {}", p),
        _ => println!("Warning: Invalid negative power value"),
    }
    
    // Security analysis
    if power_percentage > 33.33 {
        println!("WARNING: Validator would have more than 1/3 of total power");
        println!("This could affect network security and consensus");
    }
}
 
// Example: Batch validator update analysis
fn analyze_validator_updates(updates: &[ValidatorUpdate]) {
    let mut total_power_change = 0i64;
    let mut removals = 0;
    let mut additions = 0;
    let mut modifications = 0;
    
    println!("Validator Update Set Analysis:");
    println!("Total Updates: {}", updates.len());
    
    for update in updates {
        total_power_change += update.power;
        
        match update.power {
            0 => removals += 1,
            p if p > 0 && update.pub_key.is_some() => additions += 1,
            p if p > 0 => modifications += 1,
            _ => println!("Invalid update detected"),
        }
    }
    
    println!("Summary:");
    println!("  Validator Removals: {}", removals);
    println!("  New Validators: {}", additions);
    println!("  Power Modifications: {}", modifications);
    println!("  Net Power Change: {}", total_power_change);
}
 
// Example: Validate update safety
fn validate_update_safety(updates: &[ValidatorUpdate], current_total_power: i64) -> bool {
    let mut new_total_power = current_total_power;
    let mut max_single_power = 0i64;
    
    for update in updates {
        new_total_power += update.power;
        if update.power > max_single_power {
            max_single_power = update.power;
        }
    }
    
    // Check if any validator would have too much power
    if max_single_power as f64 / new_total_power as f64 > 0.3333 {
        println!("Safety Check Failed: Update would create too powerful validator");
        return false;
    }
    
    true
}

PublicKey

pub struct PublicKey {
    pub sum: Option<public_key::Sum>,
}
 
pub mod public_key {
    pub enum Sum {
        Ed25519(Vec<u8>),
        Secp256k1(Vec<u8>),
    }
}

Fields and Use Cases

sum

  • Description: Enum containing the public key data with its type
  • Use Case: Store different types of cryptographic public keys
  • Supported Types:
    • Ed25519: Modern, fast, and secure signature scheme
    • Secp256k1: Bitcoin/Ethereum compatible elliptic curve

Important Notes

  • PublicKey supports multiple cryptographic algorithms
  • Ed25519 is commonly used for validator keys
  • Secp256k1 is used for compatibility with other blockchain systems
  • The enum structure allows for future addition of new key types

Example Use Case: Public Key Processing and Validation

fn process_public_key(pub_key: &PublicKey) {
    println!("Public Key Analysis:");
    
    match &pub_key.sum {
        Some(public_key::Sum::Ed25519(key_data)) => {
            println!("Key Type: Ed25519");
            println!("Key Length: {} bytes", key_data.len());
            println!("Key Data: 0x{}", hex::encode(key_data));
            
            // Validate Ed25519 key length
            if key_data.len() != 32 {
                println!("Warning: Invalid Ed25519 key length (expected 32 bytes)");
            }
        },
        Some(public_key::Sum::Secp256k1(key_data)) => {
            println!("Key Type: Secp256k1");
            println!("Key Length: {} bytes", key_data.len());
            println!("Key Data: 0x{}", hex::encode(key_data));
            
            // Validate Secp256k1 key length
            if key_data.len() != 33 && key_data.len() != 65 {
                println!("Warning: Invalid Secp256k1 key length (expected 33 or 65 bytes)");
            }
        },
        None => {
            println!("No public key data present");
        }
    }
}
 
// Example: Key type specific validation
fn validate_public_key(pub_key: &PublicKey) -> Result<(), &'static str> {
    match &pub_key.sum {
        Some(public_key::Sum::Ed25519(key_data)) => {
            if key_data.len() != 32 {
                return Err("Invalid Ed25519 key length");
            }
            
            // Additional Ed25519 validation
            if key_data.iter().all(|&x| x == 0) {
                return Err("Invalid Ed25519 key: all zeros");
            }
        },
        Some(public_key::Sum::Secp256k1(key_data)) => {
            match key_data.len() {
                33 => {
                    // Compressed key validation
                    if !matches!(key_data[0], 0x02 | 0x03) {
                        return Err("Invalid Secp256k1 compressed key prefix");
                    }
                },
                65 => {
                    // Uncompressed key validation
                    if key_data[0] != 0x04 {
                        return Err("Invalid Secp256k1 uncompressed key prefix");
                    }
                },
                _ => return Err("Invalid Secp256k1 key length"),
            }
        },
        None => return Err("Missing public key data"),
    }
    Ok(())
}
 
// Example: Key format conversion and handling
fn handle_public_key(pub_key: &PublicKey) {
    match &pub_key.sum {
        Some(public_key::Sum::Ed25519(key_data)) => {
            // Example: Convert to base64 for storage/transmission
            let b64_key = base64::encode(key_data);
            println!("Ed25519 Key (Base64): {}", b64_key);
            
            // Example: Generate key fingerprint
            let mut hasher = sha2::Sha256::new();
            hasher.update(key_data);
            let fingerprint = hasher.finalize();
            
            println!("Key Fingerprint: 0x{}", hex::encode(&fingerprint));
        },
        Some(public_key::Sum::Secp256k1(key_data)) => {
            // Example: Convert to base64 for storage/transmission
            let b64_key = base64::encode(key_data);
            println!("Secp256k1 Key (Base64): {}", b64_key);
            
            // Example: Generate key fingerprint
            let mut hasher = sha2::Sha256::new();
            hasher.update(key_data);
            let fingerprint = hasher.finalize();
            
            println!("Key Fingerprint: 0x{}", hex::encode(&fingerprint));
        },
        None => {
            println!("No public key data present");
        }
    }
}

ConsensusParams

pub struct ConsensusParams {
    pub block: Option<BlockParams>,
    pub evidence: Option<EvidenceParams>,
    pub validator: Option<ValidatorParams>,
    pub version: Option<VersionParams>,
}

Fields and Use Cases

block

  • Description: Parameters that define block constraints
  • Use Case: Control block size and gas limits
  • Examples:
    • Maximum block size
    • Maximum gas per block

evidence

  • Description: Parameters for handling validator misbehavior evidence
  • Use Case: Define evidence submission and validation rules
  • Examples:
    • Evidence age limit
    • Maximum evidence size

validator

  • Description: Parameters that define validator requirements
  • Use Case: Specify allowed validator public key types
  • Examples:
    • Allowed public key algorithms
    • Validator requirements

version

  • Description: Parameters related to app versioning
  • Use Case: Manage application version compatibility
  • Examples:
    • App version
    • Protocol version requirements

Important Notes

  • ConsensusParams define the rules for block creation and validation
  • Changes to these parameters require network consensus
  • Parameters affect network performance and security
  • All fields are optional to allow partial updates

Example Use Case: Consensus Parameter Analysis and Validation

fn analyze_consensus_params(params: &ConsensusParams) {
    println!("Consensus Parameters Analysis:");
    
    // Analyze Block Parameters
    if let Some(block) = &params.block {
        println!("\nBlock Parameters:");
        println!("  Max Bytes: {}", block.max_bytes);
        println!("  Max Gas: {}", block.max_gas);
        
        // Validate block parameters
        if block.max_bytes <= 0 {
            println!("Warning: Invalid max_bytes value");
        }
        if block.max_gas < -1 {
            println!("Warning: Invalid max_gas value");
        }
    }
    
    // Analyze Evidence Parameters
    if let Some(evidence) = &params.evidence {
        println!("\nEvidence Parameters:");
        println!("  Max Age (blocks): {}", evidence.max_age_num_blocks);
        println!("  Max Bytes: {}", evidence.max_bytes);
        
        if let Some(duration) = &evidence.max_age_duration {
            println!("  Max Age Duration: {} seconds", 
                duration.seconds + (duration.nanos as f64 / 1_000_000_000.0));
        }
    }
    
    // Analyze Validator Parameters
    if let Some(validator) = &params.validator {
        println!("\nValidator Parameters:");
        println!("  Allowed Public Key Types:");
        for key_type in &validator.pub_key_types {
            println!("    - {}", key_type);
        }
    }
    
    // Analyze Version Parameters
    if let Some(version) = &params.version {
        println!("\nVersion Parameters:");
        println!("  App Version: {}", version.app);
    }
}
 
// Example: Parameter validation
fn validate_consensus_params(params: &ConsensusParams) -> Result<(), String> {
    // Validate Block Parameters
    if let Some(block) = &params.block {
        if block.max_bytes <= 0 {
            return Err(format!("Invalid max_bytes: {}", block.max_bytes));
        }
        if block.max_gas < -1 {
            return Err(format!("Invalid max_gas: {}", block.max_gas));
        }
    }
    
    // Validate Evidence Parameters
    if let Some(evidence) = &params.evidence {
        if evidence.max_age_num_blocks <= 0 {
            return Err(format!("Invalid max_age_num_blocks: {}", evidence.max_age_num_blocks));
        }
        if evidence.max_bytes <= 0 {
            return Err(format!("Invalid evidence max_bytes: {}", evidence.max_bytes));
        }
    }
    
    // Validate Validator Parameters
    if let Some(validator) = &params.validator {
        if validator.pub_key_types.is_empty() {
            return Err("No public key types specified".to_string());
        }
    }
    
    Ok(())
}
 
// Example: Parameter comparison
fn compare_consensus_params(old: &ConsensusParams, new: &ConsensusParams) {
    println!("Consensus Parameters Changes:");
    
    // Compare Block Parameters
    match (&old.block, &new.block) {
        (Some(old_block), Some(new_block)) => {
            if old_block.max_bytes != new_block.max_bytes {
                println!("Max Bytes: {} -> {}", old_block.max_bytes, new_block.max_bytes);
            }
            if old_block.max_gas != new_block.max_gas {
                println!("Max Gas: {} -> {}", old_block.max_gas, new_block.max_gas);
            }
        }
        _ => println!("Block parameters comparison unavailable"),
    }
    
    // Compare Version
    match (&old.version, &new.version) {
        (Some(old_version), Some(new_version)) => {
            if old_version.app != new_version.app {
                println!("App Version: {} -> {}", old_version.app, new_version.app);
            }
        }
        _ => println!("Version parameters comparison unavailable"),
    }
}

BlockParams

pub struct BlockParams {
    pub max_bytes: i64,
    pub max_gas: i64,
}

Fields and Use Cases

max_bytes

  • Description: Maximum allowed size of a block in bytes
  • Use Case: Control block size to manage network bandwidth and storage
  • Examples:
    • 1048576 (1MB)
    • 2097152 (2MB)
    • 5242880 (5MB)

max_gas

  • Description: Maximum total gas allowed per block
  • Use Case: Limit computational resources used per block
  • Examples:
    • -1: Unlimited gas
    • 10000000: 10 million gas units
    • 30000000: 30 million gas units

Important Notes

  • BlockParams control fundamental block-level constraints
  • Values affect network performance and resource usage
  • Must balance between throughput and resource constraints
  • Changes require careful consideration of network capacity

Example Use Case: Block Parameters Analysis and Validation

fn analyze_block_params(params: &BlockParams) {
    println!("Block Parameters Analysis:");
    
    // Analyze max_bytes
    println!("\nMax Bytes Analysis:");
    println!("  Value: {} bytes", params.max_bytes);
    println!("  In MB: {:.2} MB", params.max_bytes as f64 / 1_048_576.0);
    
    match params.max_bytes {
        size if size <= 0 => println!("  Warning: Invalid block size"),
        size if size < 512_000 => println!("  Note: Small block size may limit throughput"),
        size if size > 10_485_760 => println!("  Warning: Large block size may impact network stability"),
        _ => println!("  Status: Block size within normal range"),
    }
    
    // Analyze max_gas
    println!("\nMax Gas Analysis:");
    println!("  Value: {}", params.max_gas);
    
    match params.max_gas {
        -1 => println!("  Note: Unlimited gas allowed"),
        0 => println!("  Warning: Zero gas limit will prevent transactions"),
        gas if gas < 0 => println!("  Warning: Invalid negative gas limit"),
        gas if gas < 1_000_000 => println!("  Warning: Low gas limit may restrict transaction throughput"),
        gas if gas > 100_000_000 => println!("  Note: High gas limit - ensure network capacity"),
        _ => println!("  Status: Gas limit within normal range"),
    }
}
 
// Example: Parameter validation
fn validate_block_params(params: &BlockParams) -> Result<(), String> {
    // Validate max_bytes
    if params.max_bytes <= 0 {
        return Err(format!("Invalid max_bytes: {}", params.max_bytes));
    }
    
    // Validate max_gas
    if params.max_gas < -1 {
        return Err(format!("Invalid max_gas: {}", params.max_gas));
    }
    
    Ok(())
}
 
// Example: Resource usage estimation
fn estimate_block_resources(params: &BlockParams) {
    println!("Block Resource Estimation:");
    
    // Storage estimation
    let storage_mb = params.max_bytes as f64 / 1_048_576.0;
    println!("\nStorage Requirements:");
    println!("  Per Block: {:.2} MB", storage_mb);
    println!("  Per Hour: {:.2} MB", storage_mb * 60.0); // Assuming 1 block/minute
    println!("  Per Day: {:.2} GB", storage_mb * 1440.0 / 1024.0);
    
    // Gas usage estimation
    if params.max_gas > 0 {
        println!("\nGas Usage Estimation:");
        println!("  Average Transaction Gas: 100,000");
        let max_tx_per_block = params.max_gas / 100_000;
        println!("  Estimated Max Transactions per Block: {}", max_tx_per_block);
        println!("  Estimated TPS: {:.2}", max_tx_per_block as f64 / 60.0); // Assuming 1 block/minute
    }
}
 
// Example: Compare block parameters
fn compare_block_params(old: &BlockParams, new: &BlockParams) {
    println!("Block Parameters Comparison:");
    
    // Compare max_bytes
    let bytes_change = ((new.max_bytes as f64 - old.max_bytes as f64) / old.max_bytes as f64) * 100.0;
    println!("\nMax Bytes:");
    println!("  Old: {} bytes", old.max_bytes);
    println!("  New: {} bytes", new.max_bytes);
    println!("  Change: {:.2}%", bytes_change);
    
    // Compare max_gas
    if old.max_gas > 0 && new.max_gas > 0 {
        let gas_change = ((new.max_gas as f64 - old.max_gas as f64) / old.max_gas as f64) * 100.0;
        println!("\nMax Gas:");
        println!("  Old: {}", old.max_gas);
        println!("  New: {}", new.max_gas);
        println!("  Change: {:.2}%", gas_change);
    } else {
        println!("\nMax Gas:");
        println!("  Old: {}", if old.max_gas == -1 { "Unlimited" } else { &old.max_gas.to_string() });
        println!("  New: {}", if new.max_gas == -1 { "Unlimited" } else { &new.max_gas.to_string() });
    }
}

EvidenceParams

pub struct EvidenceParams {
    pub max_age_num_blocks: i64,
    pub max_age_duration: Option<Duration>,
    pub max_bytes: i64,
}

Fields and Use Cases

max_age_num_blocks

  • Description: Maximum number of blocks after which evidence is considered too old
  • Use Case: Define time window for submitting validator misbehavior evidence
  • Examples:
    • 100800: ~1 week (assuming 6s blocks)
    • 50400: ~3.5 days
    • 201600: ~2 weeks

max_age_duration

  • Description: Maximum time duration after which evidence is considered too old
  • Use Case: Provide absolute time limit for evidence submission
  • Examples:
    • 604800s: 1 week
    • 86400s: 1 day
    • 1209600s: 2 weeks

max_bytes

  • Description: Maximum size of total evidence in bytes that can be committed in a single block
  • Use Case: Control resource usage for evidence processing
  • Examples:
    • 1048576: 1MB
    • 524288: 512KB
    • 2097152: 2MB

Important Notes

  • EvidenceParams control the rules for submitting and processing validator misbehavior evidence
  • Both block height and time-based age limits must be satisfied
  • Evidence size limits prevent DoS attacks through excessive evidence submission
  • Parameters affect the network’s ability to punish misbehaving validators

Example Use Case: Evidence Parameters Analysis and Validation

fn analyze_evidence_params(params: &EvidenceParams) {
    println!("Evidence Parameters Analysis:");
    
    // Analyze block age limit
    println!("\nBlock Age Limit:");
    println!("  Max Age in Blocks: {}", params.max_age_num_blocks);
    
    // Estimate time (assuming 6s block time)
    let estimated_hours = (params.max_age_num_blocks as f64 * 6.0) / 3600.0;
    println!("  Estimated Time: {:.2} hours ({:.2} days)", 
        estimated_hours, estimated_hours / 24.0);
    
    // Analyze duration limit
    if let Some(duration) = &params.max_age_duration {
        let total_seconds = duration.seconds + (duration.nanos as f64 / 1_000_000_000.0);
        println!("\nTime Duration Limit:");
        println!("  Seconds: {}", total_seconds);
        println!("  Hours: {:.2}", total_seconds / 3600.0);
        println!("  Days: {:.2}", total_seconds / 86400.0);
    }
    
    // Analyze size limit
    println!("\nSize Limit:");
    println!("  Max Bytes: {}", params.max_bytes);
    println!("  In KB: {:.2}", params.max_bytes as f64 / 1024.0);
    println!("  In MB: {:.2}", params.max_bytes as f64 / 1_048_576.0);
}
 
// Example: Validate evidence parameters
fn validate_evidence_params(params: &EvidenceParams) -> Result<(), String> {
    // Validate block age
    if params.max_age_num_blocks <= 0 {
        return Err("Invalid max_age_num_blocks: must be positive".to_string());
    }
    
    // Validate duration if present
    if let Some(duration) = &params.max_age_duration {
        if duration.seconds < 0 || duration.nanos < 0 {
            return Err("Invalid duration: negative time not allowed".to_string());
        }
        if duration.nanos >= 1_000_000_000 {
            return Err("Invalid duration: nanos must be < 1 second".to_string());
        }
    }
    
    // Validate size limit
    if params.max_bytes <= 0 {
        return Err("Invalid max_bytes: must be positive".to_string());
    }
    
    Ok(())
}
 
// Example: Check evidence validity
fn check_evidence_validity(
    params: &EvidenceParams,
    evidence_age_blocks: i64,
    evidence_age_seconds: i64,
    evidence_size: i64,
) -> bool {
    println!("Evidence Validity Check:");
    
    // Check block age
    if evidence_age_blocks > params.max_age_num_blocks {
        println!("Evidence too old (blocks): {} > {}", 
            evidence_age_blocks, params.max_age_num_blocks);
        return false;
    }
    
    // Check time duration
    if let Some(max_duration) = &params.max_age_duration {
        if evidence_age_seconds > max_duration.seconds {
            println!("Evidence too old (time): {} > {}", 
                evidence_age_seconds, max_duration.seconds);
            return false;
        }
    }
    
    // Check size
    if evidence_size > params.max_bytes {
        println!("Evidence too large: {} > {}", evidence_size, params.max_bytes);
        return false;
    }
    
    println!("Evidence is valid");
    true
}

ValidatorParams

pub struct ValidatorParams {
    pub pub_key_types: Vec<String>,
}

Fields and Use Cases

pub_key_types

  • Description: List of allowed public key types for validators
  • Use Case: Define which cryptographic algorithms are accepted for validator keys
  • Examples:
    • ["ed25519"]
    • ["ed25519", "secp256k1"]
    • ["ed25519", "secp256k1", "sr25519"]

Important Notes

  • ValidatorParams define the acceptable cryptographic schemes for validators
  • Restricts which types of keys can be used for validation
  • Affects security and compatibility of the validator set
  • Multiple key types can be supported simultaneously

Example Use Case: Validator Parameters Analysis and Validation

fn analyze_validator_params(params: &ValidatorParams) {
    println!("Validator Parameters Analysis:");
    
    // Analyze supported key types
    println!("\nSupported Public Key Types:");
    for (index, key_type) in params.pub_key_types.iter().enumerate() {
        println!("  {}. {}", index + 1, key_type);
        
        // Provide information about each key type
        match key_type.as_str() {
            "ed25519" => println!("     - Modern, fast, and secure signature scheme"),
            "secp256k1" => println!("     - Bitcoin/Ethereum compatible elliptic curve"),
            "sr25519" => println!("     - Schnorr signatures on Ristretto point group"),
            _ => println!("     - Unknown key type"),
        }
    }
    
    // Security analysis
    println!("\nSecurity Analysis:");
    if params.pub_key_types.is_empty() {
        println!("  Warning: No public key types specified!");
    }
    
    let has_modern_crypto = params.pub_key_types.contains(&"ed25519".to_string());
    println!("  Modern Cryptography: {}", if has_modern_crypto { "Yes" } else { "No" });
    
    let has_blockchain_compatible = params.pub_key_types.contains(&"secp256k1".to_string());
    println!("  Blockchain Compatible: {}", if has_blockchain_compatible { "Yes" } else { "No" });
}
 
// Example: Validate parameters
fn validate_validator_params(params: &ValidatorParams) -> Result<(), String> {
    // Check if any key types are specified
    if params.pub_key_types.is_empty() {
        return Err("No public key types specified".to_string());
    }
    
    // Validate each key type
    for key_type in &params.pub_key_types {
        match key_type.as_str() {
            "ed25519" | "secp256k1" | "sr25519" => continue,
            unknown => return Err(format!("Unsupported key type: {}", unknown)),
        }
    }
    
    // Check for duplicates
    let mut unique_types = std::collections::HashSet::new();
    for key_type in &params.pub_key_types {
        if !unique_types.insert(key_type) {
            return Err(format!("Duplicate key type: {}", key_type));
        }
    }
    
    Ok(())
}
 
// Example: Key type compatibility check
fn check_key_compatibility(params: &ValidatorParams, key_type: &str) -> bool {
    println!("Checking compatibility for key type: {}", key_type);
    
    let is_compatible = params.pub_key_types.contains(&key_type.to_string());
    
    if is_compatible {
        println!("  Result: Compatible");
        
        // Additional information
        match key_type {
            "ed25519" => println!("  Note: Recommended for new validators"),
            "secp256k1" => println!("  Note: Compatible with Ethereum/Bitcoin ecosystems"),
            "sr25519" => println!("  Note: Supports advanced signature schemes"),
            _ => println!("  Note: Custom key type"),
        }
    } else {
        println!("  Result: Incompatible");
        println!("  Allowed types: {:?}", params.pub_key_types);
    }
    
    is_compatible
}
 
// Example: Generate validator params summary
fn generate_params_summary(params: &ValidatorParams) -> String {
    let mut summary = String::new();
    
    summary.push_str("Validator Parameters Summary:\n");
    summary.push_str(&format!("Total Key Types: {}\n", params.pub_key_types.len()));
    
    if !params.pub_key_types.is_empty() {
        summary.push_str("Supported Types:\n");
        for key_type in &params.pub_key_types {
            summary.push_str(&format!("  - {}\n", key_type));
        }
    } else {
        summary.push_str("Warning: No key types specified\n");
    }
    
    summary
}

VersionParams

pub struct VersionParams {
    pub app: i64,
}

Fields and Use Cases

app

  • Description: The application protocol version number
  • Use Case: Track and enforce application version compatibility
  • Examples:
    • 0: Initial version
    • 1: First major upgrade
    • 2: Second major upgrade

Important Notes

  • VersionParams manages application-level version compatibility
  • Critical for coordinating network upgrades
  • Helps ensure all nodes are running compatible software
  • Single version number represents the entire application state

Example Use Case: Version Parameters Analysis and Management

fn analyze_version_params(params: &VersionParams) {
    println!("Version Parameters Analysis:");
    
    // Basic version information
    println!("\nApplication Version: {}", params.app);
    
    // Version status analysis
    match params.app {
        0 => println!("Status: Initial version"),
        1..=5 => println!("Status: Early production version"),
        6..=10 => println!("Status: Mature version"),
        11.. => println!("Status: Advanced version"),
        _ => println!("Status: Invalid version"),
    }
    
    // Version compatibility check
    println!("\nCompatibility Analysis:");
    println!("Minimum Supported: 1");
    println!("Current: {}", params.app);
    println!("Compatible: {}", params.app >= 1);
}
 
// Example: Version upgrade validation
fn validate_version_upgrade(
    current: &VersionParams,
    new: &VersionParams
) -> Result<(), String> {
    println!("Validating Version Upgrade:");
    println!("  Current: {}", current.app);
    println!("  Proposed: {}", new.app);
    
    // Check for valid upgrade path
    if new.app < current.app {
        return Err(format!(
            "Invalid downgrade from {} to {}", 
            current.app, 
            new.app
        ));
    }
    
    // Check version jump size
    let version_jump = new.app - current.app;
    if version_jump > 1 {
        println!("Warning: Large version jump of {} versions", version_jump);
    }
    
    Ok(())
}
 
// Example: Version compatibility matrix
fn generate_compatibility_matrix(params: &VersionParams) {
    println!("Version Compatibility Matrix:");
    println!("Current Version: {}\n", params.app);
    
    println!("Compatibility Table:");
    println!("Version | Status");
    println!("---------|--------");
    
    for version in (params.app - 2).max(0)..=params.app + 2 {
        let status = match version.cmp(&params.app) {
            std::cmp::Ordering::Less => "Legacy",
            std::cmp::Ordering::Equal => "Current",
            std::cmp::Ordering::Greater => "Future",
        };
        println!("{:8} | {}", version, status);
    }
}
 
// Example: Version feature support check
fn check_feature_support(params: &VersionParams) {
    println!("Feature Support Analysis:");
    
    // Example feature matrix
    let features = [
        (1, "Basic Transactions"),
        (2, "Smart Contracts"),
        (3, "IBC Support"),
        (4, "Governance"),
        (5, "Advanced Features"),
    ];
    
    println!("\nSupported Features:");
    for (version, feature) in features.iter() {
        let supported = params.app >= *version;
        println!("  {}: {} (v{}+)", 
            feature,
            if supported { "Supported" } else { "Not Supported" },
            version
        );
    }
}
 
// Example: Generate version update summary
fn generate_version_summary(old: &VersionParams, new: &VersionParams) -> String {
    let mut summary = String::new();
    
    summary.push_str("Version Update Summary:\n");
    summary.push_str(&format!("Previous Version: {}\n", old.app));
    summary.push_str(&format!("New Version: {}\n", new.app));
    
    let version_diff = new.app - old.app;
    summary.push_str(&format!("Version Difference: {}\n", version_diff));
    
    if version_diff > 0 {
        summary.push_str("Update Type: Upgrade\n");
    } else if version_diff < 0 {
        summary.push_str("Update Type: Downgrade (Warning!)\n");
    } else {
        summary.push_str("Update Type: No Change\n");
    }
    
    summary
}

HashedParams

pub struct HashedParams {
    pub block_max_bytes: i64,
    pub block_max_gas: i64,
}

Fields and Use Cases

block_max_bytes

  • Description: Maximum block size in bytes (hashed version of BlockParams max_bytes)
  • Use Case: Verify and track block size limits in consensus
  • Examples:
    • 1048576 (1MB)
    • 2097152 (2MB)
    • 5242880 (5MB)

block_max_gas

  • Description: Maximum block gas limit (hashed version of BlockParams max_gas)
  • Use Case: Verify and track block gas limits in consensus
  • Examples:
    • -1: Unlimited gas
    • 10000000: 10 million gas units
    • 30000000: 30 million gas units

Important Notes

  • HashedParams is a simplified version of BlockParams used in consensus
  • Contains only the essential parameters that affect block validation
  • Used for quick verification without loading full parameter set
  • Important for maintaining consensus on block limitations

Example Use Case: Hashed Parameters Analysis and Validation

fn analyze_hashed_params(params: &HashedParams) {
    println!("Hashed Parameters Analysis:");
    
    // Block size analysis
    println!("\nBlock Size Limit:");
    println!("  Max Bytes: {}", params.block_max_bytes);
    println!("  In MB: {:.2}", params.block_max_bytes as f64 / 1_048_576.0);
    
    match params.block_max_bytes {
        size if size <= 0 => println!("  Status: Invalid block size"),
        size if size < 512_000 => println!("  Status: Conservative block size"),
        size if size > 10_485_760 => println!("  Status: Large block size - verify network capacity"),
        _ => println!("  Status: Standard block size"),
    }
    
    // Gas limit analysis
    println!("\nGas Limit:");
    println!("  Max Gas: {}", params.block_max_gas);
    
    match params.block_max_gas {
        -1 => println!("  Status: Unlimited gas"),
        0 => println!("  Status: Warning - Zero gas limit"),
        gas if gas < 0 => println!("  Status: Invalid negative gas limit"),
        gas if gas < 1_000_000 => println!("  Status: Very low gas limit"),
        gas if gas > 100_000_000 => println!("  Status: High gas limit"),
        _ => println!("  Status: Standard gas limit"),
    }
}
 
// Example: Validate parameters
fn validate_hashed_params(params: &HashedParams) -> Result<(), String> {
    // Validate block size
    if params.block_max_bytes <= 0 {
        return Err(format!(
            "Invalid block_max_bytes: {}",
            params.block_max_bytes
        ));
    }
    
    // Validate gas limit
    if params.block_max_gas < -1 {
        return Err(format!(
            "Invalid block_max_gas: {}",
            params.block_max_gas
        ));
    }
    
    Ok(())
}
 
// Example: Compare with BlockParams
fn compare_with_block_params(
    hashed: &HashedParams,
    block: &BlockParams
) -> bool {
    println!("Parameter Comparison:");
    
    let bytes_match = hashed.block_max_bytes == block.max_bytes;
    let gas_match = hashed.block_max_gas == block.max_gas;
    
    println!("\nBlock Max Bytes:");
    println!("  Hashed: {}", hashed.block_max_bytes);
    println!("  Block: {}", block.max_bytes);
    println!("  Match: {}", bytes_match);
    
    println!("\nBlock Max Gas:");
    println!("  Hashed: {}", hashed.block_max_gas);
    println!("  Block: {}", block.max_gas);
    println!("  Match: {}", gas_match);
    
    bytes_match && gas_match
}
 
// Example: Resource limit calculation
fn calculate_resource_limits(params: &HashedParams) {
    println!("Resource Limit Calculations:");
    
    // Block size calculations
    let size_mb = params.block_max_bytes as f64 / 1_048_576.0;
    println!("\nBlock Size:");
    println!("  Bytes: {}", params.block_max_bytes);
    println!("  MB: {:.2}", size_mb);
    println!("  Estimated Storage per Day: {:.2} GB", 
        (size_mb * 144.0) / 1024.0); // Assuming 10-minute blocks
    
    // Gas calculations
    if params.block_max_gas > 0 {
        println!("\nGas Usage:");
        println!("  Max Gas per Block: {}", params.block_max_gas);
        
        // Estimate transaction capacity
        let avg_tx_gas = 100_000; // Example average transaction gas
        let max_tx_per_block = params.block_max_gas / avg_tx_gas;
        println!("  Estimated Max Transactions per Block: {}", max_tx_per_block);
        println!("  Estimated Max TPS: {:.2}", 
            max_tx_per_block as f64 / 600.0); // Assuming 10-minute blocks
    } else if params.block_max_gas == -1 {
        println!("\nGas Usage: Unlimited");
    }
}