From b4c8f2e470661d6bf20a4d526826bbe80bc10997 Mon Sep 17 00:00:00 2001 From: Ali Behjati Date: Fri, 2 Sep 2022 12:39:51 +0200 Subject: [PATCH] Refactor our CW contract + cleanups (#262) * Use the cw sdk * Fix clippy warnings * Use Addr instead of String * Format the code (cargo +nightly fmt) * Depend on wormhole git instead of local dependency * Add error enum * refactor * Refactor errors * certusone->wormhole-foundation rename It will fix some compile problems * Build wormhole contract from their repo * remove wormhole package * Remove memmap2 patch It was not needed anymore with the newer verison of solana (wormhole removed it too) * Rename pyth-bridge to pyth-cosmwasm --- .github/workflows/pyth-cosmwasm-contract.yml | 2 +- CONTRIBUTING.md | 2 +- Dockerfile.client | 4 +- Dockerfile.cosmwasm | 26 +- Dockerfile.solana | 2 +- README.md | 2 +- cosmwasm/Cargo.lock | 269 +++--- cosmwasm/Cargo.toml | 4 +- cosmwasm/README.md | 16 +- cosmwasm/contracts/pyth-bridge/src/msg.rs | 46 - .../{pyth-bridge => pyth}/Cargo.toml | 6 +- .../{pyth-bridge => pyth}/src/contract.rs | 281 +++--- cosmwasm/contracts/pyth/src/error.rs | 37 + .../{pyth-bridge => pyth}/src/lib.rs | 1 + cosmwasm/contracts/pyth/src/msg.rs | 34 + .../{pyth-bridge => pyth}/src/state.rs | 28 +- cosmwasm/contracts/wormhole/.cargo/config | 5 - cosmwasm/contracts/wormhole/Cargo.toml | 32 - cosmwasm/contracts/wormhole/src/byte_utils.rs | 101 --- cosmwasm/contracts/wormhole/src/contract.rs | 417 --------- cosmwasm/contracts/wormhole/src/error.rs | 113 --- cosmwasm/contracts/wormhole/src/lib.rs | 7 - cosmwasm/contracts/wormhole/src/msg.rs | 71 -- cosmwasm/contracts/wormhole/src/state.rs | 393 -------- cosmwasm/tools/deploy-pyth-bridge.js | 2 +- cosmwasm/tools/deploy.js | 11 +- solana/memmap2-rs/Cargo.toml | 16 - solana/memmap2-rs/LICENSE-APACHE | 201 ----- solana/memmap2-rs/LICENSE-MIT | 26 - solana/memmap2-rs/README.md | 3 - solana/memmap2-rs/src/lib.rs | 839 ------------------ solana/memmap2-rs/src/stub.rs | 75 -- solana/pyth2wormhole/Cargo.lock | 18 +- solana/pyth2wormhole/Cargo.toml | 2 - solana/pyth2wormhole/client/Cargo.toml | 6 +- solana/pyth2wormhole/program/Cargo.lock | 9 - solana/pyth2wormhole/program/Cargo.toml | 6 +- third_party/abigen/go.mod | 2 +- third_party/pyth/p2w-relay/README.md | 2 +- third_party/pyth/p2w-sdk/js/package.json | 6 +- third_party/pyth/p2w-sdk/rust/Cargo.lock | 12 +- third_party/pyth/p2w-sdk/rust/Cargo.toml | 6 +- third_party/pyth/price-service/README.md | 2 +- 43 files changed, 501 insertions(+), 2642 deletions(-) delete mode 100644 cosmwasm/contracts/pyth-bridge/src/msg.rs rename cosmwasm/contracts/{pyth-bridge => pyth}/Cargo.toml (85%) rename cosmwasm/contracts/{pyth-bridge => pyth}/src/contract.rs (72%) create mode 100644 cosmwasm/contracts/pyth/src/error.rs rename cosmwasm/contracts/{pyth-bridge => pyth}/src/lib.rs (85%) create mode 100644 cosmwasm/contracts/pyth/src/msg.rs rename cosmwasm/contracts/{pyth-bridge => pyth}/src/state.rs (77%) delete mode 100644 cosmwasm/contracts/wormhole/.cargo/config delete mode 100644 cosmwasm/contracts/wormhole/Cargo.toml delete mode 100644 cosmwasm/contracts/wormhole/src/byte_utils.rs delete mode 100644 cosmwasm/contracts/wormhole/src/contract.rs delete mode 100644 cosmwasm/contracts/wormhole/src/error.rs delete mode 100644 cosmwasm/contracts/wormhole/src/lib.rs delete mode 100644 cosmwasm/contracts/wormhole/src/msg.rs delete mode 100644 cosmwasm/contracts/wormhole/src/state.rs delete mode 100644 solana/memmap2-rs/Cargo.toml delete mode 100644 solana/memmap2-rs/LICENSE-APACHE delete mode 100644 solana/memmap2-rs/LICENSE-MIT delete mode 100644 solana/memmap2-rs/README.md delete mode 100644 solana/memmap2-rs/src/lib.rs delete mode 100644 solana/memmap2-rs/src/stub.rs diff --git a/.github/workflows/pyth-cosmwasm-contract.yml b/.github/workflows/pyth-cosmwasm-contract.yml index ee1ca8e8..fc112a64 100644 --- a/.github/workflows/pyth-cosmwasm-contract.yml +++ b/.github/workflows/pyth-cosmwasm-contract.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest defaults: run: - working-directory: ./cosmwasm/contracts/pyth-bridge + working-directory: ./cosmwasm/contracts/pyth steps: - uses: actions/checkout@v2 - name: Build diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 137d9be2..68180804 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,7 +28,7 @@ and code reviews are our most important tools to accomplish that. well-defined changes. Documentation for the in-the-wild deployments lives in the -[wormhole-networks](https://github.com/certusone/wormhole-networks) repository. +[wormhole-networks](https://github.com/wormhole-foundation/wormhole-networks) repository. See [DEVELOP.md](./DEVELOP.md) for more information on how to run the development environment. diff --git a/Dockerfile.client b/Dockerfile.client index 801782df..977d0a52 100644 --- a/Dockerfile.client +++ b/Dockerfile.client @@ -25,5 +25,5 @@ RUN --mount=type=cache,target=/root/.cache \ --mount=type=cache,target=/usr/local/cargo/registry,id=cargo_registry \ --mount=type=cache,target=target,id=cargo_registry \ set -xe && \ - cargo install bridge_client --git https://github.com/certusone/wormhole --tag $WORMHOLE_TAG --locked --root /usr/local && \ - cargo install token_bridge_client --git https://github.com/certusone/wormhole --tag $WORMHOLE_TAG --locked --root /usr/local + cargo install bridge_client --git https://github.com/wormhole-foundation/wormhole --tag $WORMHOLE_TAG --locked --root /usr/local && \ + cargo install token_bridge_client --git https://github.com/wormhole-foundation/wormhole --tag $WORMHOLE_TAG --locked --root /usr/local diff --git a/Dockerfile.cosmwasm b/Dockerfile.cosmwasm index 72860c39..000a1d10 100644 --- a/Dockerfile.cosmwasm +++ b/Dockerfile.cosmwasm @@ -1,12 +1,27 @@ -# This is a multi-stage docker file, first stage builds contracts -# And the second one creates node.js environment to deploy them -FROM cosmwasm/workspace-optimizer:0.12.6@sha256:e6565a5e87c830ef3e8775a9035006b38ad0aaf0a96319158c802457b1dd1d08 AS builder +# This is a multi-stage docker file, first and second stage builds contracts +# And the third one creates node.js environment to deploy them + +FROM cosmwasm/workspace-optimizer:0.12.6@sha256:e6565a5e87c830ef3e8775a9035006b38ad0aaf0a96319158c802457b1dd1d08 AS wormhole_builder + +WORKDIR /tmp/wormhole-repo + +ARG WORMHOLE_REV=2.8.9 +ADD https://github.com/certusone/wormhole/archive/refs/tags/v${WORMHOLE_REV}.tar.gz . +RUN tar -xvf v${WORMHOLE_REV}.tar.gz +RUN mv wormhole-${WORMHOLE_REV}/cosmwasm/Cargo.lock /code/ +RUN mv wormhole-${WORMHOLE_REV}/cosmwasm/Cargo.toml /code/ +RUN mv wormhole-${WORMHOLE_REV}/cosmwasm/contracts /code/contracts + +WORKDIR /code +RUN --mount=type=cache,target=/code/target,id=cosmwasm_wormhole_target --mount=type=cache,target=/usr/local/cargo/registry optimize_workspace.sh + +FROM cosmwasm/workspace-optimizer:0.12.6@sha256:e6565a5e87c830ef3e8775a9035006b38ad0aaf0a96319158c802457b1dd1d08 AS pyth_builder COPY cosmwasm/Cargo.lock /code/ COPY cosmwasm/Cargo.toml /code/ COPY cosmwasm/contracts /code/contracts COPY third_party/pyth/p2w-sdk/rust /third_party/pyth/p2w-sdk/rust -RUN --mount=type=cache,target=/code/target,id=cosmwasm_target --mount=type=cache,target=/usr/local/cargo/registry optimize_workspace.sh +RUN --mount=type=cache,target=/code/target,id=cosmwasm_pyth_target --mount=type=cache,target=/usr/local/cargo/registry optimize_workspace.sh # Contract deployment stage FROM node:16-buster-slim@sha256:93c9fc3550f5f7d159f282027228e90e3a7f8bf38544758024f005e82607f546 @@ -15,7 +30,8 @@ RUN apt update && apt install netcat curl jq -y WORKDIR /app/tools -COPY --from=builder /code/artifacts /app/artifacts +COPY --from=wormhole_builder /code/artifacts/wormhole.wasm /app/artifacts/wormhole.wasm +COPY --from=pyth_builder /code/artifacts/pyth_cosmwasm.wasm /app/artifacts/pyth_cosmwasm.wasm COPY ./cosmwasm/tools/package.json ./cosmwasm/tools/package-lock.json /app/tools/ RUN --mount=type=cache,uid=1000,gid=1000,target=/home/node/.npm \ diff --git a/Dockerfile.solana b/Dockerfile.solana index 6b73909b..52cb2483 100644 --- a/Dockerfile.solana +++ b/Dockerfile.solana @@ -29,7 +29,7 @@ RUN cargo init --lib /tmp/decoy-crate && \ WORKDIR /usr/src/bridge ARG WORMHOLE_REV=2.8.9 -ADD https://github.com/certusone/wormhole/archive/refs/tags/v${WORMHOLE_REV}.tar.gz . +ADD https://github.com/wormhole-foundation/wormhole/archive/refs/tags/v${WORMHOLE_REV}.tar.gz . RUN tar -xvf v${WORMHOLE_REV}.tar.gz RUN mv wormhole-${WORMHOLE_REV} wormhole # RUN mkdir -p /usr/src/bridge/wormhole/solana/target diff --git a/README.md b/README.md index be330d15..678a934c 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Pyth2Wormhole. The base repository is a fork from Certus One's reference for building projects based on Wormhole's various SDKs. Much of the existing documentation from there will also apply to this repository. -[Wormhole]: https://github.com/certusone/wormhole +[Wormhole]: https://github.com/wormhole-foundation/wormhole Within this monorepo you will find the following subprojects: diff --git a/cosmwasm/Cargo.lock b/cosmwasm/Cargo.lock index feb2eee2..1657f0dd 100644 --- a/cosmwasm/Cargo.lock +++ b/cosmwasm/Cargo.lock @@ -63,9 +63,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "base64ct" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdca834647821e0b13d9539a8634eb62d3501b6b6c2cec1722786ee6671b851" +checksum = "ea2b2456fd614d856680dcd9fcc660a51a820fa09daef2e49772b56a193c8474" [[package]] name = "bigint" @@ -146,15 +146,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "bytecheck" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a31f923c2db9513e4298b72df143e6e655a759b3d6a0966df18f81223fff54f" +checksum = "d11cac2c12b5adc6570dad2ee1b87eff4955dac476fe12d81e5fdd352e52406f" dependencies = [ "bytecheck_derive", "ptr_meta", @@ -162,9 +162,9 @@ dependencies = [ [[package]] name = "bytecheck_derive" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edb17c862a905d912174daa27ae002326fff56dc8b8ada50a0a5f0976cb174f0" +checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf" dependencies = [ "proc-macro2", "quote", @@ -179,9 +179,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0b3de4a0c5e67e16066a0715723abd91edc2f9001d09c46e1dca929351e130e" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "cc" @@ -279,9 +279,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "dc948ebb96241bb40ab73effeb80d9f93afaad49359d159a5e61be51619fe813" dependencies = [ "libc", ] @@ -357,9 +357,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if", "crossbeam-utils", @@ -367,9 +367,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -378,9 +378,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d" +checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" dependencies = [ "autocfg", "cfg-if", @@ -392,9 +392,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" dependencies = [ "cfg-if", "once_cell", @@ -448,9 +448,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.2.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" dependencies = [ "byteorder", "digest", @@ -459,6 +459,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "cw-storage-plus" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "648b1507290bbc03a8d88463d7cd9b04b1fa0155e5eef366c4fa052b9caaac7a" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + [[package]] name = "cw-utils" version = "0.13.4" @@ -471,6 +482,18 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cw2" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cf4639517490dd36b333bbd6c4fbd92e325fd0acf4683b41753bc5eb63bfc1" +dependencies = [ + "cosmwasm-std", + "cw-storage-plus", + "schemars", + "serde", +] + [[package]] name = "cw20" version = "0.13.4" @@ -483,6 +506,38 @@ dependencies = [ "serde", ] +[[package]] +name = "cw20-base" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0306e606581f4fb45e82bcbb7f0333179ed53dd949c6523f01a99b4bfc1475a0" +dependencies = [ + "cosmwasm-std", + "cw-storage-plus", + "cw-utils", + "cw2", + "cw20", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw20-wrapped-2" +version = "0.1.0" +source = "git+https://github.com/wormhole-foundation/wormhole?tag=v2.8.9#e47f9e481ef84d4dea7a94c9eafbf3b180892466" +dependencies = [ + "cosmwasm-std", + "cosmwasm-storage", + "cw-storage-plus", + "cw2", + "cw20", + "cw20-base", + "schemars", + "serde", + "thiserror", +] + [[package]] name = "darling" version = "0.13.4" @@ -543,9 +598,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d07a982d1fb29db01e5a59b1918e03da4df7297eaeee7686ac45542fd4e59c8" +checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2" [[package]] name = "dynasm" @@ -614,9 +669,9 @@ dependencies = [ [[package]] name = "either" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "elliptic-curve" @@ -700,9 +755,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "fastrand" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] @@ -741,9 +796,9 @@ checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", @@ -884,15 +939,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" [[package]] name = "js-sys" -version = "0.3.58" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" +checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" dependencies = [ "wasm-bindgen", ] @@ -941,9 +996,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" [[package]] name = "libloading" @@ -1002,9 +1057,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a79b39c93a7a5a27eeaf9a23b5ff43f1b9e0ad6b1cdd441140ae53c35613fc7" +checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" dependencies = [ "libc", ] @@ -1066,9 +1121,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" [[package]] name = "opaque-debug" @@ -1143,9 +1198,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" dependencies = [ "unicode-ident", ] @@ -1180,7 +1235,7 @@ dependencies = [ ] [[package]] -name = "pyth-bridge" +name = "pyth-cosmwasm" version = "0.1.0" dependencies = [ "bigint", @@ -1192,7 +1247,7 @@ dependencies = [ "k256 0.9.6", "lazy_static", "p2w-sdk", - "pyth-sdk", + "pyth-sdk-cw", "schemars", "serde", "serde_derive", @@ -1200,14 +1255,14 @@ dependencies = [ "sha3", "terraswap", "thiserror", - "wormhole-bridge-terra", + "wormhole-bridge-terra-2", ] [[package]] name = "pyth-sdk" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f262b88557d8f152a247e1be786a8359d63112fac0a6e49fa41082a8ef789e8d" +checksum = "f5c805ba3dfb5b7ed6a8ffa62ec38391f485a79c7cf6b3b11d3bd44fb0325824" dependencies = [ "borsh", "borsh-derive", @@ -1217,10 +1272,23 @@ dependencies = [ ] [[package]] -name = "quote" -version = "1.0.20" +name = "pyth-sdk-cw" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "4f1575db8f501031a810aa5fe5da8ac3868bfcee7ce3deb27d6354c81a5833cb" +dependencies = [ + "cosmwasm-std", + "cosmwasm-storage", + "pyth-sdk", + "schemars", + "serde", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -1269,9 +1337,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] @@ -1367,15 +1435,15 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustversion" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24c8ad4f0c00e1eb5bc7614d236a7f1300e3dbd76b68cac8e06fb00b015ad8d8" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "schemars" @@ -1428,9 +1496,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.139" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0171ebb889e45aa68b44aee0859b3eede84c6f5f5c228e6f140c0b2a0a46cad6" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" dependencies = [ "serde_derive", ] @@ -1446,18 +1514,18 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212e73464ebcde48d723aa02eb270ba62eff38a9b732df31f33f1b4e145f3a54" +checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.139" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1d3230c1de7932af58ad8ffbe1d784bd55efd5a9d84ac24f69c72d83543dfb" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" dependencies = [ "proc-macro2", "quote", @@ -1477,9 +1545,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.82" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa", "ryu", @@ -1557,9 +1625,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" dependencies = [ "proc-macro2", "quote", @@ -1588,9 +1656,9 @@ dependencies = [ [[package]] name = "terraswap" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d4151fb37794dbae0a0be342fc8474566c7b5d1f3086cd96aea9b0d480b068" +checksum = "b9540f8489ec6e098de380c9fa8fa81fa95e502f87d63705aa6fba56817ad1a7" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -1602,18 +1670,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09" dependencies = [ "proc-macro2", "quote", @@ -1631,9 +1699,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" dependencies = [ "cfg-if", "log", @@ -1655,9 +1723,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" dependencies = [ "once_cell", ] @@ -1682,9 +1750,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" [[package]] name = "version_check" @@ -1706,9 +1774,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" +checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1716,13 +1784,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" +checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -1731,9 +1799,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" +checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1741,9 +1809,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" +checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" dependencies = [ "proc-macro2", "quote", @@ -1754,9 +1822,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" +checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" [[package]] name = "wasmer" @@ -1990,13 +2058,13 @@ checksum = "52144d4c78e5cf8b055ceab8e5fa22814ce4315d6002ad32cfd914f37c12fd65" [[package]] name = "which" -version = "4.2.5" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" +checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" dependencies = [ "either", - "lazy_static", "libc", + "once_cell", ] [[package]] @@ -2022,12 +2090,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "wormhole-bridge-terra" +name = "wormhole-bridge-terra-2" version = "0.1.0" +source = "git+https://github.com/wormhole-foundation/wormhole?tag=v2.8.9#e47f9e481ef84d4dea7a94c9eafbf3b180892466" dependencies = [ "cosmwasm-std", "cosmwasm-storage", - "cosmwasm-vm", + "cw20", + "cw20-base", + "cw20-wrapped-2", "generic-array", "getrandom 0.2.7", "hex", @@ -2035,18 +2106,12 @@ dependencies = [ "lazy_static", "schemars", "serde", - "serde_json", "sha3", "thiserror", ] [[package]] name = "zeroize" -version = "1.3.0" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" - -[[patch.unused]] -name = "memmap2" -version = "0.1.0" -source = "git+https://github.com/certusone/wormhole#7a1b1344a19db22935d8532135ac249da128b4e7" +checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" diff --git a/cosmwasm/Cargo.toml b/cosmwasm/Cargo.toml index 1c65edf2..c299d14d 100644 --- a/cosmwasm/Cargo.toml +++ b/cosmwasm/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["contracts/wormhole","contracts/pyth-bridge"] +members = ["contracts/pyth"] [profile.release] opt-level = 3 @@ -12,5 +12,3 @@ panic = 'abort' incremental = false overflow-checks = true -[patch.crates-io] -memmap2 = { git = "https://github.com/certusone/wormhole", package = "memmap2" } diff --git a/cosmwasm/README.md b/cosmwasm/README.md index 8ccdc543..ea233742 100644 --- a/cosmwasm/README.md +++ b/cosmwasm/README.md @@ -22,17 +22,17 @@ bash build.sh This command will build and save the Pyth contract in the `artifact` directory. -Then, to deploy the Pyth contract (`pyth_bridge.wasm`), run the following command in the `tools` directory: +Then, to deploy the Pyth contract (`pyth_cosmwasm.wasm`), run the following command in the `tools` directory: ``` sh npm ci # Do it only once to install the required packages -npm run deploy-pyth -- --network testnet --artifact ../artifacts/pyth_bridge.wasm --mnemonic "..." +npm run deploy-pyth -- --network testnet --artifact ../artifacts/pyth_cosmwasm.wasm --mnemonic "..." ``` If successful, this command will print something along the lines of: ``` sh -Storing WASM: ../artifacts/pyth_bridge.wasm (367689 bytes) +Storing WASM: ../artifacts/pyth_cosmwasm.wasm (367689 bytes) Deploy fee: 88446uluna Code ID: 2435 ``` @@ -45,17 +45,17 @@ If you want to instantiate a new contract after your deployment, pass `--instant This command will upload the code and instantiates a new Pyth contract with the resulting code id: ``` sh -npm run deploy-pyth -- --network testnet --artifact ../artifacts/pyth_bridge.wasm --mnemonic "..." --instantiate +npm run deploy-pyth -- --network testnet --artifact ../artifacts/pyth_cosmwasm.wasm --mnemonic "..." --instantiate ``` If successful, the output should look like so: ``` -Storing WASM: ../artifacts/pyth_bridge.wasm (183749 bytes) +Storing WASM: ../artifacts/pyth_cosmwasm.wasm (183749 bytes) Deploy fee: 44682uluna Code ID: 53199 Instantiating a contract Sleeping for 10 seconds for store transaction to finalize. -Instantiated Pyth Bridge at terra123456789yelw23uh22nadqlyjvtl7s5527er97 (0x0000000000000000000000001234567896267ee5479752a7d683e49317ff4294) +Instantiated Pyth at terra123456789yelw23uh22nadqlyjvtl7s5527er97 (0x0000000000000000000000001234567896267ee5479752a7d683e49317ff4294) Deployed Pyth contract at terra123456789yelw23uh22nadqlyjvtl7s5527er97 ``` @@ -64,12 +64,12 @@ If you want to upgrade an existing contract pass `--migrate --contract terra1234 This command will upload the code, and with the resulting code id, will migrate the existing contract to the new one: ``` sh -npm run deploy-pyth -- --network testnet --artifact ../artifacts/pyth_bridge.wasm --mnemonic "..." --migrate --contract "terra123..." +npm run deploy-pyth -- --network testnet --artifact ../artifacts/pyth_cosmwasm.wasm --mnemonic "..." --migrate --contract "terra123..." ``` If successful, the output should look like so: ``` -Storing WASM: ../artifacts/pyth_bridge.wasm (183749 bytes) +Storing WASM: ../artifacts/pyth_cosmwasm.wasm (183749 bytes) Deploy fee: 44682uluna Code ID: 53227 Sleeping for 10 seconds for store transaction to finalize. diff --git a/cosmwasm/contracts/pyth-bridge/src/msg.rs b/cosmwasm/contracts/pyth-bridge/src/msg.rs deleted file mode 100644 index 274ae03a..00000000 --- a/cosmwasm/contracts/pyth-bridge/src/msg.rs +++ /dev/null @@ -1,46 +0,0 @@ -use cosmwasm_std::Binary; -use pyth_sdk::{ - PriceFeed, - PriceIdentifier, -}; -use schemars::JsonSchema; -use serde::{ - Deserialize, - Serialize, -}; - -use crate::state::PythDataSource; - -type HumanAddr = String; - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct InstantiateMsg { - pub wormhole_contract: HumanAddr, - pub pyth_emitter: Binary, - pub pyth_emitter_chain: u16, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum ExecuteMsg { - SubmitVaa { data: Binary }, - AddDataSource { data_source: PythDataSource }, - RemoveDataSource { data_source: PythDataSource }, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct MigrateMsg {} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum QueryMsg { - PriceFeed { id: PriceIdentifier }, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct PriceFeedResponse { - /// Pyth Price Feed - pub price_feed: PriceFeed, -} diff --git a/cosmwasm/contracts/pyth-bridge/Cargo.toml b/cosmwasm/contracts/pyth/Cargo.toml similarity index 85% rename from cosmwasm/contracts/pyth-bridge/Cargo.toml rename to cosmwasm/contracts/pyth/Cargo.toml index afc82132..ae77769c 100644 --- a/cosmwasm/contracts/pyth-bridge/Cargo.toml +++ b/cosmwasm/contracts/pyth/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pyth-bridge" +name = "pyth-cosmwasm" version = "0.1.0" authors = ["Wormhole Contributors "] edition = "2018" @@ -20,7 +20,7 @@ schemars = "0.8.1" serde = { version = "1.0.103", default-features = false, features = ["derive"] } serde_derive = { version = "1.0.103"} terraswap = "2.4.0" -wormhole-bridge-terra = { path = "../wormhole", features = ["library"] } +wormhole-bridge-terra-2 = { git = "https://github.com/wormhole-foundation/wormhole", tag = "v2.8.9", features = ["library"] } thiserror = { version = "1.0.20" } k256 = { version = "0.9.4", default-features = false, features = ["ecdsa"] } sha3 = { version = "0.9.1", default-features = false } @@ -29,7 +29,7 @@ hex = "0.4.2" lazy_static = "1.4.0" bigint = "4" p2w-sdk = { path = "../../../third_party/pyth/p2w-sdk/rust" } -pyth-sdk = "0.4.2" +pyth-sdk-cw = "0.2.0" [dev-dependencies] cosmwasm-vm = { version = "1.0.0", default-features = false } diff --git a/cosmwasm/contracts/pyth-bridge/src/contract.rs b/cosmwasm/contracts/pyth/src/contract.rs similarity index 72% rename from cosmwasm/contracts/pyth-bridge/src/contract.rs rename to cosmwasm/contracts/pyth/src/contract.rs index ce442fbb..7117081d 100644 --- a/cosmwasm/contracts/pyth-bridge/src/contract.rs +++ b/cosmwasm/contracts/pyth/src/contract.rs @@ -13,10 +13,9 @@ use cosmwasm_std::{ StdResult, Timestamp, WasmQuery, - StdError, }; -use pyth_sdk::{ +use pyth_sdk_cw::{ PriceFeed, PriceIdentifier, PriceStatus, @@ -37,13 +36,14 @@ use crate::state::{ price_info_read, ConfigInfo, PriceInfo, - VALID_TIME_PERIOD, PythDataSource, + VALID_TIME_PERIOD, }; +use crate::error::PythContractError; + use p2w_sdk::BatchPriceAttestation; -use wormhole::error::ContractError; use wormhole::msg::QueryMsg as WormholeQueryMsg; use wormhole::state::ParsedVAA; @@ -61,10 +61,10 @@ pub fn instantiate( ) -> StdResult { // Save general wormhole and pyth info let state = ConfigInfo { - owner: info.sender.to_string(), - wormhole_contract: msg.wormhole_contract, - data_sources: HashSet::from([PythDataSource { - emitter: msg.pyth_emitter, + owner: info.sender, + wormhole_contract: deps.api.addr_validate(msg.wormhole_contract.as_ref())?, + data_sources: HashSet::from([PythDataSource { + emitter: msg.pyth_emitter, pyth_emitter_chain: msg.pyth_emitter_chain, }]), }; @@ -76,7 +76,7 @@ pub fn instantiate( pub fn parse_vaa(deps: DepsMut, block_time: u64, data: &Binary) -> StdResult { let cfg = config_read(deps.storage).load()?; let vaa: ParsedVAA = deps.querier.query(&QueryRequest::Wasm(WasmQuery::Smart { - contract_addr: cfg.wormhole_contract, + contract_addr: cfg.wormhole_contract.to_string(), msg: to_binary(&WormholeQueryMsg::VerifyVAA { vaa: data.clone(), block_time, @@ -89,8 +89,10 @@ pub fn parse_vaa(deps: DepsMut, block_time: u64, data: &Binary) -> StdResult StdResult { match msg { ExecuteMsg::SubmitVaa { data } => submit_vaa(deps, env, info, &data), - ExecuteMsg::AddDataSource { data_source } => add_data_source(deps, env, info, data_source ), - ExecuteMsg::RemoveDataSource { data_source } => remove_data_source(deps, env, info, data_source ), + ExecuteMsg::AddDataSource { data_source } => add_data_source(deps, env, info, data_source), + ExecuteMsg::RemoveDataSource { data_source } => { + remove_data_source(deps, env, info, data_source) + } } } @@ -108,7 +110,7 @@ fn submit_vaa( let data = &vaa.payload; let batch_attestation = BatchPriceAttestation::deserialize(&data[..]) - .map_err(|_| ContractError::InvalidVAA.std())?; + .map_err(|_| PythContractError::InvalidUpdatePayload)?; process_batch_attestation(deps, env, &batch_attestation) } @@ -122,25 +124,22 @@ fn add_data_source( let mut state = config_read(deps.storage).load()?; if state.owner != info.sender { - return ContractError::PermissionDenied.std_err(); + return Err(PythContractError::PermissionDenied)?; } - if state.data_sources.insert(data_source.clone()) == false { - return Err(StdError::GenericErr { msg: format!("Data source already exists") }); + if !state.data_sources.insert(data_source.clone()) { + return Err(PythContractError::DataSourceAlreadyExists)?; } config(deps.storage).save(&state)?; Ok(Response::new() - .add_attribute("action", "add_data_source") - .add_attribute( - "data_source_emitter", - format!("{}", data_source.emitter), - ) - .add_attribute( - "data_source_emitter_chain", - format!("{}", data_source.pyth_emitter_chain) - )) + .add_attribute("action", "add_data_source") + .add_attribute("data_source_emitter", format!("{}", data_source.emitter)) + .add_attribute( + "data_source_emitter_chain", + format!("{}", data_source.pyth_emitter_chain), + )) } fn remove_data_source( @@ -150,27 +149,24 @@ fn remove_data_source( data_source: PythDataSource, ) -> StdResult { let mut state = config_read(deps.storage).load()?; - + if state.owner != info.sender { - return ContractError::PermissionDenied.std_err(); + return Err(PythContractError::PermissionDenied)?; } - if state.data_sources.remove(&data_source) == false { - return Err(StdError::GenericErr { msg: format!("Data source does not exist") }); + if !state.data_sources.remove(&data_source) { + return Err(PythContractError::DataSourceDoesNotExists)?; } config(deps.storage).save(&state)?; Ok(Response::new() - .add_attribute("action", "remove_data_source") - .add_attribute( - "data_source_emitter", - format!("{}", data_source.emitter), - ) - .add_attribute( - "data_source_emitter_chain", - format!("{}", data_source.pyth_emitter_chain) - )) + .add_attribute("action", "remove_data_source") + .add_attribute("data_source_emitter", format!("{}", data_source.emitter)) + .add_attribute( + "data_source_emitter_chain", + format!("{}", data_source.pyth_emitter_chain), + )) } @@ -178,11 +174,11 @@ fn remove_data_source( // (Solana) fn verify_vaa_sender(state: &ConfigInfo, vaa: &ParsedVAA) -> StdResult<()> { let vaa_data_source = PythDataSource { - emitter: vaa.emitter_address.clone().into(), - pyth_emitter_chain: vaa.emitter_chain + emitter: vaa.emitter_address.clone().into(), + pyth_emitter_chain: vaa.emitter_chain, }; if !state.data_sources.contains(&vaa_data_source) { - return ContractError::InvalidVAA.std_err(); + return Err(PythContractError::InvalidUpdateEmitter)?; } Ok(()) } @@ -282,18 +278,17 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { pub fn query_price_feed(deps: Deps, env: Env, address: &[u8]) -> StdResult { match price_info_read(deps.storage).load(address) { - Ok(mut terra_price_info) => { + Ok(mut price_info) => { let env_time_sec = env.block.time.seconds(); - let price_pub_time_sec = terra_price_info.price_feed.publish_time as u64; + let price_pub_time_sec = price_info.price_feed.publish_time as u64; // Cases that it will cover: // - This will ensure to set status unknown if the price has become very old and hasn't // updated yet. - // - If a price has arrived very late to terra it will set the status to unknown. + // - If a price has arrived very late to this chain it will set the status to unknown. // - If a price is coming from future it's tolerated up to VALID_TIME_PERIOD seconds - // (using abs diff) but more than that is set to unknown, the reason is huge clock - // difference means there exists a problem in a either Terra or Solana blockchain and - // if it is Solana we don't want to propagate Solana internal problems to Terra + // (using abs diff) but more than that is set to unknown, the reason could be the + // clock time drift between the source and target chains. let time_abs_diff = if env_time_sec > price_pub_time_sec { env_time_sec - price_pub_time_sec } else { @@ -301,14 +296,14 @@ pub fn query_price_feed(deps: Deps, env: Env, address: &[u8]) -> StdResult VALID_TIME_PERIOD.as_secs() { - terra_price_info.price_feed.status = PriceStatus::Unknown; + price_info.price_feed.status = PriceStatus::Unknown; } Ok(PriceFeedResponse { - price_feed: terra_price_info.price_feed, + price_feed: price_info.price_feed, }) } - Err(_) => ContractError::AssetNotFound.std_err(), + Err(_) => Err(PythContractError::PriceFeedNotFound)? } } @@ -317,12 +312,15 @@ mod test { use cosmwasm_std::testing::{ mock_dependencies, mock_env, + mock_info, MockApi, MockQuerier, MockStorage, - mock_info, }; - use cosmwasm_std::OwnedDeps; + use cosmwasm_std::{ + Addr, + OwnedDeps, + }; use super::*; @@ -346,19 +344,28 @@ mod test { } } + fn create_zero_config_info() -> ConfigInfo { + ConfigInfo { + owner: Addr::unchecked(String::default()), + wormhole_contract: Addr::unchecked(String::default()), + data_sources: HashSet::default(), + } + } + fn create_price_feed(expo: i32) -> PriceFeed { let mut price_feed = PriceFeed::default(); price_feed.expo = expo; price_feed } - fn create_data_sources(pyth_emitter: Vec, pyth_emitter_chain: u16) -> HashSet { - HashSet::from([ - PythDataSource { - emitter: pyth_emitter.into(), - pyth_emitter_chain - } - ]) + fn create_data_sources( + pyth_emitter: Vec, + pyth_emitter_chain: u16, + ) -> HashSet { + HashSet::from([PythDataSource { + emitter: pyth_emitter.into(), + pyth_emitter_chain, + }]) } /// Updates the price feed with the given attestation time stamp and @@ -382,7 +389,7 @@ mod test { fn test_verify_vaa_sender_ok() { let config_info = ConfigInfo { data_sources: create_data_sources(vec![1u8], 3), - ..Default::default() + ..create_zero_config_info() }; let mut vaa = create_zero_vaa(); @@ -396,7 +403,7 @@ mod test { fn test_verify_vaa_sender_fail_wrong_emitter_address() { let config_info = ConfigInfo { data_sources: create_data_sources(vec![1u8], 3), - ..Default::default() + ..create_zero_config_info() }; let mut vaa = create_zero_vaa(); @@ -404,7 +411,7 @@ mod test { vaa.emitter_chain = 3; assert_eq!( verify_vaa_sender(&config_info, &vaa), - ContractError::InvalidVAA.std_err() + Err(PythContractError::InvalidUpdateEmitter.into()) ); } @@ -412,7 +419,7 @@ mod test { fn test_verify_vaa_sender_fail_wrong_emitter_chain() { let config_info = ConfigInfo { data_sources: create_data_sources(vec![1u8], 3), - ..Default::default() + ..create_zero_config_info() }; let mut vaa = create_zero_vaa(); @@ -420,7 +427,7 @@ mod test { vaa.emitter_chain = 2; assert_eq!( verify_vaa_sender(&config_info, &vaa), - ContractError::InvalidVAA.std_err() + Err(PythContractError::InvalidUpdateEmitter.into()) ); } @@ -595,35 +602,51 @@ mod test { assert_eq!( query_price_feed(deps.as_ref(), env, b"123".as_ref()), - ContractError::AssetNotFound.std_err() + Err(PythContractError::PriceFeedNotFound.into()) ); } #[test] fn test_add_data_source_ok_with_owner() { let (mut deps, env) = setup_test(); - config(&mut deps.storage).save(&ConfigInfo { - owner: String::from("123"), - ..Default::default() - }).unwrap(); + config(&mut deps.storage) + .save(&ConfigInfo { + owner: Addr::unchecked("123"), + ..create_zero_config_info() + }) + .unwrap(); - let data_source = PythDataSource { emitter: vec![1u8].into(), pyth_emitter_chain: 1 }; + let data_source = PythDataSource { + emitter: vec![1u8].into(), + pyth_emitter_chain: 1, + }; - assert!(add_data_source(deps.as_mut(), env.clone(), mock_info("123", &[]), data_source.clone()).is_ok()); + assert!(add_data_source( + deps.as_mut(), + env.clone(), + mock_info("123", &[]), + data_source.clone() + ) + .is_ok()); // Adding an existing data source should result an error - assert!(add_data_source(deps.as_mut(), env.clone(), mock_info("123", &[]), data_source.clone()).is_err()); + assert!(add_data_source(deps.as_mut(), env, mock_info("123", &[]), data_source).is_err()); } #[test] fn test_add_data_source_err_without_owner() { let (mut deps, env) = setup_test(); - config(&mut deps.storage).save(&ConfigInfo { - owner: String::from("123"), - ..Default::default() - }).unwrap(); + config(&mut deps.storage) + .save(&ConfigInfo { + owner: Addr::unchecked("123"), + ..create_zero_config_info() + }) + .unwrap(); - let data_source = PythDataSource { emitter: vec![1u8].into(), pyth_emitter_chain: 1 }; + let data_source = PythDataSource { + emitter: vec![1u8].into(), + pyth_emitter_chain: 1, + }; assert!(add_data_source(deps.as_mut(), env, mock_info("321", &[]), data_source).is_err()); } @@ -631,74 +654,116 @@ mod test { #[test] fn test_remove_data_source_ok_with_owner() { let (mut deps, env) = setup_test(); - config(&mut deps.storage).save(&ConfigInfo { - owner: String::from("123"), - data_sources: create_data_sources(vec![1u8], 1), - ..Default::default() - }).unwrap(); + config(&mut deps.storage) + .save(&ConfigInfo { + owner: Addr::unchecked("123"), + data_sources: create_data_sources(vec![1u8], 1), + ..create_zero_config_info() + }) + .unwrap(); - let data_source = PythDataSource { emitter: vec![1u8].into(), pyth_emitter_chain: 1 }; + let data_source = PythDataSource { + emitter: vec![1u8].into(), + pyth_emitter_chain: 1, + }; - assert!(remove_data_source(deps.as_mut(), env.clone(), mock_info("123", &[]), data_source.clone()).is_ok()); + assert!(remove_data_source( + deps.as_mut(), + env.clone(), + mock_info("123", &[]), + data_source.clone() + ) + .is_ok()); // Removing a non existent data source should result an error - assert!(remove_data_source(deps.as_mut(), env.clone(), mock_info("123", &[]), data_source.clone()).is_err()); + assert!( + remove_data_source(deps.as_mut(), env, mock_info("123", &[]), data_source).is_err() + ); } #[test] fn test_remove_data_source_err_without_owner() { let (mut deps, env) = setup_test(); - config(&mut deps.storage).save(&ConfigInfo { - owner: String::from("123"), - data_sources: create_data_sources(vec![1u8], 1), - ..Default::default() - }).unwrap(); + config(&mut deps.storage) + .save(&ConfigInfo { + owner: Addr::unchecked("123"), + data_sources: create_data_sources(vec![1u8], 1), + ..create_zero_config_info() + }) + .unwrap(); - let data_source = PythDataSource { emitter: vec![1u8].into(), pyth_emitter_chain: 1 }; + let data_source = PythDataSource { + emitter: vec![1u8].into(), + pyth_emitter_chain: 1, + }; - assert!(remove_data_source(deps.as_mut(), env, mock_info("321", &[]), data_source).is_err()); + assert!( + remove_data_source(deps.as_mut(), env, mock_info("321", &[]), data_source).is_err() + ); } #[test] fn test_verify_vaa_works_after_adding_data_source() { let (mut deps, env) = setup_test(); - config(&mut deps.storage).save(&ConfigInfo { - owner: String::from("123"), - ..Default::default() - }).unwrap(); + config(&mut deps.storage) + .save(&ConfigInfo { + owner: Addr::unchecked("123"), + ..create_zero_config_info() + }) + .unwrap(); let mut vaa = create_zero_vaa(); vaa.emitter_address = vec![1u8]; vaa.emitter_chain = 3; // Should result an error because there is no data source - assert_eq!(verify_vaa_sender(&config_read(&deps.storage).load().unwrap(), &vaa), ContractError::InvalidVAA.std_err()); + assert_eq!( + verify_vaa_sender(&config_read(&deps.storage).load().unwrap(), &vaa), + Err(PythContractError::InvalidUpdateEmitter.into()) + ); - let data_source = PythDataSource { emitter: vec![1u8].into(), pyth_emitter_chain: 3 }; - assert!(add_data_source(deps.as_mut(), env.clone(), mock_info("123", &[]), data_source.clone()).is_ok()); + let data_source = PythDataSource { + emitter: vec![1u8].into(), + pyth_emitter_chain: 3, + }; + assert!(add_data_source(deps.as_mut(), env, mock_info("123", &[]), data_source).is_ok()); - assert_eq!(verify_vaa_sender(&config_read(&deps.storage).load().unwrap(), &vaa), Ok(())); + assert_eq!( + verify_vaa_sender(&config_read(&deps.storage).load().unwrap(), &vaa), + Ok(()) + ); } #[test] fn test_verify_vaa_err_after_removing_data_source() { let (mut deps, env) = setup_test(); - config(&mut deps.storage).save(&ConfigInfo { - owner: String::from("123"), - data_sources: create_data_sources(vec![1u8], 3), - ..Default::default() - }).unwrap(); + config(&mut deps.storage) + .save(&ConfigInfo { + owner: Addr::unchecked("123"), + data_sources: create_data_sources(vec![1u8], 3), + ..create_zero_config_info() + }) + .unwrap(); let mut vaa = create_zero_vaa(); vaa.emitter_address = vec![1u8]; vaa.emitter_chain = 3; - assert_eq!(verify_vaa_sender(&config_read(&deps.storage).load().unwrap(), &vaa), Ok(())); + assert_eq!( + verify_vaa_sender(&config_read(&deps.storage).load().unwrap(), &vaa), + Ok(()) + ); - let data_source = PythDataSource { emitter: vec![1u8].into(), pyth_emitter_chain: 3 }; - assert!(remove_data_source(deps.as_mut(), env.clone(), mock_info("123", &[]), data_source.clone()).is_ok()); + let data_source = PythDataSource { + emitter: vec![1u8].into(), + pyth_emitter_chain: 3, + }; + assert!(remove_data_source(deps.as_mut(), env, mock_info("123", &[]), data_source).is_ok()); // Should result an error because data source should not exist anymore - assert_eq!(verify_vaa_sender(&config_read(&deps.storage).load().unwrap(), &vaa), ContractError::InvalidVAA.std_err()); + assert_eq!( + verify_vaa_sender(&config_read(&deps.storage).load().unwrap(), &vaa), + Err(PythContractError::InvalidUpdateEmitter.into()) + ); } } diff --git a/cosmwasm/contracts/pyth/src/error.rs b/cosmwasm/contracts/pyth/src/error.rs new file mode 100644 index 00000000..16a8b649 --- /dev/null +++ b/cosmwasm/contracts/pyth/src/error.rs @@ -0,0 +1,37 @@ +use cosmwasm_std::StdError; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum PythContractError { + /// Message sender not permitted to execute this operation + #[error("PermissionDenied")] + PermissionDenied, + + /// Wrapped asset not found in the registry + #[error("PriceFeedNotFound")] + PriceFeedNotFound, + + /// Message emitter is not an accepted data source. + #[error("InvalidUpdateMessageEmitter")] + InvalidUpdateEmitter, + + /// Message payload cannot be deserialized to a batch attestation + #[error("InvalidUpdatePayload")] + InvalidUpdatePayload, + + /// Data source does not exists error (on removing data source) + #[error("DataSourceDoesNotExists")] + DataSourceDoesNotExists, + + /// Data source already exists error (on adding data source) + #[error("DataSourceAlreadyExists")] + DataSourceAlreadyExists, +} + +impl From for StdError { + fn from(other: PythContractError) -> StdError { + StdError::GenericErr { + msg: format!("{}", other), + } + } +} diff --git a/cosmwasm/contracts/pyth-bridge/src/lib.rs b/cosmwasm/contracts/pyth/src/lib.rs similarity index 85% rename from cosmwasm/contracts/pyth-bridge/src/lib.rs rename to cosmwasm/contracts/pyth/src/lib.rs index f67a6e5e..75f395d2 100644 --- a/cosmwasm/contracts/pyth-bridge/src/lib.rs +++ b/cosmwasm/contracts/pyth/src/lib.rs @@ -2,5 +2,6 @@ extern crate lazy_static; pub mod contract; +pub mod error; pub mod msg; pub mod state; diff --git a/cosmwasm/contracts/pyth/src/msg.rs b/cosmwasm/contracts/pyth/src/msg.rs new file mode 100644 index 00000000..93048011 --- /dev/null +++ b/cosmwasm/contracts/pyth/src/msg.rs @@ -0,0 +1,34 @@ +use cosmwasm_std::Binary; +use schemars::JsonSchema; +use serde::{ + Deserialize, + Serialize, +}; + +use crate::state::PythDataSource; + +type HumanAddr = String; + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct InstantiateMsg { + pub wormhole_contract: HumanAddr, + pub pyth_emitter: Binary, + pub pyth_emitter_chain: u16, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum ExecuteMsg { + SubmitVaa { data: Binary }, + AddDataSource { data_source: PythDataSource }, + RemoveDataSource { data_source: PythDataSource }, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct MigrateMsg {} + +pub use pyth_sdk_cw::{ + PriceFeedResponse, + QueryMsg, +}; diff --git a/cosmwasm/contracts/pyth-bridge/src/state.rs b/cosmwasm/contracts/pyth/src/state.rs similarity index 77% rename from cosmwasm/contracts/pyth-bridge/src/state.rs rename to cosmwasm/contracts/pyth/src/state.rs index eed15350..c8897b37 100644 --- a/cosmwasm/contracts/pyth-bridge/src/state.rs +++ b/cosmwasm/contracts/pyth/src/state.rs @@ -1,9 +1,7 @@ -use std::{ - time::Duration, - collections::HashSet -}; +use std::collections::HashSet; +use std::time::Duration; -use pyth_sdk::PriceFeed; +use pyth_sdk_cw::PriceFeed; use schemars::JsonSchema; use serde::{ Deserialize, @@ -11,9 +9,10 @@ use serde::{ }; use cosmwasm_std::{ + Addr, + Binary, Storage, Timestamp, - Binary, }; use cosmwasm_storage::{ @@ -27,8 +26,6 @@ use cosmwasm_storage::{ Singleton, }; -type HumanAddr = String; - pub static CONFIG_KEY: &[u8] = b"config"; pub static PRICE_INFO_KEY: &[u8] = b"price_info_v3"; @@ -37,22 +34,21 @@ pub static PRICE_INFO_KEY: &[u8] = b"price_info_v3"; /// This value considers attestation delay which currently might up to a minute. pub const VALID_TIME_PERIOD: Duration = Duration::from_secs(3 * 60); -#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, Hash, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash, JsonSchema)] pub struct PythDataSource { - pub emitter: Binary, + pub emitter: Binary, pub pyth_emitter_chain: u16, } // Guardian set information -#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct ConfigInfo { - pub owner: HumanAddr, - pub wormhole_contract: HumanAddr, - pub data_sources: HashSet, + pub owner: Addr, + pub wormhole_contract: Addr, + pub data_sources: HashSet, } - -#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct PriceInfo { pub arrival_time: Timestamp, diff --git a/cosmwasm/contracts/wormhole/.cargo/config b/cosmwasm/contracts/wormhole/.cargo/config deleted file mode 100644 index 2d5cce4e..00000000 --- a/cosmwasm/contracts/wormhole/.cargo/config +++ /dev/null @@ -1,5 +0,0 @@ -[alias] -wasm = "build --release --target wasm32-unknown-unknown" -wasm-debug = "build --target wasm32-unknown-unknown" -unit-test = "test --lib --features backtraces" -integration-test = "test --test integration" \ No newline at end of file diff --git a/cosmwasm/contracts/wormhole/Cargo.toml b/cosmwasm/contracts/wormhole/Cargo.toml deleted file mode 100644 index b8a4302d..00000000 --- a/cosmwasm/contracts/wormhole/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "wormhole-bridge-terra" -version = "0.1.0" -authors = ["Yuriy Savchenko "] -edition = "2018" -description = "Wormhole contract" - -[lib] -name = "wormhole" -crate-type = ["cdylib", "rlib"] - -[features] -backtraces = ["cosmwasm-std/backtraces"] -# use library feature to disable all init/handle/query exports -library = [] - -[dependencies] -cosmwasm-std = { version = "1.0.0" } -cosmwasm-storage = { version = "1.0.0" } -schemars = "0.8.1" -serde = { version = "1.0.103", default-features = false, features = ["derive"] } -thiserror = { version = "1.0.20" } -k256 = { version = "0.9.4", default-features = false, features = ["ecdsa"] } -getrandom = { version = "0.2", features = ["custom"] } -sha3 = { version = "0.9.1", default-features = false } -generic-array = { version = "0.14.4" } -hex = "0.4.2" -lazy_static = "1.4.0" - -[dev-dependencies] -cosmwasm-vm = { version = "1.0.0", default-features = false } -serde_json = "1.0" diff --git a/cosmwasm/contracts/wormhole/src/byte_utils.rs b/cosmwasm/contracts/wormhole/src/byte_utils.rs deleted file mode 100644 index 1f3b9ee9..00000000 --- a/cosmwasm/contracts/wormhole/src/byte_utils.rs +++ /dev/null @@ -1,101 +0,0 @@ -use cosmwasm_std::CanonicalAddr; - -pub trait ByteUtils { - fn get_u8(&self, index: usize) -> u8; - fn get_u16(&self, index: usize) -> u16; - fn get_u32(&self, index: usize) -> u32; - fn get_u64(&self, index: usize) -> u64; - - fn get_u128_be(&self, index: usize) -> u128; - /// High 128 then low 128 - fn get_u256(&self, index: usize) -> (u128, u128); - fn get_address(&self, index: usize) -> CanonicalAddr; - fn get_bytes32(&self, index: usize) -> &[u8]; - fn get_bytes(&self, index: usize, bytes: usize) -> &[u8]; - fn get_const_bytes(&self, index: usize) -> [u8; N]; -} - -impl ByteUtils for &[u8] { - fn get_u8(&self, index: usize) -> u8 { - self[index] - } - fn get_u16(&self, index: usize) -> u16 { - let mut bytes: [u8; 16 / 8] = [0; 16 / 8]; - bytes.copy_from_slice(&self[index..index + 2]); - u16::from_be_bytes(bytes) - } - fn get_u32(&self, index: usize) -> u32 { - let mut bytes: [u8; 32 / 8] = [0; 32 / 8]; - bytes.copy_from_slice(&self[index..index + 4]); - u32::from_be_bytes(bytes) - } - fn get_u64(&self, index: usize) -> u64 { - let mut bytes: [u8; 64 / 8] = [0; 64 / 8]; - bytes.copy_from_slice(&self[index..index + 8]); - u64::from_be_bytes(bytes) - } - fn get_u128_be(&self, index: usize) -> u128 { - let mut bytes: [u8; 128 / 8] = [0; 128 / 8]; - bytes.copy_from_slice(&self[index..index + 128 / 8]); - u128::from_be_bytes(bytes) - } - fn get_u256(&self, index: usize) -> (u128, u128) { - (self.get_u128_be(index), self.get_u128_be(index + 128 / 8)) - } - fn get_address(&self, index: usize) -> CanonicalAddr { - // 32 bytes are reserved for addresses, but wasmd uses both 32 and 20 bytes - // https://github.com/CosmWasm/wasmd/blob/ac92fdcf37388cc8dc24535f301f64395f8fb3da/x/wasm/types/types.go#L325 - if self.get_u128_be(index) >> 32 == 0 { - return CanonicalAddr::from(&self[index + 12..index + 32]) - } - return CanonicalAddr::from(&self[index..index + 32]) - } - fn get_bytes32(&self, index: usize) -> &[u8] { - &self[index..index + 32] - } - - fn get_bytes(&self, index: usize, bytes: usize) -> &[u8] { - &self[index..index + bytes] - } - - fn get_const_bytes(&self, index: usize) -> [u8; N] { - let mut bytes: [u8; N] = [0; N]; - bytes.copy_from_slice(&self[index..index + N]); - bytes - } -} - -/// Left-pad a 20 byte address with 0s -pub fn extend_address_to_32(addr: &CanonicalAddr) -> Vec { - extend_address_to_32_array(addr).to_vec() -} - -pub fn extend_address_to_32_array(addr: &CanonicalAddr) -> [u8; 32] { - let mut v: Vec = vec![0; 32 - addr.len()]; - v.extend(addr.as_slice()); - let mut result: [u8; 32] = [0; 32]; - result.copy_from_slice(&v); - result -} - -/// Turn a string into a fixed length array. If the string is shorter than the -/// resulting array, it gets padded with \0s on the right. If longer, it gets -/// truncated. -pub fn string_to_array(s: &str) -> [u8; N] { - let bytes = s.as_bytes(); - let len = usize::min(N, bytes.len()); - let zeros = vec![0; N - len]; - let padded = [bytes[..len].to_vec(), zeros].concat(); - let mut result: [u8; N] = [0; N]; - result.copy_from_slice(&padded); - result -} - -pub fn extend_string_to_32(s: &str) -> Vec { - string_to_array::<32>(s).to_vec() -} - -pub fn get_string_from_32(v: &Vec) -> String { - let s = String::from_utf8_lossy(v); - s.chars().filter(|c| c != &'\0').collect() -} diff --git a/cosmwasm/contracts/wormhole/src/contract.rs b/cosmwasm/contracts/wormhole/src/contract.rs deleted file mode 100644 index 949e0074..00000000 --- a/cosmwasm/contracts/wormhole/src/contract.rs +++ /dev/null @@ -1,417 +0,0 @@ -use cosmwasm_std::{ - entry_point, - has_coins, - to_binary, - BankMsg, - Binary, - Coin, - CosmosMsg, - Deps, - DepsMut, - Env, - MessageInfo, - Response, - StdError, - StdResult, - Storage, - WasmMsg, -}; - -use crate::{ - byte_utils::{ - extend_address_to_32, - ByteUtils, - }, - error::ContractError, - msg::{ - ExecuteMsg, - GetAddressHexResponse, - GetStateResponse, - GuardianSetInfoResponse, - InstantiateMsg, - MigrateMsg, - QueryMsg, - }, - state::{ - config, - config_read, - guardian_set_get, - guardian_set_set, - sequence_read, - sequence_set, - vaa_archive_add, - vaa_archive_check, - ConfigInfo, - ContractUpgrade, - GovernancePacket, - GuardianAddress, - GuardianSetInfo, - GuardianSetUpgrade, - ParsedVAA, - SetFee, - TransferFee, - }, -}; - -use k256::{ - ecdsa::{ - recoverable::{ - Id as RecoverableId, - Signature as RecoverableSignature, - }, - Signature, - VerifyingKey, - }, - EncodedPoint, -}; -use sha3::{ - Digest, - Keccak256, -}; - -use generic_array::GenericArray; -use std::convert::TryFrom; - -type HumanAddr = String; - -// Chain ID of Terra -const CHAIN_ID: u16 = 3; - -// Lock assets fee amount and denomination -const FEE_AMOUNT: u128 = 0; -pub const FEE_DENOMINATION: &str = "uluna"; - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> StdResult { - Ok(Response::default()) -} - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn instantiate( - deps: DepsMut, - _env: Env, - _info: MessageInfo, - msg: InstantiateMsg, -) -> StdResult { - // Save general wormhole info - let state = ConfigInfo { - gov_chain: msg.gov_chain, - gov_address: msg.gov_address.as_slice().to_vec(), - guardian_set_index: 0, - guardian_set_expirity: msg.guardian_set_expirity, - fee: Coin::new(FEE_AMOUNT, FEE_DENOMINATION), // 0.01 Luna (or 10000 uluna) fee by default - }; - config(deps.storage).save(&state)?; - - // Add initial guardian set to storage - guardian_set_set( - deps.storage, - state.guardian_set_index, - &msg.initial_guardian_set, - )?; - - Ok(Response::default()) -} - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> StdResult { - match msg { - ExecuteMsg::PostMessage { message, nonce } => { - handle_post_message(deps, env, info, &message.as_slice(), nonce) - } - ExecuteMsg::SubmitVAA { vaa } => handle_submit_vaa(deps, env, info, vaa.as_slice()), - } -} - -/// Process VAA message signed by quardians -fn handle_submit_vaa( - deps: DepsMut, - env: Env, - _info: MessageInfo, - data: &[u8], -) -> StdResult { - let state = config_read(deps.storage).load()?; - - let vaa = parse_and_verify_vaa(deps.storage, data, env.block.time.seconds())?; - vaa_archive_add(deps.storage, vaa.hash.as_slice())?; - - if state.gov_chain == vaa.emitter_chain && state.gov_address == vaa.emitter_address { - if state.guardian_set_index != vaa.guardian_set_index { - return Err(StdError::generic_err( - "governance VAAs must be signed by the current guardian set", - )); - } - return handle_governance_payload(deps, env, &vaa.payload); - } - - ContractError::InvalidVAAAction.std_err() -} - -fn handle_governance_payload(deps: DepsMut, env: Env, data: &Vec) -> StdResult { - let gov_packet = GovernancePacket::deserialize(&data)?; - - let module = String::from_utf8(gov_packet.module).unwrap(); - let module: String = module.chars().filter(|c| c != &'\0').collect(); - - if module != "Core" { - return Err(StdError::generic_err("this is not a valid module")); - } - - if gov_packet.chain != 0 && gov_packet.chain != CHAIN_ID { - return Err(StdError::generic_err( - "the governance VAA is for another chain", - )); - } - - match gov_packet.action { - 1u8 => vaa_update_contract(deps, env, &gov_packet.payload), - 2u8 => vaa_update_guardian_set(deps, env, &gov_packet.payload), - 3u8 => handle_set_fee(deps, env, &gov_packet.payload), - 4u8 => handle_transfer_fee(deps, env, &gov_packet.payload), - _ => ContractError::InvalidVAAAction.std_err(), - } -} - -/// Parses raw VAA data into a struct and verifies whether it contains sufficient signatures of an -/// active guardian set i.e. is valid according to Wormhole consensus rules -fn parse_and_verify_vaa( - storage: &dyn Storage, - data: &[u8], - block_time: u64, -) -> StdResult { - let vaa = ParsedVAA::deserialize(data)?; - - if vaa.version != 1 { - return ContractError::InvalidVersion.std_err(); - } - - // Check if VAA with this hash was already accepted - if vaa_archive_check(storage, vaa.hash.as_slice()) { - return ContractError::VaaAlreadyExecuted.std_err(); - } - - // Load and check guardian set - let guardian_set = guardian_set_get(storage, vaa.guardian_set_index); - let guardian_set: GuardianSetInfo = - guardian_set.or_else(|_| ContractError::InvalidGuardianSetIndex.std_err())?; - - if guardian_set.expiration_time != 0 && guardian_set.expiration_time < block_time { - return ContractError::GuardianSetExpired.std_err(); - } - if (vaa.len_signers as usize) < guardian_set.quorum() { - return ContractError::NoQuorum.std_err(); - } - - // Verify guardian signatures - let mut last_index: i32 = -1; - let mut pos = ParsedVAA::HEADER_LEN; - - for _ in 0..vaa.len_signers { - if pos + ParsedVAA::SIGNATURE_LEN > data.len() { - return ContractError::InvalidVAA.std_err(); - } - let index = data.get_u8(pos) as i32; - if index <= last_index { - return ContractError::WrongGuardianIndexOrder.std_err(); - } - last_index = index; - - let signature = Signature::try_from( - &data[pos + ParsedVAA::SIG_DATA_POS - ..pos + ParsedVAA::SIG_DATA_POS + ParsedVAA::SIG_DATA_LEN], - ) - .or_else(|_| ContractError::CannotDecodeSignature.std_err())?; - let id = RecoverableId::new(data.get_u8(pos + ParsedVAA::SIG_RECOVERY_POS)) - .or_else(|_| ContractError::CannotDecodeSignature.std_err())?; - let recoverable_signature = RecoverableSignature::new(&signature, id) - .or_else(|_| ContractError::CannotDecodeSignature.std_err())?; - - let verify_key = recoverable_signature - .recover_verify_key_from_digest_bytes(GenericArray::from_slice(vaa.hash.as_slice())) - .or_else(|_| ContractError::CannotRecoverKey.std_err())?; - - let index = index as usize; - if index >= guardian_set.addresses.len() { - return ContractError::TooManySignatures.std_err(); - } - if !keys_equal(&verify_key, &guardian_set.addresses[index]) { - return ContractError::GuardianSignatureError.std_err(); - } - pos += ParsedVAA::SIGNATURE_LEN; - } - - Ok(vaa) -} - -fn vaa_update_guardian_set(deps: DepsMut, env: Env, data: &Vec) -> StdResult { - /* Payload format - 0 uint32 new_index - 4 uint8 len(keys) - 5 [][20]uint8 guardian addresses - */ - - let mut state = config_read(deps.storage).load()?; - - let GuardianSetUpgrade { - new_guardian_set_index, - new_guardian_set, - } = GuardianSetUpgrade::deserialize(&data)?; - - if new_guardian_set_index != state.guardian_set_index + 1 { - return ContractError::GuardianSetIndexIncreaseError.std_err(); - } - - let old_guardian_set_index = state.guardian_set_index; - - state.guardian_set_index = new_guardian_set_index; - - guardian_set_set(deps.storage, state.guardian_set_index, &new_guardian_set)?; - - config(deps.storage).save(&state)?; - - let mut old_guardian_set = guardian_set_get(deps.storage, old_guardian_set_index)?; - old_guardian_set.expiration_time = env.block.time.seconds() + state.guardian_set_expirity; - guardian_set_set(deps.storage, old_guardian_set_index, &old_guardian_set)?; - - Ok(Response::new() - .add_attribute("action", "guardian_set_change") - .add_attribute("old", old_guardian_set_index.to_string()) - .add_attribute("new", state.guardian_set_index.to_string())) -} - -fn vaa_update_contract(_deps: DepsMut, env: Env, data: &Vec) -> StdResult { - /* Payload format - 0 [][32]uint8 new_contract - */ - - let ContractUpgrade { new_contract } = ContractUpgrade::deserialize(&data)?; - - Ok(Response::new() - .add_message(CosmosMsg::Wasm(WasmMsg::Migrate { - contract_addr: env.contract.address.to_string(), - new_code_id: new_contract, - msg: to_binary(&MigrateMsg {})?, - })) - .add_attribute("action", "contract_upgrade")) -} - -pub fn handle_set_fee(deps: DepsMut, _env: Env, data: &Vec) -> StdResult { - let set_fee_msg = SetFee::deserialize(&data)?; - - // Save new fees - let mut state = config_read(deps.storage).load()?; - state.fee = set_fee_msg.fee; - config(deps.storage).save(&state)?; - - Ok(Response::new() - .add_attribute("action", "fee_change") - .add_attribute("new_fee.amount", state.fee.amount.to_string()) - .add_attribute("new_fee.denom", state.fee.denom.to_string())) -} - -pub fn handle_transfer_fee(deps: DepsMut, _env: Env, data: &Vec) -> StdResult { - let transfer_msg = TransferFee::deserialize(&data)?; - - Ok(Response::new().add_message(CosmosMsg::Bank(BankMsg::Send { - to_address: deps.api.addr_humanize(&transfer_msg.recipient)?.to_string(), - amount: vec![transfer_msg.amount], - }))) -} - -fn handle_post_message( - deps: DepsMut, - env: Env, - info: MessageInfo, - message: &[u8], - nonce: u32, -) -> StdResult { - let state = config_read(deps.storage).load()?; - let fee = state.fee; - - // Check fee - if fee.amount.u128() > 0 && !has_coins(info.funds.as_ref(), &fee) { - return ContractError::FeeTooLow.std_err(); - } - - let emitter = extend_address_to_32(&deps.api.addr_canonicalize(&info.sender.as_str())?); - let sequence = sequence_read(deps.storage, emitter.as_slice()); - sequence_set(deps.storage, emitter.as_slice(), sequence + 1)?; - - Ok(Response::new() - .add_attribute("message.message", hex::encode(message)) - .add_attribute("message.sender", hex::encode(emitter)) - .add_attribute("message.chain_id", CHAIN_ID.to_string()) - .add_attribute("message.nonce", nonce.to_string()) - .add_attribute("message.sequence", sequence.to_string()) - .add_attribute("message.block_time", env.block.time.seconds().to_string())) -} - -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { - match msg { - QueryMsg::GuardianSetInfo {} => to_binary(&query_guardian_set_info(deps)?), - QueryMsg::VerifyVAA { vaa, block_time } => to_binary(&query_parse_and_verify_vaa( - deps, - &vaa.as_slice(), - block_time, - )?), - QueryMsg::GetState {} => to_binary(&query_state(deps)?), - QueryMsg::QueryAddressHex { address } => to_binary(&query_address_hex(deps, &address)?), - } -} - -pub fn query_guardian_set_info(deps: Deps) -> StdResult { - let state = config_read(deps.storage).load()?; - let guardian_set = guardian_set_get(deps.storage, state.guardian_set_index)?; - let res = GuardianSetInfoResponse { - guardian_set_index: state.guardian_set_index, - addresses: guardian_set.addresses, - }; - Ok(res) -} - -pub fn query_parse_and_verify_vaa( - deps: Deps, - data: &[u8], - block_time: u64, -) -> StdResult { - parse_and_verify_vaa(deps.storage, data, block_time) -} - -// returns the hex of the 32 byte address we use for some address on this chain -pub fn query_address_hex(deps: Deps, address: &HumanAddr) -> StdResult { - Ok(GetAddressHexResponse { - hex: hex::encode(extend_address_to_32(&deps.api.addr_canonicalize(&address)?)), - }) -} - -pub fn query_state(deps: Deps) -> StdResult { - let state = config_read(deps.storage).load()?; - let res = GetStateResponse { fee: state.fee }; - Ok(res) -} - -fn keys_equal(a: &VerifyingKey, b: &GuardianAddress) -> bool { - let mut hasher = Keccak256::new(); - - let point: EncodedPoint = EncodedPoint::from(a); - let point = point.decompress(); - if bool::from(point.is_none()) { - return false; - } - let point = point.unwrap(); - - hasher.update(&point.as_bytes()[1..]); - let a = &hasher.finalize()[12..]; - - let b = &b.bytes; - if a.len() != b.len() { - return false; - } - for (ai, bi) in a.iter().zip(b.as_slice().iter()) { - if ai != bi { - return false; - } - } - true -} diff --git a/cosmwasm/contracts/wormhole/src/error.rs b/cosmwasm/contracts/wormhole/src/error.rs deleted file mode 100644 index 67603f5d..00000000 --- a/cosmwasm/contracts/wormhole/src/error.rs +++ /dev/null @@ -1,113 +0,0 @@ -use cosmwasm_std::StdError; -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum ContractError { - /// Invalid VAA version - #[error("InvalidVersion")] - InvalidVersion, - - /// Guardian set with this index does not exist - #[error("InvalidGuardianSetIndex")] - InvalidGuardianSetIndex, - - /// Guardian set expiration date is zero or in the past - #[error("GuardianSetExpired")] - GuardianSetExpired, - - /// Not enough signers on the VAA - #[error("NoQuorum")] - NoQuorum, - - /// Wrong guardian index order, order must be ascending - #[error("WrongGuardianIndexOrder")] - WrongGuardianIndexOrder, - - /// Some problem with signature decoding from bytes - #[error("CannotDecodeSignature")] - CannotDecodeSignature, - - /// Some problem with public key recovery from the signature - #[error("CannotRecoverKey")] - CannotRecoverKey, - - /// Recovered pubkey from signature does not match guardian address - #[error("GuardianSignatureError")] - GuardianSignatureError, - - /// VAA action code not recognized - #[error("InvalidVAAAction")] - InvalidVAAAction, - - /// VAA guardian set is not current - #[error("NotCurrentGuardianSet")] - NotCurrentGuardianSet, - - /// Only 128-bit amounts are supported - #[error("AmountTooHigh")] - AmountTooHigh, - - /// Amount should be higher than zero - #[error("AmountTooLow")] - AmountTooLow, - - /// Source and target chain ids must be different - #[error("SameSourceAndTarget")] - SameSourceAndTarget, - - /// Target chain id must be the same as the current CHAIN_ID - #[error("WrongTargetChain")] - WrongTargetChain, - - /// Wrapped asset init hook sent twice for the same asset id - #[error("AssetAlreadyRegistered")] - AssetAlreadyRegistered, - - /// Guardian set must increase in steps of 1 - #[error("GuardianSetIndexIncreaseError")] - GuardianSetIndexIncreaseError, - - /// VAA was already executed - #[error("VaaAlreadyExecuted")] - VaaAlreadyExecuted, - - /// Message sender not permitted to execute this operation - #[error("PermissionDenied")] - PermissionDenied, - - /// Could not decode target address from canonical to human-readable form - #[error("WrongTargetAddressFormat")] - WrongTargetAddressFormat, - - /// More signatures than active guardians found - #[error("TooManySignatures")] - TooManySignatures, - - /// Wrapped asset not found in the registry - #[error("AssetNotFound")] - AssetNotFound, - - /// Generic error when there is a problem with VAA structure - #[error("InvalidVAA")] - InvalidVAA, - - /// Thrown when fee is enabled for the action, but was not sent with the transaction - #[error("FeeTooLow")] - FeeTooLow, - - /// Registering asset outside of the wormhole - #[error("RegistrationForbidden")] - RegistrationForbidden, -} - -impl ContractError { - pub fn std(&self) -> StdError { - StdError::GenericErr { - msg: format!("{}", self), - } - } - - pub fn std_err(&self) -> Result { - Err(self.std()) - } -} diff --git a/cosmwasm/contracts/wormhole/src/lib.rs b/cosmwasm/contracts/wormhole/src/lib.rs deleted file mode 100644 index 610d16ed..00000000 --- a/cosmwasm/contracts/wormhole/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub mod byte_utils; -pub mod contract; -pub mod error; -pub mod msg; -pub mod state; - -pub use crate::error::ContractError; diff --git a/cosmwasm/contracts/wormhole/src/msg.rs b/cosmwasm/contracts/wormhole/src/msg.rs deleted file mode 100644 index 9653c052..00000000 --- a/cosmwasm/contracts/wormhole/src/msg.rs +++ /dev/null @@ -1,71 +0,0 @@ -use cosmwasm_std::{ - Binary, - Coin, -}; -use schemars::JsonSchema; -use serde::{ - Deserialize, - Serialize, -}; - -use crate::state::{ - GuardianAddress, - GuardianSetInfo, -}; - -type HumanAddr = String; - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct InstantiateMsg { - pub gov_chain: u16, - pub gov_address: Binary, - - pub initial_guardian_set: GuardianSetInfo, - pub guardian_set_expirity: u64, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum ExecuteMsg { - SubmitVAA { vaa: Binary }, - PostMessage { message: Binary, nonce: u32 }, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct MigrateMsg { -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum QueryMsg { - GuardianSetInfo {}, - VerifyVAA { vaa: Binary, block_time: u64 }, - GetState {}, - QueryAddressHex { address: HumanAddr }, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct GuardianSetInfoResponse { - pub guardian_set_index: u32, // Current guardian set index - pub addresses: Vec, // List of querdian addresses -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct WrappedRegistryResponse { - pub address: HumanAddr, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct GetStateResponse { - pub fee: Coin, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct GetAddressHexResponse { - pub hex: String, -} diff --git a/cosmwasm/contracts/wormhole/src/state.rs b/cosmwasm/contracts/wormhole/src/state.rs deleted file mode 100644 index 4c9d23ba..00000000 --- a/cosmwasm/contracts/wormhole/src/state.rs +++ /dev/null @@ -1,393 +0,0 @@ -use schemars::{ - JsonSchema, -}; -use serde::{ - Deserialize, - Serialize, -}; - -use cosmwasm_std::{ - Binary, - CanonicalAddr, - Coin, - StdResult, - Storage, - Uint128, -}; -use cosmwasm_storage::{ - bucket, - bucket_read, - singleton, - singleton_read, - Bucket, - ReadonlyBucket, - ReadonlySingleton, - Singleton, -}; - -use crate::{ - byte_utils::ByteUtils, - error::ContractError, -}; - -use sha3::{ - Digest, - Keccak256, -}; - -type HumanAddr = String; - -pub static CONFIG_KEY: &[u8] = b"config"; -pub static GUARDIAN_SET_KEY: &[u8] = b"guardian_set"; -pub static SEQUENCE_KEY: &[u8] = b"sequence"; -pub static WRAPPED_ASSET_KEY: &[u8] = b"wrapped_asset"; -pub static WRAPPED_ASSET_ADDRESS_KEY: &[u8] = b"wrapped_asset_address"; - -// Guardian set information -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct ConfigInfo { - // Current active guardian set - pub guardian_set_index: u32, - - // Period for which a guardian set stays active after it has been replaced - pub guardian_set_expirity: u64, - - // governance contract details - pub gov_chain: u16, - pub gov_address: Vec, - - // Message sending fee - pub fee: Coin, -} - -// Validator Action Approval(VAA) data -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct ParsedVAA { - pub version: u8, - pub guardian_set_index: u32, - pub timestamp: u32, - pub nonce: u32, - pub len_signers: u8, - - pub emitter_chain: u16, - pub emitter_address: Vec, - pub sequence: u64, - pub consistency_level: u8, - pub payload: Vec, - - pub hash: Vec, -} - -impl ParsedVAA { - /* VAA format: - - header (length 6): - 0 uint8 version (0x01) - 1 uint32 guardian set index - 5 uint8 len signatures - - per signature (length 66): - 0 uint8 index of the signer (in guardian keys) - 1 [65]uint8 signature - - body: - 0 uint32 timestamp (unix in seconds) - 4 uint32 nonce - 8 uint16 emitter_chain - 10 [32]uint8 emitter_address - 42 uint64 sequence - 50 uint8 consistency_level - 51 []uint8 payload - */ - - pub const HEADER_LEN: usize = 6; - pub const SIGNATURE_LEN: usize = 66; - - pub const GUARDIAN_SET_INDEX_POS: usize = 1; - pub const LEN_SIGNER_POS: usize = 5; - - pub const VAA_NONCE_POS: usize = 4; - pub const VAA_EMITTER_CHAIN_POS: usize = 8; - pub const VAA_EMITTER_ADDRESS_POS: usize = 10; - pub const VAA_SEQUENCE_POS: usize = 42; - pub const VAA_CONSISTENCY_LEVEL_POS: usize = 50; - pub const VAA_PAYLOAD_POS: usize = 51; - - // Signature data offsets in the signature block - pub const SIG_DATA_POS: usize = 1; - // Signature length minus recovery id at the end - pub const SIG_DATA_LEN: usize = 64; - // Recovery byte is last after the main signature - pub const SIG_RECOVERY_POS: usize = Self::SIG_DATA_POS + Self::SIG_DATA_LEN; - - pub fn deserialize(data: &[u8]) -> StdResult { - let version = data.get_u8(0); - - // Load 4 bytes starting from index 1 - let guardian_set_index: u32 = data.get_u32(Self::GUARDIAN_SET_INDEX_POS); - let len_signers = data.get_u8(Self::LEN_SIGNER_POS) as usize; - let body_offset: usize = Self::HEADER_LEN + Self::SIGNATURE_LEN * len_signers as usize; - - // Hash the body - if body_offset >= data.len() { - return ContractError::InvalidVAA.std_err(); - } - let body = &data[body_offset..]; - let mut hasher = Keccak256::new(); - hasher.update(body); - let hash = hasher.finalize().to_vec(); - - // Rehash the hash - let mut hasher = Keccak256::new(); - hasher.update(hash); - let hash = hasher.finalize().to_vec(); - - // Signatures valid, apply VAA - if body_offset + Self::VAA_PAYLOAD_POS > data.len() { - return ContractError::InvalidVAA.std_err(); - } - - let timestamp = data.get_u32(body_offset); - let nonce = data.get_u32(body_offset + Self::VAA_NONCE_POS); - let emitter_chain = data.get_u16(body_offset + Self::VAA_EMITTER_CHAIN_POS); - let emitter_address = data - .get_bytes32(body_offset + Self::VAA_EMITTER_ADDRESS_POS) - .to_vec(); - let sequence = data.get_u64(body_offset + Self::VAA_SEQUENCE_POS); - let consistency_level = data.get_u8(body_offset + Self::VAA_CONSISTENCY_LEVEL_POS); - let payload = data[body_offset + Self::VAA_PAYLOAD_POS..].to_vec(); - - Ok(ParsedVAA { - version, - guardian_set_index, - timestamp, - nonce, - len_signers: len_signers as u8, - emitter_chain, - emitter_address, - sequence, - consistency_level, - payload, - hash, - }) - } -} - -// Guardian address -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct GuardianAddress { - pub bytes: Binary, // 20-byte addresses -} - -use crate::contract::FEE_DENOMINATION; -#[cfg(test)] -use hex; - -#[cfg(test)] -impl GuardianAddress { - pub fn from(string: &str) -> GuardianAddress { - GuardianAddress { - bytes: hex::decode(string).expect("Decoding failed").into(), - } - } -} - -// Guardian set information -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct GuardianSetInfo { - pub addresses: Vec, - // List of guardian addresses - pub expiration_time: u64, // Guardian set expiration time -} - -impl GuardianSetInfo { - pub fn quorum(&self) -> usize { - // allow quorum of 0 for testing purposes... - if self.addresses.len() == 0 { - return 0; - } - ((self.addresses.len() * 10 / 3) * 2) / 10 + 1 - } -} - -// Wormhole contract generic information -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct WormholeInfo { - // Period for which a guardian set stays active after it has been replaced - pub guardian_set_expirity: u64, -} - -pub fn config(storage: &mut dyn Storage) -> Singleton { - singleton(storage, CONFIG_KEY) -} - -pub fn config_read(storage: &dyn Storage) -> ReadonlySingleton { - singleton_read(storage, CONFIG_KEY) -} - -pub fn guardian_set_set( - storage: &mut dyn Storage, - index: u32, - data: &GuardianSetInfo, -) -> StdResult<()> { - bucket(storage, GUARDIAN_SET_KEY).save(&index.to_be_bytes(), data) -} - -pub fn guardian_set_get(storage: &dyn Storage, index: u32) -> StdResult { - bucket_read(storage, GUARDIAN_SET_KEY).load(&index.to_be_bytes()) -} - -pub fn sequence_set(storage: &mut dyn Storage, emitter: &[u8], sequence: u64) -> StdResult<()> { - bucket(storage, SEQUENCE_KEY).save(emitter, &sequence) -} - -pub fn sequence_read(storage: &dyn Storage, emitter: &[u8]) -> u64 { - bucket_read(storage, SEQUENCE_KEY) - .load(&emitter) - .or::(Ok(0)) - .unwrap() -} - -pub fn vaa_archive_add(storage: &mut dyn Storage, hash: &[u8]) -> StdResult<()> { - bucket(storage, GUARDIAN_SET_KEY).save(hash, &true) -} - -pub fn vaa_archive_check(storage: &dyn Storage, hash: &[u8]) -> bool { - bucket_read(storage, GUARDIAN_SET_KEY) - .load(&hash) - .or::(Ok(false)) - .unwrap() -} - -pub fn wrapped_asset(storage: &mut dyn Storage) -> Bucket { - bucket(storage, WRAPPED_ASSET_KEY) -} - -pub fn wrapped_asset_read(storage: &dyn Storage) -> ReadonlyBucket { - bucket_read(storage, WRAPPED_ASSET_KEY) -} - -pub fn wrapped_asset_address(storage: &mut dyn Storage) -> Bucket> { - bucket(storage, WRAPPED_ASSET_ADDRESS_KEY) -} - -pub fn wrapped_asset_address_read(storage: &dyn Storage) -> ReadonlyBucket> { - bucket_read(storage, WRAPPED_ASSET_ADDRESS_KEY) -} - -pub struct GovernancePacket { - pub module: Vec, - pub action: u8, - pub chain: u16, - pub payload: Vec, -} - -impl GovernancePacket { - pub fn deserialize(data: &Vec) -> StdResult { - let data = data.as_slice(); - let module = data.get_bytes32(0).to_vec(); - let action = data.get_u8(32); - let chain = data.get_u16(33); - let payload = data[35..].to_vec(); - - Ok(GovernancePacket { - module, - action, - chain, - payload, - }) - } -} - -// action 1 -pub struct ContractUpgrade { - pub new_contract: u64, -} - -// action 2 -pub struct GuardianSetUpgrade { - pub new_guardian_set_index: u32, - pub new_guardian_set: GuardianSetInfo, -} - -impl ContractUpgrade { - pub fn deserialize(data: &Vec) -> StdResult { - let data = data.as_slice(); - let new_contract = data.get_u64(24); - Ok(ContractUpgrade { - new_contract, - }) - } -} - -impl GuardianSetUpgrade { - pub fn deserialize(data: &Vec) -> StdResult { - const ADDRESS_LEN: usize = 20; - - let data = data.as_slice(); - let new_guardian_set_index = data.get_u32(0); - - let n_guardians = data.get_u8(4); - - let mut addresses = vec![]; - - for i in 0..n_guardians { - let pos = 5 + (i as usize) * ADDRESS_LEN; - if pos + ADDRESS_LEN > data.len() { - return ContractError::InvalidVAA.std_err(); - } - - addresses.push(GuardianAddress { - bytes: data[pos..pos + ADDRESS_LEN].to_vec().into(), - }); - } - - let new_guardian_set = GuardianSetInfo { - addresses, - expiration_time: 0, - }; - - return Ok(GuardianSetUpgrade { - new_guardian_set_index, - new_guardian_set, - }); - } -} - -// action 3 -pub struct SetFee { - pub fee: Coin, -} - -impl SetFee { - pub fn deserialize(data: &Vec) -> StdResult { - let data = data.as_slice(); - - let (_, amount) = data.get_u256(0); - let fee = Coin { - denom: String::from(FEE_DENOMINATION), - amount: Uint128::new(amount), - }; - Ok(SetFee { fee }) - } -} - -// action 4 -pub struct TransferFee { - pub amount: Coin, - pub recipient: CanonicalAddr, -} - -impl TransferFee { - pub fn deserialize(data: &Vec) -> StdResult { - let data = data.as_slice(); - let recipient = data.get_address(0); - - let (_, amount) = data.get_u256(32); - let amount = Coin { - denom: String::from(FEE_DENOMINATION), - amount: Uint128::new(amount), - }; - Ok(TransferFee { amount, recipient }) - } -} diff --git a/cosmwasm/tools/deploy-pyth-bridge.js b/cosmwasm/tools/deploy-pyth-bridge.js index ab1b974b..b1d02dae 100644 --- a/cosmwasm/tools/deploy-pyth-bridge.js +++ b/cosmwasm/tools/deploy-pyth-bridge.js @@ -182,7 +182,7 @@ if (argv.instantiate) { throw(e); } }); - console.log(`Instantiated Pyth Bridge at ${address} (${convert_terra_address_to_hex(address)})`); + console.log(`Instantiated Pyth at ${address} (${convert_terra_address_to_hex(address)})`); return address; } diff --git a/cosmwasm/tools/deploy.js b/cosmwasm/tools/deploy.js index 4b5f2179..6191ddd3 100644 --- a/cosmwasm/tools/deploy.js +++ b/cosmwasm/tools/deploy.js @@ -1,3 +1,8 @@ +// Deploy Wormhole and Pyth contract to Tilt. If you want to +// test the contracts locally you need to build the wormhole contract +// as well. You can use Dockerfile.cosmwasm in the root of this repo +// to do that. + import { LCDClient, MnemonicKey } from "@terra-money/terra.js"; import { MsgInstantiateContract, @@ -14,7 +19,7 @@ import { zeroPad } from "ethers/lib/utils.js"; */ const artifacts = [ "wormhole.wasm", - "pyth_bridge.wasm", + "pyth_cosmwasm.wasm", ]; /* Check that the artifact folder contains all the wasm files we expect and nothing else */ @@ -152,13 +157,15 @@ addresses["wormhole.wasm"] = await instantiate("wormhole.wasm", { ], expiration_time: 0, }, + chain_id: 18, + fee_denom: "uluna", }, "wormhole"); const pythEmitterAddress = "71f8dcb863d176e2c420ad6610cf687359612b6fb392e0642b0ca6b1f186aa3b"; const pythChain = 1; -addresses["pyth_bridge.wasm"] = await instantiate("pyth_bridge.wasm", { +addresses["pyth_cosmwasm.wasm"] = await instantiate("pyth_cosmwasm.wasm", { wormhole_contract: addresses["wormhole.wasm"], pyth_emitter: Buffer.from(pythEmitterAddress, "hex").toString( "base64" diff --git a/solana/memmap2-rs/Cargo.toml b/solana/memmap2-rs/Cargo.toml deleted file mode 100644 index 263f539a..00000000 --- a/solana/memmap2-rs/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "memmap2" -version = "0.1.0" -authors = ["Dan Burkert ", "Evgeniy Reizner "] -license = "MIT/Apache-2.0" -repository = "https://github.com/RazrFalcon/memmap2-rs" -documentation = "https://docs.rs/memmap2" -description = "Cross-platform Rust API for memory-mapped file IO" -keywords = ["mmap", "memory-map", "io", "file"] -edition = "2018" - -[target.'cfg(unix)'.dependencies] -libc = "0.2" - -[dev-dependencies] -tempdir = "0.3" diff --git a/solana/memmap2-rs/LICENSE-APACHE b/solana/memmap2-rs/LICENSE-APACHE deleted file mode 100644 index 7be3d81a..00000000 --- a/solana/memmap2-rs/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [2015] [Dan Burkert] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/solana/memmap2-rs/LICENSE-MIT b/solana/memmap2-rs/LICENSE-MIT deleted file mode 100644 index 5cc9371f..00000000 --- a/solana/memmap2-rs/LICENSE-MIT +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2020 Evgeniy Reizner -Copyright (c) 2015 Dan Burkert - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/solana/memmap2-rs/README.md b/solana/memmap2-rs/README.md deleted file mode 100644 index 19667ded..00000000 --- a/solana/memmap2-rs/README.md +++ /dev/null @@ -1,3 +0,0 @@ -This is a fork of https://github.com/RazrFalcon/memmap2-rs which implements stubs for all functions which is required -to make the client code compile to WASM. It uses the v0.3.0 code (which has stubs) but was adapted to the v0.1.0 API -which is used by Solana. \ No newline at end of file diff --git a/solana/memmap2-rs/src/lib.rs b/solana/memmap2-rs/src/lib.rs deleted file mode 100644 index 916b2beb..00000000 --- a/solana/memmap2-rs/src/lib.rs +++ /dev/null @@ -1,839 +0,0 @@ -//! A cross-platform Rust API for memory mapped buffers. - -#![doc(html_root_url = "https://docs.rs/memmap2/0.3.0")] - - -mod stub; -use crate::stub::MmapInner; - -use std::fmt; -#[cfg(unix)] -use std::fs::File; -use std::io::{Error, ErrorKind, Result}; -use std::ops::{Deref, DerefMut}; -#[cfg(unix)] -use std::os::unix::io::AsRawFd; -use std::slice; -use std::usize; - - -pub struct MmapRawDescriptor(i32); - -pub trait MmapAsRawDesc { - fn as_raw_desc(&self) -> MmapRawDescriptor; -} - -#[cfg(unix)] -impl MmapAsRawDesc for &File { - fn as_raw_desc(&self) -> MmapRawDescriptor { - MmapRawDescriptor(self.as_raw_fd()) - } -} - - -/// A memory map builder, providing advanced options and flags for specifying memory map behavior. -/// -/// `MmapOptions` can be used to create an anonymous memory map using [`map_anon()`], or a -/// file-backed memory map using one of [`map()`], [`map_mut()`], [`map_exec()`], -/// [`map_copy()`], or [`map_copy_read_only()`]. -/// -/// ## Safety -/// -/// All file-backed memory map constructors are marked `unsafe` because of the potential for -/// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or -/// out of process. Applications must consider the risk and take appropriate precautions when -/// using file-backed maps. Solutions such as file permissions, locks or process-private (e.g. -/// unlinked) files exist but are platform specific and limited. -/// -/// [`map_anon()`]: MmapOptions::map_anon() -/// [`map()`]: MmapOptions::map() -/// [`map_mut()`]: MmapOptions::map_mut() -/// [`map_exec()`]: MmapOptions::map_exec() -/// [`map_copy()`]: MmapOptions::map_copy() -/// [`map_copy_read_only()`]: MmapOptions::map_copy_read_only() -#[derive(Clone, Debug, Default)] -pub struct MmapOptions { - offset: u64, - len: Option, - stack: bool, - populate: bool, -} - -impl MmapOptions { - /// Creates a new set of options for configuring and creating a memory map. - /// - /// # Example - /// - /// ``` - /// use memmap2::{MmapMut, MmapOptions}; - /// # use std::io::Result; - /// - /// # fn main() -> Result<()> { - /// // Create a new memory map builder. - /// let mut mmap_options = MmapOptions::new(); - /// - /// // Configure the memory map builder using option setters, then create - /// // a memory map using one of `mmap_options.map_anon`, `mmap_options.map`, - /// // `mmap_options.map_mut`, `mmap_options.map_exec`, or `mmap_options.map_copy`: - /// let mut mmap: MmapMut = mmap_options.len(36).map_anon()?; - /// - /// // Use the memory map: - /// mmap.copy_from_slice(b"...data to copy to the memory map..."); - /// # Ok(()) - /// # } - /// ``` - pub fn new() -> MmapOptions { - MmapOptions::default() - } - - /// Configures the memory map to start at byte `offset` from the beginning of the file. - /// - /// This option has no effect on anonymous memory maps. - /// - /// By default, the offset is 0. - /// - /// # Example - /// - /// ``` - /// use memmap2::MmapOptions; - /// use std::fs::File; - /// - /// # fn main() -> std::io::Result<()> { - /// let mmap = unsafe { - /// MmapOptions::new() - /// .offset(30) - /// .map(&File::open("LICENSE-APACHE")?)? - /// }; - /// assert_eq!(&b"Apache License"[..], - /// &mmap[..14]); - /// # Ok(()) - /// # } - /// ``` - pub fn offset(&mut self, offset: u64) -> &mut Self { - self.offset = offset; - self - } - - /// Configures the created memory mapped buffer to be `len` bytes long. - /// - /// This option is mandatory for anonymous memory maps. - /// - /// For file-backed memory maps, the length will default to the file length. - /// - /// # Example - /// - /// ``` - /// use memmap2::MmapOptions; - /// use std::fs::File; - /// - /// # fn main() -> std::io::Result<()> { - /// let mmap = unsafe { - /// MmapOptions::new() - /// .len(9) - /// .map(&File::open("README.md")?)? - /// }; - /// assert_eq!(&b"# memmap2"[..], &mmap[..]); - /// # Ok(()) - /// # } - /// ``` - pub fn len(&mut self, len: usize) -> &mut Self { - self.len = Some(len); - self - } - - /// Returns the configured length, or the length of the provided file. - fn get_len(&self, _file: &T) -> Result { - self.len.map(Ok).unwrap_or_else(|| { - let file_len = 0; - let len = file_len as u64 - self.offset; - if len > (usize::MAX as u64) { - return Err(Error::new( - ErrorKind::InvalidData, - "memory map length overflows usize", - )); - } - Ok(len as usize) - }) - } - - /// Configures the anonymous memory map to be suitable for a process or thread stack. - /// - /// This option corresponds to the `MAP_STACK` flag on Linux. It has no effect on Windows. - /// - /// This option has no effect on file-backed memory maps. - /// - /// # Example - /// - /// ``` - /// use memmap2::MmapOptions; - /// - /// # fn main() -> std::io::Result<()> { - /// let stack = MmapOptions::new().stack().len(4096).map_anon(); - /// # Ok(()) - /// # } - /// ``` - pub fn stack(&mut self) -> &mut Self { - self.stack = true; - self - } - - /// Populate (prefault) page tables for a mapping. - /// - /// For a file mapping, this causes read-ahead on the file. This will help to reduce blocking on page faults later. - /// - /// This option corresponds to the `MAP_POPULATE` flag on Linux. It has no effect on Windows. - /// - /// # Example - /// - /// ``` - /// use memmap2::MmapOptions; - /// use std::fs::File; - /// - /// # fn main() -> std::io::Result<()> { - /// let file = File::open("LICENSE-MIT")?; - /// - /// let mmap = unsafe { - /// MmapOptions::new().populate().map(&file)? - /// }; - /// - /// assert_eq!(&b"Copyright"[..], &mmap[..9]); - /// # Ok(()) - /// # } - /// ``` - pub fn populate(&mut self) -> &mut Self { - self.populate = true; - self - } - - /// Creates a read-only memory map backed by a file. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read permissions. - /// - /// # Example - /// - /// ``` - /// use memmap2::MmapOptions; - /// use std::fs::File; - /// use std::io::Read; - /// - /// # fn main() -> std::io::Result<()> { - /// let mut file = File::open("LICENSE-APACHE")?; - /// - /// let mut contents = Vec::new(); - /// file.read_to_end(&mut contents)?; - /// - /// let mmap = unsafe { - /// MmapOptions::new().map(&file)? - /// }; - /// - /// assert_eq!(&contents[..], &mmap[..]); - /// # Ok(()) - /// # } - /// ``` - pub unsafe fn map(&self, file: T) -> Result { - let desc = file.as_raw_desc(); - - MmapInner::map(self.get_len(&file)?, desc.0, self.offset, self.populate) - .map(|inner| Mmap { inner }) - } - - /// Creates a readable and executable memory map backed by a file. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read permissions. - pub unsafe fn map_exec(&self, file: T) -> Result { - let desc = file.as_raw_desc(); - - MmapInner::map_exec(self.get_len(&file)?, desc.0, self.offset, self.populate) - .map(|inner| Mmap { inner: inner }) - } - - /// Creates a writeable memory map backed by a file. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read and write permissions. - /// - /// # Example - /// - /// ``` - /// # extern crate memmap2; - /// # extern crate tempdir; - /// # - /// use std::fs::OpenOptions; - /// use std::path::PathBuf; - /// - /// use memmap2::MmapOptions; - /// # - /// # fn main() -> std::io::Result<()> { - /// # let tempdir = tempdir::TempDir::new("mmap")?; - /// let path: PathBuf = /* path to file */ - /// # tempdir.path().join("map_mut"); - /// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?; - /// file.set_len(13)?; - /// - /// let mut mmap = unsafe { - /// MmapOptions::new().map_mut(&file)? - /// }; - /// - /// mmap.copy_from_slice(b"Hello, world!"); - /// # Ok(()) - /// # } - /// ``` - pub unsafe fn map_mut(&self, file: T) -> Result { - let desc = file.as_raw_desc(); - - MmapInner::map_mut(self.get_len(&file)?, desc.0, self.offset, self.populate) - .map(|inner| MmapMut { inner: inner }) - } - - /// Creates a copy-on-write memory map backed by a file. - /// - /// Data written to the memory map will not be visible by other processes, - /// and will not be carried through to the underlying file. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with writable permissions. - /// - /// # Example - /// - /// ``` - /// use memmap2::MmapOptions; - /// use std::fs::File; - /// use std::io::Write; - /// - /// # fn main() -> std::io::Result<()> { - /// let file = File::open("LICENSE-APACHE")?; - /// let mut mmap = unsafe { MmapOptions::new().map_copy(&file)? }; - /// (&mut mmap[..]).write_all(b"Hello, world!")?; - /// # Ok(()) - /// # } - /// ``` - pub unsafe fn map_copy(&self, file: T) -> Result { - let desc = file.as_raw_desc(); - - MmapInner::map_copy(self.get_len(&file)?, desc.0, self.offset, self.populate) - .map(|inner| MmapMut { inner: inner }) - } - - /// Creates a copy-on-write read-only memory map backed by a file. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read permissions. - /// - /// # Example - /// - /// ``` - /// use memmap2::MmapOptions; - /// use std::fs::File; - /// use std::io::Read; - /// - /// # fn main() -> std::io::Result<()> { - /// let mut file = File::open("README.md")?; - /// - /// let mut contents = Vec::new(); - /// file.read_to_end(&mut contents)?; - /// - /// let mmap = unsafe { - /// MmapOptions::new().map_copy_read_only(&file)? - /// }; - /// - /// assert_eq!(&contents[..], &mmap[..]); - /// # Ok(()) - /// # } - /// ``` - pub unsafe fn map_copy_read_only(&self, file: T) -> Result { - let desc = file.as_raw_desc(); - - MmapInner::map_copy_read_only(self.get_len(&file)?, desc.0, self.offset, self.populate) - .map(|inner| Mmap { inner: inner }) - } - - /// Creates an anonymous memory map. - /// - /// Note: the memory map length must be configured to be greater than 0 before creating an - /// anonymous memory map using `MmapOptions::len()`. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails. - pub fn map_anon(&self) -> Result { - MmapInner::map_anon(self.len.unwrap_or(0), self.stack).map(|inner| MmapMut { inner }) - } - - /// Creates a raw memory map. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read and write permissions. - pub fn map_raw(&self, file: T) -> Result { - let desc = file.as_raw_desc(); - - MmapInner::map_mut(self.get_len(&file)?, desc.0, self.offset, self.populate) - .map(|inner| MmapRaw { inner: inner }) - } -} - -/// A handle to an immutable memory mapped buffer. -/// -/// A `Mmap` may be backed by a file, or it can be anonymous map, backed by volatile memory. Use -/// [`MmapOptions`] or [`map()`] to create a file-backed memory map. To create an immutable -/// anonymous memory map, first create a mutable anonymous memory map, and then make it immutable -/// with [`MmapMut::make_read_only()`]. -/// -/// A file backed `Mmap` is created by `&File` reference, and will remain valid even after the -/// `File` is dropped. In other words, the `Mmap` handle is completely independent of the `File` -/// used to create it. For consistency, on some platforms this is achieved by duplicating the -/// underlying file handle. The memory will be unmapped when the `Mmap` handle is dropped. -/// -/// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping -/// the mapped pages into physical memory) though the details of this are platform specific. -/// -/// `Mmap` is [`Sync`](std::marker::Sync) and [`Send`](std::marker::Send). -/// -/// ## Safety -/// -/// All file-backed memory map constructors are marked `unsafe` because of the potential for -/// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or -/// out of process. Applications must consider the risk and take appropriate precautions when using -/// file-backed maps. Solutions such as file permissions, locks or process-private (e.g. unlinked) -/// files exist but are platform specific and limited. -/// -/// ## Example -/// -/// ``` -/// use memmap2::MmapOptions; -/// use std::io::Write; -/// use std::fs::File; -/// -/// # fn main() -> std::io::Result<()> { -/// let file = File::open("README.md")?; -/// let mmap = unsafe { MmapOptions::new().map(&file)? }; -/// assert_eq!(b"# memmap2", &mmap[0..9]); -/// # Ok(()) -/// # } -/// ``` -/// -/// See [`MmapMut`] for the mutable version. -/// -/// [`map()`]: Mmap::map() -pub struct Mmap { - inner: MmapInner, -} - -impl Mmap { - /// Creates a read-only memory map backed by a file. - /// - /// This is equivalent to calling `MmapOptions::new().map(file)`. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read permissions. - /// - /// # Example - /// - /// ``` - /// use std::fs::File; - /// use std::io::Read; - /// - /// use memmap2::Mmap; - /// - /// # fn main() -> std::io::Result<()> { - /// let mut file = File::open("LICENSE-APACHE")?; - /// - /// let mut contents = Vec::new(); - /// file.read_to_end(&mut contents)?; - /// - /// let mmap = unsafe { Mmap::map(&file)? }; - /// - /// assert_eq!(&contents[..], &mmap[..]); - /// # Ok(()) - /// # } - /// ``` - pub unsafe fn map(file: T) -> Result { - MmapOptions::new().map(file) - } - - /// Transition the memory map to be writable. - /// - /// If the memory map is file-backed, the file must have been opened with write permissions. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with writable permissions. - /// - /// # Example - /// - /// ``` - /// # extern crate memmap2; - /// # extern crate tempdir; - /// # - /// use memmap2::Mmap; - /// use std::ops::DerefMut; - /// use std::io::Write; - /// # use std::fs::OpenOptions; - /// - /// # fn main() -> std::io::Result<()> { - /// # let tempdir = tempdir::TempDir::new("mmap")?; - /// let file = /* file opened with write permissions */ - /// # OpenOptions::new() - /// # .read(true) - /// # .write(true) - /// # .create(true) - /// # .open(tempdir.path() - /// # .join("make_mut"))?; - /// # file.set_len(128)?; - /// let mmap = unsafe { Mmap::map(&file)? }; - /// // ... use the read-only memory map ... - /// let mut mut_mmap = mmap.make_mut()?; - /// mut_mmap.deref_mut().write_all(b"hello, world!")?; - /// # Ok(()) - /// # } - /// ``` - pub fn make_mut(mut self) -> Result { - self.inner.make_mut()?; - Ok(MmapMut { inner: self.inner }) - } -} - -impl Deref for Mmap { - type Target = [u8]; - - #[inline] - fn deref(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.inner.ptr(), self.inner.len()) } - } -} - -impl AsRef<[u8]> for Mmap { - #[inline] - fn as_ref(&self) -> &[u8] { - self.deref() - } -} - -impl fmt::Debug for Mmap { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("Mmap") - .field("ptr", &self.as_ptr()) - .field("len", &self.len()) - .finish() - } -} - -/// A handle to a raw memory mapped buffer. -/// -/// This struct never hands out references to its interior, only raw pointers. -/// This can be helpful when creating shared memory maps between untrusted processes. -pub struct MmapRaw { - inner: MmapInner, -} - -impl MmapRaw { - /// Creates a writeable memory map backed by a file. - /// - /// This is equivalent to calling `MmapOptions::new().map_raw(file)`. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read and write permissions. - pub fn map_raw(file: T) -> Result { - MmapOptions::new().map_raw(file) - } - - /// Returns a raw pointer to the memory mapped file. - /// - /// Before dereferencing this pointer, you have to make sure that the file has not been - /// truncated since the memory map was created. - /// Avoiding this will not introduce memory safety issues in Rust terms, - /// but will cause SIGBUS (or equivalent) signal. - #[inline] - pub fn as_ptr(&self) -> *const u8 { - self.inner.ptr() - } - - /// Returns an unsafe mutable pointer to the memory mapped file. - /// - /// Before dereferencing this pointer, you have to make sure that the file has not been - /// truncated since the memory map was created. - /// Avoiding this will not introduce memory safety issues in Rust terms, - /// but will cause SIGBUS (or equivalent) signal. - #[inline] - pub fn as_mut_ptr(&self) -> *mut u8 { - self.inner.ptr() as _ - } - - /// Returns the length in bytes of the memory map. - /// - /// Note that truncating the file can cause the length to change (and render this value unusable). - #[inline] - pub fn len(&self) -> usize { - self.inner.len() - } -} - -impl fmt::Debug for MmapRaw { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("MmapRaw") - .field("ptr", &self.as_ptr()) - .field("len", &self.len()) - .finish() - } -} - -/// A handle to a mutable memory mapped buffer. -/// -/// A file-backed `MmapMut` buffer may be used to read from or write to a file. An anonymous -/// `MmapMut` buffer may be used any place that an in-memory byte buffer is needed. Use -/// [`MmapMut::map_mut()`] and [`MmapMut::map_anon()`] to create a mutable memory map of the -/// respective types, or [`MmapOptions::map_mut()`] and [`MmapOptions::map_anon()`] if non-default -/// options are required. -/// -/// A file backed `MmapMut` is created by `&File` reference, and will remain valid even after the -/// `File` is dropped. In other words, the `MmapMut` handle is completely independent of the `File` -/// used to create it. For consistency, on some platforms this is achieved by duplicating the -/// underlying file handle. The memory will be unmapped when the `MmapMut` handle is dropped. -/// -/// Dereferencing and accessing the bytes of the buffer may result in page faults (e.g. swapping -/// the mapped pages into physical memory) though the details of this are platform specific. -/// -/// `Mmap` is [`Sync`](std::marker::Sync) and [`Send`](std::marker::Send). -/// -/// See [`Mmap`] for the immutable version. -/// -/// ## Safety -/// -/// All file-backed memory map constructors are marked `unsafe` because of the potential for -/// *Undefined Behavior* (UB) using the map if the underlying file is subsequently modified, in or -/// out of process. Applications must consider the risk and take appropriate precautions when using -/// file-backed maps. Solutions such as file permissions, locks or process-private (e.g. unlinked) -/// files exist but are platform specific and limited. -pub struct MmapMut { - inner: MmapInner, -} - -impl MmapMut { - /// Creates a writeable memory map backed by a file. - /// - /// This is equivalent to calling `MmapOptions::new().map_mut(file)`. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file is not open with read and write permissions. - /// - /// # Example - /// - /// ``` - /// # extern crate memmap2; - /// # extern crate tempdir; - /// # - /// use std::fs::OpenOptions; - /// use std::path::PathBuf; - /// - /// use memmap2::MmapMut; - /// # - /// # fn main() -> std::io::Result<()> { - /// # let tempdir = tempdir::TempDir::new("mmap")?; - /// let path: PathBuf = /* path to file */ - /// # tempdir.path().join("map_mut"); - /// let file = OpenOptions::new() - /// .read(true) - /// .write(true) - /// .create(true) - /// .open(&path)?; - /// file.set_len(13)?; - /// - /// let mut mmap = unsafe { MmapMut::map_mut(&file)? }; - /// - /// mmap.copy_from_slice(b"Hello, world!"); - /// # Ok(()) - /// # } - /// ``` - pub unsafe fn map_mut(file: T) -> Result { - MmapOptions::new().map_mut(file) - } - - /// Creates an anonymous memory map. - /// - /// This is equivalent to calling `MmapOptions::new().len(length).map_anon()`. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails. - pub fn map_anon(length: usize) -> Result { - MmapOptions::new().len(length).map_anon() - } - - /// Flushes outstanding memory map modifications to disk. - /// - /// When this method returns with a non-error result, all outstanding changes to a file-backed - /// memory map are guaranteed to be durably stored. The file's metadata (including last - /// modification timestamp) may not be updated. - /// - /// # Example - /// - /// ``` - /// # extern crate memmap2; - /// # extern crate tempdir; - /// # - /// use std::fs::OpenOptions; - /// use std::io::Write; - /// use std::path::PathBuf; - /// - /// use memmap2::MmapMut; - /// - /// # fn main() -> std::io::Result<()> { - /// # let tempdir = tempdir::TempDir::new("mmap")?; - /// let path: PathBuf = /* path to file */ - /// # tempdir.path().join("flush"); - /// let file = OpenOptions::new().read(true).write(true).create(true).open(&path)?; - /// file.set_len(128)?; - /// - /// let mut mmap = unsafe { MmapMut::map_mut(&file)? }; - /// - /// (&mut mmap[..]).write_all(b"Hello, world!")?; - /// mmap.flush()?; - /// # Ok(()) - /// # } - /// ``` - pub fn flush(&self) -> Result<()> { - let len = self.len(); - self.inner.flush(0, len) - } - - /// Asynchronously flushes outstanding memory map modifications to disk. - /// - /// This method initiates flushing modified pages to durable storage, but it will not wait for - /// the operation to complete before returning. The file's metadata (including last - /// modification timestamp) may not be updated. - pub fn flush_async(&self) -> Result<()> { - let len = self.len(); - self.inner.flush_async(0, len) - } - - /// Flushes outstanding memory map modifications in the range to disk. - /// - /// The offset and length must be in the bounds of the memory map. - /// - /// When this method returns with a non-error result, all outstanding changes to a file-backed - /// memory in the range are guaranteed to be durable stored. The file's metadata (including - /// last modification timestamp) may not be updated. It is not guaranteed the only the changes - /// in the specified range are flushed; other outstanding changes to the memory map may be - /// flushed as well. - pub fn flush_range(&self, offset: usize, len: usize) -> Result<()> { - self.inner.flush(offset, len) - } - - /// Asynchronously flushes outstanding memory map modifications in the range to disk. - /// - /// The offset and length must be in the bounds of the memory map. - /// - /// This method initiates flushing modified pages to durable storage, but it will not wait for - /// the operation to complete before returning. The file's metadata (including last - /// modification timestamp) may not be updated. It is not guaranteed that the only changes - /// flushed are those in the specified range; other outstanding changes to the memory map may - /// be flushed as well. - pub fn flush_async_range(&self, offset: usize, len: usize) -> Result<()> { - self.inner.flush_async(offset, len) - } - - /// Returns an immutable version of this memory mapped buffer. - /// - /// If the memory map is file-backed, the file must have been opened with read permissions. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file has not been opened with read permissions. - /// - /// # Example - /// - /// ``` - /// # extern crate memmap2; - /// # - /// use std::io::Write; - /// use std::path::PathBuf; - /// - /// use memmap2::{Mmap, MmapMut}; - /// - /// # fn main() -> std::io::Result<()> { - /// let mut mmap = MmapMut::map_anon(128)?; - /// - /// (&mut mmap[..]).write(b"Hello, world!")?; - /// - /// let mmap: Mmap = mmap.make_read_only()?; - /// # Ok(()) - /// # } - /// ``` - pub fn make_read_only(mut self) -> Result { - self.inner.make_read_only()?; - Ok(Mmap { inner: self.inner }) - } - - /// Transition the memory map to be readable and executable. - /// - /// If the memory map is file-backed, the file must have been opened with execute permissions. - /// - /// # Errors - /// - /// This method returns an error when the underlying system call fails, which can happen for a - /// variety of reasons, such as when the file has not been opened with execute permissions. - pub fn make_exec(mut self) -> Result { - self.inner.make_exec()?; - Ok(Mmap { inner: self.inner }) - } -} - -impl Deref for MmapMut { - type Target = [u8]; - - #[inline] - fn deref(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.inner.ptr(), self.inner.len()) } - } -} - -impl DerefMut for MmapMut { - #[inline] - fn deref_mut(&mut self) -> &mut [u8] { - unsafe { slice::from_raw_parts_mut(self.inner.mut_ptr(), self.inner.len()) } - } -} - -impl AsRef<[u8]> for MmapMut { - #[inline] - fn as_ref(&self) -> &[u8] { - self.deref() - } -} - -impl AsMut<[u8]> for MmapMut { - #[inline] - fn as_mut(&mut self) -> &mut [u8] { - self.deref_mut() - } -} - -impl fmt::Debug for MmapMut { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("MmapMut") - .field("ptr", &self.as_ptr()) - .field("len", &self.len()) - .finish() - } -} diff --git a/solana/memmap2-rs/src/stub.rs b/solana/memmap2-rs/src/stub.rs deleted file mode 100644 index 88f270b1..00000000 --- a/solana/memmap2-rs/src/stub.rs +++ /dev/null @@ -1,75 +0,0 @@ -use std::io; - -pub struct MmapInner { - // Private member to prevent external construction - // (might be nice to change the type to ! once that's stable) - __: (), -} - -impl MmapInner { - fn new() -> io::Result { - Err(io::Error::new( - io::ErrorKind::Other, - "platform not supported", - )) - } - - pub fn map(_: usize, _: i32, _: u64, _: bool) -> io::Result { - MmapInner::new() - } - - pub fn map_exec(_: usize, _: i32, _: u64, _: bool) -> io::Result { - MmapInner::new() - } - - pub fn map_mut(_: usize, _: i32, _: u64, _: bool) -> io::Result { - MmapInner::new() - } - - pub fn map_copy(_: usize, _: i32, _: u64, _: bool) -> io::Result { - MmapInner::new() - } - - pub fn map_copy_read_only(_: usize, _: i32, _: u64, _: bool) -> io::Result { - MmapInner::new() - } - - pub fn map_anon(_: usize, _: bool) -> io::Result { - MmapInner::new() - } - - pub fn flush(&self, _: usize, _: usize) -> io::Result<()> { - unreachable!("self unconstructable"); - } - - pub fn flush_async(&self, _: usize, _: usize) -> io::Result<()> { - unreachable!("self unconstructable"); - } - - pub fn make_read_only(&mut self) -> io::Result<()> { - unreachable!("self unconstructable"); - } - - pub fn make_exec(&mut self) -> io::Result<()> { - unreachable!("self unconstructable"); - } - - pub fn make_mut(&mut self) -> io::Result<()> { - unreachable!("self unconstructable"); - } - - #[inline] - pub fn ptr(&self) -> *const u8 { - unreachable!("self unconstructable"); - } - - #[inline] - pub fn mut_ptr(&mut self) -> *mut u8 { - unreachable!("self unconstructable"); - } - - #[inline] - pub fn len(&self) -> usize { - unreachable!("self unconstructable"); - } -} diff --git a/solana/pyth2wormhole/Cargo.lock b/solana/pyth2wormhole/Cargo.lock index baf51322..8709f26a 100644 --- a/solana/pyth2wormhole/Cargo.lock +++ b/solana/pyth2wormhole/Cargo.lock @@ -2344,9 +2344,9 @@ dependencies = [ [[package]] name = "pyth-sdk" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f262b88557d8f152a247e1be786a8359d63112fac0a6e49fa41082a8ef789e8d" +checksum = "f5c805ba3dfb5b7ed6a8ffa62ec38391f485a79c7cf6b3b11d3bd44fb0325824" dependencies = [ "borsh", "borsh-derive", @@ -2357,9 +2357,9 @@ dependencies = [ [[package]] name = "pyth-sdk-solana" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb250e58d1106e47b4348af87f738b8381d6c98c33f4ad13401ab9d82300daa9" +checksum = "286f2abd9fb718190206340f3d1f98a80b34df9d724887b907e7f6f24a31efce" dependencies = [ "borsh", "borsh-derive", @@ -2725,7 +2725,7 @@ dependencies = [ [[package]] name = "rocksalt" version = "0.1.0" -source = "git+https://github.com/certusone/wormhole?tag=v2.8.9#e47f9e481ef84d4dea7a94c9eafbf3b180892466" +source = "git+https://github.com/wormhole-foundation/wormhole?tag=v2.8.9#e47f9e481ef84d4dea7a94c9eafbf3b180892466" dependencies = [ "byteorder", "proc-macro2 1.0.38", @@ -4001,7 +4001,7 @@ dependencies = [ [[package]] name = "solitaire" version = "0.1.0" -source = "git+https://github.com/certusone/wormhole?tag=v2.8.9#e47f9e481ef84d4dea7a94c9eafbf3b180892466" +source = "git+https://github.com/wormhole-foundation/wormhole?tag=v2.8.9#e47f9e481ef84d4dea7a94c9eafbf3b180892466" dependencies = [ "borsh", "byteorder", @@ -4911,7 +4911,7 @@ dependencies = [ [[package]] name = "wormhole-bridge-solana" version = "0.1.0" -source = "git+https://github.com/certusone/wormhole?tag=v2.8.9#e47f9e481ef84d4dea7a94c9eafbf3b180892466" +source = "git+https://github.com/wormhole-foundation/wormhole?tag=v2.8.9#e47f9e481ef84d4dea7a94c9eafbf3b180892466" dependencies = [ "borsh", "byteorder", @@ -5016,7 +5016,3 @@ dependencies = [ "cc", "libc", ] - -[[patch.unused]] -name = "memmap2" -version = "0.1.0" diff --git a/solana/pyth2wormhole/Cargo.toml b/solana/pyth2wormhole/Cargo.toml index e11ab972..120a061a 100644 --- a/solana/pyth2wormhole/Cargo.toml +++ b/solana/pyth2wormhole/Cargo.toml @@ -1,4 +1,2 @@ [workspace] members = ["client", "program"] -[patch.crates-io] -memmap2 = { path = "../memmap2-rs" } \ No newline at end of file diff --git a/solana/pyth2wormhole/client/Cargo.toml b/solana/pyth2wormhole/client/Cargo.toml index 79f88dbc..3bffca06 100644 --- a/solana/pyth2wormhole/client/Cargo.toml +++ b/solana/pyth2wormhole/client/Cargo.toml @@ -16,10 +16,10 @@ borsh = "=0.9.3" clap = {version = "3.1.18", features = ["derive"]} env_logger = "0.8.4" log = "0.4.14" -wormhole-bridge-solana = {git = "https://github.com/certusone/wormhole", tag = "v2.8.9"} +wormhole-bridge-solana = {git = "https://github.com/wormhole-foundation/wormhole", tag = "v2.8.9"} pyth2wormhole = {path = "../program"} p2w-sdk = { path = "../../../third_party/pyth/p2w-sdk/rust", features=["solana"] } -pyth-sdk-solana = "0.4.0" +pyth-sdk-solana = "0.5.0" serde = "1" serde_yaml = "0.8" shellexpand = "2.1.0" @@ -28,7 +28,7 @@ solana-program = "=1.10.31" solana-sdk = "=1.10.31" solana-transaction-status = "=1.10.31" # solitaire-client = {path = "../../solitaire/client"} -solitaire = {git = "https://github.com/certusone/wormhole", tag = "v2.8.9"} +solitaire = {git = "https://github.com/wormhole-foundation/wormhole", tag = "v2.8.9"} tokio = {version = "1", features = ["sync", "rt", "time"]} futures = "0.3.21" diff --git a/solana/pyth2wormhole/program/Cargo.lock b/solana/pyth2wormhole/program/Cargo.lock index e6855c08..255b45f7 100644 --- a/solana/pyth2wormhole/program/Cargo.lock +++ b/solana/pyth2wormhole/program/Cargo.lock @@ -382,15 +382,6 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" -[[package]] -name = "memmap2" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b70ca2a6103ac8b665dc150b142ef0e4e89df640c9e6cf295d189c3caebe5a" -dependencies = [ - "libc", -] - [[package]] name = "num-derive" version = "0.3.3" diff --git a/solana/pyth2wormhole/program/Cargo.toml b/solana/pyth2wormhole/program/Cargo.toml index a53a97d4..4bfdbcac 100644 --- a/solana/pyth2wormhole/program/Cargo.toml +++ b/solana/pyth2wormhole/program/Cargo.toml @@ -15,9 +15,9 @@ trace = ["solitaire/trace", "wormhole-bridge-solana/trace"] no-entrypoint = [] [dependencies] -wormhole-bridge-solana = { git = "https://github.com/certusone/wormhole", tag = "v2.8.9" } -solitaire = { git = "https://github.com/certusone/wormhole", tag = "v2.8.9"} -rocksalt = { git = "https://github.com/certusone/wormhole", tag = "v2.8.9"} +wormhole-bridge-solana = { git = "https://github.com/wormhole-foundation/wormhole", tag = "v2.8.9" } +solitaire = { git = "https://github.com/wormhole-foundation/wormhole", tag = "v2.8.9"} +rocksalt = { git = "https://github.com/wormhole-foundation/wormhole", tag = "v2.8.9"} solana-program = "=1.10.31" borsh = "=0.9.3" pyth-client = "0.2.2" diff --git a/third_party/abigen/go.mod b/third_party/abigen/go.mod index a9517c66..1480b7c3 100644 --- a/third_party/abigen/go.mod +++ b/third_party/abigen/go.mod @@ -1,4 +1,4 @@ -module github.com/certusone/wormhole/third_party/abigen +module github.com/wormhole-foundation/wormhole/third_party/abigen go 1.15 diff --git a/third_party/pyth/p2w-relay/README.md b/third_party/pyth/p2w-relay/README.md index e9326b47..2fb7e1d7 100644 --- a/third_party/pyth/p2w-relay/README.md +++ b/third_party/pyth/p2w-relay/README.md @@ -22,7 +22,7 @@ $ docker run --platform linux/amd64 -d --network=host spy_guardian \ ``` Or run the spy_guardian docker container in MainNet: -For the MainNet gossip network parameters, see https://github.com/certusone/wormhole-networks/blob/master/mainnetv2/info.md +For the MainNet gossip network parameters, see https://github.com/wormhole-foundation/wormhole-networks/blob/master/mainnetv2/info.md ``` $ docker run --platform linux/amd64 -d --network=host spy_guardian \ diff --git a/third_party/pyth/p2w-sdk/js/package.json b/third_party/pyth/p2w-sdk/js/package.json index 6b8876e3..46c667c3 100644 --- a/third_party/pyth/p2w-sdk/js/package.json +++ b/third_party/pyth/p2w-sdk/js/package.json @@ -19,7 +19,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/certusone/wormhole.git" + "url": "git+https://github.com/pyth-network/pyth-crosschain.git" }, "author": "https://certus.one", "license": "MIT", @@ -44,7 +44,7 @@ "@pythnetwork/pyth-sdk-js": "^0.1.0" }, "bugs": { - "url": "https://github.com/certusone/wormhole/issues" + "url": "https://github.com/pyth-network/pyth-crosschain/issues" }, - "homepage": "https://github.com/certusone/wormhole#readme" + "homepage": "https://github.com/pyth-network/pyth-crosschain#readme" } diff --git a/third_party/pyth/p2w-sdk/rust/Cargo.lock b/third_party/pyth/p2w-sdk/rust/Cargo.lock index 707dfc2b..1e4b9d29 100644 --- a/third_party/pyth/p2w-sdk/rust/Cargo.lock +++ b/third_party/pyth/p2w-sdk/rust/Cargo.lock @@ -696,9 +696,9 @@ dependencies = [ [[package]] name = "pyth-sdk" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f262b88557d8f152a247e1be786a8359d63112fac0a6e49fa41082a8ef789e8d" +checksum = "f5c805ba3dfb5b7ed6a8ffa62ec38391f485a79c7cf6b3b11d3bd44fb0325824" dependencies = [ "borsh", "borsh-derive", @@ -709,9 +709,9 @@ dependencies = [ [[package]] name = "pyth-sdk-solana" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb250e58d1106e47b4348af87f738b8381d6c98c33f4ad13401ab9d82300daa9" +checksum = "286f2abd9fb718190206340f3d1f98a80b34df9d724887b907e7f6f24a31efce" dependencies = [ "borsh", "borsh-derive", @@ -825,7 +825,7 @@ dependencies = [ [[package]] name = "rocksalt" version = "0.1.0" -source = "git+https://github.com/certusone/wormhole?tag=v2.8.9#e47f9e481ef84d4dea7a94c9eafbf3b180892466" +source = "git+https://github.com/wormhole-foundation/wormhole?tag=v2.8.9#e47f9e481ef84d4dea7a94c9eafbf3b180892466" dependencies = [ "byteorder", "proc-macro2", @@ -1097,7 +1097,7 @@ dependencies = [ [[package]] name = "solitaire" version = "0.1.0" -source = "git+https://github.com/certusone/wormhole?tag=v2.8.9#e47f9e481ef84d4dea7a94c9eafbf3b180892466" +source = "git+https://github.com/wormhole-foundation/wormhole?tag=v2.8.9#e47f9e481ef84d4dea7a94c9eafbf3b180892466" dependencies = [ "borsh", "byteorder", diff --git a/third_party/pyth/p2w-sdk/rust/Cargo.toml b/third_party/pyth/p2w-sdk/rust/Cargo.toml index 124ec821..f8cd154b 100644 --- a/third_party/pyth/p2w-sdk/rust/Cargo.toml +++ b/third_party/pyth/p2w-sdk/rust/Cargo.toml @@ -17,11 +17,11 @@ wasm = ["wasm-bindgen", "solana"] hex = "0.4.3" serde = { version = "1.0.103", default-features = false, features = ["derive"] } pyth-sdk = "*" -pyth-sdk-solana = { version = "0.4.0", optional = true } +pyth-sdk-solana = { version = "0.5.0", optional = true } wasm-bindgen = { version = "0.2.74", features = ["serde-serialize"], optional = true} -solitaire = { git = "https://github.com/certusone/wormhole", tag = "v2.8.9", optional = true} +solitaire = { git = "https://github.com/wormhole-foundation/wormhole", tag = "v2.8.9", optional = true} solana-program = { version = "=1.10.31", optional = true } [dev-dependencies] solana-program = "=1.10.31" -pyth-sdk-solana = "0.4.0" +pyth-sdk-solana = "0.5.0" diff --git a/third_party/pyth/price-service/README.md b/third_party/pyth/price-service/README.md index 30554550..ad02aa86 100644 --- a/third_party/pyth/price-service/README.md +++ b/third_party/pyth/price-service/README.md @@ -26,7 +26,7 @@ $ docker run --platform linux/amd64 --network=host ghcr.io/certusone/guardiand:v ``` Or run the spy_guardian docker container in MainNet: -For the MainNet gossip network parameters, see https://github.com/certusone/wormhole-networks/blob/master/mainnetv2/info.md +For the MainNet gossip network parameters, see https://github.com/wormhole-foundation/wormhole-networks/blob/master/mainnetv2/info.md ``` $ docker run --platform linux/amd64 -d --network=host ghcr.io/certusone/guardiand:v2.8.8.1 spy \