python编程示例系列
python编程示例系列二
python的Web神器Streamlit
如何应聘高薪职位
C#视觉应用开发问题系列
c#串口应用开发问题系列
microPython Python最小内核源码解析
NI-motion运动控制c语言示例代码解析
# 区块链预言机(Oracle)技术详解
一、预言机的用途
预言机(Oracle)是区块链与外部世界之间的桥梁,它能将链下数据安全地传输到区块链上。在虚拟货币和区块链生态系统中,预言机解决了一个根本性问题:区块链本身无法直接获取外部世界的数据。
主要用途包括:
- 获取价格数据:提供加密货币、法币或商品的实时价格信息
- 金融衍生品:为智能合约提供结算所需的市场数据
- 跨链通信:实现不同区块链之间的数据传输
- 随机数生成:为需要随机性的应用(如博彩、NFT铸造)提供可验证的随机数
- 现实世界事件验证:如天气数据、体育比赛结果、选举结果等
二、预言机的原理
预言机系统通常由以下几个关键组件组成:
- 数据源:外部API、网站、物联网设备等提供原始数据
- 预言机节点:收集、处理和验证来自数据源的数据
- 聚合机制:合并多个数据源的信息,过滤异常值,提高数据可靠性
- 链上合约:接收预言机提供的数据并在区块链上使用
- 激励机制:确保预言机节点诚实运作的经济激励模型
预言机解决方案主要分为中心化和去中心化两种:
- 中心化预言机:由单一实体控制,实现简单但存在单点故障风险
- 去中心化预言机:由多个独立节点组成网络,通过共识机制确保数据可靠性
三、预言机实现代码示例
下面是一个基于以太坊的简单价格预言机实现,包括链下节点和链上合约:
链上合约 (Solidity)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title 简单价格预言机合约
* @dev 此合约允许授权的预言机节点更新价格数据,并允许其他合约读取这些数据
*/
contract PriceOracle {
// 存储每种资产的价格数据,以美元计价
mapping(string => uint256) private prices;
// 记录最后更新时间
mapping(string => uint256) private lastUpdateTime;
// 授权的预言机地址
address public oracleAddress;
// 合约拥有者
address public owner;
// 事件:价格更新时触发
event PriceUpdated(string symbol, uint256 price, uint256 timestamp);
// 事件:预言机地址变更时触发
event OracleAddressChanged(address oldAddress, address newAddress);
/**
* @dev 构造函数,设置合约部署者为所有者
*/
constructor() {
owner = msg.sender;
}
/**
* @dev 修饰符:仅允许合约所有者执行
*/
modifier onlyOwner() {
require(msg.sender == owner, "只有合约所有者可以调用此函数");
_;
}
/**
* @dev 修饰符:仅允许授权的预言机地址执行
*/
modifier onlyOracle() {
require(msg.sender == oracleAddress, "只有授权的预言机可以调用此函数");
_;
}
/**
* @dev 设置授权的预言机地址
* @param _oracleAddress 新的预言机地址
*/
function setOracleAddress(address _oracleAddress) external onlyOwner {
emit OracleAddressChanged(oracleAddress, _oracleAddress);
oracleAddress = _oracleAddress;
}
/**
* @dev 更新单个资产的价格
* @param symbol 资产代号(如"BTC")
* @param price 资产价格(以美分为单位,避免浮点数)
*/
function updatePrice(string calldata symbol, uint256 price) external onlyOracle {
prices[symbol] = price;
lastUpdateTime[symbol] = block.timestamp;
emit PriceUpdated(symbol, price, block.timestamp);
}
/**
* @dev 批量更新多个资产的价格
* @param symbols 资产代号数组
* @param newPrices 对应的价格数组
*/
function updatePrices(string[] calldata symbols, uint256[] calldata newPrices) external onlyOracle {
require(symbols.length == newPrices.length, "数组长度不匹配");
for (uint i = 0; i < symbols.length; i++) {
prices[symbols[i]] = newPrices[i];
lastUpdateTime[symbols[i]] = block.timestamp;
emit PriceUpdated(symbols[i], newPrices[i], block.timestamp);
}
}
/**
* @dev 获取资产价格
* @param symbol 资产代号
* @return 资产价格和最后更新时间
*/
function getPrice(string calldata symbol) external view returns (uint256 price, uint256 timestamp) {
return (prices[symbol], lastUpdateTime[symbol]);
}
/**
* @dev 检查价格是否在有效期内
* @param symbol 资产代号
* @param maxAge 最大有效期(秒)
* @return 价格是否有效
*/
function isPriceValid(string calldata symbol, uint256 maxAge) external view returns (bool) {
if (lastUpdateTime[symbol] == 0) return false;
return (block.timestamp - lastUpdateTime[symbol]) <= maxAge;
}
}
链下预言机节点 (Node.js)
// 预言机节点实现 - 使用Node.js和ethers.js库
const { ethers } = require('ethers');
const axios = require('axios');
// 配置参数
const config = {
// 以太坊RPC节点URL
rpcUrl: 'https://mainnet.infura.io/v3/YOUR_INFURA_KEY',
// 预言机合约地址
oracleContractAddress: '0x1234567890123456789012345678901234567890',
// 价格API端点
priceApiUrl: 'https://api.coingecko.com/api/v3/simple/price',
// 需要监控的加密货币
tokens: ['bitcoin', 'ethereum', 'binancecoin'],
// 价格更新阈值(价格变化超过此百分比才更新)
updateThreshold: 0.5,
// 更新频率(毫秒)
updateInterval: 60000,
// 价格有效期(秒)
priceValidityPeriod: 300
};
// 预言机合约ABI(仅包含需要的函数)
const oracleAbi = [
"function updatePrice(string calldata symbol, uint256 price) external",
"function updatePrices(string[] calldata symbols, uint256[] calldata newPrices) external",
"function getPrice(string calldata symbol) external view returns (uint256 price, uint256 timestamp)"
];
// 存储上次更新的价格
let lastPrices = {};
/**
* 初始化以太坊提供者和签名者
*/
async function initializeEthers() {
// 连接到以太坊网络
const provider = new ethers.providers.JsonRpcProvider(config.rpcUrl);
// 使用私钥创建钱包(在生产环境中应安全存储私钥)
const privateKey = process.env.ORACLE_PRIVATE_KEY;
const wallet = new ethers.Wallet(privateKey, provider);
// 创建合约实例
const oracleContract = new ethers.Contract(
config.oracleContractAddress,
oracleAbi,
wallet
);
return { provider, wallet, oracleContract };
}
/**
* 从API获取最新价格
*/
async function fetchPrices() {
try {
// 调用价格API
const response = await axios.get(config.priceApiUrl, {
params: {
ids: config.tokens.join(','),
vs_currencies: 'usd'
}
});
const prices = {};
// 处理API响应
for (const token of config.tokens) {
if (response.data[token] && response.data[token].usd) {
// 将价格转换为整数(以美分为单位)
// 例如:$42,123.45 => 4212345
prices[token.toUpperCase()] = Math.round(response.data[token].usd * 100);
}
}
return prices;
} catch (error) {
console.error('获取价格时出错:', error);
return null;
}
}
/**
* 检查价格是否变化超过阈值
*/
function shouldUpdatePrice(symbol, newPrice) {
// 如果没有上次的价格记录,则应该更新
if (!lastPrices[symbol]) return true;
const lastPrice = lastPrices[symbol];
const priceDiff = Math.abs(newPrice - lastPrice) / lastPrice * 100;
// 如果价格变化百分比超过阈值,则更新
return priceDiff >= config.updateThreshold;
}
/**
* 更新区块链上的价格数据
*/
async function updateOraclePrices(oracleContract, prices) {
try {
const symbolsToUpdate = [];
const pricesToUpdate = [];
// 确定哪些价格需要更新
for (const [symbol, price] of Object.entries(prices)) {
if (shouldUpdatePrice(symbol, price)) {
symbolsToUpdate.push(symbol);
pricesToUpdate.push(price);
console.log(`价格变化显著,将更新 ${symbol}: ${price/100} USD`);
}
}
// 如果有价格需要更新,则调用合约
if (symbolsToUpdate.length > 0) {
// 如果只有一个价格需要更新,使用单一更新函数
if (symbolsToUpdate.length === 1) {
const tx = await oracleContract.updatePrice(
symbolsToUpdate[0],
pricesToUpdate[0]
);
await tx.wait();
console.log(`已更新 ${symbolsToUpdate[0]} 价格,交易哈希: ${tx.hash}`);
}
// 否则使用批量更新函数
else {
const tx = await oracleContract.updatePrices(
symbolsToUpdate,
pricesToUpdate
);
await tx.wait();
console.log(`已批量更新 ${symbolsToUpdate.length} 个价格,交易哈希: ${tx.hash}`);
}
// 更新本地缓存的价格
for (let i = 0; i < symbolsToUpdate.length; i++) {
lastPrices[symbolsToUpdate[i]] = pricesToUpdate[i];
}
} else {
console.log('所有价格变化均在阈值内,无需更新');
}
} catch (error) {
console.error('更新预言机价格时出错:', error);
}
}
/**
* 主函数:定期运行价格更新
*/
async function main() {
console.log('启动价格预言机节点...');
// 初始化以太坊连接
const { oracleContract } = await initializeEthers();
console.log('已连接到以太坊网络和预言机合约');
// 定期执行价格更新
setInterval(async () => {
console.log('获取最新价格数据...');
const prices = await fetchPrices();
if (prices) {
await updateOraclePrices(oracleContract, prices);
}
}, config.updateInterval);
}
// 启动程序
main().catch(error => {
console.error('预言机节点运行出错:', error);
process.exit(1);
});
四、预言机逻辑流程图
五、预言机的其他应用场景
除了为DeFi应用提供价格数据外,预言机技术还有许多其他应用场景:
-
保险智能合约:
- 农业保险:基于天气数据自动赔付
- 航班延误保险:根据航班数据自动理赔
- 参数化保险:基于预定义参数的自动理赔系统
-
供应链管理:
- 物流跟踪:将物联网设备数据上链
- 产品真实性验证:将产品信息和验证数据上链
- 条件付款:基于货物交付状态自动执行支付
-
游戏和NFT:
- 可验证随机数生成:为游戏提供公平的随机性
- 基于现实事件的游戏结果:体育比赛结果影响区块链游戏
- 动态NFT:根据外部数据变化的非同质化代币
-
身份和信用验证:
- KYC/AML验证:将身份验证结果上链
- 信用评分:将传统金融系统的信用数据上链
- 学历证明:将教育机构的证书信息上链
-
治理和投票:
- 去中心化自治组织(DAO)投票:将链下投票结果上链
- 企业治理:将股东会议结果上链
- 公共决策:将社区投票结果上链
-
预测市场:
- 事件预测:基于现实世界事件结果结算的预测市场
- 体育博彩:基于比赛结果的自动结算
- 政治选举预测:基于选举结果的智能合约结算
六、总结
预言机技术是区块链与现实世界交互的关键基础设施,解决了区块链无法直接获取外部数据的固有限制。通过预言机,智能合约能够响应现实世界的事件和数据,大大扩展了区块链应用的范围和功能。
主要优势:
- 为智能合约提供外部数据访问能力
- 支持复杂的金融衍生品和条件触发机制
- 使区块链应用能够与现实世界事件交互
主要挑战:
- 数据源的可靠性和真实性验证
- 预言机去中心化与效率的平衡
- 经济激励机制设计,确保预言机节点诚实运作
随着区块链技术的不断发展,预言机将继续发挥关键作用,推动更多创新应用的出现,并帮助区块链技术更深入地融入各行各业。
python的ast库的使用
python进行函数式编程的工具toolz
qt开发的程序 为何一个主窗口关闭了,程序不退出,而是到等到所有窗口关闭了,才退出呢?
python如何调用电脑摄像头
python如何计算隐含波动率
矩阵运算思维如何理解
microPython的源码解析之 bc.c
3D建模完成以后,如何用编程语言控制这些模型的展示和动画
python 如何绘制uml图
量化交易系统中+如何进行模型的验证和评估?
智能农业设备软件工程师如何实现精准灌溉系统
python 用于解析复杂文本数据的库PyParsing
未来十年国产替代是程序猿的黄金赛道
python如何创建内存视图
智能农业设备软件工程师如何处理设备的系统升级和版本控制
python的plotly图形库
在Windows平台下,python如何检测另外一进程写入的文件是否完成
NI-Motion控制电机轴的扭矩和运动的C语言程序示例代码
Python如何把一个列表按照一定数量均匀的切片
科学界类似matlab的工具
量化交易系统中+如何处理系统故障和异常情况?
量化交易系统中+如何处理实时流数据?
Python的高性能web框架库Tornado
GPT-4将使ChatGPT更智能
如何在 Python 中逐行读取一个文件到列表?
C#进行串口应用开发如何区分串口数据的帧头和帧尾
microPython的源码解析之 objstr.c
量化交易系统中+如何进行代码的优化和重构?
C#进行串口应用开发如何分析串口通信接口的数据吞吐量和延时
c#视觉应用开发中如何在C#中进行图像饱和度调整?
python的unittest库如何使用功能
Python如何为Journyx Timesheet提供动力。
python编写一个简单神经网络计算代码带有反向传播,不用任何框架
microPython的源码解析之 runtime.c
量化交易系统中+如何与第三方数据提供商进行集成?
C#进行串口应用开发如何实现串口的即时通信
microPython的源码解析之 objfloat.c
microPython的源码解析之 objbool.c
智能农业设备软件工程师如何处理设备的启动时间和响应速度优化
Python 中自动生成甘特图
c#的Cloo 库介绍
excel 中如何使用python操作
为什么Python对VR社区很重要
量化交易系统中+如何处理市场冲击和滑点?
microPython的源码解析之 modstruct.c
c#视觉应用开发中如何在C#中进行图像配准?
量化交易系统中+如何进行多因子模型的构建和测试?
开源htmx库简介
NI-Motion如何设置一个周期性断点,当运动轴到达预设的目标位置时,会在周期性断点位置暂停,然后继续运动直到再次到达目标位置的C语言代码示例
python的生成艺术字体的库pythonwordart
智能农业设备软件工程师如何处理设备的传输延迟和数据一致性
c#视觉应用开发中如何在C#中进行图像去混叠?
量化交易系统中+如何使用实时分析工具(如Kafka、Flink)?
Python如何处理开放神经网络交换格式
python web应用开发神器 入门十七
python 非常好用的标准库itertools
Python中怎样计算浮点数的小数部分各位上数字之和?
C#进行串口应用开发如何区分串口接收到的数据帧
量化交易系统中+如何确保数据的安全性和隐私保护?
Python在科学数据可视化中的应用
c#视觉应用开发中如何在C#中进行运动检测?
量化交易系统中+如何处理机器学习中的数据偏差和公平性问题?
c#视觉应用开发中如何在C#中进行图像光照校正?
智能农业设备软件工程师如何集成和管理农业设备的系统维护
python进行局部线性嵌入(LLE)LocallyLinearEmbedding
microPython的源码解析之 scope.c
数据降维技术和算法
智能农业设备软件工程师如何集成和管理农业设备的传感器数据分析
量化交易系统中+如何实现实时数据的展示和更新?
C#进行串口应用开发如何修复因串口配置错误导致的通信故障
车载系统软件工程师如何实现车载系统的高精度定位和导航
python如何用udp协议
C#进行串口应用开发如何实现串口通信的心跳检测与重连机制
3D人物说话时的嘴部动作与表情与语音如何配合到一起的
车载系统软件工程师如何实现车载系统的交通信息集成和显示
python的一个打包工具cx_Freeze
python的Plotly库如何使用
车载系统软件工程师如何实现车载系统的蓝牙和无线连接
量化交易系统中+如何实现实时数据分析和决策支持?
python的injectool库
智能农业设备软件工程师如何集成和管理农业设备的故障日志和报告
量化交易系统中+如何进行仓位管理和资金管理?
在 C++ 和 Qt 中如何利用GPU加速计算
c#视觉应用开发中如何在C#中进行图像去重叠?
python web应用开发神器 入门十三
Python 如何用opencv进行人脸年龄检测
jupyter深度理解六 之ipywidgets
车载系统软件工程师如何处理车载系统的低延迟通信
车载系统软件工程师如何处理车载系统的系统日志和故障报告
python web应用开发神器 入门十八
车载系统软件工程师如何处理车载系统的系统恢复和故障恢复
车载系统软件工程师如何处理车载系统的数据同步和备份
NI-Motion如何使用National Instruments的FlexMotion软件库来控制一个运动控制器执行螺旋弧线(Helical Arc)运动的C语言示例代码
气象学家如何利用Python
开发Python程序你一定要安装的一个库.让异常信息更加易读和信息量更丰富.
车载系统软件工程师如何集成车载系统与车辆诊断和维修系统
车载系统软件工程师如何实现车载系统的AR导航和显示
智能农业设备软件工程师如何处理设备的电源管理和优化
智能农业设备软件工程师如何实现农业设备的智能助理和AI应用
开源的仿红色警戒OpenRA经典RPG游戏, 源码解读game.cs