Skip to content

Commit 1de3dd4

Browse files
guibescosReisenRiateche
authored
feat: add publisher caps to the validator (#412)
* feat(program): match version with pythnet * feat: validator access point (wip) * feat: add price account flags * feat(program): fill out validator aggregation code * feat: don't aggregate on v2, clear message buffer, report validator aggregation errors * feat: return price feed messages from validator aggregation * test: enable v2 aggregation * test: test aggregation toggle * fix: don't aggregate in validator if already aggregated in this slot * chore: reexport solana_program and add derive debug * chore: add comments * fix: don't revert if c_upd_aggregate returns false * fix: make update_price_cumulative infallible; don't generate v2 messages until v1 buffer is cleared * chore: remove publisher sorting hack * chore: remove AggregationOutcome * fix: remove debug_assert * fix: allow clearing message buffers regardless of message_sent_ flag * test: add test_upd_price_with_validator * checkpoint * fix import * go * try this * go * try again * Checkpoint * go * rename * add test * cargo lock * go * go * format * rename * bump again * add z * go * chore: add missing imports and fix warnings * add m * Clippy * Update program/rust/src/accounts/price.rs Co-authored-by: Pavel Strakhov <[email protected]> * Update program/rust/src/accounts/price.rs Co-authored-by: Pavel Strakhov <[email protected]> * Remove vector * fix: remove unwrap * add comments * fix: undo this * another comment * add comment * use checked indexing * fix: use crates version of pythnet-sdk --------- Co-authored-by: Reisen <[email protected]> Co-authored-by: Pavel Strakhov <[email protected]>
1 parent 0f6a651 commit 1de3dd4

File tree

6 files changed

+205
-43
lines changed

6 files changed

+205
-43
lines changed

Cargo.lock

+58-12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

program/rust/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ num-traits = "0.2"
1717
byteorder = "1.4.3"
1818
serde = { version = "1.0", features = ["derive"], optional = true }
1919
strum = { version = "0.24.1", features = ["derive"], optional = true }
20-
pythnet-sdk = { git = "https://github.com/pyth-network/pyth-crosschain", rev="60144002053a93f424be70decd8a8ccb8d618d81"}
20+
pythnet-sdk = "2.2.0"
2121
solana-sdk = { version = "=1.14.17", optional = true }
2222
bitflags = { version = "2.6.0", features = ["bytemuck"] }
2323

@@ -31,7 +31,7 @@ rand = "0.8.5"
3131
quickcheck_macros = "1"
3232
bincode = "1.3.3"
3333
serde = { version = "1.0", features = ["derive"] }
34-
pythnet-sdk = { git = "https://github.com/pyth-network/pyth-crosschain", rev="60144002053a93f424be70decd8a8ccb8d618d81", features = ["quickcheck"]}
34+
pythnet-sdk = { version = "2.2.0" , features = ["quickcheck"]}
3535
serde_json = "1.0"
3636
test-generator = "0.3.1"
3737
csv = "1.1"

program/rust/src/accounts/price.rs

+29-5
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,14 @@ use {
1313
},
1414
pythnet_sdk::messages::{
1515
PriceFeedMessage,
16+
PublisherStakeCapsMessage,
1617
TwapMessage,
1718
},
1819
solana_program::pubkey::Pubkey,
19-
std::mem::size_of,
20+
std::{
21+
mem::size_of,
22+
u16,
23+
},
2024
};
2125

2226
/// Pythnet-specific PriceAccount implementation
@@ -111,7 +115,7 @@ mod price_pythnet {
111115
};
112116

113117
PriceFeedMessage {
114-
id: key.to_bytes(),
118+
feed_id: key.to_bytes(),
115119
price,
116120
conf,
117121
exponent: self.exponent,
@@ -141,7 +145,7 @@ mod price_pythnet {
141145
};
142146

143147
TwapMessage {
144-
id: key.to_bytes(),
148+
feed_id: key.to_bytes(),
145149
cumulative_price: self.price_cumulative.price,
146150
cumulative_conf: self.price_cumulative.conf,
147151
num_down_slots: self.price_cumulative.num_down_slots,
@@ -270,7 +274,7 @@ impl PythOracleSerialize for PriceFeedMessage {
270274
bytes[i..i + 1].clone_from_slice(&[DISCRIMINATOR]);
271275
i += 1;
272276

273-
bytes[i..i + 32].clone_from_slice(&self.id[..]);
277+
bytes[i..i + 32].clone_from_slice(&self.feed_id[..]);
274278
i += 32;
275279

276280
bytes[i..i + 8].clone_from_slice(&self.price.to_be_bytes());
@@ -313,7 +317,7 @@ impl PythOracleSerialize for TwapMessage {
313317
bytes[i..i + 1].clone_from_slice(&[DISCRIMINATOR]);
314318
i += 1;
315319

316-
bytes[i..i + 32].clone_from_slice(&self.id[..]);
320+
bytes[i..i + 32].clone_from_slice(&self.feed_id[..]);
317321
i += 32;
318322

319323
bytes[i..i + 16].clone_from_slice(&self.cumulative_price.to_be_bytes());
@@ -340,3 +344,23 @@ impl PythOracleSerialize for TwapMessage {
340344
bytes.to_vec()
341345
}
342346
}
347+
348+
impl PythOracleSerialize for PublisherStakeCapsMessage {
349+
fn to_bytes(self) -> Vec<u8> {
350+
const DISCRIMINATOR: u8 = 2;
351+
let mut result = vec![DISCRIMINATOR];
352+
result.extend_from_slice(&self.publish_time.to_be_bytes());
353+
result.extend_from_slice(
354+
&u16::try_from(self.caps.as_ref().len())
355+
.unwrap_or(u16::MAX)
356+
.to_be_bytes(),
357+
);
358+
359+
for cap in self.caps {
360+
result.extend_from_slice(&cap.publisher);
361+
result.extend_from_slice(&cap.cap.to_be_bytes());
362+
}
363+
364+
result
365+
}
366+
}

program/rust/src/tests/test_message.rs

+27
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,15 @@ use {
55
messages::{
66
Message,
77
PriceFeedMessage,
8+
PublisherStakeCapsMessage,
89
TwapMessage,
910
},
1011
wire::from_slice,
1112
},
13+
quickcheck::{
14+
Gen,
15+
QuickCheck,
16+
},
1217
quickcheck_macros::quickcheck,
1318
};
1419

@@ -38,3 +43,25 @@ fn test_twap_message_roundtrip(input: TwapMessage) -> bool {
3843
_ => false,
3944
}
4045
}
46+
47+
48+
fn prop_publisher_caps_message_roundtrip(input: PublisherStakeCapsMessage) -> bool {
49+
let reconstructed = from_slice::<BigEndian, Message>(&input.clone().to_bytes()).unwrap();
50+
51+
println!("Failed test case:");
52+
println!("{:?}", input);
53+
println!("{:?}", reconstructed);
54+
55+
match reconstructed {
56+
Message::PublisherStakeCapsMessage(reconstructed) => reconstructed == input,
57+
_ => false,
58+
}
59+
}
60+
61+
#[test]
62+
fn test_publisher_caps_message_roundtrip() {
63+
// Configure the size parameter for the generator
64+
QuickCheck::new()
65+
.gen(Gen::new(1024))
66+
.quickcheck(prop_publisher_caps_message_roundtrip as fn(PublisherStakeCapsMessage) -> bool);
67+
}

program/rust/src/tests/test_upd_price_with_validator.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ fn test_upd_price_with_validator() {
130130
.unwrap();
131131
let expected_messages1 = [
132132
PriceFeedMessage {
133-
id: price_account.key.to_bytes(),
133+
feed_id: price_account.key.to_bytes(),
134134
price: 42,
135135
conf: 2,
136136
exponent: 0,
@@ -141,7 +141,7 @@ fn test_upd_price_with_validator() {
141141
}
142142
.to_bytes(),
143143
TwapMessage {
144-
id: price_account.key.to_bytes(),
144+
feed_id: price_account.key.to_bytes(),
145145
cumulative_price: 42,
146146
cumulative_conf: 2,
147147
num_down_slots: 0,
@@ -161,7 +161,7 @@ fn test_upd_price_with_validator() {
161161

162162
let expected_messages2 = [
163163
PriceFeedMessage {
164-
id: price_account.key.to_bytes(),
164+
feed_id: price_account.key.to_bytes(),
165165
price: 42,
166166
conf: 2,
167167
exponent: 0,
@@ -172,7 +172,7 @@ fn test_upd_price_with_validator() {
172172
}
173173
.to_bytes(),
174174
TwapMessage {
175-
id: price_account.key.to_bytes(),
175+
feed_id: price_account.key.to_bytes(),
176176
cumulative_price: 84,
177177
cumulative_conf: 4,
178178
num_down_slots: 0,

0 commit comments

Comments
 (0)