- 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.
354 lines
11 KiB
Python
354 lines
11 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Synor Compiler SDK Examples for Python
|
|
|
|
Demonstrates smart contract compilation and analysis:
|
|
- WASM contract compilation and optimization
|
|
- ABI extraction and encoding
|
|
- Contract analysis and security scanning
|
|
- Validation and verification
|
|
"""
|
|
|
|
import asyncio
|
|
import os
|
|
from synor_compiler import (
|
|
SynorCompiler,
|
|
CompilerConfig,
|
|
OptimizationLevel,
|
|
StripOptions,
|
|
)
|
|
|
|
|
|
async def main():
|
|
"""Main entry point."""
|
|
# Initialize client
|
|
config = CompilerConfig(
|
|
api_key=os.environ.get("SYNOR_API_KEY", "your-api-key"),
|
|
endpoint="https://compiler.synor.io/v1",
|
|
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,
|
|
)
|
|
|
|
compiler = SynorCompiler(config)
|
|
|
|
try:
|
|
# Check service health
|
|
healthy = await compiler.health_check()
|
|
print(f"Service healthy: {healthy}\n")
|
|
|
|
# Example 1: Compile a contract
|
|
await compile_contract_example(compiler)
|
|
|
|
# Example 2: Development vs Production
|
|
await compilation_modes_example(compiler)
|
|
|
|
# Example 3: ABI operations
|
|
await abi_example(compiler)
|
|
|
|
# Example 4: Contract analysis
|
|
await analysis_example(compiler)
|
|
|
|
# Example 5: Validation
|
|
await validation_example(compiler)
|
|
|
|
# Example 6: Security scanning
|
|
await security_example(compiler)
|
|
finally:
|
|
await compiler.close()
|
|
|
|
|
|
def create_minimal_wasm() -> bytes:
|
|
"""Create a minimal valid WASM module for testing."""
|
|
return bytes([
|
|
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 def compile_contract_example(compiler: SynorCompiler):
|
|
"""Basic contract compilation."""
|
|
print("=== Contract Compilation ===")
|
|
|
|
wasm = create_minimal_wasm()
|
|
|
|
result = await compiler.compile(
|
|
wasm,
|
|
optimization_level=OptimizationLevel.SIZE,
|
|
use_wasm_opt=True,
|
|
validate=True,
|
|
extract_metadata=True,
|
|
generate_abi=True,
|
|
strip_options=StripOptions(
|
|
strip_debug=True,
|
|
strip_producers=True,
|
|
strip_names=True,
|
|
strip_custom=True,
|
|
strip_unused=True,
|
|
preserve_sections=[],
|
|
),
|
|
)
|
|
|
|
print("Compilation result:")
|
|
print(f" Contract ID: {result.contract_id}")
|
|
print(f" Code hash: {result.code_hash}")
|
|
print(f" Original size: {result.original_size} bytes")
|
|
print(f" Optimized size: {result.optimized_size} bytes")
|
|
print(f" Size reduction: {result.size_reduction:.1f}%")
|
|
print(f" Estimated deploy gas: {result.estimated_deploy_gas}")
|
|
|
|
if result.metadata:
|
|
print("\nMetadata:")
|
|
print(f" Name: {result.metadata.name}")
|
|
print(f" Version: {result.metadata.version}")
|
|
print(f" SDK Version: {result.metadata.sdk_version}")
|
|
|
|
if result.abi:
|
|
print("\nABI:")
|
|
print(f" Functions: {len(result.abi.functions or [])}")
|
|
print(f" Events: {len(result.abi.events or [])}")
|
|
print(f" Errors: {len(result.abi.errors or [])}")
|
|
|
|
print()
|
|
|
|
|
|
async def compilation_modes_example(compiler: SynorCompiler):
|
|
"""Development vs Production compilation modes."""
|
|
print("=== Compilation Modes ===")
|
|
|
|
wasm = create_minimal_wasm()
|
|
|
|
# Development mode: fast compilation, debugging support
|
|
print("Development mode:")
|
|
dev_result = await compiler.contracts.compile_dev(wasm)
|
|
print(f" Size: {dev_result.optimized_size} bytes")
|
|
print(f" Optimization: none")
|
|
|
|
# Production mode: maximum optimization
|
|
print("\nProduction mode:")
|
|
prod_result = await compiler.contracts.compile_production(wasm)
|
|
print(f" Size: {prod_result.optimized_size} bytes")
|
|
print(f" Optimization: aggressive")
|
|
print(f" Size savings: {dev_result.optimized_size - prod_result.optimized_size} bytes")
|
|
|
|
# Custom optimization levels
|
|
print("\nOptimization levels:")
|
|
levels = [
|
|
OptimizationLevel.NONE,
|
|
OptimizationLevel.BASIC,
|
|
OptimizationLevel.SIZE,
|
|
OptimizationLevel.AGGRESSIVE,
|
|
]
|
|
|
|
for level in levels:
|
|
result = await compiler.compile(wasm, optimization_level=level)
|
|
print(f" {level.value}: {result.optimized_size} bytes")
|
|
|
|
print()
|
|
|
|
|
|
async def abi_example(compiler: SynorCompiler):
|
|
"""ABI extraction and encoding."""
|
|
print("=== ABI Operations ===")
|
|
|
|
wasm = create_minimal_wasm()
|
|
|
|
# Extract ABI from WASM
|
|
abi = await compiler.abi.extract(wasm)
|
|
print(f"Contract: {abi.name}")
|
|
print(f"Version: {abi.version}")
|
|
|
|
# List functions
|
|
if abi.functions:
|
|
print("\nFunctions:")
|
|
for func in abi.functions:
|
|
inputs = ", ".join(
|
|
f"{i.name}: {i.type.type_name}" for i in (func.inputs or [])
|
|
)
|
|
outputs = ", ".join(o.type.type_name for o in (func.outputs or [])) or "void"
|
|
modifiers = " ".join(
|
|
filter(None, ["view" if func.view else "", "payable" if func.payable else ""])
|
|
)
|
|
print(f" {func.name}({inputs}) -> {outputs} {modifiers}")
|
|
print(f" Selector: {func.selector}")
|
|
|
|
# List events
|
|
if abi.events:
|
|
print("\nEvents:")
|
|
for event in abi.events:
|
|
params = ", ".join(
|
|
f"{'indexed ' if p.indexed else ''}{p.name}: {p.type.type_name}"
|
|
for p in (event.params or [])
|
|
)
|
|
print(f" {event.name}({params})")
|
|
print(f" Topic: {event.topic}")
|
|
|
|
# Encode a function call
|
|
if abi.functions:
|
|
func = abi.functions[0]
|
|
encoded = await compiler.abi.encode_call(func, ["arg1", "arg2"])
|
|
print(f"\nEncoded call to {func.name}: {encoded}")
|
|
|
|
# Decode a result
|
|
decoded = await compiler.abi.decode_result(func, encoded)
|
|
print(f"Decoded result: {decoded}")
|
|
|
|
print()
|
|
|
|
|
|
async def analysis_example(compiler: SynorCompiler):
|
|
"""Contract analysis."""
|
|
print("=== Contract Analysis ===")
|
|
|
|
wasm = create_minimal_wasm()
|
|
|
|
# Full analysis
|
|
analysis = await compiler.analysis.analyze(wasm)
|
|
|
|
# Size breakdown
|
|
if analysis.size_breakdown:
|
|
print("Size breakdown:")
|
|
print(f" Code: {analysis.size_breakdown.code} bytes")
|
|
print(f" Data: {analysis.size_breakdown.data} bytes")
|
|
print(f" Functions: {analysis.size_breakdown.functions} bytes")
|
|
print(f" Memory: {analysis.size_breakdown.memory} bytes")
|
|
print(f" Exports: {analysis.size_breakdown.exports} bytes")
|
|
print(f" Imports: {analysis.size_breakdown.imports} bytes")
|
|
print(f" Total: {analysis.size_breakdown.total} bytes")
|
|
|
|
# Function analysis
|
|
if analysis.functions:
|
|
print("\nFunction analysis:")
|
|
for func in analysis.functions[:5]:
|
|
print(f" {func.name}:")
|
|
print(f" Size: {func.size} bytes")
|
|
print(f" Instructions: {func.instruction_count}")
|
|
print(f" Locals: {func.local_count}")
|
|
print(f" Exported: {func.exported}")
|
|
print(f" Estimated gas: {func.estimated_gas}")
|
|
|
|
# Import analysis
|
|
if analysis.imports:
|
|
print("\nImports:")
|
|
for imp in analysis.imports:
|
|
print(f" {imp.module}.{imp.name} ({imp.kind})")
|
|
|
|
# Gas analysis
|
|
if analysis.gas_analysis:
|
|
print("\nGas analysis:")
|
|
print(f" Deployment: {analysis.gas_analysis.deployment_gas}")
|
|
print(f" Memory init: {analysis.gas_analysis.memory_init_gas}")
|
|
print(f" Data section: {analysis.gas_analysis.data_section_gas}")
|
|
|
|
# Extract metadata
|
|
metadata = await compiler.analysis.extract_metadata(wasm)
|
|
print("\nContract metadata:")
|
|
print(f" Name: {metadata.name}")
|
|
print(f" Version: {metadata.version}")
|
|
print(f" Build timestamp: {metadata.build_timestamp}")
|
|
|
|
# Estimate deployment gas
|
|
gas = await compiler.analysis.estimate_deploy_gas(wasm)
|
|
print(f"\nEstimated deployment gas: {gas}")
|
|
|
|
print()
|
|
|
|
|
|
async def validation_example(compiler: SynorCompiler):
|
|
"""Contract validation."""
|
|
print("=== Contract Validation ===")
|
|
|
|
wasm = create_minimal_wasm()
|
|
|
|
# Full validation
|
|
result = await compiler.validation.validate(wasm)
|
|
print(f"Valid: {result.valid}")
|
|
print(f"Exports: {result.export_count}")
|
|
print(f"Imports: {result.import_count}")
|
|
print(f"Functions: {result.function_count}")
|
|
print(f"Memory pages: {result.memory_pages}")
|
|
|
|
if result.errors:
|
|
print("\nValidation errors:")
|
|
for error in result.errors:
|
|
print(f" [{error.code}] {error.message}")
|
|
if error.location:
|
|
print(f" at {error.location}")
|
|
|
|
if result.warnings:
|
|
print("\nWarnings:")
|
|
for warning in result.warnings:
|
|
print(f" {warning}")
|
|
|
|
# Quick validation
|
|
is_valid = await compiler.validation.is_valid(wasm)
|
|
print(f"\nQuick validation: {is_valid}")
|
|
|
|
# Get validation errors only
|
|
errors = await compiler.validation.get_errors(wasm)
|
|
print(f"Error count: {len(errors)}")
|
|
|
|
# Validate required exports
|
|
has_required = await compiler.validation.validate_exports(
|
|
wasm, ["init", "execute", "query"]
|
|
)
|
|
print(f"Has required exports: {has_required}")
|
|
|
|
# Validate memory constraints
|
|
memory_valid = await compiler.validation.validate_memory(wasm, 16)
|
|
print(f"Memory within 16 pages: {memory_valid}")
|
|
|
|
print()
|
|
|
|
|
|
async def security_example(compiler: SynorCompiler):
|
|
"""Security scanning."""
|
|
print("=== Security Scanning ===")
|
|
|
|
wasm = create_minimal_wasm()
|
|
|
|
security = await compiler.analysis.security_scan(wasm)
|
|
|
|
print(f"Security score: {security.score}/100")
|
|
|
|
if security.issues:
|
|
print("\nSecurity issues:")
|
|
severity_icons = {
|
|
"critical": "🔴",
|
|
"high": "🟠",
|
|
"medium": "🟡",
|
|
"low": "🟢",
|
|
}
|
|
for issue in security.issues:
|
|
icon = severity_icons.get(issue.severity, "⚪")
|
|
print(f"{icon} [{issue.severity.upper()}] {issue.type}")
|
|
print(f" {issue.description}")
|
|
if issue.location:
|
|
print(f" at {issue.location}")
|
|
else:
|
|
print("No security issues found!")
|
|
|
|
if security.recommendations:
|
|
print("\nRecommendations:")
|
|
for rec in security.recommendations:
|
|
print(f" • {rec}")
|
|
|
|
print()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|