以太坊基础
以太坊网络
以太坊网络是一组使用以太坊协议进行通信的互联计算机。 以太坊只有一个主网,但可以创建符合相同协议规则的独立网络用于测试和开发。 有许多独立的“网络”遵循该协议,但彼此之间没有交互。 你甚至可以在自己的计算机上本地启动一个以太坊网络,以测试你的智能合约和 web3 应用程序。
- 以太坊主网:主网是指主要的以太坊生态区块链,所有具有实际价值的交易都发生在该链的分散账本中。大众和交易所涉及的 ETH 价格是主网的 ETH。
- 以太坊测试网:除了主网外,还有公开的测试网。 这是一种模拟生态环境的网络,协议开发者或智能合约开发者可以使用它们测试尚未部署在主网上的协议升级和智能合约。 你可以把它看作生产与装配服务器的模拟。Sepolia 是应用程序开发时推荐使用的默认测试网,是一个供合约和应用程序开发者测试其应用程序的网络。
- 私有网络:如果以太坊网络的节点未连接到公共网络( 主网或测试网),则以太坊网络就是私有网络。 在这种情况下,私有仅指保留或隔离,而不是保护或安全。要开发以太坊应用程序,需要在私有网络上运行该应用程序以了解它的运行情况,然后再进行部署。
- 联盟网络:共识过程由一组预定义的受信任节点控制。 例如,在由知名学术机构组成的私有网络中,每个学术机构管理一个节点,并且区块由网络中的签名者阈值进行验证。如果说公共以太坊网络像公共互联网,那么联盟网络就像私有内部网。
以太坊的数据存储
以太坊区块链的数据是分布式存储在全球运行的以太坊节点上的。具体来说:
- 节点存储
以太坊网络由成千上万的节点组成,每个节点都保存了一份区块链的完整或部分副本。节点可以分为几种类型:
- 全节点(Full Node):保存了整个区块链的完整副本,包括所有的区块和交易历史。全节点验证和广播区块,并确保网络的安全和可靠性。
- 轻节点(Light Node):只保存区块头信息,而不是完整的区块数据。轻节点依赖于全节点来获取详细信息,但可以快速同步和运行。
- 存档节点(Archive Node):保存了所有的历史状态,包括每一个区块的所有状态变化。这些节点数据量非常大,主要用于区块链分析和开发需求。
- 分布式存储
每个节点通过运行以太坊客户端(如Geth、Parity/OpenEthereum等)来保存区块链数据。客户端使用数据库(通常是LevelDB或RocksDB)来存储区块数据、交易记录、状态树和合约代码等信息。
- 区块数据结构
一个区块的数据结构包括以下内容:
- 区块头(Block Header):包括区块号、上一个区块的哈希值、Merkle根、时间戳、难度、随机数等。
- 交易列表(Transactions):包含区块中的所有交易记录。
- 叔块(Uncles):包含一些未被主链包含的区块(称为叔块)。
- 访问和同步
新节点加入网络时,会从邻近的节点获取最新的区块数据,并同步到当前的区块高度。同步过程可以是快速同步(只下载区块头和状态数据)或完全同步(下载所有历史数据)。
- 去中心化存储
由于以太坊是一个去中心化的网络,没有单一的集中式存储点。每个节点的数据库存储是独立的,但通过共识算法(如PoW和PoS)确保整个网络的数据一致性和完整性。
总之,以太坊区块链的数据通过全球成千上万的分布式节点存储和维护,每个节点保存了区块链的不同部分或完整副本,确保了数据的安全性、可靠性和不可篡改性。
以太坊客户端基本工作流程
以太坊客户端在运行时会通过**对等网络(P2P网络)**与其他以太坊节点进行通信,下载和同步区块链数据。以下是详细说明:
- 对等网络(P2P网络)
以太坊客户端(如Geth、Parity等)运行在对等网络中,这意味着它们彼此直接通信,而不依赖于中央服务器。每个客户端节点都会发现并连接到其他节点,形成一个分布式网络。
- 节点发现和连接
当你启动以太坊客户端时,它会通过一种叫做**节点发现协议(Node Discovery Protocol)**来找到其他以太坊节点。这个协议使得节点可以找到并连接到网络中的其他节点。连接成功后,节点会交换各自的区块链数据。
- 区块链数据同步
以太坊客户端连接到其他节点后,会通过以下几种方式同步区块链数据:
- 快速同步(Fast Sync):新节点只下载区块头和状态数据,而不是完整的区块数据。这样可以快速同步到最新区块高度,然后再逐步下载缺失的完整数据。
- 完全同步(Full Sync):新节点下载区块链的完整数据,包括所有的区块、交易和状态数据。这种方式耗时较长,但确保节点拥有完整的区块链历史。
- 轻同步(Light Sync):轻节点只下载区块头数据,并依赖全节点来请求具体的交易和状态数据。这种方式节省存储和计算资源,但需要信任全节点提供的数据。
- 数据验证和存储
在同步过程中,节点会验证接收到的区块和交易,以确保其符合共识规则和协议规范。验证通过后,节点会将数据存储在本地数据库中(通常使用LevelDB或RocksDB)。
- 共识机制
以太坊使用的共识机制(例如工作量证明PoW,未来可能转换为权益证明PoS)确保了全网节点对区块链数据的一致性。所有节点都必须遵循共识规则,只有验证通过的区块才能被添加到区块链中。
- 数据获取
当你查询以太坊客户端的数据(例如获取最新区块),客户端会从本地存储的区块链数据库中读取数据。如果数据不在本地,则会请求连接的对等节点提供该数据。
总结
以太坊客户端通过对等网络连接到其他节点,从而获取和同步区块链数据。这个过程确保了每个节点拥有一致和最新的区块链数据,且所有节点共同维护区块链的完整性和安全性。
节点发现协议基本流程
以太坊客户端通过一个称为**节点发现协议(Node Discovery Protocol)**的机制来发现和连接其他节点。以下是这个过程的详细说明:
- 启动阶段
当一个以太坊客户端启动时,它首先需要找到网络中的其他节点,以便加入以太坊网络。为了实现这一点,客户端通常会有一个预定义的**“种子节点”(Bootstrap Nodes)列表**。这些种子节点是一些已知的、可靠的节点,客户端可以通过这些节点来开始发现网络中的其他节点。
- 节点发现协议
以太坊使用一个改进的Kademlia分布式哈希表(DHT)协议来实现节点发现。这个协议包括以下几个步骤:
a. 节点的唯一标识
每个以太坊节点都有一个唯一的节点ID,这是通过节点的公钥生成的。节点ID用于在网络中标识和发现节点。
b. 种子节点连接
客户端首先连接到种子节点,获取初始的网络拓扑信息。这些种子节点通常是高可用的,并保持在线状态。
c. PING/PONG消息
客户端向种子节点发送PING消息,询问其他活跃节点的信息。种子节点回复PONG消息,提供一些其他节点的联系方式(IP地址和端口)。
d. 节点表(Node Table)
客户端维护一个节点表(Node Table),其中存储了已知节点的联系方式。这个表结构基于Kademlia DHT,按照距离度量(基于XOR计算)组织节点。
e. 寻找节点
客户端使用FIND_NODE消息向已知节点发送查询,请求更多节点信息。每个已知节点会返回一个接近目标节点ID的节点列表。客户端不断迭代这个过程,逐步发现更多的节点。
- 连接和验证
一旦发现新的节点,客户端会尝试与这些节点建立连接。这包括以下步骤:
a. 握手
客户端与目标节点进行握手,交换版本号、链ID、网络ID等基本信息,确保双方运行的是兼容的以太坊版本。
b. 身份验证
使用公钥加密进行身份验证,确保连接的安全性。
c. 同步状态
一旦连接成功,节点会交换最新的区块头和状态信息,开始区块链数据的同步过程。
- 保持连接
客户端会周期性地与已连接的节点交换PING/PONG消息,保持连接的活跃状态。客户端也会定期更新节点表,移除不活跃的节点,并发现新的节点。
- 优先选择邻近节点
节点发现协议会优先选择距离较近的节点(基于XOR计算),从而优化网络拓扑和数据传输效率。
总结
以太坊客户端通过节点发现协议,利用种子节点启动连接,通过Kademlia DHT协议逐步发现和连接网络中的其他节点。这种机制确保了客户端能够有效地加入以太坊网络,发现并连接其他节点,从而参与区块链的数据同步和共识过程。
节点公私钥和账户公私钥有什么区别?
节点也可以有自己的公私钥对,但是它们的用途和账户的公私钥对有所不同。以下是详细的解释:
节点的公私钥
节点的公私钥:
- 节点在运行时可能会生成自己的公私钥对,这些密钥主要用于节点间的加密通信和身份验证。
- 节点的公私钥不用于管理账户或进行交易,而是用于确保节点间通信的安全性和完整性。
用途:
- 加密通信:节点之间通过加密通信协议(如devp2p)进行交互,节点的公私钥用于建立安全的通信通道。
- 身份验证:节点的公钥可以用来标识和验证节点的身份,确保数据来自可信的节点。
账户的公私钥
账户的公私钥:
- 账户的公私钥对用于管理以太坊网络上的账户,控制账户中的资金和资产。
- 私钥用于签名交易,公钥用于生成账户地址,验证签名。
用途:
- 签名交易:账户私钥用于签名交易,以保证交易的真实性和完整性。
- 生成地址:账户公钥用于生成唯一的以太坊地址,接收和发送以太币及其他资产。
- 验证签名:通过账户公钥,可以验证交易签名,确保交易由账户所有者发起。
区别总结
功能和用途:
- 节点的公私钥:用于节点间的加密通信和身份验证。
- 账户的公私钥:用于管理账户、签名和验证交易。
生成和管理:
- 节点的公私钥:通常在节点启动时自动生成,并用于节点间的网络通信。
- 账户的公私钥:用户在创建账户时生成,并用于管理账户中的资金和资产。
存储位置:
- 节点的公私钥:存储在节点的配置文件或数据目录中,节点启动时加载使用。
- 账户的公私钥:存储在钱包中,用户可以选择不同的存储方式(如软件钱包、硬件钱包、纸钱包等)。
示例
节点的公私钥(Geth示例)
在Geth节点中,节点的公私钥用于节点间通信,可以在数据目录中找到:
# Geth的数据目录中保存节点的密钥文件
ls ~/.ethereum/geth/nodekey
账户的公私钥(使用Geth创建账户)
在Geth中,创建账户会生成账户的公私钥对:
# 创建新账户
geth account new
生成的账户私钥将存储在Geth的数据目录中。
节点和钱包有什么关系?
钱包是一种客户端,但它的功能和目的与运行以太坊节点的客户端有一些不同。以下是详细的解释:
钱包作为客户端
以太坊钱包作为客户端的一种,主要用于管理账户和执行用户级操作。它有以下特点:
密钥管理:
- 钱包生成并存储私钥和公钥对,提供安全的密钥管理功能。
- 确保私钥安全存储并在需要时用于签名交易。
用户界面:
- 钱包提供用户友好的界面,允许用户查看账户余额、发送交易、接收资金、与智能合约交互等。
- 界面设计通常强调易用性和用户体验。
交易签名和广播:
- 钱包通过私钥签名交易,然后将签名后的交易发送到以太坊网络。
- 它通常依赖于一个或多个节点来广播交易并查询区块链状态。
以太坊节点作为客户端
以太坊节点是另一种类型的客户端,主要用于维护区块链网络的运行。它有以下特点:
网络参与:
- 节点参与到以太坊网络的共识机制中,帮助验证和广播交易、区块。
- 全节点会存储区块链的全部数据,并与其他节点同步。
数据存储和同步:
- 节点存储区块链的数据,包括交易、区块、智能合约代码和状态。
- 节点会不断与网络中的其他节点同步最新的区块和交易数据。
接口和API:
- 节点提供API接口(如JSON-RPC),供钱包和其他应用程序使用,以查询区块链数据和发送交易。
- 节点本身不提供用户界面,但提供底层功能和数据访问。
钱包与节点的关系
依赖关系:
- 钱包通常依赖于一个或多个节点来获取区块链数据和广播交易。
- 钱包可以连接到本地节点(自己运行的节点)或远程节点(第三方提供的节点服务)。
功能互补:
- 钱包关注于用户交互和密钥管理,提供简便的操作界面。
- 节点负责区块链数据的存储、验证和网络通信,提供底层支持。
示例
MetaMask钱包
- MetaMask作为浏览器扩展钱包,提供易用的界面管理账户和交易。
- MetaMask默认连接到Infura等公共节点服务,获取区块链数据和广播交易。
- 用户无需运行自己的节点即可使用MetaMask管理以太坊资产。
Geth节点
- Geth是以太坊官方客户端,可以运行全节点。
- Geth提供JSON-RPC接口,允许钱包(如MetaMask)连接并使用其提供的数据和功能。
- 运行Geth节点需要更多的资源和技术设置,但提供更高的安全性和自主性。
总结
- 钱包:主要用于用户交互,管理私钥和账户,签名并发送交易。它依赖节点提供的网络服务。
- 节点:作为网络参与者,存储和验证区块链数据,提供接口供钱包和其他应用使用。
可以将钱包视为一个专注于用户体验和密钥管理的轻量客户端,而节点则是专注于区块链数据和网络参与的全功能客户端。
交易签名认证流程
交易签名认证是确保以太坊交易的合法性和完整性的重要步骤。以下是交易签名和认证的详细过程:
- 交易的构建和签名
构建交易
首先,用户构建一个交易对象,包含以下主要字段:
nonce
:发送方账户的交易计数器,确保每笔交易的唯一性。to
:接收方的账户地址。value
:发送的ETH数量。gasPrice
:每单位Gas的价格。gasLimit
:交易所允许消耗的最大Gas数量。data
:可选字段,用于传输数据或调用合约函数。
签名交易
用户使用私钥对交易进行签名。签名过程生成三个重要字段:v
、r
、s
,它们组成了交易的签名。签名过程如下:
生成交易哈希:对交易对象进行RLP编码(Recursive Length Prefix)并计算其Keccak-256哈希。
签名交易哈希:使用私钥对交易哈希进行签名,生成
r
、s
和v
值。生成签名交易对象:将原始交易字段和签名字段组合,生成签名交易对象。
示例代码(使用Web3.js和EthereumJS):
const Web3 = require('web3');
const web3 = new Web3();
const Tx = require('ethereumjs-tx').Transaction;
const privateKey = Buffer.from('your_private_key', 'hex');
const txData = {
nonce: web3.utils.toHex(0),
gasLimit: web3.utils.toHex(21000),
gasPrice: web3.utils.toHex(web3.utils.toWei('20', 'gwei')),
to: '0xRecipientAddress',
value: web3.utils.toHex(web3.utils.toWei('1', 'ether'))
};
const tx = new Tx(txData);
tx.sign(privateKey);
const serializedTx = tx.serialize();
const rawTx = '0x' + serializedTx.toString('hex');
- 交易的广播
签名后的交易通过节点(例如Geth或Infura)广播到以太坊网络:
web3.eth.sendSignedTransaction(rawTx)
.on('receipt', console.log)
.on('error', console.error);
- 验证签名
当节点接收到交易后,会验证交易签名,以确保交易是由账户的所有者发起的。
恢复公钥
通过交易的签名(v
、r
、s
),可以从签名恢复出发送方的公钥:
const ethUtil = require('ethereumjs-util');
// 交易哈希
const msgHash = ethUtil.hashPersonalMessage(Buffer.from(tx.hash));
// 恢复公钥
const pubKey = ethUtil.ecrecover(
Buffer.from(msgHash, 'hex'),
tx.v,
Buffer.from(tx.r, 'hex'),
Buffer.from(tx.s, 'hex')
);
// 从公钥生成地址
const recoveredAddress = ethUtil.pubToAddress(pubKey).toString('hex');
验证地址
从公钥生成的地址应与交易的发送方地址匹配。如果匹配,则签名有效,交易合法。
- 添加到区块
一旦签名验证通过,交易将被打包到下一个区块,并添加到区块链中。
交易签名和认证过程确保只有账户所有者可以发起交易,并且交易内容在网络传输过程中没有被篡改
EIP-1559 是软分叉还是硬分叉
EIP-1559 的引入构成了一个硬分叉。硬分叉和软分叉的区别在于:
- 硬分叉(Hard Fork):对区块链协议进行重大更改,导致旧版本节点无法接受遵循新规则的区块。如果网络中的所有节点不同时升级到新协议,可能会导致区块链分裂成两条独立的链。
- 软分叉(Soft Fork):对区块链协议进行向后兼容的更改,旧版本节点仍然可以识别和接受遵循新规则的区块,只是新功能可能对旧节点不可用。
为什么 EIP-1559 是硬分叉
EIP-1559 对以太坊网络进行了以下重大更改,这些更改需要所有节点进行升级:
费用结构的改变:
- 引入了新的交易费用机制,包括基础费(base fee)和小费(priority fee)。
- 传统交易类型和新的 EIP-1559 交易类型的费用计算方法不同,旧版本节点无法识别新的交易类型和费用规则。
交易格式的变化:
- EIP-1559 引入了新的交易格式,添加了
maxFeePerGas
和maxPriorityFeePerGas
字段。 - 旧版本节点无法解析和处理这种新格式的交易。
- EIP-1559 引入了新的交易格式,添加了
区块内容的更新:
- 新的区块包括基础费(base fee)信息,用于动态调整交易费用。
- 旧版本节点无法理解和处理包含这些新信息的区块。
由于这些更改是非向后兼容的,未升级的节点无法理解和处理升级后的区块和交易,这就导致了硬分叉。硬分叉要求所有参与者(节点、矿工、用户)在特定的区块高度同时升级到新版本,以避免链的分裂。
EIP-1559 实施的影响
在 EIP-1559 实施时,以太坊社区和开发者团队进行了广泛的沟通和协调,以确保顺利过渡:
- 节点升级:所有运行以太坊节点的用户和矿工都被要求在硬分叉发生前升级到支持 EIP-1559 的客户端版本。
- 网络一致性:通过协调一致的升级,确保了所有节点都遵循新的协议规则,避免了区块链分裂的风险。
总结来说,EIP-1559 是一个硬分叉,它对以太坊协议进行了重大且非向后兼容的更改,要求所有参与者同时升级以确保网络的一致性和稳定性。