Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

v7.0.0-alpha.0

Pre-release
Pre-release
Compare
Choose a tag to compare
@davidmurdoch davidmurdoch released this 26 Aug 21:43
· 310 commits to develop since this release
[email protected]

 Highlights    Breaking Changes    Fixes    New Features   Known Issues   Future Plans 


This major release is the first alpha release of the new and improved Ganache v7.0.0. We've got a lot in store for you in this breaking-change release, so you'll definitely want to read on!

But first, this is an alpha release; even these 7.0.0 release notes are "alpha" and the information here is likely incomplete. There will be bugs and kinks to work out before we ship things off to beta, rc, then finally to latest. You absolutely should use this alpha release, but only to try it out and let us know where it breaks for you!

In other words: 🔥🐉 Here be dragons 🔥🐉️


Highlights

  • We broke Ganache… on purpose. 😅 This is a breaking change release, so you’ll want to pay close attention to these changes! (skip to the broken-stuff)

  • It's much faster and more memory efficient. We've seen truffle test execution times for real world repositories run in 1/3 the time. CLI initialization is ~300% faster. You can now run Ganache indefinitely without ever-increasing memory usage (with a few very rare exceptions¹ we consider to be bugs that will be fixed in a later release).

  • The ganache-core and ganache-cli packages you know and love have been (almost² completely rewritten from the ground up in TypeScript.

  • The ganache-core and ganache-cli npm packages have been merged into a single ganache package. We’ll continue to publish to the old core and cli npm packages for the time being, but you’ll want to switch over to the new ganache npm package soon, or you’ll start seeing a deprecation notice upon installation.

  • The ganache-core and ganache-cli GitHub repositories have been merged together and moved to ganache. Head over to the new repo and show it some love by smashing that ⭐ button!

  • The Docker container will be moving to https://hub.docker.com/r/trufflesuite/ganache

  • Ganache now works in the browser and we are working on building interactive browser-based documentation. We've built a prototype implementation and are working on optimizing and polishing the experience.

  • For the last year Ganache has been mostly maintained by one person (me). But now there are a whole two of us! We welcomed Micaiah Reid, formerly of Lockheed Martin, to the team in May! Go give him a follow!

  • Speaking of new team members… we're hiring! We’ve got tons of exciting work planned for the future of Ethereum developer tools. Come work with us on making Ethereum more accessible to more developers! Don’t know which positions to apply to? Feel free to reach out to anyone from our team to inquire more about working here at Truffle!

back to top

Breaking Changes

Many changes are "breaking", some more than others. We've organized the breaking changes into three categories:

The big ones

These changes are likely to cause you some trouble if you upgrade blindly. We've ordered them from most-likely to least-likely to cause problems:

🟀

We've renamed our packages

We've renamed *ganache-cli and ganache-core to ganache. You'll need to uninstall the old version before installing the new.

For a global installation uninstall ganache-cli before installing ganache:

$ npm uninstall ganache-cli --global
$ npm install ganache@alpha --global

For a local installation of ganache-cli and/or ganache-core:

$ npm uninstall ganache-core ganache-cli
$ npm install ganache@alpha

You can now use the new ganache (without the -cli suffix) on the command line:

$ ganache # use `npx ganache` if you installed locally

and via global or local install in your package.json scripts:

{
  "scripts": {
    "start-ganache": "ganache"
  }
}

Note: we've aliased ganache-cli to ganache, so you can continue using the ganache-cli command in your npm scripts and in your terminal.

The Docker container will be moving soon -- from https://hub.docker.com/r/trufflesuite/ganache-cli to https://hub.docker.com/r/trufflesuite/ganache.

back to list

Transaction hashes are now returned before the transaction receipt is available.

Previously, Ganache would allow this:

// BAD CODE THAT USED TO WORK
const provider = Ganache.provider();
const txHash = await provider.send("eth_sendTransaction", [transaction]);
const receipt = await provider.send("eth_getTransactionReceipt", [txHash]);
assert.notStrictEqual(receipt, null);

The problem is that this behavior is not representative of how Ethereum nodes behave in the real world; transactions take time to be mined after being accepted by the node. If you're already using Ethereum libraries like web3.js or ethers.js and connecting over WebSockets, you shouldn't have to worry about this change, as these libraries already handle the transaction lifecycle for you.

If you are using Truffle to run your tests you'll want to enable the websockets flag in your Truffle config:

// truffle-config.js
module.exports = {
  networks: {
    development: {
      host: "127.0.0.1",
      port: 8545,
      network_id: "*",
      websockets: true // ← add this
    },
    /* … */

However, even with WebSockets enabled, some versions of these libraries, including truffle, do not always set up their subscription events fast enough. When this happens the client will miss the notification from Ganache and fall back to polling for changes (slow). We're working with libraries to fix this behavior, but in the meantime you might want to go against our advice and enable legacyInstamine mode, as described below, when starting Ganache.

If you have test code similar to the BAD CODE THAT USED TO WORK example above you'll need to make some changes.

The easy, but not recommended way is to enable legacyInstamine mode in your start up options:

$ ganache --miner.legacyInstamine true

or

const provider = Ganache.provider({ miner: { legacyInstamine: true } });

Enabling legacyInstamine mode restores the old behavior, causing transaction hashes to be returned after the transaction results are persisted in the database.

The problem with this fix is that you will be unable to reliably run your code against real Ethereum nodes later. We've seen this issue arise over and over once developers attempt their tests against a testnet or on Mainnet.

A better way is to update your code so that it will behave no matter how long it takes for your transaction receipt to be available. To do that you'll either need to use Ethereum subscriptions or HTTP polling.

Here's a somewhat robust example of how to wait for a transaction receipt in JavaScript with an EIP-1193 provider (like your browser wallet's window.ethereum) connected via WebSockets:

const send = (method, params) => provider.request({ method, params });

const sendRawTransaction = async (provider, rawTransaction) => {
  // first we need to subscribe to all new blocks
  const subId = await send("eth_subscribe", ["newHeads"]);
  try {
    // send the raw transaction
    const txHash = await send("eth_sendRawTransaction", [rawTransaction]);
    // wait for the receipt
    const receipt = await new Promise(resolve => {
      // wait for new messages
      provider.on("message", async ({ type, data }) => {
        // wait for our specific subscription
        if (type !== "eth_subscription" || data.subscription !== subId) return;

        // return our receipt if it is available
        const receipt = await send("eth_getTransactionReceipt", [txHash]);
        if (receipt === null) return;

        resolve(receipt);
      });
    });
  } finally {
    // make sure we always unsubscribe
    await send("eth_unsubscribe", [subId]);
  }
  return receipt;
};

I know… this is a lot of code for something that used to be so simple! This is why we've added a small helper for the simplest cases:

// setup
const provider = Ganache.provider();
const send = (method, params) => provider.request({ method, params });
// subscribe ONCE when starting ganache
await send("eth_subscribe", ["newHeads"]); // ← add this

// …

const txHash = await send("eth_sendRawTransaction", [transaction]);
// wait for a single block then continue
await provider.once("message"); // ← add this
const receipt = await send("eth_getTransactionReceipt", [txHash]);

provider.once is currently non-standard and should only be used in controlled environments where you are the only one interacting with the node and are sending transactions sequentially.

Note that legacyInstamine + vmErrorsOnRPCResponse mode's error messages, from a rejected Promise or the error parameter in callback-style, are now formatted as follows:

type RpcError = {
   data: Record<string /* transaction hash */, {
    hash: string;
    programCounter: number;
    result: string;
    reason?: string;
    message: string;
  }>;
};

Previously, these errors were contained within a combination of the results and hashes properties:

// OLD WAY!
type RpcError = {
  results: Record<string /* transaction hash*/, {
    error: string;
    program_counter: number;
    reason?: string;
    return: string;
  }>;
  hashes: string[]; // array of transaction hashes
};

Also, only evm_mine and miner_start return an array for the data field, as these are the only places where multiple transactions may be executed[³].

VM Errors on RPC Response now defaults to disabled

Ganache used to return error messages alongside the result for eth_sendTransaction and eth_sendRawTransaction RPC calls by default. This is invalid behavior for a node and causes problems with some libraries.

You can still enable this feature, but to do so you'll need to also enable legacyInstamine mode, as described above:

$ ganache --miner.legacyInstamine true --chain.vmErrorsOnRPCResponse true

or

const provider = Ganache.provider({
  miner: {
    legacyInstamine: true
  },
  chain: {
    vmErrorsOnRPCResponse: true
  }
});

To see why a transaction has failed you can resend the transaction via eth_call.

back to list

Default startup ether is now 1000 instead of 100

We polled 50 developers about Ganache's startup Ether amount. 44% had no opinion, 33% didn't need more, and 22% said they change the default amount to 1000 or more. While the 22% is a minority, we felt that it was a large enough percentage to warrant the change. Feel free to reach out to let us know if you like/dislike this change.

back to list

Ganache's provider and server interfaces have changed

Ganache's provider and server internals are no longer leaking. This means you can’t manipulate the vm directly anymore. We’re already planning on exposing many of the vm events that other tools rely on (like ”step”) before launching to stable, but we need further feedback on other internals that will be missed. Open a new issue if you relied on these removed internals and need us to build in public and stable access to them.

back to list

Non-consecutive transaction nonces no longer throw an error

We now support the pendingTransactions event and will soon support actual pending blocks.

Previously, if you sent a transaction with a nonce that did not match the account's transaction count that transaction would be immediately rejected. In v7 that transaction will be placed in the node's transaction queue.

You can replace these queued transactions the same way you'd replace the transaction on Mainnet or tests, by sending another transaction with the same nonce but a higher gas price.

Currently the eviction mechanism is not tunable, but we plan on exposing options to change the behavior in the near future.

Note: currently, the number of queued transactions does not have an upper bound and you can continue adding new transactions until your process runs out of memory and crashes. We consider this a memory leak and a bug. Expect this unbounded behavior to change in a patch-level release in the future.

Note 2: if you use the persisted DB option: we have never stored unexecuted transactions to disk and do not plan to do so. The same is true of these queued transactions.

back to list

We've dropped support for Node v8.x

Hopefully this won't affect your project, as it's been unsupported by Node.js for over a year now.

We plan on dropping support for Node v10 within the next few months. Please file an issue if you think you or your team will be unable to upgrade to Node v12 or later by mid October 2021.

back to list

Old databases from previous versions are not compatible with v7.0.0

Ganache's old database format is incompatible with this version. We've decided to hold off on building migration tools for this. If you will need a migration tool (you use the db_path flag and are unable to recreate your initial DB state) please open an issue to let us know.

back to list

back to breaking

Other breaking changes, but you probably won't notice or care

  • web3_clientVersion now returns Ganache/v{number/number/number}
  • Runtime Error: errors are now Runtime error:
  • change signer account is locked error to authentication needed: password or unlock
  • change Exceeds block gas limit error to exceeds block gas limit
  • server.listen isn't pre-bound to the server instance (server.listen.bind(server))
  • provider.send isn't pre-bound to the provider instance (provider.listen.bind(provider))
  • remove options.keepAliveTimeout
  • rename provider.removeAllListeners to provider.clearListeners
  • provider.close is now provider.disconnect and returns a Promise (no callback argument)
  • return Cannot wrap a "[a-zA-Z]+" as a json-rpc type on evm_revert error instead of invalid type or false for invalid snapshot ids
  • change invalid string handling to error with cannot convert string value ${value} into type Quantity; strings must be hex-encoded and prefixed with "0x".
  • change Method {method} not supported error to The method {method} does not exist/is not available
  • return error header not found for requests to non-existent blocks
  • replace mutable provider.options with provider.getOptions(); getOptions now returns a deep clone of the options object
  • default coinbase (eth_coinbase RPC call) is now the 0x0 address (fixes #201)
  • sender doesn't have enough funds to send tx errors are now prefixed with VM Exception while processing transaction
  • logs subscription events are emitted before newHeads events

back to breaking

Technically bug fixes, but these might break your tests:

  • blocks are now filled based on actual transaction gas usage, not by the transactions stated gas/gasLimit
  • the underlying state trie is now computed properly; hashes and stateRoots will differ (fixes #664)
  • chainId option defaults to 1337 everywhere
  • remove support for BN in provider RPC methods
  • require transaction data to be valid json-rpc hex-encoded DATA (must start with 0x)
  • invalid transaction v values are no longer allowed
  • previous versions sent utf-8 instead of binary over WebSockets when the request was binary encoded, the encoding is now echoed by default. There is new flag/option to revert behavior: wsBinary
  • change error code when subscription requested over http from -32000 to -32004
  • require transaction value string to be a JSON-RPC encoded hex QUANTITY.
    • Reason: the string "1000" could be the decimal number 1000 or the hex representation of the number 4096. The JSON-RPC specification requires that we disambiguate by only accepting "0x"-prefixed hexadecimal strings.
  • a result is no longer present when an error is returned (fixes #558)
  • transaction ordering from multiple accounts is now ordered by gasPrice
  • options now always treats strings that represent numbers as "0x" prefixed hex strings, not as numbers

back to breaking

back to top


Fixes

  • An actual block size is now returned in eth_getBlock* calls
  • eth_sign returns correct signatures (fixes #556)
  • The underlying state trie is now computed properly (fixes #664)

back to top


New Features

  • Updated default gasLimit to 12M
    • note: we've never considered changing the default gasLimit as a semver breaking change, but welcome civil discourse if you disagree.
  • Added more forking auth options and configuration. See ganache --help for details
  • Added namespaces for options arguments. See ganache --help for the new option names. Note:
    • You can still use the "legacy" options.
    • Let us know if you love or hate the namespaced options.
  • Added provider.once(message: string) => Promise<unknown>
  • Add the option miner.defaultTransactionGasLimit which can be set to "estimate" to automatically use a gas estimate instead of the default when gas/gasLimit has been omitted from the transaction.
  • evm_mine now accepts a new param: options: {timestamp?: number, blocks: number?}.
    • If options.blocks is given it mines that number of blocks before returning
  • Added miner.coinbase option (closed #201).
  • Added evm_setAccountNonce (closed #589).
  • Added getOptions() to provider instance.
  • Added getInitialAccounts() to provider instance.
  • evm_increaseTime now takes either a number or a JSON-RPC hex-encoded QUANTITY value (closed #118).
  • Added new flag, wsBinary (true, false, or "auto", defaults to "auto").
  • Added support for non-executable pending transactions (skipped nonces).
  • Added support for replacement transactions (closed #244 #484).

back to top


Known Issues

  • No Berlin/London support yet. We apologize for being behind on this one. This is our top priority and expect a follow up alpha release within 1 week to add in London and EIP-1559 transaction (type 2) support.
  • Forking is so very slow.
  • Forking's chainId shouldn't match the remote chain. We really should use a different chainId than the remote, but still be able to contextualize past transactions with their original chainId.
  • WebSocket connections are sometimes closed prematurely.
  • Our TypeScript types aren't properly exported.
  • Our Docker container isn't published.
  • We don't return a proper pending block.
  • Uncles aren't fully supported when forking.
  • Forking may fail in weird and unexpected ways. We need to "error better" here.

back to top


Future Plans

  • Support for enabling eligible draft EIPs before they are finalized or considered for inclusion in a hardfork.
  • New hardfork support well in advance of the hardfork launch.
  • Add an eth_createAccessList method.
  • Add in VM events so tools like solcoverage will work.
  • Track test performance metrics over time.
  • Track real world Ganache usage (opt-in and anonymized) to better tune performance and drive bug fixes and feature development.
  • Track test coverage.
  • Document how to use Ganache in the browser, and what limits it has.
  • evm_mine will return the new blocks instead of just 0x0.
  • We've laid the groundwork for additional performance improvements. We expect to see an additional 2-5x speed up for typical testing work loads in the near future.
  • Add new evm_setCode and evm_setStorageAt RPC methods.
  • Make evm_snapshot ids globally unique (unpredictable instead of a counter).
  • Support eth_getRawTransactionByHash RPC method.
  • Support debug_accountAt RPC method.
  • Allow "mining" to be disabled on start up.
  • Set CLI options via config file, package.json, or ENV vars.
  • "Flavor" Plugins: We're building support for Layer 2 plugins into Ganache so we can start up and manage other chains. e.g., The ganache filecoin command will look for the @ganache/filecoin package and start up a Filecoin and IPFS server.
  • Multi-chain configurations: you'll be able to start up your project's entire blockchain "ecosystem" from a single ganache command: e.g., ganache --flavor ethereum --flavor filecoin --flavor optimism.
    • this is where defining your CLI options via JSON config will come in very handy!
  • Integrate with Infura: e.g., ganache --fork mainnet to fork mainnet via your own Infura account.
  • Create a CLI interactive/RELP mode.
  • Enable a CLI daemon mode.

Open new issues (or join our team) to influence what we gets implemented and prioritized.

back to top


1. We don't evict excessive pending transactions, unreverted evm_snapshot references are only stored in memory, and we allow an unlimited number of wallet accounts to be created and stored in memory via personal_newAccount.
2. Truffle alum, Nick Paterno, built our ✨excellent✨ gas estimation algorithm which required no changes.
3. This isn't entirely true when a nonce is skipped and then the skipped nonce is executed, but this behavior wasn't supported in previous versions anyway.


💖 The Truffle Team