以太坊节点之间跑着一层叫 DEVp2p 的会话协议,区块、交易、状态数据都从它身上过。2017 年之前这层完全没有压缩,EIP-706 算了一笔账:用快速同步模式把主网(当时约第 4248000 块)拉一遍,客户端要吃下三十三点五九吉字节的下载量——而这些区块和交易数据高度可压缩。于是这份最终状态为 Final 的提案把 snappy 压缩塞进了传输层,成为今天每个以太坊节点默认在做的事。
规则只有几条
协商方式沿用版本表:DEVp2p 的通告版本号从 4 抬到 5。握手时对方只支持 4,一切照旧;对方支持不低于 5,则在发送时给每条消息的载荷先做 snappy 压缩、把长度字段改成压缩后的字节数,再走原有的加密流程;接收端反过来,解密后先解压再交给上层。两个硬性注脚:握手的 Hello 消息永不压缩,因为双方还得靠它协商版本;snappy 的分帧格式不使用,DEVp2p 本来就是按消息切分的,不需要再包一层。
选择在传输层动手而不是逐个子协议改造,提案里给了明确的取舍:在 eth、les 等每个应用层协议里分别加压缩,等于把传输编码问题渗进应用逻辑,每个协议都要重复一遍,跨客户端协调成本翻倍;在 DEVp2p 一处动手,所有跑在它上面的协议无缝受益。被放弃的还有“另立 xyz-compressed 平行协议”的方案,理由同样是要维护的东西太多。

防解压炸弹:先问长度再决定解不解
压缩数据天然带一个陷阱:一个几十千字节的包可以解压出几吉字节,专杀不假思索就解密的节点。snappy 的格式在开头就存了解压后的总长度,EIP-706 据此给出防御规则:解析出解压长度,超过阈值直接丢包,不进内存。阈值定为十六兆字节——和旧协议明文消息的上限一模一样。提案强调这个选择是为了保持既有保证不变,应用层不用为压缩改任何假设。
快是优点也是性格
snappy 在这个方案里的定位从头到尾不是“压得最狠”,而是“快到能当流媒体用”:以现代 CPU 的吞吐做基准,压缩解压都近似线性扫描。对照今天常识里 gzip、zstd 的压缩率排位,snappy 通常并不占优,但它给了一个节点同时维持上百条连接时的关键属性——压缩开销小到不用做旁路和缓存决策。提案自己也算过:这套方案把主网初始同步的下载量降到约十三点四六吉字节,节省六成以上,对一条按消息流式搬运的链路已经足够划算。
一笔延迟的算术
按提案给出的两组数字粗算:同一次主网同步,未压缩与压缩后的下载量之比大致是五比二,带宽受限的家宽环境里等待时间几乎等比缩短。反过来看解压阈值那十六兆字节:它约束的不是平均值而是单包极值,攻击者即使只喂一个包也顶多让节点丢弃;把这条线与“先问解压长度”的读法合在一起,就是这份提案给所有流式协议留下的最耐用的一条工程守则。
快速问答
问:压缩会影响消息完整性吗?加密和压缩谁在前?
答:先压缩后加密,接收端先解密后解压。加密层的认证不变,压缩只是载荷的变形,破坏解压结果的数据照样过不了认证检查。
问:这个提案今天还有存在感吗?
答:它以改版本号的透明方式进了所有主流实现,日常几乎不再被提起;它留下的真正话题是那种“解压前先看解压长度”的防线,任何做网络编程的人都该抄走。
常见误区
一是把它当成“区块本身改了存储格式”,压缩只在链路消息层,链上数据一个字节没变;二是以为所有流量都被压,握手与已经压缩过的载荷本就可能落入 snappy 的字面存储模式,提案特意保留这个空间;三是觉得压缩率是唯一指标,传输层的压缩首先是带宽和延迟的交换,解压安全其次。
风险提示:本文为协议机制科普,不构成任何投资建议;客户端行为以各实现文档为准。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。