您正在查看: Ethereum 分类下的文章

opside 跨链测试

Opside介绍

Opside 是一个三层区块链平台,形式为“Base chains <- Opside chain <- Rollups”。 它具有资产多样性和无限可扩展性等优势,为高吞吐量的web3应用提供友好的运行环境。

三层架构

测试三层跨链转账

1.MetaMask添加Opside测试网络信息

2.MetaMask添加Opside zkEVM 测试网络信息

3. 从水龙头获取代币

领取网址:https://faucet-testnet.opside.network/
领取时需要对指定消息进行签名

交易hash

https://opside.info/address/0x10210572d6b4924Af7Ef946136295e9b209E1FA0

领取代币类型和数量

MetaMask手动添加代币合约地址到资产

USDT:0xDEd24358C0d7C96BC419F479771D1da3443Fe52d
USDC:0x407d6E2bF44A1B70eBd51CcF0aFCFBbD5F0b6d15
VTP:0x956a81C7D7031Fd123961cC69C28a2a49884FC68

4. 测试第1层->第2层桥接

跨链桥网址: https://bridge-testnet.opside.network/

sepolia转1USDT到opside

// TODO

opside转1USDT到Opside zkEVM Testnet

跨链桥网址:https://zkbridge-testnet.opside.network/

  1. Approve USDT spending cap
    0x10210572d6b4924af7ef946136295e9b209e1fa0 -> 0xded24358c0d7c96bc419f479771d1da3443fe52d
    https://opside.info/tx/0xc0d592c5edcc533abddf83f0b38c40a4099ef2ef3de0b6fd862048df24b06036
  2. Bridge Asset
    0x10210572d6b4924af7ef946136295e9b209e1fa0 -> 0xfb15d16f87ad92f0a6d54a9fbc951676701071f9
    https://opside.info/tx/0x1d2dfc8ce07e3039b46e92f27a7bbd5dc461874f4b5020ee3931b0b12804db04

备注:https://testrpc.zkevm.opside.network/bridge-service/bridges/0x10210572d6b4924af7ef946136295e9b209e1fa0?limit=10000&offset=0
测试时这个API,ssl证书有问题:ERR_SSL_VERSION_OR_CIPHER_MISMATCH

Opside zkRollup L3 测试网的RPC同样问题 ERR_SSL_VERSION_OR_CIPHER_MISMATCH
https://testrpc.zkevm.opside.network/

// TODO 等待解决后继续测试,先忙其他

opside转1USDT到sepolia

  1. Approve USDT spending cap
    0x10210572d6b4924af7ef946136295e9b209e1fa0 -> 0x10210572d6b4924af7ef946136295e9b209e1fa0
    https://opside.info/tx/0xca2d7fdf791b7432a3e2067bc814ce9ca66ad2163d55bc805743fad6996ffc98
  2. Deposit
    0x10210572d6b4924af7ef946136295e9b209e1fa0 -> 0x832e50eec9d7f9e2b5d4286a5834400dfaeafc3f
    https://opside.info/tx/0x6b6a505b4aa1aa4b314d5b69a316713d6443f0092e7e9f2b96e8b18bc8778fe6
  3. sepolia.etherscan
    0x91b126ff9af242408090a223829eb88a61724aa5 -> 0xe8b0a865e4663636bf4d6b159c57333210b0c229
    ERC-20 Tokens Transferred: 0x89a5f2c62213b18ee5f83b21cb1a323920c9b101 -> 0x10210572d6b4924af7ef946136295e9b209e1fa0
    https://sepolia.etherscan.io/tx/0x369078b11063231d35738c6afcde52477c5fe5dd78535c9f282f1e36fcac5de8
    获得1 USDT

    https://sepolia.etherscan.io/token/0x969d499507b4f437953db24a4980fdeeda6db8a1?a=0x10210572d6b4924Af7Ef946136295e9b209E1FA0

参考文档

https://docs.opside.network/
https://docs.opside.network/user-guides/video-tutorial

分析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