This repository has been archived by the owner on Dec 5, 2021. It is now read-only.
forked from ethereum-optimism/optimism
-
Notifications
You must be signed in to change notification settings - Fork 6
Add regenesis #237
Open
boyuan-chen
wants to merge
27
commits into
develop
Choose a base branch
from
add-regenesis
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Add regenesis #237
Changes from 15 commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
62e72c5
Add regenesis
boyuan-chen 9e64856
Merge branch 'develop' into add-regenesis
CAPtheorem ec3e1ae
Merge branch 'develop' into add-regenesis
CAPtheorem 83340fd
Merge branch 'develop' into add-regenesis
CAPtheorem 353b4c1
Add L1MessengerRegenesis contract
boyuan-chen bbd746f
In progress
boyuan-chen e90dcf9
Merge branch 'develop' into add-regenesis
CAPtheorem 301c298
Merge branch 'develop' into add-regenesis
CAPtheorem 65531fb
Merge branch 'develop' into add-regenesis
boyuan-chen 28fdce1
Add regenesis
boyuan-chen 1f6a6c8
Add message relayer regenesis
boyuan-chen 9b0c8d0
Update package.json
boyuan-chen 3c4b3ac
Update package.json
boyuan-chen 9752d3c
Update README.md
boyuan-chen 4e931fb
Update README.md
boyuan-chen 33fcaa1
Remove OVM_L1CrossDomainMessenger
boyuan-chen 34d9982
Merge branch 'develop' into add-regenesis
CAPtheorem 05cd647
Fix regenesis contract
boyuan-chen baf9559
Merge branch 'develop' into add-regenesis
CAPtheorem cb66f83
regenesis v2
boyuan-chen 41713ba
Finish Regenesis
boyuan-chen f0246d1
Merge branch 'develop' into add-regenesis
CAPtheorem 217f5f8
Merge branch 'develop' into add-regenesis
CAPtheorem 0239748
Merge branch 'develop' into add-regenesis
boyuan-chen 9497c82
Add integration regenesis
boyuan-chen 7c07797
Merge branch 'add-regenesis' of https://github.com/omgnetwork/optimis…
boyuan-chen 198cb28
Merge branch 'develop' into add-regenesis
CAPtheorem File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/* External Imports */ | ||
import * as fs from 'fs' | ||
import * as path from 'path' | ||
|
||
/* Internal Imports */ | ||
import { makeRegenesisDump } from '../src/regenesis/make-regenesis' | ||
;(async () => { | ||
const outdir = path.resolve(__dirname, '../dist/dumps') | ||
const stateDumpLatestDir = path.join(outdir, 'state-dump.latest.json') | ||
const stateDumpGenesisDir = path.join(outdir, 'state-dump.genesis.json') | ||
|
||
const stateDumpLatest = JSON.parse(fs.readFileSync(stateDumpLatestDir, 'utf-8')) | ||
const stateDumpGenesis = JSON.parse(fs.readFileSync(stateDumpGenesisDir, 'utf-8')) | ||
|
||
const dump = makeRegenesisDump(stateDumpLatest, stateDumpGenesis) | ||
fs.writeFileSync(stateDumpLatestDir, JSON.stringify(dump, null, 4)) | ||
})() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
export const makeRegenesisDump = (dump:any, genesis: any) => { | ||
const stateDumpGeneis = genesis.accounts | ||
const stateDumpLatest = dump.accounts | ||
|
||
// We only update the data storage of OVM_ETH | ||
// in state-dump.latest.json | ||
const updatePredeployedContract = [ | ||
"OVM_ETH", | ||
] | ||
// get the predeployed contracts | ||
// { CONTRACT_ADDRESS: CONTRACT_NAME } | ||
const predeployedContract = Object.keys(stateDumpLatest) | ||
.reduce((acc, cur) => { | ||
acc[stateDumpLatest[cur].address] = cur | ||
return acc | ||
}, {}) | ||
|
||
predeployedContract["0x420000000000000000000000000000000000000b"] = "EXECUTION_MANAGER_WRAPPER" | ||
predeployedContract["0x420000000000000000000000000000000000000f"] = "OVM_GasPriceOracle" | ||
|
||
for (const eachAddress of Object.keys(stateDumpGeneis)) { | ||
const contractName = predeployedContract[eachAddress] | ||
// contracts that are not predeployed | ||
if (typeof contractName === 'undefined') { | ||
stateDumpLatest[eachAddress] = { | ||
address: eachAddress, | ||
...stateDumpGeneis[eachAddress] | ||
} | ||
// Update OVM_ETH | ||
} else if (updatePredeployedContract.includes(contractName)) { | ||
stateDumpLatest[contractName].storage = stateDumpGeneis[eachAddress].storage | ||
} | ||
} | ||
|
||
return { accounts: stateDumpLatest } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
NODE_ENV=local | ||
L1_NODE_WEB3_URL=http://localhost:9545 | ||
L2_NODE_WEB3_URL=http://localhost:8545 | ||
ADDRESS_MANAGER_ADDRESS=0x5FbDB2315678afecb367f032d93F642f64180aa3 | ||
DEPLOYER_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 | ||
L1_WALLET_KEY=0xde9be858da4a475276426320d5e9262ecfc3ba460bfac56360bfa6c4c28b4ee0 | ||
TEST_PRIVATE_KEY_1=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 | ||
TARGET_GAS_LIMIT=9000000000 | ||
CHAIN_ID=28 | ||
URL=http://localhost:8080/addresses.json | ||
OMGX_URL=http://localhost:8078/addresses.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# Regenesis | ||
|
||
The regenesis means that we upgrade the OMGX network by regenerating the genesis block. During the regenesis, the state dump of the latest block is generated (including all user's nonces, token balances, contract code, and contract storage) and a new chain is spun up from this latest state sump. Since the new chain is started from the new genesis block, we have to remove all transaction history and logs. The transaction history and logs will be inaccessible from the new chain except under extreme circumstances. | ||
|
||
## Upcoming | ||
|
||
### 2.0.0 - L2 upgradeablity | ||
|
||
* Rinkeby -- 08/04/2021 | ||
|
||
Upgrade the gas contract and add the fee vault contract | ||
|
||
## What will happen on the Regenesis day? | ||
|
||
The regenesis process takes up to 6 hours. All deposits will be halted and the L2 endpoint will become private! **DON'T** deposit your funds to **L1StandardTokenBridge** and **L1LiquidityPool** during the regenesis process! We will accept new transactions again once the regenesis is done. | ||
|
||
## How does a Regenesis affect tooling? | ||
|
||
Since we start from the block #0 after the regenesis, the Graph will have to re-sync their hosted service and users will have to redeploy all of their subgraphs. [blockexplorer](https://blockexplorer.rinkeby.omgx.network/?network=OmgX) won't maintain the transaction history before the regenesis. | ||
|
||
## How do we make a Regenesis? | ||
|
||
> This part is for someone who understands the optimism infrastructure. | ||
|
||
### Step 0: make the L2 endpoint private | ||
|
||
The L2 endpoint can only be accessed from specific ip addresses. | ||
|
||
### Step 1: speed up the pending transactions from L2 to L1 | ||
|
||
The genesis redeploys all L1 contracts, so there is no way to relay those messages to L1 after the regenesis. Speeding up the transactions requires us to deploy a new **OVM_L1CrossDomainMessenger** to bypass the 7-day waiting period first. | ||
|
||
Deploying a new **OVM_L1CrossDomainMessenger** via: | ||
|
||
```bash | ||
cd packages/omgx/regenesis | ||
yarn build:contracts | ||
yarn deploy | ||
``` | ||
|
||
After deploying the **OVM_L1CrossDomainMessenger** contract, run the modified message relayer via: | ||
|
||
```bash | ||
yarn build | ||
yarn start | ||
``` | ||
|
||
The modified message relayer scans all the messages that are supposed to be relayed on L1 contract and makes sure that all messages are relayed to L1 contracts. | ||
|
||
### Step 2: redeploy contracts | ||
|
||
The regenesis means that we will redeploy the L1 contracts. However, we don't redeploy the following contracts: **Lib_AddressManager**, **Proxy__OVM_L1CrossDomainMessenger**, **Proxy__OVM_L1StandardBridge** and **Proxy__OVM_L1CrossDomainMessengerFast**. The address of **Lib_AddressManager** is stored in the proxy contracts, we have to keep both proxy contracts and address manager contract. Removing the rest `.json` files in `packages/contracts/deployments/..` and deploying the new contracts via: | ||
|
||
```bash | ||
yarn deploy | ||
``` | ||
|
||
### Step 3: take a state dump of the latest block | ||
|
||
The L2 chain data is stored in EC2 and ECS. Copy the L2 chain data to your local directory first, then run | ||
|
||
```bash | ||
geth dump LATEST_BLOCK_NUMBER --datadir DATADIRCTOTY > packages/contracts/dist/dump/state-dump.regenesis.json | ||
``` | ||
|
||
Migrate the latest state dump data into our genesis block json file via: | ||
|
||
```bash | ||
yarn build:dump | ||
yarn build:regenesis | ||
``` | ||
|
||
### Step 4: fire up a new chain using the new `state-dump.latest.json` | ||
|
||
## Note | ||
|
||
The regenesis process is very **dangerous!** **DON'T touch it if you don't understand what you are doing.** | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import { Wallet, providers } from 'ethers' | ||
import { getContractFactory } from '@eth-optimism/contracts' | ||
|
||
require('dotenv').config() | ||
|
||
import hre from 'hardhat' | ||
|
||
const main = async () => { | ||
|
||
console.log('Starting OMGX regenesis contracts deployment...') | ||
|
||
//const config = parseEnv() | ||
//not clear if the output is used anywhere? | ||
|
||
const network = process.env.NETWORK || 'local' | ||
|
||
const l1Provider = new providers.JsonRpcProvider(process.env.L1_NODE_WEB3_URL) | ||
const l2Provider = new providers.JsonRpcProvider(process.env.L2_NODE_WEB3_URL) | ||
|
||
const deployer_l1 = new Wallet(process.env.DEPLOYER_PRIVATE_KEY, l1Provider) | ||
const deployer_l2 = new Wallet(process.env.DEPLOYER_PRIVATE_KEY, l2Provider) | ||
|
||
const getAddressManager = (provider: any, addressManagerAddress: any) => { | ||
return getContractFactory('Lib_AddressManager') | ||
.connect(provider) | ||
.attach(addressManagerAddress) as any | ||
} | ||
|
||
console.log(`ADDRESS_MANAGER_ADDRESS was set to ${process.env.ADDRESS_MANAGER_ADDRESS}`) | ||
const addressManager = getAddressManager(deployer_l1, process.env.ADDRESS_MANAGER_ADDRESS); | ||
|
||
const l1MessengerAddress = await addressManager.getAddress( | ||
'Proxy__OVM_L1CrossDomainMessenger' | ||
) | ||
|
||
const OVM_L1CrossDomainMessengerAddress = await addressManager.getAddress( | ||
'OVM_L1CrossDomainMessenger' | ||
) | ||
|
||
const l2MessengerAddress = await addressManager.getAddress( | ||
'OVM_L2CrossDomainMessenger' | ||
) | ||
|
||
const L1StandardBridgeAddress = await addressManager.getAddress( | ||
'Proxy__OVM_L1StandardBridge' | ||
) | ||
const L1StandardBridge = getContractFactory('OVM_L1StandardBridge') | ||
.connect(deployer_l1) | ||
.attach(L1StandardBridgeAddress) | ||
|
||
const L2StandardBridgeAddress = await L1StandardBridge.l2TokenBridge() | ||
|
||
await hre.run('deploy', { | ||
l1MessengerAddress, | ||
l2MessengerAddress, | ||
OVM_L1CrossDomainMessengerAddress, | ||
L1StandardBridgeAddress, | ||
L2StandardBridgeAddress, | ||
l1Provider, | ||
l2Provider, | ||
deployer_l1, | ||
deployer_l2, | ||
addressManager, | ||
network, | ||
//noCompile: process.env.NO_COMPILE ? true : false, //not clear how/where this is connected | ||
}) | ||
|
||
} | ||
|
||
main() | ||
.then(() => process.exit(0)) | ||
.catch((error) => { | ||
console.log( | ||
JSON.stringify({ error: error.message, stack: error.stack }, null, 2) | ||
) | ||
process.exit(1) | ||
}) | ||
|
||
//Based on the code, does not seem to be used? | ||
// function parseEnv() { | ||
|
||
// function ensure(env, type) { | ||
// if (typeof process.env[env] === 'undefined') | ||
// return undefined | ||
// if (type === 'number') | ||
// return parseInt(process.env[env], 10) | ||
// return process.env[env] | ||
// } | ||
|
||
// return { | ||
// l1provider: ensure('L1_NODE_WEB3_URL', 'string'), | ||
// l2provider: ensure('L2_NODE_WEB3_URL', 'string'), | ||
// deployer: ensure('DEPLOYER_PRIVATE_KEY', 'string'), | ||
// emOvmChainId: ensure('CHAIN_ID', 'number'), | ||
// } | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >0.5.0; | ||
|
||
/* Library Imports */ | ||
import "@eth-optimism/contracts/contracts/optimistic-ethereum/libraries/bridge/OVM_CrossDomainEnabled.sol"; | ||
import { L2Message } from "./L2Message.sol"; | ||
|
||
contract L1Message is OVM_CrossDomainEnabled { | ||
|
||
address L2MessageAddress; | ||
string crossDomainMessage; | ||
uint256 public crossDomainMessageCount; | ||
|
||
event ReceiveL2Message ( | ||
string _message | ||
); | ||
|
||
/******************** | ||
* Constructor * | ||
********************/ | ||
constructor ( | ||
address _l1CrossDomainMessenger | ||
) | ||
OVM_CrossDomainEnabled(_l1CrossDomainMessenger) | ||
{} | ||
|
||
function init ( | ||
address _L2MessageAddress | ||
) | ||
public | ||
{ | ||
L2MessageAddress = _L2MessageAddress; | ||
} | ||
|
||
function sendMessageL1ToL2 () public { | ||
bytes memory data = abi.encodeWithSelector( | ||
L2Message.receiveL1Message.selector, | ||
"messageFromL1" | ||
); | ||
|
||
// Send calldata into L1 | ||
sendCrossDomainMessage( | ||
address(L2MessageAddress), | ||
1200000, | ||
data | ||
); | ||
} | ||
|
||
/************************* | ||
* Cross-chain Functions * | ||
*************************/ | ||
|
||
/** | ||
* Receive message from L2 | ||
* @param _message message | ||
*/ | ||
function receiveL2Message( | ||
string memory _message | ||
) | ||
external | ||
onlyFromCrossDomainAccount(address(L2MessageAddress)) | ||
{ | ||
crossDomainMessage = _message; | ||
crossDomainMessageCount = crossDomainMessageCount + 1; | ||
emit ReceiveL2Message(_message); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the script that we have used to make the regenesis: https://github.com/ethereum-optimism/scripts/blob/main/scripts/state-surgery.js. It currently includes some specific logic for the previous regenesis, so look at its history if you are interested in seeing a more pure form.
Whenever there is another regenesis, we will move it into the monorepo and be very thorough around using it and documenting it.