imtoken正版官网|以太坊怎么交易

作者: imtoken正版官网
2024-03-08 19:24:37

史上最全以太坊“新手入门”攻略 - 知乎

史上最全以太坊“新手入门”攻略 - 知乎切换模式写文章登录/注册史上最全以太坊“新手入门”攻略软云存储IPFS行业的比特大陆一、什么是以太坊?以太坊能做什么? 简单来讲,以太坊(Ethereum) 类似于区块链版的安卓、iOS系统,一个区块链APP平台。以太坊是一个为去中心化应用(DApp)而生的全球开源平台。名字来源与 Ether (以太) 和后缀 ruem (希腊语义是“石油”),国内的早期社区成员将其翻译成“以太坊”。 以太坊是去中心化的、可以运行可转移计算和数据的自洽经济系统,一个去中心化的区块链平台,用于构建去中心化应用程序(DApp),以太币(Ether)是该平台所使用的加密货币。 以太坊可以轻松创建智能合约,自行执行代码,开发人员可以利用这些代码来处理各种应用程序。 以太坊几乎可以用于任何类型的交易或协议,其成本比传统的替代方案要低,例如银行卡支付,PayPal 和投票等,并且全程采用去中心化、去信任(无需中介)、安全有效并且抗审查的形式。 以太坊因其独特的可编程设计获得了开发者们和巨头的认可,至今全球已经有数千种基于以太坊的APP和数字货币;2017年,以摩根大通、微软、英特尔为代表的20多家知名企业甚至联合成立了“企业以太坊联盟”,至今已有超过150多家公司和机构加入了这一联盟。二、以太坊有什么价值? 以太坊比单纯的加密货币更有效用。通过以太坊,用户可以创建任何去中心化应用程序(即DApp)和智能合约,理论上可编程的以太坊可以用于任何经济或治理活动。 在以太坊上,你可以通过编写代码管理数字资产、运行程序,更重要的是,这一切都不受地域限制。 以太坊为全球金融系统打开了一扇大门,用户只需要通过互联网就能够以去信任化的方式访问应用程序、产品和服务。每一个人都可以与以太坊网络进行交互,亲自参与到这种数字经济形式中,而不需要第三方。 人们可以使用智能合约来为项目众筹资金、公司可以在区块链上运用智能合约进行股票发行、银行等金融机构可以用它来管理贷款收发、保险公司可以用它来实现自动理赔等等等等,甚至任何现实金融交易都可以被改造到区块链上进行,这些都是区块链的功劳。 通过以太坊平台上的治理应用程序和系统,甚至有可能消除国家之间由于边界而产生的障碍,创建一个更加开放、包容和公平的人类社会。三、以太坊是如何运作的? 以太坊区块链的结构与比特币十分相似,因为它是整个交易历史的共享记录。网络上的每个节点都存储了这个历史记录的副本。 以太坊与比特币的最大区别在于,除了所有以太坊交易外,它的节点还存储着每个智能合约的最新状态。对于每个以太坊应用程序,网络都需要跟踪“状态”或所有这些应用程序的当前信息,包括每个用户的余额、所有智能合约代码以及它们的存储位置等。四、谁创造了以太坊? 比特币诞生四年后,一位19岁的年轻人设想了一个基于这一制度的新平台,努力完全改变互联网。他便是来自多伦多的程序员,以太坊之父、天才少年——维塔利克·布特林(Vitalik Buterin),简称V神。维塔利克·布特林(Vitalik Buterin)图片来源:维基百科1994年出生的他可谓天赋异禀:4岁就能玩转Excel;12岁就自己编写游戏给自己玩;17岁联合创办《比特币杂志》开始科普比特币;19岁从滑铁卢大学辍学发布以太坊;20岁挤下Facebook创始人扎克伯格获得世界科技奖;24岁被俄罗斯总统普京接待,登上《财富》杂志40岁以下影响力人物榜……不仅如此,他还自学了多国语言,甚至能讲一口流利的中文……他的才能碾压了地球上所有的同龄人。2011年,Vitalik Buterin开始对比特币产生兴趣。他在同一年共同创办了在线新闻网站比特币杂志,撰写了数百篇关于加密货币世界的文章。2013年,他发布了可以运行智能合约和去中心化应用程序的以太坊平台白皮书。他的传奇经历和以太坊的成功,使人们开始崇拜地称他为“V神”。据猜测,V神约持有50万个以太坊,而这些年以太坊价值的暴涨,也使他名利双收,身价一度突破千亿。V神也正式站上C位,成功封神。五、什么是DApp? 得益于区块链技术,以太坊没有中心服务器,所以在以太坊上运行的APP不存在崩溃、死机的可能,数据也不会泄露,甚至不能被关闭!它跟区块链一样也是分布式和去中心化的,所以又叫分布式应用(Decentralized Application,简称DApp) DApp 一旦被“上传”到以太坊,它们将始终按照编好的程序运行。 这些应用程序可以控制数字资产; 同时还是去中心化的,这意味着没有任何单一实体或个人可以控制它们。 目前,全世界有成千上万名开发者正在以太坊上构建应用程序、发明新的应用程序,其中有许多现在已经可以使用:加密货币钱包:让你可以使用 ETH 或其他数字资产进行低成本的即时支付;金融应用程序:让你可以借贷、投资数字资产;去中心化市场:让你可以交易数字资产,甚至就现实世界事件的“预测”进行交易;游戏:你可以拥有游戏内的资产,甚至可以由此获得现实收益;六、什么是智能合约? 根据区块链可编程的特点,人们可以将合同变成代码的形式放到区块链上,并在约定的条件下自动执行, 这就是所谓的智能合约。 智能合约的概念至少可以追溯到1995 年,尼克· 萨博( Nick Szabo) 提出了如下定义:“一个智能合约是一套以数字形式定义的承诺, 包括合约参与方可以在上面执行这些承诺的协议。”他还探讨了涉及到合同协议等各个领域中,智能合约的潜在用途,例如信用体系、支付流程和版权管理。 我们可以简单地认为,智能合约就是一种“ 程序”, 只是这种“ 程序”处理的是人与人之间的权利和义务的约定。 当满足某些条件时,它则执行特定任务。因此,智能合约系统通常遵循“if ... then ...”语句。但是,即便智能合约成为一种主流的技术,但智能合约既不是法定的也不是智能化的。它们只是在分布式系统(区块链)上运行的一段代码。 实质上,区块链智能合约支持创建无需信任的协议。这意味着执行合约的双方可以通过区块链做出承诺,而无需相互了解或取得相互信任。合约内容经双方确认后,如果没达到触发条件,合约将不会被执行。除此之外,使用智能合约可以消除对中介的需求,从而显著降低运营成本。七、以太坊与比特币有什么区别? 与比特币相似,以太坊也采用POW机制,通过矿工挖矿来产生新的以太坊。不同的是,以太坊是一个可以编程的区块链,它允许任何人在上面创建去中心化的APP、编写智能合约和发行属于自己的数字货币。 不同于比特币的货币定义,以太坊释放了区块链前所未有的潜力,通过一系列的重新设计,包括虚拟机(EVM, Etheruem Virtual Machine)、账户系统,在其上可以运行智能合约。智能合约的概念是由Nick Szabo(尼克·萨博)于1997年提出的,即自动执行的合约形式。 多年来,虽然比特币协议也一直支持智能合约,但智能合约却经以太坊联合创始人Vitalik Buterin之手,从而大受欢迎。八、如何使用以太坊? 与比特币转账类似,要在以太坊网络中进行交易,以太坊是不可或缺的。以太坊是以太坊网络的原生货币。 这是一种在以太坊网络发行、类似比特币的数字货币。 你可以通过以下渠道获取以太坊:在一个加密货币交易所购买以太坊和你附近的人兑换以太坊通过挖矿获取以太坊 此外,类似比特币钱包,你也需要一个专门保存以太坊的以太坊钱包。市面上现在有各种各样的以太坊钱包,还有许多基于以太坊的应用程序可以用。 以太坊用户可以将以太坊储存在以太坊钱包中,也可以与以太坊网络上的智能合约进行交互。许多钱包都有这些功能。钱包是一种应用程序,可以便捷地保存和传送 ETH,同时可以通过钱包与以太坊上构建的应用程序进行交互。 以太坊网络中发生的每笔交易都需要一定数量的gas,gas是用于度量处理交易所需计算能力的单位。帮助验证信息真是下要付出算力成本处理交易并将其打包在区块中,理应获得相应的补偿。在以太坊系统中,这就要通过在每次交易中设定gas价格来完成,gas以Gwei(1 ETH = 1,000,000,000 Gwei)作为单位。 举个例子:用户将ETH从一个帐户发送到另一个帐户需要花费21,000 gas,如果将gas价格定为1 Gwei,则此交易花费0.000021 ETH。九、以太坊有什么优缺点?优点以太坊允许用户在区块链上使用完整的编程语言,在网络上执行更复杂的智能合约,而不需要依靠任何第三方服务以太坊可为其他产品和服务平台提供强大的生态系统以太坊拥有一个强大的发展路线图(3-5年),这意味着社区对未来几年的预期有明确的标准有很多公司参与改善以太坊以外的基础。在以太坊企业联盟(EEA)和Hyperledger团队批准其第一个以太坊项目之间,有数十家企业组织致力于以太坊的改善生态系统。除了比特币之外,其他区块链还没有得到如此多商业社区的大力支持缺点因为以太坊是一个平台,它永远不会像专门设计成加密货币的其他一样有效。比特币只是真正的分类帐,但是以太坊正在试图成为一个分类账/超级计算机/智能合约产生器/等等,为更多的用户提供服务。这种复杂性使其具有了灵活性,但是对于以上任何一种用例而言,都没有进行过深度优化。由于以太坊发展路线的原因,以太坊的一些重大升级包括将工作证明转移到证明权益的平台。如果这种转换不顺利,可能会在架构中引入一些关键问题并导致系统崩溃。相信以太坊团队可以确保这一切都不会发生,但这是一种风险。缺乏帮助开发人员的教程或文档是成为以太坊开发人员的严重障碍。你所搜索到的大多数教程都是过时的,或者只是教授对技术的概念性理解,或者只是一个基本的“hello world”教程,没有任何实质性内容。发布于 2021-06-25 18:22​赞同 17​​1 条评论​分享​喜欢​收藏​申请

以太坊怎么买卖交易?ETH买卖交易操作流程

以太坊怎么买卖交易?ETH买卖交易操作流程

首页

币园地

交易典籍

股票问答

主页 > 币园地 > 币圈知识

以太坊怎么买卖交易?ETH买卖交易操作流程

作者:小编 • 2024-03-06 19:14:58 •阅读

OKX欧易APP

全球顶尖交易所,注册即领最高¥3000元数字盲盒

APP下载  

官网注册

以太坊是当前最常用的智能合约平台之一,它提供了一个去中心化的区块链网络,可以在其中进行交易。在这里,我们将介绍如何在以太坊上进行买卖交易。步骤一:安装交易所欧易OKX 全球三大交易所之一,注册领50 USDT数币盲盒!官网注册APP下载 欧意app是一家去中心化数字资产交易平台,提供安全、可靠、便捷的区块链数字资产交易服务步骤二:购买以太币或其他代币在钱包中存有一定量的以太币或其他代币后,你就可以去交易市场进行买卖交易了。首先需要购买一定的以太币或其他代币。有很多交易市场提供以太币交易,其中加密货币交易所比较常用,例如:Binance、Coinbase、Kraken和Bitfinex等。步骤三:选择交易市场进行交易选择一个合适的交易市场进行交易,打开该交易市场的网站,并进行注册。一般需要注册邮箱、手机等常规信息以将账号与用户绑定。步骤四: 准备提现地址交易所为了保证安全会将你的资产保存在交易所的钱包内,购买你要交易的代币后,需要进行提现操作将代币提到你的以太坊钱包内。首先需要在以太坊钱包中创建一个收款地址,并复制该地址。然后再交易所进行提现时,粘贴生成的地址到提现地址这一栏即可。步骤五:交易完成以上步骤后,你就可以选择交易对进行交易了。选择一个合适的代币进行交易,将以太坊转换成你选择的代币即可。交易完成后,你可以在以太坊区块浏览器或者钱包中查看交易记录和余额。总结通过以上五个步骤,你就可以在以太坊上进行买卖交易了。需要注意的是,区块链上的交易是不可更改的,所以请在交易时务必仔细核对相关信息,谨防诈骗和误操作。

币安 Binance

选择币安、探索无限可能

APP下载  

官网注册

火币 Huobi

官网注册

老牌交易所,交易用火币

Gate芝麻

官网注册

超过1700种加密货币

 youtube去水印下载

 夸克会员码:uBb8/i_r#e

相关推荐

比特币哪里兑换人民币最划算?BTC怎么兑换人民币?

比特币永续合约怎么玩?一文搞清楚比特币永续合约玩法规则

比特币的购买方式有几种?BTC怎么买?

以太坊生态有多繁荣:八岁生日加密行业共享的巅峰时刻

2024年如何质押以太坊?如何成为ETH节点

如果以太坊 (ETH) 价格达到5000会怎样?有机会吗

搜索干货

热门文章

纸飞机TG如何解除成人敏感内容限制?

2023年08月22日

纸飞机收不到验证码怎么解决?一招解决

2023年10月17日

tg如何添加好友?电报飞机添加好友教程

2023年08月22日

币圈著名519事件|一文了解始末

2023年04月28日

MetaMask小狐狸钱包添加或更改自定

2022年12月23日

推荐文章

探索Web1、Web2及Web3的区别和

2023年05月23日

经典文章

加密货币的钱包会不会跑路?(区块链钱包是

2023年05月10日

比特币为什么具有稀缺性?(比特币稀缺和价

2022年12月21日

什么是稳定币,它们是如何运作的,它们安全

2023年02月27日

了解山寨币是什么:定义、运作方式和示例

2023年03月08日

比特币区块链对石油行业的革命?

2022年12月18日

首页

币园地

股票问答

粤ICP备2022105968号

联系我们

Q Q: 510662654

微信号:ATM6086

工作日:9:30-18:30,节假日休息

加入社群

欧易注册

首页

币安注册

Gate芝麻注册

购买以太坊(ETH)及存入钱包教程 - 知乎

购买以太坊(ETH)及存入钱包教程 - 知乎切换模式写文章登录/注册购买以太坊(ETH)及存入钱包教程CointalkEverything about crypto你可以选择从任意一个支持美元直接购买ETH的交易所进行交易,如gemini.com, kraken.com,这里我们以美国GDAX交易所来举例,如何从零开始开户、购买并储存ETH:开户:1. 进入www.gdax.com, 点击右上角的Create Account.2. 输入你的姓名、邮箱、密码,选择你所在州,勾选同意服务条款后点击继续。系统将会发送一封确认邮件到你的邮箱。点击邮件中的确认链接后,会进入如下页面。3. 点击I Accept,系统会要求你输入自己的手机号以完成2FA认证来确保账户安全。4. 输入手机短信上显示的6位验证号来绑定2FA后,会进入个人信息页面:请如实填写,即可完成注册。购买:1. 成功登陆后,你会看到如下界面:2. 点击Deposit,你会看到多种汇款方式,到账最快的是Wire Transfer,一般当日即可完成,并且没有限额,是我们推荐的一种方式。你也可以在连接自己的银行账户后使用银行转账的方式,一般需要4~5个工作日来处理,并且每周限额$10000 ~ $15000左右。需要说明的是,Wire Transfer需要$10的手续费,而银行转账没有手续费。3. 美元到账后,你就可以下单购买需要的虚拟货币。GDAX平台支持比特币(BTC),ETH,和莱特币(LTC)使用美元直接购买。下单方式有Market(市价),Limit(限价),Stop(止损)。我们推荐使用Limit Order,在略低于当前成交价的位置下单,以期获得较好的成交价格以及较快的成交速度。4. 交易完成。当你已经进行到这一步,那恭喜你,已经成功的购买了ETH。你可以选择把它们留在GDAX平台上,但更多的时候你应该想要转发给自己的钱包来保存。下面我们就来简要介绍一下钱包的使用。钱包:可供选择的钱包有很多种,包括Mist, Jaxx, MetaMask, imToken等等,我个人最喜欢的是imToken,是支持iOS和Android的移动钱包,非常简单易用,下面就以imToken在iOS平台上举例教学。创建钱包:1. 在App Store中搜索imToken并下载。第一次打开后请点击“创建钱包”。2. 根据指示,输入钱包名(随意选择)、密码(非常重要,也是你的交易密码,遗失后不能找回)、确认密码后,点击“创建钱包”,完成钱包的创建。3. 点击“备份钱包”,导出钱包的“助记词”,这是一串英文单词,请务必将其记录并放在安全的地方,任何拥有这一串英文单词的人都可以获得这个钱包的使用权。自此,你已全部完成这个钱包的准备工作。下面就是将GDAX交易所上购买的ETH转入你的钱包了。转入ETH至钱包:1. 打开imToken钱包,点击钱包名下面的一串0x开头字符,会看到如下界面:aWJhbjpYRTg5VFY2RkE5QjFBTFpWWkNNRjRNN01RQVUyVFEwRUdTUT9hbW91bnQ9MCZ0b2tlbj1FVEg= (二维码自动识别)这是你的ETH地址,点击“Copy Wallet Address”将地址复制到剪切板。2. 回到GDAX界面,在Deposit的右边可以看到Withdraw,点击Withdraw后,选择”ETH Address”, 输入想要提取ETH的数量,在地址栏复制刚刚拷贝好的你的钱包地址,再次确认地址无误后,点击Withdraw funds. 请注意,如果地址填错,你的ETH将永久丢失,无法找回。3. 几分钟后,你的ETH便存入了你的imToken钱包。现在你就可以开始投资ICO了!联系我们:邮箱:contact@cointalk.fyiTelegram: https://t.me/cointalkfyi微信:NYcointalk编辑于 2017-09-22 10:22以太币​赞同 27​​7 条评论​分享​喜欢​收藏​申请

以太坊的基本:交易 · Ethereum Community Network

基本:交易 · Ethereum Community Network新闻资讯零时学院开发者门户生态漫游ΞSearch by 以太坊的基本:交易本文剖析了以太坊交易中的元数据、缓存和数据三个重要组成部分,手把手地教会读者看懂一笔交易的数据HHaym       2022-09-23作者 | Haym

来源 | @SalomonCrypto

发送了 ETH?有为 AMM 提供流动性?部署了新的合约?你所做的任何事都会在世界计算机上留下链上记录。想知道你的交易中有些什么吗?

以太坊计算中逐个原子单位的指南

以太坊是一台世界计算机:一个存在于上千台计算机网络之间的全球共享基础设施。

用户可以通过钱包(比如 MetaMask)与以太坊进行交互,钱包可以创建和发送交易到网络中。一旦接收了交易,它就会被写入区块中。

额外的益处:对数据进行哈希计算(应用哈希函数)

哈希函数:这是一段用于将任意数据量转换为一个压缩、统一数值的代码。它的输入数据可以是任意长度,但输出数据的长度则是一样的。

(好处)哈希函数不能反向运行。

cr. @SalomonCrypto

一笔以太坊交易由三个部分组成:

元数据(metadata),包括发送/接受的 ETH 金额、gas 详细信息以及签名数据

缓存(cache),交易预计会使用的账户和私钥的列表。

数据,交易的 payload(智能合约代码或者 API 调用)

元数据 —— 交易相关信息

以下的图片展示了所有元数据字段。我们会在接下来探讨其中不显著的部分。

chainid —— 由 EIP-155 提出,用来保护链不受 ETC 的重放攻击。

type —— 这里有两种类型:一个新的合约(0x0)还有其他所有合约(0x2)。EIP-2718 提出了一个封装功能(0x2),让更多不影响以太坊核心规范的类型得以使用。

nonce —— 从特定地址发送过来的交易数量。一旦交易打包到区块上,钱包的 nonce 值就增加了。避免受到重放攻击。

to —— 接受交易的地址(钱包或智能合约)

value —— 将要转账的 ETH 数额。请注意 —— 这里只计算 ETH,不计算其他代币。

gas —— 这笔交易所使用的 gas 单位

maxFeePerGas —— 创建交易的用户愿意支付的最高费用(每 gas 要支付 WEI。译者注:WEI 是 ETH 的最小单位,1 个 ETH 相当于 10 的18次方 WEI。)它包括了基础费用和优先费。

maxPriorityFeePerGas —— 创建交易的用户在基础费用(base fee)之外愿意支付的最高优先费(每 gas 要支付的 WEI)。这笔费用会直接支付给矿工/验证者,作为激励打包的小费。

gasPrice —— 这笔交易需支付的每 gas 单位的成本

(r, s, v)—— 构成创建该交易的用户签名的三个值。它们可以用于验证用户是否在此交易上 EVM 执行之前许可了这笔交易。

更多信息,可以自行查阅:Elliptic Curve Digital Signature Algorithm (ECDSA)

缓存

这个部分包括了访问列表(accessList),它是交易将用到的地址和私钥的列表。这笔交易还可以使用该列表以外的资源,但成本会比较高。

访问列表是由 EIP-2929 提案提出的,让客户端可以获取/缓存交易期间的数据。

现在,通过访问列表获取地址和私钥数据的折扣是 9 折。但这个折扣会随着未来以太坊支持更多轻客户端而变得更多。

数据 —— 交易中传输的 payload 数据

数据可以用三种方式进行:

ETH 转账 —— 空白

智能合约 API 调用 —— 函数和参数的名字

新的智能合约 —— 智能合约的代码

输入字段的数据以二进制形式记录,但它可以转译成人类可读的形式。

输入字段存在于链上,但它不是 EVM 状态的一部分。它只是在交易期间为合约提供数据,无法被以太坊追踪到,也不能在共识层上使用。

EVM 只能使用在此交易中提供的数据;它无法查看过去的交易。

这一特质对于想要将历史数据写入以太坊区块链(比如,用于稍后的手动检索)但不考虑直接访问 EVM 的应用程序来说十分有用。

Rollup 是最早充分利用这个想法的一种应用程序。

有时间我们会谈谈 Rollup。现在,Rollup 依靠着这样一种现实:将数据写入输入字段比直接写入以太坊 EVM 状态中要相对便宜。

你现在可以看啦!这就是一笔以太坊交易的样子!

ECN的翻译工作旨在为中国以太坊社区传递优质资讯和学习资源,文章版权归原作者所有,转载须注明原文出处以及ethereum.cn,若需长期转载,请联系eth@ecn.co

进行授权。Ethereum Community Network以太坊社区网络 订阅 Ethereum Community Network以太坊社区网络 订阅

首页 | ethereum.org

ethereum.org跳转至主要内容学习用法构建参与研究搜索​​​​语言 ZH帮助更新此页面本页面有新版本,但现在只有英文版。请帮助我们翻译最新版本。翻译页面没有错误!此页面未翻译,因此特意以英文显示。不再显示Ethereum欢迎来到以太坊以太坊是由社区驱动的技术,为加密货币以太币(ETH)和成千上万的去中心化应用程序提供动力。探索以太坊开始体验ethereum.org 是你进入以太坊世界的门户。这项技术日新月异,因此指南会有所帮助。如果你想深入了解,我们有以下建议。选择钱包你可以通过钱包连接到以太坊并管理资金。获取以太币ETH 是以太坊的货币 – 你可以在应用程序中使用它。使用去中心化应用程序Dapps 是由以太坊提供支持的应用程序。看看你可以做什么。开始构建如果想在以太坊里开始编写代码,我们有文档与教程可供参考,你亦可在开发者门户中查看更多信息。什么是以太坊?以太坊是数字货币、全球支付和应用程序的技术之家。以太坊社区已经创建了蓬勃发展的数字经济,为创造者在线上获取收入开辟了大胆而创新的途径,且不止于此。它面向所有人开放,无论身处何处,只需互联网即可。什么是以太坊?关于数字货币的更多信息更加公平的金融系统今天,数十亿人无法开设银行帐户,还有一些人的支付帐户被封锁。而以太坊的去中心化金融 (DeFi) 系统永不停息,永无歧视。只需有互联网连接,你就可以在世界任何地方汇款、收款、借款、赚取利息甚至流动资金。探索去中心化金融 (DeFi)资产互联网以太坊并非仅限数字货币。你拥有的任何东西都可以采用非同质化代币 (NFT) 来表现、交易和使用。你可以将艺术品代币化,并在每次重新出售时自动获得使用费。或者,你也可以用所有物的代币来贷款。不断开辟新的可能。关于非同质化代币的更多信息开放式网络今天,我们通过放弃对个人数据的控制权来获得“免费”的互联网服务。以太坊服务则默认开放 - 只需要钱包即可。这些应用不仅免费,易于设置,由你掌控,而且无需个人信息。探索开放式网络关于钱包的更多信息代码示例你自己的银行你可以用自己编写的逻辑来建立银行。自己的货币你可以创建代币,并在应用程序之间转账和使用。JavaScript 以太坊钱包你可以使用现有语言与以太坊及其他应用程序进行交互。开放、无需许可的 DNS你可以将现有的服务重构为去中心化的开放应用程序。全新发展领域以太坊及其应用程序具有透明和开源性质。你可以分叉代码并重新使用已由他人建立的功能。如果不想学习新语言,你可以直接使用 JavaScript 和其他现有语言与开源代码进行交互。开发者门户以太坊现状最新的网络统计数据以太币质押总数当前质押的用来保护网络安全的以太币总量。3121万 30d90d今日交易过去 24 小时内,网络成功处理的交易笔数。121.9万 30d90d去中心化金融中锁定的价值(美元)以太坊数字经济及去中心化金融 (DeFi) 应用程序中的资金量。US$1330亿 30d90d节点以太坊由全球数千计志愿者运行,他们被称为节点。6,958 30d90d加入 ethereum.org 社区加入我们的 Discord 服务器(opens in a new tab),与近 4 万名成员一起交流。参加我们每月举行的社区电话会议,获取有关 Ethereum.org 发展的令人兴奋的最新消息和重要生态系统新闻。你将有机会提出问题、分享想法和提供反馈——这是你成为蓬勃发展的以太坊社区一员的绝佳机会。☎️ Ethereum.org Community Call - March 20242024年3月28日 16:00(UTC)Join Discord(opens in a new tab)添加到日历(opens in a new tab)即将召开的电话会议2024年3月21日⚙️ ethereum.org Office Hours [S3E1](opens in a new tab)2024年3月13日 QA session - ethereum.org portal(opens in a new tab)之前的电话会议2024年2月28日 QA session - ethereum.org portal(opens in a new tab)2024年2月29日☎️ Ethereum.org Community Call - February 2024(opens in a new tab)2023年11月1日 QA session - ethereum.org portal(opens in a new tab)2024年2月14日 QA session - ethereum.org portal(opens in a new tab)探索 ethereum.org提升你对网络升级的理解以太坊路线图由相互连接的升级组成,旨在使网络更具可扩展性、安全性和可持续性。企业级以太坊查看以太坊如何开启新业务模式,降低你的成本,并使你的业务经得起未来的考验。以太坊社区以太坊由社区驱动。它由来自不同背景和兴趣的人组成。看看如何加入!为 ethereum.org 贡献力量这个网站是开源的,有数百个社区贡献者。你可以对这个网站上的任何内容提出编辑建议,建议出色的新功能,或者帮助我们排除错误。关于贡献力量的更多信息GitHub(opens in a new tab)网站最后更新: 2024年2月16日(opens in a new tab)(opens in a new tab)(opens in a new tab)使用以太坊查找钱包获取以太币Dapps - 去中心化应用二层网络运行节点稳定币质押ETH学习学习中心什么是以太坊?什么是以太币 (ETH)?以太坊钱包Gas fees以太坊安全和预防欺诈措施什么是 Web3?智能合约以太坊能源消耗以太坊路线图以太坊改进提案 (Eip)以太坊的历史以太坊白皮书以太坊词汇表以太坊治理区块链桥零知识证明测试中心开发者开始体验相关文档教程通过编码来学习设置本地环境生态系统社区中心以太坊基金会以太坊基金会的博客(opens in a new tab)生态系统支持方案(opens in a new tab)以太坊漏洞悬赏计划生态系统资助计划以太坊品牌资产Devcon(opens in a new tab)企业级应用主网以太坊私密以太坊企业级应用关于ethereum.org关于我们工作机会参与贡献语言支持隐私政策使用条款缓存政策联系我们(opens in a new t

交易 | ethereum.org

ethereum.org跳转至主要内容学习用法构建参与研究搜索​​​​语言 ZH帮助更新此页面本页面有新版本,但现在只有英文版。请帮助我们翻译最新版本。翻译页面没有错误!此页面未翻译,因此特意以英文显示。不再显示Change page概述基础主题以太坊简介以太币简介去中心化应用程序简介Web2 与 Web3 的对比帐户交易区块以太坊虚拟机 (EVM)操作码Gas费用节点和客户端运行节点客户端多样性节点即服务节点架构轻客户端归档节点引导节点网络共识机制工作量证明矿工挖矿算法Dagger-HashimotoEthash权益证明Gasper弱主观性认证权益证明机制的奖励和惩罚权益证明攻击与防御密钥权益证明与工作量证明提出区块权益正明常见问题以太坊堆栈堆栈简介智能合约智能合约语言智能合约结构智能合约库测试用智能合约编译智能合约部署智能合约验证智能合约升级智能合约智能合约安全性智能合约形式化验证可组合性开发网络开发框架以太坊客户端APIJavaScript API后端APIJSON-RPC数据和分析区块浏览器存储集成开发环境 (IDE)编程语言DartDelphi.NETGolangJavaJavaScriptPythonRubyRust语言高级链桥标准令牌标准ERC-20:同质化代币ERC-721:非同质化代币 (NFT)ERC-777ERC-1155ERC-4626最大可提取价值 (MEV)预言机缩放乐观卷叠零知识卷叠状态通道侧链以太坊 Plasma 扩容解决方案Validium数据可用性网络层网络地址门户网络数据结构与编码默克尔前缀树递归长度前缀编码 (RLP)简单序列化 (SSZ)Web3 密钥存储定义设计基础设计和用户体验简介交易上次修改时间: , 2023年12月8日查看贡献者在本页面前提条件什么是交易?data字段交易类型关于燃料交易生命周期视频演示Typed Transaction Envelope 交易延伸阅读相关主题交易是由帐户发出,带密码学签名的指令。 帐户将发起交易以更新以太坊网络的状态。 最简单的交易是将 ETH 从一个帐户转到另一个帐户。前提条件为了帮助你更好地理解这个页面,我们建议先阅读帐户和我们的以太坊简介。什么是交易?以太坊交易是指由外部持有帐户发起的行动,换句话说,是指由人管理而不是智能合约管理的帐户。 例如,如果 Bob 发送 Alice 1 ETH,则 Bob 的帐户必须减少 1 ETH,而 Alice 的帐户必须增加 1 ETH。 交易会造成状态的改变。 示意图节选自以太坊虚拟机图解(opens in a new tab)改变 EVM 状态的交易需要广播到整个网络。 任何节点都可以广播在以太坊虚拟机上执行交易的请求;此后,验证者将执行交易并将由此产生的状态变化传播到网络的其他部分。交易需要付费并且必须包含在一个有效区块中。 为了使本概述更加简洁,我们将另行介绍燃料费和验证。所提交的交易包括下列信息:from - 发送者的地址,该地址将签署交易。 这将是一个外部帐户,因为合约帐户不能发送交易。recipient – 接收地址(如果是外部帐户,交易将传输值。 如果是合约帐户,交易将执行合约代码)signature – 发送者的标识符。 当发送者的私钥签署交易并确保发送者已授权此交易时,生成此签名。nonce - 一个有序递增的计数器,表示来自帐户的交易数量value – 发送者向接收者转移的以太币数量(面值为 WEI,1 个以太币 = 1e+18wei)input data – 可包括任意数据的可选字段gasLimit – 交易可以消耗的最大数量的燃料单位。 以太坊虚拟机指定每个计算步骤所需的燃料单位maxPriorityFeePerGas - 作为小费提供给验证者的已消耗燃料的最高价格maxFeePerGas - 愿意为交易支付的每单位燃料的最高费用(包括 baseFeePerGas 和 maxPriorityFeePerGas)燃料是指验证者处理交易所需的计算。 用户必须为此计算支付费用。 gasLimit 和 maxPriorityFeePerGas 决定支付给验证者的最高交易费。 关于燃料的更多信息。交易对象看起来像这样:1{2 from: "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8",3 to: "0xac03bb73b6a9e108530aff4df5077c2b3d481e5a",4 gasLimit: "21000",5 maxFeePerGas: "300"6 maxPriorityFeePerGas: "10"7 nonce: "0",8 value: "10000000000",9}显示全部 复制但交易对象需要使用发送者的私钥签名。 这证明交易只可能来自发送者,而不是欺诈。Geth 这样的以太坊客户端将处理此签名过程。示例 JSON-RPC 调用:1{2 "id": 2,3 "jsonrpc": "2.0",4 "method": "account_signTransaction",5 "params": [6 {7 "from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db",8 "gas": "0x55555",9 "maxFeePerGas": "0x1234",10 "maxPriorityFeePerGas": "0x1234",11 "input": "0xabcd",12 "nonce": "0x0",13 "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",14 "value": "0x1234"15 }16 ]17}显示全部 复制示例响应:1{2 "jsonrpc": "2.0",3 "id": 2,4 "result": {5 "raw": "0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",6 "tx": {7 "nonce": "0x0",8 "maxFeePerGas": "0x1234",9 "maxPriorityFeePerGas": "0x1234",10 "gas": "0x55555",11 "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",12 "value": "0x1234",13 "input": "0xabcd",14 "v": "0x26",15 "r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e",16 "s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",17 "hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e"18 }19 }20}显示全部 复制raw 是采用递归长度前缀 (RLP) 编码形式的签名交易tx 是已签名交易的 JSON 形式。如有签名哈希,可通过加密技术证明交易来自发送者并提交网络。data字段绝大多数交易都是从外部所有的帐户访问合约。 大多数合约用 Solidity 语言编写,并根据应用程序二进制接口 (ABI) 解释其data字段。前四个字节使用函数名称和参数的哈希指定要调用的函数。 有时可以使用本数据库(opens in a new tab)根据选择器识别函数。调用数据的其余部分是参数,按照应用程序二进制接口规范中的规定进行编码(opens in a new tab)。例如,我们来看一下这笔交易(opens in a new tab)。 使用 Click to see More(单击查看更多)查看调用数据。函数选择器是 0xa9059cbb。 有几个具有此签名的已知函数(opens in a new tab)。 本例中合约源代码(opens in a new tab)已经上传到 Etherscan,所以我们知道该函数是 transfer(address, uint256)。其余数据如下:10000000000000000000000004f6742badb049791cd9a37ea913f2bac38d012792000000000000000000000000000000000000000000000000000000003b0559f4根据应用程序二进制接口规范,整型值(例如地址,它是 20 字节整型)在应用程序二进制接口中显示为 32 字节的字,前面用零填充。 所以我们知道 to 地址是 4f6742badb049791cd9a37ea913f2bac38d01279(opens in a new tab)。 value 是 0x3b0559f4 = 990206452。交易类型以太坊有几种不同类型的交易:常规交易:从一个帐户到另一个帐户的交易。合约部署交易:没有“to”地址的交易,数据字段用于合约代码。执行合约:与已部署的智能合约进行交互的交易。 在这种情况下,“to”地址是智能合约地址。关于燃料如上所述,执行交易需要耗费燃料。 简单的转账交易需要 21000 单位燃料。因此,如果 Bob 要在 baseFeePerGas 为 190 Gwei 且 maxPriorityFeePerGas 为 10 Gwei 时给 Alice 发送一个以太币,Bob 需要支付以下费用:1(190 + 10) * 21000 = 4,200,000 gwei2--或--30.0042 ETHBob 的帐户将会扣除 1.0042 个以太币(1 个以太币给 Alice,0.0042 个以太币作为燃料费用)Alice 的帐户将会增加 +1.0 ETH基础费将会燃烧 -0.00399 ETH验证者获得 0.000210 个以太币的小费任何智能合约交互也需要燃料。 示意图节选自以太坊虚拟机图解(opens in a new tab)任何未用于交易的燃料都会退还给用户帐户。交易生命周期交易提交后,就会发生以下情况:以加密方式生成的交易哈希: 0x97d99bc7729211111a21b12c933c949d4f31684f1d6954ff477d0477538ff017然后,该交易被广播到网络,并添加到由所有其他待处理的网络交易组成的交易池中。验证者必须选择你的交易并将它包含在一个区块中,以便验证交易并认为它“成功”。随着时间的流逝,包含你的交易的区块将升级成“合理”状态,然后变成“最后确定”状态。 通过这些升级,可以进一步确定 你的交易已经成功并将无法更改。 区块一旦“最终确定”,只能通过耗费数十亿美元 的网络级攻击来更改。视频演示跟随 Austin 了解交易、燃料和挖矿。Typed Transaction Envelope 交易以太坊最初有一种交易形式。 每笔交易都包含 Nonce、燃料价格、燃料限制、目的地地址、价值、数据、v、r 和 s。 这些字段为 RLP 编码,看起来像这样:RLP([nonce, gasPrice, gasLimit, to, value, data, v, r, s])以太坊经过演变,已经支持多种类型的交易,从而能够在不影响传统交易形式的情况下实现访问列表和 EIP-1559(opens in a new tab) 等新功能。EIP-2718(opens in a new tab)是允许这种行为的。 交易解释如下:TransactionType || TransactionPayload其中,字段定义如下:TransactionType - 一个在 0 到 0x7f 之间的数字,总共为 128 种可能的交易类型。TransactionPayload - 由交易类型定义的任意字节数组。延伸阅读EIP-2718:Typed Transaction Envelope(opens in a new tab)你知道有什么社区资源帮助过你吗? 编辑并添加本页面!相关主题帐户以太坊虚拟机 (EVM)燃料back-to-top ↑本文对你有帮助吗?是否前一页帐户下一页区块编辑页面(opens in a new tab)在本页面前提条件什么是交易?data字段交易类型关于燃料交易生命周期视频演示Typed Transaction Envelope 交易延伸阅读相关主题网站最后更新: 2024年2月16日(opens in a new tab)(opens in a new tab)(opens in a new tab)使用以太坊查找钱包获取以太币Dapps - 去中心化应用二层网络运行节点稳定币质押ETH学习学习中心什么是以太坊?什么是以太币 (ETH)?以太坊钱包Gas fees以太坊安全和预防欺诈措施什么是 Web3?智能合约以太坊能源消耗以太坊路线图以太坊改进提案 (Eip)以太坊的历史以太坊白皮书以太坊词汇表以太坊治理区块链桥零知识证明测试中心开发者开始体验相关文档教程通过编码来学习设置本地环境生态系统社区中心以太坊基金会以太坊基金会的博客(opens in a new tab)生态系统支持方案(opens in a new tab)以太坊漏洞悬赏计划生态系统资助计划以太坊品牌资产Devcon(opens in a new tab)企业级应用主网以太坊私密以太坊企业级应用关于ethereum.org关于我们工作机会参与贡献语言支持隐私政策使用条款缓存政策联系我们(opens in a new t

新手最全攻略:以太坊简易指南 · Ethereum Community Network

攻略:以太坊简易指南 · Ethereum Community Network新闻资讯零时学院开发者门户生态漫游ΞSearch by 新手最全攻略:以太坊简易指南建议收藏!最全的以太坊新手指南:概览以太坊的运作方式、去中心化应用和身份认证。bbrunny.eth       2022-05-31来源 | mirror.xyz/brunny.eth

如果你是加密界的新手,面对众多概念无从入手,那么欢迎你,来对地方了。

我最聪明的一些朋友已经开始花更多时间钻研以太坊。而在此过程中,他们中有些人问过我类似的问题。通常都是关于具体概念的界定(比如,“什么是 gas ?”)或者是广泛的概念性问题(比如,“ Uniswap 如何运作”)。这些疑问促使我写成了这一篇《以太坊简易指南》。

如何使用这篇指南呢?

它被划分为五个主要部分:

“以太坊 101”入门部分,

“以太坊 201”深入探讨更为复杂的概念,

加密语境中关于身份认定部分,

去中心化金融部分,以及最后,

关于以太坊的未来。最后的部分尤其探讨向 PoS (权益证明机制) 的过渡(如果现在这些与你无关,则不要过于忧虑)。

在每一部分,我解释了很多复杂的专业术语,编制了许多实用的图表,以通俗的语言阐释以太坊中最为重要的概念性主题。并且,我还在指南的末尾附上了额外资源,供大家继续深耕。

在了解以太坊时,你可以针对性地运用指南的不同部分进行快速阅读和检查,或将指南作为探索未来的一个灵感点,或作为一个链接分享给最近对加密领域感兴趣的朋友。举例来说,可以按 Ctrl+F 键查找“ Uniswap ”更多地了解去中心化交易所。或者,还可以检索“ wallet ”(钱包)学习更多有关非托管钱包的安全知识。

在 Vitalik Buterin(以太坊联合创始人)的某篇热门博客帖子中,他写道,“有时候,差别极小的过度简化正是我们了解世界所需要的东西。”我希望,通过将这些复杂的话题浓缩为极简的内容,让这则指南可以帮助所有人了解以太坊世界。

1)以太坊101 - 基础篇

在认识以太坊之前,我们需要了解它的基础概念。在这个部分,我将阐释什么是区块链,区块如何添加到链上,以太坊如何像世界计算机一般运作,以及智能合约如何运行。

区块链 - 区块链是指特定网络中一系列独立计算机处理和维护的所有交易的公开记录本。比起用中心化的方式管理这些交易数据库(就如 Amazon 或 Facebook 控制自己数据的方式),区块链上不存在单个数据所有者,使之去中心化。在这个网络中的计算机遵循着特定的规范和机制,以保存所有交易的记录。

这些规范让计算机能够同意网络中发生的所有(交易)行为,或就其达成共识:计算机 A 是否转出资金给计算机 B ,计算机 B 是否发送这些资金给计算机 C,以及什么时候呢?上周发生了什么事呢?六个月前发生了些什么?

网络中的计算机是独立的,因此,计算机 D 和 E(和 F 和 G ......)可能不认识计算机 A、B 或 C。区块链的一系列规则意味着,单个计算机无须独自验证其他计算机提供的数据的准确性,就能对区块链历史上发生的交易达成一致。换句话说,计算机之间不用信任彼此就可以达成共识。在网络中的计算机之间,这种去信任共识机制具有举足轻重的重要性。

区块链数量十分庞大,每一条链遵循着自行设置的规范达成共识。以太坊区块链致力于为给不同领域中酷炫的、新颖的应用提供基础设施服务与设计空间,比如游戏、艺术、金融和社交媒体类的应用。

共识机制 - 当区块链上的所有计算机都同意发生在网络中的事实,这就是“达成共识”。单个计算机之间根据区块链的规则达成共识,并且每一次将新交易打包至链上,所有计算机都需要经历达成共识的全过程。一旦这些计算机达成共识,交易区块则被打包到区块链上,成为网络历史记录中的一部分。大致的意思是,假设计算机对每次新交易添加至链上的行为无异议,那就相当于同意了区块链的整个历史记录,因为他们不得不参与其中的每一环。

共识是一个支撑整个区块链世界的重要概念。如何在不信任网络中任何参与者的情况下,验证上面发生的交易,这是一个非常难以解决的人类问题,而区块链是这一问题的最优解。不同规范(或是“共识机制”)可以促使个人计算机在区块链中达成共识。下面介绍两种主要共识机制:

工作量证明(PoW)- 在工作量证明机制中,计算机之间以竞赛的方式解决复杂的数学问题。网络会给第一台解决问题的计算机提供经济奖励,这激励着计算机背后的人不断更新并运行节点(换言之,确保网络一直处理交易)。

也许你曾听过,这种竞相解决计算密集型数学问题的过程就叫“挖矿”。基本上,经验证为合法的交易,可以安全地添加到区块链上。这也是比特币区块链以及当前以太坊区块链在实施的规则。

工作量证明机制也有它的缺点,主要是1)最终,最强大的(和最昂贵的)计算机能够更快地解决问题,因此,富者衡富;2)在计算机上解决高难度的数学问题需要消耗很多精力,这已经成为整个区块链最为人诟病的一点。

权益证明机制(PoS)- 相对于耗费大量算力来达成共识(如 PoW),权益证明机制则是利用惩罚的风险(和一些经济激励)约束/激励参与者。

在权益证明机制中,参与者筹备资金(技术角度而言,他们“质押”自己的资金),并换取进入随机选拔程序的资格。被随机选中的计算机需要验证下一批即将到来的交易。当随机选中的计算机正确地处理交易(在权益证明机制的限制范围内),可以获得奖励。

如果被网络随机选中的参与者违反了权益证明机制的规定,那么这个参与者质押的资产就会减少(或“被罚没”)。

PoS区块链不会同时请求网络中的所有计算机破解那些数学难题,而是通过随机选取计算机进行交易验证。略过繁重的计算过程可以减轻PoW机制出现的两大主要问题。这也是以太坊在规划2022年部署下一代区块链时,打算启用这套共识机制的部分原因。

节点 - 为了以太坊区块链的运作,网络中的参与者需要运行特定的软件,协助他们与区块链进行交互。我倾向于认为,每个节点作为独立计算机运行着以太坊软件。同样地,节点(网络中的参与者)越多就越去中心化,但有时,维护所有节点有些麻烦,因此,不同的节点针对不同的目的:

全节点 - 全节点用来储存完整的区块链数据,帮助区块进行验证并打包到链上。这类节点还为过去的交易提供有效性证明。

轻节点 - 轻节点的功能在设计上相对少于全节点。比起储存完整的区块链数据,轻节点仅仅储存较少量过去交易的证明。这类节点让更多人参与到网络中,因为它们存储更少的数据,运行起来更加经济。

归档节点 - 归档节点是以太坊世界的程序库/维基百科词典。它们储存全节点所有的数据,甚至更多。分析工具和钱包提供商也许会利用归档节点来拉取很久之前的信息。

客户端 - 这是以太坊的软件,使得计算机(节点)能够同以太坊网络进行交互。单个节点可以选择他们想用的客户端软件,但多用一些不同类型的客户端对于去中心化至关重要,以免其中某个客户端出现 bug 或者问题。现在有执行客户端和共识客户端两种类型,但这不在指南介绍的范围内。

现如今,链上有很多可用的客户端,最近以太坊社区争取让最大的一些节点运行机构多样化其运行节点的客户端。重要的是,任何想要参与运行以太坊网络的用户,都可以创建他们自己的客户端,这意味着用户不必信赖第三方实体为其验证区块链。

状态 - 以太坊区块链的状态指的是在任何特定时间点区块链上的账户余额情况。一旦有新的事物产生(比如处理一个新的交易区块),那么状态则会更新并精确地反映区块链在打包新交易后的状况。

以太坊的状态保存不同账户及其余额的信息。换言之,一旦区块链验证新的交易,状态也会随之更新,利用刚添加的新交易信息反映出新的账户余额。

侧栏 - 如何将区块打包到区块链上?

一个用户可能想用以太坊区块链发送一些资金给另一个用户。一旦发起方用户这边发起了交易,这笔交易就要在接收方用户收到这笔钱之前,被打包至交易链上。

当这样一笔交易打包到以太坊区块链上,各个节点需要在交易打包上链并变成其一部分历史之前,完成整个达成共识的过程。

在下图中,它讨论的是上述的简单交易,就是一个用户发送资金给另一位用户。这笔交易被打包成区块,等待节点一同达成共识后将它添加至链上。

来源: Understanding Ethereum

事实上,区块链只是所有用户对于发生在网络中的历史交易达成共识的方式,而区块链状态是已实时更新过新交易的账户余额

来源: Understanding the Ethereum Yellow Paper

智能合约 - 在一定程度上,智能合约类似于物理世界中使用的传统合约的电子版。在传统合约中(例如雇佣合同或者公寓租赁),两个及以上的合约方建立一套条款,再通过律师和司法系统执行合约中的条款。

而在智能合约中,两个及以上的用户也是创建一套规则,却不是通过司法体系执行合约,而是由程序代码编写成智能合约,发送到区块链(或者部署在区块链上)。智能合约会根据已编好的代码自动运行,而不需要律师执行。

上述的侧栏部分叙述了区块打包上链的过程。智能合约是经由区块内的交易部署到链上的代码。未来的交易可以“调用”或与智能合约交互。举个简单的例子,A 用户希望和 B 用户就比特币在未来两年内的价值打赌。A 用户认为比特币在 2032 年 1 月 1 日时会超过 100,000 美元,而B用户则认为比特币会低于这个价格。那么,两位用户可以建立一个智能合约,在合约里放置彼此的资金,再约定一条简单的规则:如果比特币在 2032 年 1 月 1 日超过了 100,000 美元,智能合约则释放这些资金给 A 用户,反之,智能合约将资金打给 B 用户。这个交易过程十分简单、直接且去信任。

智能合约允许任何人以去信任的方式在世界计算机上部署代码,并且,也使得任何人去信任式地验证代码的内容(只要他们可以读懂代码!)最终,智能合约技术的存在已为一波涌现的去中心化应用浪潮带来巨大的机遇,而没有区块链技术,这些就无法成为现实。

比特币和以太坊最大的区别是,以太坊催生了一波智能合约计算平台的浪潮,这些平台是可以编写智能合约代码并直接部署到链上的区块链。以太坊基金会研究员 Josh Stark写了一部关于智能合约的文章,如果你愿意更加深入了解这个概念,我建议你阅读这篇文章。

以太币(ETH)- 以太币是支持以太坊区块链的原生货币。在工作量证明机制中,(挖矿)奖励通过以太币支付给解决数学难题的计算机。并且,参与者在权益证明机制中质押的资金也是用以太币 (需质押 32 ETH)。

以太币是加密货币的名字,以太坊是网络的名字。

以太坊虚拟机(EVM)- 以太坊虚拟机这个名字是指“虚拟的”计算机,它由所有参与以太坊网络的独立小型计算机组成。这样单个的大型计算机并非实际上处于某个位置的“物理层面上的”计算机,而是尤如一台大型(全球性的)计算机一般工作。

以太坊区块链的状态就活跃在这台计算机上,并且,当下一个区块打包至链上时,它负责执行状态更新的规范。如果以太坊网络中的用户想将智能合约代码纳入自己的交易中,那么这个代码便会在 EVM 上运行。

侧栏 - 以太坊虚拟机如何运作?

尽管对于新手来说,可能没必要了解EVM运行的复杂性,但它是以太坊区块链的重要组成部分,还能帮助读者大致了解去中心化如何规模运作。如下图,尽管图片有些复杂,但画得不错。一起按照步骤来看:

我们首先从以太坊区块链在特定时间点的状态开始。这左边的方框称作“ 世界状态σ t ”

一笔交易被打包到链上,例如从一个钱包转移以太币到另一个钱包,在图表顶端上的方框,就是“信息调用交易”。

在交易发生之前的以太坊状态(再次提示,左边的方框)加上新交易(顶上的方框)的输入数据,都在 EVM 上运行。在这里,EVM 更新区块链的状态。

一旦 EVM 更新了状态,新的状态“ World state σ t+1 ”会被储存起来。

来源: Ethereum EVM Illustrated

代币 - 通常,代币指区块链上的资产。代币可以代表许多不同类型的资产。举个例子,一般认为代币是可以当成货币的资产,或者是在具体决策过程中给持有者提供投票权的资产 (治理代币),又或者完全可以作为其他东西。代币是加密世界中代表着不同种类资产的价值的原子单位。

**同质化代币(fungible token) **- 这个术语“ fungible ”指的是可以相互转换的一些商品或是物品,即可替换性。这不是一个加密原生术语,一般的货币指的是同质化货币。例如,我口袋里的1美元可以换成你口袋里的 1 美元,并且这两个 1 美元都可以用来买1美元的东西,它们是等价的。当可替代性应用于加密概念中,它指是否可以与其同一集合中的其他加密资产进行互换。我的以太币和你的以太币可以互换。

非同质化代币(NFTs)- 非同质化代币指的是所有因独一无二的存在而不可互换的数字资产。

虽然 NFT 主要是因为数字艺术和数字藏品出圈的,但它不止于这种表现形式,它可以是任何独一无二的数字资产。数字艺术和数字藏品恰好是 NFT 最早的用例之一,而已经引起了广泛公众的共鸣。这种代币引起了许多人对加密界的兴趣,但我认为诸如无聊猿和 NBATopShot 此类 NFT 项目的兴起导致广大公众低估了在以太坊区块链这样的可信结算层上部署独一无二的数字资产所带来的其他方面的效用。

从概念上看,NFT 还可以应用于许多数字收藏品以外的其他用例。如果一种产品或者服务需要能够验证某种特定数字资产的所有权和其稀缺性的有效性,那么公共区块链上的 NFT 就派上用场了。例如,音乐会场地可能会用 NFT 替代门票,或者视频游戏的设计师可以将那些难以在游戏中获得的资产转为 NFT,由此用户之间可以转让或交易。

这个概念还能玩出新花样:一些资产可以既是同质化的,又是非同质化的,这取决于同它们进行比较的集合。例如,如果我持有一个 19 世纪的 1 美元老币,并将它作为收藏品放置于玻璃罐中。这很明显,这 1 美元(非同质化的!)和被揉作一团后塞在口袋的美元新钞截然不同。

不过,如果我将玻璃罐里的1美元掏出来去星巴克消费,他们(可能)愿意收下它。这是因为,从某种程度上看,它跟其他一美元纸币是可互换的,尽管从其他角度而言,它们完全不是一回事。

来源: Graphical Guide to Understanding Uniswap

以太坊201-进一步深入了解

在这一部分,我将阐述gas成本高昂的原因,可组合性如何运作,以及用户如何与创建在以太坊上的应用交互。

燃料 (Gas) - 与以太坊区块链的每次交互都会消耗成本 (gas),而这个成本取决于以太坊虚拟机运行那段特定代码需要消耗多少算力。由于区块链上的每个区块的空间只能容纳固定数量的交易,而 gas 的概念可以帮助以太坊分配稀缺的区块空间资源。

越是复杂的交易可能需要支付越多的 gas 才能完成。比如,从一个钱包发送以太币到另一个也许只需要在虚拟机上运行几行代码,因此,它需要的 gas 少于算力大的交互所需的 gas ,如在去中心化交易所兑换一些代币(阅读下文的去中心化金融部分了解更多!)。

你可以把 gas 看作类似于中心化的信用卡公司收取服务的手续费。例如自 20 世纪 50 年代创建、运作且维护到现在的 Visa,会向所有使用 Visa 网络的交易收取固定的 3% 费用。相对而言,以太坊的“手续费”是不固定的,它基于交易时网络的供需情况而定。Gas 费用于支付参与以太坊区块链运作的计算机(请阅读下文了解更多)。

Gas 以 ETH 计价,并且用户可以选择支付更多的 gas(通过给计算机支付小费的方式)以加速交易时间,提高交易打包到下一区块的几率。

Gwei - 在技术上Gas的价格表示为 wei,是 ETH 最小的增量单位。1 wei 等于0.000000000000000001 ETH(1018 wei,也就是用 5 个逗号才能表示 1 ETH),1 gwei 等于1,000,000,000 wei,所以比较 gas 价格时,用 gwei 兑 ETH 的计价方式更为方便。

用户已经习惯了以 gwei 为单位来表示 gas 价格。比如 0.0001 ETH是 1 gwei,这个 gas 费用很低。用户可以使用 Gas.Watch留意实时的gas价格。Gas 会随着打包进区块链的交易需求上下波动。

它应该是发音为 gwey,但我听过有人读 goo-ee。所以,我不太敢问它的读音。

侧栏 - 为什么需要 gas,它如何应用?

负责验证区块链交易的计算机需要在经济上给予激励。如果不发放这些激励,将难以说服他们运维计算机和区块链,而要是链上没有充足的计算机进行运行,就将导致区块链变得过度中心化,仅由几个用户控制。

如上所述,支付给网络参与者的 gas 会根据打包进区块链的交易需求而波动。

来源: Understanding Ethereum

Solidity - Solidity 是一种编程语言,用户可以用它在以太坊区块链中编写智能合约以及创建去中心化应用。重要的是,Solidity 是图灵完备的编程语言,这基本意味着“任何你可以编写成代码的东西都可以用 Solidity 写”。这说明,开发者能够使用 Solidity 在以太坊上开发大量的酷炫玩意。

可组合性 - 由于智能合约作为开源代码部署在以太坊上,所以,任何人都可以基于这些智能合约构建(或者“分叉”代码并自行改变),这表明以太坊 (以及其他类似区块链) 上的应用是可组合的。

可以将可组合性看作是区块链的 API 。尽管按理说早几代前开发者就能够基于其他技术基础设施创建应用,但加密可组合性对比其他领域的不同主要表现在:它所有底层协议都是去中心化的。换言之,开发者无需担忧会有某个中心化实体,掌控全部的底层数据并突然改变平台的规则,或是限制开发者的访问, 比如 2018 年基于推特 API 构建应用的开发者们遇到的情况那样。

侧栏 - 可组合性的案例有哪些?在实际中如何应用?

可组合性指的是开发者可以利用已经构建和部署在公链上的其他应用创建新的应用。

例如,Compound 作为一个 DeFi 应用,如高能储蓄账户一样能让用户通过存款赚取利润。假设一个项目(例如 Argent 加密钱包)的开发者希望将 Compound 嵌入他们构建的应用中,那么他们无需重建系统就可以轻松地集成 Compound。这就是可组合性。

来源: Understanding Ethereum

以太坊改进提案(EIP)- 鉴于如以太坊这类区块链在本质上是公开的、去中心化和开源的,其开发者社区修改协议的方式与中心化实体做决策的方式相去甚远。现代开源社区(比如 Linux 和 Python 的活跃社区)和以太坊的开发过程更加相似。

以太坊社区已经制定了一套流程以概述社区成员该如何向以太坊协议提出改进建议。这些流程包括提供进行讨论的公共论坛和鼓励社区参与开源,这对于以太坊区块链来说尤为重要,因为它是去中心化的区块链且依赖于全球分布的社区对其进行监督和改进。

提案可以与区块链遵循的核心规则相关 (比如何时达成共识),也可以就以太坊核心构建部件提议一个标准化版本如非同质化代币或者钱包(下文会展开描述)。当用户利用以太坊的可组合性基于某些已标准化的规范来构建一个应用时,显而易见代码将按预期运行。

以太坊注释请求(ERC)- ERC 是 EIP 的一种类别,具体来说,ERC 是描述“应用级别的标准和协定”的一种 EIP 。这类 EIP 值得在这提一提,因为它是以太坊上最重要且最具知名度的一些使用案例的合约标准的模板。开发者在以太坊上构建时可以使用这些合约标准以节约时间和精力,而不用从头开始。一些广为人知的 ERC 如下:

ERC-20 - 这是同质化代币的一种代币标准。

ERC-721 - 这是非同质化代币的一种代币标准。

ERC-1155 - 这是优化了部分 ERC-20 和 ERC-721 的代币标准,一般应用于碎片化非同质化代币。

侧栏 - 为什么想要碎片化(或使其可替代)非同质化代币?

尽管碎片化 NFT 这个概念本身听起来像悖论,但这也有几个不同的用例。最好的解读方式是,一些艺术品价格高昂(比如 Beeple 的 NFT 以 6900 万美元的价格售出或蒙娜丽莎这副名画),普通人很难买得起。碎片化一个昂贵的 NFT,使得消费者有机会持有(价值连城、非同质化)代币的一小部分。

来源: Algorand

值得注意的是,大多数分解后的NFT碎片之间具有可替代性,因此,某个用户持有的蒙娜丽莎面部碎片不会和手部碎片或是背景碎片相斥(即碎片之间是等价的)。这些不同部位的碎片实际上并不是可替代的(比起脸部碎片,我更乐意花更少的钱购买背景碎片)而现实中,用户只会持有整个艺术品的一片小小的可替代碎片。

碎片化 NFT 不止是钱的问题。NFT 代表着独一无二的数字资产,所以 NFT 碎片化还隐含着所有权、身份和社区的概念。

测试网 - 测试网是区块链的副本,它使开发者得以尽情开发,并测试代码在“主网”区块链上将是何种运行情况。当开发者在区块链上部署了智能合约后,尽管有些智能合约已经不再应用,但只要区块链一直活跃,这些代码都是可见的。由于存在这种永久性以及智能合约有可能与大额资金交互,开发者会希望通过在测试网测试以确保代码会按预期运行。

在以太坊案例中,有一堆的测试网(比如 Rinkby 、Ropsten 和 Kovan )可供开发者在不用冒险动用真实资产的情况下,测试自己的代码。测试网是加密软件开发者的开发实践环境。

水龙头 - 水龙头会分发“虚假” ETH 给开发者,所以他们能用这些测试币在测试网测试智能合约。开发者需要ETH部署智能合约并与之进行交互,但与主网的ETH不同,测试网的测试币不具有实际的经济价值。水龙头是开发者获取 ETH 测试币的简便渠道。

设想你是一名开发者,准备在以太坊上部署智能合约。假设你手头上的智能合约将处理一些资金,可能类似于一个去中心化的交易所(在下文的去中心化金融部分有探讨)。首先,你想在测试网上测试智能合约。以确保代码的运行达到预期。你将需要一些测试网的ETH来运行智能合约。

然而,要谨记测试网只是以太坊区块链的副本,所以测试网上面的ETH本质上是“虚假”的,因此,这些代币不能兑换成主网链的ETH。如果读者想用以太币测试合约并观察它的实际运行,那么水龙头可以方便用户获取ETH,并在测试网上尽情使用/挥霍。

预言机 - 根据需要,预言机可以用来连接区块链和外部系统。在某些时候,可以创建在以太坊上的应用,希望与非以太坊网络所保护的外部数据流进行交互。一些数据不得不从链下获取,就如今天的天气或者篮球比赛的分数。因此,预言机是通向“现实世界”的接口。

为了农作物的保险起见,预言机可用于查询弗洛里达州靠近橙子种植地的天气,或是用于验证去中心化体育博彩应用的记分。预言机具有潜在的信任隐患(因为构成区块链的计算机网络无法真的验证弗洛里达的天气如何),但是对于这些需要预言机的应用来说,有良好的方案可以解决这一隐患。

预言机提供商 (如 Chainlink ) 构建了某种系统以试图确保其预言机不易受攻击 (但是单个预言机仍然是区块链上易受攻击的弱点)。读者可以设想一下:为预言机系统 (由多个预言机组成) 建立一种共识机制,尽管其中存在易攻击点 (因为链下数据总是可能会以某种方式被操纵),但是仍然需要 9/16 个预言机对预言机网络的信息达成共识。或者类似的机制。

内存池 - 当一笔交易已被用户提交,但是还未被验证和打包上链,这种待处理的交易会被发送到一个等待区域,叫做内存池。

在处理交易之前,网络中的计算机节点会验证交易的有效性。举例来说,账户在发送交易时,可能会花费超过账户内的有效资金,或是可能出现私钥与发起方钱包(更多请看下文的钱包和身份认证的部分)的公钥不匹配的情况。当网络中的计算机在验证这些潜在隐患时,这些待处理的交易就在内存池中等待。

在技术上而言,网络中的每个参与者都有自己的内存池,但为了让入门级别的读者更好理解,把内存池想象成所有区块链交易的等待区域是可以接受的。通常,交易在内存池中等待几秒钟到几分钟不等,这取决于需求量(下文进一步讨论可扩展性)。

以太坊上待处理的交易可以在数据供应器上看到,比如 Etherscan。

侧栏 - 用户和应用如何与以太坊交互?

用户几乎都是通过如 Chrome 等浏览器使用网页应用。这些网页应用使用特定的库(如 web3.js 或者 ethers.js )建成,这些库使得网页应用可以直接同区块链节点实现交互。

来源: Understanding Ethereum

开发者建立的应用,通过节点运行客户端软件的方式与以太坊进行交互。在下面的示例中,运行的客户端是 Geth,它是一个用来与以太坊区块链交互的命令行界面。也有像 Infura 这样“节点即服务”的供应商,它让开发者得以便捷地与服务供应商控制的节点进行交互,这和开发者如何利用 AWS 访问服务器空间的过程是类似的。接下来,这些节点可以在以太坊上与智能合约和单个账户余额产生交互。

这和当下其他软件产品的“后端” VS.“前端”大不相同。在左下图表中,我们可以看到一个用户如何连接传统的网页应用。

在这个图的旁边,是一个基于以太坊的应用的架构例子。两者极其类似!区别就是,以太坊作为一个后端基础设施服务于加密应用,这使得它具有全球化、无需许可和抗审核的特性。

来源: The Architecture of a Web3.0 Application

钱包和身份

根据设计,区块链使得用户能够自我保管资产,但钱包的作用不仅是给了用户自我托管的权利,它还是用户在加密世界的自我呈现。在这一部分,我将介绍 DAO 和身份的关系,以及用户如何保证钱包安全问题。

钱包 - 将你的资产存在加密钱包中,就好比将现金存在物理钱包里。但是这些加密钱包还储存着代表你和你的行为的信息,例如你交互过的应用以及用该钱包做过的交易。

需要记住的是,根据设计,区块链交易是公开透明的,由此,当你使用钱包在以太坊上做些什么的时候,你的钱包管理着关于这些交易的可追溯、公开的数据。这些可追溯数据强调了 web3 中“持有自己的数据”的理念 —— 你的资产、交易历史、与去中心化应用交互的数据会随着你的钱包移动。而且,与物理钱包相区别的是,许多加密用户会使用多个用途不同的加密钱包。

在这里,还需要了解其他的定义才能完整地解释钱包的概念:

公钥 - 这是一行长代码,代表钱包的对外地址。公钥好比你的家庭地址;这个地址是独一无二,不是秘密(公共记录等)。而这个地址对应着一个家庭(或在这个案例中,地址对应着你的一个账户)。

你可能会与想给你寄信或礼物的朋友分享你的地址,但就算有人在当地政府的财产记录中看到你的家庭地址,那也没什么。如果有人看到你的公钥,那也是没问题的。

私钥 - 在另一方面,私钥是钱包的密码,所以不能让别人知道你的私钥。私钥会对应特定钱包的公钥,因此,如果有人得到了私钥,他们可以完全访问钱包。

私钥就像家里的钥匙,你并不介意有人随机知道了你家的地址,但是如果他们有你家的钥匙,那你必然惴惴不安。再次重申 —— 任何人得到了私钥都可以接入对应的钱包,不要将私钥告诉任何人,也不要储存在别人可以找到的地方。

侧栏-公钥和私钥的原理是?

公钥和私钥背后的机制是非常重要的基础知识。基本上,公钥和私钥是用于加密和验证身份的一种方法,叫做私钥密码学。

谨记公钥是面向外部公开的。当用户向其朋友的钱包发起交易时(使用朋友的公钥),就相当于给交易上锁,只有当用户的朋友确实持有接收方钱包的私钥时,才能把锁解开。尽管交易是可见的(因为它存在公链上),但没有特定私钥(私钥对应的持有资产的钱包)的情况下无法“解锁”这些资产。

不管你是以太坊上搭建项目的开发者或者只是用户,一定要了解公钥和私钥的区别,这很重要。误用(或者“放错”)公私钥可能造成严重的资金后果,并且,这和忘记中心化网站上的密码不同,应用开发者无法帮助用户恢复密钥。随着更多用户创建加密钱包并在区块链上交易,这种交易模式将会更为标准化。同时,注意学习曲线以及帮助向其他用户解释也尤为重要。

来源: How to Generate Public and Private Keys

助记词 - 一组助记词(通常是 12 到 24 个随机的词)是钱包在紧急情况下最终的钱包恢复工具。它需要像私钥一样被同等保护起来,因为丢失助记词或者将它保存在会被发现的地方,就意味着钱包的一切都暴露了。用户一定要采取合适的方式保存助记词,保证其安全性和机密性。

钱包应用的开发者无法访问助记词,所以,如果读者丢失了自己的密钥和助记词,那么你的钱包就不能再恢复。如果仅仅丢失了私钥,那还可以用助记词来恢复钱包。

托管钱包 - 这类钱包由托管方(任何负责管理钱包资金的中心化实体)负责管理,比如一个常规的 Coinbase 账户就是托管的。这些托管者负责管理钱包(因此,如果用户使用了一个托管钱包,就不必保管自己私钥)中的基本资产,为提供用户更为中心化、更顺畅的用户体验。

这种用户体验通常不包括加密原生的身份认证机制,例如,一位用户可以使用 Google 邮箱地址和密码登录 Coinbase 的账户。

托管钱包是一种开启加密之旅的好方式,同时也是兑换现金资产为加密货币的实用方法。另一方面,鉴于这些托管者都由中心化机构持有和管理,所以也带来了去中心化旨在解决的一些问题,比如数据所有权、信息流控制以及潜在的监管要求。

加密界有句关于托管钱包流行语 —— “无钥即无币”。即便是 Coinbase 的 CEO Brian Armstrong 曾经也提过非托管钱包的重要性,因为托管钱包的提供商会有受到政府监管的风险。对那些倾向于以一种完全去中心化的方式管理自己的资产和交易的用户来说,非托管钱包是更好的选择。

非托管钱包 - 这类钱包的管理者只是......你!软件供应商(如 MetaMask , Argent 和 Rainbow 等)提供用户访问自己钱包的软件,但主要的是,钱包资产存放在链上而不是钱包提供商那里。所以,如果 MetaMask 钱包发生了些什么导致无法访问,那么用户可以跳转到 Rainbow 钱包,导入他们的钱包(不用得到 MetaMask 的允许)并通过 Rainbow 操作自己的资产。还有一种非托管硬件钱包,它的私钥直接保存在物理设备中(通常是看起来像 USB 的小金属物件)。

非托管钱包的使用伴随着管理公钥、私钥和助记词的负担,但这种钱包给予用户以自治权(直接持有资产)和访问以太坊世界的唯一身份。以太坊应用允许用户“使用以太坊登录”(Sign in with Ethereum, SIWE ),即“使用自己的非托管钱包登录”。由此,非托管钱包代表了用户的身份,这些钱包扩展了加密界的设计空间,比如关于身份、凭证和所有权的新思维方式。

社会恢复钱包 - 这是由一些非托管钱包提供商支持的一种钱包恢复策略。这种钱包不需要助记词(有用户丢失过助记词),用户可以委任其社交网络中的其他人,验证钱包是否是否对应于它应该对应的人。通过社交恢复钱包,用户可以基于其社交圈的信任网络作为其非托管钱包的后盾,同时仍然保留非托管钱包的自我托管/去中心化/单点登录的优势。Argent 是社会恢复钱包的一个用例。

侧栏-用户如何注意钱包的使用安全?

我不打算在这一栏目用图表,因把所有有关钱包安全的必要信息放进单个图表并不现实。在加密界中,钱包的安全性至关重要,值得我们耗费一些时间探索资金管理的最佳操作。

@ Punk6529 发布了一篇很棒的推特长文,涵盖了安全使用钱包需要注意的所有信息。Vitalik 就此写过大幅的篇章论述社会社交恢复钱包的重要性(点击此处阅读中文版)。而这里是来自硬件钱包供应商 Ledger关于钱包安全的更多信息。

这里是 Punk6529长推文中的一些亮点,不过我强烈建议读者自行上推特阅读这篇推文:

“与公钥不同,永远不要将私钥透露给任何人。如果有人获取了你的私钥,那就玩完了。”

“地址/公钥:你的邮箱地址(可以共享)

私钥:收件箱的密码(永不共享)

钱包:保存私钥

助记词:私钥恢复系统(永不共享)

密码:可选项:创建新钱包的额外密码(永不丢失)”

“安全性和弹性是相悖的目标:将私钥打印在宣传单的行为极具弹性,但你的NFTs将会不翼而飞 (私钥泄露了)。你可以通过摧毁私钥的方式轻松解决安全性问题,而后果是,你本人也无法访问自己的NFTs。平衡安全性和弹性这两个目标是门艺术。”

以太坊域名服务(ENS)- 以太坊域名服务是为以太坊区块链而生的开源域名系统,某种程度上类似于传统网站的域名提供商。ENS 将以太坊上的地址映射为人类可读的名字,因此我才能使用譬如“ brunny.eth ”作为我的地址,而不是这一长串的公钥:0xF67cAEbBbE7b630d137d2901637C02899ED3211b。

读者可以在自己的加密钱包(托管的或者非托管的)里直接尝试一下:创建一笔发送少量ETH的小额交易,不要用我的公钥,而是把“ brunny.eth ”作为接受者。这个服务会匹配“ brunny.eth ”和对应的钱包地址。

总的来说,作为公共物品,ENS 域名对以太坊生态系统中的身份而言十分重要,因而它们值得有自己版本的域名系统。

去中心化自治组织(DAOs)- DAO是加密原生的组织形式。它可以是基于加密原生规则进行自我管理与组织的公司、非营利机构、社会团体或是其他任何类型的组织。这里的加密原生规则是指类似于社区所有权、透明性和去中心化等概念,而值得注意的是,去中心化有一个频谱,而不是非开即关的两种极端。

不似传统公司在实体创建和领导组织架构方面的中心化持有和管理,DAO 则为无中心实体下决策的加密原生项目和商业的经营而设计架构,并致力于争取项目的社区所有权。许多 DAO 的另一个愿景是完全去中心化和民主化的实现。也就是,DAO 的各种决策由主要参与者以民主的方式票选得出。DAO 不仅能针对链上的应用级别产品的变动进行投票,还能发挥奖励和激励系统参与者的作用。

一部分 DAO 确实十分接近自治的程度,某种意义上,自动执行的智能合约代码运行着 DAO 的许多函数。这方面的一个例子就是 DeFi 中的 DAO,这种 DAO 的核心价值定位是,对于 DeFi 中服务于某些目的智能合约的去中心化维护。大多数 DAO 向着去中心化的方向逐步发展,这其中的大部分更类似于与银行账户的多人聊天,而不是真正意义上的自治化组织。

DAO 实际上是各种事物的社会副产品,包括无需许可区块链、非托管钱包、身份认证工具(如 ENS 等)以及生态参与者的共享意愿。DAO 值得用专门的一部分展开描述(甚至是用整篇指南!),但我个人观点是,大家在加密界中参加的 DAO 正是重新定义数字原生身份的关键,所以在本章节中与“身份”一起谈 DAO 最说得通。

去中心化金融

毋庸置疑,DeFi 是目前以太坊最为成功的用例,超过 1000 亿美元的资产锁定在以太坊的 DeFi 协议当中。 DeFi 领域还擅于使用一些令人困惑的术语。在这个小节,我将从广义角度界定 DeFi,深入探讨这些令人困惑的术语,阐述 Uniswap 作为一个去中心化交易所如何在以太坊上运作。

去中心化金融(DeFi)- 去中心化金融指的是任何的不存在中心把关人且完全在区块链上运行的金融应用、交易所和系统。如今,各式各样的区块链上活跃着数以百计(如果还未达到成千上万的程度)的DeFi项目,从去中心化交易所到借贷协议,再到期权和期货合约,应用范围很广。DeFi 应用的首要目标在于重新思考:在没有中央银行掌控权力的世界体系中,如何通过去中心化的形式实现旧式银行系统提供的金融服务。

有案例给出了答案,读者可以试想一下在股票市场买进股票份额的情景。当Sally通过中介(Robinhood、 Charles Schwab 和 Vanguard 等)购买了一股特斯拉股票,这一股会辗转多个中介之手后Sally才能拿到。一般而言,当系统正常运行,这种辗转多个不同中介的行为不会被一般大众发现。但有时会发生糟糕的情况(例如,2008年全球金融危机或是2021年的Gametop股票事件),导致系统崩盘(如出现负油价和交易被取消的情况)。

系统崩盘后,人们希望寻找这场混乱的罪魁祸首。可当他们开始掘地三尺的时候,却发现传统金融市场远没有他们所想的那样透明。

去中心化交易所(DEXs)- 它是首个主要的 DeFi 构建块。区块链激活了一种新型交易所,它无须经过不透明的中介环节和半官方机构,就能直接和智能合约进行交易。

还是举 Sally 购买特斯拉股票作为例子,她不再需要通过中介经纪公司(例如 Charles Schwab )买入股票,这种中介会和做市商(比如 Citadel )进行交易,两者都受到于美国清算所(如 DTCC)施加的约束。而是和 Uniswap 智能合约做交易!智能合约的代码都是透明公开的,因此,她可以看到资金流动的过程,不会被非透明的中介蒙蔽双眼。

这些去中心化交易所运用区块链技术和经济激励,基本上为任意两种货币搭建了市场(比如 BTC 和 ETH,或者美元和欧元等)。以下我将说明,作为占据市场份额最多的 DEX,Uniswap 如何进行运作。

为了解这些去中心化交易所的运作方式,我们需要先界定一些额外的术语:

流动性提供者(LPs)- 在上面的Sally案例中,它所描述的不透明中介在传统金融系统中确实起到了有效作用:为系统提供流动性。而在传统的金融体系中,Sally 可以随时卖掉自己的股票,几乎任何时间或至少在常规的交易时间内都可以,因为中介便是雇来为 Sally 和其他股民提供流动性的人

那么,去中心化交易所协议中的智能合约哪里来资产给它进行交易?答案是流动性提供者。DEX 给予个体通过提供流动性而获利的机会,当有用户与智能合约交易资产时,系统会给流动性提供者返利一小部分由交易产生的手续费。

对 LP 来说,最为知名的是 Unswap 的模式,他们需要在智能合约中存款两种具有相同价值的代币对。再度重申,LP 把存款放进智能合约中,以获取一部分交易手续费。LP 可以将作为流动性存放进去的代币随时提取出来,但这样的话,他们显然无法获得未来交易费用上涨的分红。

自动做市商(AMMs)- 这是 DEX 的一种类别。自动做市商是指运用算法设置价格的智能合约。在此,Uniswap的恒定乘积公式 ( x*y=k ) 最有知名度,然而这超出了这篇指南的范围。AMM只是一种无需人为设置价格的公式或机制。

稳定币 - 稳定币是现实货币的数字化代表,它们代表着与其挂钩的货币的价值,只不过仅作为数字货币在区块链上流通。

DeFi 使得用户能够使用加密资产大展拳脚,却难以使用户和投资者在固定的价格范畴内管理自己的资产,这是由于加密资产的价格并不稳定。在去信任和去中心化的区块链上,稳定币作为一种波动较小的资产存在,同时还作为对比加密资产的参考价格。

通常来说,稳定币与美元挂钩,但也有其他的稳定币。不管是中心化还是去中心化的稳定币,每一种都有自己的机制,以维持它们与其锚定的货币在价格上的1:1挂钩关系。诚然,加密货币正在颠覆全球金融系统,然而主要的全球货币(如美元、欧元和日元等)作为参考价格依旧有效。

总锁仓价值(TVL)- TVL 是指锁定在特定平台的智能合约中的总额价值。TVL 概念也能应用在 DEX 智能合约以外的语境,因为除交易所以外的其他应用也可能会有流动性提供机制(比如借贷平台)。Uniswap 的总锁价值达几十亿美元,而 2022 年初以太坊上的各种应用加起来 TVL 超过了 1000 亿美元。

侧栏-Uniswap怎么运作?

首先,先谈谈用户体验。当用户想用 Uniswap(或其他交易所)兑换代币时,该用户只需在一个简易的前端界面进行操作即可,这个界面是 Uniswap 基于更加复杂的智能合约构建的。如下图所示,用户可以把ETH(或其他代币)兑换成其他资产,犹如使用自动贩卖机。用户可以连接钱包并将任意一种代币换成其他代币。非常简单!

来源: Understanding Ethereum

然而,幕后到底发生了什么?一起看下图中的蓝色方框。这是 Uniswap 的智能合约,是流动性提供者存放其代币的地方(例子中用代币 A 和代币 B )。

蓝色方框的左边描述了 LP 和质押池的关系;LP 存进两种资产,作为交换,他们会收到质押池代币,这种代币相当于流动性提供者可以赎回他们的质押资产的一个凭证。质押池代币可以随时赎回LP最初质押在智能合约的资产(在这里,交易者要警惕接下来提到的“无常损失”。)

上图中的另一端是用户。用户在无需接触质押池 LP 的情况下,进入界面并在质押池中将一种代币兑为另一种。并且,用户会支付一小笔手续费,它会均等地分给质押池中的所有 LP 。

来源: Uniswap documentation

这种机制很酷。我在职业生涯的早期便开始学习金融知识,所以,当我了解到去中心化交易所时,它比比特币的“数字黄金”和以太坊的“世界计算机”隐喻更能使我兴趣盎然。如果没有公链这种去信任基建的存在,那么 Uniswap 只会是黄粱一梦。还有什么是我们今天不敢妄想而明天却成为主流的?

截至2022年初,Uniswap 的月交易量约为 600 亿美元。

接下来提及的术语(以及文本中介绍性定义之外的内容)也许需要读者自行深入探索了。然而,它们也可能是新用户刚踏入以太坊圈子,就会接触到的第一批术语概念,因此,我坚信它们会极大地影响刚进圈的新用户,使他们困惑不已。因此,他们可以多看看文末的更多资料。

流动性挖矿 (Yield Farming) - 如名所示,流动性挖矿是指通过为 DeFi 应用提供流动资金的方式“收割”收益的行为。这些应用提供诱人的奖励作为使用的回报。如果有朋友向你透露其在 DeFi 的年收益率达到 100,000%,那他们说的就是流动性挖矿。

许多 DeFi 应用需要大笔资金注入平台(流动性,如前所述),作为体现其应用价值的关键功能,无论是什么功能(如交易资产、借贷等)。这些 DeFi 应用只有两条路能走:筹募 10 亿美元并由应用提供流动性,或者给予流动性提供者以可观的奖励,并使这些流动性挖矿者成为平台的流动性提供者。

等一下?这些可观的奖励从何而来?

好吧,这些应用正在将这些高额奖励大肆宣传为新型激励机制,但现实是,这些奖励通常只是(昂贵的)客户购置成本。也就是说,这些应用的代币在某种程度上代表了应用的价值,而他们通过应用(客户购置成本)给用户分配奖励。这些奖励是原生代币与其他代币类型的混合产物。

因此,流动性挖矿指的是寻找这种收益并为最有机会获利的应用注入资金的实践,它几乎可以视作 DeFi 应用上的一种天使投资形式。

质押 - 这个术语用得五花八门,但实际上,质押仅是指在一段时间内锁住资产并从锁仓中获利。

一般,这个概念在中心化金融领域应用,用户质押代币以换取奖励,但是质押也能运用在其他领域中。许多 DeFi 协议利用质押方式控制其协议原生代币的流动供给,好比中央银行试图管控货币供给。激励投资者短期锁定自己的代币以期经济报酬,这听起来就像债券。

无常损失 (Impermanence Loss)- 这个概念指的是在供给两种以上代币的流动性时,流动性提供者需要承担的潜在风险。在上文 Uniswap 的例子中,流动性提供者存入两种等值的代币到 Uniswap 上,并获得质押池代币。当 LP 想要提回资金时,质押池代币可以用于赎回自己的两种代币。

这里存在的细微差别是,LP 存款的两种代币都有各自的价格(还有价格波动)。当 LP 想用质押池代币赎回两种代币时,两者的价格可能已经是相去甚远:可能其中一种代币价格下跌了5%,而另一种则上涨了10%。

代币之间的价格差距也许意味着LP最好应当只持有一种的代币,而不要持有从交易费获益的质押池代币。重要的是,无常损失被贴上“非永久的”标签,是因为在 LP 真正赎回质押池代币之前,这种损失只是“账面损失”。也就是说,如果 LP 不选择赎回代币,而是继续提供流动性直到两种代币的价格相互靠拢,那么无常损失就消失了。

关于不同类型质押池的 DEX、LP 以及无常损失的优质初级读物可以在这里找到。Daily DeFi 上的无常损失计算机演示了几个例子。

Layer2和权益证明机制

2022 年被俗称为以太坊的“ L2之年”,万众瞩目的权益证明机制的过渡预计在夏季进行。这个部分将深入讨论区块链的“三角悖论”、以太坊的未来以及 rollup 的运作原理。

区块链三角悖论 - 每一条区块链都涉及三种概念之间的权衡:去中心化、可扩展性以及安全性。一般的共识是( 2022 年早期),以太坊在去中心化和安全性上做得较好,但在可扩展性上稍逊一筹( gas 费用好高!呃啊啊啊啊啊!)。希望在近期会有一些改进计划可以解决以太坊的区块链三角悖论。下面叙述了这三个方面的考量,对于理解三者的平衡对单条区块链的影响而言十分重要。

去中心化 - 比特币白皮书准确地解释了去中心化概念(我自己加粗强调了):“只需要一个基于加密学证明而非信任的电子支付系统,允许任何两个意愿方在无需信任第三方的情况下,直接与彼此进行交易。”

区块链扮演了基础设施层的角色,使得全世界的用户可以使用自己计算机与彼此互动,而不用经过中介环节。

区块链的去中心化就好比一个频谱;如果区块链可以被少数用户关停,或者网络的参与成本过高( gas 费用或配置计算机参与网络的成本),那么区块链则会向中心化的一端倾斜。中心化程度越高,权力垄断和剥削的风险也越高。

安全性 - 安全性是指基础链被外界攻击或控制的难度。有效的经验法则是 51%的大多数原则;如果有人能够控制特定链上 51%的处理交易的计算机,那他们也许可以非法入侵并损害网络的安全性。

这里有更深层的技术考量,但 51%的占比帮助用户厘清安全性、去中心化和可扩展性之间的权衡关系。为特定区块链打包交易的独立计算机越多,表明其去中心化和安全性程度越高(更多计算机=有人控制51%的网络节点的概率很低)。然而,网络中的独立计算机越多,也意味着每台计算机需要同更大的计算机网络进行交流,从而导致运行速度下降......

可扩展性 - ......网络运行速度下降意味着我们需要找到提高可扩展性的方案。当区块链上的交易需求变多时,网络也会随之变得异常拥堵。例如,以太坊也曾有过 gas 费疯涨的时期,尤其是网络需求爆满的时候。这些需求致使交易打包上链的成本水涨船高,同时造成网络拥堵、网络运行速度下降。

零知识证明 - 这个概念并非具体的扩容方案,但它是展开探讨扩容方案之前所要阐明的一个重要概念。零知识证明是一种无需获取特定信息就能验证事物有效性的加密学方法。

比如,假设我是一名 Craigslit 的买家,正打算从网络中的任意用户手里购买一台电视。这时,有人私信告诉我,他们手上有我正在找的电视,而他们的资料是匿名的。

作为一名买家,我希望在与卖家碰面之前,能确保他们真的有电视。但是卖家却不想将他们的个人信息(驾照、居家地址、室内的图片)泄露给网络中的随机用户。最重要的是,卖家也想要知道我是不是一个真人!但双方都不想分享个人信息。

通过零知识证明,我可以向卖家证明我是一个真实的人,在不告诉他们我是谁的前提下验证身份。另一方面,卖家也能证明他们确实拥有一台电视并且是合法的卖家,同样不用泄露任何敏感的个人信息。

这其中包含着错综复杂的加密学基元,因此,上文只是非常简概的介绍。大多情况下,零知识证明能够解决加密界中的安全性、可扩展性和隐私挑战问题。

Layer2 扩容方案 - 用户非常希望可以在以太坊上大展拳脚,因为它是世界上最为去中心化且最为资深的智能合约计算平台。以太坊已经吸引了分布最广的开发者网络,进行基于区块链的应用创建。但这些创建活动带来的后果是,打包交易到以太坊区块链的需求有时会造成 gas 价格过高,这也意味着以太坊用起来既慢又贵。

区块链的三角悖论暗示着,任何优化过安全性和去中心化程度的区块链,将在可扩展性上做出让步。由于去中心化和安全性对区块链的愿景承诺具有重要推动作用,所以可扩展性就成了最难解决的部分。以太坊将赌注压在了一大波改进浪潮上,希望由此解决可扩展性问题。

其中一种改进是,从用户先与以太坊区块链本身(即“ Layer1 ”)互动,改为与 Layer2 扩容方案互动。从根本上,这表明大部分以太坊主网上的交易和应用会转移到Layer2,它继承了以太坊的安全性和去中心化,但却比以太坊本身的吞吐量高几个数量级。以太坊 Layer1 将会专门负责共识问题,而它的 Layer2 则会负责执行交易和代码。

Rollups - Rollup 会在其独立的区块链中处理一批交易。在自己的链上执行这些交易后,Rollup 将所有的交易压缩成一个小型的信息数据包。这些小数据包会被“发送”到以太坊的 Layer1,这表示 Rollup 在继承了 Layer1 安全性的同时扩大了可以处理的交易数量 (因为信息被压缩了)。

这些小得多的交易信息包里包含着一些证明 (证明这些交易是基于以太坊的规则下处理的)。

来源: Understanding Rollup Economics

这听起来似乎是在去中心化上做出了妥协。但是 Rollup 一个关键的点在于以太坊可以只对证明进行验证,而不是对每一笔交易进行证明的工作,这节省了指数级别的工作量(因此让以太坊更加可扩展!)。由于以太坊拥有决定 Rollup 交易是否可以发布上链的最终确定权,所以,在不向中心化妥协的情况下,所有的 Rollup 交易仍然由以太坊提供安全保障。

以下是各种类型的 Rollup 。主要的区别在于它们向以太坊证明交易有效性的方法。

Optimistic Rollup - 这种类型的 Rollup 会将交易证明的记录保存下来,在以太坊请求具体证明时,它才会向以太坊出示这些证明。Optimistic Rollup 不会向以太坊主网证明每笔交易的有效性,而是在必要的时候提供证明,这促使可扩展性问题得到缓解。

ZK Rollup - 这一类 Rollup 不会展示交易内的所有细节,而是利用零知识加密学的方式验证交易的有效性。上面已经解释过零知识证明了,而重点在于这些 Rollup 只展示更小的零知识证明而不是整个交易过程,由此节约了许多的区块空间。

分片 - 分片是指将区块链分割成小分片以减少拥堵的过程。分片促使以太坊更加容易访问。本质上,节点只需要存储他们所连接的特定分片的数据,而不是整个以太坊区块链的数据,这也让以太坊更加可扩展。

分片是以太坊区块链改进计划的一部分,将在 The Merge 之后发挥举足轻重的作用。

信标链 - 信标链是以太坊从 PoW 到 PoS 过渡的基础。现在,信标链和以太坊区块链并行运行,并且信标链引进了质押机制,这是向 PoS 过渡的前提。

很快,信标链会和现在的以太坊区块链合并,正式引入 PoS 共识作为以太坊区块链的共识机制,标志着以太坊未来的重要转折点。

The Merge - 以 The Merge 这个术语可以恰到好处地结束这篇指南。在接下来的几个月,以太坊主网和信标链将进行合并,这是区块链行业有史以来最为广受瞩目的事件。

仅在几个月后,以太坊的 PoW 时代就将迎来它的落幕,而这种共识机制转换的反响可能是异常轰动的。如果因为某些原因,The Merge 失败了,那么它必将引起整个加密界的轩然大波。但如果合并成功,这意味着我们离以太坊成为全球结算层这一天更接近了。

资料

到这就结束啦!这是一篇入门以太坊的简易指南。

在深入了解特定的区块链特征之前,我们首先了解了区块链是什么以及区块链为何如此重要。

接着,我们探讨了一些构建在以太坊区块链上的拔尖应用;钱包、DeFi、DAOs、NFTs 。

之后,我们用以太坊的未来探讨来结束这篇指南,它主要探讨了权益证明共识机制的变迁,以及描绘了以太坊希望如何解决区块链的三角悖论。

所有这些定义都是复杂话题的简化版本,但我还是希望这篇指南可以激发读者们深入探索以太坊世界的欲望。在下文,我为那些希望进一步学习的读者收集了一些资料。如果你们希望向我提出问题或是给予反馈,来推特上给我留言吧!

感谢Josh Stark、Bethany Crystal、Daniel Schlabach、Nico Kuzak、Adam Tzur、Naz Rizvic、还有Miguel Lemos,在这里谢谢你们贴心的帮助还有反馈!

接下来去好地方:

以下资料是我和 Josh Stark 在 2021 年底开始编译后,由以太坊社区在这个文档中收集而成。

通用资料

· What is Ethereum? | ethereum.org - 结合涵盖一些前沿话题的资料链接来学习这个话题

· ETHHub - 这个社区保存着覆盖各式各样的以太坊话题的资源

· Ethereum Foundation Youtube Channel - 以太坊会谈和社区开发者电话会议

· Devcon archive - 每年Devcon会议的所有视频和谈话的存档资料

· Scott Sunarto’s Working in Web3 Handbook - 包含许多话题的手册

· Blockchain@Berkeley Courses - 免费的加密货币在线课程

· Finematics - 解释以太坊上许多话题的视频,如web 3, defi

· Fellowship of Ethereum Magicians - 为加密货币社区提供一席之地的论坛,任何人都可以参加、创建话题以及主要探讨以太坊生态昔日的EIPs和技术难题。

· text - 囊括各种以太坊相关话题的以太坊维基百科。

博客、视频和研究

· Week in Ethereum News

· Paradigm Research

· https://newsletter.thedefiant.io/

· Bankless

· The Daily Gwei

· The Block

· Decrypt

· Dark Star

· Messari Research Hub

· a16z Crypto Canon

· Linda Xie’s Beginner Guides

· Tim Beiko’s AllCoreDevs Updates

· Ben Edgington’s What’s New in Eth2 blog

· Polynya – Medium

· Ethereum: The Infinite Garden (feature documentary film in production)

· Gaby's Web3 Reading List

Podcast

· Into The Bytecode

· Bankless

· The Daily Gwei

· Into The Ether

· a16z

· Into The Ether

· Unchained

· Epicentertext

· ZK Podcast

· Uncommon Core

· Redefined Life

书籍

· The Infinite Machine

· Out of the Ether

· Mastering Ethereum (free online)

· Finite and Infinite Games

这篇指南的链接

· Graphical Guide to Understanding Uniswap

· Ethereum EVM Illustrated

· Understanding the Ethereum Yellow Paper

· Understanding Ethereum

· Punk6529 tweet thread

· Understanding Rollup Economics

· The Architecture of a Web3.0 Application

ECN的翻译工作旨在为中国以太坊社区传递优质资讯和学习资源,文章版权归原作者所有,转载须注明原文出处以及ethereum.cn,若需长期转载,请联系eth@ecn.co进行授权。

Ethereum Community Network以太坊社区网络 订阅 Ethereum Community Network以太坊社区网络 订阅

币圈新手指南--如何购买以太坊(ETH)

指南--如何购买以太坊(ETH)虚拟币: 28,156 交易所: 643 流通市值: $27,565亿 24h成交额: $1,118亿 占比: BTC 48.1% ETH 17.4% ETH Gas: 44Gwei App下载 简体中文 热门语种EnglishEN 简体中文ZH全部语种EnglishEN 简体中文ZH 繁體中文ZH-TW USD 选择法币/加密货币 法币虚拟币没有结果 ""找不到符合您搜索条件的任何内容。 请使用其他关键词再试一次。 行情 市值排行钱包新币上架交易所资金流向全局走势排行榜涨跌幅排行榜 交易所 所有现货衍生品DEX交易所 资讯 文章快讯比特币山寨币公告教程在哪里购买 IDO/ICO 即将启动正在进行已经结束Launchpad排行榜 融资库 投融资事件融资项目库投资者及组合投融资分析 产品 日历CoinCarp AppEVM公链价格计算器网站小组件 Stake-200%BonAd 登 录 注 册 × 行情 市值排行钱包新币上架交易所资金流向全局走势排行榜涨跌幅排行榜 交易所 所有现货衍生品DEX交易所 资讯 New 文章快讯比特币山寨币公告教程在哪里购买 IDO/ICO New 即将启动正在进行已经结束Launchpad排行榜 融资库 投融资事件融资项目库投资者及组合投融资分析 产品 日历CoinCarp AppEVM公链价格计算器网站小组件创建账号 登录简体中文English 简体中文 繁體中文USD 取消选择 × 法币虚拟币没有结果 ""找不到符合您搜索条件的任何内容。 请使用其他关键词再试一次。如何购买以太坊(ETH)新手在购买以太坊(ETH)加密货币时可能会遇到一些困难。 您可能不确定在哪里以及如何购买它。 现在CoinCarp将向您展示如何轻松购买以太坊(ETH)的办法。 您可通过本新手指南快速了解如何购买以太坊(ETH)。什么是以太坊(ETH)?哪里可以买到以太坊(ETH)?如何使用现金/信用卡/借记卡购买以太坊(ETH)?如何使用USDT在中心化交易所(CEX)购买以太坊(ETH)?购买以太坊(ETH)后该怎么做常见问题什么是 以太坊(ETH)?以太坊(英语:Ethereum)是一个开源的有智能合约功能的公共区块链平台。通过其专用加密货币以太币(Ether,又称“以太币”)提供去中心化的虚拟机(称为“以太虚拟机”Ethereum Virtual Machine)来处理点对点合约。以太坊的概念首次在2013至2014年间由程序员维塔利克·布特林受比特币启发后提出,大意为“下一代加密货币与去中心化应用平台”,在2014年透过ICO众筹得以开始发展。目前以太币是市值第二高的加密货币,以太坊亦被称为“第二代的区块链平台”,仅次于比特币。哪里可以购买以太坊(ETH)?支持以太坊购买的途径与平台多样,例如加密货币交易所、加密货币钱包和各种金融科技平台,甚至可以直接从其他个人那里购买。 通常来说,购买以太坊较简单、安全的方式是通过受信任的加密货币交易所或加密货币钱包。许多加密交易所或加密钱包提供以太坊(ETH)场外(OTC)交易服务,并支持使用法定货币购买以太坊(ETH)。在这种情况下,您可以使用当地的法定货币,例如美元、欧元、土耳其里拉、菲律宾比索等在加密货币交易所或加密货币钱包来购买、出售以太坊(ETH)。以下为CoinCarp整理的支持以太坊(ETH)场外交易的加密交易所和加密钱包,您可选择在以下交易所或加密钱包中进行OTC交易:如果你想购买以太坊,你可能需要准备以下东西:加密交换账户或加密钱包账户。除加密货币交易所账户外,建议创建加密钱包(如Metamask)帐户。(什么是加密钱包?)个人身份证明文件(如果您使用的是了解您的客户(KYC)平台)安全的互联网连接有效的付款方式,例如银行账户、借记卡和信用卡许多加密交易所或加密钱包提供以太坊(ETH)场外(OTC)交易服务,并支持使用法定货币购买以太坊(ETH)。在这种情况下,您可以很容易地选择加密货币交易所或加密货币钱包来购买、出售和交易以太坊(ETH)与您当地的法定货币,例如美元、欧元、土耳其里拉、PHP等。您可以从CoinCarp列出的支持场外交易以太坊(ETH)交易的加密交易所和加密钱包中进行选择:购买通过在 火币全球站注册地区 塞舌尔成立时间 2013-09支付方式 币安网注册地区 未知成立时间 2017-07支付方式 库币注册地区 塞舌尔成立时间 2017-09支付方式 CoinBase注册地区 美国成立时间 2014-05支付方式 欧易注册地区 马耳他成立时间 2014-01支付方式 除了现金(法币)购买以太坊外,您可以选择先购买稳定币(如USDT、USDC、BUSD等),然后在加密货币交易所兑换成以太坊(ETH)。 现在,以太坊(ETH) 已在以下交易所上市,您可以选择其中一家交易所并使用稳定币进行购买:以太坊实时行情现货 永续合约 交割合约 ETF/Leveraged交易所交易对价格成交额成交额%24h%更新时间 Binance ETH/FDUSD$3,943.47$2,312,486,97117.79% 4.39%Recently Binance ETH/USDT$3,942.56$2,043,146,51815.71% 4.28%Recently Bybit ETH/USDC$3,942.1$651,581,6155.01% 4.33%Recently Coinbase ETH/USD$3,947.38$510,625,4003.92% 4.13%Recently OKX(OKEx) ETH/USDT$3,943.01$508,414,1513.91% 4.32%Recently Bybit ETH/USDT$3,942.34$496,834,1023.82% 4.27%Recently* 剔除价格 ** 剔除成交额查看更多如何用现金/信用卡/借记卡购买以太坊(ETH)?要使用现金购买以太坊(ETH),例如USD(美元), 您必须使用支持通过您的银行账户或信用卡进行加密货币交易的加密货币交易所或金融平台。不同的国家所支持平台可能不同,例如,您可以通过Coinbase、Paypal(或Venmo)或美国的Robinhood购买以太坊(ETH)。但是,对于大多数国家来说,支持以太坊(ETH)以现金交易(OTC)的主流平台是中心化交易所(CEX),例如Coinbase、Binance等。由于不同的CEX操作程序不同,我们无法为您提供如何在所有不同的中心化交易所(CEX)进行购买的分步指南,但我们可以为您提供一些通用的 步骤。第1步:在中心化交易所(CEX)官网或APP注册账户。(查看ExchangeRanking),如果CEX支持(例如Binance)与您的社交账号的一键注册登陆,您可以直接使用您的社交帐户注册并登陆。第2步:验证您的身份和进行您的中心化交易所(CEX)账户安全设置。 您通常需要持有政府签发的身份证明文件。为了资产安全,您最好启用两步验证。第3步:在您的中心化交易所(CEX)中添加支付(注资)方式。要向您的帐户添加付款方式,您可以点击“添加付款方式”;在弹出框进行设置或单击您的个人资料照片并设置付款方式。 第4步:您可以选择使用借记卡/信用卡、银行存款和第三方支付方式购买以太坊(ETH)。一般来说,不同的CEX和不同的地区会有所不同。对于美国居民,如果您使用Coinbase,您可以点击代币旁边的“交易”按钮,然后填写您想投资多少美元,然后点击“购买”按钮。此外,您可以在P2P平台上买卖以太坊(ETH)。P2P(Peer-to-Peer)交易在某些地区也称为C2C(Customer-to-Customer)交易。在P2P交易中,用户在P2P平台、交易所或市场上直接买卖加密货币。 如何在中心化交易所(CEX)用USDT购买以太坊(ETH)?由于不同CEX的操作流程不同,我们无法为您提供如何在所有不同的中心化交易所(CEX)进行购买的分步指南,但我们可以为您提供一些通用的步骤。第1步:在中心化交易所(CEX)官网或APP注册账户。(查看交易所排名),如果CEX支持(例如Binance)与您的社交账户一步注册,您可以直接使用您的社交帐户注册并登陆。第2步:验证您的身份和进行中心化交易所(CEX)账户安全设置。 您通常需要持有政府签发的身份证明文件。为了资产安全,您最好启用两步验证。第3步:使用法定货币购买USDT。您可以使用CEX提供的支持OTC交易的服务,也可以使用支持通过您的银行账户或信用卡进行注资的金融服务平台(Paypal或Robinhood,适用于美国居民)。 第4步:将法币购买的USDT转入支持现货市场以太坊(ETH)交易的中心化交易所(CEX),并用USDT在现货市场买入以太坊(ETH)。注意:部分CEX在您所在的国家或地区可能不可用,您最好咨询交易所的客服或查看交易所的公告。至于税收问题,您可以咨询当地部门了解更多信息。购买以太坊(ETH)后能做些什么持有/保存以太坊(ETH)许多投资者会持有他们的以太坊并期望它升值。您可以将您的以太坊存储在您的交易所钱包(例如 Binance Wallet)或加密钱包(例如 Trust Wallet)中。如果您想长期持有它们,您可以将它们存储在冷钱包中,为了安全,不建议长期存放于热钱包。(热钱包与冷钱包: 有什么区别?).交易以太坊(ETH)您可以到交易所用以太坊(ETH) 去兑换其他加密货币。 中心化或去中心化交易所通常会为以太坊提供各种加密货币交易对以满足您的需求。赚币以太坊(ETH)通过质押代币赚取奖励。质押是一种很好的方式,可以最大化地赚取代币,这往往优于只是将代币存放在钱包或交易账户中。转账付款与向海外汇款不同,您几乎可以立即将以太坊转账支付给世界上的任何人。购物一些在线平台或线下商店接受加密货币支付。您可以从这些地方购买商品或服务。常见问题(FAQ)我可以买1个以太坊(ETH)吗?答案是肯定的,甚至您可以购买数量少于“1”的以太坊。几乎所有加密货币都是如此。 但在大多数加密货币交易所中,您必须购买价值至少为5美元以上的代币数量。在2024年入手以太坊能否盈利吗?加密货币价格不可预测。所有加密货币都会有其价格的涨跌。以太坊也不例外。 对于真正相信加密货币价值和加密货币未来应用的人来说,以太坊可能是一笔值得的投资。 但是,加密货币市场像股票市场一样非常不稳定,不建议将所有资产投资于加密货币。投资者必须先评估投资以太坊的利弊。您可在投资前做一些研究,例如,阅读项目的白皮书或查看以太坊历史价格或以太坊的投资回报率(ROI)数据。但最终,这取决于您对风险的偏好及承受程度。如何存储以太坊(ETH)?如果你想长期持有以太坊(ETH)并且不打算出售它们,安全性可能是您应该考虑的第一件事。随着安全技术的发展,尽管将它们存储在大多数排名较前的交易所和钱包中比以前更安全了,然而,由于交易所与钱包的存储原理,它们是永远联网的(所谓的“热钱包”),理论上存在被黑客入侵的可能。更重要的是,万一交易所倒闭了,您的资金将可能损失且不可追溯。因此,存储加密货币最安全方法是将它们放入“冷钱包”,它是完全离线的钱包。冷钱包有两种:纸质钱包:它是简单的使用程序离线随机生成公钥和私钥,您可以将它们打印在一张纸上,然后将其存储并保存在安全的地方。密钥以QR码的形式打印,您可以在未来进行扫码从而完成交易。 硬件冷钱包:硬件钱包是您可以存储加密货币的物理设备。您的加密地址和密钥可以保存在类似于U盘的设备中,只有拥有U盘的人才能访问资产。 大多数人目前使用的是硬件冷钱包,如果你想存储大量的硬币或代币,你可以选择使用硬件冷钱包来存储你的资产。 购买以太坊(ETH)需要多长时间?您可以立即从中心化加密货币交易所购买以太坊。但是,KYC过程可能需要几分钟到几小时。一旦您拥有经过验证的帐户,您就可以随时买卖以太坊。如果您使用P2P或银行转账存款购买,可能需要更长的时间,几十分钟甚至几个小时。 至于DEX,交易将由网络中的节点确认。确认时间取决于您设置的gas价格。如果您设置较低的gas价格,您会发现您的交易需要很长时间才能处理完成,因此建议设置合理的gas价格。如果您使用以太坊网络,可以使用Etherscan区块浏览器中的gas查询工具查看gas费用,如使用其他网络,则使用其他网络类似的查询工具进行查询。加密货币投资活动,包括在线购买或出售以太坊(ETH)的行为,都存在市场风险。 CoinCarp.com为您提供简单方便的购买或出售以太坊(ETH)的指南,我们尽最大努力向用户全面告知我们在CoinCarp上列出的每种加密货币的相关信息,但我们不负责您的以太坊(ETH)购买或出售可能产生的结果。本页及其中的任何信息并不意味着对任何特定加密货币或获取它的方法的认可。以太坊价格 以太坊 ETH 0.86,0.86,0.87,0.87,0.86,0.87,0.86,0.88,0.88,0.89,0.9,0.92,0.93,0.94,0.93,0.89,0.93,0.96,0.96,0.97,0.97,0.98,0.99,1价格 $3,943.06 24小时涨跌 4.20%7天涨跌 14.85%30天涨跌 62.79%以太坊 (ETH) 最新的价格是 $3,943.06,24 小时的交易量是$6,290,497,079. ETH的价格在过去 24 小时内上涨了4.2%。以太坊的流通量为:1.21亿 ETH,最大供应量:无限量,总供应量:1.2亿,流通市值为:$478,384,507,155。 以太坊实时价格 我在哪里购买以太坊如果你已经下定决心并准备购买,请跳过本文并购买以太坊 以太坊-美元转换器 以太坊 (ETH) 事件 坎昆升级 329Dencun 升级也称为 Cancun-Deneb,是备受期待的以太坊 (ETH) 升级,预计将于 2024 年第一季度完成。产品发布 上海升级 85Geth v1.11.5将在UTC时间4月12日22:27:35(北京时间4月13日06:27:35)启用上海主网升级。产品发布 上海升级 129 Goerli 的测试将受到高度关注,因为它是最大的公共以太坊测试网产品发布 合并事件 254预计网络将从工作量证明 (PoW) 区块链转换到权益证明 (PoS)产品发布 合并成功,共识正式转为PoS机制 170以太坊执行层(即此前主网)与权益证明共识层(即信标链)于区块高度15537393触发合并机制其它查看更多购买 Bitcoin 购买 Ethereum 购买 Tether 购买 USDC 购买 Binance Coin 购买 Cardano 购买 Ripple 购买 Binance USD 购买 Solana 购买 Dogecoin 购买 DAI 购买 Polkadot 购买 TRON 购买 Avalanche 购买 Shiba Inu 购买 Polygon 购买 Litecoin 购买 FTX Token 购买 NEAR 购买 UniswapCoinCarp 提供加密货币行情、分析、资讯和图表。我们努力成为全球领先的加密货币市场数据提供商。 电报中文机器人 CoinCarp 中文社区关于CoinCarp 关于我们 使用条款 隐私政策 免责声明价格行情 比特币行情 以太坊行情 币安币行情 狗狗币行情支持 广告合作 收录申请 联系支持 常见问题捐赠我们BitcoinETH&USDT(ERC20)USDT(TRC20)© 2024 www.coincarp.com 版权所有 为了给您提供良好的网站访问体验,我们将使用cookie来分析站点流量、个性化信息及广告目的。如想了解更多关于我们对cookies的使用说明,请阅读我们的 隐私政策 。如您继续使用该站点,将表明您授权同意我们使用cookies。 × ×

以太坊机制详解:交易与交易池 | Wong's Blog

制详解:交易与交易池 | Wong's Blog

Wong's BlogArchiveSearchTagsHome » Posts以太坊机制详解:交易与交易池October 14, 2022 · 35 min · 17393 words · WongSSHTable of Contents概述交易池初始化交易构造交易池添加交易交易重排区块打包交易池重构总结概述#我们在上一篇以太坊机制详解:Gas Price计算文章内介绍了以太坊中交易的具体gas计算相关规则。本篇文章将在此基础上介绍以下内容:客户端如何构建一笔交易服务端如何处理交易并进行打包本文以一笔交易的生命周期为主线安排全文,从交易池初始化、交易构造到交易执行,尽可能为读者全景展示以太坊中的交易所涉及的方方面面。对于交易的打包涉及状态树、数据库等内容,为强化文章专题性,我们将这一部分内容放到下一篇文章内。交易池初始化#在交易进行之前,节点首先需要完成节点初始化,本节内容主要聚焦于此。节点需要对以下数据进行初始化:type TxPoolConfig struct {

Locals []common.Address // Addresses that should be treated by default as local

NoLocals bool // Whether local transaction handling should be disabled

Journal string // Journal of local transactions to survive node restarts

Rejournal time.Duration // Time interval to regenerate the local transaction journal

PriceLimit uint64 // Minimum gas price to enforce for acceptance into the pool

PriceBump uint64 // Minimum price bump percentage to replace an already existing transaction (nonce)

AccountSlots uint64 // Number of executable transaction slots guaranteed per account

GlobalSlots uint64 // Maximum number of executable transaction slots for all accounts

AccountQueue uint64 // Maximum number of non-executable transaction slots permitted per account

GlobalQueue uint64 // Maximum number of non-executable transaction slots for all accounts

Lifetime time.Duration // Maximum amount of time non-executable transaction are queued

}

各参数含义如下:Locals 本地账户地址列表。在以太坊执行层节点内,本地交易拥有一系列特权,节点会监控交易来源地址并确定是否将其列为本地交易NoLocals 禁止本地交易处理,将所有交易均列为远程交易(即无特权交易)Journal 对交易池内的本地交易进行数据持久化的文件名Rejournal 进行数据持久化的时间间隔PriceLimit 交易池接受到最小gas价格,在EIP1559交易中代表最小Priority Fee价格PriceBump 交易gas价格提升的最小百分比AccountSlots 单个账户可执行交易的最大容量GlobalSlots 所有账户可执行交易的最大容量AccountQueue 最大单个账户非可执行交易容量GlobalQueue 全局最大非可执行交易容量Lifetime 非可执行交易的存活时间我们在上文中使用了交易容量而非交易数量,两者具有一定的区别,一般来说,一笔交易占用 1 单位交易容量,具体计算公式如下:func numSlots(tx *types.Transaction) int {

return int((tx.Size() + txSlotSize - 1) / txSlotSize)

}

其中txSlotSize为常量,其值为32768。tx.Size()代表一笔交易经过RLP编码后的体积,单位为bytes。正常交易都仅占用 1 单位交易容量。设置上述规则的原因在于避免部分用户构建超大交易占用交易池资源,正常来说一笔交易仅占用2000 bytes左右。上述各值的初始化如下:var DefaultTxPoolConfig = TxPoolConfig{

Journal: "transactions.rlp",

Rejournal: time.Hour,

PriceLimit: 1,

PriceBump: 10,

AccountSlots: 16,

GlobalSlots: 4096 + 1024, // urgent + floating queue capacity with 4:1 ratio

AccountQueue: 64,

GlobalQueue: 1024,

Lifetime: 3 * time.Hour,

}

在交易池中,我们把交易分为远程交易(remote transactions)和本地交易(local transaction)。其中,后者具有以下优先级:写入Journal文件中,在节点启动时直接载入交易池不受交易池中的PriceLimit等限制在交易排序时优先级最高不会因为交易队列已满等原因被交易队列剔除我们使用RPC API向节点发送的交易也属于local transactions(前提为节点将NoLocals设置为False)。此处的PriceLimit参数对应EIP1559交易中的Max Fee参数,这意味着只要Max Fee大于PriceLimit即可进入交易池在此处也出现了两种交易类型,如下:可执行交易(executable transaction),此交易位于pending队列中,极有可能被节点封装进入下一个区块不可执行交易(non-executable transaction),此交易位于queued队列中,不太可能被节点封装进入下一个区块封装(seal)是目前以太坊对于区块打包的描述我们通过NewTxPool函数使用上述初始化配置实现交易池的初始化。由于篇幅限制,我们不对其进行详细介绍。初始化完成后,我们通过SubscribeNewTxsEvent函数订阅在以太坊网络中广播的新的交易项目。交易构造#本节内容主要介绍客户端如何构造一笔以太坊交易。鉴于本文的很多读者并没有独立运行的以太坊节点,我们在此处主要介绍通过以太坊的API构建交易。在一笔交易的最初阶段,用户需要完成交易的初始化,设置一笔交易的各个参数。在此处,我们以以太坊标准APIeth_sendTransaction为例向大家介绍一笔交易的具体构成,具体构成如下:type 交易类型,如果使用EIP1559类型交易,则设置为0x02nonce 用户的nonce,此数值会在用户完成每一笔交易后增加1to 交易目标地址from 交易来源地址gas 即gas limit,具体参考Gas Limit 的获取value 交易转账的ETH数量(单位为wei)input 交易包含的合约运行数据,如果交互对象不是合约,可置为0xgasPrice 如果使用EIP1559,此项可置为空maxPriorityFeePerGas 设置的Max Priority FeemaxFeePerGas 设置Max FeeaccessList 由EIP2930进行了一些规定,由于目前使用较少,我们不进行介绍chainID 链ID,可通过ChainList获得相关数据接下来,我们尝试使用MetaMask提供的API构建一笔交易。首先,我们需要任一已被MetaMask授权的网站进行测试。在此处我们以MetaMask的演示网站MetaMask Test Dapp为例。点击CONNECT进行账户授权,授权完成后,可以点击ETH_ACCOUNTS与自己的地址进行对比。完成上述准备后,点击F12进入开发者模式后选择Console进入Javascript终端。输入以下内容初始化交易参数:const transactionParameters = {

to: '0x0000000000000000000000000000000000000000',

from: ethereum.selectedAddress,

value: '0x00',

data:

'0x7f7465737432000000000000000000000000000000000000000000000000000000600057'

};

我们在此处省略了很多字段,这些字段会被MetaMask自动补齐。输入内容并运行:const txHash = await ethereum.request({

method: 'eth_sendTransaction',

params: [transactionParameters],

});

如果一切顺利,读者可以看到如下内容:

如果读者需要设置gas、value等参数,需要注意这些参数均使用wei作为单位,同时使用 16 进制进行编码。1 wei 为 0.000000000000000001 eth。更加详细的对于此API的说明,读者可以自行参考文档或者前往MetaMask JSON-RPC API Reference值得注意的是,大部分RPC服务商均不支持此API。读者可以发现上述交易中不包含签名,但由于RPC服务商不托管用户私钥,不能对交易进行签名,所以不能进行交易提交。MetaMask钱包中包含用户私钥所以可以调用此函数。RPC服务商一般允许使用eth_sendRawTransaction接口,此接口需要提交已经完成签名的并使用RLP编码的交易。本质上,MetaMask也调用了此接口。如果读者希望通过命令行提交交易,可以使用Foundry提供的cast命令,具体可以参考cast send命令,支持上述所有参数。一个最简单的案例如下:cast send 0x11475691C2CAA465E19F99c445abB31A4a64955C --value 0.001ether --gas-limit 21000 --gas-price 5gwei --priority-gas-price 1.5gwei --private-key $pk --rpc-url https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161

其中$pk需要替换为用户自己的私钥。--gas-price的含义为Max Fee,--priority-gas-price含义为Max priority fee,详细介绍请参考上文给出的文档。由于后文会使用到以太坊内的交易类型,在此处,我们一并给出交易在go-ethereum中的接口,如下:type TxData interface {

txType() byte // returns the type ID

copy() TxData // creates a deep copy and initializes all fields

chainID() *big.Int

accessList() AccessList

data() []byte

gas() uint64

gasPrice() *big.Int

gasTipCap() *big.Int

gasFeeCap() *big.Int

value() *big.Int

nonce() uint64

to() *common.Address

rawSignatureValues() (v, r, s *big.Int)

setSignatureValues(chainID, v, r, s *big.Int)

}

各个参数的含义如下:txType 返回交易的类型,对应type参数gasTipCap 对应交易设置中的maxPriorityFeePerGas,即Max Priority FeegasFeeCap 对应交易设置中的maxFeePerGas,即Max Fee其他参数较为简单,读者可以直接通过名称推断其含义,故不再进行介绍。交易池添加交易#当交易完成设置并通过API发送后,节点中的交易池会接受到此交易,并将其纳入自己的交易队列中。在详细分析交易进入队列之前,我们首先讨论一下以太坊中交易队列的类型。在以太坊中,我们可以将交易队列使用以下Venn图表示:所有交易可以根据来源首先被划分为两类:本地交易 local transaction远程交易 remote transaction正如前文所言,前者在优先级上高于后者所有交易,所以在以太坊交易池中属于最高等级,需要独立对待。而远程交易remote transaction则被细分为了以下两个队列:pending队列 - 此队列数据基本可以保证会被纳入下一个区块,而在交易广播时也只广播此队列内的交易queued队列(亦称queue队列) - 此队列内的数据只能在交易池刷新队列时可能被纳入pending队列,我们会在后文进行介绍具体的更新规则但在go-ethereum中,将local transaction保存在了pending队列中,但另一方面保证了local transaction不会被pending队列剔除在go-ethereum中,上述队列定义如下:pending map[common.Address]*txList // All currently processable transactions

queue map[common.Address]*txList // Queued but non-processable transactions

在正常情况下,当一个新的交易进入节点交易池后,此交易有以下去向:大部分情况下直接进入queue队列等待刷新少部分用于增加gas费用的交易替换pending中的原有交易被纳入pending队列因不满足交易条件而被删除我们首先分析用于在交易池中加入单个交易的add函数,其代码非常长,我们将逐块分析:func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err error)

函数定义说明,此函数接受交易和标识交易是否为本地交易的local标识符作为输入,返回代表此交易是否替换了其他交易的replaced标识和错误err整个流程可以使用以下流程图说明:hash := tx.Hash()

if pool.all.Get(hash) != nil {

log.Trace("Discarding already known transaction", "hash", hash)

knownTxMeter.Mark(1)

return false, ErrAlreadyKnown

}

首先获得交易的哈希值,如果交易与交易池内的任何交易的哈希值相同,我们则丢弃此交易,并抛出异常isLocal := local || pool.locals.containsTx(tx)

此代码判断交易是否为local transaction。如果满足local标识符为True或交易发送者位于Locals地址列表内条件,则认定此交易为local transactionif err := pool.validateTx(tx, isLocal); err != nil {

log.Trace("Discarding invalid transaction", "hash", hash, "err", err)

invalidTxMeter.Mark(1)

return false, err

}

使用validateTx函数验证交易是否符合交易池的要求,限于篇幅,我们在此处直接给出validateTx函数验证的内容,具体代码实现请自行查找。具体验证内容如下:交易进行RLP编码后体积不大于131072 bytes交易的Gas Limit不大于 3000 万(即当前区块的GasLimit)交易的Max Fee和Max Priority Fee不大于2 ^ 256交易的Max Priority Fee小于Max Fee交易签名正确交易的Max Priority Fee大于交易池设置的PriceLimit交易的nonce大于交易者当前的nonce交易者账户余额可以支付交易的Gas费用满足AccessList的一些gas要求如果用户提交给节点的交易无法满足上述条件,则直接被丢弃。当交易经过校验后,交易或被纳入queued或pending队列中,这一部分逻辑较为复杂。首先,我们分析交易池容量已满的情况,我们使用以下的代码判定此情况:uint64(pool.all.Slots()+numSlots(tx)) > pool.config.GlobalSlots+pool.config.GlobalQueue

其中pool.all.Slots()会返回目前交易池内所有交易所占用的交易容量,numSlots(tx)计算准备进入交易池的交易的所占用的交易容量,如果两者之和大于GlobalSlots(所有账户可执行交易的最大容量)和GlobalQueue(全局最大非可执行交易容量),我们可以判断交易池已满。if !isLocal && pool.priced.Underpriced(tx) {

log.Trace("Discarding underpriced transaction", "hash", hash, "gasTipCap", tx.GasTipCap(), "gasFeeCap", tx.GasFeeCap())

underpricedTxMeter.Mark(1)

return false, ErrUnderpriced

}

当交易不是优先级最高的本地交易,且交易的gasTipCap(Max Priority Fee)低于交易池内最低gasTipCap时,我们直接丢弃此交易。交易池内维护有一个由交易价格构成的堆heap,可以快速查找价格最低的交易if pool.changesSinceReorg > int(pool.config.GlobalSlots/4) {

throttleTxMeter.Mark(1)

return false, ErrTxPoolOverflow

}

此处涉及到一个名词Reorg,此名词表示交易池重排。每当一个新的区块被生成,交易池会根据区块中的交易信息对交易池内的交易进行重组,包括在交易池内删除已被打包的交易(这部分交易往往位于pending队列中)、升级符合条件的queued队列中的交易、在已满的队列中删除交易以及广播交易。该部分核心实现为runReorg函数,此函数会在后文多次出现。我们一般使用channel这种特殊的go数据类型与作为单独线程的runReorg函数进行通信。在此代码中changesSinceReorg代表现在需要重组的交易数量,如果此交易数量大于GlobalQueue(所有账户可执行交易的最大容量)的1 / 4,我们则认为交易池非常拥挤,直接丢弃新的交易。在交易池启动后,runReorg函数会自动清除已满队列中的交易,开发者认为通过add函数删除太多交易并不合适,具体可参考#23095drop, success := pool.priced.Discard(pool.all.Slots()-int(pool.config.GlobalSlots+pool.config.GlobalQueue)+numSlots(tx), isLocal)

// Special case, we still can't make the room for the new remote one.

if !isLocal && !success {

log.Trace("Discarding overflown transaction", "hash", hash)

overflowedTxMeter.Mark(1)

return false, ErrTxPoolOverflow

}

// Bump the counter of rejections-since-reorg

pool.changesSinceReorg += len(drop)

// Kick out the underpriced remote transactions.

for _, tx := range drop {

log.Trace("Discarding freshly underpriced transaction", "hash", tx.Hash(), "gasTipCap", tx.GasTipCap(), "gasFeeCap", tx.GasFeeCap())

underpricedTxMeter.Mark(1)

pool.removeTx(tx.Hash(), false)

}

当我们认为交易可以被删除,我们则进行真正的交易删除步骤。首先通过pool.priced.Discard函数移除占用pool.all.Slots()-int(pool.config.GlobalSlots+pool.config.GlobalQueue)+numSlots(tx)单位的交易容量的交易。此函数不会真正删除交易,而是会返回待删除交易的列表,待删除交易的筛选规则为交易由高到低进行排序,优先删除价格最低的交易(本地交易不会被删除)。如果无法获得待删除列表,且交易不是本地交易,则返回错误。如果获得待删除交易列表,我们会更新changesSinceReorg变量。然后使用pool.removeTx真正执行删除步骤。当我们完成交易池容量方面的处理后,我们接下来处理一部分特殊的交易,即用于替换交易池pending队列的交易。这种替换交易往往用于增加已经在队列中的交易的gas,保证交易可以尽快完成。我们可以通过以下代码判断此交易是否为替换交易:from, _ := types.Sender(pool.signer, tx) // already validated

if list := pool.pending[from]; list != nil && list.Overlaps(tx)

首先使用types.Sender(pool.signer, tx)获得交易的具体签名人,然后前往pool.pending队列中查询此用户名下的所有交易,并使用Overlaps函数判断交易是否存在重复。pool.pending是一个映射pending map[common.Address]*txList,我们可以通过用户地址在其内部快速检索相关交易当我们发现交易池内已包含此笔交易后,我们会尝试将交易加入交易池,代码如下:inserted, old := list.Add(tx, pool.config.PriceBump)

if !inserted {

pendingDiscardMeter.Mark(1)

return false, ErrReplaceUnderpriced

}

此处使用到了Add函数,此函数接受交易tx后会在交易队列中查询与tx的nonce相同的交易。获得交易列表内的旧交易后,函数会校验gasTipCap和gasFeeCap相较于旧交易的增加幅度是否符合要求,如果满足上述条件,则直接在交易列表内替换旧的交易。同时返回需要替换的旧交易,以满足后续处理流程。当然,如果此处发现Add函数返回替换失败的标识,我们直接放弃替换。关于Add函数,其具体代码如下:func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) {

// 获取交易列表内 Nonce 相同的旧交易

old := l.txs.Get(tx.Nonce())

if old != nil {

// 要求新交易的 GasFeeCap 和 GasTipCap 大于旧交易

if old.GasFeeCapCmp(tx) >= 0 || old.GasTipCapCmp(tx) >= 0 {

return false, nil

}

// thresholdFeeCap = oldFC * (100 + priceBump) / 100

a := big.NewInt(100 + int64(priceBump))

aFeeCap := new(big.Int).Mul(a, old.GasFeeCap())

aTip := a.Mul(a, old.GasTipCap())

// thresholdTip = oldTip * (100 + priceBump) / 100

b := big.NewInt(100)

thresholdFeeCap := aFeeCap.Div(aFeeCap, b)

thresholdTip := aTip.Div(aTip, b)

// 要求新交易的 GasFeeCap 和 GasTipCapCmp 增加幅度大于 PriceBump

if tx.GasFeeCapIntCmp(thresholdFeeCap) < 0 || tx.GasTipCapIntCmp(thresholdTip) < 0 {

return false, nil

}

}

// 使用新交易覆盖旧交易

l.txs.Put(tx)

// 以下内容为刷新参数

if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 {

l.costcap = cost

}

if gas := tx.Gas(); l.gascap < gas {

l.gascap = gas

}

return true, old

}

读者可自行查阅上述代码及其注释理解实现过程读者可能发现上述流程仅对交易列表进行了替换,而不是对pool交易池的其他参数进行同步更新,所以我们使用以下代码更新交易池内的其他参数:if old != nil {

pool.all.Remove(old.Hash())

pool.priced.Removed(1)

pendingReplaceMeter.Mark(1)

}

pool.all.Add(tx, isLocal)

pool.priced.Put(tx, isLocal)

pool.journalTx(from, tx)

pool.queueTxEvent(tx)

log.Trace("Pooled new executable transaction", "hash", hash, "from", from, "to", tx.To())

首先在用于维护交易池内所有交易的pool.all队列中删除此交易,同时在更新交易价格构成的pool.priced队列。使用pool.journalTx方法尝试将此替换交易纳入用于交易数据存储Journal内。此处使用了尝试是因为在journalTx函数中会对交易的from进行审查,如果交易不来自local地址,则不会进行存储。在此处,使用了一个较为特殊的函数queueTxEvent,此函数会将交易推送给pool.queueTxEventCh通道,此通道的最终目的地为runReorg函数,并对queueTxEvent队列进行修改。case tx := <-pool.queueTxEventCh:

addr, _ := types.Sender(pool.signer, tx)

if _, ok := queuedEvents[addr]; !ok {

queuedEvents[addr] = newTxSortedMap()

}

queuedEvents[addr].Put(tx)

此处没有设置scheduleReorgLoop中的一个重要参数launchNextRun,此参数用于判断runReorg,即重排过程是否立即执行,若不设置,则意味着重排过程不会立即进行。而queueTxEvents定义如下:queuedEvents = make(map[common.Address]*txSortedMap)

其中txSortedMap是一个nonce到交易transaction的堆(heap)。最终,queuedEvents映射会被用于交易广播,以下给出的代码摘自runReorg函数的最后,其中events即此处的queuedEvents。if len(events) > 0 {

var txs []*types.Transaction

for _, set := range events {

txs = append(txs, set.Flatten()...)

}

pool.txFeed.Send(NewTxsEvent{txs})

}

完成上述步骤后,我们会更新账户最新的活动时间,完成整个替换交易流程。代码如下:pool.beats[from] = time.Now()

return old != nil, nil

如果一笔交易既不是对现有交易的替换,我们会使用使用以下代码直接将其推入queue队列中,代码如下:replaced, err = pool.enqueueTx(hash, tx, isLocal, true)

if err != nil {

return false, err

}

此处的enqueueTx会将交易推送进入queue队列,限于篇幅,我们在此处以注释的形式解释此函数的源代码:func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction, local bool, addAll bool) (bool, error) {

from, _ := types.Sender(pool.signer, tx) // already validated

// 如果 queue 队列内没有此地址记录,则创建一个新的映射

// queue 的定义为 map[common.Address]*txList

if pool.queue[from] == nil {

pool.queue[from] = newTxList(false)

}

// 使用 (l *txList) Add 直接加入交易

// 详情请参考上文给出的代码解析

inserted, old := pool.queue[from].Add(tx, pool.config.PriceBump)

// 处理插入失败的情况

if !inserted {

queuedDiscardMeter.Mark(1)

return false, ErrReplaceUnderpriced

}

if old != nil {

// 发生替换交易情况,刷新 pool 参数

// 类似上文提到的 替换交易 的后续处理

pool.all.Remove(old.Hash())

pool.priced.Removed(1)

queuedReplaceMeter.Mark(1)

} else {

// 没有发生替换交易的情况,增加计数器

// 计数器用于评估等功能

queuedGauge.Inc(1)

}

// If the transaction isn't in lookup set but it's expected to be there,

// show the error log.

if pool.all.Get(hash) == nil && !addAll {

log.Error("Missing transaction in lookup set, please report the issue", "hash", hash)

}

// 刷新 pool 中的 all 和 priced 变量

if addAll {

pool.all.Add(tx, local)

pool.priced.Put(tx, local)

}

// 刷新交易账户的生命周期

if _, exist := pool.beats[from]; !exist {

pool.beats[from] = time.Now()

}

return old != nil, nil

}

完成上述重要任务后,最后我们处理本地交易的问题,代码如下:if local && !pool.locals.contains(from) {

log.Info("Setting new local account", "address", from)

pool.locals.add(from)

pool.priced.Removed(pool.all.RemoteToLocals(pool.locals)) // Migrate the remotes if it's marked as local first time.

}

if isLocal {

localGauge.Inc(1)

}

pool.journalTx(from, tx)

log.Trace("Pooled new future transaction", "hash", hash, "from", from, "to", tx.To())

return replaced, nil

如果发现交易被标记为local,但账户没有被标记为local,则直接将交易发生账户列入locals名单内并对此地址下的所有交易进行提权至本地交易(local transaction),最终使用journalTx存储本地交易。当然,正常情况下我们更有可能一次性增加大量交易,所以在源代码中,我们可以看到大量函数都使用了addTxs函数,而此函数中的一个核心部分是addTxsLocked函数,我们首先介绍此函数。代码如下:func (pool *TxPool) addTxsLocked(txs []*types.Transaction, local bool) ([]error, *accountSet) {

dirty := newAccountSet(pool.signer)

errs := make([]error, len(txs))

for i, tx := range txs {

replaced, err := pool.add(tx, local)

errs[i] = err

if err == nil && !replaced {

dirty.addTx(tx)

}

}

validTxMeter.Mark(int64(len(dirty.accounts)))

return errs, dirty

}

此处使用到了pool.add函数用于向交易池内增加交易,但为了方便使用runReorg函数进行交易重排,在此处定义了一个较为特殊的dirty变量,此变量为一个交易发送者地址列表,我们使用了dirty.addTx(tx)向此地址列表内增加新的交易发送者信息。此函数名内包含Locked字样,这意味着此函数必须在交易池拿到线程锁时才能使用我们也对此函数进行分析。func (pool *TxPool) addTxs(txs []*types.Transaction, local, sync bool) []error

在此函数中,各参数含义如下:txs代表需要加入交易池的交易集合local用于标识此交易集合内的交易是否为本地交易sync用于标识此交易集合内的交易是否立即用于提权,用于测试正如前文所述,一般来说交易会被直接推入queue队列内,而函数runReorg会定期运行对交易进行提权至pending队列内。如果将addTxs中的sync设置为True,则意味着在下一次runReorg运行时会直接进行提权此函数的流程图如下:addTxs函数首先对交易进行了一个简单的验证,具体代码如下:var (

errs = make([]error, len(txs))

news = make([]*types.Transaction, 0, len(txs))

)

for i, tx := range txs {

// 验证交易是否已经存在在交易池内

if pool.all.Get(tx.Hash()) != nil {

errs[i] = ErrAlreadyKnown

knownTxMeter.Mark(1)

continue

}

// 验证交易签名是否正确

_, err := types.Sender(pool.signer, tx)

if err != nil {

errs[i] = ErrInvalidSender

invalidTxMeter.Mark(1)

continue

}

// 将交易添加到 news 列表内

news = append(news, tx)

}

if len(news) == 0 {

return errs

}

在完成基本的交易校验后,使用pool.addTxsLocked函数将交易加入交易池内,代码如下:pool.mu.Lock()

newErrs, dirtyAddrs := pool.addTxsLocked(news, local)

pool.mu.Unlock()

此处使用了pool.mu.Lock()及pool.mu.Unlock()实现交易池线程锁定和解锁。var nilSlot = 0

for _, err := range newErrs {

for errs[nilSlot] != nil {

nilSlot++

}

errs[nilSlot] = err

nilSlot++

}

一个简单的for循环实现newErrs中的错误到err的转移。done := pool.requestPromoteExecutables(dirtyAddrs)

if sync {

<-done

}

return errs

此函数实际上实现了将交易通过channel推送给runReorg的作用。其中requestPromoteExecutables的定义如下:func (pool *TxPool) requestPromoteExecutables(set *accountSet) chan struct{} {

select {

case pool.reqPromoteCh <- set:

return <-pool.reorgDoneCh

case <-pool.reorgShutdownCh:

return pool.reorgShutdownCh

}

}

对于具体的channel作用,我们会在下一节进行介绍。交易重排#我们在上一节内大量提到了runReorg函数及其作用,在本节我们将介绍runReorg实现交易重排的具体原理及其实现。runReorg函数是由scheduleReorgLoop函数启动,而scheduleReorgLoop函数在交易池初始化时就被调用,具体可以参考NewTxPool函数中的下述代码:go pool.scheduleReorgLoop()

而在scheduleReorgLoop函数内,我们可以看到大量的channel的使用。我对于golang语言中的channel使用并不是非常熟悉。所以在后文内可能出现错误,发现错误的读者可以通过我的博客中给出的邮箱地址向我反馈。我们首先给出一系列的channel定义:reqResetCh chan *txpoolResetRequest

reqPromoteCh chan *accountSet

queueTxEventCh chan *types.Transaction

reorgDoneCh chan chan struct{}

reorgShutdownCh chan struct{} // requests shutdown of scheduleReorgLoop

其传输的信息主要为:reqResetCh 传输用于区块更新的相关信息reqPromoteCh 传输用于更新的指定地址集合queueTxEventCh 传输用于加入queued队列交易的信息reorgDoneCh 传输由空结构体构成的channelreorgShutdownCh 传输reorg停止信号一个简单的示例图,如下:在这些channel中,较难理解的是reorgDoneCh和reorgShutdownCh,这两个变量的设计是为了保证并发的正确性。我们首先介绍reorgDoneCh变量,此变量非常奇怪属于chan chan struct{}类型。对于任何一个channel,分析其作用的最好方法就是分析其数据发送者和数据接收者。reorgDoneCh的数据发送者代码如下:case req := <-pool.reqResetCh:

// Reset request: update head if request is already pending.

if reset == nil {

reset = req

} else {

reset.newHead = req.newHead

}

launchNextRun = true

pool.reorgDoneCh <- nextDone

case req := <-pool.reqPromoteCh:

// Promote request: update address set if request is already pending.

if dirtyAccounts == nil {

dirtyAccounts = req

} else {

dirtyAccounts.merge(req)

}

launchNextRun = true

pool.reorgDoneCh <- nextDone

上述代码均来自scheduleReorgLoop函数内,我们可以看到都是在进行一系列数据处理后在进行推送nextDone。其中nextDone的定义为make(chan struct{}),是符合channel的类型要求的。上文给出的case代码块内,我们可以看到launchNextRun被设置为true,这意味着重排会立即进行。当然,此时进行的重排也会对上文介绍的queuedEvents中的内容一并进行重排。我们进一步分析数据接收者,代码如下:func (pool *TxPool) requestReset(oldHead *types.Header, newHead *types.Header) chan struct{} {

select {

case pool.reqResetCh <- &txpoolResetRequest{oldHead, newHead}:

return <-pool.reorgDoneCh

case <-pool.reorgShutdownCh:

return pool.reorgShutdownCh

}

}

func (pool *TxPool) requestPromoteExecutables(set *accountSet) chan struct{} {

select {

case pool.reqPromoteCh <- set:

return <-pool.reorgDoneCh

case <-pool.reorgShutdownCh:

return pool.reorgShutdownCh

}

}

这些接收函数均直接选择将pool.reorgDoneCh内的空channel作为return返回,如果读者进一步研究这两个函数的应用会发现函数的return值并没有被具体的运行逻辑使用。造成这种情况的原因是reorgDoneCh的目的仅是保证reqResetCh和reqPromoteCh函数发送给reqResetCh和reqPromoteCh的数据会被scheduleReorgLoop正确处理后关闭。更加详细的解释是当我们通过return <-pool.reorgDoneCh获得一个channel(即nextDone)时,由于channel自身具有阻塞性,主函数只有在scheduleReorgLoop进行完数据处理(即上文给出的case块)运行后退出。这一行为有效保障函数运行的同步。这种运行逻辑与async/await类似,在golang中,类似reorgDoneCh的chan chan struct{}是一种重要的无锁队列结构,假如我们不进行reorgDoneCh队列操作,那么使用requestPromoteExecutables的addTxs函数就可以无视scheduleReorgLoop的数据处理流程而自行工作,这可能导致数据在scheduleReorgLoop进行数据处理操作时被推入函数,造成并发冲突。reorgDoneCh代表的chan chan struct{}是 无锁 Channel 的重要实现方式,其他实现方式可以参考Go channels on steroids。如果读者想进一步深入学习,建议阅读Go语言设计与实现。当然,读者可以分析nextDone也是一个channel,在addTxs函数中,我们使用了以下代码:done := pool.requestPromoteExecutables(dirtyAddrs)

if sync {

<-done

}

此代码从done中获取成员,可以保证在addTxs一定在runReorg运行完后结束。上述流程都使用了channel的阻塞特性,如果读者对于go语言的此部分不熟悉,可以参考Go Channel 详解另一个较难理解的队列为reorgShutdownCh队列,此队列用于系统关闭。但我们分析此队列没有数据发送者,但存在大量的数据接收者,如下:case <-pool.reorgShutdownCh:

// Wait for current run to finish.

if curDone != nil {

<-curDone

}

close(nextDone)

return

以上代码块来自scheduleReorgLoop函数,此函数尝试早reorgShutdownCh队列中获得内容,但由于没有数据发送者,这会导致阻塞情况的发送,此case不会被激活。继续查找相关代码,我们可以查询到以下代码:case <-pool.chainHeadSub.Err():

close(pool.reorgShutdownCh)

return

此代码的关键在于close(pool.reorgShutdownCh),在go语言中,当我们关闭channel时,channel的阻塞状态消失,接收者可以在channel中获得nil类型的成员。这意味着当我们关闭reorgShutdownCh时,上文给出的case <-pool.reorgShutdownCh会被激活,在此处依旧使用了channel的阻塞特性,通过阻塞curDone空队列保证了runReorg运行结束后,再进行return操作。在上文中,我们讨论了scheduleReorgLoop与一系列channel之间的相互关系和数据流动。简单来说,所有对于交易重排的数据都会使用channel推送给的scheduleReorgLoop函数,此函数通过select结构进行分类处理,这些处理后的数据最终都会被用于一个关键函数,也是我们下文主要介绍的函数,即runReorg函数。在runReorg的开始设定了一些用于记录和关闭channel的defer部分,由于这些内容并不重要且主要涉及golang语言特性,所以在此处为我们直接跳过此部分。同时,在下文中我们认为reset结构体为空,因为此结构体主要用于接受新的区块后进行交易池更新,与我们此处设定的单笔交易进入交易池流程不符,我们会在本文的在介绍交易池更新时给出对于此部分的解析。我们首先给出函数的定义,代码如下:func (pool *TxPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirtyAccounts *accountSet, events map[common.Address]*txSortedMap)

各参数含义如下:done 用于阻塞状态的channel,实现addTxs中的sync作用reset 用于区块更新后刷新交易池的结构体,在本节我们不会详细说明dirtyAccounts 此变量为需要提权交易的账户集合,由上文给出的addTxs函数增加账户events 用于广播的替换交易,其成员主要来自上文给出的add函数中的替换交易池内已有交易部分我们首先处理对账户集合内的账户进行提权的过程。代码如下:var promoteAddrs []common.Address

if dirtyAccounts != nil && reset == nil {

promoteAddrs = dirtyAccounts.flatten()

}

pool.mu.Lock()

promoted := pool.promoteExecutables(promoteAddrs)

我们在上述代码中省略了reset部分。其中的核心函数是promoteExecutables,其代码及对应的注释如下:func (pool *TxPool) promoteExecutables(accounts []common.Address) []*types.Transaction {

var promoted []*types.Transaction

// 循环 accounts 并寻找可提权交易

for _, addr := range accounts {

list := pool.queue[addr]

if list == nil {

continue // Just in case someone calls with a non existing account

}

// 丢弃所有低于当前状态账户 nonce 的交易

forwards := list.Forward(pool.currentState.GetNonce(addr))

for _, tx := range forwards {

hash := tx.Hash()

pool.all.Remove(hash)

}

log.Trace("Removed old queued transactions", "count", len(forwards))

// 丢弃所有账户余额无法满足 gas 消耗的交易

drops, _ := list.Filter(pool.currentState.GetBalance(addr), pool.currentMaxGas)

for _, tx := range drops {

hash := tx.Hash()

pool.all.Remove(hash)

}

log.Trace("Removed unpayable queued transactions", "count", len(drops))

queuedNofundsMeter.Mark(int64(len(drops)))

// 使用 pool.pendingNonces.get(addr) 获得 pending 队列中的最大 nonce

// 使用 list.Ready 在 quenue 队列中获得上述 nonce 后的交易

readies := list.Ready(pool.pendingNonces.get(addr))

for _, tx := range readies {

hash := tx.Hash()

// 使用 pool.promoteTx 函数对交易进行提权

// 即将交易自 quenue 转移到 pending

if pool.promoteTx(addr, hash, tx) {

promoted = append(promoted, tx)

}

}

log.Trace("Promoted queued transactions", "count", len(promoted))

queuedGauge.Dec(int64(len(readies)))

// 判断用户的 quenue 队列中交易数量是否符合需求

// 如不符合则删除部分交易

var caps types.Transactions

if !pool.locals.contains(addr) {

caps = list.Cap(int(pool.config.AccountQueue))

for _, tx := range caps {

hash := tx.Hash()

pool.all.Remove(hash)

log.Trace("Removed cap-exceeding queued transaction", "hash", hash)

}

queuedRateLimitMeter.Mark(int64(len(caps)))

}

// Mark all the items dropped as removed

pool.priced.Removed(len(forwards) + len(drops) + len(caps))

queuedGauge.Dec(int64(len(forwards) + len(drops) + len(caps)))

if pool.locals.contains(addr) {

localGauge.Dec(int64(len(forwards) + len(drops) + len(caps)))

}

// Delete the entire queue entry if it became empty.

if list.Empty() {

delete(pool.queue, addr)

delete(pool.beats, addr)

}

}

return promoted

}

综上所述,对于交易在quenue到pending的转换并没有及其严格的审查,更不会校验交易中的内容是否可以正常运行。可能有读者发现在promoteExecutables函数内,我们没有对交易池pending队列长度等内容进行检测,原因在于这一部分是通过truncate系列函数实现的,代码如下:pool.truncatePending()

pool.truncateQueue()

限于篇幅,我们无法具体分析这两个函数的代码实现,但我们仍会给出相关的逻辑实现。truncatePending会将所有交易数量超过交易池限制AccountSlots且不在本地账户的账户地址构成一个以交易数量为权重的prque。完成队列构建后,代码会对此队列按权重进行循环,即权重较大者首先进入循环,并在每一次循环中,将权重较大的部分交易数量依次减去 1 ,直至总的交易数量满足交易池要求为止。值得注意的是,此流程没有考虑账户本身的交易数量限制。如果经过上述循环依旧不满足交易池要求,则以账户最大可执行交易数量为限制进行循环,直至满足要求。建议阅读源代码理解部分truncatePending函数删除账户交易时,首先按账户进入交易池的顺序进行排列,较晚进入交易池的交易被优先清理。如果此地址内的交易小于需要丢弃的交易总量,则删除此账户下的所有交易。否则,则仅删除满足要求的交易。关于以上内容,一个较好的参考资料是以太坊技术与实现,读者可以自行参考阅读完成上述流程后,我们进行数据统计和变量重置工作,代码如下:dropBetweenReorgHistogram.Update(int64(pool.changesSinceReorg))

pool.changesSinceReorg = 0 // Reset change counter

pool.mu.Unlock()

dropBetweenReorgHistogram用于统计在两次reorg之间升级的交易数量。统计后重置changesSinceReorg变量,并释放线程锁。上述步骤完成了对于dirtyAccounts中的交易的提权,我们还需要对events中的单个交易进行广播。此过程的代码我们已在上文解释add函数中的交易替换部分时给出,此处不再赘述。区块打包#在完成交易进入交易池、交易提升至pending队列后,我们需要处理区块打包问题,考虑到文章的专题性,本节不会讨论以下问题:区块的具体结构和生成方法PoS共识算法本节仅关注交易池与区块打包的对接部分。此部分主要位于miner/worker.go文件内,我们所需要介绍内容的核心函数为fillTransactions,代码如下:func (w *worker) fillTransactions(interrupt *int32, env *environment) error {

// Split the pending transactions into locals and remotes

// Fill the block with all available pending transactions.

pending := w.eth.TxPool().Pending(true)

localTxs, remoteTxs := make(map[common.Address]types.Transactions), pending

for _, account := range w.eth.TxPool().Locals() {

if txs := remoteTxs[account]; len(txs) > 0 {

delete(remoteTxs, account)

localTxs[account] = txs

}

}

if len(localTxs) > 0 {

txs := types.NewTransactionsByPriceAndNonce(env.signer, localTxs, env.header.BaseFee)

if err := w.commitTransactions(env, txs, interrupt); err != nil {

return err

}

}

if len(remoteTxs) > 0 {

txs := types.NewTransactionsByPriceAndNonce(env.signer, remoteTxs, env.header.BaseFee)

if err := w.commitTransactions(env, txs, interrupt); err != nil {

return err

}

}

return nil

}

这一部分代码中使用了types.NewTransactionsByPriceAndNonce函数。调用此函数会构造以下类型:type TransactionsByPriceAndNonce struct {

txs map[common.Address]Transactions // Per account nonce-sorted list of transactions

heads TxByPriceAndTime // Next transaction for each unique account (price heap)

signer Signer // Signer for the set of transactions

baseFee *big.Int // Current base fee

}

其中,heads属于TxByPriceAndTime类型构成堆(heap),其具体定义为[]*TxWithMinerFee,进一步TxWithMinerFee的定义如下:type TxWithMinerFee struct {

tx *Transaction

minerFee *big.Int

}

此处出现了一个变量minerFee,此变量与gas费用有关,其具体的计算公式如下:min(GasTipCap, gasFeeCap-baseFee)

等价于

min(maxPriorityFeePerGas, maxFeePerGas-BaseFee)

在后文中,我们经常使用func (*TransactionsByPriceAndNonce).Pop()函数,此函数会返回交易队列中minerFee最大的交易,如果minerFee相同则返回发现时间较早的交易。在完成NewTransactionsByPriceAndNonce函数后,我们将使用commitTransactions函数,此函数在本节中属于核心地位,我们将着重介绍。此函数的定义如下:func (w *worker) commitTransactions(env *environment, txs *types.TransactionsByPriceAndNonce, interrupt *int32) error

在此处,我们忽略用于用于传输中断信息的interrupt变量,而另一个变量env则存储有封装区块所需要的一系列其他参数,在此次我们仍将省略不谈。接下来,我们分析其代码构成:第一步,初始化gas pool,并限定区块可用gas,代码如下:gasLimit := env.header.GasLimit

if env.gasPool == nil {

env.gasPool = new(core.GasPool).AddGas(gasLimit)

}

其中,函数AddGas的功能是提供gas限额。关于区块的GasLimit的讨论,可以参考以太坊机制详解:Gas Price计算中的内容。接下来,我们会进入到一个for循环,此循环没有限定条件,仅能依靠循环体内的break跳出。在此循环内首先检查了interrupt变量,我们跳过此部分。然后,检查了gasPool的余额,代码如下:if env.gasPool.Gas() < params.TxGas {

log.Trace("Not enough gas for further transactions", "have", env.gasPool, "want", params.TxGas)

break

}

如果检测到gasPool内的gas剩余小于21000,我们认为已达到区块的gasLimit,跳出循环。检测完gas限制后,我们进一步检测交易队列的情况,若此笔交易位于队列最后,则退出循环。代码如下:tx := txs.Peek()

if tx == nil {

break

}

其中,tx.Peek()会返回TransactionsByPriceAndNonce堆中的下一个元素,但与pop不同的是此操作不会影响堆的结构。在完成上述步骤后,我们对一项非常重要的参数进行校验,即判断交易的签名是否符合EIP155的规定,关于EIP155签名的详细内容,可以参考基于链下链上双视角深入解析以太坊签名与验证。代码如下:if tx.Protected() && !w.chainConfig.IsEIP155(env.header.Number) {

log.Trace("Ignoring reply protected transaction", "hash", tx.Hash(), "eip155", w.chainConfig.EIP155Block)

txs.Pop()

continue

}

如果交易不符合EIP155的规定,交易会不配剔除打包序列。完成基本的校验后,我们准备执行交易,执行交易的代码如下:env.state.Prepare(tx.Hash(), env.tcount)

logs, err := w.commitTransaction(env, tx)

在此段代码内,我们首先初始化state,即用来记录状态变化的数据库。在第二行里,我们通过commitTransaction正式提交交易。运行交易步骤包含大量的函数调用,限于篇幅,我们无法完整介绍。在此处,我们仅给出一系列函数调用中最核心的代码,如下:if contractCreation {

ret, _, st.gas, vmerr = st.evm.Create(sender, st.data, st.gas, st.value)

} else {

// Increment the nonce for the next transaction

st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)

ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value)

}

如果交易涉及合约创建,则调用st.evm.Create,否则则调用st.evm.Call函数,所以即使交易仅是一笔转账交易,以太坊节点依旧会调用EVM,这与一般的认识是不相符的。完成交易提交后,我们通过switch语句处理交易运行失败的各种情况,读者可以阅读相关代码。如果一切正常,我们运行以下代码块:case errors.Is(err, nil):

// Everything ok, collect the logs and shift in the next transaction from the same account

coalescedLogs = append(coalescedLogs, logs...)

env.tcount++

txs.Shift()

此代码会将日志推送到coalescedLogs日志中,然后运行tx.Shift()执行下一个交易。在完成交易的执行后,我们使用以下代码将运行日志作为订阅源供用户使用:if !w.isRunning() && len(coalescedLogs) > 0 {

cpy := make([]*types.Log, len(coalescedLogs))

for i, l := range coalescedLogs {

cpy[i] = new(types.Log)

*cpy[i] = *l

}

w.pendingLogsFeed.Send(cpy)

}

return nil

我们首先对coalescedLogs进行复制,然后直接使用Send发送订阅源。此订阅源并不是在广播交易,而只是供终端用户使用。在进行使用前,请确保拥有一个ws以太坊节点,在此处,我们使用了infura提供的服务。除此之外,读者应安装ws的客户端,在此处,我使用了utws作为客户端。输入以下命令:uwsc wss://mainnet.infura.io/ws/v3/YOUR_API_KEY

回车后,在>后键入以下内容:{"jsonrpc":"2.0", "id": 1, "method": "eth_subscribe", "params": ["newPendingTransactions"]}

输入如下图:

输出如下图:

在输出中,result代表交易的哈希值,读者可https://etherscan.io/tx/{result}形式的网址访问到交易详情。最后,我们介绍用于区块密封的函数,代码如下:func (w *worker) generateWork(params *generateParams) (*types.Block, error) {

work, err := w.prepareWork(params)

if err != nil {

return nil, err

}

defer work.discard()

if !params.noTxs {

interrupt := new(int32)

timer := time.AfterFunc(w.newpayloadTimeout, func() {

atomic.StoreInt32(interrupt, commitInterruptTimeout)

})

defer timer.Stop()

err := w.fillTransactions(interrupt, work)

if errors.Is(err, errBlockInterruptedByTimeout) {

log.Warn("Block building is interrupted", "allowance", common.PrettyDuration(w.newpayloadTimeout))

}

}

return w.engine.FinalizeAndAssemble(w.chain, work.header, work.state, work.txs, work.unclelist(), work.receipts)

}

目前以太坊已经完成了合并,所以此处最终的出块是由engine完成,即共识引擎。简单给出一个当前以太坊的节点架构图:

简单来说,当共识客户端(Consensus Client)被选为区块提案者(proposer)后,会在执行客户端(Exection Client)的交易池内筛选交易,并由执行客户端运行交易。最终,共识客户端将打包后的交易进行广播,由其他节点进行投票,最终确定一个区块。目前对于合并后的基础架构,概览性资料较少,我目前仍在研究相关内容,上述的流程可能有错误。如果您发现错误,请通过我的博客给出的邮箱与我联系。在此处,我们基本完成了一笔交易在以太坊执行层内的完整流程,接下来,我们介绍当区块到达交易池后,交易池重构的相关内容。交易池重构#我们在上文仅考虑了节点直接生产区块的区块,但在实际情况中,节点更有可能无法生产区块,而仅仅作为区块的接受方,接受其他节点生产的区块。我们势必限需要讨论节点在接受到其他节点发送的区块时如何进行交易池重构的问题 。在交易池主循环内,我们可以找到如下代码:case ev := <-pool.chainHeadCh:

if ev.Block != nil {

pool.requestReset(head.Header(), ev.Block.Header())

head = ev.Block

}

当交易池在chainHeadCh内获得新的区块头后,交易池会启动requestReset函数,此函数我们在上文已有所介绍,requestReset函数会将请求发送到reqResetCh的通道内,最终由scheduleReorgLoop函数接受,代码如下:case req := <-pool.reqResetCh:

// Reset request: update head if request is already pending.

if reset == nil {

reset = req

} else {

reset.newHead = req.newHead

}

launchNextRun = true

pool.reorgDoneCh <- nextDone

实际最终还是由runReorg运行,我们在此处仅接受上文未介绍的Reset部分,第一部分的代码如下:if reset != nil {

// Reset from the old head to the new, rescheduling any reorged transactions

pool.reset(reset.oldHead, reset.newHead)

// Nonces were reset, discard any events that became stale

for addr := range events {

events[addr].Forward(pool.pendingNonces.get(addr))

if events[addr].Len() == 0 {

delete(events, addr)

}

}

// Reset needs promote for all addresses

promoteAddrs = make([]common.Address, 0, len(pool.queue))

for addr := range pool.queue {

promoteAddrs = append(promoteAddrs, addr)

}

}

我们首先介绍除了reset外的其他部分,在完成reset函数后,我们首先删除events(内部含有准备加入quenue队列的交易)内所有小于当前状态数据内的nonce的交易。小于当前状态数据库内的nonce意味着此交易已被打包,不需要进行进一步处理。然后,我们将当前交易池内quenue队列中的所有交易列入promoteAddrs中,这意味着在之后的代码运行中,这些交易均会被升级为pending队列内的交易。最后,我们介绍较为复杂的reset函数,此函数负责向交易池内提交差异交易,而不负责删除交易,删除交易的代码我们会在第二部分进行介绍。我们首先介绍第一个if语句内的交易:if oldHead != nil && oldHead.Hash() != newHead.ParentHash {

// 获得区块编号

oldNum := oldHead.Number.Uint64()

newNum := newHead.Number.Uint64()

// 当新旧区块差异过大时,不进行处理

// 此种区块一般发生在节点同步数据时

if depth := uint64(math.Abs(float64(oldNum) - float64(newNum))); depth > 64 {

log.Debug("Skipping deep transaction reorg", "depth", depth)

} else {

// 声明需要丢弃和包含的交易

var discarded, included types.Transactions

var (

// 获取区块完整数据

rem = pool.chain.GetBlock(oldHead.Hash(), oldHead.Number.Uint64())

add = pool.chain.GetBlock(newHead.Hash(), newHead.Number.Uint64())

)

if rem == nil {

// 此情况属于特殊情况,即旧区块无法检索

if newNum >= oldNum {

log.Warn("Transaction pool reset with missing oldhead",

"old", oldHead.Hash(), "oldnum", oldNum, "new", newHead.Hash(), "newnum", newNum)

return

}

log.Debug("Skipping transaction reset caused by setHead",

"old", oldHead.Hash(), "oldnum", oldNum, "new", newHead.Hash(), "newnum", newNum)

} else {

for rem.NumberU64() > add.NumberU64() {

discarded = append(discarded, rem.Transactions()...)

if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil {

log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash())

return

}

}

for add.NumberU64() > rem.NumberU64() {

included = append(included, add.Transactions()...)

if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil {

log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash())

return

}

}

for rem.Hash() != add.Hash() {

discarded = append(discarded, rem.Transactions()...)

if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil {

log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash())

return

}

included = append(included, add.Transactions()...)

if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil {

log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash())

return

}

}

reinject = types.TxDifference(discarded, included)

}

}

}

我们在源代码中给出了部分注释,但对于一些特殊情况,我们在此进行解释。rem == nil情况,此情况较为特殊,我们无法在数据库内检索到旧的区块,此种情况可细分:newNum >= oldNum 新区块编号大于或等于旧区块,此种情况下意味着我们之前使用的链并不位于主链上,而是位于分支链上。此种情况下,我们不需要对交易池进行特别处理,等待再获得一个区块重置变量即可。其他情况,这些情况都较为玄学,可能是函数运行出现问题,也可以通过等待区块重置变量解决问题除了上面这种情况,我们还会遇到以下情况:旧区块大于新区块 这意味着节点获得了一个可能来自分支链的块广播,我们将旧区块的交易列入discarded序列内。正如上文所述,此函数其实不会丢弃交易,discarded仅作为交易序列名存在。我们认为旧区块内的交易都应该删除,无论旧区块是否位于主分支等情况新区块大于旧区块 正常情况,将新区块内的交易列入included列表内在当前以太坊PoS情况下,很难出现分支链等情况当然,只要新区块与旧区块的哈希值不同,我们就需要处理其内部的交易,即rem.Hash() != add.Hash()情况,在这种情况下,我们将旧区块内的交易列入discarded,并将新区块内的交易列入included。我们也做了两个校验,代码如下:rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil

上述代码用于判断旧区块是否存在上一个区块,如果没有,则说明此区块不可信,应该直接抛弃。还有一种极其特殊的情况,代码如下:if newHead == nil {

newHead = pool.chain.CurrentBlock().Header() // Special case during testing

}

正如注释,此情况仅用于测试。在完成上述步骤后,我们通过reinject = types.TxDifference(discarded, included)获得两个区块交易集合之间的差集。这也是我们需要补充到交易池内的交易,并同时根据新的区块更新部分设置,代码如下:statedb, err := pool.chain.StateAt(newHead.Root)

if err != nil {

log.Error("Failed to reset txpool state", "err", err)

return

}

pool.currentState = statedb

pool.pendingNonces = newTxNoncer(statedb)

pool.currentMaxGas = newHead.GasLimit

// Inject any transactions discarded due to reorgs

log.Debug("Reinjecting stale transactions", "count", len(reinject))

senderCacher.recover(pool.signer, reinject)

pool.addTxsLocked(reinject, false)

// Update all fork indicator by next pending block number.

next := new(big.Int).Add(newHead.Number, big.NewInt(1))

pool.istanbul = pool.chainconfig.IsIstanbul(next)

pool.eip2718 = pool.chainconfig.IsBerlin(next)

pool.eip1559 = pool.chainconfig.IsLondon(next)

上述内容基本就是根据新区块对各个变量进行重新设置,较为简单,不再赘述。代码中出现的statedb是以太坊的状态数据库,存储有账户等信息,我们会在未来介绍接下来,我们分析runReorg的第二部分,此部分会删除部分交易。代码如下:if reset != nil {

pool.demoteUnexecutables()

if reset.newHead != nil && pool.chainconfig.IsLondon(new(big.Int).Add(reset.newHead.Number, big.NewInt(1))) {

pendingBaseFee := misc.CalcBaseFee(pool.chainconfig, reset.newHead)

pool.priced.SetBaseFee(pendingBaseFee)

}

// Update all accounts to the latest known pending nonce

nonces := make(map[common.Address]uint64, len(pool.pending))

for addr, list := range pool.pending {

highestPending := list.LastElement()

nonces[addr] = highestPending.Nonce() + 1

}

pool.pendingNonces.setAll(nonces)

}

我们首先分析demoteUnexecutables函数,代码如下:func (pool *TxPool) demoteUnexecutables() {

// 迭代交易池内的 pending 队列

for addr, list := range pool.pending {

nonce := pool.currentState.GetNonce(addr)

// 删除交易中 nonce 较低的交易

olds := list.Forward(nonce)

for _, tx := range olds {

hash := tx.Hash()

pool.all.Remove(hash)

log.Trace("Removed old pending transaction", "hash", hash)

}

// 丢弃到所有账户无法支付 gas 费用的交易

// drops 是所有无法支付 gas 费用的交易

// invalids 是指低于 drops 中最低 nonce 交易的列表

drops, invalids := list.Filter(pool.currentState.GetBalance(addr), pool.currentMaxGas)

for _, tx := range drops {

hash := tx.Hash()

log.Trace("Removed unpayable pending transaction", "hash", hash)

pool.all.Remove(hash)

}

pendingNofundsMeter.Mark(int64(len(drops)))

// invalids 内包含的交易可能符合要求,也有可能不符合要求

// 所以交易应该进入 queued 队列

for _, tx := range invalids {

hash := tx.Hash()

log.Trace("Demoting pending transaction", "hash", hash)

// Internal shuffle shouldn't touch the lookup set.

pool.enqueueTx(hash, tx, false, false)

}

// 更新计数器

pendingGauge.Dec(int64(len(olds) + len(drops) + len(invalids)))

if pool.locals.contains(addr) {

localGauge.Dec(int64(len(olds) + len(drops) + len(invalids)))

}

// 交易列表长度大于 0 ,但交易列表内没有找到 nonce 为最新 nonce 的交易

// 这意味着交易列表内的所有交易都是可能过时的

if list.Len() > 0 && list.txs.Get(nonce) == nil {

// 利用 Cap 返回交易列表内所有交易

// Cap 的功能是限制列表内的交易数,此处限制为 0

gapped := list.Cap(0)

// 执行交易降级

for _, tx := range gapped {

hash := tx.Hash()

log.Error("Demoting invalidated transaction", "hash", hash)

// Internal shuffle shouldn't touch the lookup set.

pool.enqueueTx(hash, tx, false, false)

}

// 重置计数器

pendingGauge.Dec(int64(len(gapped)))

blockReorgInvalidatedTx.Mark(int64(len(gapped)))

}

// 如果发现 list(账户地址对应的交易列表)为空,则直接在交易池内删除此账户

if list.Empty() {

delete(pool.pending, addr)

}

}

}

我们通过注释分析了以上代码,此代码的一大特点是在新区块到来时会对pending队列中不符合新区块要求的交易进行降级处理。在完成交易降级流程后,我们使用以下代码进行nonce的重置:nonces := make(map[common.Address]uint64, len(pool.pending))

for addr, list := range pool.pending {

highestPending := list.LastElement()

nonces[addr] = highestPending.Nonce() + 1

}

pool.pendingNonces.setAll(nonces)

我们通过list.LastElement()获得最新的交易,然后将交易的nonce + 1作为我们目前跟踪的nonce。此处使用的nonce是在区块生产期间内使用,所以我们无法通过statedb内的数据获得。总结#本文主要介绍了一个交易从构建到打包进入区块的完整过程,基本分析了以太坊交易池的实现和构成,也设计了部分交易打包和执行的内容。主要内容列表如下:以太坊交易池的基本参数和初始化交易参数的含义与使用MetaMask API构建交易交易池内交易队列交易池增加交易使用的函数交易池内的scheduleReorgLoop调度函数及相关channelrunReorg函数实现交易提权的过程交易打包和执行的基本情况runReorg在新区块到达情况下重置交易池状态的情况考虑到读者可以希望自己阅读源代码,此处给出关于交易的核心函数流程图,为了简单,此流程图省略了部分数据结构,如下:ethereumgeth« PrevAAVE交互指南

Next »使用Quartz部署Obsidian笔记网站© 2024 Wong's Blog

Powered by

Hugo &

Paper