Skip to content

feat(target_chains/near): add reproducible build #2339

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .github/workflows/ci-near-contract.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ env:
CARGO_TERM_COLOR: always

jobs:
build:
test:
name: Workspace test
runs-on: ubuntu-latest
defaults:
run:
Expand All @@ -25,3 +26,14 @@ jobs:
- uses: actions/checkout@v2
- name: Test
run: ./workspace-test.sh
reproducible-build:
name: Reproducible build
runs-on: ubuntu-latest
defaults:
run:
working-directory: target_chains/near/receiver
steps:
- uses: actions/checkout@v2
- run: sudo apt-get install -y libudev-dev
- run: cargo +stable install --locked cargo-near@0.13.3
- run: cargo near build reproducible-wasm
43 changes: 34 additions & 9 deletions target_chains/near/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,40 @@ of how to manually submit a price update from the CLI.

## Deployment

Deploying the NEAR contract has three steps:

1. Create a NEAR key with `near generate-key`
2. Fetch NEAR tokens from an available faucet, at last deploy around 100~ NEAR were needed.
3. See the example deploy script in `scripts/deploy.sh` to deploy the contract. You can find a codehash by:
- `sha256sum pyth.wasm` after building the contract.
- `list(bytes.fromhex(hash))` in Python to get a byte array.
- Replace the `codehash` field in deploy.sh for the initial codehash.
- Replace the sources with the keys expected by the network you're deploying on (testnet vs mainnet).
Deploying the NEAR contract has the following steps:

1. Create an account for the new contract:

```
near create-account contract-url.near --use-account <payer_account_id> --public-key ed25519:<authority_public_key> --initial-balance "2.5" --network-id mainnet
```

2. Build the contract:

```
cd receiver
cargo near build reproducible-wasm
```

3. Deploy the contract code:

```
near deploy contract-url.near target/near/pyth_near.wasm --network-id mainnet --init-function new --init-args '{"wormhole":"contract.wormhole_crypto.near","initial_source":{"emitter":[225,1,250,237,172,88,81,227,43,155,35,181,249,65,26,140,43,172,74,174,62,212,221,123,129,29,209,167,46,164,170,113],"chain":26},"gov_source":{"emitter":[86,53,151,154,34,28,52,147,30,50,98,11,146,147,164,99,6,85,85,234,113,254,151,205,98,55,173,232,117,177,46,158],"chain":1},"update_fee":"1","stale_threshold":60}'
```

To check the contract:

1. Update price feeds:

```
near call --network-id mainnet contract-url.near update_price_feeds '{ "data": "504e415501..." }' --use-account <payer_account> --gas 300000000000000 --deposit 0.01
```

2. Query price feed:

```
near view --network-id mainnet contract-url.near get_price_unsafe '{ "price_identifier": "e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43" }'
```

## Further Documentation

Expand Down
3 changes: 2 additions & 1 deletion target_chains/near/receiver/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion target_chains/near/receiver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ version = "0.1.0"
authors = ["Pyth Data Association"]
edition = "2021"
description = "A Pyth Receiver for Near"
repository = "https://github.com/pyth-network/pyth-crosschain"

[lib]
name = "pyth"
name = "pyth_near"
crate-type = ["cdylib", "lib"]

[features]
Expand All @@ -22,6 +23,7 @@ num-derive = { version = "0.3.3" }
pyth-wormhole-attester-sdk = { path = "../../../wormhole_attester/sdk/rust" }
pyth-sdk = { version = "0.7.0" }
pythnet-sdk = { path = "../../../pythnet/pythnet_sdk" }
schemars = { version = "0.8.21" }
serde_wormhole = { git = "https://github.com/wormhole-foundation/wormhole", tag="rust-sdk-2024-01-25" }
strum = { version = "0.24.1", features = ["derive"] }
thiserror = { version = "1.0.38" }
Expand All @@ -47,3 +49,9 @@ lto = "fat"
debug = false
panic = "abort"
overflow-checks = true

[package.metadata.near.reproducible_build]
image = "sourcescan/cargo-near:0.13.3-rust-1.84.1"
image_digest = "sha256:baa712c5d2b7522d38175e36330d336ad2c4ce32bfaaa41af94ce40407ecd803"
passed_env = []
container_build_command = ["cargo", "near", "build", "non-reproducible-wasm", "--locked"]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

such a strange thing: the reproducible build runs non-reproducible-wasm build command lol

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the difference between them is that reproducible-wasm spins up a docker container, so it makes sense that it's not needed inside the container.

10 changes: 10 additions & 0 deletions target_chains/near/receiver/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
fn main() {
// CARGO_NEAR_ABI_GENERATION env var is set by cargo-near when generating ABI.
// We need to expose it as a cfg option to allow conditional compilation
// of our JsonSchema impls.
println!("cargo::rerun-if-env-changed=CARGO_NEAR_ABI_GENERATION");
println!("cargo::rustc-check-cfg=cfg(abi)");
if std::env::var("CARGO_NEAR_ABI_GENERATION").as_deref() == Ok("true") {
println!("cargo::rustc-cfg=abi");
}
}
21 changes: 21 additions & 0 deletions target_chains/near/receiver/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use {
},
pyth_wormhole_attester_sdk::PriceAttestation,
pythnet_sdk::messages::PriceFeedMessage,
schemars::{gen::SchemaGenerator, schema::Schema, JsonSchema},
wormhole_sdk::Chain as WormholeChain,
};

Expand Down Expand Up @@ -68,6 +69,20 @@ impl near_sdk::serde::Serialize for PriceIdentifier {
}
}

impl JsonSchema for PriceIdentifier {
fn is_referenceable() -> bool {
false
}

fn schema_name() -> String {
String::schema_name()
}

fn json_schema(gen: &mut SchemaGenerator) -> Schema {
String::json_schema(gen)
}
}

/// A price with a degree of uncertainty, represented as a price +- a confidence interval.
///
/// The confidence interval roughly corresponds to the standard error of a normal distribution.
Expand All @@ -79,6 +94,10 @@ impl near_sdk::serde::Serialize for PriceIdentifier {
#[derive(BorshDeserialize, BorshSerialize, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[borsh(crate = "near_sdk::borsh")]
#[serde(crate = "near_sdk::serde")]
// I64 and U64 only implement JsonSchema when "abi" feature is enabled in near_sdk,
// but unconditionally enabling this feature doesn't work, so we have to make this impl
// conditional.
#[cfg_attr(abi, derive(JsonSchema))]
pub struct Price {
pub price: I64,
/// Confidence interval around the price
Expand Down Expand Up @@ -161,6 +180,7 @@ impl From<&PriceFeedMessage> for PriceFeed {
PartialEq,
PartialOrd,
Serialize,
JsonSchema,
)]
#[borsh(crate = "near_sdk::borsh")]
#[serde(crate = "near_sdk::serde")]
Expand Down Expand Up @@ -197,6 +217,7 @@ impl From<Chain> for u16 {
PartialEq,
PartialOrd,
Serialize,
JsonSchema,
)]
#[borsh(crate = "near_sdk::borsh")]
#[serde(crate = "near_sdk::serde")]
Expand Down
6 changes: 3 additions & 3 deletions target_chains/near/receiver/tests/workspaces.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use {
near_sdk::json_types::{I64, U128, U64},
near_workspaces::types::{Gas, NearToken},
pyth::{
pyth_near::{
governance::{GovernanceAction, GovernanceInstruction, GovernanceModule},
state::{Chain, Price, PriceIdentifier, Source},
},
Expand All @@ -27,9 +27,9 @@ async fn initialize_chain() -> (

// Deploy Pyth
let contract = worker
.dev_deploy(&std::fs::read("pyth.wasm").expect("Failed to find pyth.wasm"))
.dev_deploy(&std::fs::read("pyth_near.wasm").expect("Failed to find pyth_near.wasm"))
.await
.expect("Failed to deploy pyth.wasm");
.expect("Failed to deploy pyth_near.wasm");

// Deploy Wormhole Stub, this is a dummy contract that always verifies VAA's correctly so we
// can test the ext_wormhole API.
Expand Down
2 changes: 1 addition & 1 deletion target_chains/near/receiver/workspace-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ set -euo pipefail
rustup target add wasm32-unknown-unknown

cargo build --release --target wasm32-unknown-unknown
cp target/wasm32-unknown-unknown/release/pyth.wasm .
cp target/wasm32-unknown-unknown/release/pyth_near.wasm .

(
cd ../wormhole-stub
Expand Down
33 changes: 0 additions & 33 deletions target_chains/near/scripts/deploy.sh

This file was deleted.

Loading