Giter Club home page Giter Club logo

pyth-client's Introduction

pyth-client

Pyth oracle program and off-chain client API.

Oracle Program

The Pyth oracle program lives in the program/ directory. It consists of both C and Rust code, but everything can be built and tested using cargo.

Build Instructions

First, make sure you have the solana tool suite installed on your machine. (The build depends on some C makefiles that are in the tool suite.) Make sure you have installed the same solana version that is being used in CI

Then, simply run cargo build to compile the oracle program as a native binary, or cargo build-bpf to build a BPF binary that can be uploaded to the blockchain. This step will produce a program binary target/deploy/pyth_oracle.so.

Testing

Simply run cargo test. This command will run several sets of tests:

  • Unit tests of individual functions
  • Simulated transaction tests against the BPF binary running on a solana simulator
  • Exhaustive / randomized test batteries for core oracle functionality

Rust tests live in the tests/ module of the rust code, and C tests are named something like test_*.c. The C tests are linked into the rust binary so they run as part of cargo test as well (see tests/test_c_code.rs).

You can also run cargo test-bpf, which runs the same tests as cargo test, though it's slightly slower and the UX is worse.

pre-commit hooks

pre-commit is a tool that checks and fixes simple issues (formatting, ...) before each commit. You can install it by following their website. In order to enable checks for this repo run pre-commit install from command-line in the root of this repo.

The checks are also performed in the CI to ensure the code follows consistent formatting. Formatting is only currently enforced in the program/ directory. You might also need to install the nightly toolchain to run the formatting by running rustup toolchain install nightly.

pythd (off-chain client API)

⚠️ pythd is deprecated and has been replaced by pyth-agent. This new client is backward compatible with pythd, but more stable and configurable.

pythd provides exposes a web API for interacting with the on-chain oracle program.

Build Instructions

# depends on openssl
apt install libssl-dev

# depends on libz
apt install zlib1g zlib1g-dev

# depends on libzstd
apt install libzstd-dev

# uses cmake to build
apt install cmake

# default is release build
./scripts/build.sh

You may want to build this repository inside a linux docker container for various reasons, e.g., if building on an M1 mac, or to run BPF binaries. You can run the following command to open a shell in a linux docker container with the pyth-client directory mounted:

export PYTH_REPO=/path/to/host/pyth-client

// Use the latest pythd image from https://hub.docker.com/r/pythfoundation/pyth-client/tags?name=pythd
export IMAGE=...

docker run -it \
  --volume "${HOME}:/home/pyth/home" \
  --volume "${HOME}/.config:/home/pyth/.config" \
  --mount "type=bind,src=${PYTH_REPO},target=/home/pyth/pyth-client" \
  --userns=host \
  --user="$( id -ur ):$( id -gr )" \
  --platform linux/amd64 \
  $IMAGE \
  /bin/bash -l

This command runs a recent pyth-client docker image that already has the necessary dependencies installed. Therefore, once the container is running, all you have to do is run cd pyth-client && ./scripts/build.sh. Note that updates to the pyth-client directory made inside the docker container will be persisted to the host filesystem (which is probably desirable).

Alternatively, you can run ./scripts/start-docker-build-env.sh && cd pyth-client && cargo build --release

Fuzzing

Build a docker image for running fuzz tests:

docker build . --platform linux/amd64 -f docker/fuzz/Dockerfile -t pyth-fuzz

Each fuzz test is invoked via an argument to the fuzz command-line program, and has a corresponding set of test cases in the subdirectory with the same name as the test. You can run these tests using a command like:

docker run -t \
  --platform linux/amd64 \
  -v "$(pwd)"/findings:/home/pyth/pyth-client/findings \
  pyth-fuzz \
  sh -c "./afl/afl-fuzz -i ./pyth-client/pyth/tests/fuzz/add/testcases -o ./pyth-client/findings ./pyth-client/build/fuzz add"

This command will run the add fuzz test on the tests cases in pyth/tests/fuzz/add/testcases, saving any outputs to findings/. Note that findings/ is shared between the host machine and the docker container, so you can inspect any error cases by looking in that subdirectory on the host.

If you find an error case that you want to investigate further, you can run the program on the failing input using something like:

docker run -t \
  --platform linux/amd64 \
  -v "$(pwd)"/findings:/home/pyth/pyth-client/findings \
  pyth-fuzz \
  sh -c "./pyth-client/build/fuzz add < ./pyth-client/findings/crashes/id\:000000\,sig\:06\,src\:000000\,op\:flip1\,pos\:0"

in this example, id\:000000\,sig\:06\,src\:000000\,op\:flip1\,pos\:0 is the file containing the failing input.

Development Setup Using VS Code

First create a docker container in daemon as your working container (IMAGE and PYTH_REPO same as above):

docker run --name pyth-dev -d \\
  --volume "${HOME}:/home/pyth/home" \\
  --volume "${HOME}/.config:/home/pyth/.config" \\
  --volume "${HOME}/.ssh:/home/pyth/.ssh" \\ # Github access
  --mount "type=bind,src=${PYTH_REPO},target=/home/pyth/pyth-client" \\
  --platform linux/amd64 \\
  $IMAGE \\
  /bin/bash -c "while [ true ]; do sleep 1000; done"

Default user in the image is pyth which may not have access to your directories. Assign your user id and group id to it to enable access.

host@host$ id $USER # Shows user_id, group_id, and group names
host@host$ docker exec -ti pyth-dev bash
pyth@pyth-dev$ sudo su
root@pyth-dev# groupadd -g 1004 1004
root@pyth-dev# usermod -u 1002 -g 1004 -s /bin/bash pyth

Finally, in docker extension inside VS Code click right and choose "Attach VS Code". If you're using a remote host in VS Code make sure to let this connection be open.

Deployment

Oracle program upgrades are managed by the Pythian Council multisig. The steps to deploy a new version are:

  1. Create a release branch from main. This should include the binary for the Pythnet oracle program (pyth_oracle_pythnet.so).
  2. Install Solana CLI if not already installed.
  3. Set Solana config for the target network, e.g., devnet: solana config set --url https://api.devnet.solana.com.
  4. Execute solana program write-buffer pyth_oracle_pythnet.so to obtain the buffer address.
  5. Run solana program show <ORACLE_PROGRAM_PUBKEY> to obtain the authority of the current program.
  6. Use solana program set-buffer-authority <BUFFER_PUBKEY> --new-buffer-authority <NEW_BUFFER_AUTHORITY> to assign the upgrade authority from the previous step to the buffer address.
  7. Submit a proposal with xc-admin for program upgrade using the upgrade-program command.
  8. Verify the buffer by running solana program dump <BUFFER> temp_file && shasum -a 256 temp_file && rm temp_file, comparing the hash with the one from build-bpf.sh#L35.
  9. Once the proposal secures enough signatures, it will be automatically relayed to the target network, upgrading the program.

pyth-client's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyth-client's Issues

arb slotIndex in pyth_tx

It's possible for one Solana node to be behind another Solana node. In determining the leader, arb several Solana rpc nodes.

Native HTTPS support

pythd does not natively support connecting to HTTPS endpoints.

#49 is a brittle workaround. Several users are having issues connecting to nodes that require TLS. Having to manage an additional NGINX instance is an added maintenance burden and introduces another single point of failure.

Please consider using a HTTP client library such as

replace qsort module

Replace the qsort module, which was a temporary workaround for lack of sort in the Solana library.

Pyth Daemon - "not ready to publish - check rpc / pyth_tx connection" on RPC reconnect

pythd version - 2.9.1
command: home/pyth/pyth-client/build/pythd -r nginx:7899:7900 -t pyth-tx-server-mainnet:8898 -k $KDIR -w /home/pyth/pyth-client/dashboard"

When pythd reconnects to the Solana RPC we see either of the following logs:

[2021-11-29T14:37:24.923149Z 11 INF rpc_connected                           ]
[2021-11-29T14:37:24.896228Z 11 ERR rpc_websocket_reset                     ] error=fail to read [11 Resource temporarily unavailable],host=nginx:7899:7900,port=7899
[2021-11-29T05:09:28.396393Z 11 ERR rpc_http_reset                          ] error=fail to read [11 Resource temporarily unavailable],host=nginx:7899:7900,port=7899
[2021-11-29T05:09:28.451638Z 11 INF rpc_connected    

After the reconnect happens, we are unable to post price_update because of the following JSON RPC error:

Error code: -32002 message: not ready to publish - check rpc / pyth_tx connection

We don't see any matching pythx errors. The only way for us to fix this is to restart the pythd process.

Ideally pythd would be able to handle those JSON RPC requests without having to restart it after a RPC reconnect.

Arbitrary JSON RPC subscription API?

Hi everyone!

We tried to use the the price webosocket endpoint with the jsonrpc library of parity.
We could not manage to make it work because the subscribe endpoint is expected to provide a subscription ID straight in the result field of the rpc response. But the current implementation is wrapping the ID in an object with a subscription field.
We checked various websocket subscription implementations over JSONRPC and all of them were answering with the ID straight in the result field.

I updated the endpoint to be compliant with the common implementation PR #20 (I also linked many known implementations of it which are behaving correctly).

Any chance we get this merged? I don't know whether there are more stuff to change so feel free to give a strong review on my changes.

NOTE: even your website is using the common implementation for the price feed :)

Static Analysis - Cleanup & Automation

Running CLion inspections over the repo reveals lots of issues, such as:

  • uninitialized members
  • unused and shadowed variables
  • subclass-shadowed non-virtual functions
  • non-explicit single-argument constructors
  • C-style casts and macros in C++ code
  • missing override specifiers

We should clean these up and protect against future static analysis failures with automation, using CLion's inspect.sh or a tool like clang-tidy.

As a first step, add a second GitHub Action which installs and runs extra tools on top of the base docker.yaml.

Pythd Dashboard Issue

We had a few questions about the pythd dashboard referenced in your documentation [here]
(https://urldefense.com/v3/__https:/docs.pyth.network/publish-data*running-the-dashboard__;Iw!!GSt_xZU7050wKg!qOrCVC6LYuM9QkJT5v0UNKyt_FzhxX27xu4cI4ccru8FsSs_jcyUmeVdd1nmza1ybJXCPL-5Ms6r6d3DVKvlSaw$).

First, the dashboard is broken. The file dashboard/dashboard.js attempts to make a websocket connection to pythd at a hardcoded URL: ws://localhost:8910. This is a problem for multiple reasons:
• You might not want to view the dashboard on the same host on which you’re running pythd.
• Even if you are viewing the dashboard on the same host as pythd’s docker container, the container’s published port is unlikely to be 8910.
The dashboard, as-is, only works if the browser you’re viewing it on is on the same host as pythd and the published port of pythd’s container is 8910. Can your team fix this?

Second, the dashboard doesn’t seem very useful to a publisher. It shows a view of the current aggregated state of all symbols. It might be more useful to us if it was a view of what pythd was seeing from its clients and sending to the broader pyth network. Is that something that you could change?

Thanks,

Pythd rpc host url token support

A lot of Solana shared node providers use tokens in the url to authenticate.

Pythd doesn't seem to accept such urls in the rpc_host parameter.

Are there any plans to support them?

Unable to build v2021-07-27 branch

In file included from /home/ubuntu/solana-test/pyth-client/pc/manager.cpp:1:
In file included from /home/ubuntu/solana-test/pyth-client/pc/manager.hpp:5:
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:136:10: error: 'pc::init_mapping::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::create_account * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::create_account *')
void on_response( rpc::program_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:137:10: error: 'pc::init_mapping::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::init_mapping * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::init_mapping *')
void on_response( rpc::program_subscribe * ) override;

/home/ubuntu/solana-test/pyth-client/pc/request.hpp:138:10: error: 'pc::init_mapping::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::signature_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::signature_subscribe *')
void on_response( rpc::program_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:195:10: error: 'pc::add_mapping::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::create_account * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::create_account *')
void on_response( rpc::program_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:196:10: error: 'pc::add_mapping::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::add_mapping * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::add_mapping *')
void on_response( rpc::program_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:197:10: error: 'pc::add_mapping::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::signature_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::signature_subscribe *')
void on_response( rpc::program_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:228:10: error: 'pc::add_product::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::create_account * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::create_account *')
void on_response( rpc::program_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:229:10: error: 'pc::add_product::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::signature_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::signature_subscribe *')
void on_response( rpc::program_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:230:10: error: 'pc::add_product::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::add_product * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::add_product *')
void on_response( rpc::program_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:263:10: error: 'pc::upd_product::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::signature_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::signature_subscribe *')
void on_response( rpc::program_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:264:10: error: 'pc::upd_product::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::upd_product * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::upd_product *')
void on_response( rpc::program_subscribe * ) override;
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:300:10: error: 'pc::add_price::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::create_account * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::create_account *')
void on_response( rpc::program_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:301:10: error: 'pc::add_price::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::signature_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::signature_subscribe *')
void on_response( rpc::program_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:302:10: error: 'pc::add_price::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::add_price * ) override;
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::add_price *')
void on_response( rpc::program_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:336:10: error: 'pc::init_price::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::signature_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::signature_subscribe *')
void on_response( rpc::program_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:337:10: error: 'pc::init_price::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::init_price * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::init_price *')
void on_response( rpc::program_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:367:10: error: 'pc::add_publisher::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::add_publisher * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::add_publisher *')
void on_response( rpc::program_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:368:10: error: 'pc::add_publisher::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::signature_subscribe * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::signature_subscribe *')
void on_response( rpc::program_subscribe * ) override;
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:399:10: error: 'pc::del_publisher::on_response' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void on_response( rpc::del_publisher * ) override;
^
/home/ubuntu/solana-test/pyth-client/pc/request.hpp:102:10: note: hidden overloaded virtual function 'pc::request::on_response' declared here: type mismatch at 1st parameter ('rpc::program_subscribe *' vs 'rpc::del_publisher *')
void on_response( rpc::program_subscribe * ) override;
^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
make[2]: *** [CMakeFiles/pc.dir/build.make:141: CMakeFiles/pc.dir/pc/manager.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:98: CMakeFiles/pc.dir/all] Error 2
make: *** [Makefile:141: all] Error 2

pythd: invalid or corrupt product account

pyth client (testnet) is crashing with the following error:

pythd: invalid or corrupt product account

Startup arguments:

pythd -r pyth-testnet-rpc-1.solana.p2p.org:80:80 -k /app/pyth-client/keystore -d -w /app/pyth-client/dashboard -x

Log file leading up to the crash is attached.
pyth-client.log.gz

Pyth client websocket interface should lower case headers before comparing them

Headers in HTTP should be processed case-insentively, however the pythd proxy relies on the headers being capitalised. This causes issues when attempting to place the Pythd websocket interface behind a proxy (or using a client that uses lower-case headers).

Relevant locations in the pythd source (AFAICT):

./net_socket.cpp:1059:  if ( !get_header_val( "Sec-WebSocket-Key", key ) ) {
./net_socket.cpp:1028:          0 == __builtin_strncmp( "Upgrade", hdr, hlen ) &&

The first causes a 'hang' (the connection just stalls) if Sec-WebSocket-Key is specified with any other capitalisation. The second case causes websocket upgrades to not be processed at all and the pythd API returns 404 (as it doesn't attempt websocket upgrades).

pythd throws when HOME undefined

pythd crashes with the following when getenv ( "HOME" ) returns nullptr:

terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_M_construct null not valid
Aborted

HOME being undefined is not common and in my case may be an artifact of what nitro-cli is doing under the hood, but figured this would be helpful for anyone who runs into the same issue. A quick test to ensure the envvar is defined and provide less cryptic output may also be helpful.

Instruction count regression tests

Requires #64
Required for #98

Create a regression test suite similar to those in pyth/tests (see #83) which compares instruction counts to expected values. For code changes which are expected to affect instruction counts, these values can be updated by running the test suite with --inplace.

[pythd] mainnet: error=failed to handshake websocket: Too Many Requests

Hi,

I'm trying to use pythd with mainnet-beta, but I can't connect. It runs fine using devnet, but mainet-beta fails.

./pythd -k $KDIR -r $RHOST
[2021-10-01T10:01:03.758888Z 722534 INF publish_key ] key_name=CZfEVuDoUKEgpyuoBtTHDkUcetvyKrTKWfPJsYfqv355
[2021-10-01T10:01:03.758935Z 722534 INF mapping_key ] key_name=AHtgzX45WTKfkPG53L6WYhGEXwQkN1BVknET3sVsLL8J
[2021-10-01T10:01:03.758949Z 722534 INF program_key ] key_name=FsJ3A3u2vn5cTVofAjvy6y5kwABJAqYWpe4975bi2epH
[2021-10-01T10:01:03.796309Z 722534 INF listening ] port=8910,content_dir=
[2021-10-01T10:01:03.796316Z 722534 INF initialized ] version=2,rpc_host=api.mainnet-beta.solana.com,tx_host=localhost,capture_file=,commitment=confirmed,publish_interval(ms)=227
[2021-10-01T10:01:03.865403Z 722534 INF rpc_connected ]
[2021-10-01T10:01:03.926304Z 722534 INF received_recent_block_hash ] curr_slot=99230323,hash_slot=99230269,round_trip_time(ms)=30.283889
[2021-10-01T10:01:03.957041Z 722534 INF add_mapping ] account=AHtgzX45WTKfkPG53L6WYhGEXwQkN1BVknET3sVsLL8J,num_products=43
[2021-10-01T10:01:03.987762Z 722534 INF add_product ] account=5uKdRzB3FzdmwyCHrqSGq4u2URja617jqtKkM71BVrkw,attr={"asset_type":"Crypto","symbol":"BCH/USD","country":"US","quote_currency":"USD","description":"BCH/USD","tenor":"Spot","generic_symbol":"BCHUSD"}
[2021-10-01T10:01:03.988206Z 722534 INF add_product ] account=ETuC4VK6kuHfxc9MCU14dASfnGBfzgFUVCs1oVowawHb,attr={"asset_type":"Crypto","symbol":"LTC/USD","country":"US","quote_currency":"USD","description":"LTC/USD","tenor":"Spot","generic_symbol":"LTCUSD"}
[2021-10-01T10:01:03.988539Z 722534 INF add_product ] account=4aDoSXJ5o3AuvL7QFeR6h44jALQfTmUUCTVGDD6aoJTM,attr={"asset_type":"Crypto","symbol":"BTC/USD","country":"US","quote_currency":"USD","description":"BTC/USD","tenor":"Spot","generic_symbol":"BTCUSD"}
[2021-10-01T10:01:03.988871Z 722534 INF add_product ] account=4ANvG59u4YToJnVi2CkZbbfTE9mWHpyNbMmm69R43E3q,attr={"asset_type":"Crypto","symbol":"BNB/USD","country":"US","quote_currency":"USD","description":"BNB/USD","tenor":"Spot","generic_symbol":"BNBUSD"}
[2021-10-01T10:01:03.989246Z 722534 INF add_product ] account=GeSpWQucSvWhaXVvC2RJihpne9dCdL25pn46BTiDLyYs,attr={"asset_type":"Crypto","symbol":"DOGE/USD","country":"US","quote_currency":"USD","description":"DOGE/USD","tenor":"Spot","generic_symbol":"XDGUSD"}
[2021-10-01T10:01:03.989538Z 722534 INF add_product ] account=Av6XyAMJnyi68FdsKSPYgzfXGjYrrt6jcAMwtvzLCqaM,attr={"asset_type":"Crypto","symbol":"USDT/USD","country":"US","quote_currency":"USD","description":"USDT/USD","tenor":"Spot","generic_symbol":"USDTUSD"}
[2021-10-01T10:01:03.989866Z 722534 INF add_product ] account=ALP8SdU9oARYVLgLR7LrqMNCYBnhtnQz1cj6bwgwQmgj,attr={"asset_type":"Crypto","symbol":"SOL/USD","country":"US","quote_currency":"USD","description":"SOL/USD","tenor":"Spot","generic_symbol":"SOLUSD"}
[2021-10-01T10:01:03.990104Z 722534 INF add_product ] account=8GWTTbNiXdmyZREXbjsZBmCRuzdPrW55dnZGDkTRjWvb,attr={"asset_type":"Crypto","symbol":"USDC/USD","country":"US","quote_currency":"USD","description":"USDC/USD","tenor":"Spot","generic_symbol":"USDCUSD"}
[2021-10-01T10:01:03.990411Z 722534 INF add_product ] account=EMkxjGC1CQ7JLiutDbfYb7UKb3zm9SJcUmr1YicBsdpZ,attr={"asset_type":"Crypto","symbol":"ETH/USD","country":"US","quote_currency":"USD","description":"ETH/USD","tenor":"Spot","generic_symbol":"ETHUSD"}
[2021-10-01T10:01:03.990688Z 722534 INF add_product ] account=6T1eJbKWyhZXEjmuBej9gPk3SRTagzrEQovCSwAWD57P,attr={"asset_type":"Crypto","symbol":"SRM/USD","country":"US","quote_currency":"USD","description":"SRM/USD","tenor":"Spot","generic_symbol":"SRMUSD"}
[2021-10-01T10:01:04.020090Z 722534 ERR rpc_http_reset ] error=fail to read [104 Connection reset by peer],host=api.mainnet-beta.solana.com,port=80
[2021-10-01T10:01:04.088382Z 722534 ERR rpc_websocket_reset ] error=failed to handshake websocket: Too Many Requests,host=api.mainnet-beta.solana.com,port=80
[2021-10-01T10:01:06.083764Z 722534 ERR rpc_websocket_reset ] error=failed to handshake websocket: Too Many Requests,host=api.mainnet-beta.solana.com,port=80
[2021-10-01T10:01:10.084534Z 722534 ERR rpc_websocket_reset ] error=failed to handshake websocket: Too Many Requests,host=api.mainnet-beta.solana.com,port=80
[2021-10-01T10:01:18.086001Z 722534 INF rpc_connected ]
[2021-10-01T10:01:18.152652Z 722534 INF received_recent_block_hash ] curr_slot=99230356,hash_slot=99230321,round_trip_time(ms)=33.398536
[2021-10-01T10:01:18.186456Z 722534 INF add_mapping ] account=AHtgzX45WTKfkPG53L6WYhGEXwQkN1BVknET3sVsLL8J,num_products=43
[2021-10-01T10:01:18.186835Z 722534 INF add_product ] account=5uKdRzB3FzdmwyCHrqSGq4u2URja617jqtKkM71BVrkw,attr={"asset_type":"Crypto","symbol":"BCH/USD","country":"US","quote_currency":"USD","description":"BCH/USD","tenor":"Spot","generic_symbol":"BCHUSD"}
[2021-10-01T10:01:18.187316Z 722534 INF add_price ] account=5ALDzwcRJfSyGdGyhP3kP628aqBNHZzLuVww7o9kdspe,product=5uKdRzB3FzdmwyCHrqSGq4u2URja617jqtKkM71BVrkw,symbol=BCH/USD,price_type=price,version=2,exponent=-8,num_publishers=9
[2021-10-01T10:01:18.187568Z 722534 INF add_product ] account=ETuC4VK6kuHfxc9MCU14dASfnGBfzgFUVCs1oVowawHb,attr={"asset_type":"Crypto","symbol":"LTC/USD","country":"US","quote_currency":"USD","description":"LTC/USD","tenor":"Spot","generic_symbol":"LTCUSD"}
[2021-10-01T10:01:18.188111Z 722534 INF add_price ] account=8RMnV1eD55iqUFJLMguPkYBkq8DCtx81XcmAja93LvRR,product=ETuC4VK6kuHfxc9MCU14dASfnGBfzgFUVCs1oVowawHb,symbol=LTC/USD,price_type=price,version=2,exponent=-8,num_publishers=11
[2021-10-01T10:01:18.188375Z 722534 INF add_product ] account=4aDoSXJ5o3AuvL7QFeR6h44jALQfTmUUCTVGDD6aoJTM,attr={"asset_type":"Crypto","symbol":"BTC/USD","country":"US","quote_currency":"USD","description":"BTC/USD","tenor":"Spot","generic_symbol":"BTCUSD"}
[2021-10-01T10:01:18.188793Z 722534 INF add_price ] account=GVXRSBjFk6e6J3NbVPXohDJetcTjaeeuykUpbQF8UoMU,product=4aDoSXJ5o3AuvL7QFeR6h44jALQfTmUUCTVGDD6aoJTM,symbol=BTC/USD,price_type=price,version=2,exponent=-8,num_publishers=17
[2021-10-01T10:01:18.189053Z 722534 INF add_product ] account=4ANvG59u4YToJnVi2CkZbbfTE9mWHpyNbMmm69R43E3q,attr={"asset_type":"Crypto","symbol":"BNB/USD","country":"US","quote_currency":"USD","description":"BNB/USD","tenor":"Spot","generic_symbol":"BNBUSD"}
[2021-10-01T10:01:18.221274Z 722534 ERR rpc_http_reset ] error=fail to read [104 Connection reset by peer],host=api.mainnet-beta.solana.com,port=80
[2021-10-01T10:01:19.088638Z 722534 INF rpc_connected ]
[2021-10-01T10:01:19.160880Z 722534 INF received_recent_block_hash ] curr_slot=99230359,hash_slot=99230322,round_trip_time(ms)=37.319143
pythd: Connection rate limits exceeded, contact your app developer or [email protected].
[2021-10-01T10:01:19.193679Z 722534 INF pythd_teardown

move pyth admin functions to python

there is no need to have these admin functions implemented in C++

also, many of these should be bundled into the same transaction to avoid undesirable behavior (price account added but no initialized, etc)

RPC host fails name resolution if it contains a path

Hello,

I'm trying to use a RPC host at rpcpool.com with a URL that looks like this: my-subdomain.rpcpool.com/some-path

When I pass that URL as the rpc host with the -r flag, the pythd daemon fails with the following error:

pythd: failed to resolve host

I traced the source code and confirmed that getaddrinfo is being called with the entire URL and not just the hostname, which is where it's failing.

I'm guessing this is the same underlying issue as #93 but it's hard to tell since they didn't mention where it's failing for them.

API connection error

after connecting without issue for about a month, I am now getting the following error:
ClientConnectorCertificateError: Cannot connect to host api.devnet.solana.com:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:997)')]

The snippet presented in github was used to test the connection but the error remains:
from pythclient.pythclient import PythClient
from pythclient.pythaccounts import PythPriceAccount
from pythclient.utils import get_key

solana_network="devnet"
async with PythClient(
first_mapping_account_key=get_key(solana_network, "mapping"),
program_key=get_key(solana_network, "program") if use_program else None,
) as c:
await c.refresh_all_prices()
products = await c.get_products()
for p in products:
print(p.attrs)
prices = await p.get_prices()
for _, pr in prices.items():
print(
pr.price_type,
pr.aggregate_price_status,
pr.aggregate_price,
"p/m",
pr.aggregate_price_confidence_interval,
)

I am running python 3.10 at the moment.

[pyth] Add a "get_all_product_data" method

Currently pyth has get_product_list which returns a list of product keys. In order to see price details you have to call get_product [product_key] many times.

Add a get_all_product_data command which prints all products, prices and publisher details in a single query.

How to publish price using libpc? test_publish.cpp incomplete?

I want to publish EUR/USD price. From the docs at
https://github.com/pyth-network/pyth-client/blob/main/doc/getting_started.md,
After building pyth-client, I should:

  1. Run the proxy via pyth_tx -r $KHOST
  2. Run the test publisher program via test_publish -k $KDIR -r $KHOST -t $THOST
    Now, from what I understand, I am supposed to expect the test_publish::on_response callbacks to be triggered when the test publisher program receives a message from pyth_tx, and then inside that callback, there's the chance for me to publish the price (I haven't figured out exactly how yet).

Q1: However, I notice that test_publish::on_response never ever gets called. Why?

Digging some more into the test_publish.cpp code, I notice that test_connect's pub1_ and pub2_ members are created but never used, and that test_connect::get_price is not implemented. So these missing parts (unused member, unimplemented method) seem to suggest that test_publish.cpp is incomplete, specifically missing parts on how to actually publish price. Also, putting the missing implementations aside, are the SYMBOL1 and SYMBOL2 in the construction of the 2 test_publish objects arbitrary, or must they correspond to existing instruments in the solana network?

Q2: Exactly, how should one publish price, for say, EUR/USD, step-by-step, using libpc? I tried to understand the docs and reading the sources but it doesn't seem so clear.

rpc_client reset with outstanding requests

if rpc_client::reset is called with outstanding requests, the mapping from id to request type gets cleared and the subsequent processing of responses results can use the wrong message type

Convert `program/` to C++.

  • Remove #ifdef __cplusplus and extern "C" boilerplate.
  • Replace constant macros with safer constexprs.
  • Replace prefix conventions (pc_, pd_, etc.) with namespace/class-scoping.
  • Add access control, const methods, etc.
  • Avoid confusing static analyzers and IDEs with multi-language headers.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.