一睹更快更强的Ganache 7

Ganache 7 发布, 再也不卡死了,速度更快,功能更强。

Ganache是以太坊开发领域的先驱,自2016年以来帮助DApp开发者和爱好者构建、测试和探索区块链。我们很高兴地宣布最新版本的Ganache发布了,分叉(fork)性能提高了30倍,并与Infura整合,允许你免费访问存档数据,重放历史交易。

也许你还不不熟悉Ganache,Ganache是一个用与本地开发的区块链,用于在以太坊区块链上开发去中心化的应用程序。Ganache模拟了以太坊网络,你可以在发布到生产环境之前看到你的DApp将如何执行。

在以太坊网络上开发去中心化应用,通常的方式是设置一个以太坊客户端,如Geth或OpenEthereum,为你提供以太坊虚拟机(EVM)环境。

虽然这是一个在以太坊上开发去中心化应用的好方法,但它不是最有效和最友好的方法,因为你需要手动配置这些客户端并保持运行。维护一个自我托管的节点可能是昂贵和耗时的,你不希望在开发过程中花费宝贵的时间来排查一个失败的节点。

有了Ganache,你所需要做的就是启动应用程序,你就有一个预先配置好的以太坊客户端,有10个预先存款和解锁的账户可以使用。这使你能够在整个开发周期内快速测试你的DApp。

Ganache 7:分叉提高30倍速度和操作也更快

许多在以太坊上构建的Web3开发者已经使用Ganache在他们的本地环境中分叉和测试智能合约,以便在部署前获得信心。利用从以前的迭代中获得的经验,我们从头开始重写了Ganache,任务是让这个区块链模拟器工具更加灵活、快速和稳定。

我们听到了你们关于Ganache v6安装缓慢,运行缓慢,并且泄露内存的反馈。它还没有使用现代语言特性和开发人员今天使用的范式,如TypeScript类型和Promise抽象。Ganache v6的架构使得测试、修复错误和添加功能变得困难和费时。

Ganache v7如何更好?

  • 凭借最新版本的高级缓存功能,Ganache的分叉功能(如:fork主网 )比v6快30倍。
  • 零配置的主网分叉, Ganache v7有一个与Infura的原生集成,可以免费访问历史数据
  • 你可以无限期地运行Ganache,而不会遇到因内存问题而崩溃的情况
  • 普通操作比v6快3倍左右。

安装和设置Ganache 7

Ganache可以用多种方式使用:包括作为命令行工具,通过Node.js进行编程,或在浏览器中使用。请看下面的说明,为所有这些使用情况安装和使用Ganache 7。

A. 在命令行上使用Ganache 7

要在命令行上运行Ganache 7,你的电脑上必须安装Node.js >= v12.0.0和NPM >= 6.4.1。参见here下载适合你的操作系统的最新版本,或者使用nvm来管理你的UnixWindows的Node安装。

在安装了Node.js和NPM之后,你可以通过运行npm install ganache --global来全局安装Ganache 7。一旦安装完毕,你可以在命令行的任何地方运行ganache

你的终端应该看起来像这样。

screenshot-1

默认情况下,Ganache提供了10个测试账户,每个账户有1000个(假)以太币,以及相应的私钥和用于生成私钥的助记词。在开发过程中,你可以使用这个助记词将账户导入到MetaMask等钱包。

我们可以在启动Ganache 7时通过指定选项来覆盖所有的默认值;例如,我们可以通过提供私钥与账户余额的映射来对账户创建进行更多的控制,就像这样:

ganache --wallet.accounts "0xfd485338e322f5930f7cf475f385341ec88bfc4f8a0a16f30b2fb417d1bb5427, 1000000000000000000000" "0x05bba0b9f7a251080aa23feee4eab3f75a1abee905c0271008c93e5d2e2e7541, 10000000000000000000000"

我们还可以指定一个助记词组来推导所有的初始账户,一个矿工Gas价格,以及区块Gas限制。例如:

ganache --miner.defaultGasPrice 200 --miner.blockGasLimit 90071 --miner.callGasLimit 898989 --wallet.mnemonic "alarm cause brave super lab glide awake hunt rose win sugar idea"

运行命令ganache --help可以获得所有Ganache的可用选项的列表。

我们也可以使用npm install ganache将ganache安装到本地的Node.js项目中,不使用--global标志,然后将其添加到项目的package.jsonscripts中,例如,"scripts":{"ganache": {"ganache --mnemonic <12 words mnemonic>"}

B. 以编程方式使用Ganache 7

Ganache 7可以在你的Node.js项目中以编程的方式使用, 如作为:

  • 一个独立的EIP-1193提供者。
  • 一个JSON-RPC服务器和EIP-1193提供者。
  • 一个web3.js提供者。
  • 一个ethers.js提供者。

请看下面这些不同使用场景的代码示例。

首先,将Ganache 7作为npm包安装在你的Node.js项目中

$ npm install ganache

作为一个独立的EIP-1193提供者:

const ganache = require("ganache");

const options = {};
const provider = ganache.provider(options);
const accounts = await provider.request({ method: "eth_accounts", params: [] });
...

作为一个JSON-RPC网络服务器和EIP-1193提供者:

const ganache = require("ganache");

const options = {};
const server = ganache.server(options);
const PORT = 8545;
server.listen(PORT, err => {
  if (err) throw err;

  console.log(`ganache listening on port ${PORT}...`);
  const provider = server.provider;
  const accounts = await provider.request({ method: "eth_accounts", params:[] });
});
...

作为一个Web3.js提供者

const Web3 = require("web3");
const ganache = require("ganache");

const web3 = new Web3(ganache.provider());
...

作为Ethers.js的提供者

const ganache = require("ganache");

const provider = new ethers.providers.Web3Provider(ganache.provider());

C. 在浏览器中使用Ganache 7

你可以在浏览器中使用Ganache 7,在你的HTML代码中加入以下脚本标签。

<script src="https://cdn.jsdelivr.net/npm/ganache@7.0.0/dist/web/ganache.min.js"></script>

通过这样做,Ganache 7 就会自动在你的浏览器中供你使用。

const options = {};
const provider = Ganache.provider(options);

同样,请参阅这里,了解你可以传入的可用选项的清单。

Ganache 7 新功能

1. 零配置的主网分叉

Ganache支持开箱即用的主网分叉,无需任何配置,允许你在本地机器上模拟拥有与以太坊主网相同的状态。

这带来了许多可能性;例如,你可以在开发过程中与真实世界的协议/合约进行本地交互,通过,并在本地调试主网交易(使用truffle debug),允许对查看合约调用细节。

这里有2016年Ganache团队使用主网分叉功能来演示DAO黑客攻击

要使用这个功能,使用ganache --fork命令启动Ganache 7。Ganache默认使用Infura作为其引擎的提供者,但你也可以通过传递一个URL来指定一个提供者;例如,你可以通过运行这个命令使用你自己的Infura URL。

$ ganache --fork.url wss://mainnet.infura.io/ws/v3/<PROJECT ID>

Ganache默认从最新的区块中回退五个区块,以避免因重新排序而丢失区块。

这是一个可配置的行为;你可以使用--fork.blockNumber <BLOCK NUMBER>或者通过设置--fork.preLatestConfirmations 0来指定你想要分叉的确切块。

2. 分叉任何以太坊测试网络,无需等待同步时间

除了能够以零配置分叉以太坊主网络外,Ganache还允许你从任何以太坊测试网络分叉,包括Ropsten、Kovan、Rinkeby和Görli。

你可以通过运行带有网络选项的fork命令来做到这一点:ganache -- fork.network <NETWORK NAME>。很酷,是吗?下面是Rinkeby测试网的分叉情况。

screenshot-2

3. 支持大规模交易追踪(超过10GB以上)

Ganache使用debug_traceTransaction RPC方法支持大规模交易追踪。

要使用这个功能,需要从Mainnet(或任何测试网络)中分叉出一个比你要追踪的交易高一个区块号的参数启动Ganache;例如,如果你想追踪一个在区块13,886,877内的交易,你需要在区块号13,886,878处启动Ganache。

$ ganache --fork.network mainnet --fork.blockNumber <blockNumber>

然后使用debug_traceTransaction方法发送一个curl请求,指定交易哈希值,像这样:

$ curl -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0", "id": 1, "method": "debug_traceTransaction", "params": [ "<TRANSACTION HASH>" ] }' http://localhost:8545

这将返回该交易的汇总信息,用于后处理。

用一个大的交易试试,比如0x8bb8dc5c7c830bac85fa48acad2505e9300a91c3ff239c9517d0cae33b595090(Warp Finance黑客)。

首先,启动ganache(用大量的额外内存)。

$ NODE_OPTIONS=--max-old-space-size=16384 ganache --fork --fork.blockNumber 14037983

然后执行debug_traceTransaction并将输出发送到trace.json。

$ curl -H 'Content-Type: application/json'   --data '{"jsonrpc":"2.0", "id": 1, "method": "debug_traceTransaction", "params": [ "0x8bb8dc5c7c830bac85fa48acad2505e9300a91c3ff239c9517d0cae33b595090" ] }' http://localhost:8545 -o trace.json

如果你真的想测试一下可能的极限(并且有很多时间--大约1-2小时),试试10GB以上的Cream Finance黑客交易,0x0fe2542079644e107cbf13690eb9c2c65963ccb79089ff96bfaf8dced2331c92!

4. 快照和还原状态

在区块链术语中,快照指的是捕捉和记录区块链在某个特定区块编号的状态的行为。快照是区块链在该特定区块的完整视图,包括所有现有地址及其相关数据,包括交易、费用、余额、元数据等。

在Ganache中,你可以使用evm_snapshot RPC方法对你的开发区块链(甚至是Mainnet的分叉)进行快照;evm_snapshot不需要任何参数,它返回创建的快照的ID。

Ganache还支持使用evm_revertRPC方法将状态恢复到之前的快照,尽管一旦调用并成功恢复,你就不能再使用具有相应ID的快照,因为你只能恢复快照一次。

如果你需要多次恢复到同一个点,你应该考虑在每次evm_revert之后创建一个新的快照;这里有一个在Ganache中拍摄快照和恢复状态的演示。

const provider = ganache.provider();
const [from, to] = await provider.send("eth_accounts");
const startingBalance = BigInt(await provider.send("eth_getBalance", [from] ));

// take a snapshot
const snapshotId = await provider.send("evm_snapshot");

// send value to another account (over-simplified example)
await provider.send("eth_subscribe", ["newHeads"] );
await provider.send("eth_sendTransaction", [{from, to, value: "0xffff"}] );
await provider.once("message"); // Note: `await provider.once` is non-standard

// ensure balance has updated
const newBalance = await provider.send("eth_getBalance", [from] );
assert(BigInt(newBalance) < startingBalance);

// revert the snapshot
const isReverted = await provider.send("evm_revert", [snapshotId] );
assert(isReverted);

// ensure balance has reverted
const endingBalance = await provider.send("eth_getBalance", [from] );
const isBalanceReverted = assert.strictEqual(BigInt(endingBalance), startingBalance);
console.log({isBalanceReverted: isBalanceReverted});

5. 可即时、间隔或按需出块

Ganache允许你配置在开发过程中配置按需出块;默认配置下,区块会在收到交易后立即被开采,但你也可以选择以下选项:

  • 设置间隔时间出块。你可以通过--miner.blockTime <TIME IN SECONDS>选项来指定Ganache在开采下一个交易之前应该等待的时间(秒)。设置为0意味着Ganache 会立即挖掘新的交易。
  • 根据需要出块。Ganache还公开了一个evm_mine的RPC方法,该方法强制开采一个区块,无论开采是在运行还是停止。如果mempool中没有交易存在,这将挖掘一个空块。请看下面的代码示例。
console.log("start", await provider.send("eth_blockNumber"));
await provider.send("evm_mine", [{blocks: 5}] ); // mines 5 blocks
console.log("end", await provider.send("eth_blockNumber"));

6. 快进时间

Ganache 还提供了两个RPC方法,用于操纵链上时间。

一个典型的使用场景是,智能合约要求在用户采取某些行动之前必须经过特定的时间;如果你不想等待的这段时间,你可以使用evm_increaseTime将区块链当前的时间戳增加指定的秒(以十六进制传递)。

curl -H 'Content-Type: application/json' --data' {"jsonrpc": "2.0", "id": 1, "method": "evm_increaseTime", "params": ["0x15180"] }' http://localhost:8545

这将返回调整后的总时间,单位为毫秒。此外,你可以使用evm_setTime来设置为特定的时间戳;它接受精度为毫秒的JavaScript时间戳(Unix epoch),并返回给定时间戳和当前时间之间的秒数。

curl -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0", "id": 1, "method": "evm_increaseTime", "params": ["0x15180"] }' http://localhost:8545

你应该谨慎使用这个方法,因为它允许你向后移动时间,这可能导致新区块出现在旧区块之前被开采,从而使区块链状态无效。

7. 冒充任何账户

Ganache允许你在开发过程中冒充(Impersonate)另一个账户。这在与分叉功能一起使用时更加有趣;你可以分叉Mainnet并冒充任何账户。

下面是一个例子,你可以分叉Mainnet,冒充一个账户,并发送一些代币给另一个账户。

  • 通过分叉Mainnet并冒充(解锁)一个随机账户,启动Ganache。ganache --fork --wallet.unlockedAccounts <Account Address Here>
  • 获取已解锁账户的余额: curl -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0", "id": 1, "method": "eth_getBalance", "params": ["<Account Address Here>"] }' http://localhost:8545. 这将返回以WEI编码的十六进制数字的余额。
  • 从解锁的账户发送一些以太币到另一个账户: curl -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0", "id": 1, "method": "eth_sendTransaction", "params": [{"from": "UNLOCKED ACCOUNT", "to": "RECEIVING ACCOUNT", "value": "AMOUNT TO SEND"}] }' http://localhost:8545

现在验证一下,解锁账户的余额是否减少了发送的以太数量。

向另一个账户发送以太币并不是唯一的使用场景,因为你可以冒充一个账户来调用智能合约中某些只属于所有者的功能,就像我们之前看到的convex benchmark合约那样。

8. 待定交易(pending)

在以太坊中,每个交易都有一个nonce。nonce是一个给定地址发送的所有交易数量,无论何时你发送一个交易,nonce都会增加1。

在早期版本的Ganache中,如果你发送的交易的nonce值比上一个nonce值大1,Ganache会出错,交易会被拒绝。

在Ganache 7中,如果前一个交易的nonce是1,而你由于某种原因发送了一个nonce设置为3的交易,那么这个nonce为3的交易将在交易池中坐等一个nonce为2的交易被发送,届时这两个交易将被挖出并添加到区块链状态。


今天就开始使用Ganache 7,只需运行npm install ganache --global && ganache --help,或者查看v7发行说明


这个版本已经酝酿了多年,我们对我们所做的工作感到非常自豪。我们希望你和我们一样喜欢它。

感谢每一个参与实现这个版本的人--贡献者、指导者、审查者、问题报告者和社区参与者都对Ganache v7的实现起到了重要作用。我们对你们所有人表示衷心感谢。

本翻译由 Duet Protocol 赞助支持。

点赞 3
收藏 5
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

5 条评论

请先 登录 后评论
翻译小组
翻译小组
0x9e64...7c84
大家看到好的文章可以在 GitHub 提 Issue: https://github.com/lbc-team/Pioneer/issues 欢迎关注我的 Twitter: https://twitter.com/UpchainDAO