diff --git a/.dockerignore b/.dockerignore index 899e50f654..772449ce10 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,6 @@ * !target/x86_64-unknown-linux-musl/release/server +!target/x86_64-unknown-linux-musl/release/server_supervisor !target/x86_64-unknown-linux-musl/release/prover !docker/prover/prover-entry.sh !docker/nginx/nginx.conf diff --git a/.drone.yml b/.drone.yml index 89f94877fc..7b956c6c3d 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,246 +1,283 @@ +--- kind: pipeline type: docker name: tests + +platform: + os: linux + arch: amd64 + clone: - depth: 10 -volumes: - - name: cache - host: - path: /drone-cache -services: - - name: geth - image: matterlabs/geth:latest - - name: postgres - image: postgres:10.4 -trigger: - event: - - pull_request + depth: 10 + steps: - name: restore-cache image: drillster/drone-volume-cache + settings: + mount: + - ./target/rust-ci-cache + - ./keys + restore: true volumes: - name: cache path: /cache - settings: - restore: true - mount: - - ./target/cargo - - ./keys + - name: init image: matterlabs/ci commands: - export ZKSYNC_HOME=`pwd` - export PATH=$ZKSYNC_HOME/bin:$PATH - - export CARGO_HOME=$ZKSYNC_HOME/target/cargo - ci-prepare-env.sh - zksync env ci - zksync yarn - zksync db-wait - zksync db-setup + - zksync dummy-prover ensure-disabled depends_on: - restore-cache + +- name: rust-checks + image: matterlabs/ci + commands: + - export ZKSYNC_HOME=`pwd` + - export PATH=$ZKSYNC_HOME/bin:$PATH + - cargo fmt -- --check + - f cargo clippy --tests --benches -- -D warnings + depends_on: + - init + +- name: rust-build + image: matterlabs/ci + commands: + - export ZKSYNC_HOME=`pwd` + - export PATH=$ZKSYNC_HOME/bin:$PATH + - f cargo build --release --all-targets + - f cargo test --release --all-targets --no-run + - f cargo test --release -p prover --no-run + - f cargo test --release -p circuit --no-run + - pushd core/storage + - f cargo test --release -p storage --features "db_test" --no-run + - popd + - sccache --show-stats + depends_on: + - init + - name: run-genesis image: matterlabs/ci commands: - export ZKSYNC_HOME=`pwd` - export PATH=$ZKSYNC_HOME/bin:$PATH - - export CARGO_HOME=$ZKSYNC_HOME/target/cargo - zksync genesis depends_on: - - init -- name: rust-tests-and-checks + - rust-build + +- name: circuit-rust-tests image: matterlabs/ci commands: - export ZKSYNC_HOME=`pwd` - export PATH=$ZKSYNC_HOME/bin:$PATH - - export CARGO_HOME=$ZKSYNC_HOME/target/cargo - - zksync dummy-prover ensure-disabled - zksync circuit-tests + depends_on: + - run-genesis + +- name: non-circuit-rust-tests + image: matterlabs/ci + commands: + - export ZKSYNC_HOME=`pwd` + - export PATH=$ZKSYNC_HOME/bin:$PATH - zksync prover-tests - zksync db-test - f cargo test --release - - cargo fmt -- --check - - f cargo clippy --tests --benches -- -D warnings depends_on: - run-genesis + - name: build-contracts image: matterlabs/ci commands: - export ZKSYNC_HOME=`pwd` - export PATH=$ZKSYNC_HOME/bin:$PATH - - export CARGO_HOME=$ZKSYNC_HOME/target/cargo - zksync build-contracts depends_on: - init + - name: redeploy-and-integration-testkit image: matterlabs/ci commands: - export ZKSYNC_HOME=`pwd` - export PATH=$ZKSYNC_HOME/bin:$PATH - - export CARGO_HOME=$ZKSYNC_HOME/target/cargo - zksync redeploy - zksync integration-testkit depends_on: - run-genesis - build-contracts + - name: contract-test image: matterlabs/ci commands: - export ZKSYNC_HOME=`pwd` - export PATH=$ZKSYNC_HOME/bin:$PATH - - export CARGO_HOME=$ZKSYNC_HOME/target/cargo - zksync test-contracts depends_on: - build-contracts + - name: rebuild-cache image: drillster/drone-volume-cache + settings: + mount: + - ./target/rust-ci-cache + - ./keys + rebuild: true volumes: - name: cache path: /cache - settings: - rebuild: true - mount: - - ./target/cargo - - ./keys depends_on: - - redeploy-and-integration-testkit - - rust-tests-and-checks + - redeploy-and-integration-testkit + - circuit-rust-tests + - non-circuit-rust-tests + +services: +- name: geth + image: matterlabs/geth:latest + +- name: postgres + image: postgres:10.4 + +volumes: +- name: cache + host: + path: /drone-cache + +trigger: + event: + - pull_request + --- kind: pipeline type: docker name: integration-simple-fullexit + +platform: + os: linux + arch: amd64 + clone: - depth: 10 -volumes: - - name: cache - host: - path: /drone-cache -services: - - name: geth - image: matterlabs/geth:latest - - name: postgres - image: postgres:10.4 -trigger: - event: - - pull_request + depth: 10 + steps: - name: restore-cache image: drillster/drone-volume-cache + settings: + mount: + - ./target/rust-ci-cache + - ./keys + restore: true volumes: - name: cache path: /cache - settings: - restore: true - mount: - - ./target/cargo - - ./keys + - name: preparations-for-integration-simple image: matterlabs/ci commands: - export ZKSYNC_HOME=`pwd` - export PATH=$ZKSYNC_HOME/bin:$PATH - - export CARGO_HOME=$ZKSYNC_HOME/target/cargo - ci-prepare-env.sh - zksync env ci - zksync yarn - zksync db-wait - zksync db-setup - - ssed -E "s/(.*constant DUMMY_VERIFIER)(.*)\;/\1 = true\;/" -i $ZKSYNC_HOME/contracts/contracts/Verifier.sol - - zksync build-contracts - - zksync db-reset - zksync genesis - - zksync redeploy + - zksync dummy-prover enable - f cargo build --release --bin server - - f cargo build --bin dummy_prover + - f cargo build --release --bin dummy_prover depends_on: - restore-cache + - name: start-server-detached image: matterlabs/ci detach: true commands: - export ZKSYNC_HOME=`pwd` - export PATH=$ZKSYNC_HOME/bin:$PATH - - export CARGO_HOME=$ZKSYNC_HOME/target/cargo - zksync server depends_on: - preparations-for-integration-simple + - name: start-prover-detached image: matterlabs/ci detach: true commands: - export ZKSYNC_HOME=`pwd` - export PATH=$ZKSYNC_HOME/bin:$PATH - - export CARGO_HOME=$ZKSYNC_HOME/target/cargo - zksync dummy-prover depends_on: - preparations-for-integration-simple + - name: integration-simple image: matterlabs/ci commands: - export ZKSYNC_HOME=`pwd` - export PATH=$ZKSYNC_HOME/bin:$PATH - - export CARGO_HOME=$ZKSYNC_HOME/target/cargo - sleep 15 - zksync integration-simple - zksync integration-full-exit depends_on: - start-server-detached - start-prover-detached + +services: +- name: geth + image: matterlabs/geth:latest + +- name: postgres + image: postgres:10.4 + +volumes: +- name: cache + host: + path: /drone-cache + +trigger: + event: + - pull_request + --- -# This pipeline publishes images and updates stage kind: pipeline type: docker name: update-stage -clone: - depth: 10 -volumes: - - name: cache - host: - path: /drone-cache - - name: docker-sock - host: - path: /var/run/docker.sock - - name: cargo-git-musl - host: - path: /tmp/cargo-git-musl - - name: cargo-registry-musl - host: - path: /tmp/cargo-registry-musl +platform: + os: linux + arch: amd64 -trigger: - target: - - stage - event: - - promote +clone: + depth: 10 steps: - name: restore-cache image: drillster/drone-volume-cache + settings: + mount: + - ./target/rust-ci-cache + - ./keys + restore: true volumes: - name: cache path: /cache - settings: - restore: true - mount: - - ./target/cargo - - ./keys - name: init image: matterlabs/ci - environment: - STAGE_ENV_BASE64: - from_secret: stage_env_base64 commands: - git checkout ${DRONE_COMMIT_SHA} - export ZKSYNC_HOME=`pwd` - export PATH=$ZKSYNC_HOME/bin:$PATH - - export CARGO_HOME=$ZKSYNC_HOME/target/cargo - echo -n $STAGE_ENV_BASE64| base64 --decode > $ZKSYNC_HOME/etc/env/stage.env - zksync env stage - zksync yarn - zksync gen-keys-if-not-present - zksync build-contracts + environment: + STAGE_ENV_BASE64: + from_secret: stage_env_base64 depends_on: - restore-cache @@ -249,9 +286,7 @@ steps: commands: - export ZKSYNC_HOME=`pwd` - export PATH=$ZKSYNC_HOME/bin:$PATH - - export CARGO_HOME=$ZKSYNC_HOME/target/cargo - zksync env stage - # too much logs and pipeline is failing - zksync yarn - zksync dist-client > /dev/null - zksync dist-explorer > /dev/null @@ -265,12 +300,12 @@ steps: - docker build -t $REPO:${DRONE_COMMIT_SHA:0:8} -f $DOCKERFILE . - docker push $REPO:${DRONE_COMMIT_SHA:0:8} environment: - USERNAME: - from_secret: docker_username + DOCKERFILE: ./docker/nginx/Dockerfile PASSWORD: from_secret: docker_password - DOCKERFILE: ./docker/nginx/Dockerfile REPO: matterlabs/nginx + USERNAME: + from_secret: docker_username volumes: - name: docker-sock path: /var/run/docker.sock @@ -279,11 +314,6 @@ steps: - name: build-rust image: ekidd/rust-musl-builder - volumes: - - name: cargo-git-musl - path: /home/rust/.cargo/git - - name: cargo-registry-musl - path: /home/rust/.cargo/registry commands: - export ZKSYNC_HOME=`pwd` - export PATH=$ZKSYNC_HOME/bin:$PATH @@ -291,22 +321,46 @@ steps: - sudo chown -R rust:rust /home/rust/.cargo/git /home/rust/.cargo/registry - sudo chown -R rust:rust ./target - f cargo build --release + volumes: + - name: cargo-git-musl + path: /home/rust/.cargo/git + - name: cargo-registry-musl + path: /home/rust/.cargo/registry depends_on: - init -- name: server-image-publish +- name: server-supervisor-image-publish image: docker + commands: + - docker login -u $USERNAME -p $PASSWORD + - docker build -t $REPO:${DRONE_COMMIT_SHA:0:8} -f $DOCKERFILE . + - docker push $REPO:${DRONE_COMMIT_SHA:0:8} environment: - USERNAME: - from_secret: docker_username + DOCKERFILE: ./docker/server_supervisor/Dockerfile PASSWORD: from_secret: docker_password - DOCKERFILE: ./docker/server/Dockerfile - REPO: matterlabs/server + REPO: matterlabs/server_supervisor + USERNAME: + from_secret: docker_username + volumes: + - name: docker-sock + path: /var/run/docker.sock + depends_on: + - build-rust + +- name: server-image-publish + image: docker commands: - docker login -u $USERNAME -p $PASSWORD - docker build -t $REPO:${DRONE_COMMIT_SHA:0:8} -f $DOCKERFILE . - docker push $REPO:${DRONE_COMMIT_SHA:0:8} + environment: + DOCKERFILE: ./docker/server/Dockerfile + PASSWORD: + from_secret: docker_password + REPO: matterlabs/server + USERNAME: + from_secret: docker_username volumes: - name: docker-sock path: /var/run/docker.sock @@ -315,17 +369,17 @@ steps: - name: prover-image-publish image: docker - environment: - USERNAME: - from_secret: docker_username - PASSWORD: - from_secret: docker_password - DOCKERFILE: ./docker/prover/Dockerfile - REPO: matterlabs/prover commands: - docker login -u $USERNAME -p $PASSWORD - docker build -t $REPO:${DRONE_COMMIT_SHA:0:8} -f $DOCKERFILE . - docker push $REPO:${DRONE_COMMIT_SHA:0:8} + environment: + DOCKERFILE: ./docker/prover/Dockerfile + PASSWORD: + from_secret: docker_password + REPO: matterlabs/prover + USERNAME: + from_secret: docker_username volumes: - name: docker-sock path: /var/run/docker.sock @@ -334,73 +388,105 @@ steps: - name: stage-deploy image: matterlabs/ci - environment: - KUBECONFIG_BASE64: - from_secret: stage_kubeconfig_base64 commands: - export ZKSYNC_HOME=`pwd` - export PATH=$ZKSYNC_HOME/bin:$PATH - echo -n $KUBECONFIG_BASE64 | base64 --decode > `pwd`/kubeconfig.yaml - python3 $ZKSYNC_HOME/bin/replace-env-variable.py $ZKSYNC_HOME/etc/env/stage.env KUBECONFIG=`pwd`/kubeconfig.yaml + - zksync db-migrate - zksync apply-kubeconfig - zksync restart + environment: + KUBECONFIG_BASE64: + from_secret: stage_kubeconfig_base64 depends_on: - nginx-image-publish - server-image-publish - prover-image-publish +volumes: +- name: cache + host: + path: /drone-cache +- name: docker-sock + host: + path: /var/run/docker.sock +- name: cargo-git-musl + host: + path: /tmp/cargo-git-musl +- name: cargo-registry-musl + host: + path: /tmp/cargo-registry-musl + +trigger: + event: + - promote + target: + - stage + --- -# This pipeline updates testnet rinkeby demo or ropsten demo kind: pipeline type: docker name: update-testnet -clone: - depth: 1 -volumes: - - name: docker-sock - host: - path: /var/run/docker.sock +platform: + os: linux + arch: amd64 -trigger: - target: - - testnet - event: - - promote +clone: + depth: 1 steps: - name: check out to commit image: matterlabs/ci commands: - git checkout ${DRONE_COMMIT_SHA} + - name: check-images-exist image: docker - environment: - USERNAME: - from_secret: docker_username - PASSWORD: - from_secret: docker_password commands: - docker login -u $USERNAME -p $PASSWORD - docker pull matterlabs/server:${DRONE_COMMIT_SHA:0:8} - docker pull matterlabs/prover:${DRONE_COMMIT_SHA:0:8} - docker pull matterlabs/nginx:${DRONE_COMMIT_SHA:0:8} + environment: + ENV_BASE64: + from_secret: ${ZKSYNC_ENV}_env_base64 + PASSWORD: + from_secret: docker_password + USERNAME: + from_secret: docker_username volumes: - name: docker-sock path: /var/run/docker.sock + - name: testnet-deploy image: matterlabs/ci - environment: - ENV_BASE64: - from_secret: ${ZKSYNC_ENV}_env_base64 - KUBECONFIG_BASE64: - from_secret: ${ZKSYNC_ENV}_kubeconfig_base64 commands: - export ZKSYNC_HOME=`pwd` - export PATH=$ZKSYNC_HOME/bin:$PATH - echo -n $ENV_BASE64 | base64 --decode > $ZKSYNC_HOME/etc/env/${ZKSYNC_ENV}.env - zksync env ${ZKSYNC_ENV} - echo -n $KUBECONFIG_BASE64 | base64 --decode > `pwd`/kubeconfig.yaml - - python3 $ZKSYNC_HOME/bin/replace-env-variable.py $ZKSYNC_HOME/etc/env/${ZKSYNC_ENV}z.env KUBECONFIG=`pwd`/kubeconfig.yaml + - python3 $ZKSYNC_HOME/bin/replace-env-variable.py $ZKSYNC_HOME/etc/env/${ZKSYNC_ENV}.env KUBECONFIG=`pwd`/kubeconfig.yaml + - zksync db-migrate - zksync apply-kubeconfig - zksync restart + environment: + ENV_BASE64: + from_secret: ${ZKSYNC_ENV}_env_base64 + KUBECONFIG_BASE64: + from_secret: ${ZKSYNC_ENV}_kubeconfig_base64 + +volumes: +- name: docker-sock + host: + path: /var/run/docker.sock + +trigger: + event: + - promote + target: + - testnet + +... diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index af6f165ca8..78117a0f98 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -7,7 +7,7 @@ # notify about any circuit, prover and server changes /core/circuit/ @alexander-movchan @gluk64 /core/prover/ @furkhat -/core @dvush +/core @dvush @popzxc # dev tools /bin @dvush diff --git a/Cargo.lock b/Cargo.lock index 3f0ceac02a..731e66e047 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,14 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "actix-codec" version = "0.1.2" @@ -314,6 +323,11 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "anyhow" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arc-swap" version = "0.4.4" @@ -337,6 +351,18 @@ name = "arrayvec" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "async-compression" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "atty" version = "0.2.14" @@ -408,6 +434,11 @@ dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base-x" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "base64" version = "0.9.3" @@ -481,6 +512,15 @@ name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitvec" +version = "0.17.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "radium 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "blake2-rfc_bellman_edition" version = "0.0.1" @@ -491,6 +531,16 @@ dependencies = [ "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "blake2b_simd" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "blake2s_const" version = "0.6.0" @@ -581,6 +631,11 @@ name = "bumpalo" version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "byte-slice-cast" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byte-tools" version = "0.3.1" @@ -660,7 +715,7 @@ dependencies = [ "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "testkit 0.1.0", - "web3 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "web3 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -924,7 +979,7 @@ dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "crypto_exports 0.1.0", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -936,7 +991,7 @@ dependencies = [ "signal-hook 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "storage 0.0.1", "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "web3 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "web3 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -963,6 +1018,16 @@ dependencies = [ "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "derive_more" +version = "0.99.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "diesel" version = "1.4.3" @@ -1007,6 +1072,31 @@ dependencies = [ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dirs" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dirs-sys" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "discard" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "dtoa" version = "0.4.5" @@ -1059,26 +1149,26 @@ dependencies = [ name = "eth_client" version = "0.1.0" dependencies = [ - "ethabi 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "models 0.0.1", + "parity-crypto 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "secp256k1 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "web3 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "web3 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethabi" -version = "8.0.1" +version = "9.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1088,11 +1178,11 @@ dependencies = [ [[package]] name = "ethbloom" -version = "0.6.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1100,28 +1190,15 @@ dependencies = [ [[package]] name = "ethereum-types" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ethbloom 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethbloom 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ethsign" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "parity-crypto 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "secp256k1 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1175,14 +1252,13 @@ dependencies = [ [[package]] name = "fixed-hash" -version = "0.3.2" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1423,7 +1499,7 @@ dependencies = [ "indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1436,14 +1512,6 @@ dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "heapsize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "heck" version = "0.3.1" @@ -1606,7 +1674,7 @@ dependencies = [ "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1631,7 +1699,7 @@ dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1657,10 +1725,10 @@ dependencies = [ [[package]] name = "impl-codec" -version = "0.2.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parity-codec 3.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1679,6 +1747,14 @@ dependencies = [ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "impl-serde" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "indexmap" version = "1.3.2" @@ -1747,18 +1823,6 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "jsonrpc-core" -version = "11.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "jsonrpc-core" version = "14.0.5" @@ -1843,6 +1907,22 @@ dependencies = [ "ws 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "k8s-openapi" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde-value 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -1867,6 +1947,45 @@ dependencies = [ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "kube" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "Inflector 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "k8s-openapi 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kube-derive" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "Inflector 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "language-tags" version = "0.2.2" @@ -1913,16 +2032,8 @@ dependencies = [ "server 0.0.1", "structopt 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", "testkit 0.1.0", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "web3 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lock_api" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "web3 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2096,22 +2207,23 @@ dependencies = [ "bigdecimal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "criterion 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crypto_exports 0.1.0", - "ethabi 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethsign 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-crypto 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "secp256k1 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "web3 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "web3 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2234,6 +2346,14 @@ dependencies = [ "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ordered-float" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pairing_ce" version = "0.20.0" @@ -2244,44 +2364,39 @@ dependencies = [ "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parity-codec" -version = "3.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parity-crypto" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "block-modes 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "scrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "secp256k1 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "parking_lot" -version = "0.8.0" +name = "parity-scale-codec" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitvec 0.17.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-slice-cast 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2303,21 +2418,6 @@ dependencies = [ "parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parking_lot_core" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parking_lot_core" version = "0.6.2" @@ -2412,7 +2512,7 @@ dependencies = [ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "models 0.0.1", - "web3 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "web3 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2441,14 +2541,14 @@ dependencies = [ [[package]] name = "primitive-types" -version = "0.3.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fixed-hash 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2543,9 +2643,8 @@ dependencies = [ "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "signal-hook 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "storage 0.0.1", - "testhelper 0.1.0", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "web3 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "web3 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2591,6 +2690,11 @@ dependencies = [ "scheduled-thread-pool 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "radium" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rand" version = "0.3.23" @@ -2792,6 +2896,16 @@ name = "redox_syscall" version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "redox_users" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "regex" version = "1.3.4" @@ -2862,6 +2976,7 @@ name = "reqwest" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "async-compression 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2883,7 +2998,7 @@ dependencies = [ "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2919,6 +3034,17 @@ dependencies = [ "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rust-argon2" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rust-crypto" version = "0.2.36" @@ -2954,6 +3080,16 @@ dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustversion" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ryu" version = "1.0.2" @@ -3013,11 +3149,19 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.15.5" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "secp256k1-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "secp256k1-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3060,6 +3204,15 @@ dependencies = [ "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde-value" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde_bytes" version = "0.11.3" @@ -3110,6 +3263,17 @@ dependencies = [ "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_yaml" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "server" version = "0.0.1" @@ -3126,7 +3290,7 @@ dependencies = [ "diesel 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "eth_client 0.1.0", - "ethabi 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3148,9 +3312,24 @@ dependencies = [ "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "storage 0.0.1", - "testhelper 0.1.0", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "web3 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "web3 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "server_supervisor" +version = "0.1.0" +dependencies = [ + "anyhow 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "diesel 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "k8s-openapi 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kube 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kube-derive 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "storage 0.0.1", + "tokio 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3250,9 +3429,59 @@ dependencies = [ "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "standback" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "static_assertions" -version = "0.2.5" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "stdweb" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb-derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb-internal-macros 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb-internal-runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stdweb-derive" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stdweb-internal-macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base-x 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stdweb-internal-runtime" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3274,7 +3503,7 @@ dependencies = [ "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "testkit 0.1.0", - "web3 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "web3 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3360,17 +3589,6 @@ dependencies = [ "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "synstructure" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "synstructure" version = "0.12.3" @@ -3403,15 +3621,6 @@ dependencies = [ "winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "testhelper" -version = "0.1.0" -dependencies = [ - "crypto_exports 0.1.0", - "models 0.0.1", - "web3 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "testkit" version = "0.1.0" @@ -3420,7 +3629,7 @@ dependencies = [ "crypto_exports 0.1.0", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "eth_client 0.1.0", - "ethabi 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3430,8 +3639,8 @@ dependencies = [ "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "server 0.0.1", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "web3 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "web3 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3442,6 +3651,24 @@ dependencies = [ "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "thiserror" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "thiserror-impl 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "thread_local" version = "1.0.1" @@ -3468,6 +3695,40 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "time" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rustversion 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "standback 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stdweb 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "time-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "time-macros-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time-macros-impl" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tiny-keccak" version = "1.5.0" @@ -3476,6 +3737,14 @@ dependencies = [ "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tinytemplate" version = "1.0.3" @@ -3510,7 +3779,7 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.11" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3725,7 +3994,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3785,7 +4054,7 @@ dependencies = [ "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3873,13 +4142,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "uint" -version = "0.7.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4094,21 +4363,21 @@ dependencies = [ [[package]] name = "web3" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 11.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4116,7 +4385,7 @@ dependencies = [ "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "websocket 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4226,11 +4495,11 @@ dependencies = [ ] [[package]] -name = "zeroize" -version = "0.9.3" +name = "yaml-rust" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "zeroize_derive 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4238,18 +4507,8 @@ name = "zeroize" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "zeroize_derive" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [metadata] +"checksum Inflector 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" "checksum actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9f2c11af4b06dc935d8e1b1491dad56bfb32febc49096a91e773f8535c176453" "checksum actix-connect 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fade9bd4bb46bacde89f1e726c7a3dd230536092712f5d94d77ca57c087fca0" "checksum actix-cors 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "66e5b071c68ac8ab182e7b7717167ef29ea93e166bc26391f678f19ac08ed129" @@ -4272,10 +4531,12 @@ dependencies = [ "checksum ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6f33b5018f120946c1dcf279194f238a9f146725593ead1c08fa47ff22b0b5d3" "checksum aho-corasick 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "743ad5a418686aad3b87fd14c43badd828cf26e214a00f92a384291cf22e1811" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum anyhow 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "d9a60d744a80c30fcb657dfe2c1b22bcb3e814c1a1e3674f32bf5820b570fbff" "checksum arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" "checksum arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" +"checksum async-compression 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "be3e94dc198f93aa4107649e68fbb7f4d759398643d36f498eb72a2ee8256652" "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" @@ -4283,6 +4544,7 @@ dependencies = [ "checksum backoff 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "66483433ebf577e03c6546df761778e4cc40b00e5a1ea7ed850733ffb555d71f" "checksum backtrace 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e4036b9bf40f3cf16aba72a3d65e8a520fc4bafcdc7079aea8f848c58c5b5536" "checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" +"checksum base-x 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" @@ -4292,7 +4554,9 @@ dependencies = [ "checksum bit-vec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a4523a10839ffae575fb08aa3423026c8cb4687eef43952afb956229d4f246f7" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum bitvec 0.17.4 (registry+https://github.com/rust-lang/crates.io-index)" = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c" "checksum blake2-rfc_bellman_edition 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fdc60350286c7c3db13b98e91dbe5c8b6830a6821bc20af5b0c310ce94d74915" +"checksum blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" "checksum blake2s_const 0.6.0 (git+https://github.com/matter-labs/bellman?branch=plonk)" = "" "checksum blake2s_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab9e07352b829279624ceb7c64adb4f585dacdb81d35cafae81139ccd617cf44" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" @@ -4303,6 +4567,7 @@ dependencies = [ "checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" "checksum bstr 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "502ae1441a0a5adb8fbd38a5955a6416b9493e92b465de5e4a9bde6a539c2c48" "checksum bumpalo 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187" +"checksum byte-slice-cast 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" @@ -4339,26 +4604,29 @@ dependencies = [ "checksum ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7dfd2d8b4c82121dfdff120f818e09fc4380b0b7e17a742081a89b94853e87f" "checksum derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6d944ac6003ed268757ef1ee686753b57efc5fcf0ebe7b64c9fc81e7e32ff839" "checksum derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a141330240c921ec6d074a3e188a7c7ef95668bb95e7d44fa0e5778ec2a7afe" +"checksum derive_more 0.99.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2323f3f47db9a0e77ce7a300605d8d2098597fc451ed1a97bb1f6411bb550a7" "checksum diesel 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d7cc03b910de9935007861dce440881f69102aaaedfd4bc5a6f40340ca5840c" "checksum diesel_derives 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" +"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" +"checksum discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" "checksum dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" "checksum enum-as-inner 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d58266c97445680766be408285e798d3401c6d4c378ec5552e78737e681e37d" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" -"checksum ethabi 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebdeeea85a6d217b9fcc862906d7e283c047e04114165c433756baf5dce00a6c" -"checksum ethbloom 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3932e82d64d347a045208924002930dc105a138995ccdc1479d0f05f0359f17c" -"checksum ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62d1bc682337e2c5ec98930853674dd2b4bd5d0d246933a9e98e5280f7c76c5f" -"checksum ethsign 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b656fefa0b59f41b39000532c69359e927c0f1850186808ccf1586734ac3365f" +"checksum ethabi 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "965126c64662832991f5a748893577630b558e47fa94e7f35aefcd20d737cef7" +"checksum ethbloom 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cfe1c169414b709cf28aa30c74060bdb830a03a8ba473314d079ac79d80a5f" +"checksum ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba744248e3553a393143d5ebb68939fc3a4ec0c22a269682535f5ffe7fed728c" "checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" "checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum ff_ce 0.7.1 (git+https://github.com/matter-labs/ff.git?branch=playground)" = "" "checksum ff_derive_ce 0.6.0 (git+https://github.com/matter-labs/ff.git?branch=playground)" = "" -"checksum fixed-hash 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d1a683d1234507e4f3bf2736eeddf0de1dc65996dc0164d57eba0a74bcf29489" +"checksum fixed-hash 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3367952ceb191f4ab95dd5685dc163ac539e36202f9fcfd0cb22f9f9c542fefc" "checksum flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" @@ -4386,7 +4654,6 @@ dependencies = [ "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" "checksum h2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "377038bf3c89d18d6ca1431e7a5027194fbd724ca10592b9487ede5e8e144f42" "checksum hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" -"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" @@ -4406,9 +4673,10 @@ dependencies = [ "checksum hyper-tls 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3adcd308402b9553630734e9c36b77a7e48b3821251ca2493e8cd596763aafaa" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2050d823639fbeae26b2b5ba09aca8907793117324858070ade0673c49f793b" +"checksum impl-codec 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1be51a921b067b0eaca2fad532d9400041561aa922221cc65f95a85641c6bf53" "checksum impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7a72f11830b52333f36e3b09a288333888bf54380fd0ac0790a3c31ab0f3c5" "checksum impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "58e3cae7e99c7ff5a995da2cf78dd0a5383740eda71d98cf7b1910c301ac69b8" +"checksum impl-serde 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5bbe9ea9b182f0fb1cabbd61f4ff9b7b7b9197955e95a7e4c27de5055eb29ff8" "checksum indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" "checksum instant 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c346c299e3fe8ef94dc10c2c0253d858a69aac1245157a3bf4125915d528caf" "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" @@ -4417,7 +4685,6 @@ dependencies = [ "checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" "checksum js-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1cb931d43e71f560c81badb0191596562bafad2be06a3f9025b845c847c60df5" "checksum jsonrpc-client-transports 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0a9ae166c4d1f702d297cd76d4b55758ace80272ffc6dbb139fdc1bf810de40b" -"checksum jsonrpc-core 11.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97b83fdc5e0218128d0d270f2f2e7a5ea716f3240c8518a58bc89e6716ba8581" "checksum jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fe3b688648f1ef5d5072229e2d672ecb92cbff7d1c79bcf3fd5898f3f3df0970" "checksum jsonrpc-core-client 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "080dc110be17701097df238fad3c816d4a478a1899dfbcf8ec8957dd40ec7304" "checksum jsonrpc-derive 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8609af8f63b626e8e211f52441fcdb6ec54f1a446606b10d5c89ae9bf8a20058" @@ -4425,13 +4692,15 @@ dependencies = [ "checksum jsonrpc-pubsub 14.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5b31c9b90731276fdd24d896f31bb10aecf2e5151733364ae81123186643d939" "checksum jsonrpc-server-utils 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "95b7635e618a0edbbe0d2a2bbbc69874277c49383fcf6c3c0414491cfb517d22" "checksum jsonrpc-ws-server 14.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b94e5773b2ae66e0e02c80775ce6bbba6f15d5bb47c14ec36a36fcf94f8df851" +"checksum k8s-openapi 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "96affb18356fc998baa692c2185d198095ffdf6e6fff3bc9efb4927952f86851" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum kube 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "66be960d78ad587c7f89b24eb5f85a2b83da0e11d0fd7ffb000ce7bc01c52514" +"checksum kube-derive 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e94aee9e53e543a11c6f13a8b7c7dbd4aedf78eb08214570a17c7878de90c37" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" -"checksum lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed946d4529956a20f2d63ebe1b69996d5a2137c91913fe3ebbeff957f5bca7ff" "checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" @@ -4464,13 +4733,12 @@ dependencies = [ "checksum openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)" = "973293749822d7dd6370d6da1e523b0d1db19f06c459134c658b2a4261378b52" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)" = "1024c0a59774200a555087a6da3f253a9095a5f344e353b212ac4c8b8e450986" +"checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518" "checksum pairing_ce 0.20.0 (git+https://github.com/matter-labs/pairing.git?branch=affine-ops)" = "" -"checksum parity-codec 3.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2b9df1283109f542d8852cd6b30e9341acc2137481eb6157d2e62af68b0afec9" -"checksum parity-crypto 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27a9c2b525c93d717a234eb220c26474f8d97b08ac50d79faeac4cb6c74bf0b9" +"checksum parity-crypto 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4015edcfb0304c3b32f6c4ad68fb8b0a14f1d7d250bd0c6b9cd312d38038000" +"checksum parity-scale-codec 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "329c8f7f4244ddb5c37c103641027a76c530e65e8e4b8240b29f81ea40508b17" "checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" -"checksum parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7767817701cce701d5585b9c4db3cdd02086398322c1d7e8bf5094a96a2ce7" "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -"checksum parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb88cb1cb3790baa6776844f968fea3be44956cf184fa1be5a03341f5491278c" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" "checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" @@ -4484,7 +4752,7 @@ dependencies = [ "checksum plotters 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "4e3bb8da247d27ae212529352020f3e5ee16e83c0c258061d27b08ab92675eeb" "checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" "checksum pq-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac25eee5a0582f45a67e837e350d784e7003bd29a5f460796772061ca49ffda" -"checksum primitive-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2288eb2a39386c4bc817974cc413afe173010dc80e470fcb1e9a35580869f024" +"checksum primitive-types 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e4336f4f5d5524fa60bcbd6fe626f9223d8142a50e7053e979acdf0da41ab975" "checksum proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" "checksum proc-macro-error 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" "checksum proc-macro-error-attr 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" @@ -4497,6 +4765,7 @@ dependencies = [ "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum r2d2 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1497e40855348e4a8a40767d8e55174bce1e445a3ac9254ad44ad468ee0485af" +"checksum radium 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" "checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" @@ -4518,6 +4787,7 @@ dependencies = [ "checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" "checksum regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" "checksum regex-automata 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" "checksum regex-syntax 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b28dfe3fe9badec5dbf0a79a9cccad2cfc2ab5484bdb3e44cbd1ae8b3ba2be06" @@ -4527,11 +4797,13 @@ dependencies = [ "checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" "checksum ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a" "checksum rlp 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3a44d5ae8afcb238af8b75640907edc6c931efcfab2c854e81ed35fa080f84cd" +"checksum rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum rustversion 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bba175698996010c4f6dce5e7f173b6eb781fce25d2cfc45e27091ce0b79f6" "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" "checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" "checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" @@ -4540,17 +4812,20 @@ dependencies = [ "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum scrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "656c79d0e90d0ab28ac86bf3c3d10bfbbac91450d3f190113b4e76d9fec3cfdd" -"checksum secp256k1 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4d311229f403d64002e9eed9964dfa5a0a0c1ac443344f7546bf48e916c6053a" +"checksum secp256k1 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2932dc07acd2066ff2e3921a4419606b220ba6cd03a9935123856cc534877056" +"checksum secp256k1-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ab2c26f0d3552a0f12e639ae8a64afc2e3db9c52fe32f5fc6c289d38519f220" "checksum security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" "checksum security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" +"checksum serde-value 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a65a7291a8a568adcae4c10a677ebcedbc6c9cec91c054dee2ce40b0e3290eb" "checksum serde_bytes 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "325a073952621257820e7a3469f55ba4726d8b28657e7e36653d1c36dc2c84ae" "checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" "checksum serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" +"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" "checksum sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" @@ -4561,7 +4836,12 @@ dependencies = [ "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" "checksum smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" "checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" -"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" +"checksum standback 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ee531c64ad0f80d289504bd32fb047f42a9e957cda584276ab96eb587e9abac3" +"checksum static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +"checksum stdweb 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" +"checksum stdweb-derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" +"checksum stdweb-internal-macros 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" +"checksum stdweb-internal-runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" "checksum stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8131256a5896cabcf5eb04f4d6dacbe1aefda854b0d9896e09cb58829ec5638c" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" @@ -4572,18 +4852,23 @@ dependencies = [ "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" "checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5" "checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" -"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +"checksum thiserror 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f0570dc61221295909abdb95c739f2e74325e14293b2026b0a7e195091ec54ae" +"checksum thiserror-impl 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "227362df41d566be41a28f64401e07a043157c21c14b9785a0d8e256f940a8fd" "checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum time 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6329a7835505d46f5f3a9a2c237f8d6bf5ca6f0015decb3698ba57fcdbb609ba" +"checksum time-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ae9b6e9f095bc105e183e3cd493d72579be3181ad4004fceb01adbe9eecab2d" +"checksum time-macros-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987cfe0537f575b5fc99909de6185f6c19c3ad8889e2275e686a873d0869ba1" "checksum tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" +"checksum tiny-keccak 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" "checksum tinytemplate 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "57a3c6667d3e65eb1bc3aed6fd14011c6cbc3a0665218ab7f5daf040b9ec371a" "checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" -"checksum tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8fdd17989496f49cdc57978c96f0c9fe5e4a58a8bddc6813c449a4624f6a030b" +"checksum tokio 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5a0dd887e37d37390c13ff8ac830f992307fe30a1fff0ab8427af67211ba28" "checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" "checksum tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" @@ -4614,7 +4899,7 @@ dependencies = [ "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" -"checksum uint 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2143cded94692b156c356508d92888acc824db5bffc0b4089732264c6fcf86d4" +"checksum uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e75a4cdd7b87b28840dba13c483b9a88ee6bbf16ba5c951ee1ecfcf723078e0d" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" @@ -4642,7 +4927,7 @@ dependencies = [ "checksum wasm-bindgen-macro-support 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "25bda4168030a6412ea8a047e27238cadf56f0e53516e1e83fec0a8b7c786f6d" "checksum wasm-bindgen-shared 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "fc9f36ad51f25b0219a3d4d13b90eb44cd075dff8b6280cca015775d7acaddd8" "checksum web-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)" = "721c6263e2c66fd44501cc5efbfa2b7dfa775d13e4ea38c46299646ed1f9c70a" -"checksum web3 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "076f34ed252d74a8521e3b013254b1a39f94a98f23aae7cfc85cda6e7b395664" +"checksum web3 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0631c83208cf420eeb2ed9b6cb2d5fc853aa76a43619ccec2a3d52d741f1261" "checksum websocket 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c9faed2bff8af2ea6b9f8b917d3d00b467583f6781fe3def174a9e33c879703" "checksum widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" @@ -4655,6 +4940,5 @@ dependencies = [ "checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" "checksum ws 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a2c47b5798ccc774ffb93ff536aec7c4275d722fd9c740c83cdd1af1f2d94" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "45af6a010d13e4cf5b54c94ba5a2b2eba5596b9e46bf5875612d332a1f2b3f86" +"checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" "checksum zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3cbac2ed2ba24cc90f5e06485ac8c7c1e5449fe8911aef4d8877218af021a5b8" -"checksum zeroize_derive 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "080616bd0e31f36095288bb0acdf1f78ef02c2fa15527d7e993f2a6c7591643e" diff --git a/Cargo.toml b/Cargo.toml index 50895ea03a..837fd6a2b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,8 +11,8 @@ members = [ "core/prover", "core/key_generator", "core/spec_test", - "core/testhelper", "core/testkit", "core/loadtest", - "core/crypto_exports" + "core/crypto_exports", + "core/server_supervisor" ] diff --git a/Makefile b/Makefile index e387528342..96243b5457 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ export CI_PIPELINE_ID ?= $(shell date +"%Y-%m-%d-%s") export SERVER_DOCKER_IMAGE ?=matterlabs/server:$(IMAGE_TAG) +export SERVER_SUPERVISOR_DOCKER_NAME ?=matterlabs/server_supervisor:$(IMAGE_TAG) export PROVER_DOCKER_IMAGE ?=matterlabs/prover:$(IMAGE_TAG) export NGINX_DOCKER_IMAGE ?= matterlabs/nginx:$(IMAGE_TAG) export GETH_DOCKER_IMAGE ?= matterlabs/geth:latest @@ -124,6 +125,9 @@ clean-target: image-server: build-target @docker build -t "${SERVER_DOCKER_IMAGE}" -f ./docker/server/Dockerfile . +image-server-supervisor: build-target + @docker build -t "${SERVER_SUPERVISOR_DOCKER_NAME}" -f ./docker/server_supervisor/Dockerfile . + image-prover: build-target @docker build -t "${PROVER_DOCKER_IMAGE}" -f ./docker/prover/Dockerfile . @@ -132,6 +136,9 @@ image-rust: image-server image-prover push-image-server: docker push "${SERVER_DOCKER_IMAGE}" +push-image-server-supervisor: + docker push "${SERVER_SUPERVISOR_DOCKER_NAME}" + push-image-prover: docker push "${PROVER_DOCKER_IMAGE}" @@ -245,7 +252,7 @@ start-kube: apply-kubeconfig ifeq (dev,$(ZKSYNC_ENV)) start: image-nginx image-rust start-local else -start: apply-kubeconfig start-provers start-server start-nginx +start: apply-kubeconfig start-provers start-server-supervisor start-server start-nginx endif ifeq (dev,$(ZKSYNC_ENV)) @@ -253,7 +260,7 @@ stop: else ifeq (ci,$(ZKSYNC_ENV)) stop: else -stop: confirm_action stop-provers stop-server stop-nginx +stop: confirm_action stop-provers stop-server stop-nginx stop-server-supervisor endif restart: stop start @@ -265,7 +272,11 @@ start-nginx: @bin/kube scale deployments/$(ZKSYNC_ENV)-nginx --namespace $(ZKSYNC_ENV) --replicas=1 start-server: - @bin/kube scale deployments/$(ZKSYNC_ENV)-server --namespace $(ZKSYNC_ENV) --replicas=1 + @bin/kube scale deployments/$(ZKSYNC_ENV)-server --namespace $(ZKSYNC_ENV) --replicas=2 + +start-server-supervisor: + @bin/kube scale deployments/$(ZKSYNC_ENV)-server-supervisor --namespace $(ZKSYNC_ENV) --replicas=1 + stop-provers: @bin/provers-scale 0 @@ -273,6 +284,9 @@ stop-provers: stop-server: @bin/kube scale deployments/$(ZKSYNC_ENV)-server --namespace $(ZKSYNC_ENV) --replicas=0 +stop-server-supervisor: + @bin/kube scale deployments/$(ZKSYNC_ENV)-server-supervisor --namespace $(ZKSYNC_ENV) --replicas=0 + stop-nginx: @bin/kube scale deployments/$(ZKSYNC_ENV)-nginx --namespace $(ZKSYNC_ENV) --replicas=0 diff --git a/bin/check-environment.sh b/bin/check-environment.sh index ec9285fdb2..81d11e3021 100755 --- a/bin/check-environment.sh +++ b/bin/check-environment.sh @@ -10,7 +10,7 @@ echo Checking environment check_tool yarn check_tool node -node --version | grep "v10.*" > /dev/null || (echo "ERROR, need node version 10" && exit 1) +node --version | grep "v10.20.1" > /dev/null || (echo "ERROR, node.js version 10.20.1 is required" && exit 1) check_tool docker check_tool docker-compose check_tool envsubst diff --git a/bin/k8s-secret b/bin/k8s-secret index 2814b7eeff..718bd84f91 100755 --- a/bin/k8s-secret +++ b/bin/k8s-secret @@ -9,6 +9,6 @@ echo data: grep -v '^#' $ENV_FILE | grep -v '^$' | while read -r line; do VAR=`sed 's/=.*//' <<< $line` echo -n " $VAR: " - echo -n ${!VAR} | base64 --wrap=0 + uname -a | grep Darwin > /dev/null && echo -n ${!VAR} | base64 || echo -n ${!VAR} | base64 --wrap=0 echo done diff --git a/core/circuit/Cargo.toml b/core/circuit/Cargo.toml index 6e90df3782..55bc7ec614 100644 --- a/core/circuit/Cargo.toml +++ b/core/circuit/Cargo.toml @@ -23,4 +23,4 @@ serde_json = "1.0.0" [dev-dependencies] bigdecimal = { version = "0.1.0", features = ["serde"]} testkit = { path = "../testkit", version = "0.1.0"} -web3 = "0.8.0" +web3 = "0.10.0" diff --git a/core/circuit/src/witness/test_utils.rs b/core/circuit/src/witness/test_utils.rs index e7903a8a30..4597ef9849 100644 --- a/core/circuit/src/witness/test_utils.rs +++ b/core/circuit/src/witness/test_utils.rs @@ -30,7 +30,7 @@ pub fn test_genesis_plasma_state( .into_iter() .chain(accounts.into_iter()) .collect(); - let plasma_state = PlasmaState::new(validator_account, 1); + let plasma_state = PlasmaState::from_acc_map(validator_account, 1); let mut circuit_account_tree = CircuitAccountTree::new(models::params::account_tree_depth()); for (id, account) in plasma_state.get_accounts() { diff --git a/core/data_restore/Cargo.toml b/core/data_restore/Cargo.toml index 7ed12fecdf..173c8784d0 100755 --- a/core/data_restore/Cargo.toml +++ b/core/data_restore/Cargo.toml @@ -5,9 +5,9 @@ edition = "2018" [dependencies] bigdecimal = { version = "0.1.0", features = ["serde"]} -web3 = "0.8.0" tiny-keccak = "1.4.2" -ethabi = "8.0.0" +ethabi = "9.0.0" +web3 = "0.10.0" hex = "0.3.2" lazy_static = "1.2.0" crypto_exports = { path = "../crypto_exports", version = "0.1.0" } diff --git a/core/data_restore/src/contract_functions.rs b/core/data_restore/src/contract_functions.rs index 232732d4dd..021efbf62b 100644 --- a/core/data_restore/src/contract_functions.rs +++ b/core/data_restore/src/contract_functions.rs @@ -1,4 +1,3 @@ -extern crate ethabi; use crate::eth_tx_helpers::get_input_data_from_ethereum_transaction; use models::node::account::Account; use models::params::{INPUT_DATA_ADDRESS_BYTES_WIDTH, INPUT_DATA_ROOT_HASH_BYTES_WIDTH}; diff --git a/core/data_restore/src/data_restore_driver.rs b/core/data_restore/src/data_restore_driver.rs index ab1a6d62f9..c630e82755 100755 --- a/core/data_restore/src/data_restore_driver.rs +++ b/core/data_restore/src/data_restore_driver.rs @@ -1,15 +1,24 @@ -use crate::contract_functions::{get_genesis_account, get_total_verified_blocks}; -use crate::eth_tx_helpers::get_ethereum_transaction; -use crate::events_state::EventsState; -use crate::rollup_ops::RollupOpsBlock; -use crate::storage_interactor; -use crate::tree_state::TreeState; -use models::abi::{governance_contract, zksync_contract}; -use models::node::{AccountMap, AccountUpdate}; +// External deps +use web3::{ + contract::Contract, + types::{H160, H256}, + Transport, Web3, +}; +// Workspace deps +use models::{ + abi::{governance_contract, zksync_contract}, + node::{AccountMap, AccountUpdate}, +}; use storage::ConnectionPool; -use web3::contract::Contract; -use web3::types::{H160, H256}; -use web3::{Transport, Web3}; +// Local deps +use crate::{ + contract_functions::{get_genesis_account, get_total_verified_blocks}, + eth_tx_helpers::get_ethereum_transaction, + events_state::EventsState, + rollup_ops::RollupOpsBlock, + storage_interactor, + tree_state::TreeState, +}; /// Storage state update: /// - None - The state is updated completely last time - start from fetching the new events @@ -26,8 +35,11 @@ pub enum StorageUpdateState { /// It is actually a finite state machine, that has following states: /// - Empty - The state is new /// - None - The state is completely updated last time, driver will load state from storage and fetch new events -/// - Events - The events has been fetched and saved successfully and firstly driver will load state from storage and get new operation for last saved events -/// - Operations - The operations and events has been fetched and saved successfully and firstly driver will load state from storage and update merkle tree by last saved operations +/// - Events - The events has been fetched and saved successfully and firstly driver will load state from storage +/// and get new operation for last saved events +/// - Operations - The operations and events has been fetched and saved successfully and firstly driver will load +/// state from storage and update merkle tree by last saved operations +/// /// Driver can interact with other restoring components for their updating: /// - Events /// - Operations @@ -229,6 +241,11 @@ impl DataRestoreDriver { let total_verified_blocks = get_total_verified_blocks(&self.franklin_contract); let last_verified_block = self.tree_state.state.block_number; + + // We must update the Ethereum stats table to match the actual stored state + // to keep the `state_keeper` consistent with the `eth_sender`. + storage_interactor::update_eth_stats(&self.connection_pool); + info!( "State updated\nProcessed {:?} blocks of total {:?} verified on contract\nRoot hash: {:?}\n", last_verified_block, diff --git a/core/data_restore/src/events_state.rs b/core/data_restore/src/events_state.rs index ac9a7a50e8..d5b19ef8ac 100755 --- a/core/data_restore/src/events_state.rs +++ b/core/data_restore/src/events_state.rs @@ -146,9 +146,9 @@ impl EventsState { from_block_number_u64 + eth_blocks_step }; - let to_block_number = BlockNumber::Number(to_block_number_u64); + let to_block_number = BlockNumber::Number(to_block_number_u64.into()); - let from_block_number = BlockNumber::Number(from_block_number_u64); + let from_block_number = BlockNumber::Number(from_block_number_u64.into()); let block_logs = EventsState::get_block_logs( web3, diff --git a/core/data_restore/src/rollup_ops.rs b/core/data_restore/src/rollup_ops.rs index 77be2d1bcc..b0d98ff2aa 100755 --- a/core/data_restore/src/rollup_ops.rs +++ b/core/data_restore/src/rollup_ops.rs @@ -130,15 +130,15 @@ mod test { #[test] fn test_part_exit() { - let tx = Withdraw { - from: "7777777777777777777777777777777777777777".parse().unwrap(), - to: [9u8; 20].into(), - token: 1, - amount: BigDecimal::from(20), - fee: BigDecimal::from(10), - nonce: 2, - signature: TxSignature::default(), - }; + let tx = Withdraw::new( + "7777777777777777777777777777777777777777".parse().unwrap(), + [9u8; 20].into(), + 1, + BigDecimal::from(20), + BigDecimal::from(10), + 2, + None, + ); let op1 = FranklinOp::Withdraw(Box::new(WithdrawOp { tx, account_id: 3 })); let pub_data1 = op1.public_data(); let op2 = RollupOpsBlock::get_rollup_ops_from_data(&pub_data1) @@ -191,15 +191,15 @@ mod test { #[test] fn test_transfer_to_new() { - let tx = Transfer { - from: "7777777777777777777777777777777777777777".parse().unwrap(), - to: "8888888888888888888888888888888888888888".parse().unwrap(), - token: 1, - amount: BigDecimal::from(20), - fee: BigDecimal::from(10), - nonce: 3, - signature: TxSignature::default(), - }; + let tx = Transfer::new( + "7777777777777777777777777777777777777777".parse().unwrap(), + "8888888888888888888888888888888888888888".parse().unwrap(), + 1, + BigDecimal::from(20), + BigDecimal::from(10), + 3, + None, + ); let op1 = FranklinOp::TransferToNew(Box::new(TransferToNewOp { tx, from: 11, @@ -216,15 +216,15 @@ mod test { #[test] fn test_transfer() { - let tx = Transfer { - from: "7777777777777777777777777777777777777777".parse().unwrap(), - to: "8888888888888888888888888888888888888888".parse().unwrap(), - token: 1, - amount: BigDecimal::from(20), - fee: BigDecimal::from(10), - nonce: 3, - signature: TxSignature::default(), - }; + let tx = Transfer::new( + "7777777777777777777777777777777777777777".parse().unwrap(), + "8888888888888888888888888888888888888888".parse().unwrap(), + 1, + BigDecimal::from(20), + BigDecimal::from(10), + 3, + None, + ); let op1 = FranklinOp::Transfer(Box::new(TransferOp { tx, from: 11, diff --git a/core/data_restore/src/storage_interactor.rs b/core/data_restore/src/storage_interactor.rs index 847b17b5e5..b1e5a5b946 100755 --- a/core/data_restore/src/storage_interactor.rs +++ b/core/data_restore/src/storage_interactor.rs @@ -1,22 +1,25 @@ // Built-in deps -use std::convert::TryFrom; -use std::str::FromStr; +use std::{convert::TryFrom, str::FromStr}; // External deps use web3::types::H256; // Workspace deps -use crate::data_restore_driver::StorageUpdateState; -use crate::events::{BlockEvent, EventType}; -use crate::events_state::EventsState; -use crate::rollup_ops::RollupOpsBlock; -use models::node::block::Block; -use models::node::{AccountMap, AccountUpdate, AccountUpdates, FranklinOp}; -use models::TokenAddedEvent; -use models::{Action, EncodedProof, Operation}; +use models::{ + node::{block::Block, AccountMap, AccountUpdate, AccountUpdates, FranklinOp}, + Action, EncodedProof, Operation, TokenAddedEvent, +}; use storage::{ - chain::state::records::{NewBlockEvent, StoredBlockEvent}, - data_restore::records::{NewLastWatchedEthBlockNumber, StoredRollupOpsBlock}, + data_restore::records::{ + NewBlockEvent, NewLastWatchedEthBlockNumber, StoredBlockEvent, StoredRollupOpsBlock, + }, ConnectionPool, }; +// Local deps +use crate::{ + data_restore_driver::StorageUpdateState, + events::{BlockEvent, EventType}, + events_state::EventsState, + rollup_ops::RollupOpsBlock, +}; /// Saves genesis account state in storage /// @@ -45,7 +48,7 @@ pub fn save_genesis_tree_state( .expect("Cant update genesis state"); } -/// Updates stored tree state: saves block transactions in storage mempool, stores blocks and account updates +/// Updates stored tree state: saves block transactions in storage, stores blocks and account updates /// /// # Arguments /// @@ -202,8 +205,7 @@ pub fn get_storage_state(connection_pool: &ConnectionPool) -> StorageUpdateState let storage = connection_pool.access_storage().expect("db failed"); let storage_state_string = storage - .chain() - .state_schema() + .data_restore_schema() .load_storage_state() .expect("Cant load storage state") .storage_state; @@ -248,8 +250,7 @@ pub fn get_block_events_state_from_storage(connection_pool: &ConnectionPool) -> let storage = connection_pool.access_storage().expect("db failed"); let committed = storage - .chain() - .state_schema() + .data_restore_schema() .load_committed_events_state() .expect("Cant load committed state"); @@ -260,8 +261,7 @@ pub fn get_block_events_state_from_storage(connection_pool: &ConnectionPool) -> } let verified = storage - .chain() - .state_schema() + .data_restore_schema() .load_verified_events_state() .expect("Cant load verified state"); let mut verified_events: Vec = vec![]; @@ -322,3 +322,26 @@ pub fn get_tree_state(connection_pool: &ConnectionPool) -> (u32, AccountMap, u64 (last_block, account_map, unprocessed_prior_ops, fee_acc_id) } + +/// Updates the `eth_stats` table with the currently last available committed/verified blocks +/// data for `eth_sender` module to operate correctly. +pub fn update_eth_stats(connection_pool: &ConnectionPool) { + let storage = connection_pool.access_storage().expect("db failed"); + + let last_committed_block = storage + .chain() + .block_schema() + .get_last_committed_block() + .expect("Can't get the last committed block"); + + let last_verified_block = storage + .chain() + .block_schema() + .get_last_verified_block() + .expect("Can't get the last verified block"); + + storage + .data_restore_schema() + .initialize_eth_stats(last_committed_block, last_verified_block) + .expect("Can't update the eth_stats table") +} diff --git a/core/data_restore/src/tree_state.rs b/core/data_restore/src/tree_state.rs index e6457d936c..953be7869f 100755 --- a/core/data_restore/src/tree_state.rs +++ b/core/data_restore/src/tree_state.rs @@ -52,7 +52,7 @@ impl TreeState { current_unprocessed_priority_op: u64, fee_account: AccountId, ) -> Self { - let state = PlasmaState::new(accounts, current_block); + let state = PlasmaState::from_acc_map(accounts, current_block); let last_fee_account_address = state .get_account(fee_account) .expect("Cant get fee account from tree state") @@ -392,7 +392,6 @@ mod test { use crate::rollup_ops::RollupOpsBlock; use crate::tree_state::TreeState; use bigdecimal::BigDecimal; - use models::node::tx::TxSignature; use models::node::{ Deposit, DepositOp, FranklinOp, Transfer, TransferOp, TransferToNewOp, Withdraw, WithdrawOp, }; @@ -418,15 +417,15 @@ mod test { fee_account: 0, }; - let tx2 = Withdraw { - from: [7u8; 20].into(), - to: [7u8; 20].into(), - token: 1, - amount: BigDecimal::from(20), - fee: BigDecimal::from(1), - nonce: 1, - signature: TxSignature::default(), - }; + let tx2 = Withdraw::new( + [7u8; 20].into(), + [7u8; 20].into(), + 1, + BigDecimal::from(20), + BigDecimal::from(1), + 1, + None, + ); let op2 = FranklinOp::Withdraw(Box::new(WithdrawOp { tx: tx2, account_id: 0, @@ -440,15 +439,15 @@ mod test { fee_account: 0, }; - let tx3 = Transfer { - from: [7u8; 20].into(), - to: [8u8; 20].into(), - token: 1, - amount: BigDecimal::from(20), - fee: BigDecimal::from(1), - nonce: 3, - signature: TxSignature::default(), - }; + let tx3 = Transfer::new( + [7u8; 20].into(), + [8u8; 20].into(), + 1, + BigDecimal::from(20), + BigDecimal::from(1), + 3, + None, + ); let op3 = FranklinOp::TransferToNew(Box::new(TransferToNewOp { tx: tx3, from: 0, @@ -463,15 +462,15 @@ mod test { fee_account: 0, }; - let tx4 = Transfer { - from: [8u8; 20].into(), - to: [7u8; 20].into(), - token: 1, - amount: BigDecimal::from(19), - fee: BigDecimal::from(1), - nonce: 1, - signature: TxSignature::default(), - }; + let tx4 = Transfer::new( + [8u8; 20].into(), + [7u8; 20].into(), + 1, + BigDecimal::from(19), + BigDecimal::from(1), + 1, + None, + ); let op4 = FranklinOp::Transfer(Box::new(TransferOp { tx: tx4, from: 1, @@ -542,30 +541,30 @@ mod test { })); let pub_data1 = op1.public_data(); - let tx2 = Withdraw { - from: [7u8; 20].into(), - to: [9u8; 20].into(), - token: 1, - amount: BigDecimal::from(20), - fee: BigDecimal::from(1), - nonce: 1, - signature: TxSignature::default(), - }; + let tx2 = Withdraw::new( + [7u8; 20].into(), + [9u8; 20].into(), + 1, + BigDecimal::from(20), + BigDecimal::from(1), + 1, + None, + ); let op2 = FranklinOp::Withdraw(Box::new(WithdrawOp { tx: tx2, account_id: 0, })); let pub_data2 = op2.public_data(); - let tx3 = Transfer { - from: [7u8; 20].into(), - to: [8u8; 20].into(), - token: 1, - amount: BigDecimal::from(20), - fee: BigDecimal::from(1), - nonce: 3, - signature: TxSignature::default(), - }; + let tx3 = Transfer::new( + [7u8; 20].into(), + [8u8; 20].into(), + 1, + BigDecimal::from(20), + BigDecimal::from(1), + 3, + None, + ); let op3 = FranklinOp::TransferToNew(Box::new(TransferToNewOp { tx: tx3, from: 0, @@ -573,15 +572,15 @@ mod test { })); let pub_data3 = op3.public_data(); - let tx4 = Transfer { - from: [8u8; 20].into(), - to: [7u8; 20].into(), - token: 1, - amount: BigDecimal::from(19), - fee: BigDecimal::from(1), - nonce: 1, - signature: TxSignature::default(), - }; + let tx4 = Transfer::new( + [8u8; 20].into(), + [7u8; 20].into(), + 1, + BigDecimal::from(19), + BigDecimal::from(1), + 1, + None, + ); let op4 = FranklinOp::Transfer(Box::new(TransferOp { tx: tx4, from: 1, diff --git a/core/eth_client/Cargo.toml b/core/eth_client/Cargo.toml index a115adca7b..dc4a8349a3 100644 --- a/core/eth_client/Cargo.toml +++ b/core/eth_client/Cargo.toml @@ -7,11 +7,11 @@ edition = "2018" models = { path = "../models", version = "0.0.1" } serde = "1.0.90" serde_derive = "1.0.90" -ethabi = "8.0.0" -web3 = "0.8.0" +ethabi = "9.0.0" +web3 = "0.10.0" +parity-crypto = {version = "0.5.0", features = ["publickey"] } futures = { version = "0.3", features = ["compat"] } rlp = "0.4.0" tiny-keccak = "1.4.2" -secp256k1 = "0.15" log = "0.4" failure = "0.1" diff --git a/core/eth_client/src/lib.rs b/core/eth_client/src/lib.rs index 2cfdf48b7a..95355670f5 100644 --- a/core/eth_client/src/lib.rs +++ b/core/eth_client/src/lib.rs @@ -9,7 +9,7 @@ use futures::compat::Future01CompatExt; use web3::contract::tokens::Tokenize; use web3::contract::Options; use web3::types::{Address, BlockNumber, Bytes}; -use web3::types::{H160, H256, U256}; +use web3::types::{H160, H256, U256, U64}; use web3::{Error, Transport, Web3}; pub mod signer; @@ -92,7 +92,7 @@ impl ETHClient { .await } - pub async fn block_number(&self) -> Result { + pub async fn block_number(&self) -> Result { self.web3.eth().block_number().compat().await } diff --git a/core/eth_client/src/signer.rs b/core/eth_client/src/signer.rs index 7df350c72d..4bbd2efbae 100644 --- a/core/eth_client/src/signer.rs +++ b/core/eth_client/src/signer.rs @@ -1,12 +1,6 @@ -use rlp; -use secp256k1; -use tiny_keccak; - -use self::rlp::RlpStream; -use self::tiny_keccak::keccak256; -use secp256k1::key::SecretKey; -use secp256k1::Message; -use secp256k1::Secp256k1; +use parity_crypto::publickey::sign; +use rlp::RlpStream; +use tiny_keccak::keccak256; use web3::types::{H160, H256, U256}; /// Description of a Transaction, pending or in the chain. @@ -46,7 +40,7 @@ impl RawTransaction { /// Signs and returns the RLP-encoded transaction pub fn sign(&self, private_key: &H256) -> Vec { let hash = self.hash(); - let sig = ecdsa_sign(&hash, &private_key.0, self.chain_id); + let sig = ecdsa_sign(hash, &private_key, self.chain_id); let mut tx = RlpStream::new(); tx.begin_unbounded_list(); self.encode(&mut tx); @@ -57,15 +51,11 @@ impl RawTransaction { let s_start = find_first_nonzero(&sig.s); let s = &sig.s[s_start..]; tx.append(&s); - - // tx.append(&sig.r); - // tx.append(&sig.s); - tx.finalize_unbounded_list(); tx.out() } - fn hash(&self) -> Vec { + fn hash(&self) -> [u8; 32] { let mut hash = RlpStream::new(); hash.begin_unbounded_list(); self.encode(&mut hash); @@ -73,7 +63,7 @@ impl RawTransaction { hash.append(&U256::zero()); hash.append(&U256::zero()); hash.finalize_unbounded_list(); - keccak256_hash(&hash.out()) + keccak256(&hash.out()) } fn encode(&self, s: &mut RlpStream) { @@ -90,22 +80,15 @@ impl RawTransaction { } } -fn keccak256_hash(bytes: &[u8]) -> Vec { - keccak256(bytes).iter().cloned().collect() -} - -fn ecdsa_sign(hash: &[u8], private_key: &[u8], chain_id: u8) -> EcdsaSig { - let s = Secp256k1::signing_only(); - let msg = Message::from_slice(hash).unwrap(); - let key = SecretKey::from_slice(private_key).unwrap(); - let (v, sig_bytes) = s.sign_recoverable(&msg, &key).serialize_compact(); +fn ecdsa_sign(hash: [u8; 32], private_key: &H256, chain_id: u8) -> EcdsaSig { + let sig = sign(&(*private_key).into(), &hash.into()).expect("failed to sign eth message"); //debug!("V m8 {:?}", v); EcdsaSig { - v: vec![v.to_i32() as u8 + chain_id * 2 + 35], - r: sig_bytes[0..32].to_vec(), - s: sig_bytes[32..64].to_vec(), + v: vec![sig.v() as u8 + chain_id * 2 + 35], + r: sig.r().to_vec(), + s: sig.s().to_vec(), } } @@ -114,30 +97,3 @@ pub struct EcdsaSig { r: Vec, s: Vec, } - -// mod test { - -// #[test] -// fn test_signs_transaction() { -// use std::io::Read; -// use std::fs::File; -// use ethereum_types::*; -// use raw_transaction::RawTransaction; -// use serde_json; - -// #[derive(Deserialize)] -// struct Signing { -// signed: Vec, -// private_key: H256 -// } - -// let mut file = File::open("./test/test_txs.json").unwrap(); -// let mut f_string = String::new(); -// file.read_to_string(&mut f_string).unwrap(); -// let txs: Vec<(RawTransaction, Signing)> = serde_json::from_str(&f_string).unwrap(); - -// for (tx, signed) in txs.into_iter() { -// assert_eq!(signed.signed, tx.sign(&signed.private_key)); -// } -// } -// } diff --git a/core/loadtest/Cargo.toml b/core/loadtest/Cargo.toml index 1b1acb6fcc..fa72dd087f 100644 --- a/core/loadtest/Cargo.toml +++ b/core/loadtest/Cargo.toml @@ -13,7 +13,7 @@ serde = "1.0.90" serde_derive = "1.0.90" serde_json = "1.0.0" -web3 = "0.8.0" +web3 = "0.10.0" futures = { version = "0.3", features = ["compat"] } tokio = { version = "0.2", features = ["full"] } reqwest = { version = "0.10", features = ["json"] } diff --git a/core/models/Cargo.toml b/core/models/Cargo.toml index 8a9c46604f..b06f6da917 100644 --- a/core/models/Cargo.toml +++ b/core/models/Cargo.toml @@ -7,8 +7,8 @@ edition = "2018" bigdecimal = { version = "0.1.0", features = ["serde"]} crypto_exports = { path = "../crypto_exports", version = "0.1.0" } -ethabi = "8.0.0" -web3 = "0.8.0" +ethabi = "9.0.0" +web3 = "0.10.0" serde = "1.0.90" serde_derive = "1.0.90" serde_bytes = "0.11.1" @@ -21,11 +21,13 @@ hex = "0.3" failure = "0.1" log = "0.4" futures = { version = "0.3", features = ["compat"] } -ethsign = "0.7.3" tiny-keccak = "1.4.2" +parity-crypto = {version = "0.5.0", features = ["publickey"] } [dev-dependencies] criterion = "0.3.0" +secp256k1 = {version = "0.17.2", features = ["std", "recovery"] } + [[bench]] name = "criterion" diff --git a/core/models/benches/criterion/lib.rs b/core/models/benches/criterion/lib.rs index faf1e284ca..ab2982d9a9 100644 --- a/core/models/benches/criterion/lib.rs +++ b/core/models/benches/criterion/lib.rs @@ -2,8 +2,10 @@ use criterion::criterion_main; use merkle_tree::merkle_tree_benches; use primitives::primitives_benches; +use signatures::signature_benches; mod merkle_tree; mod primitives; +mod signatures; -criterion_main!(merkle_tree_benches, primitives_benches); +criterion_main!(merkle_tree_benches, primitives_benches, signature_benches); diff --git a/core/models/benches/criterion/merkle_tree/sequential_smt.rs b/core/models/benches/criterion/merkle_tree/sequential_smt.rs index 38e61d16b8..66e6fc6c43 100644 --- a/core/models/benches/criterion/merkle_tree/sequential_smt.rs +++ b/core/models/benches/criterion/merkle_tree/sequential_smt.rs @@ -26,7 +26,7 @@ fn gen_account(id: u32) -> CircuitAccount { /// Measures the time of `RealSMT` creation time. fn smt_create(b: &mut Bencher<'_>) { - let depth = models::params::account_tree_depth() as u32; + let depth = models::params::account_tree_depth(); b.iter(|| { RealSMT::new(black_box(depth)); @@ -35,7 +35,7 @@ fn smt_create(b: &mut Bencher<'_>) { /// Measures the time of insertion into an empty SMT. fn smt_insert_empty(b: &mut Bencher<'_>) { - let depth = models::params::account_tree_depth() as u32; + let depth = models::params::account_tree_depth(); // Create an empty SMT and one account in setup. let tree = RealSMT::new(depth); @@ -55,13 +55,13 @@ fn smt_insert_empty(b: &mut Bencher<'_>) { /// Measures the time of insertion into a non-empty SMT. fn smt_insert_filled(b: &mut Bencher<'_>) { - let depth = models::params::account_tree_depth() as u32; + let depth = models::params::account_tree_depth(); let accounts: Vec<_> = (0..N_ACCOUNTS).map(gen_account).collect(); // Create a tree and fill it with some accounts. let mut tree = RealSMT::new(depth); for (id, account) in accounts.into_iter().enumerate() { - tree.insert(id as u32, account.clone()) + tree.insert(id, account.clone()) } let latest_account = gen_account(N_ACCOUNTS); @@ -71,7 +71,7 @@ fn smt_insert_filled(b: &mut Bencher<'_>) { setup, |(mut tree, account)| { let id = N_ACCOUNTS; - tree.insert(black_box(id), account); + tree.insert(black_box(id as usize), account); }, BatchSize::SmallInput, ); @@ -79,13 +79,13 @@ fn smt_insert_filled(b: &mut Bencher<'_>) { /// Measures the time of obtaining a SMT root hash. fn smt_root_hash(b: &mut Bencher<'_>) { - let depth = models::params::account_tree_depth() as u32; + let depth = models::params::account_tree_depth(); let accounts: Vec<_> = (0..N_ACCOUNTS).map(gen_account).collect(); // Create a tree and fill it with some accounts. let mut tree = RealSMT::new(depth); for (id, account) in accounts.into_iter().enumerate() { - tree.insert(id as u32, account.clone()) + tree.insert(id, account.clone()) } let setup = || (tree.clone()); diff --git a/core/models/benches/criterion/signatures/mod.rs b/core/models/benches/criterion/signatures/mod.rs new file mode 100644 index 0000000000..918460adad --- /dev/null +++ b/core/models/benches/criterion/signatures/mod.rs @@ -0,0 +1,91 @@ +use criterion::{black_box, criterion_group, BatchSize, Bencher, Criterion, Throughput}; +use crypto_exports::franklin_crypto::eddsa::PrivateKey; +use crypto_exports::rand::{Rng, SeedableRng, XorShiftRng}; +use models::node::tx::{PackedEthSignature, TxSignature}; +use web3::types::H256; + +fn bench_signature_zksync_musig_verify(b: &mut Bencher<'_>) { + let mut rng = XorShiftRng::from_seed([1, 2, 3, 4]); + const WITHDRAW_TX_LEN: usize = 65; + + let pk = PrivateKey(rng.gen()); + let message = rng + .gen_iter::() + .take(WITHDRAW_TX_LEN) + .collect::>(); + + let setup = || (TxSignature::sign_musig(&pk, &message), message.clone()); + + b.iter_batched( + setup, + |(signature, msg)| { + black_box(signature.verify_musig(&msg)); + }, + BatchSize::SmallInput, + ); +} + +fn bench_signature_verify_eth_packed(b: &mut Bencher<'_>) { + let mut rng = XorShiftRng::from_seed([1, 2, 3, 4]); + const TYPICAL_ETH_SIGNATURE_LEN: usize = 150; + + let pk = H256(rng.gen()); + let message = rng + .gen_iter::() + .take(TYPICAL_ETH_SIGNATURE_LEN) + .collect::>(); + let signature = PackedEthSignature::sign(&pk, &message).unwrap(); + + let setup = || (signature.clone(), message.clone()); + + b.iter_batched( + setup, + |(signature, msg)| { + let _ = black_box(signature.signature_recover_signer(&msg)); + }, + BatchSize::SmallInput, + ); +} + +/// For reference, raw speed of optimized signature library +fn bench_signature_seckp_recover(b: &mut Bencher<'_>) { + let mut rng = XorShiftRng::from_seed([1, 2, 3, 4]); + + let message = secp256k1::Message::from_slice(&rng.gen::<[u8; 32]>()).expect("msg creation"); + let secret_key = + &secp256k1::SecretKey::from_slice(&rng.gen::<[u8; 32]>()).expect("secret key creation"); + + let secp = secp256k1::Secp256k1::new(); + let signature = secp.sign_recoverable(&message, &secret_key); + + let verify_secp = secp256k1::Secp256k1::verification_only(); + + let setup = || (&verify_secp, message, signature); + b.iter_batched( + setup, + |(secp, msg, sign)| { + let _ = black_box(secp.recover(&msg, &sign)); + }, + BatchSize::SmallInput, + ); +} + +pub fn bench_signatures(c: &mut Criterion) { + let mut group = c.benchmark_group("Signature verify"); + group.throughput(Throughput::Elements(1)); + group.bench_function( + "bench_signature_verify_zksync_musig", + bench_signature_zksync_musig_verify, + ); + group.bench_function( + "bench_signature_verify_eth_packed", + bench_signature_verify_eth_packed, + ); + group.bench_function( + "bench_signature_seckp_recover", + bench_signature_seckp_recover, + ); + group.finish(); +} + +criterion_group!(signature_benches, bench_signatures); diff --git a/core/models/src/config_options.rs b/core/models/src/config_options.rs index 7067532dae..ac66781442 100644 --- a/core/models/src/config_options.rs +++ b/core/models/src/config_options.rs @@ -78,6 +78,7 @@ impl EthSenderOptions { #[derive(Debug, Clone)] pub struct ConfigurationOptions { + pub replica_name: String, pub rest_api_server_address: SocketAddr, pub json_rpc_http_server_address: SocketAddr, pub json_rpc_ws_server_address: SocketAddr, @@ -101,6 +102,7 @@ impl ConfigurationOptions { /// Panics if any of options is missing or has inappropriate value. pub fn from_env() -> Self { Self { + replica_name: parse_env("SERVER_REPLICA_NAME"), rest_api_server_address: parse_env("REST_API_BIND"), json_rpc_http_server_address: parse_env("HTTP_RPC_API_BIND"), json_rpc_ws_server_address: parse_env("WS_API_BIND"), diff --git a/core/models/src/lib.rs b/core/models/src/lib.rs index 4fd5a9f7ed..4476808a7c 100644 --- a/core/models/src/lib.rs +++ b/core/models/src/lib.rs @@ -30,6 +30,29 @@ use serde_bytes; use std::convert::TryFrom; use web3::types::{Address, Log, U256}; +/// Converts the field element into a byte array. +pub fn fe_to_bytes(value: &F) -> Vec { + let mut buf: Vec = Vec::with_capacity(32); + value.into_repr().write_be(&mut buf).unwrap(); + + buf +} + +pub fn fe_from_bytes(value: &[u8]) -> Result { + let mut repr = F::Repr::default(); + + // `repr.as_ref()` converts `repr` to a list of `u64`. Each element has 8 bytes, + // so to obtain size in bytes, we multiply the array size with the size of `u64`. + let expected_input_size = repr.as_ref().len() * 8; + if value.len() != expected_input_size { + failure::bail!("Incorrect input size") + } + repr.read_be(value) + .map_err(|e| format_err!("Cannot parse value {:?}: {}", value, e))?; + F::from_repr(repr) + .map_err(|e| format_err!("Cannot convert into prime field value {:?}: {}", value, e)) +} + /// Returns hex representation of the field element without `0x` prefix. pub fn fe_to_hex(value: &F) -> String { let mut buf: Vec = Vec::with_capacity(32); @@ -44,10 +67,15 @@ pub fn fe_from_hex(value: &str) -> Result { value }; + // Buffer is reversed and read as little endian, since we pad it with zeros to + // match the expected length. let mut buf = hex::decode(&value) .map_err(|e| format_err!("could not decode hex: {}, reason: {}", value, e))?; buf.reverse(); let mut repr = F::Repr::default(); + + // `repr.as_ref()` converts `repr` to a list of `u64`. Each element has 8 bytes, + // so to obtain size in bytes, we multiply the array size with the size of `u64`. buf.resize(repr.as_ref().len() * 8, 0); repr.read_le(&buf[..]) .map_err(|e| format_err!("could not read {}: {}", value, e))?; @@ -179,3 +207,39 @@ impl TryFrom for TokenAddedEvent { }) } } + +#[cfg(test)] +mod tests { + use super::*; + + use crate::node::Fr; + use crypto_exports::rand::{Rand, SeedableRng, XorShiftRng}; + + /// Checks that converting FE to the hex form and back results + /// in the same FE. + #[test] + fn fe_hex_roundtrip() { + let mut rng = XorShiftRng::from_seed([1, 2, 3, 4]); + + let fr = Fr::rand(&mut rng); + + let encoded_fr = fe_to_hex(&fr); + let decoded_fr = fe_from_hex(&encoded_fr).expect("Can't decode encoded fr"); + + assert_eq!(fr, decoded_fr); + } + + /// Checks that converting FE to the bytes form and back results + /// in the same FE. + #[test] + fn fe_bytes_roundtrip() { + let mut rng = XorShiftRng::from_seed([1, 2, 3, 4]); + + let fr = Fr::rand(&mut rng); + + let encoded_fr = fe_to_bytes(&fr); + let decoded_fr = fe_from_bytes(&encoded_fr).expect("Can't decode encoded fr"); + + assert_eq!(fr, decoded_fr); + } +} diff --git a/core/models/src/merkle_tree/sequential_smt.rs b/core/models/src/merkle_tree/sequential_smt.rs index fee9d010a4..87f9933f88 100644 --- a/core/models/src/merkle_tree/sequential_smt.rs +++ b/core/models/src/merkle_tree/sequential_smt.rs @@ -9,16 +9,16 @@ use std::fmt::Debug; // Tree of depth 20 should contain 2^20 elements // [0, (2^TREE_DEPTH - 1)] -type ItemIndex = u32; +type ItemIndex = usize; // [0, TREE_DEPTH] -type Depth = u32; +type Depth = usize; // Hash index determines on what level of the tree the hash is // and kept as level (where zero is a root) and item in a level indexed from 0 -type HashIndex = (u32, u32); +type HashIndex = (usize, usize); -type ItemIndexPacked = u64; +type ItemIndexPacked = usize; trait PackToIndex { fn pack(&self) -> ItemIndexPacked; @@ -26,10 +26,10 @@ trait PackToIndex { impl PackToIndex for HashIndex { fn pack(&self) -> ItemIndexPacked { - let mut packed = 0u64; - packed += u64::from(self.0); - packed <<= 32u64; - packed += u64::from(self.1); + let mut packed = 0usize; + packed += self.0; + packed <<= 32usize; + packed += self.1; packed } @@ -65,7 +65,7 @@ where H: Hasher, { /// Returns the capacity of the tree (how many items can the tree hold). - pub fn capacity(&self) -> u32 { + pub fn capacity(&self) -> usize { 1 << self.tree_depth } diff --git a/core/models/src/merkle_tree/tests.rs b/core/models/src/merkle_tree/tests.rs index 2be26e5f34..93ea5276cb 100644 --- a/core/models/src/merkle_tree/tests.rs +++ b/core/models/src/merkle_tree/tests.rs @@ -54,13 +54,13 @@ fn cross_trees_merkle_path_comparison() { let mut par_tree = parallel_smt::SparseMerkleTree::>::new(depth); let mut seq_tree = - sequential_smt::SparseMerkleTree::>::new(depth as u32); + sequential_smt::SparseMerkleTree::>::new(depth); for (idx, item) in elements.into_iter().enumerate() { // Insert the same element in both trees and verify that the root hash is the same. let idx = idx as u32; par_tree.insert(idx, item); - seq_tree.insert(idx, item); + seq_tree.insert(idx as usize, item); assert_eq!( par_tree.root_hash(), seq_tree.root_hash(), @@ -70,7 +70,7 @@ fn cross_trees_merkle_path_comparison() { ); let par_merkle_path = par_tree.merkle_path(idx); - let seq_merkle_path = seq_tree.merkle_path(idx); + let seq_merkle_path = seq_tree.merkle_path(idx as usize); // Check that proofs are equal. assert_eq!( @@ -108,7 +108,7 @@ fn simulate_transfer_to_new_par_tree_seq_tree() { let mut par_tree = parallel_smt::SparseMerkleTree::>::new(depth); let mut seq_tree = - sequential_smt::SparseMerkleTree::>::new(depth as u32); + sequential_smt::SparseMerkleTree::>::new(depth); let from_account_id = 1; let from_account_before_bal = 5; @@ -128,9 +128,9 @@ fn simulate_transfer_to_new_par_tree_seq_tree() { let (seq_root_before, seq_audit_to_before) = { let tree = &mut seq_tree; - tree.insert(from_account_id, from_account_before_bal); + tree.insert(from_account_id as usize, from_account_before_bal); let root_before = tree.root_hash(); - let audit_to_before = tree.merkle_path(to_account_id); + let audit_to_before = tree.merkle_path(to_account_id as usize); (root_before, audit_to_before) }; diff --git a/core/models/src/node/config.rs b/core/models/src/node/config.rs index bd522d3599..83504c16d0 100644 --- a/core/models/src/node/config.rs +++ b/core/models/src/node/config.rs @@ -9,5 +9,10 @@ pub const PROVER_HEARTBEAT_INTERVAL: u64 = 5; // sec pub const PROVER_CYCLE_WAIT: u64 = 5; // sec pub const TX_MINIBATCH_CREATE_TIME: Duration = Duration::from_millis(100); pub const MAX_WITHDRAWALS_TO_COMPLETE_IN_A_CALL: u64 = 20; +/// After server replica places its into leader_election table, +/// it checks db to see who is current leader with this interval. +pub const LEADER_LOOKUP_INTERVAL: Duration = Duration::from_secs(1); +/// Interval between state updates in server replica's observer mode. +pub const OBSERVER_MODE_PULL_INTERVAL: Duration = Duration::from_secs(1); pub const DEFAULT_KEYS_PATH: &str = "keys"; diff --git a/core/models/src/node/operations.rs b/core/models/src/node/operations.rs index 5f33d9c01e..601fc57fb1 100644 --- a/core/models/src/node/operations.rs +++ b/core/models/src/node/operations.rs @@ -165,18 +165,9 @@ impl TransferToNewOp { ) .ok_or_else(|| format_err!("Cant get fee from transfer to new pubdata"))?; let nonce = 0; // It is unknown from pubdata - let signature = TxSignature::default(); // It is unknown from pubdata Ok(Self { - tx: Transfer { - from, - to, - token, - amount, - fee, - nonce, - signature, - }, + tx: Transfer::new(from, to, token, amount, fee, nonce, None), from: from_id, to: to_id, }) @@ -234,7 +225,6 @@ impl TransferOp { ) .ok_or_else(|| format_err!("Cant get fee from transfer pubdata"))?; let nonce = 0; // It is unknown from pubdata - let signature = TxSignature::default(); // It is unknown from pubdata let from_id = bytes_slice_to_uint32(&bytes[from_offset..from_offset + ACCOUNT_ID_BIT_WIDTH / 8]) .ok_or_else(|| format_err!("Cant get from account id from transfer pubdata"))?; @@ -242,15 +232,7 @@ impl TransferOp { .ok_or_else(|| format_err!("Cant get to account id from transfer pubdata"))?; Ok(Self { - tx: Transfer { - from: from_address, - to: to_address, - token, - amount, - fee, - nonce, - signature, - }, + tx: Transfer::new(from_address, to_address, token, amount, fee, nonce, None), from: from_id, to: to_id, }) @@ -311,18 +293,9 @@ impl WithdrawOp { ) .ok_or_else(|| format_err!("Cant get fee from withdraw pubdata"))?; let nonce = 0; // From pubdata it is unknown - let signature = TxSignature::default(); // From pubdata it is unknown Ok(Self { - tx: Withdraw { - from, - to, - token, - amount, - fee, - nonce, - signature, - }, + tx: Withdraw::new(from, to, token, amount, fee, nonce, None), account_id, }) } @@ -394,11 +367,7 @@ impl ChangePubKeyOp { pub fn get_eth_witness(&self) -> Vec { if let Some(eth_signature) = &self.tx.eth_signature { - let mut data = Vec::with_capacity(65); - data.extend_from_slice(ð_signature.0.r); - data.extend_from_slice(ð_signature.0.s); - data.push(eth_signature.0.v); - data + eth_signature.serialize_packed().to_vec() } else { Vec::new() } diff --git a/core/models/src/node/tx.rs b/core/models/src/node/tx.rs index 221722cc3c..1e019b9b32 100644 --- a/core/models/src/node/tx.rs +++ b/core/models/src/node/tx.rs @@ -19,8 +19,10 @@ use crate::misc::utils::format_ether; use crate::node::operations::ChangePubKeyOp; use crate::params::JUBJUB_PARAMS; use crate::primitives::{big_decimal_to_u128, pedersen_hash_tx_msg, u128_to_bigdecimal}; -use ethsign::{SecretKey, Signature as ETHSignature}; -use failure::{ensure, format_err}; +use failure::{bail, ensure, format_err}; +use parity_crypto::publickey::{ + public_to_address, recover, sign, KeyPair, Signature as ETHSignature, +}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::convert::TryInto; use std::fmt; @@ -81,6 +83,21 @@ impl<'de> Deserialize<'de> for TxHash { } } +/// Stores precomputed signature verification result to speedup tx execution +#[derive(Debug, Clone)] +enum VerifiedSignatureCache { + /// No cache scenario + NotCached, + /// Cached: None if signature is incorrect. + Cached(Option), +} + +impl Default for VerifiedSignatureCache { + fn default() -> Self { + Self::NotCached + } +} + /// Signed by user. #[derive(Debug, Clone, Serialize, Deserialize)] @@ -93,11 +110,58 @@ pub struct Transfer { pub fee: BigDecimal, pub nonce: Nonce, pub signature: TxSignature, + #[serde(skip)] + cached_signer: VerifiedSignatureCache, } impl Transfer { const TX_TYPE: u8 = 5; + /// Creates transaction from parts + /// signature is optional, because sometimes we don't know it (i.e. data_restore) + pub fn new( + from: Address, + to: Address, + token: TokenId, + amount: BigDecimal, + fee: BigDecimal, + nonce: Nonce, + signature: Option, + ) -> Self { + let mut tx = Self { + from, + to, + token, + amount, + fee, + nonce, + signature: signature.clone().unwrap_or_default(), + cached_signer: VerifiedSignatureCache::NotCached, + }; + if signature.is_some() { + tx.cached_signer = VerifiedSignatureCache::Cached(tx.verify_signature()); + } + tx + } + + /// Creates signed transaction using private key, checks for correcteness + pub fn new_signed( + from: Address, + to: Address, + token: TokenId, + amount: BigDecimal, + fee: BigDecimal, + nonce: Nonce, + private_key: &PrivateKey, + ) -> Result { + let mut tx = Self::new(from, to, token, amount, fee, nonce, None); + tx.signature = TxSignature::sign_musig(private_key, &tx.get_bytes()); + if !tx.check_correctness() { + bail!("Transfer is incorrect, check amounts"); + } + Ok(tx) + } + pub fn get_bytes(&self) -> Vec { let mut out = Vec::new(); out.extend_from_slice(&[Self::TX_TYPE]); @@ -110,19 +174,27 @@ impl Transfer { out } - pub fn check_correctness(&self) -> bool { - self.amount.is_integer() // TODO: remove after # 366 + pub fn check_correctness(&mut self) -> bool { + let mut valid = self.amount.is_integer() // TODO: remove after # 366 && self.fee.is_integer() && is_token_amount_packable(&self.amount) - && is_fee_amount_packable(&self.fee) - && self.verify_signature().is_some() + && is_fee_amount_packable(&self.fee); + if valid { + let signer = self.verify_signature(); + valid = valid && signer.is_some(); + self.cached_signer = VerifiedSignatureCache::Cached(signer); + }; + valid } pub fn verify_signature(&self) -> Option { - self.signature - .verify_musig_sha256(&self.get_bytes()) - .as_ref() - .map(PubKeyHash::from_pubkey) + if let VerifiedSignatureCache::Cached(cached_signer) = &self.cached_signer { + cached_signer.clone() + } else if let Some(pub_key) = self.signature.verify_musig_sha256(&self.get_bytes()) { + Some(PubKeyHash::from_pubkey(&pub_key)) + } else { + None + } } /// Get message that should be signed by Ethereum keys of the account for 2F authentication. @@ -151,11 +223,58 @@ pub struct Withdraw { pub fee: BigDecimal, pub nonce: Nonce, pub signature: TxSignature, + #[serde(skip)] + cached_signer: VerifiedSignatureCache, } impl Withdraw { const TX_TYPE: u8 = 3; + /// Creates transaction from parts + /// signature is optional, because sometimes we don't know it (i.e. data_restore) + pub fn new( + from: Address, + to: Address, + token: TokenId, + amount: BigDecimal, + fee: BigDecimal, + nonce: Nonce, + signature: Option, + ) -> Self { + let mut tx = Self { + from, + to, + token, + amount, + fee, + nonce, + signature: signature.clone().unwrap_or_default(), + cached_signer: VerifiedSignatureCache::NotCached, + }; + if signature.is_some() { + tx.cached_signer = VerifiedSignatureCache::Cached(tx.verify_signature()); + } + tx + } + + /// Creates signed transaction using private key, checks for correcteness + pub fn new_signed( + from: Address, + to: Address, + token: TokenId, + amount: BigDecimal, + fee: BigDecimal, + nonce: Nonce, + private_key: &PrivateKey, + ) -> Result { + let mut tx = Self::new(from, to, token, amount, fee, nonce, None); + tx.signature = TxSignature::sign_musig(private_key, &tx.get_bytes()); + if !tx.check_correctness() { + bail!("Transfer is incorrect, check amounts"); + } + Ok(tx) + } + pub fn get_bytes(&self) -> Vec { let mut out = Vec::new(); out.extend_from_slice(&[Self::TX_TYPE]); @@ -168,16 +287,24 @@ impl Withdraw { out } - pub fn check_correctness(&self) -> bool { - self.amount <= u128_to_bigdecimal(u128::max_value()) - && self.verify_signature().is_some() + pub fn check_correctness(&mut self) -> bool { + let mut valid = self.amount <= u128_to_bigdecimal(u128::max_value()) && self.amount.is_integer() // TODO: remove after # 366 && self.fee.is_integer() - && is_fee_amount_packable(&self.fee) + && is_fee_amount_packable(&self.fee); + + if valid { + let signer = self.verify_signature(); + valid = valid && signer.is_some(); + self.cached_signer = VerifiedSignatureCache::Cached(signer); + } + valid } pub fn verify_signature(&self) -> Option { - if let Some(pub_key) = self.signature.verify_musig_sha256(&self.get_bytes()) { + if let VerifiedSignatureCache::Cached(cached_signer) = &self.cached_signer { + cached_signer.clone() + } else if let Some(pub_key) = self.signature.verify_musig_sha256(&self.get_bytes()) { Some(PubKeyHash::from_pubkey(&pub_key)) } else { None @@ -336,7 +463,7 @@ impl FranklinTx { } } - pub fn check_correctness(&self) -> bool { + pub fn check_correctness(&mut self) -> bool { match self { FranklinTx::Transfer(tx) => tx.check_correctness(), FranklinTx::Withdraw(tx) => tx.check_correctness(), @@ -386,7 +513,16 @@ pub struct TxSignature { } impl TxSignature { - pub fn verify_musig_pedersen(&self, msg: &[u8]) -> Option> { + pub fn sign_musig(pk: &PrivateKey, msg: &[u8]) -> Self { + Self::sign_musig_sha256(pk, msg) + } + + pub fn verify_musig(&self, msg: &[u8]) -> Option> { + self.verify_musig_sha256(msg) + } + + #[allow(dead_code)] + fn verify_musig_pedersen(&self, msg: &[u8]) -> Option> { let hashed_msg = pedersen_hash_tx_msg(msg); let valid = self.pub_key.0.verify_musig_pedersen( &hashed_msg, @@ -401,7 +537,7 @@ impl TxSignature { } } - pub fn verify_musig_sha256(&self, msg: &[u8]) -> Option> { + fn verify_musig_sha256(&self, msg: &[u8]) -> Option> { let hashed_msg = pedersen_hash_tx_msg(msg); let valid = self.pub_key.0.verify_musig_sha256( &hashed_msg, @@ -416,7 +552,8 @@ impl TxSignature { } } - pub fn sign_musig_pedersen(pk: &PrivateKey, msg: &[u8]) -> Self { + #[allow(dead_code)] + fn sign_musig_pedersen(pk: &PrivateKey, msg: &[u8]) -> Self { let hashed_msg = pedersen_hash_tx_msg(msg); let seed = Seed::deterministic_seed(&pk, &hashed_msg); let signature = pk.musig_pedersen_sign( @@ -436,7 +573,7 @@ impl TxSignature { } } - pub fn sign_musig_sha256(pk: &PrivateKey, msg: &[u8]) -> Self { + fn sign_musig_sha256(pk: &PrivateKey, msg: &[u8]) -> Self { let hashed_msg = pedersen_hash_tx_msg(msg); let seed = Seed::deterministic_seed(&pk, &hashed_msg); let signature = pk.musig_sha256_sign( @@ -625,69 +762,64 @@ impl Serialize for EIP1271Signature { /// Struct used for working with ethereum signatures created using eth_sign (using geth, ethers.js, etc) /// message is serialized as 65 bytes long `0x` prefixed string. +/// +/// Some notes on implementation of methods of this structure: +/// +/// Ethereum signed messages expect v parameter to be 27 + recovery_id(0,1,2,3) +/// Library that we use for signature verification (written for bitcoin) expects v = recovery_id +/// +/// That is why: +/// 1) when we create this structure by deserialization of message produced by user +/// we subtract 27 from v in `ETHSignature` and store it in ETHSignature structure this way. +/// 2) When we serialize/create this structure we add 27 to v in `ETHSignature`. +/// +/// This way when we have methods that consumes &self we can be sure that ETHSignature::recover_signer works +/// And we can be sure that we are compatible with Ethereum clients. +/// #[derive(Debug, Clone, PartialEq, Eq)] -pub struct PackedEthSignature(pub ETHSignature); +pub struct PackedEthSignature(ETHSignature); impl PackedEthSignature { pub fn serialize_packed(&self) -> [u8; 65] { - let mut result = [0u8; 65]; - result[0..32].copy_from_slice(&self.0.r); - result[32..64].copy_from_slice(&self.0.s); - result[64] = self.0.v; - result + // adds 27 to v + self.0.clone().into_electrum() } pub fn deserialize_packed(bytes: &[u8]) -> Result { ensure!(bytes.len() == 65, "eth signature length should be 65 bytes"); - Ok(PackedEthSignature(ETHSignature { - r: bytes[0..32].try_into().unwrap(), - s: bytes[32..64].try_into().unwrap(), - v: bytes[64], - })) + // assumes v = recover + 27 + Ok(PackedEthSignature(ETHSignature::from_electrum(&bytes))) + } + + /// Signs message using ethereum private key, results are identical to signature created + /// using `geth`, `ethers.js`, etc. No hashing and prefixes required. + pub fn sign(private_key: &H256, msg: &[u8]) -> Result { + let secret_key = (*private_key).into(); + let signed_bytes = Self::message_to_signed_bytes(msg); + let signature = sign(&secret_key, &signed_bytes)?; + Ok(PackedEthSignature(signature)) } - fn message_to_signed_bytes(msg: &[u8]) -> Vec { + fn message_to_signed_bytes(msg: &[u8]) -> H256 { let prefix = format!("\x19Ethereum Signed Message:\n{}", msg.len()); let mut bytes = Vec::with_capacity(prefix.len() + msg.len()); bytes.extend_from_slice(prefix.as_bytes()); bytes.extend_from_slice(msg); - tiny_keccak::keccak256(&bytes).to_vec() + tiny_keccak::keccak256(&bytes).into() } /// Checks signature and returns ethereum address of the signer. /// message should be the same message that was passed to `eth.sign`(or similar) method /// as argument. No hashing and prefixes required. pub fn signature_recover_signer(&self, msg: &[u8]) -> Result { - let mut signature = self.0.clone(); - // workaround for ethsign library limitations - signature.v = signature - .v - .checked_sub(27) - .ok_or_else(|| format_err!("signature v should be 27 + recovery_id"))?; - let signed_bytes = Self::message_to_signed_bytes(msg); - let pk = signature.recover(&signed_bytes)?; - Ok(Address::from_slice(pk.address())) - } - - /// Signs message using ethereum private key, results are identical to signature created - /// using `geth`, `ethers.js`, etc. No hashing and prefixes required. - pub fn sign(private_key: &H256, msg: &[u8]) -> Result { - let secret_key = SecretKey::from_raw(private_key.as_bytes())?; let signed_bytes = Self::message_to_signed_bytes(msg); - let mut signed_message = secret_key.sign(&signed_bytes)?; - // workaround for ethsign library limitations - signed_message.v = signed_message - .v - .checked_add(27) - .ok_or_else(|| format_err!("failed to add 27 to signature v"))?; - Ok(PackedEthSignature(signed_message)) + let public_key = recover(&self.0, &signed_bytes)?; + Ok(public_to_address(&public_key)) } /// Get Ethereum address from private key, - /// TODO: refactor eth signing with utils to other module. pub fn address_from_private_key(private_key: &H256) -> Result { - let secret_key = SecretKey::from_raw(private_key.as_bytes())?; - Ok(Address::from_slice(secret_key.public().address())) + Ok(KeyPair::from_secret((*private_key).into())?.address()) } } diff --git a/core/models/src/params.rs b/core/models/src/params.rs index b37df1e4ec..7ffcd8a245 100644 --- a/core/models/src/params.rs +++ b/core/models/src/params.rs @@ -19,7 +19,9 @@ pub fn account_tree_depth() -> usize { unsafe { if ACCOUNT_TREE_DEPTH_VALUE == 0 { - let value: &'static str = env!("ACCOUNT_TREE_DEPTH"); + let value: &'static str = option_env!("ACCOUNT_TREE_DEPTH") + .expect("ACCOUNT_TREE_DEPTH variable was not set during compilation. \ + Make sure that ACCOUNT_TREE_DEPTH is set in `dev.env` file and recompile the project"); ACCOUNT_TREE_DEPTH_VALUE = usize::from_str(value).expect("account tree depth value is invalid"); let runtime_value = env::var("ACCOUNT_TREE_DEPTH").expect("ACCOUNT_TREE_DEPTH missing"); diff --git a/core/plasma/Cargo.toml b/core/plasma/Cargo.toml index e12be92e89..6a859734b1 100644 --- a/core/plasma/Cargo.toml +++ b/core/plasma/Cargo.toml @@ -14,10 +14,10 @@ bigdecimal = { version = "0.1.0", features = ["serde"]} log = "0.4" failure = "0.1" crypto_exports = { path = "../crypto_exports", version = "0.1.0" } -web3 = "0.8.0" [dev-dependencies] criterion = "0.3.0" +web3 = "0.10.0" [[bench]] name = "criterion" diff --git a/core/plasma/benches/criterion/ops.rs b/core/plasma/benches/criterion/ops.rs index e4d592cfb7..53beede294 100644 --- a/core/plasma/benches/criterion/ops.rs +++ b/core/plasma/benches/criterion/ops.rs @@ -11,7 +11,7 @@ use models::node::{ account::{Account, PubKeyHash}, priority_ops::{Deposit, FullExit}, priv_key_from_fs, - tx::{ChangePubKey, PackedEthSignature, Transfer, TxSignature, Withdraw}, + tx::{ChangePubKey, PackedEthSignature, Transfer, Withdraw}, AccountId, AccountMap, Address, BlockNumber, FranklinPriorityOp, FranklinTx, PrivateKey, TokenId, }; @@ -55,7 +55,7 @@ fn generate_state() -> (HashMap, PlasmaState) { keys.insert(account_id, (sk, eth_sk)); } - let state = PlasmaState::new(accounts, CURRENT_BLOCK); + let state = PlasmaState::from_acc_map(accounts, CURRENT_BLOCK); (keys, state) } @@ -67,18 +67,16 @@ fn apply_transfer_to_new_op(b: &mut Bencher<'_>) { let from_account = state.get_account(0).expect("Can't get the account"); - let mut transfer = Transfer { - from: from_account.address, - to: Address::random(), - token: ETH_TOKEN_ID, - amount: 10.into(), - fee: 1.into(), - nonce: 0, - signature: TxSignature::default(), - }; - - transfer.signature = TxSignature::sign_musig_sha256(&private_key, &transfer.get_bytes()); - + let transfer = Transfer::new_signed( + from_account.address, + Address::random(), + ETH_TOKEN_ID, + 10.into(), + 1.into(), + 0, + private_key, + ) + .expect("failed to sign transfer"); let transfer_tx = FranklinTx::Transfer(Box::new(transfer)); let setup = || (state.clone(), transfer_tx.clone()); @@ -102,17 +100,16 @@ fn apply_transfer_op(b: &mut Bencher<'_>) { let from_account = state.get_account(0).expect("Can't get the account"); let to_account = state.get_account(1).expect("Can't get the account"); - let mut transfer = Transfer { - from: from_account.address, - to: to_account.address, - token: ETH_TOKEN_ID, - amount: 10.into(), - fee: 1.into(), - nonce: 0, - signature: TxSignature::default(), - }; - - transfer.signature = TxSignature::sign_musig_sha256(&private_key, &transfer.get_bytes()); + let transfer = Transfer::new_signed( + from_account.address, + to_account.address, + ETH_TOKEN_ID, + 10.into(), + 1.into(), + 0, + private_key, + ) + .expect("failed to sign transfer"); let transfer_tx = FranklinTx::Transfer(Box::new(transfer)); @@ -187,17 +184,16 @@ fn apply_withdraw_op(b: &mut Bencher<'_>) { let from_account = state.get_account(0).expect("Can't get the account"); let (private_key, _) = keys.get(&0).expect("Can't key the private key"); - let mut withdraw = Withdraw { - from: from_account.address, - to: Address::random(), - token: ETH_TOKEN_ID, - amount: 10.into(), - fee: 1.into(), - nonce: 0, - signature: TxSignature::default(), - }; - - withdraw.signature = TxSignature::sign_musig_sha256(&private_key, &withdraw.get_bytes()); + let withdraw = Withdraw::new_signed( + from_account.address, + Address::random(), + ETH_TOKEN_ID, + 10.into(), + 1.into(), + 0, + private_key, + ) + .expect("failed to sign withdraw"); let withdraw_tx = FranklinTx::Withdraw(Box::new(withdraw)); diff --git a/core/plasma/src/state.rs b/core/plasma/src/state.rs index 894f78e402..3cd1fcdcd6 100644 --- a/core/plasma/src/state.rs +++ b/core/plasma/src/state.rs @@ -6,6 +6,7 @@ use models::node::operations::{ WithdrawOp, }; use models::node::tx::ChangePubKey; +use models::node::Address; use models::node::{Account, AccountTree, FranklinPriorityOp, PubKeyHash}; use models::node::{ AccountId, AccountMap, AccountUpdate, AccountUpdates, BlockNumber, Fr, TokenId, @@ -13,7 +14,6 @@ use models::node::{ use models::node::{Close, Deposit, FranklinTx, FullExit, Transfer, Withdraw}; use models::params; use std::collections::HashMap; -use web3::types::Address; #[derive(Debug)] pub struct OpSuccess { @@ -50,7 +50,7 @@ impl PlasmaState { } } - pub fn new(accounts: AccountMap, current_block: u32) -> Self { + pub fn from_acc_map(accounts: AccountMap, current_block: BlockNumber) -> Self { let mut empty = Self::empty(); empty.block_number = current_block; for (id, account) in accounts { @@ -59,6 +59,18 @@ impl PlasmaState { empty } + pub fn new( + balance_tree: AccountTree, + account_id_by_address: HashMap, + current_block: BlockNumber, + ) -> Self { + Self { + balance_tree, + block_number: current_block, + account_id_by_address, + } + } + pub fn get_accounts(&self) -> Vec<(u32, Account)> { self.balance_tree .items diff --git a/core/prover/Cargo.toml b/core/prover/Cargo.toml index 1f016ab479..5123b89581 100644 --- a/core/prover/Cargo.toml +++ b/core/prover/Cargo.toml @@ -14,7 +14,7 @@ hex = "0.3" rust-crypto = "0.2" rustc-hex = "2.0.1" -web3 = "0.8.0" +web3 = "0.10.0" signal-hook = "0.1.8" tokio = "0.1.18" futures = "0.1.28" @@ -34,6 +34,3 @@ reqwest = "0.9.22" failure = "0.1" backoff = "0.1.6" clap = "2.33.0" - -[dev-dependencies] -testhelper = { path = "../testhelper", version = "0.1.0"} diff --git a/core/server/Cargo.toml b/core/server/Cargo.toml index 17569770c6..6058a6bb25 100644 --- a/core/server/Cargo.toml +++ b/core/server/Cargo.toml @@ -14,8 +14,8 @@ circuit = { path = "../circuit", version = "0.1.1"} crypto_exports = { path = "../crypto_exports", version = "0.1.0" } hex = "0.3.2" -ethabi = "8.0.0" -web3 = "0.8.0" +ethabi = "9.0.0" +web3 = "0.10.0" serde = "1.0.90" serde_derive = "1.0.90" serde_json = "1.0.0" @@ -46,5 +46,4 @@ futures01 = { package = "futures", version = "0.1" } reqwest = "0.9.22" [dev-dependencies] -testhelper = { path = "../testhelper", version = "0.1.0"} lazy_static = "1.4" diff --git a/core/server/src/api_server/rest.rs b/core/server/src/api_server/rest.rs index 77ad4c5bf6..4dfb04b499 100644 --- a/core/server/src/api_server/rest.rs +++ b/core/server/src/api_server/rest.rs @@ -386,13 +386,13 @@ fn handle_get_block_transactions( } #[derive(Deserialize)] -struct BlockSearchQuery { +struct BlockExplorerSearchQuery { query: String, } -fn handle_block_search( +fn handle_block_explorer_search( data: web::Data, - query: web::Query, + query: web::Query, ) -> ActixResult { let storage = data.access_storage()?; let result = storage @@ -455,7 +455,7 @@ fn start_server(state: AppState, bind_to: SocketAddr) { ) .route("/blocks/{block_id}", web::get().to(handle_get_block_by_id)) .route("/blocks", web::get().to(handle_get_blocks)) - .route("/search", web::get().to(handle_block_search)), + .route("/search", web::get().to(handle_block_explorer_search)), ) // Endpoint needed for js isReachable .route( diff --git a/core/server/src/eth_watch.rs b/core/server/src/eth_watch.rs index cb717b5e7b..bf842cd7ea 100644 --- a/core/server/src/eth_watch.rs +++ b/core/server/src/eth_watch.rs @@ -205,8 +205,8 @@ impl EthWatch { // restore priority queue let prior_queue_events = self .get_priority_op_events( - BlockNumber::Number(previous_block_with_accepted_events), - BlockNumber::Number(new_block_with_accepted_events), + BlockNumber::Number(previous_block_with_accepted_events.into()), + BlockNumber::Number(new_block_with_accepted_events.into()), ) .await .expect("Failed to restore priority queue events from ETH"); @@ -220,7 +220,7 @@ impl EthWatch { let new_tokens = self .get_new_token_events( BlockNumber::Earliest, - BlockNumber::Number(new_block_with_accepted_events), + BlockNumber::Number(new_block_with_accepted_events.into()), ) .await .expect("Failed to restore token list from ETH"); @@ -242,14 +242,14 @@ impl EthWatch { let new_tokens = self .get_new_token_events( - BlockNumber::Number(previous_block_with_accepted_events), - BlockNumber::Number(new_block_with_accepted_events), + BlockNumber::Number(previous_block_with_accepted_events.into()), + BlockNumber::Number(new_block_with_accepted_events.into()), ) .await?; let priority_op_events = self .get_priority_op_events( - BlockNumber::Number(previous_block_with_accepted_events), - BlockNumber::Number(new_block_with_accepted_events), + BlockNumber::Number(previous_block_with_accepted_events.into()), + BlockNumber::Number(new_block_with_accepted_events.into()), ) .await?; diff --git a/core/server/src/leader_election.rs b/core/server/src/leader_election.rs new file mode 100644 index 0000000000..216563937a --- /dev/null +++ b/core/server/src/leader_election.rs @@ -0,0 +1,37 @@ +//! Leader election is a always live routine that continuously votes to become the leader. + +use models::node::config::LEADER_LOOKUP_INTERVAL; +use std::thread; + +/// Places itself as candidate to leader_election table and continuously looks up who is current leader. +/// Lookups happen with `LEADER_LOOKUP_INTERVAL` period. +/// Current leader is the oldest candidate in leader_election table who did not bail. +/// +/// # Panics +/// +/// Panics on failed connection to db. +pub fn keep_voting_to_be_leader( + name: String, + connection_pool: storage::ConnectionPool, +) -> Result<(), failure::Error> { + let st = connection_pool + .access_storage() + .map_err(|e| failure::format_err!("could not access storage: {}", e))?; + st.leader_election_schema() + .place_candidate(&name) + .map_err(|e| failure::format_err!("could not place candidate: {}", e))?; + log::info!("placed candidate to leader election board {}", name); + loop { + let leader = st + .leader_election_schema() + .current_leader() + .map_err(|e| failure::format_err!("could not get current leader: {}", e))?; + if let Some(leader) = leader { + if leader.name == name { + break; + } + } + thread::sleep(LEADER_LOOKUP_INTERVAL); + } + Ok(()) +} diff --git a/core/server/src/lib.rs b/core/server/src/lib.rs index b333c6f661..2bc620b2e8 100644 --- a/core/server/src/lib.rs +++ b/core/server/src/lib.rs @@ -10,7 +10,9 @@ pub mod block_proposer; pub mod committer; pub mod eth_sender; pub mod eth_watch; +pub mod leader_election; pub mod mempool; +pub mod observer_mode; pub mod prover_server; pub mod signature_checker; pub mod state_keeper; diff --git a/core/server/src/main.rs b/core/server/src/main.rs index 0dd6e580fb..9dc23883c0 100644 --- a/core/server/src/main.rs +++ b/core/server/src/main.rs @@ -6,15 +6,17 @@ use clap::{App, Arg}; // Workspace uses use futures::{channel::mpsc, executor::block_on, SinkExt, StreamExt}; use models::config_options::ConfigurationOptions; -use models::node::config::{PROVER_GONE_TIMEOUT, PROVER_PREPARE_DATA_INTERVAL}; +use models::node::config::{ + OBSERVER_MODE_PULL_INTERVAL, PROVER_GONE_TIMEOUT, PROVER_PREPARE_DATA_INTERVAL, +}; use server::api_server::start_api_server; use server::block_proposer::run_block_proposer_task; use server::committer::run_committer; -use server::eth_sender; use server::eth_watch::start_eth_watch; use server::mempool::run_mempool_task; use server::prover_server::start_prover_server; -use server::state_keeper::{start_state_keeper, PlasmaStateInitParams, PlasmaStateKeeper}; +use server::state_keeper::{start_state_keeper, PlasmaStateKeeper}; +use server::{eth_sender, leader_election, observer_mode}; use std::cell::RefCell; use std::time::Duration; use storage::ConnectionPool; @@ -26,7 +28,7 @@ fn main() { let config_opts = ConfigurationOptions::from_env(); - let cli = App::new("Franklin operator node") + let cli = App::new("zkSync operator node") .author("Matter Labs") .arg( Arg::with_name("genesis") @@ -66,6 +68,30 @@ fn main() { ); } + // Start observing the state and try to become leader. + let (stop_observer_mode_tx, stop_observer_mode_rx) = std::sync::mpsc::channel(); + let (observed_state_tx, observed_state_rx) = std::sync::mpsc::channel(); + let conn_pool_clone = connection_pool.clone(); + let jh = std::thread::Builder::new() + .name("Observer mode".to_owned()) + .spawn(move || { + let state = observer_mode::run( + conn_pool_clone.clone(), + OBSERVER_MODE_PULL_INTERVAL, + stop_observer_mode_rx, + ); + observed_state_tx.send(state).expect("unexpected failure"); + }) + .expect("failed to start observer mode"); + leader_election::keep_voting_to_be_leader( + config_opts.replica_name.clone(), + connection_pool.clone(), + ) + .expect("voting for leader fail"); + stop_observer_mode_tx.send(()).expect("unexpected failure"); + let observer_mode_final_state = observed_state_rx.recv().expect("unexpected failure"); + jh.join().unwrap(); + // spawn threads for different processes // see https://docs.google.com/drawings/d/16UeYq7cuZnpkyMWGrgDAbmlaGviN2baY1w1y745Me70/edit?usp=sharing @@ -98,7 +124,7 @@ fn main() { let (executed_tx_notify_sender, executed_tx_notify_receiver) = mpsc::channel(256); let (mempool_request_sender, mempool_request_receiver) = mpsc::channel(256); let state_keeper = PlasmaStateKeeper::new( - PlasmaStateInitParams::restore_from_db(connection_pool.clone()), + observer_mode_final_state.state_keeper_init, config_opts.operator_franklin_addr, state_keeper_req_receiver, proposed_blocks_sender, @@ -140,6 +166,8 @@ fn main() { Duration::from_secs(PROVER_GONE_TIMEOUT as u64), Duration::from_secs(PROVER_PREPARE_DATA_INTERVAL), stop_signal_sender, + observer_mode_final_state.circuit_acc_tree, + observer_mode_final_state.circuit_tree_block, ); run_mempool_task( diff --git a/core/server/src/observer_mode.rs b/core/server/src/observer_mode.rs new file mode 100644 index 0000000000..4f0fe992ae --- /dev/null +++ b/core/server/src/observer_mode.rs @@ -0,0 +1,171 @@ +//! Observer mode continuously checks the database and keeps updated state of the accounts in memory. +//! The state is then fed to other actors when server transitions to the leader mode. + +use crate::state_keeper::PlasmaStateInitParams; +use circuit::witness::change_pubkey_offchain::apply_change_pubkey_offchain_tx; +use circuit::witness::close_account::apply_close_account_tx; +use circuit::witness::deposit::apply_deposit_tx; +use circuit::witness::full_exit::apply_full_exit_tx; +use circuit::witness::transfer::apply_transfer_tx; +use circuit::witness::transfer_to_new::apply_transfer_to_new_tx; +use circuit::witness::withdraw::apply_withdraw_tx; +use log::info; +use models::circuit::account::CircuitAccount; +use models::circuit::CircuitAccountTree; +use models::node::{BlockNumber, FranklinOp}; +use std::sync::mpsc; +use std::thread; +use std::time::Duration; + +/// The state being observed during observer mode. Meant to be used later to initialize server actors. +pub struct ObservedState { + /// Used to initialize `PlasmaStateKeeper` + pub state_keeper_init: PlasmaStateInitParams, + /// Used to initialize pool of prover_server. + pub circuit_acc_tree: CircuitAccountTree, + /// Block number corresponding to the state in `circuit_acc_tree`. + pub circuit_tree_block: BlockNumber, + + storage: storage::StorageProcessor, +} + +impl ObservedState { + fn new(storage: storage::StorageProcessor) -> Self { + Self { + state_keeper_init: PlasmaStateInitParams::new(), + circuit_acc_tree: CircuitAccountTree::new(models::params::account_tree_depth()), + circuit_tree_block: 0, + storage, + } + } + + /// Init state by pulling verified and committed state from db. + fn init(&mut self) -> Result<(), failure::Error> { + self.init_circuit_tree()?; + info!("updated circuit tree to block: {}", self.circuit_tree_block); + self.state_keeper_init.load_from_db(&self.storage)?; + info!( + "updated state keeper init params to block: {}", + self.state_keeper_init.last_block_number + ); + Ok(()) + } + + fn init_circuit_tree(&mut self) -> Result<(), failure::Error> { + let (block_number, accounts) = self + .storage + .chain() + .state_schema() + .load_verified_state() + .map_err(|e| failure::format_err!("couldn't load committed state: {}", e))?; + for (account_id, account) in accounts.into_iter() { + let circuit_account = CircuitAccount::from(account.clone()); + self.circuit_acc_tree.insert(account_id, circuit_account); + } + self.circuit_tree_block = block_number; + Ok(()) + } + + /// Pulls new changes from db and update. + fn update(&mut self) -> Result<(), failure::Error> { + let old = self.circuit_tree_block; + self.update_circuit_account_tree()?; + if old != self.circuit_tree_block { + info!("updated circuit tree to block: {}", self.circuit_tree_block); + } + let old = self.state_keeper_init.last_block_number; + self.state_keeper_init.load_state_diff(&self.storage)?; + if old != self.state_keeper_init.last_block_number { + info!( + "updated state keeper init params to block: {}", + self.state_keeper_init.last_block_number + ); + } + Ok(()) + } + + fn update_circuit_account_tree(&mut self) -> Result<(), failure::Error> { + let block_number = self + .storage + .chain() + .block_schema() + .get_last_verified_block() + .map_err(|e| failure::format_err!("failed to get last committed block: {}", e))?; + + for bn in self.circuit_tree_block..block_number { + let ops = self + .storage + .chain() + .block_schema() + .get_block_operations(bn + 1) + .map_err(|e| failure::format_err!("failed to get block operations {}", e))?; + self.apply(ops); + } + self.circuit_tree_block = block_number; + Ok(()) + } + + fn apply(&mut self, ops: Vec) { + for op in ops { + match op { + FranklinOp::Deposit(deposit) => { + apply_deposit_tx(&mut self.circuit_acc_tree, &deposit); + } + FranklinOp::Transfer(transfer) => { + apply_transfer_tx(&mut self.circuit_acc_tree, &transfer); + } + FranklinOp::TransferToNew(transfer_to_new) => { + apply_transfer_to_new_tx(&mut self.circuit_acc_tree, &transfer_to_new); + } + FranklinOp::Withdraw(withdraw) => { + apply_withdraw_tx(&mut self.circuit_acc_tree, &withdraw); + } + FranklinOp::Close(close) => { + apply_close_account_tx(&mut self.circuit_acc_tree, &close); + } + FranklinOp::FullExit(full_exit_op) => { + let success = full_exit_op.withdraw_amount.is_some(); + apply_full_exit_tx(&mut self.circuit_acc_tree, &full_exit_op, success); + } + FranklinOp::ChangePubKeyOffchain(change_pkhash_op) => { + apply_change_pubkey_offchain_tx(&mut self.circuit_acc_tree, &change_pkhash_op); + } + FranklinOp::Noop(_) => {} + } + } + } +} + +/// Accumulate state from db continuously and return that state on stop signal. +/// +/// # Panics +/// Panics on failed connection to db. +pub fn run( + conn_pool: storage::ConnectionPool, + interval: Duration, + stop: mpsc::Receiver<()>, +) -> ObservedState { + info!("starting observer mode"); + let storage = conn_pool.access_storage().expect("failed to access db"); + let mut observed_state = ObservedState::new(storage); + observed_state + .init() + .expect("failed to init observed state"); + loop { + let exit = match stop.try_recv() { + Err(mpsc::TryRecvError::Empty) => false, + Err(e) => { + panic!("stop channel recv error: {}", e); + } + Ok(_) => true, + }; + thread::sleep(interval); + observed_state + .update() + .expect("failed to update observed state"); + if exit { + break; + } + } + observed_state +} diff --git a/core/server/src/prover_server.rs b/core/server/src/prover_server.rs index 98690203f3..d236a0c180 100644 --- a/core/server/src/prover_server.rs +++ b/core/server/src/prover_server.rs @@ -9,6 +9,7 @@ use actix_web::{web, App, HttpResponse, HttpServer}; use futures::channel::mpsc; use log::{error, info, trace}; // Workspace deps +use models::circuit::CircuitAccountTree; use models::config_options::ThreadPanicNotify; use models::node::BlockNumber; use prover::client; @@ -168,6 +169,8 @@ pub fn start_prover_server( prover_timeout: time::Duration, rounds_interval: time::Duration, panic_notify: mpsc::Sender, + account_tree: CircuitAccountTree, + tree_block_number: BlockNumber, ) { thread::Builder::new() .name("prover_server".to_string()) @@ -180,6 +183,8 @@ pub fn start_prover_server( connection_pool.clone(), Arc::clone(&data_pool), rounds_interval, + account_tree, + tree_block_number, ); pool_maintainer.start(panic_notify); diff --git a/core/server/src/prover_server/pool.rs b/core/server/src/prover_server/pool.rs index 2be31f9683..d4367e53b7 100644 --- a/core/server/src/prover_server/pool.rs +++ b/core/server/src/prover_server/pool.rs @@ -22,7 +22,7 @@ use circuit::witness::{ withdraw::{apply_withdraw_tx, calculate_withdraw_operations_from_witness}, }; use models::{ - circuit::{account::CircuitAccount, CircuitAccountTree}, + circuit::CircuitAccountTree, config_options::ThreadPanicNotify, node::{BlockNumber, Fr, FranklinOp}, Operation, @@ -127,7 +127,8 @@ impl ProversDataPool { /// /// The essential part of this structure is `maintain` function /// which runs forever and adds data to the externally owned -/// pool. +/// pool. It maintains its own circuit tree to generates witness. +/// Initial circuit tree is substituted in constructor. /// /// `migrate` function is private and is invoked by the /// public `start` function, which starts @@ -155,13 +156,15 @@ impl Maintainer { conn_pool: storage::ConnectionPool, data: Arc>, rounds_interval: time::Duration, + account_tree: CircuitAccountTree, + block_number: BlockNumber, ) -> Self { Self { conn_pool, data, rounds_interval, - account_tree: CircuitAccountTree::new(models::params::account_tree_depth()), - next_block_number: 0, + account_tree, + next_block_number: block_number + 1, } } @@ -226,22 +229,6 @@ impl Maintainer { // Create a storage for prepared data. let mut prepared = HashMap::new(); - if self.uninitialized() { - let min_next_block_num = queue.next_block_number(); - if let Some(block_number) = min_next_block_num { - // Initialize `next_block_number` and circuit tree. Done only once. - let storage = self - .conn_pool - .access_storage() - .expect("failed to connect to db"); - self.init_account_tree(&storage, block_number - 1)?; - self.next_block_number = block_number; - } else { - // Nothing to initialize from. - return Ok(()); - } - } - // Go through queue, take the next operation to process, and build the // prover data for it. while !queue.is_empty() { @@ -277,34 +264,6 @@ impl Maintainer { Ok(()) } - /// Initializes account tree, obtaining the state for the requested block. - fn init_account_tree( - &mut self, - storage: &storage::StorageProcessor, - new_block: u32, - ) -> Result<(), String> { - assert!( - self.uninitialized(), - "Attempt to invoke 'init_account_tree' with already initialized state", - ); - let (_, accounts) = storage - .chain() - .state_schema() - .load_committed_state(Some(new_block)) - .map_err(|e| format!("failed to load committed state: {}", e))?; - - for (k, v) in accounts.iter() { - self.account_tree - .insert(*k, CircuitAccount::from(v.clone())); - } - debug!("Prover state is initialized"); - Ok(()) - } - - fn uninitialized(&self) -> bool { - self.next_block_number == 0 - } - fn build_prover_data( &mut self, storage: &storage::StorageProcessor, diff --git a/core/server/src/signature_checker.rs b/core/server/src/signature_checker.rs index 7633f9c121..f9d64fb06f 100644 --- a/core/server/src/signature_checker.rs +++ b/core/server/src/signature_checker.rs @@ -37,8 +37,8 @@ impl VerifiedTx { ) -> Result { verify_eth_signature(&request, eth_watch_req) .await - .map(|_| verify_tx_correctness(&request.tx)) - .map(|_| Self(request.tx.clone())) + .and_then(|_| verify_tx_correctness(request.tx.clone())) + .map(Self) } /// Takes the `FranklinTx` out of the wrapper. @@ -121,12 +121,12 @@ async fn verify_eth_signature( /// Verifies the correctness of the ZKSync transaction (including the /// signature check). -fn verify_tx_correctness(tx: &FranklinTx) -> Result<(), TxAddError> { +fn verify_tx_correctness(mut tx: FranklinTx) -> Result { if !tx.check_correctness() { return Err(TxAddError::IncorrectTx); } - Ok(()) + Ok(tx) } /// Request for the signature check. diff --git a/core/server/src/state_keeper.rs b/core/server/src/state_keeper.rs index 894c767260..685e1ed07f 100644 --- a/core/server/src/state_keeper.rs +++ b/core/server/src/state_keeper.rs @@ -1,5 +1,4 @@ -use std::collections::VecDeque; -use std::time::Instant; +use std::collections::{HashMap, VecDeque}; // External uses use futures::channel::{mpsc, oneshot}; use futures::stream::StreamExt; @@ -10,10 +9,11 @@ use crate::mempool::ProposedBlock; use models::node::block::{Block, ExecutedOperations, ExecutedPriorityOp, ExecutedTx}; use models::node::tx::{FranklinTx, TxHash}; use models::node::{ - Account, AccountId, AccountMap, AccountUpdate, AccountUpdates, BlockNumber, PriorityOp, + Account, AccountId, AccountTree, AccountUpdate, AccountUpdates, BlockNumber, PriorityOp, }; use models::params::max_block_chunk_size; -use models::{ActionType, CommitRequest}; +use models::ActionType; +use models::CommitRequest; use plasma::state::{OpSuccess, PlasmaState}; use storage::ConnectionPool; use web3::types::Address; @@ -79,55 +79,110 @@ pub struct PlasmaStateKeeper { } pub struct PlasmaStateInitParams { - pub accounts: AccountMap, + pub tree: AccountTree, + pub acc_id_by_addr: HashMap, pub last_block_number: BlockNumber, pub unprocessed_priority_op: u64, } +impl Default for PlasmaStateInitParams { + fn default() -> Self { + Self::new() + } +} + impl PlasmaStateInitParams { - pub fn restore_from_db(db_pool: ConnectionPool) -> Self { - let timer = Instant::now(); + pub fn new() -> Self { + Self { + tree: AccountTree::new(models::params::account_tree_depth()), + acc_id_by_addr: HashMap::new(), + last_block_number: 0, + unprocessed_priority_op: 0, + } + } + pub fn restore_from_db(db_pool: ConnectionPool) -> Result { let storage = db_pool .access_storage() .expect("db connection failed for state restore"); - let (last_committed, accounts) = storage + let mut init_params = Self::new(); + init_params.load_from_db(&storage)?; + Ok(init_params) + } + + pub fn load_from_db( + &mut self, + storage: &storage::StorageProcessor, + ) -> Result<(), failure::Error> { + let (block_number, accounts) = storage .chain() .state_schema() .load_committed_state(None) - .expect("db failed"); - let last_verified = storage - .chain() - .block_schema() - .get_last_verified_block() - .expect("db failed"); - let unprocessed_priority_op = storage + .map_err(|e| failure::format_err!("couldn't load committed state: {}", e))?; + for (account_id, account) in accounts.into_iter() { + self.insert_account(account_id, account); + } + self.last_block_number = block_number; + self.unprocessed_priority_op = Self::unprocessed_priority_op_id(&storage, block_number)?; + Ok(()) + } + + pub fn load_state_diff( + &mut self, + storage: &storage::StorageProcessor, + ) -> Result<(), failure::Error> { + let state_diff = storage .chain() - .operations_schema() - .get_operation(last_committed, ActionType::COMMIT) - .map(|storage_op| { - storage_op - .into_op(&storage) - .expect("storage_op convert") - .block - .processed_priority_ops - .1 - }) - .unwrap_or_default(); + .state_schema() + .load_state_diff(self.last_block_number, None) + .map_err(|e| failure::format_err!("failed to load committed state: {}", e))?; + + if let Some((block_number, updates)) = state_diff { + for (id, update) in updates.into_iter() { + let updated_account = Account::apply_update(self.remove_account(id), update); + if let Some(account) = updated_account { + self.insert_account(id, account); + } + } + self.unprocessed_priority_op = + Self::unprocessed_priority_op_id(&storage, block_number)?; + self.last_block_number = block_number; + } + Ok(()) + } - info!( - "Restored committed state from db, committed: {}, verified: {}, unprocessed priority op: {}, elapsed time: {} ms", - last_committed, - last_verified, - unprocessed_priority_op, - timer.elapsed().as_millis(), - ); + pub fn insert_account(&mut self, id: u32, acc: Account) { + self.acc_id_by_addr.insert(acc.address, id); + self.tree.insert(id, acc); + } - Self { - accounts, - last_block_number: last_committed, - unprocessed_priority_op, + pub fn remove_account(&mut self, id: u32) -> Option { + if let Some(acc) = self.tree.remove(id) { + self.acc_id_by_addr.remove(&acc.address); + Some(acc) + } else { + None + } + } + + fn unprocessed_priority_op_id( + storage: &storage::StorageProcessor, + block_number: BlockNumber, + ) -> Result { + let storage_op = storage + .chain() + .operations_schema() + .get_operation(block_number, ActionType::COMMIT); + if let Some(storage_op) = storage_op { + Ok(storage_op + .into_op(&storage) + .map_err(|e| failure::format_err!("could not convert storage_op: {}", e))? + .block + .processed_priority_ops + .1) + } else { + Ok(0) } } } @@ -140,7 +195,11 @@ impl PlasmaStateKeeper { tx_for_commitments: mpsc::Sender, executed_tx_notify_sender: mpsc::Sender, ) -> Self { - let state = PlasmaState::new(initial_state.accounts, initial_state.last_block_number + 1); + let state = PlasmaState::new( + initial_state.tree, + initial_state.acc_id_by_addr, + initial_state.last_block_number + 1, + ); let (fee_account_id, _) = state .get_account_by_address(&fee_account_address) @@ -194,7 +253,7 @@ impl PlasmaStateKeeper { .state_schema() .apply_state_update(0) .expect("db fail"); - let state = PlasmaState::new(accounts, last_committed + 1); + let state = PlasmaState::from_acc_map(accounts, last_committed + 1); let root_hash = state.root_hash(); info!("Genesis block created, state: {}", state.root_hash()); println!("GENESIS_ROOT=0x{}", root_hash.to_hex()); diff --git a/core/server/tests/prover_server.rs b/core/server/tests/prover_server.rs index 25b95454a6..e0d0f8c054 100644 --- a/core/server/tests/prover_server.rs +++ b/core/server/tests/prover_server.rs @@ -7,11 +7,12 @@ use futures::channel::mpsc; // Workspace deps use circuit::witness::deposit::apply_deposit_tx; use circuit::witness::deposit::calculate_deposit_operations_from_witness; -use models::params::block_chunk_sizes; +use models::circuit::CircuitAccountTree; +use models::node::Address; +use models::params::{account_tree_depth, block_chunk_sizes}; use prover::client; use prover::ApiClient; use server::prover_server; -use testhelper::TestAccount; fn spawn_server(prover_timeout: time::Duration, rounds_interval: time::Duration) -> String { // TODO: make single server spawn for all tests @@ -19,8 +20,17 @@ fn spawn_server(prover_timeout: time::Duration, rounds_interval: time::Duration) let conn_pool = storage::ConnectionPool::new(); let addr = net::SocketAddr::from_str(bind_to).unwrap(); let (tx, _rx) = mpsc::channel(1); + let tree = CircuitAccountTree::new(account_tree_depth()); thread::spawn(move || { - prover_server::start_prover_server(conn_pool, addr, prover_timeout, rounds_interval, tx); + prover_server::start_prover_server( + conn_pool, + addr, + prover_timeout, + rounds_interval, + tx, + tree, + 0, + ); }); bind_to.to_string() } @@ -150,16 +160,13 @@ pub fn test_operation_and_wanted_prover_data( // insert account and its balance let storage = access_storage(); - let validator_test_account = TestAccount::new(); - // Fee account let mut accounts = models::node::AccountMap::default(); - let mut validator_account = models::node::Account::default(); - validator_account.address = validator_test_account.address; + let validator_account = models::node::Account::default_with_address(&Address::random()); let validator_account_id: u32 = 0; accounts.insert(validator_account_id, validator_account.clone()); - let mut state = plasma::state::PlasmaState::new(accounts, 1); + let mut state = plasma::state::PlasmaState::from_acc_map(accounts, 1); println!( "acc_number 0, acc {:?}", models::circuit::account::CircuitAccount::from(validator_account.clone()).pub_key_hash, @@ -169,11 +176,12 @@ pub fn test_operation_and_wanted_prover_data( models::circuit::account::CircuitAccount::from(validator_account.clone()), ); let initial_root = circuit_tree.root_hash(); + let initial_root2 = circuit_tree.root_hash(); let deposit_priority_op = models::node::FranklinPriorityOp::Deposit(models::node::Deposit { - from: validator_test_account.address, + from: validator_account.address, token: 0, amount: bigdecimal::BigDecimal::from(10), - to: validator_test_account.address, + to: validator_account.address, }); let mut op_success = state.execute_priority_op(deposit_priority_op.clone()); let mut fees = Vec::new(); @@ -294,7 +302,7 @@ pub fn test_operation_and_wanted_prover_data( }, prover::prover_data::ProverData { public_data_commitment, - old_root: initial_root, + old_root: initial_root2, new_root: block.new_root_hash, validator_address: models::node::Fr::from_str(&block.fee_account.to_string()).unwrap(), operations, diff --git a/core/server_supervisor/Cargo.toml b/core/server_supervisor/Cargo.toml new file mode 100644 index 0000000000..1302f042e6 --- /dev/null +++ b/core/server_supervisor/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "server_supervisor" +version = "0.1.0" +authors = ["furkhat "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +kube = "0.31.0" +kube-derive = "0.31.0" +k8s-openapi = { version = "0.7.1", default-features = false, features = ["v1_15"] } +storage = { path = "../storage", version = "0.0.1" } +log = "0.4" +env_logger = "0.6" +tokio = { version = "0.2", features = ["full"] } +futures = { version = "0.3", features = ["compat"] } +anyhow = "1.0.13" +diesel = { version = "1.4.3", features = ["postgres", "serde_json", "r2d2", "chrono"] } \ No newline at end of file diff --git a/core/server_supervisor/src/main.rs b/core/server_supervisor/src/main.rs new file mode 100644 index 0000000000..bd9eaeeff7 --- /dev/null +++ b/core/server_supervisor/src/main.rs @@ -0,0 +1,105 @@ +//! Supervisor is part of leader election procedure within server replicas. +//! It participates in regular pod lifetime and replicas rolling updates. +//! Use #1, pod lifecycle: +//! Whenever pod is deleted, it is removed from leader election by supervisor. +//! Whenever leader pod is having terminated status, it bails and next candidate becomes leader. +//! Use #2, +#[macro_use] +extern crate log; +use futures::{StreamExt, TryStreamExt}; +use k8s_openapi::api::core::v1::Pod; +use kube::{ + api::{ListParams, Meta, Resource, WatchEvent}, + runtime::Informer, + Client, Configuration, +}; +use std::env; +use storage::StorageProcessor; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + env_logger::init(); + let storage = StorageProcessor::establish_connection().expect("failed connect to db"); + let namespace = env::var("NAMESPACE").unwrap_or_else(|_| "default".into()); + let client = Client::from(Configuration::infer().await?); + // We are interested in events related to the leader pod, but watch events of all pods + // in the same namespace. This is due to limitations of the library. And to keep things simpler too. + let resource = Resource::namespaced::(&namespace); + let inf = Informer::new(client, ListParams::default(), resource); + + loop { + let mut pods = inf.poll().await?.boxed(); + + while let Some(event) = pods.try_next().await? { + handle_pod(event, &storage)?; + } + } +} + +// This function lets the app handle an event from kube +// When receives event of the leader pod with last state being terminated, bails it from election, +// thus enforces new leader. +fn handle_pod(ev: WatchEvent, storage: &StorageProcessor) -> anyhow::Result<()> { + match ev { + WatchEvent::Added(o) => { + let name = Meta::name(&o); + let containers = o + .spec + .unwrap() + .containers + .into_iter() + .map(|c| c.name) + .collect::>(); + debug!("Added Pod: {} (containers={:?})", name, containers); + } + WatchEvent::Modified(o) => { + let name = Meta::name(&o); + let owner = &Meta::meta(&o).owner_references.clone().unwrap()[0]; + let status = o.status.unwrap(); + let phase = status.phase.unwrap(); + debug!( + "Modified Pod: {} (phase={}, owner={})", + name, phase, owner.name + ); + if let Some(container_statuses) = &status.container_statuses { + if let Some(last_state) = &container_statuses[0].last_state { + if last_state.terminated != None { + bail_if_leader(&storage, name); + } + } + } + } + WatchEvent::Deleted(o) => { + let name = Meta::name(&o); + debug!("Deleted Pod: {}", name); + info!("Bailing pod because it is being deleted: {}", name); + storage + .leader_election_schema() + .bail(&name, None) + .expect("failed to bail deleted pod from election"); + } + WatchEvent::Error(e) => { + warn!("Error event: {:?}", e); + } + } + Ok(()) +} + +fn bail_if_leader(storage: &StorageProcessor, name: String) { + let current_leader = storage + .leader_election_schema() + .current_leader() + .expect("failed to get current leader"); + if let Some(leader) = current_leader { + if leader.name == name { + info!( + "Bailing leader because pod is last known to be terminated: {}", + leader.name + ); + storage + .leader_election_schema() + .bail(&leader.name, Some(leader.created_at)) + .expect("failed to bail terminated leader from election"); + } + } +} diff --git a/core/spec_test/src/main.rs b/core/spec_test/src/main.rs index d55faac09e..126e9c54b6 100644 --- a/core/spec_test/src/main.rs +++ b/core/spec_test/src/main.rs @@ -21,17 +21,10 @@ fn address(req: web::Json) -> impl Responder { web::Json(ResultAddress { address }) } -#[derive(Deserialize)] -enum SignatureType { - MusigPedersen, - MusigSha256, -} - #[derive(Deserialize)] struct SignedMessage { msg: Vec, signature: TxSignature, - variant: SignatureType, } #[derive(Serialize)] @@ -42,11 +35,10 @@ struct SignedMessageKey { fn check_signature(req: web::Json) -> impl Responder { let signed_msg = req.0; - let pk = match signed_msg.variant { - SignatureType::MusigPedersen => signed_msg.signature.verify_musig_pedersen(&signed_msg.msg), - SignatureType::MusigSha256 => signed_msg.signature.verify_musig_sha256(&signed_msg.msg), - } - .map(PackedPublicKey); + let pk = signed_msg + .signature + .verify_musig(&signed_msg.msg) + .map(PackedPublicKey); web::Json(SignedMessageKey { correct: pk.is_some(), diff --git a/core/storage/Cargo.toml b/core/storage/Cargo.toml index 5ad8db9ca2..7ac41a63c0 100644 --- a/core/storage/Cargo.toml +++ b/core/storage/Cargo.toml @@ -14,7 +14,7 @@ fnv = "1.0.6" serde = "1.0.90" serde_derive = "1.0.90" serde_json = "1.0.0" -web3 = "0.8.0" +web3 = "0.10.0" diesel = { version = "1.4.2", features = ["postgres", "serde_json", "r2d2", "chrono", "numeric"] } bigdecimal = { version = "0.1.0", features = ["serde"]} crypto_exports = { path = "../crypto_exports", version = "0.1.0" } diff --git a/core/storage/migrations/2018-12-11-084553_operations/down.sql b/core/storage/migrations/2018-12-11-084553_operations/down.sql deleted file mode 100644 index 5af5462412..0000000000 --- a/core/storage/migrations/2018-12-11-084553_operations/down.sql +++ /dev/null @@ -1,4 +0,0 @@ -DROP TABLE IF EXISTS account_updates CASCADE; -DROP TABLE IF EXISTS accounts CASCADE; -DROP TABLE IF EXISTS operations CASCADE; -DROP TABLE IF EXISTS op_config CASCADE; diff --git a/core/storage/migrations/2018-12-11-084553_operations/up.sql b/core/storage/migrations/2018-12-11-084553_operations/up.sql deleted file mode 100644 index bbdfe8bca1..0000000000 --- a/core/storage/migrations/2018-12-11-084553_operations/up.sql +++ /dev/null @@ -1,53 +0,0 @@ --- op_config table is used to keep track of nonce sequences for different sender addresses -CREATE TABLE op_config( - addr text primary key, -- sender address for ETH - next_nonce bigint -- nonce sequence holder -); -INSERT INTO op_config VALUES ('0x0', 0); -CREATE RULE noins_op_config AS ON INSERT TO op_config DO NOTHING; -CREATE RULE nodel_op_config AS ON DELETE TO op_config DO NOTHING; - -CREATE OR REPLACE FUNCTION op_config_next_nonce() RETURNS integer AS -$$ -BEGIN - UPDATE op_config SET next_nonce = next_nonce + 1; - RETURN (SELECT next_nonce - 1 from op_config); -END; -$$ LANGUAGE 'plpgsql'; - -CREATE OR REPLACE FUNCTION op_config_addr() RETURNS text AS -$$ -BEGIN - RETURN (SELECT addr from op_config); -END; -$$ LANGUAGE 'plpgsql'; - -CREATE TABLE operations ( - id bigserial primary key, - data jsonb not null, - addr text not null default op_config_addr(), - nonce bigint not null default op_config_next_nonce(), - block_number bigint not null, - action_type text not null, - tx_hash text, - created_at timestamp not null default now() -); - -CREATE INDEX operations_block_index ON operations (block_number); - -CREATE TABLE accounts ( - id bigint not null primary key, - last_block bigint not null, - data json not null -); - -CREATE INDEX accounts_block_index ON accounts (last_block); - -CREATE TABLE account_updates ( - account_id bigint not null, - block_number bigint not null, - data json not null, - PRIMARY KEY (account_id, block_number) -); - -CREATE INDEX account_updates_block_index ON account_updates (block_number); diff --git a/core/storage/migrations/2019-04-02-100645_proofs/down.sql b/core/storage/migrations/2019-04-02-100645_proofs/down.sql deleted file mode 100644 index dd86e3e6b8..0000000000 --- a/core/storage/migrations/2019-04-02-100645_proofs/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE IF EXISTS proofs CASCADE; \ No newline at end of file diff --git a/core/storage/migrations/2019-04-02-100645_proofs/up.sql b/core/storage/migrations/2019-04-02-100645_proofs/up.sql deleted file mode 100644 index ff3a081078..0000000000 --- a/core/storage/migrations/2019-04-02-100645_proofs/up.sql +++ /dev/null @@ -1,15 +0,0 @@ --- Your SQL goes here - -CREATE TABLE proofs ( - block_number bigserial primary key, - proof jsonb not null, - created_at timestamp not null default now() -); - -CREATE TABLE prover_runs ( - id serial primary key, - block_number bigint not null, - worker text, - created_at timestamp not null default now(), - updated_at timestamp not null default now() -); \ No newline at end of file diff --git a/core/storage/migrations/2019-05-02-110639_transactions/down.sql b/core/storage/migrations/2019-05-02-110639_transactions/down.sql deleted file mode 100644 index 21e736af20..0000000000 --- a/core/storage/migrations/2019-05-02-110639_transactions/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE IF EXISTS transactions CASCADE; \ No newline at end of file diff --git a/core/storage/migrations/2019-05-02-110639_transactions/up.sql b/core/storage/migrations/2019-05-02-110639_transactions/up.sql deleted file mode 100644 index 6924683cb2..0000000000 --- a/core/storage/migrations/2019-05-02-110639_transactions/up.sql +++ /dev/null @@ -1,17 +0,0 @@ -CREATE TABLE transactions ( - id serial primary key, - - tx_type text not null, - from_account bigint not null, - to_account bigint, - nonce bigint, - amount integer not null, - fee integer not null, - - block_number bigint, - state_root text, - - created_at timestamp not null default now() -); - -CREATE INDEX transactions_block_index ON transactions (block_number); diff --git a/core/storage/migrations/2019-05-08-114230_config/down.sql b/core/storage/migrations/2019-05-08-114230_config/down.sql deleted file mode 100644 index 874e86e465..0000000000 --- a/core/storage/migrations/2019-05-08-114230_config/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE IF EXISTS server_config CASCADE; diff --git a/core/storage/migrations/2019-05-08-114230_config/up.sql b/core/storage/migrations/2019-05-08-114230_config/up.sql deleted file mode 100644 index 14bc999016..0000000000 --- a/core/storage/migrations/2019-05-08-114230_config/up.sql +++ /dev/null @@ -1,8 +0,0 @@ -CREATE TABLE server_config( - -- enforce single record - id bool PRIMARY KEY NOT NULL DEFAULT true, - CONSTRAINT single_server_config CHECK (id), - - contract_addr text, - gov_contract_addr text -); diff --git a/core/storage/migrations/2019-05-16-130227_provers/down.sql b/core/storage/migrations/2019-05-16-130227_provers/down.sql deleted file mode 100644 index cabf3c70b7..0000000000 --- a/core/storage/migrations/2019-05-16-130227_provers/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE IF EXISTS provers CASCADE; diff --git a/core/storage/migrations/2019-05-16-130227_provers/up.sql b/core/storage/migrations/2019-05-16-130227_provers/up.sql deleted file mode 100644 index dbf0df9ae3..0000000000 --- a/core/storage/migrations/2019-05-16-130227_provers/up.sql +++ /dev/null @@ -1,6 +0,0 @@ -CREATE TABLE active_provers ( - id serial primary key, - worker text not null, - created_at timestamp not null default now(), - stopped_at timestamp -); diff --git a/core/storage/migrations/2019-06-24-124654_change_accounts/down.sql b/core/storage/migrations/2019-06-24-124654_change_accounts/down.sql deleted file mode 100644 index ef50158f53..0000000000 --- a/core/storage/migrations/2019-06-24-124654_change_accounts/down.sql +++ /dev/null @@ -1,29 +0,0 @@ -ALTER TABLE accounts - ADD COLUMN data json, - DROP COLUMN nonce CASCADE, - DROP COLUMN pk_x CASCADE, - DROP COLUMN pk_y CASCADE; - -DROP TABLE tokens cascade; - -drop table balances cascade; - -ALTER TABLE account_updates - add column data json, - drop column coin_id cascade, - drop column balance cascade; - -DROP TABLE account_creates cascade; - -CREATE TABLE account_updates -( - account_id bigint not null, - block_number bigint not null, - data json not null, - PRIMARY KEY (account_id, block_number) -); - -CREATE INDEX account_updates_block_index ON account_updates (block_number); - -drop table account_balance_updates cascade; -drop table account_creates cascade; diff --git a/core/storage/migrations/2019-06-24-124654_change_accounts/up.sql b/core/storage/migrations/2019-06-24-124654_change_accounts/up.sql deleted file mode 100644 index b5fd1cd83a..0000000000 --- a/core/storage/migrations/2019-06-24-124654_change_accounts/up.sql +++ /dev/null @@ -1,55 +0,0 @@ -ALTER TABLE accounts - DROP COLUMN data CASCADE, - ADD COLUMN nonce BIGINT not null, - ADD COLUMN address bytea not null; - -CREATE TABLE tokens -( - id integer not null primary key, - address text not null, - symbol text -); - --- Add ETH token -INSERT INTO tokens -values (0, '0x0000000000000000000000000000000000000000', 'ETH'); - -CREATE TABLE balances -( - account_id bigint REFERENCES accounts (id) ON UPDATE CASCADE ON DELETE CASCADE, - coin_id integer REFERENCES tokens (id) ON UPDATE CASCADE, - balance numeric not null default 0, - PRIMARY KEY (account_id, coin_id) -); - - -DROP TABLE account_updates cascade; - -create TABLE account_balance_updates -( - balance_update_id serial not null, - account_id bigint not null, - block_number bigint not null, - coin_id integer not null references tokens (id) on update cascade, - old_balance numeric not null, - new_balance numeric not null, - old_nonce bigint not null, - new_nonce bigint not null, - PRIMARY KEY (balance_update_id) -); - -CREATE TABLE account_creates -( - account_id bigint not null, - is_create bool not null, - block_number bigint not null, - address bytea not null, - nonce bigint not null, - PRIMARY KEY (account_id, block_number) -); - - -ALTER TABLE transactions - drop column nonce cascade, - add column nonce bigint not null, - add column token integer not null; diff --git a/core/storage/migrations/2019-06-25-201056_pool/down.sql b/core/storage/migrations/2019-06-25-201056_pool/down.sql deleted file mode 100644 index 25d3ea1037..0000000000 --- a/core/storage/migrations/2019-06-25-201056_pool/down.sql +++ /dev/null @@ -1,21 +0,0 @@ -drop table if exists mempool cascade; -drop table if exists executed_transactions cascade; - -CREATE TABLE transactions -( - id serial primary key, - - tx_type text not null, - from_account bigint not null, - to_account bigint, - nonce bigint, - amount integer not null, - fee integer not null, - - block_number bigint, - state_root text, - - created_at timestamp not null default now() -); - -CREATE INDEX transactions_block_index ON transactions (block_number); diff --git a/core/storage/migrations/2019-06-25-201056_pool/up.sql b/core/storage/migrations/2019-06-25-201056_pool/up.sql deleted file mode 100644 index c915f8305c..0000000000 --- a/core/storage/migrations/2019-06-25-201056_pool/up.sql +++ /dev/null @@ -1,20 +0,0 @@ -create table mempool -( - hash bytea primary key, - primary_account_address bytea not null, - nonce bigint not null, - tx jsonb not null, - created_at timestamp not null default now() -); - -create table executed_transactions -( - id serial primary key, - block_number bigint not null, - tx_hash bytea not null references mempool (hash), - operation jsonb, - success bool not null, - fail_reason text -); - -drop table if exists transactions cascade; diff --git a/core/storage/migrations/2019-07-15-173846_data_restore/down.sql b/core/storage/migrations/2019-07-15-173846_data_restore/down.sql deleted file mode 100644 index 1031582299..0000000000 --- a/core/storage/migrations/2019-07-15-173846_data_restore/down.sql +++ /dev/null @@ -1,5 +0,0 @@ --- This file should undo anything in `up.sql` -DROP TABLE IF EXISTS data_restore_last_watched_eth_block CASCADE; -DROP TABLE IF EXISTS events_state CASCADE; -DROP TABLE IF EXISTS rollup_ops CASCADE; -DROP TABLE IF EXISTS storage_state_update CASCADE; diff --git a/core/storage/migrations/2019-07-15-173846_data_restore/up.sql b/core/storage/migrations/2019-07-15-173846_data_restore/up.sql deleted file mode 100644 index 7510fd010e..0000000000 --- a/core/storage/migrations/2019-07-15-173846_data_restore/up.sql +++ /dev/null @@ -1,24 +0,0 @@ --- Your SQL goes here -CREATE TABLE data_restore_last_watched_eth_block ( - id SERIAL PRIMARY KEY, - block_number TEXT NOT NULL -); - -CREATE TABLE events_state ( - id SERIAL PRIMARY KEY, - block_type TEXT NOT NULL, - transaction_hash BYTEA NOT NULL, - block_num BIGINT NOT NULL -); - -CREATE TABLE rollup_ops ( - id SERIAL PRIMARY KEY, - block_num BIGINT NOT NULL, - operation JSONB NOT NULL, - fee_account BIGINT NOT NULL -); - -CREATE TABLE storage_state_update ( - id SERIAL PRIMARY KEY, - storage_state TEXT NOT NULL -); diff --git a/core/storage/migrations/2019-08-30-111817_operations_update/up.sql b/core/storage/migrations/2019-08-30-111817_operations_update/up.sql deleted file mode 100644 index 3e1751f15f..0000000000 --- a/core/storage/migrations/2019-08-30-111817_operations_update/up.sql +++ /dev/null @@ -1,17 +0,0 @@ -CREATE TABLE eth_operations -( - id bigserial primary key, - op_id bigserial references operations (id), - nonce bigint not null, - deadline_block bigint not null, - gas_price numeric not null, - tx_hash bytea not null, - confirmed bool not null default false, - raw_tx bytea not null -); - -ALTER TABLE operations - ADD COLUMN confirmed bool not null default false, - DROP COLUMN addr CASCADE, - DROP COLUMN nonce CASCADE, - DROP COLUMN tx_hash CASCADE diff --git a/core/storage/migrations/2019-09-20-093057_priority_ops/down.sql b/core/storage/migrations/2019-09-20-093057_priority_ops/down.sql deleted file mode 100644 index c7871a45fa..0000000000 --- a/core/storage/migrations/2019-09-20-093057_priority_ops/down.sql +++ /dev/null @@ -1 +0,0 @@ --- unimplemented \ No newline at end of file diff --git a/core/storage/migrations/2019-09-20-093057_priority_ops/up.sql b/core/storage/migrations/2019-09-20-093057_priority_ops/up.sql deleted file mode 100644 index 3c5e2e7f16..0000000000 --- a/core/storage/migrations/2019-09-20-093057_priority_ops/up.sql +++ /dev/null @@ -1,29 +0,0 @@ -create table executed_priority_operations -( - id serial primary key, - -- sidechain block info - block_number bigint not null, - block_index int not null, - -- operation data - operation jsonb not null, - -- operation metadata - priority_op_serialid bigint not null, - deadline_block bigint not null, - eth_fee numeric not null -); - - -ALTER TABLE executed_transactions - ADD COLUMN block_index int; - -ALTER TABLE operations - DROP COLUMN data; - -create table blocks -( - number bigint primary key, - root_hash text not null, - fee_account_id bigint not null, - unprocessed_prior_op_before bigint not null, - unprocessed_prior_op_after bigint not null -); diff --git a/core/storage/migrations/2019-10-09-153023_add_tablefunc/down.sql b/core/storage/migrations/2019-10-09-153023_add_tablefunc/down.sql deleted file mode 100644 index 8245c74615..0000000000 --- a/core/storage/migrations/2019-10-09-153023_add_tablefunc/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP EXTENSION tablefunc; diff --git a/core/storage/migrations/2019-10-09-153023_add_tablefunc/up.sql b/core/storage/migrations/2019-10-09-153023_add_tablefunc/up.sql deleted file mode 100644 index 189aeb5280..0000000000 --- a/core/storage/migrations/2019-10-09-153023_add_tablefunc/up.sql +++ /dev/null @@ -1,2 +0,0 @@ --- tablefunc enables crosstab (pivot) -CREATE EXTENSION IF NOT EXISTS tablefunc; diff --git a/core/storage/migrations/2019-11-12-150641_add_eth_hash/down.sql b/core/storage/migrations/2019-11-12-150641_add_eth_hash/down.sql deleted file mode 100644 index 631e665749..0000000000 --- a/core/storage/migrations/2019-11-12-150641_add_eth_hash/down.sql +++ /dev/null @@ -1,2 +0,0 @@ --- This file should undo anything in `up.sql` -alter table executed_priority_operations drop column eth_hash; diff --git a/core/storage/migrations/2019-11-12-150641_add_eth_hash/up.sql b/core/storage/migrations/2019-11-12-150641_add_eth_hash/up.sql deleted file mode 100644 index 4b773b865a..0000000000 --- a/core/storage/migrations/2019-11-12-150641_add_eth_hash/up.sql +++ /dev/null @@ -1,2 +0,0 @@ --- Your SQL goes here -alter table executed_priority_operations add column eth_hash bytea not null; diff --git a/core/storage/migrations/2020-01-19-134954_new-pubkey-hash-tx/down.sql b/core/storage/migrations/2020-01-19-134954_new-pubkey-hash-tx/down.sql deleted file mode 100644 index c6ad7733af..0000000000 --- a/core/storage/migrations/2020-01-19-134954_new-pubkey-hash-tx/down.sql +++ /dev/null @@ -1,11 +0,0 @@ --- This file should undo anything in `up.sql` -DROP TABLE IF EXISTS account_pubkey_updates CASCADE; - -ALTER TABLE accounts - DROP COLUMN pubkey_hash CASCADE; - -ALTER TABLE account_balance_updates - DROP COLUMN update_order_id CASCADE; - -ALTER TABLE account_creates - DROP COLUMN update_order_id CASCADE; diff --git a/core/storage/migrations/2020-01-19-134954_new-pubkey-hash-tx/up.sql b/core/storage/migrations/2020-01-19-134954_new-pubkey-hash-tx/up.sql deleted file mode 100644 index e4507c3937..0000000000 --- a/core/storage/migrations/2020-01-19-134954_new-pubkey-hash-tx/up.sql +++ /dev/null @@ -1,21 +0,0 @@ -create TABLE account_pubkey_updates -( - pubkey_update_id serial not null, - update_order_id integer not null, - account_id bigint not null, - block_number bigint not null, - old_pubkey_hash bytea not null, - new_pubkey_hash bytea not null, - old_nonce bigint not null, - new_nonce bigint not null, - PRIMARY KEY (pubkey_update_id) -); - -ALTER TABLE accounts - ADD COLUMN pubkey_hash bytea not null; - -ALTER TABLE account_balance_updates - ADD COLUMN update_order_id integer not null; - -ALTER TABLE account_creates - ADD COLUMN update_order_id integer not null; diff --git a/core/storage/migrations/2020-02-19-055132_add_block_size/down.sql b/core/storage/migrations/2020-02-19-055132_add_block_size/down.sql deleted file mode 100644 index f04db92881..0000000000 --- a/core/storage/migrations/2020-02-19-055132_add_block_size/down.sql +++ /dev/null @@ -1,5 +0,0 @@ -alter table blocks -drop column block_size; - -alter table active_provers -drop column block_size; diff --git a/core/storage/migrations/2020-02-19-055132_add_block_size/up.sql b/core/storage/migrations/2020-02-19-055132_add_block_size/up.sql deleted file mode 100644 index 8dfc258ee2..0000000000 --- a/core/storage/migrations/2020-02-19-055132_add_block_size/up.sql +++ /dev/null @@ -1,5 +0,0 @@ -alter table blocks -add block_size bigint not null; - -alter table active_provers -add block_size bigint not null; diff --git a/core/storage/migrations/2020-02-19-124124_token-symbol-required/down.sql b/core/storage/migrations/2020-02-19-124124_token-symbol-required/down.sql deleted file mode 100644 index d9a93fe9a1..0000000000 --- a/core/storage/migrations/2020-02-19-124124_token-symbol-required/down.sql +++ /dev/null @@ -1 +0,0 @@ --- This file should undo anything in `up.sql` diff --git a/core/storage/migrations/2020-02-19-124124_token-symbol-required/up.sql b/core/storage/migrations/2020-02-19-124124_token-symbol-required/up.sql deleted file mode 100644 index ff0547ffcf..0000000000 --- a/core/storage/migrations/2020-02-19-124124_token-symbol-required/up.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE tokens - ALTER COLUMN symbol SET NOT NULL; diff --git a/core/storage/migrations/2020-03-19-042712_more_eth_data/down.sql b/core/storage/migrations/2020-03-19-042712_more_eth_data/down.sql deleted file mode 100644 index af3daf8af0..0000000000 --- a/core/storage/migrations/2020-03-19-042712_more_eth_data/down.sql +++ /dev/null @@ -1,21 +0,0 @@ --- This file should undo anything in `up.sql` -DROP TABLE IF EXISTS eth_nonce CASCADE; -DROP TABLE IF EXISTS eth_stats CASCADE; -DROP TABLE IF EXISTS eth_ops_binding CASCADE; -DROP TABLE IF EXISTS eth_tx_hashes CASCADE; - -ALTER TABLE eth_operations - -- Restore `op_id` - ADD COLUMN op_id bigserial REFERENCES operations (id), - -- Restore `tx_hash` field - ADD COLUMN tx_hash bytea not null, - -- Remove `op_type` - DROP COLUMN op_type CASCADE, - -- Rename `last_used_gas_price` to `gas_price` - ADD COLUMN gas_price numeric not null, - DROP COLUMN last_used_gas_price CASCADE, - -- Rename `last_deadline_block` to `deadline_block` - ADD COLUMN deadline_block bigint not null, - DROP COLUMN last_deadline_block CASCADE, - -- Remove `final_hash` - DROP COLUMN final_hash CASCADE diff --git a/core/storage/migrations/2020-03-19-042712_more_eth_data/up.sql b/core/storage/migrations/2020-03-19-042712_more_eth_data/up.sql deleted file mode 100644 index f40d52899d..0000000000 --- a/core/storage/migrations/2020-03-19-042712_more_eth_data/up.sql +++ /dev/null @@ -1,51 +0,0 @@ --- Your SQL goes here --- Locally stored Ethereum nonce -CREATE TABLE eth_nonce ( - -- enforce single record - id bool PRIMARY KEY NOT NULL DEFAULT true, - nonce BIGINT NOT NULL -); - --- Gathered operations statistics -CREATE TABLE eth_stats ( - -- enforce single record - id bool PRIMARY KEY NOT NULL DEFAULT true, - commit_ops BIGINT NOT NULL, - verify_ops BIGINT NOT NULL, - withdraw_ops BIGINT NOT NULL -); - --- Table connection `eth_operations` and `operations` table. --- Each entry provides a mapping between the Ethereum transaction and the ZK Sync operation. -CREATE TABLE eth_ops_binding -( - id bigserial PRIMARY KEY, - op_id bigserial NOT NULL REFERENCES operations (id), - eth_op_id bigserial NOT NULL REFERENCES eth_operations (id) -); - --- Table storing all the sent Ethereum transaction hashes. -CREATE TABLE eth_tx_hashes -( - id bigserial PRIMARY KEY, - eth_op_id bigserial NOT NULL REFERENCES eth_operations (id), - tx_hash bytea NOT NULL -); - -ALTER TABLE eth_operations - -- Add the operation type (`commit` / `verify` / `withdraw`). - ADD COLUMN op_type text not null, - -- Remove the `op_id` field, since `withdraw` operation does not have an associated operation. - -- The `eth_ops_binding` table should be used since now. - DROP COLUMN op_id CASCADE, - -- Different tx hashes are now stored in the `eth_tx_hashes` table, so this field isn't needed anymore. - DROP COLUMN tx_hash CASCADE, - -- Add the field containing the final hash of the committed tx. - -- This field is `null` until tx has enough confirmations. - ADD COLUMN final_hash bytea default null, - -- Rename `deadline_block` to `last_deadline_block` - DROP COLUMN deadline_block CASCADE, - ADD COLUMN last_deadline_block bigint not null, - -- Rename `gas_price` to `last_used_gas_price` - DROP COLUMN gas_price CASCADE, - ADD COLUMN last_used_gas_price numeric not null diff --git a/core/storage/migrations/2019-08-30-111817_operations_update/down.sql b/core/storage/migrations/2020-03-26-172806_leader-election/down.sql similarity index 50% rename from core/storage/migrations/2019-08-30-111817_operations_update/down.sql rename to core/storage/migrations/2020-03-26-172806_leader-election/down.sql index 6612641c0b..2efd0fe1c1 100644 --- a/core/storage/migrations/2019-08-30-111817_operations_update/down.sql +++ b/core/storage/migrations/2020-03-26-172806_leader-election/down.sql @@ -1,2 +1,2 @@ -- This file should undo anything in `up.sql` --- unimplemented \ No newline at end of file +DROP TABLE IF EXISTS leader_election CASCADE; diff --git a/core/storage/migrations/2020-03-26-172806_leader-election/up.sql b/core/storage/migrations/2020-03-26-172806_leader-election/up.sql new file mode 100644 index 0000000000..9cf578537a --- /dev/null +++ b/core/storage/migrations/2020-03-26-172806_leader-election/up.sql @@ -0,0 +1,7 @@ +-- Your SQL goes here +CREATE TABLE leader_election ( + id serial primary key, + name text not null, + created_at timestamp not null default now(), + bail_at timestamp null +); diff --git a/core/storage/migrations/2020-04-07-065600_init_storage/down.sql b/core/storage/migrations/2020-04-07-065600_init_storage/down.sql new file mode 100644 index 0000000000..33561c6c7e --- /dev/null +++ b/core/storage/migrations/2020-04-07-065600_init_storage/down.sql @@ -0,0 +1,61 @@ +-- Drop all the indexes. +DROP INDEX operations_block_index; +DROP INDEX blocks_root_hash_index; +DROP INDEX tokens_symbol_index; +DROP INDEX eth_ops_binding_op_id_index; +DROP INDEX eth_tx_hashes_eth_op_id_index; + +DROP INDEX accounts_block_index; +DROP INDEX accounts_address_index; +DROP INDEX account_balance_updates_block_index; +DROP INDEX account_creates_block_index; +DROP INDEX account_pubkey_updates_block_index; + +DROP INDEX executed_transactions_block_number_index; +DROP INDEX executed_transactions_hash_index; +DROP INDEX executed_transactions_from_account_index; +DROP INDEX executed_transactions_to_account_index; + +DROP INDEX executed_priority_operations_block_index; +DROP INDEX executed_priority_operations_serialid_index; +DROP INDEX executed_priority_operations_eth_hash_index; +DROP INDEX executed_priority_operations_from_account_index; +DROP INDEX executed_priority_operations_to_account_index; + +-- Clear transactions/operations section +DROP TABLE IF EXISTS blocks; +DROP TABLE IF EXISTS operations; +DROP TABLE IF EXISTS executed_priority_operations; +DROP TABLE IF EXISTS rollup_ops; +DROP TABLE IF EXISTS mempool; +DROP TABLE IF EXISTS executed_transactions; + +-- Clear accounts section +DROP TABLE IF EXISTS accounts; +DROP TABLE IF EXISTS account_balance_updates; +DROP TABLE IF EXISTS account_creates; +DROP TABLE IF EXISTS account_pubkey_updates; +DROP TABLE IF EXISTS balances; + +-- Clear state section +DROP TABLE IF EXISTS events_state; +DROP TABLE IF EXISTS storage_state_update; + +-- Clear prover section +DROP TABLE IF EXISTS proofs; +DROP TABLE IF EXISTS prover_runs; +DROP TABLE IF EXISTS active_provers; + +-- Remove tokens section +DROP TABLE IF EXISTS tokens; + +-- Remove server config table +DROP TABLE IF EXISTS server_config; + +-- Clear ETH section +DROP TABLE IF EXISTS eth_operations; +DROP TABLE IF EXISTS eth_nonce; +DROP TABLE IF EXISTS eth_stats; +DROP TABLE IF EXISTS eth_ops_binding; +DROP TABLE IF EXISTS eth_tx_hashes; +DROP TABLE IF EXISTS data_restore_last_watched_eth_block; diff --git a/core/storage/migrations/2020-04-07-065600_init_storage/up.sql b/core/storage/migrations/2020-04-07-065600_init_storage/up.sql new file mode 100644 index 0000000000..60ce78aa69 --- /dev/null +++ b/core/storage/migrations/2020-04-07-065600_init_storage/up.sql @@ -0,0 +1,322 @@ +/* +This migration initializes the ZKSync database state by creating all the +required tables and performing the associated operations (e.g. creating indexes). + +File is structured to contain statements in the following order: + +- Tables creation (split by comments into logically separated sections). +- Indexes creation. +- Extensions enabling. +- Data insertion. + +Note that this script does not insert all the required data by itself, +some of the data is inserted by the scripts from the `bin` folder. +To be sure that database is fully initialized, migrations should not +be run directly via `diesel_cli`, but `zksync db-reset` should be used instead. +*/ + +-- ------------------------------- -- +-- Transactions/operations section -- +-- ------------------------------- -- + +-- Table containing all the ZKSync block execution operations. +-- Operations are associated with some block and every block can +-- have multiple related operations with different action types +-- (e.g. `commit` / `verify`). +CREATE TABLE operations ( + id bigserial PRIMARY KEY, + block_number BIGINT NOT NULL, + action_type TEXT NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT now(), + confirmed bool NOT NULL DEFAULT false +); + +-- Block header entry. +CREATE TABLE blocks ( + number BIGINT PRIMARY KEY, + root_hash BYTEA NOT NULL, + fee_account_id BIGINT NOT NULL, + unprocessed_prior_op_before BIGINT NOT NULL, + unprocessed_prior_op_after BIGINT NOT NULL, + block_size BIGINT NOT NULL +); + +-- Table for the executed priority operations (e.g. deposit). +CREATE TABLE executed_priority_operations ( + id serial PRIMARY KEY, + -- sidechain block info + block_number BIGINT NOT NULL, + block_index INT NOT NULL, + -- operation data + operation jsonb NOT NULL, + -- operation metadata + from_account bytea NOT NULL, + to_account bytea NOT NULL, + priority_op_serialid BIGINT NOT NULL, + deadline_block BIGINT NOT NULL, + eth_fee NUMERIC NOT NULL, + eth_hash bytea NOT NULL +); + +-- Table for the executed common operations (e.g. transfer). +CREATE TABLE executed_transactions ( + id serial PRIMARY KEY, + -- sidechain block info + block_number BIGINT NOT NULL, + block_index INT, + -- operation data + tx jsonb NOT NULL, + operation jsonb NOT NULL, + -- operation metadata + tx_hash bytea NOT NULL, + from_account bytea NOT NULL, + to_account bytea, + success bool NOT NULL, + fail_reason TEXT, + primary_account_address bytea NOT NULL, + nonce BIGINT NOT NULL +); + +-- -------------- -- +-- Tokens section -- +-- -------------- -- + +-- Token types known to the ZKSync node. +-- By default has the ETH token only (see the `INSERT` statement in the end of the file). +CREATE TABLE tokens ( + id INTEGER NOT NULL PRIMARY KEY, + address TEXT NOT NULL, + symbol TEXT NOT NULL +); + +-- ---------------- -- +-- Accounts section -- +-- ---------------- -- + +-- Table for the ZKSync accounts. +CREATE TABLE accounts ( + id BIGINT NOT NULL PRIMARY KEY, + last_block BIGINT NOT NULL, + nonce BIGINT NOT NULL, + address bytea NOT NULL, + pubkey_hash bytea NOT NULL +); + +-- Table for the account balance change operations. +CREATE TABLE account_balance_updates ( + balance_update_id serial NOT NULL, + account_id BIGINT NOT NULL, + block_number BIGINT NOT NULL, + coin_id INTEGER NOT NULL REFERENCES tokens(id) ON UPDATE CASCADE, + old_balance NUMERIC NOT NULL, + new_balance NUMERIC NOT NULL, + old_nonce BIGINT NOT NULL, + new_nonce BIGINT NOT NULL, + update_order_id INTEGER NOT NULL, + PRIMARY KEY (balance_update_id) +); + +-- Table for the account creation operations. +CREATE TABLE account_creates ( + account_id BIGINT NOT NULL, + is_create bool NOT NULL, + block_number BIGINT NOT NULL, + address bytea NOT NULL, + nonce BIGINT NOT NULL, + update_order_id INTEGER NOT NULL, + PRIMARY KEY (account_id, block_number) +); + +-- Table for the account public key change operations. +CREATE TABLE account_pubkey_updates ( + pubkey_update_id serial NOT NULL, + update_order_id INTEGER NOT NULL, + account_id BIGINT NOT NULL, + block_number BIGINT NOT NULL, + old_pubkey_hash bytea NOT NULL, + new_pubkey_hash bytea NOT NULL, + old_nonce BIGINT NOT NULL, + new_nonce BIGINT NOT NULL, + PRIMARY KEY (pubkey_update_id) +); + +-- Table for the account balances. One account can have several balances, +-- but every balance account has must have an unique token (meaning that +-- there may be user with `ETH` and `ERC-20` balances, but not with `ETH` +-- and `ETH` balances). +CREATE TABLE balances ( + account_id BIGINT REFERENCES accounts(id) ON UPDATE CASCADE ON DELETE CASCADE, + coin_id INTEGER REFERENCES tokens(id) ON UPDATE CASCADE, + balance NUMERIC NOT NULL DEFAULT 0, + PRIMARY KEY (account_id, coin_id) +); + +-- ------------- -- +-- Data restore section -- +-- ------------- -- + +CREATE TABLE data_restore_events_state ( + id SERIAL PRIMARY KEY, + block_type TEXT NOT NULL, + transaction_hash BYTEA NOT NULL, + block_num BIGINT NOT NULL +); + +CREATE TABLE data_restore_storage_state_update +( + id SERIAL PRIMARY KEY, + storage_state TEXT NOT NULL +); + +CREATE TABLE data_restore_last_watched_eth_block +( + id SERIAL PRIMARY KEY, + block_number TEXT NOT NULL +); + +-- Table for the executed franklin operations, used by +CREATE TABLE data_restore_rollup_ops +( + id SERIAL PRIMARY KEY, + block_num BIGINT NOT NULL, + operation JSONB NOT NULL, + fee_account BIGINT NOT NULL +); + + +-- -------------- -- +-- Prover section -- +-- -------------- -- + +-- Stored proofs for the blocks. +CREATE TABLE proofs ( + block_number bigserial PRIMARY KEY, + proof jsonb NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT now() +); + +-- Ongoing block proving jobs. +CREATE TABLE prover_runs ( + id serial PRIMARY KEY, + block_number BIGINT NOT NULL, + worker TEXT, + created_at TIMESTAMP NOT NULL DEFAULT now(), + updated_at TIMESTAMP NOT NULL DEFAULT now() +); + +-- List of currently available provers. +CREATE TABLE active_provers ( + id serial PRIMARY KEY, + worker TEXT NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT now(), + stopped_at TIMESTAMP, + block_size BIGINT NOT NULL +); + +-- --------------------- -- +-- Server config section -- +-- --------------------- -- + +-- Unique server configuration entry. +-- Expected to be initialized separately, e.g. by `zksync db-reset` or `zksync init` command. +CREATE TABLE server_config ( + -- enforce single record + id bool PRIMARY KEY NOT NULL DEFAULT true, + CONSTRAINT single_server_config CHECK (id), + contract_addr TEXT, + gov_contract_addr TEXT +); + +-- ----------- -- +-- ETH section -- +-- ----------- -- + +-- Stored Ethereum anchoring operations. +CREATE TABLE eth_operations ( + id bigserial PRIMARY KEY, + nonce BIGINT NOT NULL, + confirmed bool NOT NULL DEFAULT false, + raw_tx bytea NOT NULL, + op_type TEXT NOT NULL, + final_hash bytea DEFAULT NULL, + last_deadline_block BIGINT NOT NULL, + last_used_gas_price NUMERIC NOT NULL +); + +-- Locally stored Ethereum nonce +CREATE TABLE eth_nonce ( + -- enforce single record + id bool PRIMARY KEY NOT NULL DEFAULT true, + nonce BIGINT NOT NULL +); + +-- Gathered operations statistics +CREATE TABLE eth_stats ( + -- enforce single record + id bool PRIMARY KEY NOT NULL DEFAULT true, + commit_ops BIGINT NOT NULL, + verify_ops BIGINT NOT NULL, + withdraw_ops BIGINT NOT NULL +); + +-- Table connection `eth_operations` and `operations` table. +-- Each entry provides a mapping between the Ethereum transaction and the ZK Sync operation. +CREATE TABLE eth_ops_binding ( + id bigserial PRIMARY KEY, + op_id bigserial NOT NULL REFERENCES operations(id), + eth_op_id bigserial NOT NULL REFERENCES eth_operations(id) +); + +-- Table storing all the sent Ethereum transaction hashes. +CREATE TABLE eth_tx_hashes ( + id bigserial PRIMARY KEY, + eth_op_id bigserial NOT NULL REFERENCES eth_operations(id), + tx_hash bytea NOT NULL +); + +-- --------------- -- +-- Indexes section -- +-- --------------- -- + +-- Indexes are built for tables on the columns which are used intensively in queries. +CREATE INDEX operations_block_index ON operations (block_number); +CREATE INDEX blocks_root_hash_index ON blocks (root_hash); +CREATE INDEX tokens_symbol_index ON tokens (symbol); +CREATE INDEX eth_ops_binding_op_id_index ON eth_ops_binding (op_id); +CREATE INDEX eth_tx_hashes_eth_op_id_index ON eth_tx_hashes (eth_op_id); + +CREATE INDEX accounts_block_index ON accounts (last_block); +CREATE INDEX accounts_address_index ON accounts (address); +CREATE INDEX account_balance_updates_block_index ON account_balance_updates (block_number); +CREATE INDEX account_creates_block_index ON account_creates (block_number); +CREATE INDEX account_pubkey_updates_block_index ON account_pubkey_updates (block_number); + +CREATE INDEX executed_transactions_block_number_index ON executed_transactions (block_number); +CREATE INDEX executed_transactions_hash_index ON executed_transactions (tx_hash); +CREATE INDEX executed_transactions_from_account_index ON executed_transactions (from_account); +CREATE INDEX executed_transactions_to_account_index ON executed_transactions (to_account); + +CREATE INDEX executed_priority_operations_block_index ON executed_priority_operations (block_number); +CREATE INDEX executed_priority_operations_serialid_index ON executed_priority_operations (priority_op_serialid); +CREATE INDEX executed_priority_operations_eth_hash_index ON executed_priority_operations (eth_hash); +CREATE INDEX executed_priority_operations_from_account_index ON executed_priority_operations (from_account); +CREATE INDEX executed_priority_operations_to_account_index ON executed_priority_operations (to_account); + +-- ------------------ -- +-- Extensions section -- +-- ------------------ -- + +-- `tablefunc` enables `crosstab` (pivot) +CREATE EXTENSION IF NOT EXISTS tablefunc; + +-- ---------------------- -- +-- Data insertion section -- +-- ---------------------- -- + +-- Add ETH token +INSERT INTO tokens +VALUES ( + 0, + '0x0000000000000000000000000000000000000000', + 'ETH' +); diff --git a/core/storage/src/chain/block/conversion.rs b/core/storage/src/chain/block/conversion.rs index 4318309b87..e9c967ee3f 100644 --- a/core/storage/src/chain/block/conversion.rs +++ b/core/storage/src/chain/block/conversion.rs @@ -2,6 +2,8 @@ //! These methods are only needed for the `block` module, so they're kept in a //! private module. +// Built-in deps +use std::convert::TryFrom; // External imports // Workspace imports use diesel::prelude::*; @@ -20,7 +22,6 @@ use crate::{ NewExecutedPriorityOperation, NewExecutedTransaction, StoredExecutedPriorityOperation, StoredExecutedTransaction, StoredOperation, }, - operations_ext::records::ReadTx, state::StateSchema, }, prover::ProverSchema, @@ -56,31 +57,20 @@ impl StoredOperation { } impl StoredExecutedTransaction { - pub fn into_executed_tx(self, stored_tx: Option) -> Result { - if let Some(op) = self.operation { - let franklin_op: FranklinOp = - serde_json::from_value(op).expect("Unparsable FranklinOp in db"); - Ok(ExecutedTx { - tx: franklin_op - .try_get_tx() - .expect("FranklinOp should not have tx"), - success: true, - op: Some(franklin_op), - fail_reason: None, - block_index: Some(self.block_index.expect("Block idx should be set") as u32), - }) - } else if let Some(stored_tx) = stored_tx { - let tx: FranklinTx = serde_json::from_value(stored_tx.tx).expect("Unparsable tx in db"); - Ok(ExecutedTx { - tx, - success: false, - op: None, - fail_reason: self.fail_reason, - block_index: None, - }) - } else { - failure::bail!("Unsuccessful tx was lost from db."); - } + pub fn into_executed_tx(self) -> Result { + let franklin_tx: FranklinTx = + serde_json::from_value(self.tx).expect("Unparsable FranklinTx in db"); + let franklin_op: Option = + serde_json::from_value(self.operation).expect("Unparsable FranklinOp in db"); + Ok(ExecutedTx { + tx: franklin_tx, + success: self.success, + op: franklin_op, + fail_reason: self.fail_reason, + block_index: self + .block_index + .map(|val| u32::try_from(val).expect("Invalid block index")), + }) } } @@ -112,10 +102,25 @@ impl NewExecutedPriorityOperation { let mut operation = serde_json::to_value(&exec_prior_op.op).unwrap(); operation["eth_fee"] = serde_json::to_value(exec_prior_op.priority_op.eth_fee.to_string()).unwrap(); + + let (from_account, to_account) = match exec_prior_op.op { + FranklinOp::Deposit(deposit) => (deposit.priority_op.from, deposit.priority_op.to), + FranklinOp::FullExit(full_exit) => { + let eth_address = full_exit.priority_op.eth_address; + (eth_address, eth_address) + } + _ => panic!( + "Incorrect type of priority op: {:?}", + exec_prior_op.priority_op + ), + }; + Self { block_number: i64::from(block), block_index: exec_prior_op.block_index as i32, operation, + from_account: from_account.as_ref().to_vec(), + to_account: to_account.as_ref().to_vec(), priority_op_serialid: exec_prior_op.priority_op.serial_id as i64, deadline_block: exec_prior_op.priority_op.deadline_block as i64, eth_fee: exec_prior_op.priority_op.eth_fee, @@ -126,13 +131,50 @@ impl NewExecutedPriorityOperation { impl NewExecutedTransaction { pub fn prepare_stored_tx(exec_tx: ExecutedTx, block: BlockNumber) -> Self { + fn cut_prefix(input: &str) -> String { + if input.starts_with("0x") { + input[2..].into() + } else if input.starts_with("sync:") { + input[5..].into() + } else { + input.into() + } + } + + let tx = serde_json::to_value(&exec_tx.tx).expect("Cannot serialize tx"); + let operation = serde_json::to_value(&exec_tx.op).expect("Cannot serialize operation"); + + let (from_account_hex, to_account_hex): (String, Option) = match exec_tx.tx { + FranklinTx::Withdraw(_) | FranklinTx::Transfer(_) => ( + serde_json::from_value(tx["from"].clone()).unwrap(), + serde_json::from_value(tx["to"].clone()).unwrap(), + ), + FranklinTx::ChangePubKey(_) => ( + serde_json::from_value(tx["account"].clone()).unwrap(), + serde_json::from_value(tx["newPkHash"].clone()).unwrap(), + ), + FranklinTx::Close(_) => ( + serde_json::from_value(tx["account"].clone()).unwrap(), + serde_json::from_value(tx["account"].clone()).unwrap(), + ), + }; + + let from_account: Vec = hex::decode(cut_prefix(&from_account_hex)).unwrap(); + let to_account: Option> = + to_account_hex.map(|value| hex::decode(cut_prefix(&value)).unwrap()); + Self { block_number: i64::from(block), tx_hash: exec_tx.tx.hash().as_ref().to_vec(), - operation: exec_tx.op.map(|o| serde_json::to_value(o).unwrap()), + from_account, + to_account, + tx, + operation, success: exec_tx.success, fail_reason: exec_tx.fail_reason, block_index: exec_tx.block_index.map(|idx| idx as i32), + primary_account_address: exec_tx.tx.account().as_bytes().to_vec(), + nonce: exec_tx.tx.nonce() as i64, } } } diff --git a/core/storage/src/chain/block/mod.rs b/core/storage/src/chain/block/mod.rs index ad5939e556..7f51e155ff 100644 --- a/core/storage/src/chain/block/mod.rs +++ b/core/storage/src/chain/block/mod.rs @@ -3,21 +3,20 @@ use diesel::dsl::max; use diesel::prelude::*; use diesel::result::Error as DieselError; -use diesel::sql_types::Text; // Workspace imports use models::node::{ block::{Block, ExecutedOperations}, - AccountId, BlockNumber, Fr, FranklinOp, + AccountId, BlockNumber, FranklinOp, }; -use models::{fe_from_hex, fe_to_hex, Action, ActionType, Operation}; +use models::{fe_from_bytes, fe_to_bytes, Action, ActionType, Operation}; // Local imports use self::records::{BlockDetails, StorageBlock}; use crate::prover::records::StoredProof; +use crate::prover::ProverSchema; use crate::schema::*; use crate::StorageProcessor; use crate::{ chain::{ - mempool::MempoolSchema, operations::{ records::{ NewExecutedPriorityOperation, NewExecutedTransaction, NewOperation, @@ -25,7 +24,6 @@ use crate::{ }, OperationsSchema, }, - operations_ext::records::{InsertTx, ReadTx}, state::StateSchema, }, ethereum::records::ETHBinding, @@ -53,12 +51,19 @@ impl<'a> BlockSchema<'a> { match &op.action { Action::Commit => { - StateSchema(self.0) - .commit_state_update(op.block.block_number, &op.accounts_updated)?; + StateSchema(self.0).commit_state_update(block_number, &op.accounts_updated)?; self.save_block(op.block)?; } - Action::Verify { .. } => { - StateSchema(self.0).apply_state_update(op.block.block_number)? + Action::Verify { proof } => { + let stored_proof = ProverSchema(self.0).load_proof(block_number); + match stored_proof { + Err(DieselError::NotFound) => { + ProverSchema(self.0).store_proof(block_number, proof)?; + } + Err(e) => return Err(e), + Ok(_) => {} + }; + StateSchema(self.0).apply_state_update(block_number)? } }; @@ -77,25 +82,8 @@ impl<'a> BlockSchema<'a> { for block_tx in block.block_transactions.into_iter() { match block_tx { ExecutedOperations::Tx(tx) => { - // Copy the tx data. - let hash = tx.tx.hash().as_ref().to_vec(); - let primary_account_address = tx.tx.account().as_bytes().to_vec(); - let nonce = tx.tx.nonce() as i64; - let serialized_tx = serde_json::to_value(&tx.tx).unwrap_or_default(); - - // Create records for `operations` and `mempool` tables. + // Store the executed operation in the corresponding schema. let new_tx = NewExecutedTransaction::prepare_stored_tx(*tx, block.block_number); - let mempool_tx = InsertTx { - hash, - primary_account_address, - nonce, - tx: serialized_tx, - }; - - // Store the transaction in `mempool` and `operations` tables. - // Note that `mempool` table should be updated *first*, since hash there - // is a foreign key in `operations` table. - MempoolSchema(self.0).insert_tx(mempool_tx)?; OperationsSchema(self.0).store_executed_operation(new_tx)?; } ExecutedOperations::PriorityOp(prior_op) => { @@ -128,10 +116,8 @@ impl<'a> BlockSchema<'a> { // Load transactions for this block. let block_transactions = self.get_block_executed_ops(block)?; - // Change the root hash format from `sync-bl:FF..FF` to `0xFF..FF`. - assert!(stored_block.root_hash.starts_with("sync-bl:")); - let new_root_hash = fe_from_hex::(&format!("0x{}", &stored_block.root_hash[8..])) - .expect("Unparsable root hash"); + // Encode the root hash as `0xFF..FF`. + let new_root_hash = fe_from_bytes(&stored_block.root_hash).expect("Unparsable root hash"); // Return the obtained block in the expected format. Ok(Some(Block { @@ -170,16 +156,10 @@ impl<'a> BlockSchema<'a> { // from the database. let (executed_ops, executed_priority_ops) = self.0.conn().transaction::<_, DieselError, _>(|| { - // To load executed transactions, we join `executed_transactions` table (which - // contains the header of the transaction) and `mempool` which contains the - // transactions body. let executed_ops = executed_transactions::table - .left_join(mempool::table.on(executed_transactions::tx_hash.eq(mempool::hash))) .filter(executed_transactions::block_number.eq(i64::from(block))) - .load::<(StoredExecutedTransaction, Option)>(self.0.conn())?; + .load::(self.0.conn())?; - // For priority operations, we simply load them from - // `executed_priority_operations` table. let executed_priority_ops = executed_priority_operations::table .filter(executed_priority_operations::block_number.eq(i64::from(block))) .load::(self.0.conn())?; @@ -190,7 +170,7 @@ impl<'a> BlockSchema<'a> { // Transform executed operations to be `ExecutedOperations`. let executed_ops = executed_ops .into_iter() - .filter_map(|(stored_exec, stored_tx)| stored_exec.into_executed_tx(stored_tx).ok()) + .filter_map(|stored_exec| stored_exec.into_executed_tx().ok()) .map(|tx| ExecutedOperations::Tx(Box::new(tx))); executed_operations.extend(executed_ops); @@ -237,7 +217,7 @@ impl<'a> BlockSchema<'a> { with eth_ops as ( \ select \ operations.block_number, \ - '0x' || encode(eth_tx_hashes.tx_hash::bytea, 'hex') as tx_hash, \ + eth_tx_hashes.tx_hash, \ operations.action_type, \ operations.created_at \ from operations \ @@ -268,6 +248,23 @@ impl<'a> BlockSchema<'a> { diesel::sql_query(query).load(self.0.conn()) } + /// Helper method for `find_block_by_height_or_hash`. It checks whether + /// provided string can be interpreted like a hash, and if so, returns the + /// hexadecimal string without prefix. + fn try_parse_hex(&self, query: &str) -> Option { + const HASH_STRING_SIZE: usize = 32 * 2; // 32 bytes, 2 symbols per byte. + + if query.starts_with("0x") { + Some(query[2..].into()) + } else if query.starts_with("sync-bl:") { + Some(query[8..].into()) + } else if query.len() == HASH_STRING_SIZE && hex::decode(query).is_ok() { + Some(query.into()) + } else { + None + } + } + /// Performs a database search with an uncertain query, which can be either of: /// - Hash of commit/verify Ethereum transaction for the block. /// - The state root hash of the block. @@ -276,8 +273,36 @@ impl<'a> BlockSchema<'a> { /// Will return `None` if the query is malformed or there is no block that matches /// the query. pub fn find_block_by_height_or_hash(&self, query: String) -> Option { - let block_number = query.parse::().unwrap_or(i64::max_value()); - let l_query = query.to_lowercase(); + // Adapt the SQL query based on the input data format. + let mut where_condition = String::new(); + + // If the input looks like hash, add the hash lookup part. + if let Some(hex_query) = self.try_parse_hex(&query) { + let hash_lookup = format!( + " \ + or committed.tx_hash = decode('{hex_query}', 'hex') \ + or verified.tx_hash = decode('{hex_query}', 'hex') \ + or blocks.root_hash = decode('{hex_query}', 'hex') \ + ", + hex_query = hex_query + ); + + where_condition += &hash_lookup; + }; + + // If the input can be interpreted as integer, add the block number lookup part. + if let Ok(int_query) = query.parse::() { + let block_lookup = format!("or blocks.number = {}", int_query); + + where_condition += &block_lookup; + } + + // If `where` condition is empty (input doesn't look like hash or integer), no query + // should be performed. + if where_condition.is_empty() { + return None; + } + // This query does the following: // - joins the `operations` and `eth_tx_hashes` (using the intermediate `eth_ops_binding` table) // tables to collect the data: @@ -294,7 +319,7 @@ impl<'a> BlockSchema<'a> { with eth_ops as ( \ select \ operations.block_number, \ - '0x' || encode(eth_tx_hashes.tx_hash::bytea, 'hex') as tx_hash, \ + eth_tx_hashes.tx_hash, \ operations.action_type, \ operations.created_at \ from operations \ @@ -315,19 +340,14 @@ impl<'a> BlockSchema<'a> { left join eth_ops verified on \ verified.block_number = blocks.number and verified.action_type = 'VERIFY' \ where false \ - or lower(committed.tx_hash) = $1 \ - or lower(verified.tx_hash) = $1 \ - or lower(blocks.root_hash) = $1 \ - or blocks.number = {block_number} \ + {where_condition} \ order by blocks.number desc \ limit 1; \ ", - block_number = block_number + where_condition = where_condition ); - diesel::sql_query(sql_query) - .bind::(l_query) - .get_result(self.0.conn()) - .ok() + + diesel::sql_query(sql_query).get_result(self.0.conn()).ok() } pub fn load_commit_op(&self, block_number: BlockNumber) -> Option { @@ -358,26 +378,16 @@ impl<'a> BlockSchema<'a> { ) -> QueryResult> { self.0.conn().transaction(|| { let ops: Vec<(StoredOperation, Option)> = diesel::sql_query(format!( - " - WITH sized_operations AS ( - SELECT operations.*, proofs.*, operations.block_number as the_block_number - FROM operations - LEFT JOIN blocks - ON number = block_number - LEFT JOIN proofs - USING (block_number) - ) - SELECT * - FROM sized_operations - WHERE action_type = 'COMMIT' - AND the_block_number > ( - SELECT COALESCE(max(the_block_number), 0) - FROM sized_operations - WHERE action_type = 'VERIFY' - ) - AND the_block_number > {} - ORDER BY the_block_number - LIMIT {} + "SELECT operations.*, proofs.* + FROM operations + LEFT JOIN blocks + ON number = block_number + LEFT JOIN proofs + USING (block_number) + WHERE operations.action_type = 'COMMIT' + AND operations.block_number > {} + ORDER BY operations.block_number + LIMIT {} ", block, limit )) @@ -412,7 +422,7 @@ impl<'a> BlockSchema<'a> { pub(crate) fn save_block(&self, block: Block) -> QueryResult<()> { self.0.conn().transaction(|| { let number = i64::from(block.block_number); - let root_hash = format!("sync-bl:{}", fe_to_hex(&block.new_root_hash)); + let root_hash = fe_to_bytes(&block.new_root_hash); let fee_account_id = i64::from(block.fee_account); let unprocessed_prior_op_before = block.processed_priority_ops.0 as i64; let unprocessed_prior_op_after = block.processed_priority_ops.1 as i64; diff --git a/core/storage/src/chain/block/records.rs b/core/storage/src/chain/block/records.rs index 7e6d21e4ac..db3c8eac0e 100644 --- a/core/storage/src/chain/block/records.rs +++ b/core/storage/src/chain/block/records.rs @@ -1,16 +1,17 @@ // External imports use chrono::prelude::*; -use diesel::sql_types::{BigInt, Nullable, Text, Timestamp}; +use diesel::sql_types::{BigInt, Binary, Nullable, Timestamp}; use serde_derive::{Deserialize, Serialize}; // Workspace imports // Local imports use crate::schema::*; +use crate::utils::{BytesToHexSerde, OptionBytesToHexSerde, SyncBlockPrefix, ZeroxPrefix}; #[derive(Debug, Insertable, Queryable)] #[table_name = "blocks"] pub struct StorageBlock { pub number: i64, - pub root_hash: String, + pub root_hash: Vec, pub fee_account_id: i64, pub unprocessed_prior_op_before: i64, pub unprocessed_prior_op_after: i64, @@ -22,17 +23,20 @@ pub struct BlockDetails { #[sql_type = "BigInt"] pub block_number: i64, - #[sql_type = "Text"] - pub new_state_root: String, + #[sql_type = "Binary"] + #[serde(with = "BytesToHexSerde::")] + pub new_state_root: Vec, #[sql_type = "BigInt"] pub block_size: i64, - #[sql_type = "Nullable"] - pub commit_tx_hash: Option, + #[sql_type = "Nullable"] + #[serde(with = "OptionBytesToHexSerde::")] + pub commit_tx_hash: Option>, - #[sql_type = "Nullable"] - pub verify_tx_hash: Option, + #[sql_type = "Nullable"] + #[serde(with = "OptionBytesToHexSerde::")] + pub verify_tx_hash: Option>, #[sql_type = "Timestamp"] pub committed_at: NaiveDateTime, diff --git a/core/storage/src/chain/mempool/mod.rs b/core/storage/src/chain/mempool/mod.rs deleted file mode 100644 index 1dcf53fc3e..0000000000 --- a/core/storage/src/chain/mempool/mod.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Built-in deps -// External imports -use diesel::prelude::*; -// Workspace imports -// Local imports -use crate::schema::*; -use crate::{chain::operations_ext::records::InsertTx, StorageProcessor}; - -/// Mempool schema is an auxiliary structure encapsulating the interaction -/// with the mempool table. -/// -/// Note that there are no getters here, since the mempool table is used -/// mostly in joined form for read access. -#[derive(Debug)] -pub(crate) struct MempoolSchema<'a>(pub &'a StorageProcessor); - -impl<'a> MempoolSchema<'a> { - pub fn insert_tx(&self, tx: InsertTx) -> QueryResult<()> { - diesel::insert_into(mempool::table) - .values(tx) - .on_conflict_do_nothing() - .execute(self.0.conn())?; - Ok(()) - } -} diff --git a/core/storage/src/chain/mod.rs b/core/storage/src/chain/mod.rs index 669e44722d..f62a39d5da 100644 --- a/core/storage/src/chain/mod.rs +++ b/core/storage/src/chain/mod.rs @@ -1,6 +1,5 @@ pub mod account; pub mod block; -pub mod mempool; pub mod operations; pub mod operations_ext; pub mod state; diff --git a/core/storage/src/chain/operations/mod.rs b/core/storage/src/chain/operations/mod.rs index a4796f503e..24018f7955 100644 --- a/core/storage/src/chain/operations/mod.rs +++ b/core/storage/src/chain/operations/mod.rs @@ -62,8 +62,6 @@ impl<'a> OperationsSchema<'a> { } /// Stores the executed operation in the database. - /// Note: This method should only be called after the transaction is stored in - /// the `mempool` table, since `executed_transactions` has a foreign key relying on it. pub(crate) fn store_executed_operation( &self, operation: NewExecutedTransaction, diff --git a/core/storage/src/chain/operations/records.rs b/core/storage/src/chain/operations/records.rs index 6945739623..47afc6ab1b 100644 --- a/core/storage/src/chain/operations/records.rs +++ b/core/storage/src/chain/operations/records.rs @@ -3,22 +3,9 @@ use bigdecimal::BigDecimal; use chrono::prelude::*; use serde_json::value::Value; // Workspace imports -use models::node::{AccountId, BlockNumber, FranklinOp}; // Local imports use crate::schema::*; -#[derive(Debug, Clone, Insertable)] -#[table_name = "executed_priority_operations"] -pub struct NewExecutedPriorityOperation { - pub block_number: i64, - pub block_index: i32, - pub operation: Value, - pub priority_op_serialid: i64, - pub deadline_block: i64, - pub eth_fee: BigDecimal, - pub eth_hash: Vec, -} - #[derive(Debug, Clone, Insertable)] #[table_name = "operations"] pub struct NewOperation { @@ -36,13 +23,14 @@ pub struct StoredOperation { pub confirmed: bool, } -#[derive(Debug, Clone, Queryable, QueryableByName)] +#[derive(Debug, Clone, Insertable)] #[table_name = "executed_priority_operations"] -pub struct StoredExecutedPriorityOperation { - pub id: i32, +pub struct NewExecutedPriorityOperation { pub block_number: i64, pub block_index: i32, pub operation: Value, + pub from_account: Vec, + pub to_account: Vec, pub priority_op_serialid: i64, pub deadline_block: i64, pub eth_fee: BigDecimal, @@ -50,60 +38,49 @@ pub struct StoredExecutedPriorityOperation { } #[derive(Debug, Clone, Queryable, QueryableByName)] -#[table_name = "rollup_ops"] -pub struct StoredFranklinOp { +#[table_name = "executed_priority_operations"] +pub struct StoredExecutedPriorityOperation { pub id: i32, - pub block_num: i64, + pub block_number: i64, + pub block_index: i32, pub operation: Value, - pub fee_account: i64, + pub from_account: Vec, + pub to_account: Vec, + pub priority_op_serialid: i64, + pub deadline_block: i64, + pub eth_fee: BigDecimal, + pub eth_hash: Vec, } -impl StoredFranklinOp { - pub fn into_franklin_op(self) -> FranklinOp { - serde_json::from_value(self.operation).expect("Unparsable FranklinOp in db") - } -} #[derive(Debug, Clone, Insertable)] -#[table_name = "rollup_ops"] -pub struct NewFranklinOp { - pub block_num: i64, - pub operation: Value, - pub fee_account: i64, -} - -impl NewFranklinOp { - pub fn prepare_stored_op( - franklin_op: &FranklinOp, - block: BlockNumber, - fee_account: AccountId, - ) -> Self { - Self { - block_num: i64::from(block), - operation: serde_json::to_value(franklin_op.clone()).unwrap(), - fee_account: i64::from(fee_account), - } - } -} - -#[derive(Debug, Clone, Queryable, QueryableByName)] #[table_name = "executed_transactions"] -pub struct StoredExecutedTransaction { - pub id: i32, +pub struct NewExecutedTransaction { pub block_number: i64, + pub block_index: Option, + pub tx: Value, + pub operation: Value, pub tx_hash: Vec, - pub operation: Option, + pub from_account: Vec, + pub to_account: Option>, pub success: bool, pub fail_reason: Option, - pub block_index: Option, + pub primary_account_address: Vec, + pub nonce: i64, } -#[derive(Debug, Clone, Insertable)] +#[derive(Debug, Clone, Queryable, QueryableByName)] #[table_name = "executed_transactions"] -pub struct NewExecutedTransaction { +pub struct StoredExecutedTransaction { + pub id: i32, pub block_number: i64, + pub block_index: Option, + pub tx: Value, + pub operation: Value, pub tx_hash: Vec, - pub operation: Option, + pub from_account: Vec, + pub to_account: Option>, pub success: bool, pub fail_reason: Option, - pub block_index: Option, + pub primary_account_address: Vec, + pub nonce: i64, } diff --git a/core/storage/src/chain/operations_ext/mod.rs b/core/storage/src/chain/operations_ext/mod.rs index 858a693f69..1784db365a 100644 --- a/core/storage/src/chain/operations_ext/mod.rs +++ b/core/storage/src/chain/operations_ext/mod.rs @@ -2,14 +2,13 @@ // External imports use diesel::prelude::*; use itertools::Itertools; -use serde_json::value::Value; // Workspace imports use models::node::{Address, PubKeyHash, TokenId}; use models::ActionType; // Local imports use self::records::{ - AccountTransaction, PriorityOpReceiptResponse, ReadTx, TransactionsHistoryItem, - TxByHashResponse, TxReceiptResponse, + AccountTransaction, PriorityOpReceiptResponse, TransactionsHistoryItem, TxByHashResponse, + TxReceiptResponse, }; use crate::schema::*; use crate::tokens::TokensSchema; @@ -141,10 +140,7 @@ impl<'a> OperationsExtSchema<'a> { if let Some(tx) = tx { let block_number = tx.block_number; - let operation = tx.operation.unwrap_or_else(|| { - log::debug!("operation empty in executed_transactions"); - Value::default() - }); + let operation = tx.operation; let tx_type = operation["type"].as_str().unwrap_or("unknown type"); let tx_token = operation["tx"]["token"].as_i64().unwrap_or(-1); @@ -284,8 +280,6 @@ impl<'a> OperationsExtSchema<'a> { // TODO: txs are not ordered // This query does the following: - // - joins the `mempool` table (which contains the tx body) and - // the `executed_transaction` (which contains the tx header); // - creates a union of data above and the `executed_priority_operations` // - unifies the information to match the `TransactionsHistoryItem` // structure layout @@ -304,25 +298,22 @@ impl<'a> OperationsExtSchema<'a> { select * from ( + with vars (address_bytes) as ( select decode('{address}', 'hex') ) select tx, - 'sync-tx:' || encode(hash, 'hex') as hash, + 'sync-tx:' || encode(tx_hash, 'hex') as hash, null as pq_id, success, fail_reason, block_number from - mempool - left join - executed_transactions - on - tx_hash = hash + executed_transactions, vars where - tx->>'from' = '{address}' + from_account = address_bytes or - tx->>'to' = '{address}' + to_account = address_bytes or - tx->>'account' = '{address}' + primary_account_address = address_bytes union all select operation as tx, @@ -332,15 +323,11 @@ impl<'a> OperationsExtSchema<'a> { null as fail_reason, block_number from - executed_priority_operations + executed_priority_operations, vars where - operation->'priority_op'->>'from' = '{address}' - or - operation->'priority_op'->>'to' = '{address}' - or - operation->'priority_op'->>'account' = '{address}' + from_account = address_bytes or - operation->'priority_op'->>'eth_address' = '{address}') t + to_account = address_bytes) t order by block_number desc offset @@ -365,7 +352,7 @@ impl<'a> OperationsExtSchema<'a> { using (block_number) ", - address = format!("{:#?}", address), + address = hex::encode(address.as_ref().to_vec()), offset = offset, limit = limit ); @@ -411,40 +398,29 @@ impl<'a> OperationsExtSchema<'a> { &self, address: &PubKeyHash, ) -> QueryResult> { - let all_txs: Vec<_> = mempool::table - .filter(mempool::primary_account_address.eq(address.data.to_vec())) - .left_join( - executed_transactions::table.on(executed_transactions::tx_hash.eq(mempool::hash)), - ) + let all_txs: Vec<_> = executed_transactions::table + .filter(executed_transactions::primary_account_address.eq(address.data.to_vec())) .left_join( operations::table .on(operations::block_number.eq(executed_transactions::block_number)), ) - .load::<( - ReadTx, - Option, - Option, - )>(self.0.conn())?; + .load::<(StoredExecutedTransaction, Option)>(self.0.conn())?; let res = all_txs .into_iter() - .group_by(|(mempool_tx, _, _)| mempool_tx.hash.clone()) + .group_by(|(stored_tx, _)| stored_tx.tx_hash.clone()) .into_iter() .map(|(_op_id, mut group_iter)| { // TODO: replace the query with pivot - let (mempool_tx, executed_tx, operation) = group_iter.next().unwrap(); + let (executed_tx, operation) = group_iter.next().unwrap(); let mut res = AccountTransaction { - tx: mempool_tx.tx, - tx_hash: hex::encode(mempool_tx.hash.as_slice()), - success: false, - fail_reason: None, + tx: executed_tx.operation, + tx_hash: hex::encode(executed_tx.tx_hash.as_slice()), + success: executed_tx.success, + fail_reason: executed_tx.fail_reason, committed: false, verified: false, }; - if let Some(executed_tx) = executed_tx { - res.success = executed_tx.success; - res.fail_reason = executed_tx.fail_reason; - } if let Some(operation) = operation { if operation.action_type == ActionType::COMMIT.to_string() { res.committed = operation.confirmed; @@ -452,7 +428,7 @@ impl<'a> OperationsExtSchema<'a> { res.verified = operation.confirmed; } } - if let Some((_mempool_tx, _executed_tx, operation)) = group_iter.next() { + if let Some((_executed_tx, operation)) = group_iter.next() { if let Some(operation) = operation { if operation.action_type == ActionType::COMMIT.to_string() { res.committed = operation.confirmed; diff --git a/core/storage/src/chain/operations_ext/records.rs b/core/storage/src/chain/operations_ext/records.rs index 25faeafbc3..31b8bb6fd4 100644 --- a/core/storage/src/chain/operations_ext/records.rs +++ b/core/storage/src/chain/operations_ext/records.rs @@ -1,12 +1,10 @@ // External imports -use chrono::prelude::*; use diesel::sql_types::{BigInt, Bool, Int4, Jsonb, Nullable, Text}; use serde_derive::{Deserialize, Serialize}; use serde_json::value::Value; // Workspace imports // Local imports use crate::prover::records::ProverRun; -use crate::schema::*; #[derive(Debug, Serialize, Deserialize)] pub struct AccountTransaction { @@ -18,24 +16,6 @@ pub struct AccountTransaction { pub verified: bool, } -#[derive(Debug, Insertable)] -#[table_name = "mempool"] -pub struct InsertTx { - pub hash: Vec, - pub primary_account_address: Vec, - pub nonce: i64, - pub tx: Value, -} - -#[derive(Debug, Queryable)] -pub struct ReadTx { - pub hash: Vec, - pub primary_account_address: Vec, - pub nonce: i64, - pub tx: Value, - pub created_at: NaiveDateTime, -} - #[derive(Debug, Serialize, Deserialize, QueryableByName)] pub struct TransactionsHistoryItem { #[sql_type = "Nullable"] diff --git a/core/storage/src/chain/state/mod.rs b/core/storage/src/chain/state/mod.rs index a16225d307..69670d07f1 100644 --- a/core/storage/src/chain/state/mod.rs +++ b/core/storage/src/chain/state/mod.rs @@ -7,7 +7,6 @@ use diesel::prelude::*; use models::node::PubKeyHash; use models::node::{apply_updates, reverse_updates, AccountMap, AccountUpdate, AccountUpdates}; // Local imports -use self::records::{NewBlockEvent, NewStorageState, StoredBlockEvent, StoredStorageState}; use crate::chain::{ account::{ records::{ @@ -23,8 +22,6 @@ use crate::diff::StorageAccountDiff; use crate::schema::*; use crate::StorageProcessor; -pub mod records; - /// State schema is capable of managing... well, the state of the chain. /// /// This roughly includes the two main topics: @@ -417,46 +414,4 @@ impl<'a> StateSchema<'a> { self.load_state_diff(block_number - 1, Some(block_number)) .map(|diff| diff.unwrap_or_default().1) } - - pub fn load_committed_events_state(&self) -> QueryResult> { - let events = events_state::table - .filter(events_state::block_type.eq("Committed".to_string())) - .order(events_state::block_num.asc()) - .load::(self.0.conn())?; - Ok(events) - } - - pub fn load_verified_events_state(&self) -> QueryResult> { - let events = events_state::table - .filter(events_state::block_type.eq("Verified".to_string())) - .order(events_state::block_num.asc()) - .load::(self.0.conn())?; - Ok(events) - } - - pub fn load_storage_state(&self) -> QueryResult { - storage_state_update::table.first(self.0.conn()) - } - - pub(crate) fn update_storage_state(&self, state: NewStorageState) -> QueryResult<()> { - self.0.conn().transaction(|| { - diesel::delete(storage_state_update::table).execute(self.0.conn())?; - diesel::insert_into(storage_state_update::table) - .values(state) - .execute(self.0.conn())?; - Ok(()) - }) - } - - pub(crate) fn update_block_events(&self, events: &[NewBlockEvent]) -> QueryResult<()> { - self.0.conn().transaction(|| { - diesel::delete(events_state::table).execute(self.0.conn())?; - for event in events.iter() { - diesel::insert_into(events_state::table) - .values(event) - .execute(self.0.conn())?; - } - Ok(()) - }) - } } diff --git a/core/storage/src/chain/state/records.rs b/core/storage/src/chain/state/records.rs deleted file mode 100644 index 359ab999b6..0000000000 --- a/core/storage/src/chain/state/records.rs +++ /dev/null @@ -1,35 +0,0 @@ -// External imports -use serde_derive::{Deserialize, Serialize}; -// Workspace imports -// Local imports -use crate::schema::*; - -#[derive(Debug, Insertable)] -#[table_name = "storage_state_update"] -pub struct NewStorageState { - pub storage_state: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Queryable, QueryableByName)] -#[table_name = "storage_state_update"] -pub struct StoredStorageState { - pub id: i32, - pub storage_state: String, -} - -#[derive(Debug, Insertable)] -#[table_name = "events_state"] -pub struct NewBlockEvent { - pub block_type: String, // 'Committed', 'Verified' - pub transaction_hash: Vec, - pub block_num: i64, -} - -#[derive(Debug, Clone, Insertable, Serialize, Deserialize, Queryable, QueryableByName)] -#[table_name = "events_state"] -pub struct StoredBlockEvent { - pub id: i32, - pub block_type: String, // 'Committed', 'Verified' - pub transaction_hash: Vec, - pub block_num: i64, -} diff --git a/core/storage/src/data_restore/mod.rs b/core/storage/src/data_restore/mod.rs index ce408e68d4..7a68728e54 100644 --- a/core/storage/src/data_restore/mod.rs +++ b/core/storage/src/data_restore/mod.rs @@ -1,5 +1,6 @@ // Built-in deps // External imports +use diesel::dsl::update; use diesel::prelude::*; use itertools::Itertools; // Workspace imports @@ -8,17 +9,13 @@ use models::node::{AccountId, AccountUpdate, BlockNumber, FranklinOp, Token}; use models::{Operation, TokenAddedEvent}; // Local imports use self::records::{ - NewLastWatchedEthBlockNumber, StoredLastWatchedEthBlockNumber, StoredRollupOpsBlock, + NewBlockEvent, NewFranklinOp, NewLastWatchedEthBlockNumber, NewStorageState, StoredBlockEvent, + StoredFranklinOp, StoredLastWatchedEthBlockNumber, StoredRollupOpsBlock, StoredStorageState, }; use crate::schema::*; use crate::StorageProcessor; use crate::{ - chain::{ - block::BlockSchema, - operations::records::{NewFranklinOp, StoredFranklinOp}, - state::records::{NewBlockEvent, NewStorageState}, - state::StateSchema, - }, + chain::{block::BlockSchema, state::StateSchema}, tokens::TokensSchema, }; @@ -35,7 +32,7 @@ impl<'a> DataRestoreSchema<'a> { pub fn save_block_transactions(&self, block: Block) -> QueryResult<()> { self.0.conn().transaction(|| { BlockSchema(self.0).save_block_transactions(block)?; - StateSchema(self.0).update_storage_state(self.new_storage_state("None"))?; + self.update_storage_state(self.new_storage_state("None"))?; Ok(()) }) } @@ -46,47 +43,17 @@ impl<'a> DataRestoreSchema<'a> { verify_op: Operation, ) -> QueryResult<()> { self.0.conn().transaction(|| { - BlockSchema(self.0).execute_operation(commit_op)?; - BlockSchema(self.0).execute_operation(verify_op)?; - StateSchema(self.0).update_storage_state(self.new_storage_state("None"))?; - Ok(()) - }) - } - - pub fn save_events_state( - &self, - block_events: &[NewBlockEvent], - token_events: &[TokenAddedEvent], - last_watched_eth_number: &NewLastWatchedEthBlockNumber, - ) -> QueryResult<()> { - self.0.conn().transaction(|| { - StateSchema(self.0).update_block_events(block_events)?; - - for &TokenAddedEvent { id, address } in token_events.iter() { - let token = Token::new(id, address, &format!("ERC20-{}", id)); - TokensSchema(self.0).store_token(token)?; - } - - self.update_last_watched_block_number(last_watched_eth_number)?; - StateSchema(self.0).update_storage_state(self.new_storage_state("Events"))?; - - Ok(()) - }) - } - - pub fn save_rollup_ops( - &self, - ops: &[(BlockNumber, &FranklinOp, AccountId)], - ) -> QueryResult<()> { - self.0.conn().transaction(|| { - diesel::delete(rollup_ops::table).execute(self.0.conn())?; - for op in ops.iter() { - let stored_op = NewFranklinOp::prepare_stored_op(&op.1, op.0, op.2); - diesel::insert_into(rollup_ops::table) - .values(&stored_op) - .execute(self.0.conn())?; - } - StateSchema(self.0).update_storage_state(self.new_storage_state("Operations"))?; + let commit_op = BlockSchema(self.0).execute_operation(commit_op)?; + let verify_op = BlockSchema(self.0).execute_operation(verify_op)?; + update( + operations::table.filter( + operations::id.eq_any(vec![commit_op.id.unwrap(), verify_op.id.unwrap()]), + ), + ) + .set(operations::confirmed.eq(true)) + .execute(self.0.conn()) + .map(drop)?; + self.update_storage_state(self.new_storage_state("None"))?; Ok(()) }) } @@ -100,8 +67,8 @@ impl<'a> DataRestoreSchema<'a> { } pub fn load_rollup_ops_blocks(&self) -> QueryResult> { - let stored_operations = rollup_ops::table - .order(rollup_ops::id.asc()) + let stored_operations = data_restore_rollup_ops::table + .order(data_restore_rollup_ops::id.asc()) .load::(self.0.conn())?; let ops_blocks: Vec = stored_operations .into_iter() @@ -153,4 +120,105 @@ impl<'a> DataRestoreSchema<'a> { storage_state: state.to_string(), } } + + pub fn save_events_state( + &self, + block_events: &[NewBlockEvent], + token_events: &[TokenAddedEvent], + last_watched_eth_number: &NewLastWatchedEthBlockNumber, + ) -> QueryResult<()> { + self.0.conn().transaction(|| { + self.update_block_events(block_events)?; + + for &TokenAddedEvent { id, address } in token_events.iter() { + let token = Token::new(id, address, &format!("ERC20-{}", id)); + TokensSchema(self.0).store_token(token)?; + } + + self.update_last_watched_block_number(last_watched_eth_number)?; + self.update_storage_state(self.new_storage_state("Events"))?; + + Ok(()) + }) + } + + pub fn save_rollup_ops( + &self, + ops: &[(BlockNumber, &FranklinOp, AccountId)], + ) -> QueryResult<()> { + self.0.conn().transaction(|| { + diesel::delete(data_restore_rollup_ops::table).execute(self.0.conn())?; + for op in ops.iter() { + let stored_op = NewFranklinOp::prepare_stored_op(&op.1, op.0, op.2); + diesel::insert_into(data_restore_rollup_ops::table) + .values(&stored_op) + .execute(self.0.conn())?; + } + self.update_storage_state(self.new_storage_state("Operations"))?; + Ok(()) + }) + } + + /// Method that initializes the `eth_stats` table. + /// Since `eth_sender` module uses this table to identify the expected next block numbers + /// for sending operations to the Ethereum, we must initialize it with actual values. + pub fn initialize_eth_stats( + &self, + last_committed_block: BlockNumber, + last_verified_block: BlockNumber, + ) -> QueryResult<()> { + // Withdraw ops counter is set equal to the `verify` ops counter + // since we assume that we've sent a withdraw for every `verify` op. + update(eth_stats::table.filter(eth_stats::id.eq(true))) + .set(( + eth_stats::commit_ops.eq(last_committed_block as i64), + eth_stats::verify_ops.eq(last_verified_block as i64), + eth_stats::withdraw_ops.eq(last_verified_block as i64), + )) + .execute(self.0.conn())?; + + Ok(()) + } + + pub fn load_committed_events_state(&self) -> QueryResult> { + let events = data_restore_events_state::table + .filter(data_restore_events_state::block_type.eq("Committed".to_string())) + .order(data_restore_events_state::block_num.asc()) + .load::(self.0.conn())?; + Ok(events) + } + + pub fn load_verified_events_state(&self) -> QueryResult> { + let events = data_restore_events_state::table + .filter(data_restore_events_state::block_type.eq("Verified".to_string())) + .order(data_restore_events_state::block_num.asc()) + .load::(self.0.conn())?; + Ok(events) + } + + pub fn load_storage_state(&self) -> QueryResult { + data_restore_storage_state_update::table.first(self.0.conn()) + } + + pub(crate) fn update_storage_state(&self, state: NewStorageState) -> QueryResult<()> { + self.0.conn().transaction(|| { + diesel::delete(data_restore_storage_state_update::table).execute(self.0.conn())?; + diesel::insert_into(data_restore_storage_state_update::table) + .values(state) + .execute(self.0.conn())?; + Ok(()) + }) + } + + pub(crate) fn update_block_events(&self, events: &[NewBlockEvent]) -> QueryResult<()> { + self.0.conn().transaction(|| { + diesel::delete(data_restore_events_state::table).execute(self.0.conn())?; + for event in events.iter() { + diesel::insert_into(data_restore_events_state::table) + .values(event) + .execute(self.0.conn())?; + } + Ok(()) + }) + } } diff --git a/core/storage/src/data_restore/records.rs b/core/storage/src/data_restore/records.rs index 8acab6d8a2..3778a0022b 100644 --- a/core/storage/src/data_restore/records.rs +++ b/core/storage/src/data_restore/records.rs @@ -1,4 +1,5 @@ // External imports +use serde_json::Value; // Workspace imports use models::node::{AccountId, BlockNumber, FranklinOp}; use serde_derive::{Deserialize, Serialize}; @@ -25,3 +26,69 @@ pub struct StoredLastWatchedEthBlockNumber { pub id: i32, pub block_number: String, } + +#[derive(Debug, Clone, Queryable, QueryableByName)] +#[table_name = "data_restore_rollup_ops"] +pub struct StoredFranklinOp { + pub id: i32, + pub block_num: i64, + pub operation: Value, + pub fee_account: i64, +} + +impl StoredFranklinOp { + pub fn into_franklin_op(self) -> FranklinOp { + serde_json::from_value(self.operation).expect("Unparsable FranklinOp in db") + } +} +#[derive(Debug, Clone, Insertable)] +#[table_name = "data_restore_rollup_ops"] +pub struct NewFranklinOp { + pub block_num: i64, + pub operation: Value, + pub fee_account: i64, +} + +impl NewFranklinOp { + pub fn prepare_stored_op( + franklin_op: &FranklinOp, + block: BlockNumber, + fee_account: AccountId, + ) -> Self { + Self { + block_num: i64::from(block), + operation: serde_json::to_value(franklin_op.clone()).unwrap(), + fee_account: i64::from(fee_account), + } + } +} + +#[derive(Debug, Insertable)] +#[table_name = "data_restore_storage_state_update"] +pub struct NewStorageState { + pub storage_state: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, Queryable, QueryableByName)] +#[table_name = "data_restore_storage_state_update"] +pub struct StoredStorageState { + pub id: i32, + pub storage_state: String, +} + +#[derive(Debug, Insertable)] +#[table_name = "data_restore_events_state"] +pub struct NewBlockEvent { + pub block_type: String, // 'Committed', 'Verified' + pub transaction_hash: Vec, + pub block_num: i64, +} + +#[derive(Debug, Clone, Insertable, Serialize, Deserialize, Queryable, QueryableByName)] +#[table_name = "data_restore_events_state"] +pub struct StoredBlockEvent { + pub id: i32, + pub block_type: String, // 'Committed', 'Verified' + pub transaction_hash: Vec, + pub block_num: i64, +} diff --git a/core/storage/src/leader_election/mod.rs b/core/storage/src/leader_election/mod.rs new file mode 100644 index 0000000000..e53a103d90 --- /dev/null +++ b/core/storage/src/leader_election/mod.rs @@ -0,0 +1,59 @@ +// Built-in deps +// External imports +use diesel::prelude::*; +// Local imports +use crate::schema::leader_election; +use crate::schema::leader_election::dsl; +use crate::StorageProcessor; +use chrono::{NaiveDateTime, Utc}; + +pub mod records; + +/// Schema for election for a leader position and getting current leader. +#[derive(Debug)] +pub struct LeaderElectionSchema<'a>(pub &'a StorageProcessor); + +impl<'a> LeaderElectionSchema<'a> { + /// Inserts a new candidate to the leader election table to become leader if all who was before bail. + pub fn place_candidate(&self, name: &str) -> QueryResult<()> { + let name = name.to_owned(); + // At this point of time the candidate must be the last to be leader within all active candidates. + // In case of system inadequate behavior it is possible that candidate was placed to leader election table + // and replica is restarted without bailing. To ensure correct order of leader election, candidate needs to bail all + // previous placements before placing again. + self.bail(&name, None)?; + diesel::insert_into(leader_election::table) + .values(&records::NewLeaderElection { name }) + .execute(self.0.conn())?; + Ok(()) + } + + /// Returns current leader name. + /// Current leader is the longest waiting candidate in leader election table. + pub fn current_leader(&self) -> QueryResult> { + leader_election::table + .filter(dsl::bail_at.is_null()) + .order_by(dsl::created_at.asc()) + .first(self.0.conn()) + .optional() + } + + /// Bails candidate with given name. If `until` is None, assumes to bail all records, otherwise + /// bails records created before or at the same time. + pub fn bail(&self, name: &str, until: Option) -> QueryResult<()> { + let datetime = if let Some(datetime) = until { + datetime + } else { + let now = Utc::now(); + NaiveDateTime::from_timestamp(now.timestamp(), now.timestamp_subsec_nanos()) + }; + let query = leader_election::table + .filter(dsl::bail_at.is_null()) + .filter(dsl::name.eq(name.to_owned())) + .filter(dsl::created_at.le(datetime)); + diesel::update(query) + .set(dsl::bail_at.eq(diesel::dsl::now)) + .execute(self.0.conn())?; + Ok(()) + } +} diff --git a/core/storage/src/leader_election/records.rs b/core/storage/src/leader_election/records.rs new file mode 100644 index 0000000000..f335189ea5 --- /dev/null +++ b/core/storage/src/leader_election/records.rs @@ -0,0 +1,20 @@ +// External imports +use chrono::prelude::*; +// Workspace imports +// Local imports +use crate::schema::*; + +#[derive(Debug, Clone, Queryable, QueryableByName, PartialEq)] +#[table_name = "leader_election"] +pub struct LeaderElection { + pub id: i32, + pub name: String, + pub created_at: NaiveDateTime, + pub bail_at: Option, +} + +#[derive(Debug, Clone, Insertable, PartialEq)] +#[table_name = "leader_election"] +pub struct NewLeaderElection { + pub name: String, +} diff --git a/core/storage/src/lib.rs b/core/storage/src/lib.rs index e7cd8dc67f..9d02edcfdc 100644 --- a/core/storage/src/lib.rs +++ b/core/storage/src/lib.rs @@ -41,7 +41,6 @@ //! //! - account, for storing and loading account data. //! - block, the main one, which implements the logic of the block creation. -//! - mempool, the auxiliary wrapper over a mempool table. //! - operations, the transactions storage. //! - operations_ext, a set of getters for the operations, more specific and convenient to use than operations has. //! - state, basically the sidechain state manager (which includes the applying of the state changes). @@ -93,8 +92,10 @@ pub mod connection; pub mod data_restore; pub mod diff; pub mod ethereum; +pub mod leader_election; pub mod prover; pub mod tokens; +pub mod utils; pub use crate::connection::ConnectionPool; @@ -157,6 +158,11 @@ impl StorageProcessor { tokens::TokensSchema(self) } + // Gains access to the `LeaderElection` schema. + pub fn leader_election_schema(&self) -> leader_election::LeaderElectionSchema<'_> { + leader_election::LeaderElectionSchema(self) + } + /// Performs several database operations within one database transaction. pub fn transaction(&self, f: F) -> Result where diff --git a/core/storage/src/schema.rs b/core/storage/src/schema.rs index 39a42551e3..2e74877251 100644 --- a/core/storage/src/schema.rs +++ b/core/storage/src/schema.rs @@ -67,7 +67,7 @@ table! { table! { blocks (number) { number -> Int8, - root_hash -> Text, + root_hash -> Bytea, fee_account_id -> Int8, unprocessed_prior_op_before -> Int8, unprocessed_prior_op_after -> Int8, @@ -75,6 +75,15 @@ table! { } } +table! { + data_restore_events_state (id) { + id -> Int4, + block_type -> Text, + transaction_hash -> Bytea, + block_num -> Int8, + } +} + table! { data_restore_last_watched_eth_block (id) { id -> Int4, @@ -82,6 +91,22 @@ table! { } } +table! { + data_restore_rollup_ops (id) { + id -> Int4, + block_num -> Int8, + operation -> Jsonb, + fee_account -> Int8, + } +} + +table! { + data_restore_storage_state_update (id) { + id -> Int4, + storage_state -> Text, + } +} + table! { eth_nonce (id) { id -> Bool, @@ -127,21 +152,14 @@ table! { } } -table! { - events_state (id) { - id -> Int4, - block_type -> Text, - transaction_hash -> Bytea, - block_num -> Int8, - } -} - table! { executed_priority_operations (id) { id -> Int4, block_number -> Int8, block_index -> Int4, operation -> Jsonb, + from_account -> Bytea, + to_account -> Bytea, priority_op_serialid -> Int8, deadline_block -> Int8, eth_fee -> Numeric, @@ -153,28 +171,16 @@ table! { executed_transactions (id) { id -> Int4, block_number -> Int8, + block_index -> Nullable, + tx -> Jsonb, + operation -> Jsonb, tx_hash -> Bytea, - operation -> Nullable, + from_account -> Bytea, + to_account -> Nullable, success -> Bool, fail_reason -> Nullable, - block_index -> Nullable, - } -} - -table! { - mempool (hash) { - hash -> Bytea, primary_account_address -> Bytea, nonce -> Int8, - tx -> Jsonb, - created_at -> Timestamp, - } -} - -table! { - op_config (addr) { - addr -> Text, - next_nonce -> Nullable, } } @@ -206,15 +212,6 @@ table! { } } -table! { - rollup_ops (id) { - id -> Int4, - block_num -> Int8, - operation -> Jsonb, - fee_account -> Int8, - } -} - table! { server_config (id) { id -> Bool, @@ -224,17 +221,19 @@ table! { } table! { - storage_state_update (id) { + tokens (id) { id -> Int4, - storage_state -> Text, + address -> Text, + symbol -> Text, } } table! { - tokens (id) { + leader_election (id) { id -> Int4, - address -> Text, - symbol -> Text, + name -> Text, + created_at -> Timestamp, + bail_at -> Nullable, } } @@ -244,7 +243,6 @@ joinable!(balances -> tokens (coin_id)); joinable!(eth_ops_binding -> eth_operations (eth_op_id)); joinable!(eth_ops_binding -> operations (op_id)); joinable!(eth_tx_hashes -> eth_operations (eth_op_id)); -joinable!(executed_transactions -> mempool (tx_hash)); allow_tables_to_appear_in_same_query!( account_balance_updates, @@ -254,22 +252,21 @@ allow_tables_to_appear_in_same_query!( active_provers, balances, blocks, + data_restore_events_state, data_restore_last_watched_eth_block, + data_restore_rollup_ops, + data_restore_storage_state_update, eth_nonce, eth_operations, eth_ops_binding, eth_stats, eth_tx_hashes, - events_state, executed_priority_operations, executed_transactions, - mempool, - op_config, operations, proofs, prover_runs, - rollup_ops, server_config, - storage_state_update, tokens, + leader_election, ); diff --git a/core/storage/src/tests/chain/block.rs b/core/storage/src/tests/chain/block.rs index 9b6de46132..3ff61c22db 100644 --- a/core/storage/src/tests/chain/block.rs +++ b/core/storage/src/tests/chain/block.rs @@ -3,7 +3,7 @@ use web3::types::H256; // Workspace imports use crypto_exports::rand::XorShiftRng; use models::node::{apply_updates, block::Block, AccountMap, AccountUpdate, BlockNumber, Fr}; -use models::{ethereum::OperationType, Action, Operation}; +use models::{ethereum::OperationType, fe_to_bytes, Action, Operation}; // Local imports use super::utils::{acc_create_random_updates, get_operation}; use crate::tests::{create_rng, db_test}; @@ -151,15 +151,11 @@ fn find_block_by_height_or_hash() { ) -> diesel::QueryResult<()> { let mut queries = vec![ expected_block_detail.block_number.to_string(), - expected_block_detail.new_state_root.clone(), - expected_block_detail - .commit_tx_hash - .as_ref() - .unwrap() - .clone(), + hex::encode(&expected_block_detail.new_state_root), + hex::encode(&expected_block_detail.commit_tx_hash.as_ref().unwrap()), ]; if let Some(verify_tx_hash) = expected_block_detail.verify_tx_hash.as_ref() { - queries.push(verify_tx_hash.clone()); + queries.push(hex::encode(&verify_tx_hash)); } for query in queries { @@ -248,10 +244,9 @@ fn find_block_by_height_or_hash() { // Initialize reference sample fields. current_block_detail.block_number = operation.block.block_number as i64; - current_block_detail.new_state_root = - format!("sync-bl:{}", operation.block.new_root_hash.to_hex()); + current_block_detail.new_state_root = fe_to_bytes(&operation.block.new_root_hash); current_block_detail.block_size = operation.block.block_transactions.len() as i64; - current_block_detail.commit_tx_hash = Some(format!("0x{}", hex::encode(eth_tx_hash))); + current_block_detail.commit_tx_hash = Some(eth_tx_hash.as_ref().to_vec()); // Add verification for the block if required. if block_number <= n_verified { @@ -279,8 +274,7 @@ fn find_block_by_height_or_hash() { )?; EthereumSchema(&conn).add_hash_entry(response.id, ð_tx_hash)?; EthereumSchema(&conn).confirm_eth_tx(ð_tx_hash)?; - current_block_detail.verify_tx_hash = - Some(format!("0x{}", hex::encode(eth_tx_hash))); + current_block_detail.verify_tx_hash = Some(eth_tx_hash.as_ref().to_vec()); } } @@ -452,17 +446,17 @@ fn load_commits_after_block() { }, Vec::new(), ))?; - ProverSchema(&conn).store_proof(2, &Default::default())?; + ProverSchema(&conn).store_proof(3, &Default::default())?; // Now test the method. let empty_vec = vec![]; let test_vector = vec![ // Blocks 2 & 3. - ((1, 2), &operations[1..3], vec![true, false]), + ((1, 2), &operations[1..3], vec![false, true]), // Block 2. - ((1, 1), &operations[1..2], vec![true]), + ((1, 1), &operations[1..2], vec![false]), // Block 3. - ((2, 1), &operations[2..3], vec![false]), + ((2, 1), &operations[2..3], vec![true]), // No block (there are no blocks AFTER block 3. ((3, 1), &empty_vec, vec![]), // Obviously none. diff --git a/core/storage/src/tests/chain/operations.rs b/core/storage/src/tests/chain/operations.rs index 020d362a75..4b6775fc3f 100644 --- a/core/storage/src/tests/chain/operations.rs +++ b/core/storage/src/tests/chain/operations.rs @@ -4,13 +4,9 @@ use models::ActionType; // Local imports use crate::tests::db_test; use crate::{ - chain::{ - mempool::MempoolSchema, - operations::{ - records::{NewExecutedPriorityOperation, NewExecutedTransaction, NewOperation}, - OperationsSchema, - }, - operations_ext::records::InsertTx, + chain::operations::{ + records::{NewExecutedPriorityOperation, NewExecutedTransaction, NewOperation}, + OperationsSchema, }, StorageProcessor, }; @@ -49,21 +45,16 @@ fn executed_operations() { let executed_tx = NewExecutedTransaction { block_number: 1, tx_hash: vec![0xDE, 0xAD, 0xBE, 0xEF], - operation: None, + tx: Default::default(), + operation: Default::default(), + from_account: Default::default(), + to_account: None, success: true, fail_reason: None, block_index: None, - }; - - // We have to store the transaction in mempool before storing it - // as executed. - let mempool_tx = InsertTx { - hash: executed_tx.tx_hash.clone(), primary_account_address: Default::default(), nonce: Default::default(), - tx: Default::default(), }; - MempoolSchema(&conn).insert_tx(mempool_tx)?; OperationsSchema(&conn).store_executed_operation(executed_tx.clone())?; @@ -73,10 +64,18 @@ fn executed_operations() { assert_eq!(stored_operation.block_number, executed_tx.block_number); assert_eq!(stored_operation.tx_hash, executed_tx.tx_hash); + assert_eq!(stored_operation.tx, executed_tx.tx); assert_eq!(stored_operation.operation, executed_tx.operation); + assert_eq!(stored_operation.from_account, executed_tx.from_account); + assert_eq!(stored_operation.to_account, executed_tx.to_account); assert_eq!(stored_operation.success, executed_tx.success); assert_eq!(stored_operation.fail_reason, executed_tx.fail_reason); assert_eq!(stored_operation.block_index, executed_tx.block_index); + assert_eq!(stored_operation.nonce, executed_tx.nonce); + assert_eq!( + stored_operation.primary_account_address, + executed_tx.primary_account_address + ); Ok(()) }); @@ -92,6 +91,8 @@ fn executed_priority_operations() { block_number: 1, block_index: 1, operation: Default::default(), + from_account: Default::default(), + to_account: Default::default(), priority_op_serialid: 0, deadline_block: 100, eth_fee: Default::default(), @@ -106,6 +107,8 @@ fn executed_priority_operations() { assert_eq!(stored_operation.block_number, executed_tx.block_number); assert_eq!(stored_operation.block_index, executed_tx.block_index); assert_eq!(stored_operation.operation, executed_tx.operation); + assert_eq!(stored_operation.from_account, executed_tx.from_account); + assert_eq!(stored_operation.to_account, executed_tx.to_account); assert_eq!( stored_operation.priority_op_serialid, executed_tx.priority_op_serialid diff --git a/core/storage/src/tests/chain/operations_ext.rs b/core/storage/src/tests/chain/operations_ext.rs index 55ca06d923..375979a75f 100644 --- a/core/storage/src/tests/chain/operations_ext.rs +++ b/core/storage/src/tests/chain/operations_ext.rs @@ -284,7 +284,6 @@ fn get_account_transactions_history() { let tx_token = tx_info["token"].as_str().map(String::from); let tx_amount = tx_info["amount"].as_str().map(String::from); - println!("tx_type: {} info: {:#?}", tx_type, tx_info); assert_eq!(tx_from_addr, *from); assert_eq!(tx_to_addr, *to); assert_eq!(tx_token, *token); diff --git a/core/storage/src/tests/leader_election.rs b/core/storage/src/tests/leader_election.rs new file mode 100644 index 0000000000..e3d863d2f2 --- /dev/null +++ b/core/storage/src/tests/leader_election.rs @@ -0,0 +1,41 @@ +// Built-in +// External imports +// Workspace imports +// Local imports +use crate::tests::db_test; +use crate::StorageProcessor; + +#[test] +#[cfg_attr(not(feature = "db_test"), ignore)] +fn leader_election() { + let conn = StorageProcessor::establish_connection().unwrap(); + db_test(conn.conn(), || { + conn.leader_election_schema().place_candidate("foo")?; + assert_eq!( + conn.leader_election_schema() + .current_leader()? + .unwrap() + .name, + "foo".to_owned() + ); + conn.leader_election_schema().place_candidate("bar")?; + assert_eq!( + &conn + .leader_election_schema() + .current_leader()? + .unwrap() + .name, + "foo" + ); + conn.leader_election_schema().bail("foo", None).unwrap(); + assert_eq!( + &conn + .leader_election_schema() + .current_leader()? + .unwrap() + .name, + "bar" + ); + Ok(()) + }); +} diff --git a/core/storage/src/tests/mod.rs b/core/storage/src/tests/mod.rs index 0de6337de5..71a0d831f6 100644 --- a/core/storage/src/tests/mod.rs +++ b/core/storage/src/tests/mod.rs @@ -34,6 +34,7 @@ mod chain; mod config; mod data_restore; mod ethereum; +mod leader_election; mod prover; mod tokens; diff --git a/core/storage/src/utils.rs b/core/storage/src/utils.rs new file mode 100644 index 0000000000..d00dee530a --- /dev/null +++ b/core/storage/src/utils.rs @@ -0,0 +1,113 @@ +//! Utils used in storage crate + +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +/// Trait for specifying prefix for bytes to hex serialization +pub trait Prefix { + fn prefix() -> &'static str; +} + +/// "sync-bl:" hex prefix +pub struct SyncBlockPrefix; +impl Prefix for SyncBlockPrefix { + fn prefix() -> &'static str { + "sync-bl:" + } +} + +/// "0x" hex prefix +pub struct ZeroxPrefix; +impl Prefix for ZeroxPrefix { + fn prefix() -> &'static str { + "0x" + } +} + +/// "sync-tx:" hex prefix +pub struct SyncTxPrefix; +impl Prefix for SyncTxPrefix { + fn prefix() -> &'static str { + "sync-tx:" + } +} + +/// Used to annotate `Vec` fields that you want to serialize like hex-encoded string with prefix +/// Use this struct in annotation like that `[serde(with = BytesToHexSerde::]` +/// where T is concrete prefix type (e.g. `SyncBlockPrefix`) +pub struct BytesToHexSerde

{ + _marker: std::marker::PhantomData

, +} + +impl BytesToHexSerde

{ + pub fn serialize(value: &[u8], serializer: S) -> Result + where + S: Serializer, + { + // First, serialize `Fr` to hexadecimal string. + let hex_value = format!("{}{}", P::prefix(), hex::encode(value)); + + // Then, serialize it using `Serialize` trait implementation for `String`. + String::serialize(&hex_value, serializer) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + let deserialized_string = String::deserialize(deserializer)?; + + if deserialized_string.starts_with(P::prefix()) { + hex::decode(&deserialized_string[P::prefix().len()..]).map_err(de::Error::custom) + } else { + Err(de::Error::custom(format!( + "string value missing prefix: {}", + P::prefix() + ))) + } + } +} + +/// Used to annotate `Option>` fields that you want to serialize like hex-encoded string with prefix +/// Use this struct in annotation like that `[serde(with = OptionBytesToHexSerde::]` +/// where T is concrete prefix type (e.g. `SyncBlockPrefix`) +pub struct OptionBytesToHexSerde

{ + _marker: std::marker::PhantomData

, +} + +impl OptionBytesToHexSerde

{ + pub fn serialize(value: &Option>, serializer: S) -> Result + where + S: Serializer, + { + // First, serialize `Fr` to hexadecimal string. + let hex_value = value + .as_ref() + .map(|val| format!("{}{}", P::prefix(), hex::encode(val))); + + // Then, serialize it using `Serialize` trait implementation for `String`. + Option::serialize(&hex_value, serializer) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result>, D::Error> + where + D: Deserializer<'de>, + { + // First, deserialize a string value. It is expected to be a + // hexadecimal representation of `Fr`. + let optional_deserialized_string: Option = Option::deserialize(deserializer)?; + + optional_deserialized_string + .map(|s| { + if s.starts_with(P::prefix()) { + Ok(&s[P::prefix().len()..]) + .and_then(|hex_str| hex::decode(hex_str).map_err(de::Error::custom)) + } else { + Err(de::Error::custom(format!( + "string value missing prefix: {}", + P::prefix() + ))) + } + }) + .transpose() + } +} diff --git a/core/testhelper/Cargo.toml b/core/testhelper/Cargo.toml deleted file mode 100644 index 455d984a9b..0000000000 --- a/core/testhelper/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "testhelper" -version = "0.1.0" -authors = ["furkhat "] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -models = { path = "../models", version = "0.0.1" } -crypto_exports = { path = "../crypto_exports", version = "0.1.0" } -web3 = "0.8.0" diff --git a/core/testhelper/src/lib.rs b/core/testhelper/src/lib.rs deleted file mode 100644 index b1a1b63b8b..0000000000 --- a/core/testhelper/src/lib.rs +++ /dev/null @@ -1,40 +0,0 @@ -use crypto_exports::franklin_crypto; -use crypto_exports::rand; - -use crate::rand::Rng; - -/// TestAccount is an account with random generated keys and address. -pub struct TestAccount { - pub private_key: - franklin_crypto::eddsa::PrivateKey, - pub public_key: - franklin_crypto::eddsa::PublicKey, - pub address: web3::types::Address, -} - -// TODO: move to helper crate -impl TestAccount { - pub fn new() -> Self { - let rng = &mut rand::thread_rng(); - let p_g = franklin_crypto::alt_babyjubjub::FixedGenerators::SpendingKeyGenerator; - let jubjub_params = &franklin_crypto::alt_babyjubjub::AltJubjubBn256::new(); - let private_key = franklin_crypto::eddsa::PrivateKey::< - franklin_crypto::bellman::pairing::bn256::Bn256, - >(rng.gen()); - let address = rng.gen::<[u8; 20]>().into(); - let public_key = franklin_crypto::eddsa::PublicKey::< - franklin_crypto::bellman::pairing::bn256::Bn256, - >::from_private(&private_key, p_g, jubjub_params); - TestAccount { - private_key, - public_key, - address, - } - } -} - -impl Default for TestAccount { - fn default() -> Self { - TestAccount::new() - } -} diff --git a/core/testkit/Cargo.toml b/core/testkit/Cargo.toml index 2ee7b9aba5..d7d2136f12 100644 --- a/core/testkit/Cargo.toml +++ b/core/testkit/Cargo.toml @@ -17,8 +17,8 @@ futures = { version = "0.3", features = ["compat"] } log = "0.4" env_logger = "0.6" bigdecimal = { version = "0.1.0", features = ["serde"]} -web3 = "0.8.0" -ethabi = "8.0.0" +ethabi = "9.0.0" +web3 = "0.10.0" failure = "0.1" serde = "1.0.90" serde_derive = "1.0.90" diff --git a/core/testkit/src/eth_account.rs b/core/testkit/src/eth_account.rs index e2ed680ba3..5fdb844241 100644 --- a/core/testkit/src/eth_account.rs +++ b/core/testkit/src/eth_account.rs @@ -600,10 +600,7 @@ async fn get_revert_reason( value: Some(value), data: Some(input), }, - receipt - .block_number - .clone() - .map(|n| BlockNumber::Number(n.as_u64())), + receipt.block_number.clone().map(BlockNumber::Number), ) .compat() .await?; diff --git a/core/testkit/src/lib.rs b/core/testkit/src/lib.rs index 83ddaf4f5a..366c40e7f0 100644 --- a/core/testkit/src/lib.rs +++ b/core/testkit/src/lib.rs @@ -182,15 +182,10 @@ impl AccountSet { /// Initialize plasma state with one account - fee account. pub fn genesis_state(fee_account_address: &Address) -> PlasmaStateInitParams { - let mut accounts = AccountMap::default(); let operator_account = Account::default_with_address(fee_account_address); - accounts.insert(0, operator_account); - - PlasmaStateInitParams { - accounts, - last_block_number: 0, - unprocessed_priority_op: 0, - } + let mut params = PlasmaStateInitParams::new(); + params.insert_account(0, operator_account); + params } pub async fn state_keeper_get_account( diff --git a/core/testkit/src/zksync_account.rs b/core/testkit/src/zksync_account.rs index bced56bfeb..0894390810 100644 --- a/core/testkit/src/zksync_account.rs +++ b/core/testkit/src/zksync_account.rs @@ -99,17 +99,16 @@ impl ZksyncAccount { increment_nonce: bool, ) -> (Transfer, PackedEthSignature) { let mut stored_nonce = self.nonce.lock().unwrap(); - let mut transfer = Transfer { - from: self.address, - to: *to, - token: token_id, + let transfer = Transfer::new_signed( + self.address, + *to, + token_id, amount, fee, - nonce: nonce.unwrap_or_else(|| *stored_nonce), - signature: TxSignature::default(), - }; - transfer.signature = - TxSignature::sign_musig_sha256(&self.private_key, &transfer.get_bytes()); + nonce.unwrap_or_else(|| *stored_nonce), + &self.private_key, + ) + .expect("Failed to sign transfer"); if increment_nonce { *stored_nonce += 1; @@ -135,17 +134,16 @@ impl ZksyncAccount { increment_nonce: bool, ) -> (Withdraw, PackedEthSignature) { let mut stored_nonce = self.nonce.lock().unwrap(); - let mut withdraw = Withdraw { - from: self.address, - to: *eth_address, - token: token_id, + let withdraw = Withdraw::new_signed( + self.address, + *eth_address, + token_id, amount, fee, - nonce: nonce.unwrap_or_else(|| *stored_nonce), - signature: TxSignature::default(), - }; - withdraw.signature = - TxSignature::sign_musig_sha256(&self.private_key, &withdraw.get_bytes()); + nonce.unwrap_or_else(|| *stored_nonce), + &self.private_key, + ) + .expect("Failed to sign withdraw"); if increment_nonce { *stored_nonce += 1; @@ -166,7 +164,7 @@ impl ZksyncAccount { nonce: nonce.unwrap_or_else(|| *stored_nonce), signature: TxSignature::default(), }; - close.signature = TxSignature::sign_musig_sha256(&self.private_key, &close.get_bytes()); + close.signature = TxSignature::sign_musig(&self.private_key, &close.get_bytes()); if increment_nonce { *stored_nonce += 1; diff --git a/docker/ci/Dockerfile b/docker/ci/Dockerfile index e1a94d013f..5262122bf6 100644 --- a/docker/ci/Dockerfile +++ b/docker/ci/Dockerfile @@ -2,11 +2,17 @@ FROM fedora:30 ENV PATH="/root/.cargo/bin:${PATH}" RUN dnf install -y gettext nodejs nodejs-yarn axel jq postgresql libpq-devel rust make openssl-devel git python gcc-c++ docker which && dnf clean all \ && curl https://sh.rustup.rs -sSf | bash -s -- -y \ - && cargo install diesel_cli --no-default-features --features postgres \ - && cargo install wasm-pack \ - && rm -rf ~/.cargo/registry \ && ln -s /usr/bin/nodejs-yarn /usr/bin/yarn +RUN cargo install diesel_cli --no-default-features --features postgres +RUN cargo install wasm-pack + +# sccache support +RUN cargo install sccache +ENV RUSTC_WRAPPER=/root/.cargo/bin/sccache +ENV SCCACHE_DIR=/drone/src/target/rust-ci-cache/sccache +ENV CARGO_HOME=/drone/src/target/rust-ci-cache/cargo + RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl RUN chmod +x ./kubectl RUN mv ./kubectl /usr/local/bin/kubectl diff --git a/docker/server_supervisor/Dockerfile b/docker/server_supervisor/Dockerfile new file mode 100644 index 0000000000..8c31edf9a8 --- /dev/null +++ b/docker/server_supervisor/Dockerfile @@ -0,0 +1,3 @@ +FROM alpine +COPY target/x86_64-unknown-linux-musl/release/server_supervisor / +ENTRYPOINT ["/server_supervisor"] diff --git a/docs/setup-dev.md b/docs/setup-dev.md index d64a9787e6..fc60a4d4b8 100644 --- a/docs/setup-dev.md +++ b/docs/setup-dev.md @@ -33,7 +33,8 @@ The problem should be solved at this step. ## `Node` & `Yarn` -1. Install `Node`. +1. Install `Node`. Be sure to install `Node` v10.20.1. Other 10x versions (e.g. v10.16.1) can cause mysterious errors, +which won't look related to the `Node` itself. 2. Install `yarn`. Instructions can be found on the [official site](https://classic.yarnpkg.com/en/docs/install/). diff --git a/etc/env/dev.env.example b/etc/env/dev.env.example index a513a9a931..7e458c6ff5 100755 --- a/etc/env/dev.env.example +++ b/etc/env/dev.env.example @@ -87,7 +87,7 @@ WS_API_ADDR=ws://localhost:3031 API_SERVER=http://localhost:3000 MAX_OUTSTANDING_TXS=120000 -RUST_LOG=storage=info,server=debug,prover=debug,plasma=info,eth_client=info,data_restore=info,dummy_prover=info,key_generator=info,exodus_test=info,loadtest=info +RUST_LOG=storage=info,server=debug,prover=debug,plasma=info,eth_client=info,data_restore=info,dummy_prover=info,key_generator=info,exodus_test=info,loadtest=info,server_supervisor=info,kube=debug PROVER_SERVER_URL=http://0.0.0.0:8088 PROVER_SERVER_BIND=0.0.0.0:8088 @@ -106,3 +106,5 @@ DRONE_SERVER="" DRONE_TOKEN="" CONFIRMATIONS_FOR_ETH_EVENT=1 + +SERVER_REPLICA_NAME=server-1 diff --git a/etc/kube/server.yaml b/etc/kube/server.yaml index 3d8b2757a9..036a1aeba8 100644 --- a/etc/kube/server.yaml +++ b/etc/kube/server.yaml @@ -1,3 +1,31 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ${ZKSYNC_ENV}-server-supervisor + namespace: ${ZKSYNC_ENV} +spec: + replicas: 1 + selector: + matchLabels: + app: ${ZKSYNC_ENV}-server-supervisor + strategy: + type: Recreate + template: + metadata: + labels: + app: ${ZKSYNC_ENV}-server-supervisor + spec: + containers: + - name: server + image: matterlabs/server_supervisor:${IMAGE_TAG} + imagePullPolicy: Always + envFrom: + - secretRef: + name: ${ZKSYNC_ENV}-secret + env: + - name: NAMESPACE + value: "${ZKSYNC_ENV}" +--- apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: @@ -60,12 +88,10 @@ metadata: spec: strategy: type: Recreate - replicas: 1 + replicas: 2 selector: matchLabels: app: ${ZKSYNC_ENV}-server - strategy: - type: Recreate template: metadata: labels: @@ -76,6 +102,11 @@ spec: image: matterlabs/server:${IMAGE_TAG} imagePullPolicy: Always resources: ${SERVER_CONTAINER_RESOURCES} + readinessProbe: + tcpSocket: + port: 3000 + initialDelaySeconds: 5 + periodSeconds: 100 ports: - containerPort: 3000 - containerPort: 3030 @@ -87,3 +118,8 @@ spec: env: - name: ZKSYNC_ENV value: "${ZKSYNC_ENV}" + - name: SERVER_REPLICA_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name