Skip to content

Commit

Permalink
add create genesis script
Browse files Browse the repository at this point in the history
  • Loading branch information
invocamanman committed Nov 23, 2022
1 parent c70978d commit 3a866d9
Show file tree
Hide file tree
Showing 13 changed files with 294 additions and 209 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ cp .env.example .env
Fill `.env` with your `MNEMONIC` and `INFURA_PROJECT_ID`

```
cd deployment/deployment_v2-0
cd deployment
cp deploy_parameters.json.example deploy_parameters.json
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
const { ethers } = require('hardhat');
const path = require('path');
const fs = require('fs');
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });

const pathOutputJson = path.join(__dirname, './deploy_output.json');

Expand Down
File renamed without changes.
59 changes: 0 additions & 59 deletions deployment/deployment_v2-0/generateGenesisAddress.js

This file was deleted.

79 changes: 0 additions & 79 deletions deployment/deployment_v2-0/genesis.json

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@
"function": "initialize",
"paramsFunction": [
1,
"0xAE4bB80bE56B819606589DE61d5ec3b522EEB032"
"0xAE4bB80bE56B819606589DE61d5ec3b522EEB032",
"0x0000000000000000000000000000000000000000",
0
],
"contractName": "Bridge"
}
Expand Down
34 changes: 34 additions & 0 deletions deployment/genesis.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const hre = require('hardhat');
const { expect } = require('chai');
const { ethers } = require('hardhat');

const openzeppelinUpgrade = require(`../../.openzeppelin/${process.env.HARDHAT_NETWORK}.json`);
const openzeppelinUpgrade = require(`../.openzeppelin/${process.env.HARDHAT_NETWORK}.json`);
const pathDeployOutputParameters = path.join(__dirname, './deploy_output.json');
const deployOutputParameters = require(pathDeployOutputParameters);

Expand Down
8 changes: 4 additions & 4 deletions docker/scripts/deploy-docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ sudo rm -rf docker/gethData/geth_data
DEV_PERIOD=1 docker-compose -f docker/docker-compose.geth.yml up -d geth
sleep 5
node docker/scripts/fund-accounts.js
cp docker/scripts/deploy_parameters_docker.json deployment/deployment_v2-0/deploy_parameters.json
cp docker/scripts/genesis_docker.json deployment/deployment_v2-0/genesis.json
npx hardhat run deployment/deployment_v2-0/deployPoE_v2-0.js --network localhost
cp docker/scripts/deploy_parameters_docker.json deployment/deploy_parameters.json
cp docker/scripts/genesis_docker.json deployment/genesis.json
npx hardhat run deployment/deployPoE_v2-0.js --network localhost
mkdir docker/deploymentOutput
mv deployment/deployment_v2-0/deploy_output.json docker/deploymentOutput
mv deployment/deploy_output.json docker/deploymentOutput
docker-compose -f docker/docker-compose.geth.yml down
sudo docker build -t hermeznetwork/geth-zkevm-contracts -f docker/Dockerfile.geth .
# Let it readable for the multiplatform build coming later!
Expand Down
70 changes: 15 additions & 55 deletions docker/scripts/genesis_docker.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion docker/scripts/genesis_gen_docker.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@
"function": "initialize",
"paramsFunction": [
1,
"0xAE4bB80bE56B819606589DE61d5ec3b522EEB032"
"0xAE4bB80bE56B819606589DE61d5ec3b522EEB032",
"0x0000000000000000000000000000000000000000",
0
],
"contractName": "Bridge"
}
Expand Down
15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"homepage": "https://github.com/0xPolygonHermez/contracts-zkEVM#readme",
"license": "pending",
"dependencies": {
"@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#v0.5.0.0",
"@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#feature/fixMultipleBatchesHash",
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-etherscan": "^3.1.0",
"@nomiclabs/hardhat-waffle": "^2.0.3",
Expand Down Expand Up @@ -58,14 +58,15 @@
"scripts": {
"test": "npx hardhat test test/contracts/**.test.js",
"docgen": "npx solidity-docgen --solc-module solc-0.8 -t ./docs/templates -e ./contracts/verifiers,./contracts/mocks",
"deploy:PoE2_0:hardhat": "npx hardhat run deployment/deployment_v2-0/deployPoE_v2-0.js --network hardhat",
"deploy:PoE2_0:goerli": "npx hardhat run deployment/deployment_v2-0/deployPoE_v2-0.js --network goerli",
"verify:PoE2_0:goerli": "npx hardhat run deployment/deployment_v2-0/verifyPoE_v2-0.js --network goerli",
"lint": "npx eslint ./test && npx eslint ./docker/scripts && npx eslint ./deployment/deployment_v2-0 && npx eslint ./src",
"lint:fix": "npx eslint ./test --fix && npx eslint ./docker/scripts --fix && npx eslint ./deployment/deployment_v2-0 --fix && npx eslint ./src --fix",
"deploy:PoE2_0:hardhat": "npx hardhat run deployment/deployPoE_v2-0.js --network hardhat",
"deploy:PoE2_0:goerli": "npx hardhat run deployment/deployPoE_v2-0.js --network goerli",
"verify:PoE2_0:goerli": "npx hardhat run deployment/verifyPoE_v2-0.js --network goerli",
"lint": "npx eslint ./test && npx eslint ./docker/scripts && npx eslint ./deployment && npx eslint ./src",
"lint:fix": "npx eslint ./test --fix && npx eslint ./docker/scripts --fix && npx eslint ./deployment --fix && npx eslint ./src --fix",
"compile": "npx hardhat compile",
"check:deploy:PoE": "npx hardhat node > /dev/null 2>&1 & npx hardhat run --network localhost deployment/testnet/deployPoETestnet.js && npx hardhat run --network localhost deployment/testnet/checkDeployment.js && pkill -f 'hardhat'",
"docker:contracts": "./docker/scripts/deploy-docker.sh",
"push:docker:contracts": "docker push hermeznetwork/geth-zkevm-contracts"
"push:docker:contracts": "docker push hermeznetwork/geth-zkevm-contracts",
"update:genesis": "node src/create-genesis.js --gen ../deployment/genesis-gen.json --out ../deployment/genesis.json && node src/create-genesis.js --gen ../docker/scripts/genesis_gen_docker.json --out ../docker/scripts/genesis_docker.json"
}
}
224 changes: 224 additions & 0 deletions src/create-genesis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
/* eslint-disable global-require */
/* eslint-disable import/no-dynamic-require */
/* eslint-disable no-unused-expressions */
/* eslint-disable no-console */
/* eslint-disable multiline-comment-style */
/* eslint-disable no-restricted-syntax */
/* eslint-disable no-await-in-loop */
/* eslint-disable guard-for-in */
/* eslint-disable import/no-extraneous-dependencies */

const { Scalar } = require('ffjavascript');
const fs = require('fs');

const ethers = require('ethers');
const {
Address,
} = require('ethereumjs-util');
const { defaultAbiCoder } = require('@ethersproject/abi');
const path = require('path');

const { argv } = require('yargs');
const {
MemDB, ZkEVMDB, getPoseidon, processorUtils, smtUtils, Constants,
} = require('@0xpolygonhermez/zkevm-commonjs');
const contractsPolygonHermez = require('../index');

// Example of use: node create-genesis.js --gen genesis-gen.json --out genesis.json
async function main() {
// load generator
const inputPath = (typeof argv.gen === 'undefined') ? undefined : argv.gen;
if (inputPath === undefined) { throw Error('Input genesis must be provided'); }

// load output file
const outPath = (typeof argv.out === 'undefined') ? undefined : argv.out;
if (outPath === undefined) { throw Error('Output file must be specified'); }

const genesisGenerator = require(path.join(__dirname, inputPath));

const genesisOutput = {};
const poseidon = await getPoseidon();
const { F } = poseidon;

const genesisRoot = [F.zero, F.zero, F.zero, F.zero];
const accHashInput = [F.zero, F.zero, F.zero, F.zero];
const globalExitRoot = ethers.constants.HashZero;

const {
genesis,
txs,
sequencerAddress,
timestamp,
defaultChainId,
} = genesisGenerator;

const db = new MemDB(F);

// create a zkEVMDB and build a batch
const zkEVMDB = await ZkEVMDB.newZkEVM(
db,
poseidon,
genesisRoot,
accHashInput,
genesis,
null,
null,
defaultChainId,
);

/*
* build, sign transaction and generate rawTxs
* rawTxs would be the calldata inserted in the contract
*/
const addressToContractName = {};
const rawTxs = [];
for (let j = 0; j < txs.length; j++) {
const currentTx = txs[j];

const tx = {
to: currentTx.to || '0x',
nonce: currentTx.nonce,
value: processorUtils.toHexStringRlp(ethers.utils.parseUnits(currentTx.value, 'wei')),
gasLimit: currentTx.gasLimit,
gasPrice: processorUtils.toHexStringRlp(ethers.utils.parseUnits(currentTx.gasPrice, 'wei')),
chainId: currentTx.chainId,
data: currentTx.data || '0x',
};

// Contract deployment from tx
let bytecode; let
abi;
if (contractsPolygonHermez[currentTx.contractName]) {
({ bytecode, abi } = contractsPolygonHermez[currentTx.contractName]);
}
if (currentTx.function) {
const interfaceContract = new ethers.utils.Interface(abi);
tx.data = interfaceContract.encodeFunctionData(currentTx.function, currentTx.paramsFunction);
} else {
if (currentTx.paramsDeploy) {
const params = defaultAbiCoder.encode(currentTx.paramsDeploy.types, currentTx.paramsDeploy.values);
tx.data = bytecode + params.slice(2);
} else {
tx.data = bytecode;
}
const addressContract = await ethers.utils.getContractAddress(
{ from: currentTx.from, nonce: currentTx.nonce },
);
addressToContractName[addressContract.toLowerCase()] = currentTx.contractName;
}

let customRawTx;
const address = genesis.find((o) => o.address === currentTx.from);
const wallet = new ethers.Wallet(address.pvtKey);
if (tx.chainId === 0) {
const signData = ethers.utils.RLP.encode([
processorUtils.toHexStringRlp(Scalar.e(tx.nonce)),
processorUtils.toHexStringRlp(tx.gasPrice),
processorUtils.toHexStringRlp(tx.gasLimit),
processorUtils.toHexStringRlp(tx.to),
processorUtils.toHexStringRlp(tx.value),
processorUtils.toHexStringRlp(tx.data),
processorUtils.toHexStringRlp(tx.chainId),
'0x',
'0x',
]);
const digest = ethers.utils.keccak256(signData);
const signingKey = new ethers.utils.SigningKey(address.pvtKey);
const signature = signingKey.signDigest(digest);
const r = signature.r.slice(2).padStart(64, '0'); // 32 bytes
const s = signature.s.slice(2).padStart(64, '0'); // 32 bytes
const v = (signature.v).toString(16).padStart(2, '0'); // 1 bytes
customRawTx = signData.concat(r).concat(s).concat(v);
} else {
const rawTxEthers = await wallet.signTransaction(tx);
customRawTx = processorUtils.rawTxToCustomRawTx(rawTxEthers);
}
rawTxs.push(customRawTx);
}

const skipUpdateSystemStorage = true;
const batch = await zkEVMDB.buildBatch(
timestamp,
sequencerAddress,
smtUtils.stringToH4(globalExitRoot),
undefined,
skipUpdateSystemStorage,
);
for (let j = 0; j < rawTxs.length; j++) {
batch.addRawTx(rawTxs[j]);
}

// execute the transactions added to the batch
await batch.executeTxs();
// consolidate state
await zkEVMDB.consolidate(batch);

// clean address 0 batch, clean globalExitRoot
const updatedAccounts = batch.getUpdatedAccountsBatch();
const currentVM = batch.vm;
const accountsOutput = [];

for (const item in updatedAccounts) {
const address = item;
const account = updatedAccounts[address];
const currentAccountOutput = {};
currentAccountOutput.balance = account.balance.toString();
currentAccountOutput.nonce = account.nonce.toString();
currentAccountOutput.address = address;

// If account is a contract, update storage and bytecode
if (account.isContract()) {
const addressInstance = Address.fromString(address);
const smCode = await currentVM.stateManager.getContractCode(addressInstance);
const sto = await currentVM.stateManager.dumpStorage(addressInstance);
const storage = {};
const keys = Object.keys(sto).map((v) => `0x${v}`);
const values = Object.values(sto).map((v) => `0x${v}`);
for (let k = 0; k < keys.length; k++) {
storage[keys[k]] = ethers.utils.RLP.decode(values[k]);
}

currentAccountOutput.bytecode = `0x${smCode.toString('hex')}`;
currentAccountOutput.storage = storage;
currentAccountOutput.contractName = addressToContractName[address];
} else if (address !== Constants.ADDRESS_SYSTEM
&& address.toLowerCase() !== Constants.ADDRESS_GLOBAL_EXIT_ROOT_MANAGER_L2.toLowerCase()) {
currentAccountOutput.pvtKey = (genesis.find((o) => o.address.toLowerCase() === address.toLowerCase())).pvtKey;
}
accountsOutput.push(currentAccountOutput);
}

// add accounts that has not been used
for (let i = 0; i < genesis.length; i++) {
const item = genesis[i];
if (typeof updatedAccounts[item.address.toLowerCase()] === 'undefined') {
accountsOutput.push(item);
}
}

genesisOutput.root = smtUtils.h4toString(batch.currentStateRoot);
genesisOutput.genesis = accountsOutput;
const genesisOutputPath = path.join(__dirname, outPath);
await fs.writeFileSync(genesisOutputPath, JSON.stringify(genesisOutput, null, 2));

if (argv.update) {
const updatePath = (typeof argv.update === 'undefined') ? undefined : argv.update;

if (!fs.existsSync(updatePath)) {
throw new Error('Update file does not exist');
}

const testVectors = JSON.parse(fs.readFileSync(updatePath));
testVectors[0].genesis = genesisOutput.genesis;
testVectors[0].expectedOldRoot = genesisOutput.root;
await fs.writeFileSync(updatePath, JSON.stringify(testVectors, null, 2));
}
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

0 comments on commit 3a866d9

Please sign in to comment.