协议演进 / BIP/比特币改进提案 / BIP-171

BIP-171 货币/汇率信息 API

为向服务器查询货币汇率信息定义统一的 HTTP/JSON 接口,使钱包只需实现一次即可对接所有兼容的行情提供方。本 BIP 目前处于已关闭状态。

一、档案卡

档案卡
编号BIP-171
标题Currency/exchange rate information API
作者Luke Dashjr <[email protected]>
指定日期2017-03-04
层级Applications(应用)
类型Specification(规范类)
状态Closed(已关闭)
阅读版https://bips.dev/171
官方原文https://github.com/bitcoin/bips/blob/master/bip-0171.mediawiki

二、放在哪一族

应用层的外部数据接口一族。它不属于 P2P 网络协议,也不属于链上规则,而是管“链外世界的数据怎么以统一格式喂给钱包软件”:钱包想给用户显示一个法币计价,就需要向某个行情服务器查询汇率,BIP-171 想把这类查询的请求与应答格式标准化。

原文文件头没有 Requires、Replaces 等关系字段。它在概念上与本 BIP 中定义的计价单位 XBT 相连——原文把 XBT 定义为 100,000,000 satoshis(即通常所说的 1 BTC),并要求一切比特币金额的查询都以 XBT 为单位提出,哪怕最终展示给用户的单位不同。

三、它要解决什么

原文 Motivation 写得很直白:终端用户经常希望在比特币钱包软件里看到法币计价的信息。但由于比特币的性质,汇率天然不存在任何权威来源:提供这类信息的独立服务方有很多,却各用各的格式。结果是钱包软件被迫为每一个行情提供方写一套专门的对接代码。

标准接口的意义在于一次实现、处处互通:钱包(及其他软件)与服务提供方只要各自实现一遍本规范,就立刻能与所有其他兼容实现互操作。换言之,它要消除的是“每个提供方一种方言”的重复劳动,而不是去指定汇率本身应该是多少、该信哪一家。

原文的 Rationale 还解释了两个格式细节的设计理由:多条结果之间用换行符分隔而不是 JSON 数组,是为了让客户端可以把历史数据简单地追加进缓存文件,也能逐行解析而不必把整批数据读进内存组成一个对象;长描述中需要换行时,则借 JSON 本身的转义(\n、\n\n)表达,不破坏逐行结构。

四、规则本身

4.1 通用约定

四种请求全部以 GET 方式发往一个共同 URI,参数用 application/x-www-form-urlencoded 编码。所有匹配参数都可以用逗号分隔的多个值表示,含义是“其中任意一个”。应答一律是 JSON 格式,多条结果之间用换行符(LF,绝不用回车)分隔。

其他通用规则:

4.2 请求一:列举支持的货币对(mode=list)

参数可带 quote、base、locale 作过滤(服务器可以据此收窄结果)。每条结果是一个 JSON 对象,含货币对标记 cp、计价货币 quote、基础货币 base、可选的适用 locale、可选的简短描述 desc(建议短于 45 字符),以及可选签名。

4.3 请求二:货币对的展示信息(mode=info)

按 cp 查询某个货币对的元信息。除了 list 的字段外,还包括:更长的描述 longdesc(可含换行);计价货币的符号 symbol(前缀与后缀,各自可以是固定字符串、按正负数区分的一对字符串或 null,正负号的呈现必须全在这里交代,不得另行暗示);数字系统 digits(常用 0–9 应标为 arabic);千位分组规则 grouping(数字与分隔符交替的数组,末尾的 0 表示最后一段分组无限重复,例如美式分组为 [3, ",", 0]);小数分隔符 fraction_sep 与小数位数规则 fraction_digits;轮询下限 minpoll(秒,客户端不应比这更频繁地轮询);是否支持长轮询 longpoll;历史数据最早可达的时间戳 history;以及表示服务器已不再提供现行汇率的 archive 时间戳。

这一节的用意是:金额怎么显示(符号、分组、小数位)不该由每个钱包自行猜测,而由数据提供方随数据一并交代。

4.4 请求三:当前汇率(mode=rate)

按 cp 查询现行汇率,可用 type 指定想要的汇率种类(high、low、average、typical 或任意其他名称;省略时由服务器提供它认为合适的种类)。若请求带上 minrate/maxrate,则构成长轮询:服务器应等到汇率跌破或升破所给数值时再应答;带 nonce 时,服务器应在每条结果中原样回带。每条结果含货币对标记、该汇率适用的时间 time(POSIX 时间戳,应约等于请求时刻)、以及以种类为键、数值为值的 rates 对象。

4.5 请求四:历史汇率(mode=history)

参数在 rate 的基础上增加时间范围:from 与 to(省略 to 则取当前时间);nearest 为真时表示只要离 from 最近的那一条,不需要一段范围;ratedelta/timedelta 允许服务器在汇率或时间变化不显著时省略记录,两者同时给出时任一变化显著即应给出新记录。结果格式与当前汇率相同,按时间顺序给出(只需在每个货币对的范围内有序);若 from/to 恰好没有精确记录,应各补一条范围外最近的记录,nearest 或省略 to 的情形除外。

向后兼容方面,原文说得很简单:在这一新标准被采用的同时,软件与提供方可以继续使用和提供各自原有的格式,直到它们不再被需要。原文的 Reference implementation 一节在仓库中仍标注为 TODO。

五、谁必须动

普通持币人(钱包用户):无直接动作。钱包界面上显示的法币数字从哪来、准不准,取决于钱包选了哪家提供方,而不是本 BIP。

钱包开发者:本 BIP 的目标受益者兼实现方:按统一接口实现一次查询与展示逻辑(包括按 info 返回的符号、分组与小数规则排版金额,并遵守 minpoll 的轮询下限),即可对接所有兼容服务器。

行情服务提供方:按四种 mode 实现服务器端,至少支持一个与 XBT 比价的货币对;比特币金额一律以 XBT 为查询单位。

全节点、矿工与共识层:完全不动。汇率是链外信息,不进区块、不影响任何交易的确认与有效性。

六、现在算不算数,以及一个常见误读

状态为 Closed(已关闭)。按现行 BIP 状态体系,这意味着该提案已被关闭,不再是有效的现行规范——不能指望今天的钱包与行情服务普遍按 BIP-171 互通;现实中各钱包与提供方仍多用各自的接口,正是本 BIP 当年想消除而未竟的局面。它的文档价值在于留下一套完整设想:连“符号怎么标、多久才许轮询一次”都写进标准,钱包显示金额的口径才可能统一。

常见误读:

“比特币协议里本就规定了汇率,或者某个 BIP 给出的汇率就是官方汇率。”

不对,而且原文明说反面:由于比特币的性质,汇率天然不存在权威来源。本 BIP 从头到尾只规定“怎么问、怎么答”的接口格式,不规定任何一家提供方的数据是对的,更没有把某个价格写进协议。钱包里看到的法币数字始终是链外数据的展示,不是共识的一部分。

七、延伸

本页内容整理自 bitcoin/bips 仓库与 bips.dev,事实已与仓库核对;解读仅供学习参考。