您正在查看: 2023年3月

分析0xSplits - 收入拆分协议

技术背景

很多时候,我们需要把一份收入(金额)拆分到不同的地址,而又不想让付款人(通常是用户)承担拆分收入部分的 GAS费用, 0xSplits 的架构及解决思路值得我们参考。
本文先介绍了0xSplits 是什么,0xSplits 采用的架构是怎么样的,同时介绍了几种其他的拆分方式可能带来的问题,另外还有一些0xSplits在 Gas 优化上的做法。

0xSplits是什么

0xSplits 是链上收入拆分的协议, 它是一个智能合约,允许你将任何付款拆分到许多收款人,例如,它可以用于NFT版税。EIP-2918允许你只指定一个地址作为收款人,但如果你把这个地址设置为0xSplits地址,你就可以有很多个收款人。
0xSplits由一个主合约组成,可以创建许多子克隆合约(SplitWallet)。

  1. 你通过调用主合约创建一个新的拆分(split)
  2. 它创建一个负责接收ETH的子合约
  3. 在需要接收ETH的地方使用子合约的地址

译者注:克隆合约是使用同一份代码,创建(复制)多个出合约, 每个合约都有自己的状态。

这里是子克隆合约的代码,你可以看到,它非常简单。它可以接收ETH,并且有一个函数可以将ETH转移到主合约, 0xSplits也支持ERC-20,但省略了这部分代码

但收到的ETH如何拆分给接收者?这就是主合约的任务(为了便于阅读,代码做了修改):


所以,资金是静止不动的,直到有人明确地调用 distributeETH。但为什么有人会浪费Gas来调用这个函数呢?答案是distributorFee(分配费用)。这是在创建拆分时设置的,谁调用distributionETH就归谁。

这种激励性的代码调用是必要的,因为EVM没有周期任务(cron )或回调来定期分配资金,一切都需要由个人或链外机器人发起,distributorFee有点类似于CryptoKitties合约中的autoBirthFee。

为什么0xSplits会选择这种架构?还有,为什么不在收到资金的时候立即分发?这是我们这篇文章的主要想解决的问题。

0xSplits 架构

你可以在Etherscan找到0xSplits的代码

克隆SplitWallet合约接收付款并持有资金,直到它们被调用,将资金转移到主合约。

分销商(distributor)被激励在主合约中调用distributeEth,这将把资金从克隆合约转移到主合约中,同时也将支付/分成。

但是在这一点上,资金仍然存放在主合约中(合约有一个从收款人地址到余额的映射)。为了实际接收资金,用户必须调用主合约中的withdraw函数。

此架构的可能替代方案
现有的设定是相当复杂的:克隆合约接收付款,分销商(distributor)将这些资金从克隆合约转移到主合约,并将资金分给接收者。但是收款人仍然需要调用withdraw来接收实际拆分到的资金。所以,端到端的用户流程并不是完全自动化的(另外,有些钱会被分销商收取)。

为什么0xSplits需要如此复杂的设置?让我们来看看其他的方法,以及它们为什么不可行。

若在收到资金时进行拆分?

为什么不在收到资金的同一函数中进行拆分呢?也就是说,不在合约中保存资金, 而是立即分配,这里有2个原因:

  1. 付款人需要提供额外的Gas
  2. 它破坏了互操作性。付款人不能再直接将ETH转账(transfer)到克隆合约中。而是要求付款人将不得不调用合约上的一个特定函数(来进行拆分),这会破坏互操作性。你可能会说只要重写receive函数,但receive函数经常受2300个Gas限制,这意味着你不能在其函数中进行大量的转账。

若使用共享合约而不是克隆合约呢?

为什么没有一个共享的合约,为所有可能的拆分接收所有的付款?这将摆脱克隆(创建新合约),但它并不奏效,因为当共享合约收到付款时,它不知道付款是要进行怎样的拆分。

将distributeEth和withdraw合二为一呢?

为什么不把整个过程端到端自动化,让分销商在一个函数中执行这2个操作?主要是因为安全问题。强烈建议使用pull over push - 即让用户手动拉取他们的自己资金,而不是把资金自动推送他们。

为什么 "推(push)"被认为是一种安全风险?阅读下面的链接以获得完整的答案,但简而言之,这是因为不是所有的接收者都能保证正确处理ETH的接收。一些恶意的行为者可能会部署一个智能合约,在 receive 功能中进行回退(revert)。因此,如果至少有一个接收者回退(revert),整个操作就会回退(revert)。
参考阅读文章:Pull over Push 将转移以太坊的相关风险转移到用户身上。

如果你想出另一种替代架构,请告诉我(在评论中这里)。

我认为0xSplits为他们所针对的使用场景选择了正确的架构--这就是成为DeFi生态系统中的一个基本构件。还有其他类似的支付拆分器,它们是针对不同的使用场景,它们使用不同的架构。例如,disperse.app在收到资金时进行拆分,它可能是一个更好的一次性付款拆分工具。

0xSplits 代码

我对合约进行了重组,并将所有内容按功能分组,以方便阅读。
现在我们来看看现有的架构是如何在代码中实现的。
这里只有2个合约:SplitMain.sol和SplitWallet.sol(克隆)。其余的是库和接口。
你已经在前面看到了SplitWallet.sol的代码,但我把再次复制到这里只是为了参考。

这很简单。它可以接收ETH并将资金转账到主合约。你可能会问,如果没有 receive 功能,它如何接收ETH?答案是,"克隆 "库创建该合约的克隆,神奇地插入 receive 功能的汇编代码。

现在到了主合约 - SplitMain.sol, 这是所有行动发生的地方。

创建一个拆分合约

SplitMain.sol合约开头的函数,用于创建新的拆分。

validSplit只是验证一些东西,如:

  • 百分比的总和应该是1。
  • 收款人和百分比数组具有相同的长度。
  • 收款人地址数组需要被排序。为什么?我们很快就会知道。

如果controller是零地址,这意味着拆分没有所有者,它变得不可改变。Clones库将创建一个SplitWallet合约的克隆,并保存在构造函数中。

clone和cloneDeterministic(在上面的createSplit函数中)的区别是,确定性的部署到一个预先定义的地址(由传入的splitHash决定)。不可变(Immutable)的拆分合约使用确定性的克隆,以避免有人创建完全相同的拆分合约时时发生碰撞。

拆分(split)是由这些数据结构表示的:

使用哈希值的Gas优化

请注意,上面只保存了拆分的哈希值,而没有保存地址、收款人和distributorFee。为什么我们需要哈希值?

哈希值是用来将所有关于拆分的信息(收款人、百分比、distributorFee)合成一个字符串。

通过只存储哈希值而不是函数的所有参数,我们节省了大量的存储空间,从而节省了Gas。

但是,我们如何查找在哈希过程中丢失的信息,如recipients?我们要求这些信息被传递到需要它们的函数中。在合约中,我们只需再次对传入的参数进行散列,并与存储的散列进行比较。如果它们匹配,传入的参数就是正确的。

分销商被激励在链外记录recipients, percentages等,并将这些信息传递给所有需要它们的函数。分销商费用则是支付他们的服务的费用。

另外,我们现在明白为什么收款人地址数组需要在createSplit函数中进行排序。因为否则,哈希值将无法重现。

更新拆分的内容

用哈希值更新拆分也变得非常有效。只要更新哈希值即可。

(onlySplitController确保msg.sender == split.controller)

所有权的转移

如果一个拆分是可变的,你可以转移其所有权。

这是有两步过程:

为什么是两步程序?为了防止意外转移到一个错误的地址。两步程序使你的合约更安全一些(代价是略微多一点Gas)。

资金如何拆分分配

资金是如何分配的?让我们来看看:

我们首先通过哈希算法验证传入的args,并与存储的哈希算法进行比较。然后我们将资金转移到主合约,为分销商预留奖励,最后分配资金。

这个函数为了可读性做了大量的修改。请阅读原始的源代码以了解实际的实现。

终端用户提取资金

主合约的最后一个功能是收款人提取资金的能力。这是一个非常简单的功能。


由于ethBalances中的资金来于所有的克隆拆分合约。但是withdraw需要手动调用,机器人/分销商没有受到激励进行这个动作。

同样有趣的是,有人可以代表你调用withdraw(为你的Gas付钱)。

其他的想法

  • 0xSplits 实际上允许你有嵌套的拆分--指定一个拆分为另一个拆分的收款人。
  • 0xSplits 也适用于 ERC-20 资金的拆分。我只是省略了代码以方便阅读。
  • 不小心发送到主合约的资金是无法恢复的,因为没有办法提取多余的ETH。
  • OpenZeppelin也有一个支付拆分器,但我还没有研究过它是如何实现的,还有disperse.app,对于一次性的拆分来说可能更好。
  • 用比特币而不是用以太坊来拆分支付要容易得多。由于UTXO架构的存在,比特币几乎拥有这种开箱即用的功能。(见 Solidity Fridays)

就这样吧!让我知道你对0xSplits的看法,在评论区

转载:https://learnblockchain.cn/article/5560

Solidity Gas 优化 - 理解不同变量 Gas 差异

本文我们来尝试进行 RareSkills Gas 优化的一个挑战,完成这个挑战可以学习到更多 Gas 技巧。
以下是 Distribute 合约,合约的作用是向 4 个贡献者平均分配 1 ETH, 代码如下

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.15;

contract Distribute {
    address[4] public contributors;
    uint256 public createTime;

    constructor(address[4] memory _contributors) payable {
        contributors = _contributors;
        createTime = block.timestamp;
    }

    function distribute() external {
        require(
            block.timestamp > createTime + 1 weeks,
            "cannot distribute yet"
        );

        uint256 amount = address(this).balance / 4;
        payable(contributors[0]).transfer(amount);
        payable(contributors[1]).transfer(amount);
        payable(contributors[2]).transfer(amount);
        payable(contributors[3]).transfer(amount);
    }
}

合约代码:https://github.com/RareSkills/gas-puzzles/blob/main/contracts/Distribute.sol

这个合约默认情况下,所需 GAS 是 71953, 需要优化到 57044, 以便通过测试用例,测试用例代码在这里。
这是默认运行的截图:

在原始合约上运行测试结果

挑战的要求是仅修改合约Solidity代码来使 distribute 下降到57044, 因此不可以修改优化器或solidity版本、不可以修改测试文件,也不使用huff/yul/bytecode 层面的优化,也不变更函数属性(不能使函数为 "payable")。
在进一步阅读之前,请确保你自己先尝试解决这个难题,它真的很有趣,而且能让你学到东西。

让我们来优化吧!

让我们先做一些明显的事情。

  • 变更变量为不可变(immutable)变量,而不是存储变量(节省 10710Gas--因为不可变变量是作为常量嵌入合约字节码的,而不是从存储中读取)。
  • 用 send 取代 transfer(节省108 Gas--因为send没有检查转账是否成功)。
  • 用endTime代替currentTime (节省了69个Gas - 在构造函数中进行时间计算)

以下是修改后的合约:

这样我们就可以让Gas 节约到61066,已经比原来的好了10887,但仍比目标值高出 4千, 需继续努力。

那么,还有什么诀窍呢?

这个挑战有一个特别的技巧,应该教给你。而这是一种通过SELFDESTRUCT向地址发送ETH的老方法:

通过Selfdestruct 解谜, 仅仅这一招就为你节省了4066*的Gas,并且达到了目标!

但如果继续深入呢?

每一个理智的优化总是有其疯狂的邪恶兄弟(作弊)......让我们看看我们能把这个推到什么程度!
让合约自毁(selfdestruct)感觉像是在作弊 -- 为什么你会有一个这样的合约,在第一次调用分发后就不存在了呢?不过测试通过,所以我想这是允许的......?

让我们看看还有什么(真正的作弊)能让测试通过,但又能优化更多Gas。

  • 让contributors成为常数,而不是不可变(immutable)(节省24个Gas - 因为Hardhat地址总是相同的,所以可以这样做,对吧?
  • 使金额恒定为0.25ETH,而不是从余额中计算(节省了106个Gas -- 因为在测试中金额总是相同的,所以为什么不这样做呢?)
  • 使用Assembly来做call,而不是通常的solidityaddress.send(节省9 0 Gas)。


到目前为止使用的 Gas 是 56780

还可以更进一步吗?

把地址作为字节32的数字直接放在调用中,可以为我们多节省9个Gas!

在调用中的手动用零填充地址, 可以节约到 56771 Gas

我们继续走下去如何?

既然我们已经针对测试上做优化,那我们就进一步
为什么我们不直接返回,如果测试是 "Gas目标"?
知道Hardhat总是在相同的区块链中运行测试,我们可以把这个代码放在 distribute()函数的开头:

if (block.number == 5) return;

这样在测试中,测量 gas 时,直接返回,而不会消耗很多Gas,但仍将在 "逻辑检查" 测试中完成了的功能检查:)
不明白的同学可以回顾这里的测试用例代码,测试用例会先检查 Gas 是否达标再检查是否"逻辑"满足。


这给了我们一个惊人的21207Gas! 令人难以置信吧,不过你明白这里发生了什么......

但,这就是作弊!

是的,但谨记,这样的作弊经常在链上发生,MEV,漏洞,代码即法律,以及所有其他的东西。

还记得最近的Gas挑战比赛吗,最佳优化者获得了NFT?在那里,没有人在解决原来的问题--一切都在 "欺骗 "智能合约,以接受所需的值,并通过所需的测试,以最低的字节码和最低的Gas--你就能得到NFT。

这也给我们了一些启示,更好的测试和更好的条件可以规避这些作弊,同时让程序更安全。
对于开发我们更应该注重有效的程序,而不仅仅是巧妙地入侵系统。

转载自:https://learnblockchain.cn/article/5515

ETH2.0 技术调研和测试部署

1. ETH1.0和2.0的对比

1.1 共识机制

共识改进

  • 节能,比pow消耗更少能源
  • 低门槛,硬件相对较低
  • 降低中心化,pos更易节点参与
  • 增加攻击成本,违规惩罚

1.2 节点组成

2. ETH 2.0 方案组成

2.1 节点架构

  • 执行层->P2P1

    • 维护交易池,交易处理,gossip广播
    • 状态管理
    • 创建执行负载
    • 用户网关->提供对外RPC
  • 共识层->P2P2

    • 共享广播块和证明
    • 运行分叉选择算法
    • 跟踪链的头部
    • 管理信标状态(包含共识和执行信息)
    • 跟踪 RANDAO 中累积的随机性
    • 跟踪justification和finalization
    • 验证器
      • 提议区块
      • 创建证明
      • 累积奖励/惩罚

    客户端设置

2.2 执行与共识层通信

共识和执行层之间通过“Engine-API”的API发送指令。

共享一个 ENR(以太坊节点记录),其中包含(eth1 密钥和 eth2 密钥)。

层内广播协议:gossip

共识层非区块生产者:

共识层-->接收区块->预先验证块(有效sender)->区块中的交易->执行层->执行交易并验证块头中的状态(哈希匹配)->共识层->添加本地链头部->创建证明->广播证明

共识层为区块生产者时:

共识层->收到通知(下一个区块当选生产者)->调用执行层(create block)->交易内存池->打包区块->执行交易生成区块哈希<-共识层抓取交易和区块哈希->添加到信标块->广播区块

3. 环境测试

3.1 测试方案选配

根据客户端多样性分布
https://clientdiversity.org/

测试方案:Prysm棱镜 + Geth

部署参考文档(prylabs

3.2 测试环境

  • 系统: Ubuntu 20.04
    • CPU:4+ 核 @ 2.8+ GHz
    • 内存:16GB+
    • 存储:2TB+ SSD
    • 网络:8 MBit/秒
  • 测试网络: Goerli-Prater
  • 执行客户端: Geth 1.11.3
  • EN-BN 连接: HTTP-JWT

eth2.0测试网

  • Sepolia
    • 封闭验证器集
    • 验证者集受到限制,主要由客户和测试团队监督
    • 较小的区块链状态和历史
    • 同步速度快,需要更少的存储承诺
  • Goerli
    • 开放验证者集
    • 携带大状态并需要高存储承诺
    • 需要更长的时间才能与网络的当前状态同步

如果测试合约选Sepolia, 如果想测试参与节点治理选Goerli

3.3 测试环境部署

设置工作目录

export workdir=/mnt/d/eth2.0/ethereum

3.3.1 安装 Prysm

cd $workdir
mkdir consensus
mkdir execution
cd consensus
mkdir prysm && cd prysm
curl https://raw.githubusercontent.com/prysmaticlabs/prysm/master/prysm.sh --output prysm.sh && chmod +x prysm.sh

3.3.2 生成 JWT Secret

./prysm.sh beacon-chain generate-auth-secret

3.3.3 下载和运行执行客户端

下载

cd $workdir/execution
wget https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.11.3-5ed08c47.tar.gz
tar -zxvf ./geth-linux-amd64-1.11.3-5ed08c47.tar.gz
mv ./geth-linux-amd64-1.11.3-5ed08c47/geth ./
rm ./geth-linux-amd64-1.11.3-5ed08c47.tar.gz
rm -rf ./geth-linux-amd64-1.11.3-5ed08c47

运行

nohup ./geth --goerli --http --http.api eth,net,engine,admin --authrpc.jwtsecret $workdir/consensus/prysm/jwt.hex 2>> ./geth.log &

3.3.4 Prysm 运行信标节点

cd $workdir/consensus/prysm/

nohup ./prysm.sh beacon-chain --execution-endpoint=http://localhost:8551 --prater --jwt-secret=./jwt.hex --suggested-fee-recipient=0x10210572d6b4924Af7Ef946136295e9b209E1FA0 --accept-terms-of-use --checkpoint-sync-url=https://sync-goerli.beaconcha.in --genesis-beacon-api-url=https://sync-goerli.beaconcha.in 2>> ./prysm.log &

3.3.5 Prysm 运行验证器

cd $workdir/
git clone -b master --single-branch https://github.com/ethereum/staking-deposit-cli.git
cd staking-deposit-cli/
./deposit.sh new-mnemonic

按照提示,依次输入参数

Please choose your language ['1. العربية', '2. ελληνικά', '3. English', '4. Français', '5. Bahasa melayu', '6. Italiano', '7. 日本語', '8. 한국어', '9. Português do Brasil', '10. român', '11. Türkçe', '12. 简
体中文']:  [English]: 12
请选择您的助记符语言 ['1. 简体中文', '2. 繁體中文', '3. čeština', '4. English', '5. Italiano', '6. 한국어', '7. Português', '8. Español']:  [简体中文]: 4
请选择您想要运行多少验证者: 1
请选择(主网或测试网)网络名/链名 ['mainnet', 'ropsten', 'goerli', 'sepolia', 'zhejiang']:  [mainnet]: goerli
用来保护您密钥库的密码。您在设置您的 Ethereum PoS 验证者时需要重新输入密码以便解密它们。:
重复输入以确认:

最后生成助记词,保存并输入确认

cool disorder brand vast jaguar sponsor bamboo ...
您的密钥可以在这里找到: /mnt/d/eth2.0/ethereum/staking-deposit-cli/validator_keys

执行完将生成

  1. 新的助记词
  2. validator_keys文件夹
    1. deposit_data-*.json // 上传到以太坊启动板的存款数据
    2. keystore-m_*.json // 公钥和加密的私钥

复制validator_keysconsensus文件夹中

cp -r $workdir/staking-deposit-cli/validator_keys $workdir/consensus
导入密钥库
cd $workdir/consensus/prysm
./prysm.sh validator accounts import --keys-dir=$workdir/consensus/validator_keys --prater

出现以下提示代表成功

INFO accounts: Successfully created new wallet wallet-path=/home/surou/.eth2validators/prysm-wallet-v2
Successfully imported 1 accounts, view all of them by running `accounts list`

导入后钱包位置:$HOME/.eth2validators/prysm-wallet-v2

上传存款数据

转到Goerli-Prater Launchpad 的存款数据上传页面,将上面的deposit_data-*.json 上传,会提示您连接钱包。

此时会存入 32 GETH Prater 测试网的存款合约。

避免重复抵押

提交dapp已经做了的判断

查看发起的抵押交易

goerli.etherscan.io

查看链上合约

goerli.etherscan.io

/// @notice Submit a Phase 0 DepositData object.
    /// @param pubkey A BLS12-381 public key.
    /// @param withdrawal_credentials Commitment to a public key for withdrawals.
    /// @param signature A BLS12-381 signature.
    /// @param deposit_data_root The SHA-256 hash of the SSZ-encoded DepositData object.
    /// Used as a protection against malformed input.
    function deposit(
        bytes calldata pubkey,
        bytes calldata withdrawal_credentials,
        bytes calldata signature,
        bytes32 deposit_data_root
    ) override external payable {
        // Extended ABI length checks since dynamic types are used.
        require(pubkey.length == 48, "DepositContract: invalid pubkey length");
        require(withdrawal_credentials.length == 32, "DepositContract: invalid withdrawal_credentials length");
        require(signature.length == 96, "DepositContract: invalid signature length");

        // Check deposit amount
        require(msg.value >= 1 ether, "DepositContract: deposit value too low");
        require(msg.value % GWEI == 0, "DepositContract: deposit value not multiple of gwei");
        uint deposit_amount = msg.value / GWEI;
        require(deposit_amount <= type(uint64).max, "DepositContract: deposit value too high");

        // Emit `DepositEvent` log
        bytes memory amount = to_little_endian_64(uint64(deposit_amount));
        emit DepositEvent(
            pubkey,
            withdrawal_credentials,
            amount,
            signature,
            to_little_endian_64(uint64(deposit_count))
        );

        // Compute deposit data root (`DepositData` hash tree root)
        bytes32 pubkey_root = sha256(abi.encodePacked(pubkey, bytes16(0)));
        bytes32 signature_root = sha256(abi.encodePacked(
            sha256(abi.encodePacked(signature[:64])),
            sha256(abi.encodePacked(signature[64:], bytes32(0)))
        ));
        bytes32 node = sha256(abi.encodePacked(
            sha256(abi.encodePacked(pubkey_root, withdrawal_credentials)),
            sha256(abi.encodePacked(amount, bytes24(0), signature_root))
        ));

        // Verify computed and expected deposit data roots match
        require(node == deposit_data_root, "DepositContract: reconstructed DepositData does not match supplied deposit_data_root");

        // Avoid overflowing the Merkle tree (and prevent edge case in computing `branch`)
        require(deposit_count < MAX_DEPOSIT_COUNT, "DepositContract: merkle tree full");

        // Add deposit data root to Merkle tree (update a single `branch` node)
        deposit_count += 1;
        uint size = deposit_count;
        for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH; height++) {
            if ((size & 1) == 1) {
                branch[height] = node;
                return;
            }
            node = sha256(abi.encodePacked(branch[height], node));
            size /= 2;
        }
        // As the loop should always end prematurely with the `return` statement,
        // this code should be unreachable. We assert `false` just to be safe.
        assert(false);
    }

合约内没有限定质押地址,可以代为质押

交易参数如下
0   pubkey  bytes   0xb23fca698e5b57c2dd09f16e10b97d532a18b574a46e6539bd9d83e79c5922230bc8990def676e3e78534a3fd8cbe58d
1   withdrawal_credentials  bytes   0x004734640dd34942fc621f643910f86e52b4e5f03db42d9cf6e14863b1148529
2   signature   bytes   0xb46ac23ab45b798331d706b91a635f59b00019cff96462493fae91877dc18d2c6d30e2684197547cd48c079ad94265ff07f36ab48b61b94ef90e3e7e3eeaf96d52dbb012690113c4fe3bc42274a9eb72d82dbdcbea8aa08e2e00e88978c0de3e
3   deposit_data_root   bytes32 0x0c4b49597ef312f110596b87e333e4c76ef8381216dd52ca63f2c84ea2c152d8

信标链处理您的存款大约需要 16-24 小时。 一旦存入金额总计达到 32 ETH,该验证器就有资格被激活。

查看已抵押信息

beaconcha.in

当前测试抵押节点信息

beaconscan.com
质押生效后才能看到信息

运行验证器

nohup ./prysm.sh validator --wallet-dir=$HOME/.eth2validators/prysm-wallet-v2 --wallet-password-file ./password --prater 2>> ./validator.log &

检查节点和验证器状态

节点日志

追块过程中
  • Geth常规日志
INFO [03-11|16:46:14.726] Syncing: chain download in progress      synced=44.90% ...
INFO [03-11|16:46:15.318] Forkchoice requested sync to new head    number=8,633,606 hash=522f76..69cb70 finalized=8,633,551
INFO [03-11|16:46:15.859] Syncing: state download in progress      synced=10.27% s
  • prysm常规日志
[2023-03-11 16:47:40]  INFO blockchain: Called new payload with optimistic block payloadBlockHash=0xb7864552d082 slot=5166177
  • validator日志
[2023-03-11 16:48:55]  INFO validator: Waiting for beacon node to sync to latest chain head
追齐高度后
生效之前

validator日志显示

INFO validator: Waiting for deposit to be observed by beacon node pubKey=0xb23fca698e5b status=UNKNOWN_STATUS

prysm日志显示

 WARN rpc/validator: Not connected to ETH1. Cannot determine validator ETH1 deposit block number
生效之后

// 待补充

怠工惩罚

如果当前节点质押生效后,未能及时提议区块和证明,将被惩罚 -10680 GWei/epoch

4. 附加配置

开放必要端口

执行客户端 默认端口 共识客户端 默认端口
Geth 30303 TCP/UDP Teku 9000 TCP/UDP
Besu 30303 TCP/UDP Lighthouse 9000 TCP/UDP
Erigon 30303 TCP/UDP Nimbus 9000 TCP/UDP
Nethermind 30303 TCP/UDP Prysm 13000 TCP, 12000 UDP

配置时间同步

timedatectl // 检查是否NTP服务是积极的.
sudo timedatectl set-ntp on // 如果NTP服务不是积极的

5. 在线文档

节点设置

费用收件人

Lighthouse | Nimbus | Prysm | Teku

Discord

JWT认证

最新公告

Goerli-PraterMainnet

监控

Lighthouse | Nimbus | Prysm | Teku

安全最佳实践

https://docs.prylabs.network/docs/security-best-practices

Prysm社区

邮件列表Prysm Discord 服务器r/ethstakerEthStaker Discord 服务器

6. 节点运行架构

以太坊节点

公共检查点

https://notes.ethereum.org/@launchpad/checkpoint-sync

节点统计

https://www.ethernodes.org/

节点质押

goerli: https://goerli.launchpad.ethereum.org/zh

mainnet: https://launchpad.ethereum.org/zh

生产服务器配置

最低要求
  • 2 核以上的 CPU
  • 8 GB 内存
  • 700GB 可用磁盘空间
  • 10+ MBit/s 带宽
推荐规格
  • 具有 4 个以上内核的快速 CPU
  • 16 GB+ 内存
  • 1+TB 的快速 SSD
  • 25+ MBit/s 带宽

测试网

即插即用解决方案

https://docs.dappnode.io/user/quick-start/first-steps/

https://github.com/NiceNode/nice-node

https://eth-docker.net/

https://docs.sedge.nethermind.io/docs/intro

Goerli 与 Sepolia 测试网比较:哪个更好?

Goerli 和 Sepolia 是以太坊开发人员用来测试其应用程序的两个权益证明测试网。web3 开发人员在选择测试网之前应考虑多种原因,包括测试 ETH 的可用性、RPC 节点提供商支持、智能合约可用性等。

在本文中,我们将介绍每个测试网是什么,它们的技术差异,强调三个注意事项,并帮助您为您的项目选择最佳的以太坊测试网。

Goerli 测试网介绍

Goerli 于 2018 年在 ETH-Berlin 开始作为黑客马拉松项目,然后于 2019 年正式启动。它是第一个成功与 Geth、Nethermind、Besu 等客户端同步的权威证明 (PoA) 跨客户端测试网。

Goerli测试网络是一个公开开放的权益证明 (PoS) 测试网,由一个开放的验证器集维护,这意味着任何希望运行自己的测试网验证器的人都可以参与。但是,由于网络的状态很大,需要更长的同步时间和更多的存储来运行一个节点。

与 Sepolia 相比的主要区别

  • 开放验证者集
  • 无需许可即可获得共识
  • 支持跨客户端功能
  • 携带大状态并需要高存储承诺
  • 需要更长的时间才能与网络的当前状态同步

Goerli 测试网络配置

如果您要将 Goerli 区块链添加到您的钱包,这是要包括的网络信息:

Sepolia 测试网

Sepolia于 2021 年推出,是一个经过许可的权益证明测试网络,由主要由客户和测试团队控制的封闭验证器集维护。虽然开发人员可以公开使用测试网来测试和部署他们的去中心化应用程序 dDapps),但并不是每个人都可以选择运行验证节点,使其成为一个许可网络

由于 Sepolia 是一个较年轻的测试网,与 Goerli 等更成熟的测试网相比,部署的应用程序较少。它具有更小的状态和历史记录,允许更快的同步并需要最少的磁盘空间来运行节点。

与Goerli相比的主要区别

  • 封闭验证器集(权威证明配置)
  • 获得共识是允许的
  • 验证者集受到限制,主要由客户和测试团队监督
  • 支持跨客户端兼容性
  • 较小的区块链状态和历史
  • 同步速度快,需要更少的存储承诺

Sepolia链信息

如果您要将 Sepolia 区块链添加到您的钱包,这是要包括的网络信息:

要开始在 Sepolia 上构建,请注册一个免费的 Alchemy 帐户,并从 Alchemy 的公共水龙头获取免费的 SepoliaETH 代币

选择在 Sepolia 或 Goerli 上开发之前需要考虑的事项

在选择 Sepolia 测试网络或 Goerli 之前要考虑的三件事是:

  1. 测试 ETH 的可用性和成本
  2. RPC 和 API 支持
  3. 智能合约的可用性

1. 测试ETH的可用性

在 Goerli 和 Sepolia 之间进行选择时的主要考虑因素是可用性、可访问性和获取测试 ETH 代币的成本。测试 ETH 代币用于支付测试网上的 gas,web3 开发人员需要在与以太坊主网环境非常相似的环境中部署和测试他们的智能合约。

Goerli ETH是免费的吗?

从历史上看,开发人员在 Goerli 测试网上使用的测试 ETH goETH 一直是免费的,但是由于 goETH 的稀缺性,已经创建了流动性市场,开发人员可以在其中买卖 goETH 以换取真实的 ETH。

Web3 开发者仍然可以通过 Goerli Faucet 获取免费的 Goerli ETH,但是由于 goETH 的总量有硬性上限,所以每天可以领取的 goETH 数量是有限制的。

与积累 Goerli ETH 相关的稀缺性和成本是许多以太坊开发人员从 Goerli 转向 Sepolia 的原因之一。

Sepolia ETH 是免费的吗?

是的,Sepolia ETH 是免费的,可以从Sepolia ETH 水龙头领取。由于市场上可用的 sepETH 总数没有上限,因此每次从 Sepolia 水龙头请求测试 ETH 时,像 Alchemy 这样的水龙头供应商都能够为开发人员提供更多的 sepETH。

2. RPC 和 API 支持

在决定在 Sepolia 或 Goerli 上构建之前,了解支持每个测试网的 RPC 节点提供商以及它们支持的 API 端点非常重要。例如,Alchemy 等一些 RPC 提供商支持 Sepolia 测试网,而其他提供商可能不支持。此外,某些 RPC 提供程序可能缺乏对重要 API 端点的支持,例如需要 Erigon 节点的跟踪 API。

Alchemy 支持 Sepolia 上的所有核心 JSON-RPC 方法以及存档节点支持和跟踪 API 端点。未来,Alchemy 还将支持在 Sepolia 上增强的 API 方法。

3. 智能合约可用性

如果你的智能合约依赖于其他智能合约,那么你决定构建 Goerli 还是 Sepolia 将取决于依赖智能合约的部署位置。

例如,如果您的智能合约需要访问 Uniswap v3 合约,而 Uniswap 只在 Goerli 测试网上部署了他们的合约,那么您将需要在 Goerli 上部署您的智能合约,直到 Uniswap 将他们的测试网迁移到 Sepolia。

4. 其他注意事项

在 Goerli 和 Sepolia 测试网络之间进行选择时,除了智能合约的可用性和节点提供商的支持外,还应考虑网络稳定性、验证者集和以太坊基金会的长期支持等因素。

Goerli 或 Sepolia:我应该选择哪个测试网?

选择正确的测试网络是一个重要的决定,它会影响 dapp 开发的成功。每个测试网络都有自己的技术规范、功能和权衡,选择正确的网络可以节省您的时间和资源。

在部署和测试应用程序和智能合约方面,Ethereum.org 推荐 Sepolia 作为测试应用程序和智能合约的首选,因为它具有受限的验证器集和更高的稳定性保证。

另一方面,如果你想测试你的信标链验证器、节点设置、客户端版本,或者想在部署到主网络之前尝试协议升级,Goerli 是一个不错的选择。它是最接近以太坊主网的测试网,也可用于测试复杂的智能合约交互。

英文原文:https://www.alchemy.com/overviews/goerli-vs-sepolia
翻译:谷歌