编者按:本文来自以太坊爱好者,翻译校对:Ray&阿剑,作者:AodhganGleeson,Odaily星球日报经授权转载。本文的目的是为在以太坊生态中发送交易使用的各类技术,模式和机制提供一个指南。由于新技术层出不穷,本文也会随之更新,所以可以认为是未完待续的一个状态。针对这个公认的大课题,本文将包含以下内容:以太坊交易的简明介绍Gas的用途和gas代币元交易潜艇交易反事实合约实例化零确认交易批量转账基于短信的付款订阅付款通过预言机合约为批量交易节省Gas使用一次性地址进行多笔付款背景知识
以太坊是一个基于账户的系统,目前有两种账户:普通账户和合约账户。这两种账户都有自己的以太坊地址,交易计数器Nonce和余额。合约账户还额外拥有不可变的代码以及相应的存储空间。这里有一篇介绍这些基本概念的好文章。一个以太坊交易包含以下关键字段:Nonce,或者说交易计数器,即该账户主动发起的交易数量,从0开始计数gasPrice,决定了该笔交易需要支付的Ether数量gasLimit,即处理该交易所允许的最大gas数量目标地址,即接受该笔交易的对象,如为空,则该交易会创建一个新的合约交易金额,即发送的Ether数量数据,即可以是任意的一条文本消息,也可以是某合约的一次调用或者创建新合约的一段代码请注意,以上关键点在于没有“交易发起”地址,因为该地址可以从生成该笔交易哈希值签名的公钥-私钥对推导出来,其中交易字段采用了适当的RLP编码。Gas用途和Gas代币
站在一个很通俗的角度,区块链可以看成是一个共享数据库。每次从该数据库读取或者写入数据都需要花费gas以防止类似垃圾邮件的恶意攻击。具体来说,以太坊上执行的每个计算步骤都需要花费gas,以避免可能导致以太坊停摆的恶意攻击。每个操作码的gas开销都在以太坊黄皮书中有说明。但操作码的gas开销仍是一个热烈讨论的活跃话题,以太坊的社区成员们正在研究引入存储租金机制的可能性,甚至是gas和操作码的动态定价方案。在以太坊区块链中写入数据很贵,比如创建一个非空的存储单元需要花费20000gas,几乎与一次简单的Ether转账交易花费相当。作为缓解区块链数据存储暴涨的一种激励方案,以太坊协议会为清空不再使用的旧存储单元退还10000个gas。这个Ether的退还机制最多可以返还合约交易花费的一半gas。GasToken允许开发者简单而高效地利用这个退款机制,即通过gas的代币化,在gas价格低的时候囤货,然后在gas价格高的时候花掉之前储存的gas代币。最近确实有在一些交易所发现了一个没有正确设定交易gas上限的漏洞。攻击方法很简单:在交易所申请提现,然后将提现交易目标地址设置成一个攻击者部署的恶意合约,其默认fallback函数就会趁机铸造新的gasToken。元交易
《上海市浦东新区文物艺术品交易若干规定》通过:数字藏品催生艺术品交易新思路新业态:金色财经报道,据上海市人大常委会办公厅官方微信,《上海市浦东新区文物艺术品交易若干规定》经市十五届人大常委会第四十三次会议表决通过,并将于今年10月1日起施行。《若干规定》鼓励有条件的文物艺术品经营单位通过电子商务新业态、新模式,开展文物艺术品在线展示、交易、定制服务等活动。数字藏品催生艺术品交易的新思路、新业态。每件藏品在加密后会得到一个“数字编号”,即便外在形态一样,却也因其“唯一性”吸引了一票收藏爱好者。[2022/8/28 12:53:39]
元交易是这样一种发送交易的模式:发送方先对一个合法的以太坊交易签名,然后把该交易和签名通过链下传递的方式转交给一个中继方,该中继方愿意承担该笔交易的gas开销并最终发送交易到以太坊网络中。
-以太坊的技术宅们都喜欢抽象化-这种元交易模式很有用,因为发送方不再需要在发送账户中存有Ether,从用户体验角度这很有益处。我之前在这篇文章中提到过元交易及其在UX上的影响。元交易最终的目标地址一般都是某个以太坊合约,且在某种程度上,该合约知道,交易的签名方并不是交易实际的发送者。以太坊交易API的msg.sender字段会返回中继方的地址,但其很可能并没有代表签名方操作的权利,所以在这个场景下并没有太大意义。因此,许多元交易依赖链上的签名校验来保证签名方账户的确是在一份合适的白名单里面。潜艇交易
矿工抢跑现象在基于区块链经济的交易市场中是一个很难杜绝的老问题,即矿工可以对交易重新排序,随意裁剪或者让他们自己的交易插队来获利。潜艇交易试图通过极强的保密特性来提供矿工抢跑问题的一个解决方案。不仅仅是隐藏交易金额,潜艇交易会尝试完全隐藏该笔交易的存在。当然,如果一笔交易永远都被隐藏着,那也就没啥意思了。潜艇交易允许发送方在未来的某个时刻公开该笔交易,这也是称其为“潜艇”交易的缘由。
-通过使用潜艇交易,用户的交易就不会被矿工抢跑-用户提交一个包含加密承诺的交易,其中包含了用户希望发送给目标合约的若干应用数据,并在潜艇地址中锁定交易涉及的Ether或者代币,其中潜艇地址与一个全新的地址无异。锁定在该地址中的Ether或者代币只有目标合约可以解锁。通过在承诺交易中附加货币价值,我们保证了有效的经济约束来防止某些恶意用户选择性地公开承诺。只要承诺交易被成功打包并经过足够区块确认,用户就可以向目标合约公开其加密承诺,然后合约便会执行该笔交易中包含的应用逻辑。反事实合约实例化
Counterfactual一词源于哲学和思辩中的一个概念。一条反事实陈述是一连串有理有据的推理以及相应的结论,但是该陈述的前提是有意与事实相反的。除开这个与事实不符的前提,整个推理链条是合理的,所以如果前提正确,最终结论也会是正确的。应用到区块链交易场景,Conterfactual的逻辑不光会考虑区块链当前的状态,还会考虑如果某合约部署完成后,区块链的状态。
更具体来说,在合约部署之前就获取它的地址,这种模式被称作反事实合约实例化,这个理论由L4发表在他们的“反事实状态通道”论文中,并受到以太坊社区的广泛欢迎。目前,新的合约地址由以太坊操作码CREATE生成,并可通过合约的创建者账户地址以及创建者已经发出去的交易数量来明确决定,即sender和nonce字段会通过RLP编码然后经过Keccak256哈希算法生成新的合约地址。EIP1014引入的SkinnyCREATE2操作码更进一步,允许用户与链上尚不存在的地址进行交互;虽然该地址上还没有代码,但可以保证它最终只可能包含通过一段特定的初始代码生成的合约逻辑。与CREATE操作码一般使用sender-nonce然后哈希得到合约地址不同,CREATE2操作码使用的是如下地址生成公式:keccak256(0xff++address++salt++keccak256(init_code)))。这种模式,对于涉及与尚不存在的合约进行交互的状态通道场景,尤其重要。它让以太坊主链可以成为争议层,并且不需要考虑合约部署的真实开销。类似地,这种模式在已知功能将创建新地址的场景也可以使用,比如这里的借贷还款地址。零确认交易
零确认交易源于BitcoinCash社区,目前仍是一个有趣但尚未经过证明的研究领域,在这样的一个区块链网络中,出块时间实质上可能更加不利于用户体验。零确认交易的发送方需要提交一个保证金,如果有双花行为,发送方就会损失掉该保证金。在比特币现金中,双花行为可以通过UTXO的输入项重用被检测到。任何人都可以提交找到的两笔双花交易,然后得到保证金的奖励。在以太坊的账户网络中,不同于使用类似比特币的UTXO,我们可以检查同一发送方是否重用了同一个nonce。比如一个已部署合约提供一个reportDoubleSpend方法,该方法接受两个待完成的已签名交易,然后合约会检查其发送方和nonce,如果相等,就会把保证金奖励给方法调用者。原理很简单:如果保证金数额足够大,这对于交易发送方而言,就是防止其作弊的一个有力武器,因为他们有可能损失缴纳的保证金。这种交易类型被认为最适合用于小额一次性的单笔支付场景,因为有一系列针对该场景的潜在攻击模式存在。批量转账
跟ERC20代币交互的一个主要问题在于,一般需要两次不同的交易:一次是调用代币合约的approve方法,另一次才是真正调用目标合约使用代币完成特定逻辑。这种模式就会产生非原子性交易的一系列问题。最简单的情况就是,如果doSomethingForTokens调用交易失败了,之前的approve调用不会回滚,即approve方法允许合约支配的代币额度仍然成立。
-ERC20代币合约的approve和transferFrom方法是非原子性的-Limechain实现了一种特殊的批量转账方法。借鉴元交易中的链上签名校验原理,失败的doSomethingForTokens调用交易会回滚相应的approve调用,从而改善了ERC20代币原本approve和transferFrom方法的非原子性。基于短信的付款
CoinText可能是最有名的基于短信的密码学货币支付服务商,目前专注提供比特币现金的交易。这种付款机制对于发展中国家和地区的移动设备尤其有用。Eth2也已经在以太坊上部署了类似的技术,它可以通过传统的基于移动应用的以太坊钱包来工作。
-eth2.io的基于短信的加密数字付款方案-这个特定方案采用了一个托管合约。交易发送方生成一个临时的公私钥对,然后往托管合约存入Ether,该笔转账中附带之前生成的临时公钥。私钥则通过随机生成的对称密钥加密,然后密文通过链下方式发送给某个中心化的校验服务器。提现时,如果接收方手机号码校验成功,校验服务器就会把密文发给接收方,接收方可以解密,然后对提现交易消息签名,托管合约随后可以对该签名进行校验,确认是由临时私钥完成的签名。中心化服务器用来对手机号做验证并传递秘钥,但是Eth2的服务器无法控制锁定在托管合约中的Ether。如果中心化服务器被攻击了,付款交易会失败,但是Ether仍在托管合约中。如果此时想拿回锁定的Ether,发送方可以通过调用托管合约取消该笔付款。订阅付款
基于可选择退出的订阅服务付款是Web2.0时代互联网服务的主流变现方式,比如Spotify,Netflix,Headspace和Tinder都是基于订阅付款构建其商业收入模型。密码学货币中的订阅付款概念也不是新东西,在比特币中,nLocktime字段就可以用来保证一笔已签名的交易在指定的区块高度之前不会被打包。但在以太坊上,用于未来支付的预签名交易意义不大,因为账户的nonce会随着该账户不停发出交易而增长,会导致预签名时所用nonce偏小,进而导致交易无效。幸好,以太坊的图灵完备性提供了一个解决办法:有一些针对重复订阅类型交易的架构方案。这些架构在保证金,用户体验复杂性,可选功能,gas开销和可延展性方面有不同的权衡取舍。基于预言机的方法调用
另一种更加特殊的交易发送方式是使用预言机服务,比如Oraclize,以期通过适当的中心化来换取gas使用量的减少,可以参见此文。
-使用Oraclize减少常量合约调用的gas使用量-这种类型适用于非交易型的方法调用。已经与以太坊主网同步的节点,可以通过以太坊JSON-RPC的eth_call接口来调用上述方法。只要继承了usingOraclize,在你的合约中就可以使用Oraclize的oraclize_query方法进行常量查询。另外,你的合约里面还必须定义一个__callback(bytes32queryId,stringresults)的回调函数,Oraclize查询会调用该函数并保存查询结果。与调用Oraclize相比,直接进行链上查询来获取和计算这些状态常量可能更加昂贵。使用一次性地址进行多笔付款
如背景知识中介绍的,交易字段中并没有“发起地址”。这个地址可以通过ecRecover函数计算得出。那么问题来了:我们能不能在交易签名中任意填入我们想要的数据?事实表明,有一半的签名是正确的,即ecRecover仍然返回一个合法的公钥。由于我们无法控制生成的地址,那么我们通过设置字段值,其实是在构建这样一个交易:该交易可以花费看上去是一个随机生成的地址中的余额。如果我们创建了这样一笔交易,并给生成的地址充值了若干Ether,那么该笔交易就可以像一般交易一样执行。这样我们实质上创建了一个一次性的地址,因为其中的余额只能被一笔交易使用。如果我们以某种可预测的方式选择交易签名中的字段值并公布该笔交易,我们就可以向任何人证明,发给交易发送方地址的金额,只能被该笔交易使用,而不能被其它任何交易使用。
如上图所述,该场景尝试发送交易至11140个目标地址,由一系列发送Ether至多个地址的交易组成,每个交易发送到110个地址,其中发送方的地址通过上述方法生成。对于签名字段,我们填入‘0xDA0DA0DA0…’?,这是一个可预测的值,这样我们确定,没有人能拿到这些签名所对应地址的私钥。这就创建了一批拥有“一次性地址”的交易,这些地址可以用来给相应交易提供所需交易金额。但104个要签名的交易对于受托自然人而言还是太多了,所以我们重复一次上述过程,形成一个级联结构:我们先构造104笔交易,每笔交易都有其对应的唯一地址,然后再构造一笔发送Ether到对应的104个地址的转账。通过验证,代码确实可以按照预期运行,那么任何人就可以这些构建好的交易发送到以太坊网络中,整个过程就像多米诺骨牌一样自动进行了:名单上的11400个地址都会收到Ether,但我们仅仅用了一次人工签名。以太坊上完成交易居然有这么多不同的方式!!
郑重声明: 本文版权归原作者所有, 转载文章仅为传播更多信息之目的, 如作者信息标记有误, 请第一时间联系我们修改或删除, 多谢。