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

Parallel static calls in fork #1532

Closed
0xGorilla opened this issue Nov 10, 2021 · 3 comments · Fixed by #1592
Closed

Parallel static calls in fork #1532

0xGorilla opened this issue Nov 10, 2021 · 3 comments · Fixed by #1592
Assignees
Milestone

Comments

@0xGorilla
Copy link

Even though we send multiple static calls to a fork at the same time, they are being processed one by one.

Is there any way we can make them work in parallel since they shouldn't affect the state of the EVM?

@davidmurdoch
Copy link
Member

This should be the behavior as things are right now, if not, it is a bug. Can you provide reproduction steps?

@0xGorilla
Copy link
Author

You can use this snippet and you will see that the balance wallet order follows the declaration map order, and it gets processed one by one:

import Ganache from 'ganache';

const rpc = 'YOUR_RPC';
const port = 10_000;
const forkBlock = 13601629;

const dai = '0x6B175474E89094C44Da98b954EedeAC495271d0F';
const addresses = [
  'bebc44782c7db0a1a60cb6fe97d0b483032ff1c7',
  '5d3a536e4d6dbd6114cc1ead35777bab948e3643',
  '028171bca77440897b824ca71d1c56cac55b68a3',
  'e78388b4ce79068e89bf8aa7f218ef6b9ab0e9d0',
  '40ec5b33f54e0e8a33a975908c5ba1c14e5bbbdf',
  '34d7d7aaf50ad4944b70b320acb24c95fa2def7c',
  '47ac0fb4f2d84898e4d9e7b4dab3c24507a6d503',
  'c564ee9f21ed8a2d8e7e76c085740d5e4c5fafbe',
  '6c6bc977e13df9b0de53b251522280bb72383700',
  'ba12222222228d8ba445958a75a0704d566bf2c8',
  '8e595470ed749b85c6f7669de83eae304c2ec68f',
  'c3d03e4f041fd4cd388c549ee2a29a9e5075882f',
  '7344e478574acbe6dac9de1077430139e17eec3d',
  'fb76e9be55758d0042e003c1e46e186360f0627e',
  '5a16552f59ea34e44ec81e58b3817833e9fd5436',
  '31f8cc382c9898b273eff4e0b7626a6987c846e8',
];

const server = Ganache.server({
  fork: rpc,
  fork_block_number: forkBlock
});

server.listen(port, async (err: any) => {
  if (err) throw new Error(err);

  console.log(`Ganache server started at port ${port}`);

  const promises = addresses.map(async (address) => {
    console.log(`Asking balance of wallet ${address}`);

    const balance = await server.provider.request({
      method: 'eth_call',
      params: [{
        data: '0x70a08231000000000000000000000000' + address, // ERC20 balanceOf
        to: dai
      }, forkBlock]
    });

    console.log(`Balance retrieved of wallet ${address}`, balance);
  });

  await Promise.all(promises);
});

@davidmurdoch
Copy link
Member

Looks like you found a bug in our default values for the chain.asyncRequestProcessing option, though the test above doesn't really demonstrate this issue. The eth_calls you make will take roughly the same amount of time so they're likely to resolve in the order they were sent.

Try the following code with the asyncRequestProcessing flag set to false and then true to better demonstrate the bug.

import Ganache from 'ganache';

const rpc = 'YOUR_RPC';
const port = 10_000;
const forkBlock = 13601629;

const dai = '0x6B175474E89094C44Da98b954EedeAC495271d0F';
const addresses = [
  'bebc44782c7db0a1a60cb6fe97d0b483032ff1c7',
  '5d3a536e4d6dbd6114cc1ead35777bab948e3643',
  '028171bca77440897b824ca71d1c56cac55b68a3',
  'e78388b4ce79068e89bf8aa7f218ef6b9ab0e9d0',
  '40ec5b33f54e0e8a33a975908c5ba1c14e5bbbdf',
  '34d7d7aaf50ad4944b70b320acb24c95fa2def7c',
  '47ac0fb4f2d84898e4d9e7b4dab3c24507a6d503',
  'c564ee9f21ed8a2d8e7e76c085740d5e4c5fafbe',
  '6c6bc977e13df9b0de53b251522280bb72383700',
  'ba12222222228d8ba445958a75a0704d566bf2c8',
  '8e595470ed749b85c6f7669de83eae304c2ec68f',
  'c3d03e4f041fd4cd388c549ee2a29a9e5075882f',
  '7344e478574acbe6dac9de1077430139e17eec3d',
  'fb76e9be55758d0042e003c1e46e186360f0627e',
  '5a16552f59ea34e44ec81e58b3817833e9fd5436',
  '31f8cc382c9898b273eff4e0b7626a6987c846e8',
];

const server = Ganache.server({
  fork: {
    url: rpc,
    blockNumber: forkBlock,
    disableCache: true,
    deleteCache: true
  },
  chain: {
    asyncRequestProcessing: true
  }
});

server.listen(port, async (err: any) => {
  if (err) throw new Error(err);

  console.log(`Ganache server started at port ${port}`);
  const [from] = server.provider.request({method: "eth_accounts", params: []});

  const promises = [];
  addresses.forEach(async (address) => {
    console.log(`Asking balance of wallet ${address}`);

    const call1 = server.provider.request({
      method: 'eth_call',
      params: [{
        data: '0x70a08231000000000000000000000000' + address, // ERC20 balanceOf
        to: dai
      }, forkBlock]
    }).then((result) => {
      console.log(`Balance retrieved of wallet ${address}`, result);
    })
    promises.push(call1);

    console.log(`Perform simple value transfer to ${address}`);
    const call2 = server.provider.request({
      method: 'eth_call',
      params: [{
        from: from,
        to: from,
        value: "0x0" // simple value transfer of 0 to make it simple
      }, "latest"]
    }).then((result) => {
      console.log(`Simple value transfer complete!`);
    })
    promises.push(call2);
  });

  await Promise.all(promises);
})

We'll have a fix for this out in the release following the alpha.2 release we are prepping on today. Thanks for finding this!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants