AI Agent与Web3融合:构建自主链上智能体

引言 AI Agent与Web3的融合代表了两个最前沿技术的交汇点。当AI Agent能够自主地与区块链交互,我们将迎来全新的应用范式。本文将探讨如何构建能够理解、操作和优化链上系统的智能体。 链上AI推理 去中心化AI推理网络 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 from typing import List, Dict import hashlib import json class OnChainInferenceNetwork: """链上AI推理网络""" def __init__(self, blockchain_rpc: str): self.web3 = Web3(Web3.HTTPProvider(blockchain_rpc)) self.private_key = os.getenv("PRIVATE_KEY") self.account = self.web3.eth.account.from_key(self.private_key) # 加载推理合约ABI self.inference_contract = self.web3.eth.contract( address="0x...", # AI推理合约地址 abi=[...] # 合约ABI ) def submit_inference_task( self, model_id: str, input_data: Dict, reward: int ) -> str: """提交推理任务""" # 准备任务数据 task_data = { "modelId": model_id, "input": input_data, "reward": reward, "timeout": 3600, # 1小时超时 "timestamp": int(time.time()) } # 计算任务哈希 task_hash = self._compute_task_hash(task_data) # 提交到链上 tx_hash = self.inference_contract.functions.submitTask( task_hash, json.dumps(input_data), reward, task_data["timeout"] ).transact({'from': self.account.address}) self.web3.eth.wait_for_transaction_receipt(tx_hash) return task_hash def submit_inference_result( self, task_hash: str, output_data: Dict ) -> str: """提交推理结果""" # 准备结果数据 result_hash = self._compute_result_hash({ "taskHash": task_hash, "output": output_data, "submitter": self.account.address }) # 提交结果 tx_hash = self.inference_contract.functions.submitResult( task_hash, json.dumps(output_data), result_hash ).transact({'from': self.account.address}) self.web3.eth.wait_for_transaction_receipt(tx_hash) return tx_hash def claim_reward(self, task_hash: str) -> str: """领取奖励""" # 检查任务是否完成 task = self.inference_contract.functions.tasks(task_hash).call() if not task["completed"]: raise Exception("Task not completed yet") # 领取奖励 tx_hash = self.inference_contract.functions.claimReward( task_hash ).transact({'from': self.account.address}) self.web3.eth.wait_for_transaction_receipt(tx_hash) return tx_hash def verify_result( self, task_hash: str, output_data: Dict ) -> bool: """验证结果""" # 从链上获取任务 task = self.inference_contract.functions.tasks(task_hash).call() # 计算期望的输出哈希 expected_hash = self._compute_output_hash( task["input"], task["modelId"] ) # 验证结果哈希 result_hash = self._compute_result_hash({ "taskHash": task_hash, "output": output_data }) return result_hash == expected_hash def _compute_task_hash(self, task_data: Dict) -> str: """计算任务哈希""" data_string = json.dumps(task_data, sort_keys=True) return hashlib.sha256(data_string.encode()).hexdigest() def _compute_result_hash(self, result_data: Dict) -> str: """计算结果哈希""" data_string = json.dumps(result_data, sort_keys=True) return hashlib.sha256(data_string.encode()).hexdigest() def _compute_output_hash(self, input_data: Dict, model_id: str) -> str: """计算输出哈希(模拟AI推理)""" # 实际应用中,这里应该运行AI模型 # 这里简化处理 output = self._run_model(input_data, model_id) return hashlib.sha256(json.dumps(output).encode()).hexdigest() def _run_model(self, input_data: Dict, model_id: str) -> Dict: """运行AI模型""" # 实际应用中,这里应该调用真实的AI模型 # 可以使用OpenAI API、本地模型等 if model_id == "text-classifier": return self._classify_text(input_data["text"]) elif model_id == "image-analyzer": return self._analyze_image(input_data["imageUrl"]) elif model_id == "sentiment-analyzer": return self._analyze_sentiment(input_data["text"]) else: raise Exception(f"Unknown model: {model_id}") def _classify_text(self, text: str) -> Dict: """文本分类""" # 简化实现,实际应该调用真实模型 categories = { "technology": 0.8, "finance": 0.6, "sports": 0.1 } predicted_category = max(categories, key=categories.get) return { "category": predicted_category, "confidence": categories[predicted_category] } def _analyze_image(self, image_url: str) -> Dict: """图像分析""" return { "objects": ["person", "car", "building"], "scene": "street", "confidence": 0.95 } def _analyze_sentiment(self, text: str) -> Dict: """情感分析""" # 简化实现 positive_words = ["good", "great", "excellent", "happy"] negative_words = ["bad", "terrible", "awful", "sad"] words = text.lower().split() positive_count = sum(1 for word in words if word in positive_words) negative_count = sum(1 for word in words if word in negative_words) if positive_count > negative_count: sentiment = "positive" elif negative_count > positive_count: sentiment = "negative" else: sentiment = "neutral" return { "sentiment": sentiment, "score": (positive_count - negative_count) / len(words) } 智能合约与AI协作 AI辅助的智能合约审计 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 from transformers import AutoTokenizer, AutoModelForCausalLM from typing import List, Dict class AIContractAuditor: """AI智能合约审计助手""" def __init__(self, model_name="microsoft/CodeGPT-small"): self.tokenizer = AutoTokenizer.from_pretrained(model_name) self.model = AutoModelForCausalLM.from_pretrained(model_name) def audit_contract( self, contract_source: str ) -> Dict: """审计智能合约""" # 1. 代码结构分析 structure_analysis = self._analyze_structure(contract_source) # 2. 漏洞检测 vulnerabilities = self._detect_vulnerabilities(contract_source) # 3. 最佳实践检查 best_practices = self._check_best_practices(contract_source) # 4. Gas优化建议 gas_optimization = self._suggest_gas_optimization(contract_source) # 5. 生成审计报告 report = self._generate_report({ "structure": structure_analysis, "vulnerabilities": vulnerabilities, "best_practices": best_practices, "gas_optimization": gas_optimization }) return report def _analyze_structure(self, source: str) -> Dict: """分析合约结构""" prompt = f""" Analyze the following smart contract code structure: {source} Provide: 1. Contract architecture 2. Key functions and their roles 3. State variables and their purposes 4. Access control mechanisms 5. External dependencies """ response = self._generate(prompt) return { "architecture": self._parse_response(response, "architecture"), "functions": self._parse_response(response, "functions"), "state_variables": self._parse_response(response, "state_variables"), "access_control": self._parse_response(response, "access_control"), "dependencies": self._parse_response(response, "dependencies") } def _detect_vulnerabilities(self, source: str) -> List[Dict]: """检测漏洞""" known_vulnerabilities = { "reentrancy": { "patterns": [ r"\.call\{.*value:\s*msg\.value", r"\.send\{.*value:\s*msg\.value" ], "severity": "critical", "description": "Reentrancy vulnerability detected" }, "overflow": { "patterns": [ r"uint256.*=.*\+.*(?!\.add\()", r"uint256.*=.*-.*(?!\.sub\()" ], "severity": "high", "description": "Potential integer overflow/underflow" }, "access_control": { "patterns": [ r"function\s+\w+\s*\(\s*\)\s*public(?!\s*onlyOwner|onlyRole)", r"tx\.origin" ], "severity": "high", "description": "Weak access control" }, "unchecked_call": { "patterns": [ r"\.call\s*\(", r"\.send\s*\(" ], "severity": "medium", "description": "Unchecked external call" } } detected = [] for vuln_type, vuln_info in known_vulnerabilities.items(): for pattern in vuln_info["patterns"]: matches = re.finditer(pattern, source) for match in matches: detected.append({ "type": vuln_type, "severity": vuln_info["severity"], "description": vuln_info["description"], "location": match.span(), "code_snippet": source[match.start()-20:match.end()+20] }) return detected def _check_best_practices(self, source: str) -> List[Dict]: """检查最佳实践""" checks = { "uses_safe_math": r"SafeMath|\.add\(|\.sub\(" in source, "has_reentrancy_guard": r"ReentrancyGuard|nonReentrant" in source, "uses_openzeppelin": r"@openzeppelin" in source, "has_events": r"event\s+\w+" in source, "uses_checks_effects_interactions": r"Checks-Effects-Interactions" in source, "has_pause": r"whenNotPaused|Pausable" in source, "has_timelock": r"TimelockController|releaseTimeLock" in source } results = [] for check_name, check_result in checks.items(): results.append({ "check": check_name, "passed": check_result, "description": self._get_check_description(check_name) }) return results def _suggest_gas_optimization(self, source: str) -> List[str]: """建议Gas优化""" optimizations = [] # 检查循环 if "for (" in source: optimizations.append("Consider using unchecked blocks for loop iterations") # 检查storage操作 if re.search(r"uint256\s+public\s+\w+", source): optimizations.append("Consider packing struct variables to save storage") # 检查重复计算 if re.search(r"keccak256\(", source): optimizations.append("Cache keccak256 results in local variables") # 检查memory vs storage if re.search(r".*\.\w+\s*=\s*\w+\[.*\]\s*\+\s*1", source): optimizations.append("Consider using calldata instead of memory for arrays") return optimizations def _generate_report(self, audit_data: Dict) -> Dict: """生成审计报告""" # 计算风险评分 risk_score = self._calculate_risk_score(audit_data) # 生成总结 summary = self._generate_summary(audit_data, risk_score) # 生成修复建议 recommendations = self._generate_recommendations(audit_data) return { "risk_score": risk_score, "summary": summary, "vulnerabilities": audit_data["vulnerabilities"], "best_practices": audit_data["best_practices"], "optimizations": audit_data["gas_optimization"], "recommendations": recommendations } def _calculate_risk_score(self, audit_data: Dict) -> int: """计算风险评分(0-100)""" score = 100 for vuln in audit_data["vulnerabilities"]: if vuln["severity"] == "critical": score -= 30 elif vuln["severity"] == "high": score -= 15 elif vuln["severity"] == "medium": score -= 5 elif vuln["severity"] == "low": score -= 2 return max(score, 0) def _generate_summary(self, audit_data: Dict, risk_score: int) -> str: """生成审计总结""" vuln_count = len(audit_data["vulnerabilities"]) critical_count = sum(1 for v in audit_data["vulnerabilities"] if v["severity"] == "critical") summary = f""" Smart Contract Audit Summary ========================== Risk Score: {risk_score}/100 Total Vulnerabilities: {vuln_count} Critical Issues: {critical_count} """ if risk_score >= 80: summary += "Overall Assessment: LOW RISK" elif risk_score >= 50: summary += "Overall Assessment: MEDIUM RISK" else: summary += "Overall Assessment: HIGH RISK" return summary def _generate_recommendations(self, audit_data: Dict) -> List[str]: """生成修复建议""" recommendations = [] for vuln in audit_data["vulnerabilities"]: if vuln["type"] == "reentrancy": recommendations.append( "Use ReentrancyGuard or implement Checks-Effects-Interactions pattern" ) elif vuln["type"] == "overflow": recommendations.append( "Use Solidity 0.8.0+ or SafeMath library for arithmetic operations" ) elif vuln["type"] == "access_control": recommendations.append( "Implement proper access control using onlyOwner or role-based access" ) return recommendations def _generate(self, prompt: str) -> str: """生成文本""" inputs = self.tokenizer(prompt, return_tensors="pt") with torch.no_grad(): outputs = self.model.generate( **inputs, max_new_tokens=500, temperature=0.3, do_sample=True ) response = self.tokenizer.decode(outputs[0], skip_special_tokens=True) return response 自主交易Agent DeFi交易Agent 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 from typing import List, Dict, Optional from datetime import datetime import ccxt import pandas as pd import numpy as np class DeFiTradingAgent: """DeFi交易Agent""" def __init__( self, initial_capital: float, exchanges: List[str], llm_model: str = "gpt-4" ): self.capital = initial_capital self.portfolio = {} # {token: amount} self.exchanges = {} self.trade_history = [] # 初始化交易所连接 for exchange_name in exchanges: if exchange_name == "uniswap": exchange = ccxt.uniswap({ "enableRateLimit": True }) elif exchange_name == "pancakeswap": exchange = ccxt.pancakeswap({ "enableRateLimit": True }) else: exchange = ccxt.binance({ "enableRateLimit": True }) self.exchanges[exchange_name] = exchange # 初始化LLM self.llm = self._init_llm(llm_model) def _init_llm(self, model_name: str): """初始化LLM""" # 实际应用中,这里应该连接到真实的LLM API # 或运行本地模型 from transformers import AutoTokenizer, AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained(model_name) tokenizer = AutoTokenizer.from_pretrained(model_name) return { "model": model, "tokenizer": tokenizer } def analyze_market( self, tokens: List[str], timeframe: str = "1h" ) -> Dict: """分析市场""" # 获取市场数据 market_data = self._fetch_market_data(tokens, timeframe) # 技术分析 ta_analysis = self._technical_analysis(market_data) # 使用LLM生成市场洞察 market_insight = self._generate_market_insight( market_data, ta_analysis ) return { "market_data": market_data, "technical_analysis": ta_analysis, "insight": market_insight } def _fetch_market_data( self, tokens: List[str], timeframe: str ) -> Dict: """获取市场数据""" data = {} for token in tokens: # 从各个交易所获取数据 for exchange_name, exchange in self.exchanges.items(): try: ohlcv = exchange.fetch_ohlcv( f"{token}/USDT", timeframe, limit=100 ) if token not in data: data[token] = [] # 转换为DataFrame df = pd.DataFrame( ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'] ) df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms') data[token].append(df) break # 使用第一个成功的数据源 except Exception as e: print(f"Error fetching data for {token}: {e}") return data def _technical_analysis(self, market_data: Dict) -> Dict: """技术分析""" analysis = {} for token, dfs in market_data.items(): if not dfs: continue df = dfs[0] # 使用第一个数据源 # 计算技术指标 df['sma_20'] = df['close'].rolling(window=20).mean() df['sma_50'] = df['close'].rolling(window=50).mean() df['rsi'] = self._calculate_rsi(df['close'], 14) df['macd'] = self._calculate_macd(df['close']) # 趋势分析 latest_close = df['close'].iloc[-1] sma_20 = df['sma_20'].iloc[-1] sma_50 = df['sma_50'].iloc[-1] trend = "bullish" if latest_close > sma_20 > sma_50 else "bearish" analysis[token] = { "current_price": latest_close, "sma_20": sma_20, "sma_50": sma_50, "rsi": df['rsi'].iloc[-1], "trend": trend, "support_levels": self._find_support_levels(df), "resistance_levels": self._find_resistance_levels(df) } return analysis def _calculate_rsi(self, prices: pd.Series, period: int = 14) -> pd.Series: """计算RSI""" delta = prices.diff() gain = (delta.where(delta > 0, 0)).rolling(window=period).mean() loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean() rs = gain / loss rsi = 100 - (100 / (1 + rs)) return rsi def _calculate_macd(self, prices: pd.Series) -> Dict: """计算MACD""" exp1 = prices.ewm(span=12, adjust=False).mean() exp2 = prices.ewm(span=26, adjust=False).mean() macd = exp1 - exp2 signal = macd.ewm(span=9, adjust=False).mean() histogram = macd - signal return { "macd": macd.iloc[-1], "signal": signal.iloc[-1], "histogram": histogram.iloc[-1] } def _find_support_levels(self, df: pd.DataFrame) -> List[float]: """寻找支撑位""" # 简化实现:使用局部最小值 from scipy.signal import argrelextrema prices = df['close'].values local_min = argrelextrema(prices, np.less, order=20) support_levels = sorted(prices[local_min]) return support_levels[-5:] # 返回最近的5个支撑位 def _find_resistance_levels(self, df: pd.DataFrame) -> List[float]: """寻找阻力位""" from scipy.signal import argrelextrema prices = df['close'].values local_max = argrelextrema(prices, np.greater, order=20) resistance_levels = sorted(prices[local_max], reverse=True) return resistance_levels[-5:] # 返回最近的5个阻力位 def _generate_market_insight( self, market_data: Dict, ta_analysis: Dict ) -> str: """生成市场洞察""" # 准备prompt prompt = f""" Analyze the following cryptocurrency market data and provide trading insights: Technical Analysis: {json.dumps(ta_analysis, indent=2)} Based on this analysis, provide: 1. Market trend analysis 2. Key support and resistance levels 3. Trading recommendations 4. Risk factors to consider 5. Optimal entry and exit points Be specific and actionable. """ # 调用LLM response = self._generate(prompt) return response def execute_trade( self, exchange: str, symbol: str, side: str, amount: float, price: Optional[float] = None ) -> Dict: """执行交易""" exchange_obj = self.exchanges[exchange] try: if side == "buy": # 限价买单 if price: order = exchange_obj.create_limit_buy_order( symbol, amount, price ) else: # 市价买单 order = exchange_obj.create_market_buy_order( symbol, amount ) else: # 卖单 if price: order = exchange_obj.create_limit_sell_order( symbol, amount, price ) else: order = exchange_obj.create_market_sell_order( symbol, amount ) # 记录交易 trade_record = { "exchange": exchange, "symbol": symbol, "side": side, "amount": amount, "price": price, "timestamp": datetime.now().isoformat(), "status": "executed" } self.trade_history.append(trade_record) return trade_record except Exception as e: print(f"Trade execution failed: {e}") return { "status": "failed", "error": str(e) } def run_strategy( self, strategy_config: Dict ) -> List[Dict]: """运行交易策略""" # 1. 分析市场 market_analysis = self.analyze_market( strategy_config["tokens"], strategy_config.get("timeframe", "1h") ) # 2. 生成交易信号 signals = self._generate_trading_signals( market_analysis, strategy_config ) # 3. 执行交易 executed_trades = [] for signal in signals: if signal["action"] == "hold": continue trade = self.execute_trade( exchange=signal["exchange"], symbol=signal["symbol"], side=signal["side"], amount=signal["amount"], price=signal.get("price") ) if trade.get("status") == "executed": executed_trades.append(trade) return executed_trades def _generate_trading_signals( self, market_analysis: Dict, strategy_config: Dict ) -> List[Dict]: """生成交易信号""" signals = [] ta_analysis = market_analysis["technical_analysis"] for token, analysis in ta_analysis.items(): # 简单的移动平均策略 if (analysis["trend"] == "bullish" and analysis["rsi"] < 70 and analysis["current_price"] > analysis["sma_20"]): signals.append({ "action": "buy", "exchange": "uniswap", "symbol": f"{token}/USDT", "side": "buy", "amount": strategy_config.get("trade_size", 100), "reason": "Bullish trend with RSI below overbought" }) elif (analysis["trend"] == "bearish" and analysis["rsi"] > 30): signals.append({ "action": "sell", "exchange": "uniswap", "symbol": f"{token}/USDT", "side": "sell", "amount": strategy_config.get("trade_size", 100), "reason": "Bearish trend detected" }) return signals DAO治理Agent 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 from typing import List, Dict, Optional class DAOGovernanceAgent: """DAO治理Agent""" def __init__( self, dao_address: str, llm_model: str = "gpt-4" ): self.dao_address = dao_address self.llm = self._init_llm(llm_model) # 治理历史 self.governance_history = [] # 提案分析 self.proposals_db = {} def analyze_proposal( self, proposal_data: Dict ) -> Dict: """分析提案""" # 1. 提取关键信息 key_info = self._extract_proposal_info(proposal_data) # 2. 风险评估 risk_assessment = self._assess_risk(proposal_data) # 3. 财务影响分析 financial_impact = self._analyze_financial_impact(proposal_data) # 4. 生成投票建议 voting_recommendation = self._generate_voting_recommendation({ "key_info": key_info, "risk_assessment": risk_assessment, "financial_impact": financial_impact }) return { "proposal_id": proposal_data["id"], "key_info": key_info, "risk_assessment": risk_assessment, "financial_impact": financial_impact, "recommendation": voting_recommendation } def _extract_proposal_info(self, proposal: Dict) -> Dict: """提取提案关键信息""" prompt = f""" Extract key information from this DAO proposal: Title: {proposal.get('title', '')} Description: {proposal.get('description', '')} Please extract: 1. Proposal type (e.g., parameter change, spending, governance change) 2. Key changes proposed 3. Affected stakeholders 4. Implementation timeline 5. Required resources """ response = self._generate(prompt) # 解析LLM响应 key_info = { "type": self._parse_field(response, "Proposal type"), "changes": self._parse_field(response, "Key changes"), "stakeholders": self._parse_field(response, "Stakeholders"), "timeline": self._parse_field(response, "Timeline"), "resources": self._parse_field(response, "Resources") } return key_info def _assess_risk(self, proposal: Dict) -> Dict: """评估风险""" risk_factors = [] # 检查提案类型 proposal_type = self._extract_proposal_type(proposal) if proposal_type == "spending": # 检查金额 amount = self._extract_amount(proposal) if amount > 1000000: risk_factors.append({ "type": "financial", "severity": "high", "description": "Large expenditure proposed" }) elif proposal_type == "parameter_change": # 检查参数范围 params = self._extract_parameters(proposal) if self._is_risk_parameter_change(params): risk_factors.append({ "type": "governance", "severity": "medium", "description": "Parameter changes may affect protocol stability" }) return { "risk_score": self._calculate_risk_score(risk_factors), "risk_factors": risk_factors, "mitigation_strategies": self._suggest_mitigation(risk_factors) } def _generate_voting_recommendation(self, analysis: Dict) -> Dict: """生成投票建议""" prompt = f""" Based on the following DAO proposal analysis: Key Information: {json.dumps(analysis['key_info'], indent=2)} Risk Assessment: {json.dumps(analysis['risk_assessment'], indent=2)} Financial Impact: {json.dumps(analysis['financial_impact'], indent=2)} Provide a voting recommendation: 1. Vote: For/Against/Abstain 2. Confidence: High/Medium/Low 3. Reasoning: Detailed explanation 4. Conditions: Any conditions for changing the vote Consider: - Long-term sustainability - Community impact - Financial health - Innovation vs stability """ response = self._generate(prompt) # 解析建议 recommendation = { "vote": self._parse_field(response, "Vote"), "confidence": self._parse_field(response, "Confidence"), "reasoning": self._parse_field(response, "Reasoning"), "conditions": self._parse_field(response, "Conditions") } return recommendation def automate_governance(self) -> None: """自动化治理决策""" # 获取待处理提案 pending_proposals = self._fetch_pending_proposals() for proposal in pending_proposals: # 分析提案 analysis = self.analyze_proposal(proposal) # 根据建议自动投票 if analysis["recommendation"]["vote"].lower() == "for": self._cast_vote( proposal["id"], "for", analysis["recommendation"]["reasoning"] ) def _fetch_pending_proposals(self) -> List[Dict]: """获取待处理提案""" # 实际应用中,这里应该从链上或DAO的API获取 # 简化实现 proposals = [] # 示例提案 proposals.append({ "id": "proposal-123", "title": "Grant Program Funding", "description": "Allocate $500,000 for grants", "status": "pending", "voting_deadline": datetime.now() + timedelta(days=7) }) return proposals def _cast_vote(self, proposal_id: str, vote: str, reason: str) -> str: """投票""" # 实际应用中,这里应该调用链上治理合约 print(f"Voting {vote} on proposal {proposal_id}") print(f"Reason: {reason}") return f"voted-{vote}-{proposal_id}" 总结 AI Agent与Web3的融合将开启全新的应用范式: ...

区块链跨链技术深度解析:从原子交换到轻客户端验证

引言 跨链技术是WEB3生态实现互操作性的关键。随着多条公链并存,资产和数据的跨链转移变得日益重要。本文将深入探讨从原子交换到轻客户端验证的各种跨链技术原理和实现。 跨链基础 为什么需要跨链 多链生态的现实: ├── Ethereum: DeFi、NFT主要生态 ├── Solana: 高性能应用 ├── Polygon: 低成本交易 ├── BSC: 中心化交易所公链 └── Cosmos/Polkadot: 跨链生态 问题: - 资产孤立:各链资产无法互通 - 流动性分散:DeFi流动性被分割 - 用户体验差:需要跨链桥,步骤繁琐 - 安全风险:中心化桥是黑客主要目标 跨链方案分类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 interface CrossChainSolutions { centralized: { name: "中心化跨链桥", examples: ["Binance Bridge", "Core DAO Bridge"], pros: ["速度快", "用户体验好"], cons: ["需要信任", "单点故障风险"] }, liquidity: { name: "流动性跨链桥", examples: ["Hop Protocol", "Across"], pros: ["去中心化", "速度快"], cons: ["依赖流动性提供者", "资金效率低"] }, lightClient: { name: "轻客户端验证", examples: ["IBC (Cosmos)", "XCM (Polkadot)"], pros: ["安全性高", "真正的去中心化"], cons: ["实现复杂", "跨链速度慢"] }, atomic: { name: "原子交换", examples: ["THORChain", "LIOS"], pros: ["无需信任", "点对点"], cons: ["只支持资产交换", "限制多"] } } 哈希时间锁定合约(HTLC) HTLC原理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract HTLC { struct Swap { address payable sender; address payable receiver; uint256 amount; bytes32 hashLock; // 哈希锁 uint256 timeLock; // 时间锁 bytes32 preimage; // 原像(秘密) bool claimed; // 是否已提取 bool refunded; // 是否已退款 } mapping(bytes32 => Swap) public swaps; event SwapCreated( bytes32 indexed swapId, address indexed sender, address indexed receiver, uint256 amount, bytes32 hashLock, uint256 timeLock ); event SwapClaimed(bytes32 indexed swapId, bytes32 preimage); event SwapRefunded(bytes32 indexed swapId); // 创建HTLC function createSwap( address payable _receiver, bytes32 _hashLock, uint256 _timeLock ) external payable returns (bytes32) { require(msg.value > 0, "Amount must be greater than 0"); require(_timeLock > block.timestamp, "Time lock must be in future"); bytes32 swapId = keccak256( abi.encodePacked( msg.sender, _receiver, msg.value, _hashLock, _timeLock, block.number ) ); swaps[swapId] = Swap({ sender: payable(msg.sender), receiver: payable(_receiver), amount: msg.value, hashLock: _hashLock, timeLock: _timeLock, preimage: bytes32(0), claimed: false, refunded: false }); emit SwapCreated( swapId, msg.sender, _receiver, msg.value, _hashLock, _timeLock ); return swapId; } // 提取资金(需要知道preimage) function claimSwap(bytes32 _swapId, bytes32 _preimage) external { Swap storage swap = swaps[_swapId]; require(swap.amount > 0, "Swap does not exist"); require(!swap.claimed, "Already claimed"); require(!swap.refunded, "Already refunded"); require(swap.receiver == msg.sender, "Not the receiver"); // 验证preimage require( keccak256(abi.encodePacked(_preimage)) == swap.hashLock, "Invalid preimage" ); swap.preimage = _preimage; swap.claimed = true; emit SwapClaimed(_swapId, _preimage); // 转移资金 swap.receiver.transfer(swap.amount); } // 退款(时间锁过期后) function refundSwap(bytes32 _swapId) external { Swap storage swap = swaps[_swapId]; require(swap.amount > 0, "Swap does not exist"); require(!swap.claimed, "Already claimed"); require(!swap.refunded, "Already refunded"); require(swap.sender == msg.sender, "Not the sender"); require(block.timestamp >= swap.timeLock, "Time lock not expired"); swap.refunded = true; emit SwapRefunded(_swapId); // 退还资金 swap.sender.transfer(swap.amount); } } // 使用示例 // Alice想和Bob跨链交换1 ETH换100 USDT // 1. Alice生成随机数secret,计算hashLock = keccak256(secret) // 2. Alice在以太坊上创建HTLC,发送1 ETH,设置hashLock和时间锁 // 3. Bob在BSC上创建HTLC,发送100 USDT,使用相同的hashLock和时间锁 // 4. Bob在以太坊上调用claimSwap,提供secret,获得1 ETH // 5. Alice从Bob的交易中获得secret // 6. Alice在BSC上调用claimSwap,提供secret,获得100 USDT 跨链原子交换流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 interface AtomicSwapFlow { step1: "Alice生成随机数secret", step2: "Alice计算hashLock = H(secret)", step3: "Alice在Chain A创建HTLC(hashLock, 时间锁24小时)", step4: "Bob在Chain B创建HTLC(hashLock, 时间锁23小时)", step5: "Bob在Chain A调用claim(secret)提取资金", step6: "Alice从Chain A的交易中读取secret", step7: "Alice在Chain B调用claim(secret)提取资金", timeout: "如果24小时内Bob未提取,Alice可以退款" } // 实现原子交换 class AtomicSwap { async initiateSwap( fromChain: string, toChain: string, fromToken: string, toToken: string, amount: bigint, counterparty: string ): Promise<string> { // 1. 生成secret const secret = this.generateSecret() const hashLock = this.hashFunction(secret) // 2. 在源链创建HTLC const swapId = await this.createHTLC( fromChain, amount, hashLock, 24 * 60 * 60 // 24小时时间锁 ) // 3. 发送hashLock给对方 await this.notifyCounterparty(counterparty, { swapId, hashLock, toChain, toToken, amount }) return swapId } async participateSwap( hashLock: string, toChain: string, toToken: string, amount: bigint ): Promise<string> { // 在目标链创建HTLC // 使用稍短的时间锁(23小时) const swapId = await this.createHTLC( toChain, amount, hashLock, 23 * 60 * 60 ) return swapId } async claimSwap( chain: string, swapId: string, secret: string ): Promise<void> { // 调用claim合约方法 const tx = await this.executeContract( chain, swapId, 'claimSwap', [secret] ) await tx.wait() } } 轻客户端验证 SPV (Simple Payment Verification) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 // SPV证明 interface MerkleProof { txId: string blockHash: string merkleProof: string[] blockHeader: BlockHeader } class SPVVerifier { /** * 验证交易是否在区块中 */ verifyTransaction(proof: MerkleProof): boolean { // 1. 验证区块头工作量证明 const isValidPOW = this.verifyProofOfWork(proof.blockHeader) if (!isValidPOW) return false // 2. 计算Merkle根 const calculatedRoot = this.calculateMerkleRoot( proof.txId, proof.merkleProof ) // 3. 比较Merkle根 return calculatedRoot === proof.blockHeader.merkleRoot } /** * 计算Merkle根 */ private calculateMerkleRoot( txId: string, proof: string[] ): string { let hash = txId for (const sibling of proof) { // 根据位置确定hash顺序 if (this.isLeftChild(hash)) { hash = this.hashPair(hash, sibling) } else { hash = this.hashPair(sibling, hash) } } return hash } /** * 验证工作量证明 */ private verifyProofOfWork(header: BlockHeader): boolean { const target = this.calculateTarget(header.bits) const headerHash = this.hashHeader(header) return BigInt('0x' + headerHash) < target } /** * 双SHA256哈希 */ private sha256(data: string): string { return crypto.createHash('sha256') .update(data) .digest('hex') } private hashPair(a: string, b: string): string { return this.sha256(this.sha256(a + b)) } } 轻客户端实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 import { ethers } from 'ethers' class LightClient { private headers: Map<number, BlockHeader> = new Map() private currentHeight: number = 0 /** * 添加新的区块头 */ async addHeader(header: BlockHeader): Promise<boolean> { // 验证区块头 if (!this.verifyHeader(header)) { throw new Error('Invalid block header') } // 如果是第一个区块头 if (this.headers.size === 0) { this.headers.set(header.number, header) this.currentHeight = header.number return true } // 验证区块连接 const parentHeader = this.headers.get(header.number - 1) if (parentHeader && header.parentHash !== parentHeader.hash) { throw new Error('Block does not connect to known chain') } // 存储区块头 this.headers.set(header.number, header) this.currentHeight = Math.max(this.currentHeight, header.number) // 限制存储大小 if (this.headers.size > 1000) { const oldest = Math.min(...this.headers.keys()) this.headers.delete(oldest) } return true } /** * 验证默克尔证明 */ verifyMerkleProof( blockNumber: number, txHash: string, proof: MerkleProof ): boolean { const header = this.headers.get(blockNumber) if (!header) { throw new Error('Unknown block') } // 计算根哈希 let hash = txHash for (const sibling of proof.siblings) { if (proof.path % 2 === 0) { hash = ethers.utils.keccak256( ethers.utils.concat([hash, sibling]) ) } else { hash = ethers.utils.keccak256( ethers.utils.concat([sibling, hash]) ) ) proof.path = Math.floor(proof.path / 2) } // 验证根哈希匹配 return hash === header.transactionsRoot } } Cosmos IBC协议 IBC架构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 // IBC核心组件 package ibc // Channel握手状态 type ChannelState string const ( INIT ChannelState = "INIT" TRYOPEN ChannelState = "TRYOPEN" OPEN ChannelState = "OPEN" CLOSED ChannelState = "CLOSED" ) // Channel结构 type Channel struct { State ChannelState Ordering Order Counterparty Counterparty ConnectionHops []string Version string } // IBC消息 type Message interface { Type() string ValidateBasic() error } // ChannelOpenInit消息 type MsgChannelOpenInit struct { PortId string ChannelId string Ordering Order Counterparty Counterparty Version string Signer string } func (msg MsgChannelOpenInit) ValidateBasic() error { if msg.PortId == "" { return fmt.Errorf("port ID cannot be empty") } if msg.ChannelId != "" { return fmt.Errorf("channel ID must be empty for Init") } return nil } // Packet数据结构 type Packet struct { Data []byte TimeoutHeight uint64 TimeoutTimestamp uint64 Sequence uint64 SourcePort string SourceChannel string DestPort string DestChannel string } // IBC Handler type IBCModule interface { OnChanOpenInit( ctx sdk.Context, order ChannelOrder, connectionHops []string, portId string, channelId string, counterparty Counterparty, version string, ) (string, error) OnChanOpenTry( ctx sdk.Context, order ChannelOrder, connectionHops []string, portId string, channelId string, counterparty Counterparty, counterpartyVersion string, ) error OnChanOpenAck( ctx sdk.Context, portId string, channelId string, counterpartyChannelId string, counterpartyVersion string, ) error OnChanOpenConfirm( ctx sdk.Context, portId string, channelId string, ) error OnRecvPacket( ctx sdk.Context, packet Packet, relayer sdk.AccAddress, ) exported.Acknowledgement OnAcknowledgePacket( ctx sdk.Context, packet Packet, acknowledgement []byte, relayer sdk.AccAddress, ) error OnTimeoutPacket( ctx sdk.Context, packet Packet, relayer sdk.AccAddress, ) error } IBC跨链转账 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 // ICS-20: 跨链代币转账标准 package ics20 type TransferData struct { Sender string Receiver string Amount sdk.Int Denom string Memo string } type MsgTransfer struct { SourcePort string SourceChannel string Token sdk.Coin Sender string Receiver string TimeoutHeight uint64 TimeoutTimestamp uint64 Memo string } func (msg MsgTransfer) ValidateBasic() error { if msg.Token.Amount.IsZero() || msg.Token.Amount.IsNegative() { return fmt.Errorf("amount must be positive") } if msg.Sender == "" || msg.Receiver == "" { return fmt.Errorf("sender and receiver cannot be empty") } return nil } // 转账逻辑 func (k Keeper) Transfer( ctx sdk.Context, msg MsgTransfer, ) error { // 1. 锁定或销毁代币 sender, err := sdk.AccAddressFromBech32(msg.Sender) if err != nil { return err } if err := k.SendCoins(ctx, sender, msg.Token); err != nil { return err } // 2. 创建IBC Packet packet := channeltypes.Packet{ Data: modulecdc.MustMarshalJSON(&TransferData{ Sender: msg.Sender, Receiver: msg.Receiver, Amount: msg.Token.Amount, Denom: msg.Token.Denom, Memo: msg.Memo, }), TimeoutHeight: clienttypes.Height{ RevisionNumber: 0, RevisionHeight: msg.TimeoutHeight, }, TimeoutTimestamp: msg.TimeoutTimestamp, } // 3. 发送Packet _, err = k.channelKeeper.SendPacket(ctx, packet) if err != nil { return err } return nil } // 接收跨链代币 func (k Keeper) OnRecvPacket( ctx sdk.Context, packet channeltypes.Packet, ) exported.Acknowledgement { var data TransferData if err := modulecdc.UnmarshalJSON(packet.Data, &data); err != nil { return channeltypes.NewErrorAcknowledgement(err) } // 铸造代币给接收者 receiver, err := sdk.AccAddressFromBech32(data.Receiver) if err != nil { return channeltypes.NewErrorAcknowledgement(err) } coins := sdk.NewCoins(sdk.NewCoin(data.Denom, data.Amount)) if err := k.bankKeeper.MintCoins(ctx, coins); err != nil { return channeltypes.NewErrorAcknowledgement(err) } if err := k.bankKeeper.SendCoins(ctx, k.GetAccount(ctx), receiver, coins); err != nil { return channeltypes.NewErrorAcknowledgement(err) } return channeltypes.NewResultAcknowledgement([]byte{byte(1)}) } Polkadot XCM XCM消息格式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 // XCM (Cross-Consensus Message) 类型定义 use xcm::v3::{ Xcm, Junction, Junctions::X1, MultiAsset, MultiLocation, Instruction, WeightLimit, }; // 构建跨链转账XCM fn create_transfer_xcm( dest: MultiLocation, amount: u128, ) -> Xcm<()> { Xcm(vec![ // 1. 提取资产 WithdrawAsset(MultiAsset::from((dest, amount))), // 2. 初始化资产 InitiateReserveWithdraw( X1([Parachain(2000)]), // 中继链 MultiAsset::from((dest, amount)), ), // 3. 跨链传输 TransferReserveAsset( X1([Parachain(2000)]), X1([AccountId32 { network: None, id: [/* 目标账户 */], }]), MultiAsset::from((dest, amount)), ), ]) } // XCM执行器 pub struct XcmExecutor; impl XcmExecutor { pub fn execute_xcm( origin: MultiLocation, xcm: Xcm<()>, ) -> Result<XcmOutcome, XcmError> { match xcm { Xcm::TransferReserveAsset { assets, dest, xcm, } => { // 处理资产转移 Self::handle_reserve_transfer(assets, dest, xcm) } Xcm::Transact { origin_kind, require_weight_at_most, call, } => { // 处理跨链调用 Self::handle_transact(origin_kind, require_weight_at_most, call) } _ => Ok(XcmOutcome::Complete) } } } 跨链智能合约调用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 use xcm::v3::{Instruction, WeightLimit}; // 构建跨链合约调用XCM fn create_cross_chain_call( target_chain: u32, contract_address: [u8; 32], call_data: Vec<u8>, ) -> Xcm<()> { Xcm(vec![ // 设置权重限制 SetAppendix(Xcm(vec![ SetTopic([0u8; 32]), ])), // 执行远程调用 Transact { origin_kind: OriginKind::SovereignAccount, require_weight_at_most: WeightLimit::Limited(3_000_000_000), call: { let encoded_call = Encode::encode(&Call::EVM(evm::Call::call( contract_address.into(), call_data, ))); // 编码为XCM格式 (/* 调用编码 */) }, }, ]) } 跨链桥安全 常见攻击向量 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 interface CrossChainAttackVectors { fakeDeposits: { name: "虚假存款攻击", description: "攻击者在源链存款后,在目标链欺骗性地铸造包装代币", mitigation: "使用轻客户端验证,等待足够的确认数" }, dataAvailability: { name: "数据可用性攻击", description: "中继器提交虚假或无效的数据", mitigation: "多个独立中继器,欺诈证明机制" }, doubleSpend: { name: "双花攻击", description: "利用跨链延迟在多条链上花费同一笔资产", mitigation: "适当的锁定期和确认数" }, bridgeCompromise: { name: "桥合约被攻破", description: "智能合约漏洞导致资产被盗", mitigation: "多重签名、时间锁、渐进式去中心化" } } 安全跨链桥实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "@openzeppelin/contracts/access/AccessControl.sol"; contract SecureBridge is ReentrancyGuard, Pausable, AccessControl { bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE"); bytes32 public constant RELAYER_ROLE = keccak256("RELAYER_ROLE"); // 映射:源链交易哈希 -> 是否已处理 mapping(bytes32 => bool) public processedTransactions; // 桥接配置 uint256 public minConfirmations = 6; uint256 public maxDailyTransfer = 1000000 * 1e18; uint256 public dailyTransferLimit = 100000 * 1e18; mapping(address => uint256) public userDailyTransfer; mapping(uint256 => uint256) public dailyTotalTransfer; event Deposit( address indexed user, uint256 amount, bytes32 indexed destTxHash ); event Withdraw( address indexed user, uint256 amount, bytes32 indexed srcTxHash ); modifier onlyRelayer() { require( hasRole(RELAYER_ROLE, msg.sender), "Not a relayer" ); _; } constructor() { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(GUARDIAN_ROLE, msg.sender); } // 存款(源链) function deposit( bytes32 destTxHash, address recipient, uint256 amount ) external whenNotPaused nonReentrant { require(amount > 0, "Amount must be greater than 0"); // 检查每日限额 uint256 currentDay = block.timestamp / 1 days; uint256 userDaily = userDailyTransfer[recipient]; uint256 dailyTotal = dailyTotalTransfer[currentDay]; require( userDaily + amount <= dailyTransferLimit, "User daily limit exceeded" ); require( dailyTotal + amount <= maxDailyTransfer, "Bridge daily limit exceeded" ); // 更新限额 userDailyTransfer[recipient] = userDaily + amount; dailyTotalTransfer[currentDay] = dailyTotal + amount; // 转入资金 IERC20(USDT).transferFrom(msg.sender, address(this), amount); emit Deposit(msg.sender, amount, destTxHash); } // 取款(目标链,由中继器触发) function withdraw( bytes32 srcTxHash, address recipient, uint256 amount, uint256 confirmations, bytes memory proof ) external onlyRelayer whenNotPaused nonReentrant { // 检查是否已处理 require( !processedTransactions[srcTxHash], "Transaction already processed" ); // 验证证明 require( verifyWithdrawProof(srcTxHash, recipient, amount, confirmations, proof), "Invalid proof" ); // 检查确认数 require(confirmations >= minConfirmations, "Not enough confirmations"); // 标记为已处理 processedTransactions[srcTxHash] = true; // 转出资金 uint256 balance = IERC20(USDT).balanceOf(address(this)); uint256 amountToTransfer = amount > balance ? balance : amount; if (amountToTransfer > 0) { IERC20(USDT).transfer(recipient, amountToTransfer); } emit Withdraw(recipient, amountToTransfer, srcTxHash); } // 验证取款证明(使用轻客户端验证) function verifyWithdrawProof( bytes32 srcTxHash, address recipient, uint256 amount, uint256 confirmations, bytes memory proof ) internal view returns (bool) { // 这里实现轻客户端验证逻辑 // 验证: // 1. 交易确实存在于源链 // 2. 有足够的确认数 // 3. 证明由多个独立的中继器签名 // 简化实现,实际应用中需要完整的SPV验证 return true; } // 紧急暂停 function pause() external onlyRole(GUARDIAN_ROLE) { _pause(); } function unpause() external onlyRole(GUARDIAN_ROLE) { _unpause(); } // 更新配置(需要多签) function setMinConfirmations(uint256 _minConfirmations) external onlyRole(DEFAULT_ADMIN_ROLE) { minConfirmations = _minConfirmations; } } 实战案例 案例:EVM链跨链桥 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 import { ethers } from 'ethers' import axios from 'axios' class EVMCrossChainBridge { private sourceChain: ethers.providers.Provider private destChain: ethers.providers.Provider private bridgeContract: ethers.Contract constructor( sourceRpc: string, destRpc: string, bridgeAddress: string, privateKey: string ) { this.sourceChain = new ethers.JsonRpcProvider(sourceRpc) this.destChain = new ethers.JsonRpcProvider(destRpc) const wallet = new ethers.Wallet(privateKey, this.destChain) this.bridgeContract = new ethers.Contract( bridgeAddress, [ 'function deposit(bytes32 destTxHash, address recipient, uint256 amount)', 'function withdraw(bytes32 srcTxHash, address recipient, uint256 amount, uint256 confirmations, bytes proof)', 'event Deposit(address indexed user, uint256 amount, bytes32 indexed destTxHash)', 'event Withdraw(address indexed user, uint256 amount, bytes32 indexed srcTxHash)' ], wallet ) } /** * 跨链转移资产 */ async transfer( fromAddress: string, toAddress: string, amount: bigint, tokenAddress: string ): Promise<string> { // 1. 在源链授权 const tokenContract = new ethers.Contract( tokenAddress, ['function approve(address spender, uint256 amount)'], new ethers.Wallet(process.env.PRIVATE_KEY, this.sourceChain) ) const approveTx = await tokenContract.approve( this.bridgeContract.address, amount ) await approveTx.wait() // 2. 存款到桥合约 const destTxHash = ethers.utils.keccak256( ethers.utils.defaultAbiCoder.encode( ['address', 'uint256', 'uint256'], [toAddress, amount, Date.now()] ) ) const depositTx = await this.bridgeContract.deposit( destTxHash, toAddress, amount ) const receipt = await depositTx.wait() // 3. 等待确认后,在目标链提取 const srcTxHash = receipt.transactionHash await this.waitForConfirmations(srcTxHash, 6) // 4. 提取资金 const withdrawTx = await this.bridgeContract.withdraw( srcTxHash, toAddress, amount, 6, // 确认数 '0x' // 证明(简化) ) await withdrawTx.wait() return withdrawTx.hash } /** * 等待足够的确认数 */ private async waitForConfirmations( txHash: string, confirmations: number ): Promise<void> { while (true) { const tx = await this.sourceChain.getTransaction(txHash) const currentBlock = await this.sourceChain.getBlockNumber() const confirmations = currentBlock - tx.blockNumber if (confirmations >= confirmations) { break } await new Promise(resolve => setTimeout(resolve, 10000)) // 等待10秒 } } } 案例:Cosmos IBC转账 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 package ibc import ( sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) type IBCTransferKeeper struct { bankKeeper banktypes.Keeper channelKeeper ChannelKeeper portKeeper PortKeeper } // 跨链转账 func (k IBCTransferKeeper) Transfer( ctx sdk.Context, sourcePort string, sourceChannel string, token sdk.Coin, sender sdk.AccAddress, receiver string, timeoutHeight uint64, ) error { // 1. 验证参数 if token.Amount.IsZero() { return fmt.Errorf("amount must be positive") } // 2. 从发送者账户扣除代币 if err := k.bankKeeper.SendCoins( ctx, sender, accountAddr, sdk.NewCoins(token), ); err != nil { return err } // 3. 创建IBC数据包 packetData := TransferData{ Sender: sender.String(), Receiver: receiver, Amount: token, Memo: "", } packetBz := modulecdc.MustMarshalJSON(&packetData) packet := channeltypes.Packet{ Data: packetBz, TimeoutHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: timeoutHeight}, TimeoutTimestamp: 0, } // 4. 发送数据包 _, err := k.channelKeeper.SendPacket(ctx, packet) if err != nil { return err } ctx.EventManager().EmitEvents( sdk.Events{ sdk.NewEvent( "ibc_transfer", sdk.NewAttribute("sender", sender.String()), sdk.NewAttribute("receiver", receiver), sdk.NewAttribute("amount", token.String()), ), }, ) return nil } // 接收跨链代币 func (k IBCTransferKeeper) OnRecvPacket( ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress, ) exported.Acknowledgement { var data TransferData if err := modulecdc.UnmarshalJSON(packet.Data, &data); err != nil { return channeltypes.NewErrorAcknowledgement(err) } // 解析接收者地址 receiver, err := sdk.AccAddressFromBech32(data.Receiver) if err != nil { return channeltypes.NewErrorAcknowledgement(err) } // 铸造代币 coins := sdk.NewCoins(data.Amount) if err := k.bankKeeper.MintCoins(ctx, coins); err != nil { return channeltypes.NewErrorAcknowledgement(err) } // 发送给接收者 if err := k.bankKeeper.SendCoins( ctx, accountAddr, receiver, coins, ); err != nil { return channeltypes.NewErrorAcknowledgement(err) } // 记录事件 ctx.EventManager().EmitEvents( sdk.Events{ sdk.NewEvent( "ibc_receive", sdk.NewAttribute("receiver", receiver.String()), sdk.NewAttribute("amount", data.Amount.String()), ), }, ) return channeltypes.NewResultAcknowledgement([]byte{0x01}) } 总结 跨链技术是多链生态实现互操作性的核心。从简单的HTLC到复杂的轻客户端验证,不同的技术方案适用于不同的场景。 ...

WEB3去中心化身份(DID)技术深度解析

引言 去中心化身份(Decentralized Identity,简称DID)是WEB3的核心基础设施之一。它让用户完全掌控自己的身份数据,不再依赖中心化的身份提供商。本文将深入探讨DID的技术原理、W3C标准、可验证凭证(VC)以及如何构建生产级的去中心化身份系统。 DID基础概念 传统身份系统的问题 中心化身份平台 ├── Google账号 │ └── 谷歌掌握所有数据 ├── 微信账号 │ └── 腾讯掌握所有数据 └── 支付宝账号 └── 蚂蚁掌握所有数据 问题: - 数据孤岛:各平台数据不互通 - 隐私泄露:中心化服务器易被攻击 - 审查风险:平台可随时封禁账号 - 数据滥用:平台可擅自使用用户数据 去中心化身份的优势 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // DID架构 interface DIDArchitecture { user: { control: "complete", // 用户完全控制 portable: true, // 身份可跨平台使用 privacy: "enhanced" // 隐私保护 }, verifier: { trust: "decentralized", // 去中心化信任 cost: "low" // 验证成本低 }, issuer: { efficiency: "high", // 发行效率高 revocation: "easy" // 撤销机制简单 } } W3C DID标准 DID结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // DID URL格式 did:method:specific-idstring // 示例 did:ethr:0x5a2e... // Ethereum DID did:sol:1234... // Solana DID did:web:example.com // Web DID did:key:z6Mk... // Key DID // 解析DID interface DID { method: string // 方法名(ethr, sol, web, key等) id: string // 特定方法的标识符 } DID文档 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 { "@context": [ "https://www.w3.org/ns/did/v1" ], "id": "did:ethr:0x5a2e...", "verificationMethod": [ { "id": "did:ethr:0x5a2e...#controller", "type": "EcdsaSecp256k1RecoveryMethod2020", "controller": "did:ethr:0x5a2e...", "blockchainAccountId": "0x5a2e...@eip155:1" } ], "authentication": [ "did:ethr:0x5a2e...#controller" ], "assertionMethod": [ "did:ethr:0x5a2e...#controller" ], "capabilityDelegation": [ "did:ethr:0x5a2e...#controller" ], "capabilityInvocation": [ "did:ethr:0x5a2e...#controller" ], "keyAgreement": [ { "id": "did:ethr:0x5a2e...#keyAgreement", "type": "X25519KeyAgreementKey2019", "controller": "did:ethr:0x5a2e...", "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" } ], "service": [ { "id": "did:ethr:0x5a2e...#vcs", "type": "VerifiableCredentialService", "serviceEndpoint": "https://example.com/vcs/" } ] } DID方法实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 // Ethereum DID Registry import { ethers } from 'ethers' class EthrDID { private registry: ethers.Contract private provider: ethers.Provider constructor() { this.provider = new ethers.JsonRpcProvider('https://eth.llamarpc.com') this.registry = new ethers.Contract( '0xdca7ef03e98e0dc2b855be647c39abe984fcf21b', ['function owner(address) view returns (address)'], this.provider ) } async resolve(did: string): Promise<DIDDocument> { // 解析DID const [, , address] = did.split(':') // 从链上获取DID文档 const owner = await this.registry.owner(address) return { '@context': 'https://www.w3.org/ns/did/v1', id: did, verificationMethod: [{ id: `${did}#controller`, type: 'EcdsaSecp256k1RecoveryMethod2020', controller: did, blockchainAccountId: `${address}@eip155:1` }], authentication: [`${did}#controller`], assertionMethod: [`${did}#controller`] } } async createDID(privateKey: string): Promise<string> { const wallet = new ethers.Wallet(privateKey) const address = await wallet.getAddress() return `did:ethr:${address}` } } // 使用 const ethrDid = new EthrDID() const did = await ethrDid.createDID(privateKey) // did:ethr:0x5a2e... const document = await ethrDid.resolve(did) 可验证凭证(Verifiable Credentials) VC数据模型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 interface VerifiableCredential { '@context': string[] | string type: string[] id?: string issuer: string | Issuer issuanceDate: string expirationDate?: string credentialSubject: CredentialSubject credentialStatus?: CredentialStatus refreshService?: RefreshService termsOfUse?: TermsOfUse[] evidence?: Evidence[] proof?: Proof } // 示例:大学学历凭证 const universityDegree: VerifiableCredential = { '@context': [ 'https://www.w3.org/2018/credentials/v1', 'https://www.w3.org/2018/credentials/examples/v1' ], type: ['VerifiableCredential', 'UniversityDegreeCredential'], id: 'urn:uuid:12345678-1234-5678-1234-567812345678', issuer: 'did:ethr:0x1234...', issuanceDate: '2024-01-06T12:00:00Z', expirationDate: '2034-01-06T12:00:00Z', credentialSubject: { id: 'did:ethr:0xabcd...', degree: { type: 'BachelorDegree', name: '计算机科学学士' }, university: '示例大学' }, proof: { type: 'EcdsaSecp256k1Signature2019', created: '2024-01-06T12:00:00Z', proofPurpose: 'assertionMethod', verificationMethod: 'did:ethr:0x1234...#controller', jws: 'eyJhbGciOiJFUzI1Nk...' // 签名 } } VC发行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 import { ethers } from 'ethers' import { createVerifiableCredentialJwt } from 'did-jwt-vc' class CredentialIssuer { private issuerDid: string private issuerWallet: ethers.Wallet constructor(did: string, privateKey: string) { this.issuerDid = did this.issuerWallet = new ethers.Wallet(privateKey) } async issueCredential( subjectDid: string, claims: object, expiresIn: string = '1y' ): Promise<string> { const vc: VerifiableCredential = { '@context': ['https://www.w3.org/2018/credentials/v1'], type: ['VerifiableCredential'], issuer: this.issuerDid, issuanceDate: new Date().toISOString(), expirationDate: new Date(Date.now() + this.parseExpiration(expiresIn)).toISOString(), credentialSubject: { id: subjectDid, ...claims } } // 创建签名 const signer = this.issuerWallet.signMessage.bind(this.issuerWallet) // 生成JWT格式的VC const vcJwt = await createVerifiableCredentialJwt( vc, { issuer: this.issuerDid, signer } ) return vcJwt } parseExpiration(expiresIn: string): number { const match = expiresIn.match(/^(\d+)([dhmy])$/) if (!match) throw new Error('Invalid expiration format') const value = parseInt(match[1]) const unit = match[2] const multipliers = { 'd': 86400000, 'h': 3600000, 'm': 60000, 'y': 31536000000 } return value * multipliers[unit] } } // 使用示例 const issuer = new CredentialIssuer( 'did:ethr:0x1234...', '0x私钥' ) const vcJwt = await issuer.issueCredential( 'did:ethr:0xabcd...', { degree: { type: 'BachelorDegree', name: '计算机科学学士' }, university: '示例大学' }, '1y' ) VC验证 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 import { verifyCredential, verifyPresentation } from 'did-jwt-vc' import { resolveDid } from '@identitybuilding/did-resolver' class CredentialVerifier { private didResolver: any constructor() { this.didResolver = resolveDid } async verifyCredential(vcJwt: string): Promise<VerificationResult> { try { // 验证签名 const verifiedVC = await verifyCredential(vcJwt, { resolver: this.didResolver }) // 检查过期 if (verifiedVC.expirationDate) { const expirationDate = new Date(verifiedVC.expirationDate) if (expirationDate < new Date()) { return { valid: false, reason: 'Credential has expired' } } } // 检查撤销状态 const status = await this.checkRevocation(verifiedVC) if (!status.valid) { return { valid: false, reason: 'Credential has been revoked' } } return { valid: true, credential: verifiedVC } } catch (error) { return { valid: false, reason: error.message } } } async checkRevocation(vc: VerifiableCredential): Promise<{ valid: boolean }> { if (!vc.credentialStatus) { return { valid: true } } const { id, type } = vc.credentialStatus if (type === 'RevocationList2021') { // 检查比特映射 const index = parseInt(id.split('#')[1]) const revoked = await this.checkBitMap(index) return { valid: !revoked } } return { valid: true } } async checkBitMap(index: number): Promise<boolean> { // 从链上或IPFS获取撤销列表 // ... return false } } // 使用示例 const verifier = new CredentialVerifier() const result = await verifier.verifyCredential(vcJwt) if (result.valid) { console.log('凭证有效', result.credential) } else { console.log('凭证无效:', result.reason) } VP(可验证表达) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 // Verifiable Presentation interface VerifiablePresentation { '@context': string[] | string type: string[] id?: string verifiableCredential?: VerifiableCredential[] holder?: string proof?: Proof } // 创建VP import { createVerifiablePresentationJwt } from 'did-jwt-vc' class PresentationHolder { private holderDid: string private holderWallet: ethers.Wallet constructor(did: string, privateKey: string) { this.holderDid = did this.holderWallet = new ethers.Wallet(privateKey) } async createPresentation( vcs: string[], audience: string ): Promise<string> { const vp: VerifiablePresentation = { '@context': ['https://www.w3.org/2018/credentials/v1'], type: ['VerifiablePresentation'], holder: this.holderDid, verifiableCredential: vcs.map(vcJwt => { // 简化版,实际应该解析JWT return { '@context': '...', type: ['VerifiableCredential'], ... } }) } const signer = this.holderWallet.signMessage.bind(this.holderWallet) const vpJwt = await createVerifiablePresentationJwt( vp, { audience, holder: this.holderDid, signer } ) return vpJwt } } // 使用 const holder = new PresentationHolder( 'did:ethr:0xabcd...', '0x用户私钥' ) const vpJwt = await holder.createPresentation( [vcJwt], 'did:ethr:0x9999...' // verifier的DID ) 链上身份协议 Lens Protocol 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 // Lens Profile NFT interface LensProfile { handle: string // @username imageURI: string // 头像 followModule: FollowModule followNFTURI: string dispatcher: Address } // 创建Lens Profile import { providers, Contract, utils } from 'ethers' class LensProfileManager { private lensHub: Contract private provider: providers.Provider constructor(rpcUrl: string) { this.provider = new providers.JsonRpcProvider(rpcUrl) this.lensHub = new Contract( '0xDb46d1Dc155634FfC7D94Fda11Bc2b0D29Ad869d', // LensHub on Polygon [ 'function createProfile(tuple(tuple(string handle,string imageURI) profile)) external', 'function getDefaultProfile(address) view returns (uint256)', 'function getProfile(uint256) view returns (tuple(...))' ], new ethers.Wallet(process.env.PRIVATE_KEY, this.provider) ) } async createProfile(handle: string, imageURI: string): Promise<string> { const tx = await this.lensHub.createProfile({ profile: { handle, imageURI } }) const receipt = await tx.wait() console.log('Profile created:', receipt.transactionHash) return receipt.transactionHash } async getProfile(profileId: number): Promise<LensProfile> { const profile = await this.lensHub.getProfile(profileId) return { handle: profile.handle, imageURI: profile.imageURI, followModule: profile.followModule, followNFTURI: profile.followNFTURI, dispatcher: profile.dispatcher } } } // 使用 const lens = new LensProfileManager('https://polygon-rpc.com') await lens.createProfile( 'myusername', 'ipfs://Qm...' ) ENS (Ethereum Name Service) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 import { providers, Contract } from 'ethers' class ENSManager { private ensRegistry: Contract private resolverContract: Contract private provider: providers.Provider constructor(rpcUrl: string) { this.provider = new providers.JsonRpcProvider(rpcUrl) // ENS Registry this.ensRegistry = new Contract( '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e', ['function owner(bytes32 node) view returns (address)'], this.provider ) // Public Resolver this.resolverContract = new Contract( '0x4976fb03C32e5B8cfe2b6cCCb85c41a121551E2F', [ 'function addr(bytes32 node) view returns (address)', 'function setText(bytes32 node, string key, string value)', 'function text(bytes32 node, string key) view returns (string)' ], this.provider ) } namehash(name: string): string { // ENS namehash算法 const node = '0x0000000000000000000000000000000000000000000000000000000000000000' if (name === '') { return node } const labels = name.split('.') let hash = node for (let i = labels.length - 1; i >= 0; i--) { const labelHash = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(labels[i])) hash = ethers.utils.keccak256( ethers.utils.concat([hash, labelHash]) ) } return hash } async getAddress(name: string): Promise<string> { const node = this.namehash(name) return await this.resolverContract.addr(node) } async setText(name: string, key: string, value: string, signer: ethers.Signer) { const node = this.namehash(name) const resolverWithSigner = this.resolverContract.connect(signer) const tx = await resolverWithSigner.setText(node, key, value) await tx.wait() } async getText(name: string, key: string): Promise<string> { const node = this.namehash(name) return await this.resolverContract.text(node, key) } } // 使用 const ens = new ENSManager('https://eth.llamarpc.com') // 解析ENS域名 const address = await ens.getAddress('vitalik.eth') // 0xab5801a7D398351b8bE11C439e05C5B3259aEbC4 // 设置和读取ENS记录 await ens.setText( 'mydomain.eth', 'com.twitter', '@myhandle', signer ) Soulbound Token (SBT) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 // SBT(灵魂绑定代币)是不可转移的NFT import { ethers } from 'ethers' // SBT合约ABI const SBT_ABI = [ 'function issue(address to, uint256 tokenId, string uri) external', 'function revoke(address from, uint256 tokenId) external', 'function tokenURI(uint256 tokenId) view returns (string)', 'function balanceOf(address) view returns (uint256)', 'function tokenOfOwnerByIndex(address owner, uint256 index) view returns (uint256)' ] class SoulboundManager { private sbtContract: ethers.Contract constructor(contractAddress: string, privateKey: string) { const provider = new ethers.JsonRpcProvider('https://eth.llamarpc.com') const wallet = new ethers.Wallet(privateKey, provider) this.sbtContract = new ethers.Contract( contractAddress, SBT_ABI, wallet ) } async issueSBT( recipient: string, tokenId: number, metadataURI: string ): Promise<string> { const tx = await this.sbtContract.issue( recipient, tokenId, metadataURI ) const receipt = await tx.wait() return receipt.transactionHash } async getSBTsByAddress(address: string): Promise<number[]> { const balance = await this.sbtContract.balanceOf(address) const tokens = [] for (let i = 0; i < balance.toNumber(); i++) { const tokenId = await this.sbtContract.tokenOfOwnerByIndex(address, i) tokens.push(tokenId.toNumber()) } return tokens } async getSBTMetadata(tokenId: number): Promise<object> { const uri = await this.sbtContract.tokenURI(tokenId) // 从IPFS获取metadata const response = await fetch(uri) const metadata = await response.json() return metadata } } // 使用示例 const sbtManager = new SoulboundManager( '0x...', // SBT合约地址 process.env.PRIVATE_KEY ) // 发行SBT凭证 await sbtManager.issueSBT( '0x用户地址', 1, 'ipfs://Qm...' // metadata URI ) // 查询用户的SBT const tokens = await sbtManager.getSBTsByAddress('0x用户地址') for (const tokenId of tokens) { const metadata = await sbtManager.getSBTMetadata(tokenId) console.log('SBT:', metadata) // { // name: "大学学历凭证", // description: "计算机科学学士学位", // image: "ipfs://...", // attributes: [ // { trait_type: "大学", value: "示例大学" }, // { trait_type: "专业", value: "计算机科学" }, // { trait_type: "学位", value: "学士" } // ] // } } 链上声誉系统 信任分数算法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 interface ReputationData { totalInteractions: number successfulInteractions: number averageRating: number stakingAmount: number accountAge: number } class ReputationCalculator { calculateScore(data: ReputationData): number { let score = 50 // 基础分 // 交互成功率(+30分) if (data.totalInteractions > 0) { const successRate = data.successfulInteractions / data.totalInteractions score += successRate * 30 } // 平均评分(+10分) score += (data.averageRating - 3) * 3.33 // 1-5分制 // 质押金额(+5分) const stakingBonus = Math.log10(data.stakingAmount + 1) * 2 score += Math.min(stakingBonus, 5) // 账号年龄(+5分) const ageInYears = data.accountAge / (365 * 24 * 60 * 60) score += Math.min(ageInYears * 2, 5) return Math.min(Math.max(score, 0), 100) } calculateTier(score: number): string { if (score >= 90) return '钻石级' if (score >= 75) return '黄金级' if (score >= 60) return '白银级' if (score >= 40) return '青铜级' return '新手级' } } // 链上声誉合约 import { ethers } from 'ethers' class OnChainReputation { private contract: ethers.Contract constructor() { const provider = new ethers.JsonRpcProvider('https://polygon-rpc.com') const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider) this.contract = new ethers.Contract( '0x...', // 声誉合约地址 [ 'function recordInteraction(address user, bool success, uint8 rating) external', 'function getReputationScore(address user) view returns (uint256)', 'function stakeTokens(uint256 amount) external', 'function unstakeTokens(uint256 amount) external', 'event ReputationUpdated(address indexed user, uint256 score)' ], wallet ) } async recordInteraction( user: string, success: boolean, rating: number ): Promise<void> { const tx = await this.contract.recordInteraction( user, success, rating ) await tx.wait() console.log('Interaction recorded') } async getReputationScore(user: string): Promise<number> { const score = await this.contract.getReputationScore(user) return score.toNumber() } async stakeTokens(amount: number): Promise<void> { const tx = await this.contract.stakeTokens( ethers.utils.parseEther(amount.toString()) ) await tx.wait() console.log('Tokens staked') } listenToReputationUpdates() { this.contract.on('ReputationUpdated', (user, score) => { console.log(`Reputation updated for ${user}: ${score}`) }) } } DID钱包实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 import { ethers } from 'ethers' import { hdkey } from 'ethereumjs-wallet' import * as bip39 from 'bip39' class DIDWallet { private mnemonic: string private hdNode: any private did: string private credentials: string[] = [] constructor() { this.generate() } private generate() { // 生成助记词 this.mnemonic = bip39.generateMnemonic() // 从助记词生成HD钱包 const seed = bip39.mnemonicToSeedSync(this.mnemonic) this.hdNode = hdkey.fromMasterSeed(seed) // 派生第一个账户作为DID const path = "m/44'/60'/0'/0/0" const wallet = this.hdNode.derivePath(path).getWallet() const address = wallet.getAddressString() this.did = `did:ethr:${address}` } getDID(): string { return this.did } getAddress(): string { return this.did.split(':')[2] } async sign(message: string): Promise<string> { const path = "m/44'/60'/0'/0/0" const wallet = this.hdNode.derivePath(path).getWallet() const signature = await wallet.signMessage(message) return signature } async verify(message: string, signature: string): Promise<boolean> { const address = ethers.utils.verifyMessage(message, signature) return address.toLowerCase() === this.getAddress().toLowerCase() } addCredential(vcJwt: string) { this.credentials.push(vcJwt) } getCredentials(): string[] { return this.credentials } exportWallet(): string { return JSON.stringify({ mnemonic: this.mnemonic, did: this.did, credentials: this.credentials }) } importWallet(data: string) { const wallet = JSON.parse(data) this.mnemonic = wallet.mnemonic this.did = wallet.did this.credentials = wallet.credentials || [] const seed = bip39.mnemonicToSeedSync(this.mnemonic) this.hdNode = hdkey.fromMasterSeed(seed) } } // React Hook import { useState, useEffect } from 'react' export function useDIDWallet() { const [wallet, setWallet] = useState<DIDWallet | null>(null) useEffect(() => { // 从localStorage加载钱包 const savedWallet = localStorage.getItem('did-wallet') if (savedWallet) { const newWallet = new DIDWallet() newWallet.importWallet(savedWallet) setWallet(newWallet) } else { // 创建新钱包 const newWallet = new DIDWallet() setWallet(newWallet) // 保存到localStorage localStorage.setItem('did-wallet', newWallet.exportWallet()) } }, []) const backupWallet = () => { if (wallet) { const data = wallet.exportWallet() const blob = new Blob([data], { type: 'application/json' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `did-wallet-${Date.now()}.json` a.click() } } return { wallet, backupWallet } } 完整DID应用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 import { useState } from 'react' import { DIDWallet } from './did-wallet' import { CredentialIssuer } from './credential-issuer' import { CredentialVerifier } from './credential-verifier' export default function DIDApp() { const [wallet] = useState(() => new DIDWallet()) const [credentials, setCredentials] = useState<string[]>([]) const [presentation, setPresentation] = useState<string>('') const issueCredential = async (claims: object) => { const issuer = new CredentialIssuer( wallet.getDID(), '0x...' // 发行方私钥 ) const vcJwt = await issuer.issueCredential( wallet.getDID(), claims ) setCredentials([...credentials, vcJwt]) } const createPresentation = async () => { const holder = new PresentationHolder( wallet.getDID(), '0x...' // 用户私钥 ) const vpJwt = await holder.createPresentation( credentials, 'did:ethr:0x9999...' // verifier DID ) setPresentation(vpJwt) } const verifyPresentation = async (vpJwt: string) => { const verifier = new CredentialVerifier() const result = await verifier.verifyPresentation(vpJwt) return result } return ( <div> <h1>DID身份钱包</h1> <div> <h2>我的DID</h2> <p>{wallet.getDID()}</p> </div> <div> <h2>凭证</h2> {credentials.map((vc, index) => ( <div key={index}> <pre>{vc}</pre> </div> ))} </div> <div> <h2>可验证表达</h2> <pre>{presentation}</pre> </div> <button onClick={() => issueCredential({ name: '张三' })}> 发行凭证 </button> <button onClick={createPresentation}> 创建表达 </button> </div> ) } 总结 去中心化身份(DID)是WEB3的重要基础设施,通过W3C标准化、区块链技术和密码学,为用户提供了真正自主可控的身份系统。 ...

Web3与区块链开发完全指南:从智能合约到DApp

引言 Web3和区块链技术正在重塑互联网的形态。本文将深入探讨智能合约开发、DeFi协议、NFT等核心主题,帮助开发者进入Web3世界。 一、Solidity智能合约 1.1 基础合约结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract MyToken is ERC20, Ownable { uint256 public constant MAX_SUPPLY = 1_000_000_000 * 10**18; constructor() ERC20("MyToken", "MTK") { _mint(msg.sender, MAX_SUPPLY); } function mint(address to, uint256 amount) public onlyOwner { _mint(to, amount); } function burn(uint256 amount) public { _burn(msg.sender, amount); } } 1.2 安全最佳实践 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 // ========== 重入攻击防护 ========== contract ReentrancyGuard { bool private locked; modifier noReentrant() { require(!locked, "Reentrant call"); locked = true; _; locked = false; } function withdraw() external noReentrant { // ... } } // ========== 访问控制 ========== contract AccessControl { mapping(address => bool) public admins; modifier onlyAdmin() { require(admins[msg.sender], "Not admin"); _; } function addAdmin(address admin) external onlyAdmin { admins[admin] = true; } } // ========== 安全数学运算 ========== library SafeMath { function add(uint256 a, uint256 b) internal pure returns (uint256) { require(a + b >= a, "Overflow"); return a + b; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(a >= b, "Underflow"); return a - b; } } 二、DeFi协议开发 2.1 AMM交换池 1 2 3 4 5 6 7 8 9 10 11 12 contract AMMPool { uint256 public reserve0; uint256 public reserve1; function addLiquidity(uint256 amount0, uint256 amount1) external { // ... } function swap(uint256 amount0In, uint256 amount1In) external { // ... } } 三、NFT开发 1 2 3 4 5 6 7 8 9 10 11 12 import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; contract MyNFT is ERC721URIStorage { uint256 private _tokenIdCounter; function mint(address to, string memory uri) public returns (uint256) { uint256 tokenId = _tokenIdCounter++; _safeMint(to, tokenId); _setTokenURI(tokenId, uri); return tokenId; } } 四、前端集成 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import { ethers } from 'ethers'; // 连接钱包 async function connectWallet() { const provider = new ethers.BrowserProvider(window.ethereum); await provider.send("eth_requestAccounts", []); const signer = await provider.getSigner(); return signer; } // 调用合约 async function mintNFT(signer, contractAddress, uri) { const contract = new ethers.Contract( contractAddress, ['function mint(address to, string memory uri) returns (uint256)'], signer ); const tx = await contract.mint(await signer.getAddress(), uri); await tx.wait(); } 总结 Web3开发需要掌握智能合约、区块链原理和前端集成。持续关注安全最佳实践至关重要。 ...