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
header
- 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
: Success1
: Error2
: Invalid sequence11
: 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 validator100
: Set voting power to 1001000
: 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) = ¶ms.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) = ¶ms.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) = ¶ms.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) = ¶ms.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) = ¶ms.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) = ¶ms.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) = ¶ms.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 gas10000000
: 10 million gas units30000000
: 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 days201600
: ~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 week86400s
: 1 day1209600s
: 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
: 1MB524288
: 512KB2097152
: 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) = ¶ms.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) = ¶ms.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) = ¶ms.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 ¶ms.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 ¶ms.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 ¶ms.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 version1
: First major upgrade2
: 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(¶ms.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 gas10000000
: 10 million gas units30000000
: 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");
}
}