面向开发者 / 现实世界资产
一个价格如何形成
两种聚合方法,一个发布者。下面那套算术让一个价格在某个交易所行为异常时仍然稳健;它不是让这个价格可信的东西。那是最后一节,也是在你拿这些数字去清算任何东西之前该读的那一节。
一个价格从哪里来
Thirteen feeds are aggregated from five public spot venues, each subscribed with that venue's own product id. The other twenty have no venue leg and come from Pyth Network's Hermes service alone.
| 来源 | 是什么 |
|---|---|
| 现货交易所 | Coinbase, Kraken, Bitstamp, Gemini, Bitfinex每一个都以那家交易所自己的产品 id 订阅,取自目录 |
| 第二来源 | Pyth Network,经由它的 Hermes 服务那二十个没有交易所腿的价格源的唯一来源,也是另外十三个的交叉核对 |
这两种方法失败的方式不同,而消费者需要了解两种行为。一个由交易所支撑的价格源能挺过一家交易所 断线,因为中位数是在五家之间取的,而且每一家都带着自己的新鲜度。一个单来源价格源挺不过它的 来源不可用,而它会明说,而不是去猜。
一个交易所何时算数
在任何东西被合并之前,每家交易所都先被单独评估。规则按这个顺序施加,而第一个不通过的规则就把 这家交易所从那一次评估的中位数里剔除:
| 规则 | 阈值 |
|---|---|
| Connection state | must be onlinea venue whose socket is down is never fresh, whatever its last quote said |
| Quote age | 10 smeasured on a MONOTONIC receive clock, never on the exchange's timestamp or the host's wall clock |
| Delivery lag | 5 s either waya timestamp trailing its receipt means the socket is replaying a backlog; one leading it means the venue dates quotes in the future. The whole venue sits out rather than falling through to its last trade |
| Spread | 50 bpsthe mid is used when the book is uncrossed and tighter than this |
| Last trade | 60 sthe fallback when no usable mid exists, inside its own longer window |
不是按交易所的时间戳,也不是按主机的挂钟。一家时钟走快或走慢的交易所没法让自己的报价看起来 很新鲜,而一台时钟跳变的主机也没法一次性作废每一家交易所。交易所时间戳只用于一件事:送达 延迟检查,它在两个方向上把它和收到的那一刻作比较。
当订单簿够新、未交叉,而且比价差上限更窄时,优先采用最优买价和卖价。否则由最近一笔成交顶替, 在它自己那个更长的窗口之内。一家 socket 正在重放积压的交易所会被整个剔除,而不是退而采用它的 最近一笔成交,因为那笔成交迟了同样多。
中位数
- Evaluate every venue against the rules above and keep the fresh ones.
- If fewer than minSources are fresh, publish nothing and report the reason - no_sources when none is fresh, too_few_sources otherwise. Nothing thin is ever published.
- Take the median of what survives.
- If the spread between the included venues exceeds 200 bps and dropping one would still leave minSources, drop the venue furthest from the median - on a tie the older observation - and take the median again. At most one venue is dropped.
- Round half-even to the feed's decimals. The result is an integer, not a float.
- Date the aggregate with the NEWEST included quote, capped at the current wall clock so no venue with a fast clock can date a median into the future.
degraded is set when the median rested on exactly minSources venues: still published, one drop-out from silence.
一个来源太少的价格源宁可什么都不发布
minSources 是逐价格源的,而在每一个由交易所支撑的价格源上它都是 3。低于它就 根本没有答案:链上不会重新发布任何最近已知值,那一轮不推进,updatedAt 停止 移动。服务仍然把最近那个好答案作为 lastKnown 报出来以便诊断,而那个字段明确 不是一个可以据以交易的价格。
聚合值以被纳入的最新那条报价定时,并以当前挂钟为上限。两半都要紧:一家用 一笔六十秒前的成交顶替了陈旧订单簿的交易所,不该给一个其他输入都是亚秒级的中位数定时;而 任何时钟走快的交易所都不得把一个观测时间推到未来,在那里合约会以理由 4 跳过它。
交叉核对与顶替
An exchange-backed feed that also has a Pyth leg is cross-checked against it on every evaluation. Within 100 bps the two are recorded as agreeing; beyond it the feed is marked diverged and the dispersion flag is raised.
When the venues go stale, Pyth may stand in for them - but only if the two agreed recently and are not diverging now. A feed publishing from the stand-in is marked degraded and its source reads pyth rather than exchanges-median, so a consumer can tell. If they are diverged and Pyth is fresh, the feed publishes nothing and reports cross_check_diverged.
有两个字段把这件事暴露出来。crossCheckBps 是两种方法之间当前的距离,而 source 说的是哪一种产生了你手上这一轮:1 是交易所中位数,2 是第二来源。一个 source 变过的价格源仍然是一个有效的价格,只是 由另一种方式产生的;如果这对你的产品有影响,就去盯这个字段,而不是去推断它。
第二来源
第二来源的每一次更新在有资格成为一个价格之前都要通过这些检查。一次被拒的更新会按理由给一个 计数器加一,在服务的来源路由和审计路由上逐价格源可见:
| 检查 | 限制 |
|---|---|
| Exponent | pinned on the first updateany later drift is rejected, so a silent rescaling cannot pass |
| Slot and publish time | must advancean update that does not move them forward is dropped |
| Future tolerance | 5 sa publish time further ahead than this is rejected |
| Confidence | 50 bps crypto and index, 30 equity, 10 commodity and fxthe reported confidence interval as a fraction of the price; wider is rejected |
| EMA band | 10 % crypto and index, 5 % elsewherea jump away from the exponential moving average needs a SECOND sample within 100 bps of the first before it is used. A lone spike is dropped |
| Freshness | 10 s since receipt, 30 s publish lagboth measured at receipt on the monotonic clock |
没有那份凭据,三十三个价格源里有二十个是沉默的
The upstream needs a credential. Without one it answers unauthorised and every feed with no venue leg stays unpublished - twenty of the thirty-three, which is the whole real-world set plus XMR/USD.
The thirteen exchange-backed feeds continue: they are computed from public venues and need no credential. What they lose is the cross-check and the stand-in, since neither can be established without a Pyth price to compare against. Readiness reports this as a warning rather than a failure, so the service looks healthy while two thirds of the catalog is silent - check the per-feed status, not the service's.
指数检查是安静的那一个,也是最重要的那一个。一次更新的标度在第一次通过认证的更新那里就被钉 死,之后任何漂移都被直接拒绝,因为一次无声的重新标度,就是一个差了十的幂、却看起来格式完全 正常的价格。
它怎样到达链上
- The aggregating service holds no signing key at all. It computes prices and serves them on an internal port.
- The node's publisher polls that port, authenticates the body with a shared HMAC of the exact bytes, and re-checks every item against on-chain state before signing - mirroring the contract's own skip rules so a bad item costs a counter rather than gas.
- The batch is written as ONE system transaction per EVM block, signed by the publisher key, which lives in the node's process and is used by nothing else in it.
- The service then reads its own result back off the chain and reports it, which is what the onchain field of every FeedView is.
At most 64 feeds go into one batch by default, and the contract's own maxBatch caps it again. A batch older than 2 s is not published.
分工才是重点。所有慢的或可能出错的事情,轮询、认证、读目录、选择、编码、签名以及预写日志的 追加,都发生在封存路径之外,而封存路径收到的是一笔做好的交易,并以任何其他交易的代价施加它。 而且因为发布者在签名之前会拿每一条与链上状态重新核对,镜像合约自己的跳过规则,所以一个聚合器 送来一个坏东西,花掉的是一个计数器而不是一轮。
信任模型
A price is as trustworthy as the operator that produces blocks, and no more. The publisher is the block producer.
- One party operates the node, holds the publisher key and orders transactions. A price inherits exactly the assumption that already governs ordering.
- Nothing on chain arbitrates a price. There is no second publisher, no dispute window and no slashing: the contract checks that an item is well formed, positive, not from the future and not older than the feed's last observation, and then writes it.
- The owner role can add a feed, change a feed's policy, rotate the publisher and adjust the batch and tolerance parameters. Ownership transfer is two-step. Those are the only write paths that are not the publisher's.
- Splitting the key from the computation limits one failure, not the other: compromising the aggregating service lets an attacker propose prices, and every one is still re-checked and signed by the node. Compromising the node is the end of the argument.
- If you liquidate on these prices, that is the assumption you are taking, and it is the one to state to your own users.
上面所有的东西都改变不了这一点。交易所规则、中位数、异常值剔除和交叉核对,让一个价格在某个来源行为异常时保持稳健,那是一种真实而常见的失败。它们对签名的那一方什么也做不了。 请把它们读作质量控制,而不是一种共识。
对集成方的实际后果是:这些价格适合这样一种产品,它的用户被告知了是谁产生了它们,而它们带着 和你自己交易的排序一样的那个假设,所以如果你为了使用这条链本来就接受了那个假设,消费这些 价格源并不增加新的假设。如果你的设计需要一个没有任何单一方能够伪造的价格,这一层不提供它, 而且没有任何参数能让它做到。