- Introduced `ibc_example.rs` demonstrating Inter-Blockchain Communication operations including cross-chain transfers, channel management, packet handling, and relayer operations. - Introduced `zk_example.rs` showcasing Zero-Knowledge proof operations such as circuit compilation, proof generation and verification, and on-chain verification with multiple proving systems.
435 lines
14 KiB
Rust
435 lines
14 KiB
Rust
//! Synor Compiler SDK Examples for Rust
|
|
//!
|
|
//! Demonstrates smart contract compilation and analysis:
|
|
//! - WASM contract compilation and optimization
|
|
//! - ABI extraction and encoding
|
|
//! - Contract analysis and security scanning
|
|
//! - Validation and verification
|
|
|
|
use std::env;
|
|
use synor_compiler::{
|
|
CompilerConfig, CompileOptions, OptimizationLevel, StripOptions, SynorCompiler,
|
|
};
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
// Initialize client
|
|
let config = CompilerConfig {
|
|
api_key: env::var("SYNOR_API_KEY").unwrap_or_else(|_| "your-api-key".to_string()),
|
|
endpoint: "https://compiler.synor.io/v1".to_string(),
|
|
timeout: 60000,
|
|
retries: 3,
|
|
debug: false,
|
|
default_optimization_level: OptimizationLevel::Size,
|
|
max_contract_size: 256 * 1024,
|
|
use_wasm_opt: true,
|
|
validate: true,
|
|
extract_metadata: true,
|
|
generate_abi: true,
|
|
};
|
|
|
|
let compiler = SynorCompiler::new(config)?;
|
|
|
|
// Check service health
|
|
let healthy = compiler.health_check().await?;
|
|
println!("Service healthy: {}\n", healthy);
|
|
|
|
// Run examples
|
|
compile_contract_example(&compiler).await?;
|
|
compilation_modes_example(&compiler).await?;
|
|
abi_example(&compiler).await?;
|
|
analysis_example(&compiler).await?;
|
|
validation_example(&compiler).await?;
|
|
security_example(&compiler).await?;
|
|
|
|
compiler.close().await?;
|
|
Ok(())
|
|
}
|
|
|
|
/// Create a minimal valid WASM module for testing.
|
|
fn create_minimal_wasm() -> Vec<u8> {
|
|
vec![
|
|
0x00, 0x61, 0x73, 0x6d, // Magic: \0asm
|
|
0x01, 0x00, 0x00, 0x00, // Version: 1
|
|
// Type section
|
|
0x01, 0x07, 0x01, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f,
|
|
// Function section
|
|
0x03, 0x02, 0x01, 0x00,
|
|
// Export section
|
|
0x07, 0x08, 0x01, 0x04, 0x61, 0x64, 0x64, 0x00, 0x00,
|
|
// Code section
|
|
0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b,
|
|
]
|
|
}
|
|
|
|
async fn compile_contract_example(compiler: &SynorCompiler) -> Result<(), Box<dyn std::error::Error>> {
|
|
println!("=== Contract Compilation ===");
|
|
|
|
let wasm = create_minimal_wasm();
|
|
|
|
let result = compiler
|
|
.compile(
|
|
&wasm,
|
|
Some(CompileOptions {
|
|
optimization_level: OptimizationLevel::Size,
|
|
use_wasm_opt: true,
|
|
validate: true,
|
|
extract_metadata: true,
|
|
generate_abi: true,
|
|
strip_options: Some(StripOptions {
|
|
strip_debug: true,
|
|
strip_producers: true,
|
|
strip_names: true,
|
|
strip_custom: true,
|
|
strip_unused: true,
|
|
preserve_sections: vec![],
|
|
}),
|
|
}),
|
|
)
|
|
.await?;
|
|
|
|
println!("Compilation result:");
|
|
println!(" Contract ID: {}", result.contract_id);
|
|
println!(" Code hash: {}", result.code_hash);
|
|
println!(" Original size: {} bytes", result.original_size);
|
|
println!(" Optimized size: {} bytes", result.optimized_size);
|
|
println!(" Size reduction: {:.1}%", result.size_reduction);
|
|
println!(" Estimated deploy gas: {}", result.estimated_deploy_gas);
|
|
|
|
if let Some(metadata) = &result.metadata {
|
|
println!("\nMetadata:");
|
|
println!(" Name: {}", metadata.name);
|
|
println!(" Version: {}", metadata.version);
|
|
println!(" SDK Version: {}", metadata.sdk_version);
|
|
}
|
|
|
|
if let Some(abi) = &result.abi {
|
|
println!("\nABI:");
|
|
println!(" Functions: {}", abi.functions.as_ref().map_or(0, |f| f.len()));
|
|
println!(" Events: {}", abi.events.as_ref().map_or(0, |e| e.len()));
|
|
println!(" Errors: {}", abi.errors.as_ref().map_or(0, |e| e.len()));
|
|
}
|
|
|
|
println!();
|
|
Ok(())
|
|
}
|
|
|
|
async fn compilation_modes_example(compiler: &SynorCompiler) -> Result<(), Box<dyn std::error::Error>> {
|
|
println!("=== Compilation Modes ===");
|
|
|
|
let wasm = create_minimal_wasm();
|
|
|
|
// Development mode: fast compilation, debugging support
|
|
println!("Development mode:");
|
|
let dev_result = compiler.contracts.compile_dev(&wasm).await?;
|
|
println!(" Size: {} bytes", dev_result.optimized_size);
|
|
println!(" Optimization: none");
|
|
|
|
// Production mode: maximum optimization
|
|
println!("\nProduction mode:");
|
|
let prod_result = compiler.contracts.compile_production(&wasm).await?;
|
|
println!(" Size: {} bytes", prod_result.optimized_size);
|
|
println!(" Optimization: aggressive");
|
|
println!(
|
|
" Size savings: {} bytes",
|
|
dev_result.optimized_size - prod_result.optimized_size
|
|
);
|
|
|
|
// Custom optimization levels
|
|
println!("\nOptimization levels:");
|
|
let levels = [
|
|
OptimizationLevel::None,
|
|
OptimizationLevel::Basic,
|
|
OptimizationLevel::Size,
|
|
OptimizationLevel::Aggressive,
|
|
];
|
|
|
|
for level in levels {
|
|
let result = compiler
|
|
.compile(
|
|
&wasm,
|
|
Some(CompileOptions {
|
|
optimization_level: level,
|
|
..Default::default()
|
|
}),
|
|
)
|
|
.await?;
|
|
println!(" {:?}: {} bytes", level, result.optimized_size);
|
|
}
|
|
|
|
println!();
|
|
Ok(())
|
|
}
|
|
|
|
async fn abi_example(compiler: &SynorCompiler) -> Result<(), Box<dyn std::error::Error>> {
|
|
println!("=== ABI Operations ===");
|
|
|
|
let wasm = create_minimal_wasm();
|
|
|
|
// Extract ABI from WASM
|
|
let abi = compiler.abi.extract(&wasm).await?;
|
|
println!("Contract: {}", abi.name);
|
|
println!("Version: {}", abi.version);
|
|
|
|
// List functions
|
|
if let Some(functions) = &abi.functions {
|
|
if !functions.is_empty() {
|
|
println!("\nFunctions:");
|
|
for func in functions {
|
|
let inputs = func
|
|
.inputs
|
|
.as_ref()
|
|
.map(|inputs| {
|
|
inputs
|
|
.iter()
|
|
.map(|i| format!("{}: {}", i.name, i.type_info.type_name))
|
|
.collect::<Vec<_>>()
|
|
.join(", ")
|
|
})
|
|
.unwrap_or_default();
|
|
|
|
let outputs = func
|
|
.outputs
|
|
.as_ref()
|
|
.map(|outputs| {
|
|
outputs
|
|
.iter()
|
|
.map(|o| o.type_info.type_name.clone())
|
|
.collect::<Vec<_>>()
|
|
.join(", ")
|
|
})
|
|
.unwrap_or_else(|| "void".to_string());
|
|
|
|
let mut modifiers = vec![];
|
|
if func.view {
|
|
modifiers.push("view");
|
|
}
|
|
if func.payable {
|
|
modifiers.push("payable");
|
|
}
|
|
|
|
println!(
|
|
" {}({}) -> {} {}",
|
|
func.name,
|
|
inputs,
|
|
outputs,
|
|
modifiers.join(" ")
|
|
);
|
|
println!(" Selector: {}", func.selector);
|
|
}
|
|
}
|
|
}
|
|
|
|
// List events
|
|
if let Some(events) = &abi.events {
|
|
if !events.is_empty() {
|
|
println!("\nEvents:");
|
|
for event in events {
|
|
let params = event
|
|
.params
|
|
.as_ref()
|
|
.map(|params| {
|
|
params
|
|
.iter()
|
|
.map(|p| {
|
|
let indexed = if p.indexed { "indexed " } else { "" };
|
|
format!("{}{}: {}", indexed, p.name, p.type_info.type_name)
|
|
})
|
|
.collect::<Vec<_>>()
|
|
.join(", ")
|
|
})
|
|
.unwrap_or_default();
|
|
|
|
println!(" {}({})", event.name, params);
|
|
println!(" Topic: {}", event.topic);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Encode a function call
|
|
if let Some(functions) = &abi.functions {
|
|
if let Some(func) = functions.first() {
|
|
let encoded = compiler
|
|
.abi
|
|
.encode_call(func, &["arg1".to_string(), "arg2".to_string()])
|
|
.await?;
|
|
println!("\nEncoded call to {}: {}", func.name, encoded);
|
|
|
|
// Decode a result
|
|
let decoded = compiler.abi.decode_result(func, &encoded).await?;
|
|
println!("Decoded result: {:?}", decoded);
|
|
}
|
|
}
|
|
|
|
println!();
|
|
Ok(())
|
|
}
|
|
|
|
async fn analysis_example(compiler: &SynorCompiler) -> Result<(), Box<dyn std::error::Error>> {
|
|
println!("=== Contract Analysis ===");
|
|
|
|
let wasm = create_minimal_wasm();
|
|
|
|
// Full analysis
|
|
let analysis = compiler.analysis.analyze(&wasm).await?;
|
|
|
|
// Size breakdown
|
|
if let Some(breakdown) = &analysis.size_breakdown {
|
|
println!("Size breakdown:");
|
|
println!(" Code: {} bytes", breakdown.code);
|
|
println!(" Data: {} bytes", breakdown.data);
|
|
println!(" Functions: {} bytes", breakdown.functions);
|
|
println!(" Memory: {} bytes", breakdown.memory);
|
|
println!(" Exports: {} bytes", breakdown.exports);
|
|
println!(" Imports: {} bytes", breakdown.imports);
|
|
println!(" Total: {} bytes", breakdown.total);
|
|
}
|
|
|
|
// Function analysis
|
|
if let Some(functions) = &analysis.functions {
|
|
if !functions.is_empty() {
|
|
println!("\nFunction analysis:");
|
|
for func in functions.iter().take(5) {
|
|
println!(" {}:", func.name);
|
|
println!(" Size: {} bytes", func.size);
|
|
println!(" Instructions: {}", func.instruction_count);
|
|
println!(" Locals: {}", func.local_count);
|
|
println!(" Exported: {}", func.exported);
|
|
println!(" Estimated gas: {}", func.estimated_gas);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Import analysis
|
|
if let Some(imports) = &analysis.imports {
|
|
if !imports.is_empty() {
|
|
println!("\nImports:");
|
|
for imp in imports {
|
|
println!(" {}.{} ({})", imp.module, imp.name, imp.kind);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Gas analysis
|
|
if let Some(gas) = &analysis.gas_analysis {
|
|
println!("\nGas analysis:");
|
|
println!(" Deployment: {}", gas.deployment_gas);
|
|
println!(" Memory init: {}", gas.memory_init_gas);
|
|
println!(" Data section: {}", gas.data_section_gas);
|
|
}
|
|
|
|
// Extract metadata
|
|
let metadata = compiler.analysis.extract_metadata(&wasm).await?;
|
|
println!("\nContract metadata:");
|
|
println!(" Name: {}", metadata.name);
|
|
println!(" Version: {}", metadata.version);
|
|
println!(" Build timestamp: {}", metadata.build_timestamp);
|
|
|
|
// Estimate deployment gas
|
|
let gas = compiler.analysis.estimate_deploy_gas(&wasm).await?;
|
|
println!("\nEstimated deployment gas: {}", gas);
|
|
|
|
println!();
|
|
Ok(())
|
|
}
|
|
|
|
async fn validation_example(compiler: &SynorCompiler) -> Result<(), Box<dyn std::error::Error>> {
|
|
println!("=== Contract Validation ===");
|
|
|
|
let wasm = create_minimal_wasm();
|
|
|
|
// Full validation
|
|
let result = compiler.validation.validate(&wasm).await?;
|
|
println!("Valid: {}", result.valid);
|
|
println!("Exports: {}", result.export_count);
|
|
println!("Imports: {}", result.import_count);
|
|
println!("Functions: {}", result.function_count);
|
|
println!("Memory pages: {}", result.memory_pages);
|
|
|
|
if let Some(errors) = &result.errors {
|
|
if !errors.is_empty() {
|
|
println!("\nValidation errors:");
|
|
for error in errors {
|
|
println!(" [{}] {}", error.code, error.message);
|
|
if let Some(location) = &error.location {
|
|
println!(" at {}", location);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if let Some(warnings) = &result.warnings {
|
|
if !warnings.is_empty() {
|
|
println!("\nWarnings:");
|
|
for warning in warnings {
|
|
println!(" {}", warning);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Quick validation
|
|
let is_valid = compiler.validation.is_valid(&wasm).await?;
|
|
println!("\nQuick validation: {}", is_valid);
|
|
|
|
// Get validation errors only
|
|
let errors = compiler.validation.get_errors(&wasm).await?;
|
|
println!("Error count: {}", errors.len());
|
|
|
|
// Validate required exports
|
|
let has_required = compiler
|
|
.validation
|
|
.validate_exports(&wasm, &["init", "execute", "query"])
|
|
.await?;
|
|
println!("Has required exports: {}", has_required);
|
|
|
|
// Validate memory constraints
|
|
let memory_valid = compiler.validation.validate_memory(&wasm, 16).await?;
|
|
println!("Memory within 16 pages: {}", memory_valid);
|
|
|
|
println!();
|
|
Ok(())
|
|
}
|
|
|
|
async fn security_example(compiler: &SynorCompiler) -> Result<(), Box<dyn std::error::Error>> {
|
|
println!("=== Security Scanning ===");
|
|
|
|
let wasm = create_minimal_wasm();
|
|
|
|
let security = compiler.analysis.security_scan(&wasm).await?;
|
|
|
|
println!("Security score: {}/100", security.score);
|
|
|
|
if let Some(issues) = &security.issues {
|
|
if !issues.is_empty() {
|
|
println!("\nSecurity issues:");
|
|
for issue in issues {
|
|
let icon = match issue.severity.as_str() {
|
|
"critical" => "[CRIT]",
|
|
"high" => "[HIGH]",
|
|
"medium" => "[MED]",
|
|
"low" => "[LOW]",
|
|
_ => "[???]",
|
|
};
|
|
println!("{} [{}] {}", icon, issue.severity.to_uppercase(), issue.issue_type);
|
|
println!(" {}", issue.description);
|
|
if let Some(location) = &issue.location {
|
|
println!(" at {}", location);
|
|
}
|
|
}
|
|
} else {
|
|
println!("No security issues found!");
|
|
}
|
|
}
|
|
|
|
if let Some(recommendations) = &security.recommendations {
|
|
if !recommendations.is_empty() {
|
|
println!("\nRecommendations:");
|
|
for rec in recommendations {
|
|
println!(" * {}", rec);
|
|
}
|
|
}
|
|
}
|
|
|
|
println!();
|
|
Ok(())
|
|
}
|