为了将比特币相对庞大的市值注入到以太坊DeFi世界中,许多团队尝试去做两边跨链的转移,发行针对比特币做锚定的代币,例如imBTC,wBTC,tBTC等专案,而相对去中心化的tBTC在5/15上线3天后紧急关闭,原因是合约存在漏洞,官方于5/20发布了详尽的说明,这边做一点翻译跟总结,让大家快速了解到底发生了什么事情
TL; DR
tBTC验证比特币链上交易的设计有瑕疵,导致某些情况下合法的赎回永远无法被确认,造成错误赔偿,可被有心使用者作为攻击手段
对细节有兴趣的朋友,可以继续往下看,会需要一些基本的比特币脚本知识
tBTC如何运作
首先很快速的描述一下tBTC基本上是怎么运作的,这边的细节并不影响理解实际出问题的替代。
每一次抵押铸币及赎回,是由系统中随机选出来的三个签名者去协助完成的,这些签名者可以是任意使用者,他们需要超额抵押ETH到合约里做担保,超额抵押贷款150%,目的是防止signer卷款逃走。
赎回时,申请赎回的人需要多支付一些费用给signer(目的是奖励signer),并且指定赎回的目的地,signers他们确认后需要一起签出bitcoin的交易并等待tBTC系统确认这笔交易已经上链,才可以拿回原先抵押的ETH以及额外的手续费。
透过这样的抵押机制,希望可以做到去中心化的跨链货币转换。
什么地方出了错?
tBTC在智能合约里面验证通过歌手发送给他们的比特币tx中,第一个输出脚本与redeemer当初次指定的一致,即,签名人确实有返还比特币给用户指定的地址(或输出脚本)。合约中使用的输出资料结构如下图
tBTC智能合约中使用的比特币TX输出的数据结构
而出问题的部分,是在验证交易的最后一项检查
require( keccak256 (_output.slice(8,3).concat(_output.extractHash()))== keccak256(abi.encodePacked(_d.redeemerOutputScript)), “ Tx将值发送到错误的pubkeyhash” );
首先他先将第8〜10这三个字节拉出来,并且跟_output.extractHash()做合并,目的是得到下图这样的结果
用输出脚本附加长度
利用这样的结构,去跟原先的的redeemerOutputScript做比对,期待两者一致,可是很不幸的,这样的做法,只适用于原生隔离见证脚本。
从地址格式探讨Bitcoin和Ethereum的差异
Bitcoin和Ethereum在许多方面有着截然不同的设计,这篇文章会从地址格式出发,比较两者在交易格式以及身份认定上的差异,透过这些差异了解两套系统在设计哲学上的不同之处。由于篇
不同标准类型的比特币输出脚本的脚本结构
上图为bitcoin标准输出脚本各种类型态分别的组成结构,extractHash()这个功能会解析出输出脚本中的hash部分(上图绿色区块链,可能为公钥哈希或脚本哈希),对于不同类型的脚本,哈希前面都有可能还有bitcoin OP_CODE,在这边称为hash的prefix&postfix(上图橘色和蓝色区块链),下面将是上述结构统一整成一张图,作为比较。
比特币脚本结构分解
由此可知_output.slice(8, 3).concat(_output.extractHash())这样的做法,遇到P2PKH或P2SH型态的输出脚本时,并无法完整还原出正确的输出脚本,在这样的情况下,即使签名者发送出正确的交易,也永远不可能被验证成功,而根据tBTC的设计,签名者收到退款退回申请后,必须在6小时之内发送出赎回交易并成功被确认,迟迟无法验证会员签名者离线,因此也会将原本超额抵押的ETH返回给redeemer做补偿,但实际上BTC是有成功赎回的,等于redeemer白白拿走多余的ETH。
为什么现在才发现?
坦白说,tBTC团队本身需要付满大的责任,根据官方说法,他们原本只支持P2PKH这种地址,不过后来上了一个PR让赎回可以支持多种地址,此PR作者在提交消息里面写着
结果通过了所有当前测试,尽管回购中还没有针对非p2wpkh输出脚本的测试。
另外根据官方文章的描述,他们没有在测试链上测到赎回的部分(不确定原因),而他们测试链使用的钱包是P2SH地址,如果有测到,就应该会发现了。
其实还有更严重的问题被挖出
tBTC团队通过此事件进一步发现,甚至输出脚本组对了,仍然可能会被恶意攻击,原因出局在redeemer可能提交了一个不合法的比特币脚本,目前tBTC合约并没有另外检查脚本合法性,不合法的脚本想当然是不可能的上链,同样地超过6小时之后,签名者的抵押的ETH被清算,虽然攻击者确实也没有拿回BTC,却拿到价值更高的ETH。
影响
由于问题很快就被发现(因为很容易就撞到),而初始上线期间参与的signer主要是同一个人,因此所幸幸影响范围并不广。
总结
测试很重要!
测试很重要!
测试很重要!
Bitcoin在地址以及脚本的部分高度很高,开发时必须非常谨慎,需要先定义出支持哪一部分地址,并在入口层级就先挡掉不支持的型态进入,单元测试的部分要完整测到每一种辅助型态的各种情况,才能确保对各种型态的比特币脚本的支持度。
另外,利用验证输出脚本的方式作为依据有一些风险,这部分必须要相当了解比特币脚本运作方式以及应对未来OP_CODE的更动,个人是认为,除非有其他考量,否则验证地址会是比较实际的解法。
tBTC其实是有审计过的(ConsenSys Diligence),以结果来看,第一种可能是审计公司对比特币的细节敏感度不够高,第二种可能是没审到。从这次事件可以得到一个警讯,如果是做跨链的项目,必须要找两边都非常熟悉的审计公司去做完整的审查。
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。
AMIS如何透过自动调整交易矿工费来降低网络发生阻塞
当网络发生堵塞,交易迟迟不上链会发生什么问题呢?使用者或是钱包服务提供商,该如何减少这类情况的发生?本文将针对上述问题做探讨,并且介绍AMIS Wallet Service 目前针对发送交
原创文章,作者:掘金K,如若转载,请注明出处:https://www.20on.com/112617.html