Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prod release 5/4 #131

Merged
merged 10 commits into from
May 5, 2020
Merged
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ WORKDIR /server
COPY . /server
RUN yarn

# Copy live env config updates file to /server so that it may be updated while running.
COPY ./packages/rollup-full-node/config/env_var_updates.config /server

WORKDIR /server/packages/rollup-full-node

EXPOSE 8545
Expand Down
5 changes: 5 additions & 0 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM node:11
WORKDIR /mnt/full-node/packages/rollup-full-node

EXPOSE 8545
CMD [ "bash", "./exec/wait-for-nodes.sh", "yarn", "run", "server:fullnode:debug" ]
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,5 +120,20 @@ Run tests for a specific package or set of packages:
PKGS=your,packages,here yarn test
```

### Running the fullnode in Docker
Running the fullnode in [Docker](https://www.docker.com/) allows us launch our entire stack with a single command.

To run the fullnode in Docker in production run:

`docker-compose up`

To run it in development run:

```sh
rm -rf node_modules
docker-compose -f docker-compose.yml -f docker-compose.dev.yml run rollup-full-node yarn
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up
```

**Contributors: remember to run tests and lint before submitting a pull request!**
Linted code with passing tests makes life easier for everyone and means your contribution can get pulled into this project faster.
4 changes: 2 additions & 2 deletions aws/synthetix/prod/web/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ services:
postgres_pass: let-me-in
postgres_db: graph-node
ipfs: '0.0.0.0:5001'
ethereum: 'ovm:http://0.0.0.0:8545'
ethereum: 'ovm:http://0.0.0.0:8546'
RUST_LOG: info
STARTUP_WAIT_TIMEOUT: 30
OVM_URL_WITH_PORT: 'http://0.0.0.0:8545'
OVM_URL_WITH_PORT: 'http://0.0.0.0:8546'
volumes:
- postgres-data:/data/postgres
- ipfs-data:/data/ipfs
Expand Down
4 changes: 2 additions & 2 deletions aws/synthetix/uat/web/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ services:
postgres_pass: let-me-in
postgres_db: graph-node
ipfs: '0.0.0.0:5001'
ethereum: 'ovm:http://0.0.0.0:8545'
ethereum: 'ovm:http://0.0.0.0:8546'
RUST_LOG: info
STARTUP_WAIT_TIMEOUT: 30
OVM_URL_WITH_PORT: 'http://0.0.0.0:8545'
OVM_URL_WITH_PORT: 'http://0.0.0.0:8546'
volumes:
- postgres-data:/data/postgres
- ipfs-data:/data/ipfs
Expand Down
9 changes: 9 additions & 0 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: "3"
services:

rollup-full-node:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- .:/mnt/full-node:rw
56 changes: 56 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ services:
- L2_RPC_SERVER_PORT=8545
- TRANSACTION_NODE_URL=http://rollup-full-node:8546
- READ_ONLY_NODE_URL=http://read-only-node:8547
- REQUEST_LIMIT_PERIOD_MILLIS=1000
- MAX_NON_TRANSACTION_REQUESTS_PER_UNIT_TIME=10
- MAX_TRANSACTIONS_PER_UNIT_TIME=10

read-only-node:
image: optimism-monorepo_rollup-full-node:latest
Expand Down Expand Up @@ -77,7 +80,60 @@ services:
ports:
- 9545:9545

graph-node:
build:
context: docker/the-graph
dockerfile: Dockerfile
ports:
- '8000:8000'
- '8001:8001'
- '8020:8020'
- '8030:8030'
- '8040:8040'
environment:
postgres_host: postgres:5432
postgres_user: graph-node
postgres_pass: let-me-in
postgres_db: graph-node
ipfs: 'ipfs:5001'
ethereum: 'ovm:http://router:8545'
RUST_LOG: info
STARTUP_WAIT_TIMEOUT: 30
OVM_URL_WITH_PORT: 'http://router:8545'
volumes:
- postgres-data:/data/postgres
- ipfs-data:/data/ipfs

ipfs:
image: ipfs/go-ipfs:v0.4.23
ports:
- '5001:5001'
volumes:
- ipfs-data:/data/ipfs

postgres:
image: postgres
ports:
- '5432:5432'
command: ["postgres", "-cshared_preload_libraries=pg_stat_statements"]
environment:
POSTGRES_USER: graph-node
POSTGRES_PASSWORD: let-me-in
POSTGRES_DB: graph-node
volumes:
- postgres-data:/var/lib/postgresql/data

volumes:
full-node-data:
l1-node-data:
l2-node-data:
postgres-data:
ipfs-data:








21 changes: 18 additions & 3 deletions packages/core-utils/src/app/log.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
import debug from 'debug'
import { Logger } from '../types'

export const LOG_NEWLINE_STRING = '<\n>'
export const joinNewlinesAndDebug = (logs: string) =>
debug(logs.replace('\n', LOG_NEWLINE_STRING))
export const LOG_CR_STRING = '<\\r>'
export const LOG_NEWLINE_STRING = '<\\n>'
export const joinNewlinesAndDebug = (...logs: any[]) => {
const stringifiedLogs = []
for (const l of logs) {
if (typeof l !== 'string') {
stringifiedLogs.push(JSON.stringify(l))
} else {
stringifiedLogs.push(l)
}
}
return debug(
stringifiedLogs
.join(' ')
.replace(/\n/g, LOG_NEWLINE_STRING)
.replace(/\r/g, LOG_CR_STRING)
)
}

export const getLogger = (
identifier: string,
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/src/core/src/spec/jump-transpilation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,4 @@ Duplicate above code once for each (compare jumpdest, post-transpile jumpdest) p

**Note on bytecode interpretation**

Note that properly processing these conditions requires preprocessing the code; a particularly pathological use case is ``PUSH2 JUMPDEST PUSH1 PUSH2 JUMPDEST PUSH1 PUSH2 JUMPDEST PUSH1 ...``, as this code has all ``JUMPDEST``s invalid but an alternative piece of code equivalent to this but only with the leading ``PUSH2`` replaced with another op (eg. ``BALANCE``) will have all ``JUMPDESTS`` valid. We appropriately deal with this, both in our transpiler and purity checker.
Note that properly processing these conditions requires preprocessing the code; a particularly pathological use case is ``PUSH2 JUMPDEST PUSH1 PUSH2 JUMPDEST PUSH1 PUSH2 JUMPDEST PUSH1 ...``, as this code has all ``JUMPDEST``s invalid but an alternative piece of code equivalent to this but only with the leading ``PUSH2`` replaced with another op (eg. ``BALANCE``) will have all ``JUMPDESTS`` valid. We appropriately deal with this, both in our transpiler and safety checker.
6 changes: 3 additions & 3 deletions packages/docs/src/core/src/spec/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ OVM Overview and Architecture

The core functionality of the OVM is to run transactions in such a way that they are "pure" or "deterministic"--that is, no matter what time in the future a dispute about them is triggered on layer 1, the output of the computation is the same--*no matter what the state of the L1.

To accomplish this, there are two critical smart contracts: the Execution Manager, and the Purity Checker.
To accomplish this, there are two critical smart contracts: the Execution Manager, and the Safety Checker.

*****************
Execution Manager
Expand All @@ -19,10 +19,10 @@ The execution manager interfaces with "code contracts," which are contracts comp
<img src="../../_static/images/execution-manager.png" alt="The Execution Manager">

**************
Purity Checker
Safety Checker
**************

To ensure that the execution of an OVM transaction is deterministic between L1 and L2, we must enforce that **only** the container interface described above is used. To accomplish this, we have a "purity checker." The purity checker analyzes the low-level assembly bytecode of an EVM contract to tell the execution manager whether the code conforms to the OVM interface. If it does not, then the execution manager does not allow such a contract to be created or used in a fraud proof.
To ensure that the execution of an OVM transaction is deterministic between L1 and L2, we must enforce that **only** the container interface described above is used. To accomplish this, we have a "safety checker." The safety checker analyzes the low-level assembly bytecode of an EVM contract to tell the execution manager whether the code conforms to the OVM interface. If it does not, then the execution manager does not allow such a contract to be created or used in a fraud proof.

.. raw:: html

Expand Down
4 changes: 2 additions & 2 deletions packages/docs/src/core/src/spec/transpilation-details.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The following opcodes perform stack operations which are constant in terms of L1
- "Pure" memory modifying operations:
- ``MLOAD, MSTORE, MSTORE8, MSIZE``.
- Permitted execution-context-dependent operations:
- ``CALLVALUE*, CALLDATALOAD, CALLDATASIZE, CALLDATACOPY, CODESIZE, RETURNDATASIZE, RETURNDATACOPY`` \*Note: ``CALLVALUE`` will always be 0 because we enforce that all ``CALL`` s always pass 0 in our purity checking.
- ``CALLVALUE*, CALLDATALOAD, CALLDATASIZE, CALLDATACOPY, CODESIZE, RETURNDATASIZE, RETURNDATACOPY`` \*Note: ``CALLVALUE`` will always be 0 because we enforce that all ``CALL`` s always pass 0 in our safety checking.

Replaced Opcodes
================
Expand Down Expand Up @@ -119,7 +119,7 @@ These opcodes are banned simply because we don't want to support them currently.
ETH-native Value
-----------------------------------------

We have made the decision for now not to use native ETH, and instead do everything with wrapped ETH (WETH). Note: ``CALLVALUE`` is actually able to be whitelisted, because our Purity Checker enforces that all Calls are made with a value of 0. Contracts are welcome to use msg.value, it will just always return 0. This means that the following opcodes are banned, not just transpiled:
We have made the decision for now not to use native ETH, and instead do everything with wrapped ETH (WETH). Note: ``CALLVALUE`` is actually able to be whitelisted, because our Safety Checker enforces that all Calls are made with a value of 0. Contracts are welcome to use msg.value, it will just always return 0. This means that the following opcodes are banned, not just transpiled:
- ``BALANCE`` -- gets ``address(this).balance``
While not a ban, another note here is that all ``value``-related inputs to other opcodes like ``CREATE`` or ``CALL`` are overridden to ``0`` by their transpiled counterparts. We do have good inline documentation for how a native ``value`` could be added if needed. Another option is we could even transpile the native ETH opcodes to use ``WETH`` instead. TBD.

Expand Down
4 changes: 2 additions & 2 deletions packages/ovm/config/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# Mnemonic for the wallet used to deploy the contracts
DEPLOY_MNEMONIC='response fresh afford leader twice silent table exist aisle pelican focus bird'

DEPLOY_PURITY_CHECKER_CONTRACT_ADDRESS='0x some address here'
DEPLOY_SAFETY_CHECKER_CONTRACT_ADDRESS='0x some address here'

# Note: can use any network name. 'local' or leaving it blank will deploy to DEPLOY_LOCAL_URL
DEPLOY_NETWORK='local'
Expand All @@ -30,4 +30,4 @@ OPCODE_WHITELIST_MASK='0x600a0000000000000000001fffffffffffffffff0fcf000063f0000
# CREATE, CREATE2, DELEGATECALL, DIFFICULTY, EXTCODECOPY, EXTCODESIZE,
# GASLIMIT, GASPRICE, NUMBER, ORIGIN, SELFDESTRUCT, SLOAD, SSTORE,
# STATICCALL, TIMESTAMP
# See test/purity-checker/whitelist-mask-generator.spec.ts for more info
# See test/safety-checker/whitelist-mask-generator.spec.ts for more info
6 changes: 3 additions & 3 deletions packages/ovm/deploy/execution-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { deploy, deployContract } from '@eth-optimism/core-utils'
import { Wallet } from 'ethers'

/* Internal Imports */
import { deployPurityChecker } from './purity-checker'
import { deploySafetyChecker } from './safety-checker'
import * as ExecutionManager from '../build/contracts/ExecutionManager.json'
import { resolve } from 'path'
import { GAS_LIMIT, DEFAULT_OPCODE_WHITELIST_MASK } from '../src/app'
Expand All @@ -13,13 +13,13 @@ const executionManagerDeploymentFunction = async (
): Promise<string> => {
console.log(`\nDeploying ExecutionManager!\n`)

const purityCheckerContractAddress = await deployPurityChecker()
const safetyCheckerContractAddress = await deploySafetyChecker()

const executionManager = await deployContract(
ExecutionManager,
wallet,
DEFAULT_OPCODE_WHITELIST_MASK,
purityCheckerContractAddress,
safetyCheckerContractAddress,
GAS_LIMIT,
true
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ import { deploy, deployContract, add0x } from '@eth-optimism/core-utils'
import { Wallet } from 'ethers'

/* Internal Imports */
import * as PurityChecker from '../build/contracts/PurityChecker.json'
import * as SafetyChecker from '../build/contracts/SafetyChecker.json'
import { resolve } from 'path'

const purityCheckerDeploymentFunction = async (
const safetyCheckerDeploymentFunction = async (
wallet: Wallet
): Promise<Address> => {
let purityCheckerContractAddress =
process.env.DEPLOY_PURITY_CHECKER_CONTRACT_ADDRESS
if (!purityCheckerContractAddress) {
console.log(`\nDeploying Purity Checker!\n`)
let safetyCheckerContractAddress =
process.env.DEPLOY_SAFETY_CHECKER_CONTRACT_ADDRESS
if (!safetyCheckerContractAddress) {
console.log(`\nDeploying Safety Checker!\n`)

// Default config whitelists all opcodes EXCEPT:
// ADDRESS, BALANCE, BLOCKHASH, CALLCODE, CALLER, COINBASE,
// CREATE, CREATE2, DELEGATECALL, DIFFICULTY, EXTCODECOPY, EXTCODESIZE,
// GASLIMIT, GASPRICE, NUMBER, ORIGIN, SELFDESTRUCT, SLOAD, SSTORE,
// STATICCALL, TIMESTAMP
// See test/purity-checker/whitelist-mask-generator.spec.ts for more info
// See test/contracts/whitelist-mask-generator.spec.ts for more info
const whitelistMask =
process.env.OPCODE_WHITELIST_MASK ||
'0x600a0000000000000000001fffffffffffffffff0fcf000063f000013fff0fff'
Expand All @@ -29,41 +29,41 @@ const purityCheckerDeploymentFunction = async (
process.env.EXECUTION_MANAGER_ADDRESS || add0x('12'.repeat(20))

console.log(
`Deploying Purity Checker using mask '${whitelistMask}' and execution manager '${executionManagerAddress}'...`
`Deploying Safety Checker using mask '${whitelistMask}' and execution manager '${executionManagerAddress}'...`
)
whitelistMask
const purityChecker = await deployContract(
PurityChecker,
const safetyChecker = await deployContract(
SafetyChecker,
wallet,
whitelistMask,
executionManagerAddress
)
purityCheckerContractAddress = purityChecker.address
safetyCheckerContractAddress = safetyChecker.address

console.log(
`Purity Checker deployed to ${purityCheckerContractAddress}!\n\n`
`Safety Checker deployed to ${safetyCheckerContractAddress}!\n\n`
)
} else {
console.log(
`Using Purity Checker contract at ${purityCheckerContractAddress}\n`
`Using Safety Checker contract at ${safetyCheckerContractAddress}\n`
)
}
return purityCheckerContractAddress
return safetyCheckerContractAddress
}

/**
* Deploys the Purity Checker contract.
* Deploys the Safety Checker contract.
*
* @param rootContract Whether or not this is the main contract being deployed (as compared to a dependency).
* @returns The deployed contract's address.
*/
export const deployPurityChecker = async (
export const deploySafetyChecker = async (
rootContract: boolean = false
): Promise<string> => {
// Note: Path is from 'build/deploy/<script>.js'
const configDirPath = resolve(__dirname, `../../config/`)

return deploy(purityCheckerDeploymentFunction, configDirPath, rootContract)
return deploy(safetyCheckerDeploymentFunction, configDirPath, rootContract)
}

deployPurityChecker(true)
deploySafetyChecker(true)
2 changes: 1 addition & 1 deletion packages/ovm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"build": "mkdir -p ./build && waffle waffle-config.json && tsc -p .",
"clean": "rimraf build/",
"deploy:execution-manager": "yarn build && node ./build/deploy/execution-manager.js",
"deploy:purity-checker": "yarn build && node ./build/deploy/purity-checker.js"
"deploy:safety-checker": "yarn build && node ./build/deploy/safety-checker.js"
},
"keywords": [
"optimistic",
Expand Down
Loading