Add the Squads Mesh program to Tilt and initialize a Vault for it (#421)

* solana-devnet: Deploy a copy of the Mesh multisig program

* solana/keys: Add keys for multisig testing

* *.py: Remove airdrop, use devnet_setup.sh keypair instead

* Dockerfile.p2w-attest: Improve caching

- Move cheap Python script additions after the expensive rust build
- Cache Cargo's package cache to shorten the "updating crates.io registry" build steps

* Add a multisig Tilt resource, k8s yaml and runtime script

This contains most of the work on Tilt/testing harness side.

* multisig-wh-message-builder: Add init-vault subcommand

This new subcommand enables the runtime Python script to create a
multisig vault on the fly on the mock Solana devnet.

* multisig-wh-message-builder: findProgramAddress -> getMsPDA

* mutlisig-wh-message-builder: apply review advice

- Use default mesh program address
- remove unused program.json
- remove redundant null checks
- hardcode vault address (it is deterministic against the constant
mesh program pubkey)
- Start depending on solana-devnet in Tilt
- Add carol to vault and set threshold to 2
This commit is contained in:
Stanisław Drozd 2022-12-13 14:05:06 +01:00 committed by GitHub
parent 92bb656f93
commit f69a91d97c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 419 additions and 114 deletions

37
Dockerfile.multisig Normal file
View File

@ -0,0 +1,37 @@
#syntax=docker/dockerfile:1.2@sha256:e2a8561e419ab1ba6b2fe6cbdf49fd92b95912df1cf7d313c3e2230a333fdbcc
FROM ghcr.io/certusone/solana:1.10.31
# This image builds an environment to initialize and use a local
# devnet multisig. It uses Pyth's Mesh client.
RUN apt-get update && apt-get install -yq python3 libudev-dev ncat
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
WORKDIR /root
# Also used by the multisig provisioning script
ENV MULTISIG_SCRIPT_DIR=/root/pyth/multisig-wh-message-builder
WORKDIR $MULTISIG_SCRIPT_DIR
ENV LOCAL_MULTISIG_SCRIPT_DIR=third_party/pyth/multisig-wh-message-builder
# Add a barebones representation of our deps for Docker layer caching
ADD $LOCAL_MULTISIG_SCRIPT_DIR/package.json \
$LOCAL_MULTISIG_SCRIPT_DIR/package-lock.json \
$LOCAL_MULTISIG_SCRIPT_DIR/tsconfig.json \
.
RUN mkdir src # tsc is run as part of the install, add minimal placeholders to satisfy it
RUN touch src/index.ts
RUN --mount=type=cache,target=/home/node/.cache \
npm ci && cp -r node_modules node_modules_cached
RUN rm -rf node_modules && mv node_modules_cached node_modules
# Add the rest of the code. This ensures that real code changes do not affect the layer caching of `npm ci`
ADD third_party/pyth /root/pyth
ADD solana/keys /usr/src/solana/keys
RUN npm install

View File

@ -34,6 +34,15 @@ RUN tar -xvf v${WORMHOLE_REV}.tar.gz
RUN mv wormhole-${WORMHOLE_REV} wormhole
# RUN mkdir -p /usr/src/bridge/wormhole/solana/target
WORKDIR /usr/src/squads
ARG SQUADS_REV=1.2.0
ADD https://github.com/Squads-Protocol/squads-mpl/archive/refs/tags/v${SQUADS_REV}.tar.gz .
RUN tar -xvf v${SQUADS_REV}.tar.gz
RUN mv squads-mpl-${SQUADS_REV} squads-mpl
WORKDIR /usr/src/bridge
ADD solana solana
ADD pythnet pythnet
@ -48,14 +57,17 @@ WORKDIR /usr/src/bridge/solana
# Build Wormhole Solana programs
RUN --mount=type=cache,target=/usr/src/bridge/wormhole/solana/target \
--mount=type=cache,target=/usr/src/bridge/solana/pyth2wormhole/target \
--mount=type=cache,target=/usr/src/squads/squads-mpl/target \
--mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/root/.cache \
cargo build-bpf --manifest-path "../wormhole/solana/bridge/program/Cargo.toml" -- --locked && \
cargo build-bpf --manifest-path "../wormhole/solana/bridge/cpi_poster/Cargo.toml" -- --locked && \
cargo build-bpf --manifest-path "pyth2wormhole/program/Cargo.toml" -- --locked && \
cargo build-bpf --manifest-path "/usr/src/squads/squads-mpl/programs/mesh/Cargo.toml" -- --locked && \
cp ../wormhole/solana/target/deploy/bridge.so /opt/solana/deps/bridge.so && \
cp ../wormhole/solana/target/deploy/cpi_poster.so /opt/solana/deps/cpi_poster.so && \
cp pyth2wormhole/target/deploy/pyth2wormhole.so /opt/solana/deps/pyth2wormhole.so
cp pyth2wormhole/target/deploy/pyth2wormhole.so /opt/solana/deps/pyth2wormhole.so && \
cp /usr/src/squads/squads-mpl/target/deploy/mesh.so /opt/solana/deps/mesh.so
COPY --from=pyth-oracle-copy /home/pyth/pyth-client/target/oracle.so /opt/solana/deps/pyth_oracle.so

View File

@ -351,3 +351,18 @@ k8s_resource(
labels = ["prometheus"],
trigger_mode = trigger_mode,
)
docker_build(
ref = "multisig",
context = ".",
dockerfile = "Dockerfile.multisig",
)
k8s_yaml_with_ns("devnet/multisig.yaml")
k8s_resource(
"multisig",
resource_deps = ["solana-devnet"],
labels = ["solana"],
trigger_mode = trigger_mode,
)

39
devnet/multisig.yaml Normal file
View File

@ -0,0 +1,39 @@
---
apiVersion: v1
kind: Service
metadata:
name: multisig
labels:
app: multisig
spec:
clusterIP: None
selector:
app: multisig
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: multisig
spec:
selector:
matchLabels:
app: multisig
serviceName: multisig
template:
metadata:
labels:
app: multisig
spec:
restartPolicy: Always
terminationGracePeriodSeconds: 0
containers:
- name: multisig
image: multisig
readinessProbe:
tcpSocket:
port: 2000
periodSeconds: 1
failureThreshold: 300
command:
- python3
- /root/pyth/prepare_multisig.py

View File

@ -50,6 +50,9 @@ spec:
- --bpf-program
- P2WH424242424242424242424242424242424242424
- /opt/solana/deps/pyth2wormhole.so
- --bpf-program
- SMPLVC8MxZ5Bf5EfF7PaMiTCxoBAcmkbM2vkrvMK8ho # copied from squads-mpl/programs/mesh/src/lib.rs
- /opt/solana/deps/mesh.so
- --log
ports:
- containerPort: 8001

View File

@ -0,0 +1,6 @@
[
174, 86, 158, 146, 5, 14, 115, 61, 113, 135, 247, 80, 154, 1, 168, 241, 237,
184, 94, 53, 32, 115, 162, 198, 35, 226, 72, 198, 108, 242, 35, 175, 226, 156,
60, 163, 77, 178, 58, 243, 50, 48, 28, 249, 226, 125, 150, 188, 35, 23, 131,
149, 177, 124, 235, 145, 103, 119, 237, 30, 30, 25, 145, 128
]

View File

@ -0,0 +1,6 @@
[
172, 234, 168, 90, 159, 133, 183, 38, 206, 220, 115, 240, 201, 186, 191, 12,
38, 133, 233, 164, 62, 92, 164, 155, 149, 133, 68, 83, 168, 233, 67, 12, 1,
134, 165, 231, 211, 192, 216, 167, 186, 77, 109, 120, 172, 131, 36, 27, 95,
207, 60, 228, 128, 201, 74, 109, 132, 176, 165, 156, 62, 146, 247, 75
]

View File

@ -0,0 +1,6 @@
[
196, 148, 217, 170, 205, 37, 40, 95, 214, 198, 118, 8, 52, 12, 250, 196, 95,
138, 15, 163, 55, 212, 93, 215, 72, 15, 11, 125, 221, 67, 196, 176, 219, 38,
22, 196, 10, 226, 177, 210, 88, 255, 245, 194, 140, 68, 61, 222, 16, 199, 151,
74, 161, 165, 178, 130, 124, 60, 99, 168, 130, 199, 251, 149
]

View File

@ -0,0 +1,6 @@
[
238, 68, 150, 179, 87, 216, 135, 224, 44, 190, 97, 182, 75, 109, 167, 101,
146, 236, 95, 142, 190, 237, 251, 179, 186, 54, 100, 145, 166, 113, 222, 85,
0, 42, 46, 190, 161, 239, 138, 33, 240, 218, 84, 112, 63, 54, 170, 185, 140,
21, 211, 216, 57, 146, 161, 87, 170, 18, 29, 186, 231, 15, 241, 91
]

View File

@ -0,0 +1,6 @@
[
140, 155, 132, 14, 35, 183, 53, 188, 155, 194, 27, 24, 251, 0, 26, 136, 173,
9, 140, 24, 155, 157, 172, 249, 41, 205, 221, 234, 114, 32, 128, 179, 120,
208, 86, 87, 116, 157, 31, 72, 104, 90, 21, 155, 104, 85, 190, 144, 253, 151,
189, 47, 172, 194, 170, 246, 97, 26, 211, 96, 203, 106, 98, 216
]

View File

@ -5,10 +5,7 @@ RUN apt-get update && apt-get install -yq python3 libudev-dev ncat
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
ADD pythnet/remote-executor /usr/src/pythnet/remote-executor
ADD third_party/pyth/pyth_utils.py /usr/src/pyth/pyth_utils.py
ADD third_party/pyth/p2w_autoattest.py /usr/src/pyth/p2w_autoattest.py
ADD third_party/pyth/p2w-sdk/rust /usr/src/third_party/pyth/p2w-sdk/rust
ADD solana /usr/src/solana
WORKDIR /usr/src/solana/pyth2wormhole
@ -17,14 +14,18 @@ ENV EMITTER_ADDRESS="11111111111111111111111111111115"
ENV BRIDGE_ADDRESS="Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o"
RUN --mount=type=cache,target=/root/.cache \
--mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=target \
cargo test --package pyth2wormhole-client && \
cargo build --package pyth2wormhole-client && \
mv target/debug/pyth2wormhole-client /usr/local/bin/pyth2wormhole-client && \
chmod a+rx /usr/src/pyth/*.py
mv target/debug/pyth2wormhole-client /usr/local/bin/pyth2wormhole-client
ADD third_party/pyth/pyth_utils.py /usr/src/pyth/pyth_utils.py
ADD third_party/pyth/p2w_autoattest.py /usr/src/pyth/p2w_autoattest.py
RUN chmod a+rx /usr/src/pyth/*.py
ENV P2W_OWNER_KEYPAIR="/usr/src/solana/keys/p2w_owner.json"
ENV P2W_ATTESTATIONS_PORT="4343"
ENV PYTH_PUBLISHER_KEYPAIR="/usr/src/solana/keys/pyth_publisher.json"
ENV PYTH_PROGRAM_KEYPAIR="/usr/src/solana/keys/pyth_program.json"
ENV SOL_AIRDROP_AMT="100"

View File

@ -16,10 +16,14 @@
"@solana/web3.js": "^1.53.0",
"@sqds/mesh": "^1.0.6",
"@types/lodash": "^4.14.186",
"@types/node-fetch": "^2.6.2",
"@types/node-hid": "^1.3.1",
"bs58": "^5.0.0",
"commander": "^9.4.0",
"ethers": "^5.7.0",
"lodash": "^4.17.21"
"lodash": "^4.17.21",
"ts-node": "^10.9.1",
"typescript": "^4.8.3"
},
"devDependencies": {
"@types/bn.js": "^5.1.0",
@ -29,9 +33,7 @@
"eslint": "^8.23.0",
"jest": "^28.0.8",
"prettier": "^2.7.1",
"ts-jest": "^28.0.8",
"ts-node": "^10.9.1",
"typescript": "^4.8.3"
"ts-jest": "^28.0.8"
}
},
"node_modules/@ampproject/remapping": {
@ -674,7 +676,6 @@
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
"dependencies": {
"@jridgewell/trace-mapping": "0.3.9"
},
@ -686,7 +687,6 @@
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
@ -1869,7 +1869,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
@ -1886,8 +1885,7 @@
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
"dev": true
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.15",
@ -2414,26 +2412,22 @@
"node_modules/@tsconfig/node10": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
"integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
"dev": true
"integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA=="
},
"node_modules/@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"dev": true
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"dev": true
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow=="
},
"node_modules/@tsconfig/node16": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
"integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
"dev": true
"integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ=="
},
"node_modules/@types/babel__core": {
"version": "7.1.19",
@ -2557,6 +2551,23 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.15.tgz",
"integrity": "sha512-XnjpaI8Bgc3eBag2Aw4t2Uj/49lLBSStHWfqKvIuXD7FIrZyMLWp8KuAFHAqxMZYTF9l08N1ctUn9YNybZJVmQ=="
},
"node_modules/@types/node-fetch": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz",
"integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==",
"dependencies": {
"@types/node": "*",
"form-data": "^3.0.0"
}
},
"node_modules/@types/node-hid": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@types/node-hid/-/node-hid-1.3.1.tgz",
"integrity": "sha512-VPxuGDCoDxOUKrTZPSok7IEmiK4cVLfj8Csu09FtG5uF+eqf1HETERHXQkO02Rk6j6YiiHxp0/DA9R4llvhEzQ==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/prettier": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.0.tgz",
@ -2781,7 +2792,6 @@
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
"integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
},
@ -2802,7 +2812,6 @@
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
"integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
"dev": true,
"engines": {
"node": ">=0.4.0"
}
@ -2963,8 +2972,7 @@
"node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
},
"node_modules/argparse": {
"version": "2.0.1",
@ -3648,8 +3656,7 @@
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
},
"node_modules/cross-fetch": {
"version": "3.1.5",
@ -3793,7 +3800,6 @@
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true,
"engines": {
"node": ">=0.3.1"
}
@ -5893,8 +5899,7 @@
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
},
"node_modules/makeerror": {
"version": "1.0.12",
@ -7406,7 +7411,6 @@
"version": "10.9.1",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
"integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
"dev": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
@ -7529,7 +7533,6 @@
"version": "4.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz",
"integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -7619,8 +7622,7 @@
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="
},
"node_modules/v8-to-istanbul": {
"version": "9.0.1",
@ -7804,7 +7806,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true,
"engines": {
"node": ">=6"
}
@ -8319,7 +8320,6 @@
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
"requires": {
"@jridgewell/trace-mapping": "0.3.9"
},
@ -8328,7 +8328,6 @@
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"dev": true,
"requires": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
@ -9091,8 +9090,7 @@
"@jridgewell/resolve-uri": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
"dev": true
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w=="
},
"@jridgewell/set-array": {
"version": "1.1.2",
@ -9103,8 +9101,7 @@
"@jridgewell/sourcemap-codec": {
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
"dev": true
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
},
"@jridgewell/trace-mapping": {
"version": "0.3.15",
@ -9561,26 +9558,22 @@
"@tsconfig/node10": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
"integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
"dev": true
"integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA=="
},
"@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"dev": true
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="
},
"@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"dev": true
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow=="
},
"@tsconfig/node16": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
"integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
"dev": true
"integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ=="
},
"@types/babel__core": {
"version": "7.1.19",
@ -9704,6 +9697,23 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.15.tgz",
"integrity": "sha512-XnjpaI8Bgc3eBag2Aw4t2Uj/49lLBSStHWfqKvIuXD7FIrZyMLWp8KuAFHAqxMZYTF9l08N1ctUn9YNybZJVmQ=="
},
"@types/node-fetch": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz",
"integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==",
"requires": {
"@types/node": "*",
"form-data": "^3.0.0"
}
},
"@types/node-hid": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@types/node-hid/-/node-hid-1.3.1.tgz",
"integrity": "sha512-VPxuGDCoDxOUKrTZPSok7IEmiK4cVLfj8Csu09FtG5uF+eqf1HETERHXQkO02Rk6j6YiiHxp0/DA9R4llvhEzQ==",
"requires": {
"@types/node": "*"
}
},
"@types/prettier": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.0.tgz",
@ -9838,8 +9848,7 @@
"acorn": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
"integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
"dev": true
"integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w=="
},
"acorn-jsx": {
"version": "5.3.2",
@ -9851,8 +9860,7 @@
"acorn-walk": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
"integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
"dev": true
"integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA=="
},
"aes-js": {
"version": "3.0.0",
@ -9981,8 +9989,7 @@
"arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
},
"argparse": {
"version": "2.0.1",
@ -10529,8 +10536,7 @@
"create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
},
"cross-fetch": {
"version": "3.1.5",
@ -10629,8 +10635,7 @@
"diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
},
"diff-sequences": {
"version": "28.1.1",
@ -12233,8 +12238,7 @@
"make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
},
"makeerror": {
"version": "1.0.12",
@ -13329,7 +13333,6 @@
"version": "10.9.1",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
"integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
"dev": true,
"requires": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
@ -13410,8 +13413,7 @@
"typescript": {
"version": "4.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz",
"integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==",
"dev": true
"integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig=="
},
"update-browserslist-db": {
"version": "1.0.7",
@ -13469,8 +13471,7 @@
"v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="
},
"v8-to-istanbul": {
"version": "9.0.1",
@ -13609,8 +13610,7 @@
"yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="
},
"yocto-queue": {
"version": "0.1.0",

View File

@ -18,7 +18,7 @@
"prepublishOnly": "npm test && npm run lint",
"preversion": "npm run lint",
"version": "npm run format && git add -A src",
"start": "ts-node src/index.ts"
"start": "node lib/index.js"
},
"keywords": [
"pyth",
@ -33,9 +33,7 @@
"eslint": "^8.23.0",
"jest": "^28.0.8",
"prettier": "^2.7.1",
"ts-jest": "^28.0.8",
"ts-node": "^10.9.1",
"typescript": "^4.8.3"
"ts-jest": "^28.0.8"
},
"dependencies": {
"@certusone/wormhole-sdk": "^0.6.2",
@ -45,9 +43,13 @@
"@solana/web3.js": "^1.53.0",
"@sqds/mesh": "^1.0.6",
"@types/lodash": "^4.14.186",
"@types/node-fetch": "^2.6.2",
"@types/node-hid": "^1.3.1",
"bs58": "^5.0.0",
"commander": "^9.4.0",
"ethers": "^5.7.0",
"lodash": "^4.17.21"
"lodash": "^4.17.21",
"ts-node": "^10.9.1",
"typescript": "^4.8.3"
}
}

View File

@ -15,7 +15,7 @@ import {
TransactionInstruction,
} from "@solana/web3.js";
import Squads from "@sqds/mesh";
import { getIxAuthorityPDA, getIxPDA } from "@sqds/mesh";
import { getIxAuthorityPDA, getIxPDA, getMsPDA } from "@sqds/mesh";
import { InstructionAccount } from "@sqds/mesh/lib/types";
import bs58 from "bs58";
import { program } from "commander";
@ -26,7 +26,21 @@ import { getActiveProposals, getProposalInstructions } from "./multisig";
setDefaultWasm("node");
type Cluster = "devnet" | "mainnet" | "localnet";
// NOTE(2022-11-30): Naming disambiguation:
// - "mainnet" - always means a public production environment
//
// - "testnet" in Wormhole context - a collection of public testnets
// of the supported blockchain
// - "testnet" in Solana context - Never used here; The public solana
// cluster called "testnet" at https://api.testnet.solana.com
//
// - "devnet" in Wormhole context - local Tilt devnet
// - "devnet" in Solana context - The "devnet" public Solana cluster
// at https://api.devnet.solana.com
//
// - "localdevnet" - always means the Tilt devnet
type Cluster = "devnet" | "mainnet" | "localdevnet";
type WormholeNetwork = "TESTNET" | "MAINNET" | "DEVNET";
type Config = {
@ -46,10 +60,10 @@ const CONFIG: Record<Cluster, Config> = {
vault: new PublicKey("FVQyHcooAtThJ83XFrNnv74BcinbRH3bRmfFamAHBfuj"),
wormholeRpcEndpoint: "https://wormhole-v2-mainnet-api.certus.one",
},
localnet: {
localdevnet: {
wormholeClusterName: "DEVNET",
vault: new PublicKey("2VVHgWVHi32P1aoMjHmL3e1Hf6yi7uERahXF1T5n6EHx"), // Placeholder
wormholeRpcEndpoint: "https://wormhole-v2-mainnet-api.certus.one", // Placeholder
vault: new PublicKey("DFkA5ubJSETKiFnniAsm8qRXUa7RrnnE7U9awTzbcrJF"),
wormholeRpcEndpoint: "http://guardian:7071",
},
};
@ -58,6 +72,77 @@ program
.description("CLI to creating and executing multisig transactions for pyth")
.version("0.1.0");
program
.command("init-vault")
.description(
"Initialize a new multisig vault. NOTE: It's unlikely that you need run this manually. Primarily used in the Tilt local devnet"
)
.requiredOption(
"-k --create-key <address>",
"Vault create key. It's a pubkey used to seed the vault's address"
)
.requiredOption(
"-x --external-authority <address>",
"External authority address"
)
.option("-c --cluster <network>", "solana cluster to use", "devnet")
.option("-p --payer <filepath>", "payer keypair file")
.option(
"-t --threshold <threshold_number>",
"Approval quorum threshold for the vault",
"2"
)
.requiredOption(
"-i --initial-members <comma_separated_members>",
"comma-separated list of initial multisig members, without spaces"
)
.option(
"-r --solana-rpc <url>",
"Solana RPC address to use",
"http://localhost:8899"
)
.action(async (options: any) => {
let cluster: Cluster = options.cluster;
let createKeyAddr: PublicKey = new PublicKey(options.createKey);
let extAuthorityAddr: PublicKey = new PublicKey(options.externalAuthority);
let threshold: number = parseInt(options.threshold, 10);
let initialMembers = options.initialMembers
.split(",")
.map((m: string) => new PublicKey(m));
let mesh = await getSquadsClient(
cluster,
options.ledger,
options.ledgerDerivationAccount,
options.ledgerDerivationChange,
options.payer,
cluster == "localdevnet" ? options.solanaRpc : undefined
);
let vaultAddr = CONFIG[cluster].vault;
console.log("Creating new vault at", vaultAddr.toString());
try {
let _multisig = await mesh.getMultisig(vaultAddr);
// NOTE(2022-12-08): If this check prevents you from iterating dev
// work in tilt, restart solana-devnet.
console.log(
"Reached an existing vault under the address, refusing to create."
);
process.exit(17); // EEXIST
} catch (e: any) {}
console.log("No existing vault found, creating...");
await mesh.createMultisig(
extAuthorityAddr,
threshold,
createKeyAddr,
initialMembers
);
});
program
.command("create")
.description("Create a new multisig transaction")
@ -308,6 +393,7 @@ program
options.ledgerDerivationChange,
options.wallet
);
await addMember(
options.cluster,
squad,
@ -361,7 +447,8 @@ async function getSquadsClient(
ledger: boolean,
ledgerDerivationAccount: number | undefined,
ledgerDerivationChange: number | undefined,
walletPath: string
walletPath: string,
solRpcUrl?: string
) {
let wallet: LedgerNodeWallet | NodeWallet;
if (ledger) {
@ -379,13 +466,27 @@ async function getSquadsClient(
);
console.log(`Loaded wallet with address: ${wallet.publicKey.toBase58()}`);
}
const squad =
cluster === "devnet"
? Squads.devnet(wallet)
: cluster == "mainnet"
? Squads.mainnet(wallet)
: Squads.endpoint("http://127.0.0.1:8899", wallet);
return squad;
switch (cluster) {
case "devnet": {
return Squads.devnet(wallet);
break;
}
case "mainnet": {
return Squads.mainnet(wallet);
break;
}
case "localdevnet": {
if (solRpcUrl) {
return Squads.endpoint(solRpcUrl, wallet);
} else {
console.log("rpc:", solRpcUrl);
throw `ERROR: solRpcUrl was not specified for localdevnet!`;
}
}
default: {
throw `ERROR: unrecognized cluster ${cluster}`;
}
}
}
async function createTx(squad: Squads, vault: PublicKey): Promise<PublicKey> {

View File

@ -37,18 +37,6 @@ WORMHOLE_ADDRESS = os.environ.get(
# attester needs string, but we validate as int first
P2W_RPC_TIMEOUT_SECS = str(int(os.environ.get("P2W_RPC_TIMEOUT_SECS", "20")))
if SOL_AIRDROP_AMT > 0:
# Fund the p2w owner
sol_run_or_die(
"airdrop",
[
str(SOL_AIRDROP_AMT),
"--keypair",
P2W_OWNER_KEYPAIR,
"--commitment",
"finalized",
],
)
if P2W_INITIALIZE_SOL_CONTRACT is not None:
# Get actor pubkeys
@ -56,7 +44,7 @@ if P2W_INITIALIZE_SOL_CONTRACT is not None:
"address", ["--keypair", P2W_OWNER_KEYPAIR], capture_output=True
).stdout.strip()
PYTH_OWNER_ADDRESS = sol_run_or_die(
"address", ["--keypair", PYTH_PROGRAM_KEYPAIR], capture_output=True
"address", ["--keypair", PYTH_PROGRAM_KEYPAIR], capture_output=True,
).stdout.strip()
init_result = run_or_die(
@ -67,7 +55,7 @@ if P2W_INITIALIZE_SOL_CONTRACT is not None:
"--rpc-url",
SOL_RPC_URL,
"--payer",
P2W_OWNER_KEYPAIR,
SOL_PAYER_KEYPAIR,
"init",
"--wh-prog",
WORMHOLE_ADDRESS,
@ -77,6 +65,7 @@ if P2W_INITIALIZE_SOL_CONTRACT is not None:
PYTH_OWNER_ADDRESS,
],
capture_output=True,
debug=True,
die=False,
)
@ -92,7 +81,7 @@ if P2W_INITIALIZE_SOL_CONTRACT is not None:
"--rpc-url",
SOL_RPC_URL,
"--payer",
P2W_OWNER_KEYPAIR,
SOL_PAYER_KEYPAIR,
"set-config",
"--owner",
P2W_OWNER_KEYPAIR,
@ -190,7 +179,7 @@ first_attest_result = run_or_die(
"--rpc-url",
SOL_RPC_URL,
"--payer",
P2W_OWNER_KEYPAIR,
SOL_PAYER_KEYPAIR,
"attest",
"-f",
P2W_ATTESTATION_CFG,
@ -220,7 +209,7 @@ while True:
"--rpc-url",
SOL_RPC_URL,
"--payer",
P2W_OWNER_KEYPAIR,
SOL_PAYER_KEYPAIR,
"attest",
"-f",
P2W_ATTESTATION_CFG,

60
third_party/pyth/prepare_multisig.py vendored Normal file
View File

@ -0,0 +1,60 @@
# This script prepares a local Squads multisig deployment for use with
# the multisig-wh-message-builder
import errno
import os
import sys
from pyth_utils import *
MULTISIG_SCRIPT_CMD_PREFIX = "npm run start --".split(" ")
MULTISIG_SCRIPT_DIR = os.environ.get("MULTISIG_SCRIPT_DIR", "/root/pyth/multisig-wh-message-builder")
MESH_KEY_DIR = "/usr/src/solana/keys/squads/"
MESH_PROGRAM_ADDR = "SMPLVC8MxZ5Bf5EfF7PaMiTCxoBAcmkbM2vkrvMK8ho"
MESH_CREATE_KEY_PATH = MESH_KEY_DIR + "create_key.json"
MESH_VAULT_EXT_AUTHORITY_KEY_PATH = MESH_KEY_DIR + "external_authority.json"
ALICE_KEY_PATH = MESH_KEY_DIR + "member_alice.json"
BOB_KEY_PATH = MESH_KEY_DIR + "member_bob.json"
CAROL_KEY_PATH = MESH_KEY_DIR + "member_carol.json"
create_key_addr = sol_run_or_die("address", ["--keypair", MESH_CREATE_KEY_PATH], capture_output=True).stdout.strip()
ext_authority_addr = sol_run_or_die("address", ["--keypair", MESH_VAULT_EXT_AUTHORITY_KEY_PATH], capture_output=True).stdout.strip()
alice_addr = sol_run_or_die("address", ["--keypair", ALICE_KEY_PATH], capture_output=True).stdout.strip()
bob_addr = sol_run_or_die("address", ["--keypair", BOB_KEY_PATH], capture_output=True).stdout.strip()
carol_addr = sol_run_or_die("address", ["--keypair", CAROL_KEY_PATH], capture_output=True).stdout.strip()
# wrap run_or_die in msg builder common cli args
def msg_builder_run_or_die(args = [], debug=False, **kwargs):
"""
Message builder boilerplate in front of run_or_die()
"""
return run_or_die(
MULTISIG_SCRIPT_CMD_PREFIX + args, cwd=MULTISIG_SCRIPT_DIR, debug=debug, **kwargs)
# create a Multisig Vault
res = msg_builder_run_or_die([
"init-vault",
"-k", create_key_addr,
"-x", ext_authority_addr,
"-p", SOL_PAYER_KEYPAIR,
"-c", "localdevnet",
"-r", SOL_RPC_URL,
"-i", f"{alice_addr},{bob_addr},{carol_addr}",
"-t", "2", # 2/3 threshold
],
capture_output=True, debug=True, die=False)
if res.returncode == errno.EEXIST:
print("WARNING: Skipping vault creation and testing, received EEXIST from script", file=sys.stderr)
elif res.returncode != 0:
print(f"ERROR: unexpected failure with code {res.returncode}", file=sys.stderr)
sys.exit(res.returncode)
else:
print("Vault created, starting test routine", file=sys.stderr)
# TODO(2022-12-08): Add test scenarios
sys.stderr.flush()
readiness()

View File

@ -12,6 +12,11 @@ import sys
import threading
import time
# The mock publisher needs to fund the publisher identity account,
# unable to use a separate payer
SOL_AIRDROP_AMT = int(os.environ.get("SOL_AIRDROP_AMT", 0))
class PythAccEndpoint(BaseHTTPRequestHandler):
"""
A dumb endpoint to respond with a JSON containing Pyth symbol and mapping addresses

View File

@ -6,6 +6,12 @@ import subprocess
import sys
from http.client import HTTPConnection
# A generic unprivileged payer account with funds
SOL_PAYER_KEYPAIR = os.environ.get(
"SOL_PAYER_KEYPAIR", "/usr/src/solana/keys/solana-devnet.json"
)
# Settings specific to local devnet Pyth instance
PYTH = os.environ.get("PYTH", "./pyth")
PYTH_ADMIN = os.environ.get("PYTH_ADMIN", "./pyth_admin")
@ -17,6 +23,7 @@ PYTH_PROGRAM_SO_PATH = os.environ.get("PYTH_PROGRAM_SO", "../target/oracle.so")
PYTH_PUBLISHER_KEYPAIR = os.environ.get(
"PYTH_PUBLISHER_KEYPAIR", f"{PYTH_KEY_STORE}/publish_key_pair.json"
)
# How long to sleep between mock Pyth price updates
PYTH_PUBLISHER_INTERVAL_SECS = float(os.environ.get("PYTH_PUBLISHER_INTERVAL_SECS", "5"))
PYTH_TEST_SYMBOL_COUNT = int(os.environ.get("PYTH_TEST_SYMBOL_COUNT", "11"))
@ -34,9 +41,6 @@ PYTH_MAPPING_KEYPAIR = os.environ.get(
"PYTH_MAPPING_KEYPAIR", f"{PYTH_KEY_STORE}/mapping_key_pair.json"
)
# 0 setting disables airdropping
SOL_AIRDROP_AMT = int(os.environ.get("SOL_AIRDROP_AMT", 0))
# SOL RPC settings
SOL_RPC_HOST = os.environ.get("SOL_RPC_HOST", "solana-devnet")
SOL_RPC_PORT = int(os.environ.get("SOL_RPC_PORT", 8899))
@ -48,7 +52,7 @@ SOL_RPC_URL = os.environ.get(
READINESS_PORT = int(os.environ.get("READINESS_PORT", "2000"))
def run_or_die(args, die=True, **kwargs):
def run_or_die(args, die=True, debug=False, **kwargs):
"""
Opinionated subprocess.run() call with fancy logging
"""
@ -57,23 +61,29 @@ def run_or_die(args, die=True, **kwargs):
sys.stderr.flush()
ret = subprocess.run(args, text=True, **kwargs)
if ret.returncode != 0:
if ret.returncode == 0:
print(f"CMD OK\t{args_readable}", file=sys.stderr)
else:
print(f"CMD FAIL {ret.returncode}\t{args_readable}", file=sys.stderr)
if debug:
out = ret.stdout if ret.stdout is not None else "<not captured>"
err = ret.stderr if ret.stderr is not None else "<not captured>"
print(f"CMD STDOUT\n{out}", file=sys.stderr)
print(f"CMD STDERR\n{err}", file=sys.stderr)
sys.stderr.flush()
if ret.returncode != 0:
if die:
sys.exit(ret.returncode)
else:
print(f'{"CMD DIE FALSE"}', file=sys.stderr)
sys.stderr.flush()
else:
print(f"CMD OK\t{args_readable}", file=sys.stderr)
sys.stderr.flush()
return ret
@ -143,4 +153,5 @@ def readiness():
with socketserver.TCPServer(
("0.0.0.0", READINESS_PORT), ReadinessTCPHandler
) as srv:
print(f"Opening port {READINESS_PORT} for readiness TCP probe")
srv.serve_forever()