Skip to content

Commit 7088523

Browse files
committed
feat(starkex_handler): Fixed starkex implementation & added tests
1 parent 49a5366 commit 7088523

File tree

2 files changed

+44
-24
lines changed

2 files changed

+44
-24
lines changed

pragma-node/src/handlers/entries/subscribe_to_entry.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ use crate::AppState;
2121

2222
use super::{AssetOraclePrice, SignedPublisherPrice};
2323

24-
const PRAGMA_ORACLE_NAME: &str = "PRAGMA";
24+
/// "PRAGMA" to number is bigger than 2**40 - we alias it to "PRGM" to fit in 40 bits.
25+
/// Needed for StarkEx signature.
26+
const PRAGMA_ORACLE_NAME: &str = "PRGM";
2527
const CHANNEL_UPDATE_INTERVAL_IN_MS: u64 = 500;
2628

2729
#[derive(Default, Debug, Serialize, Deserialize)]

pragma-node/src/utils/starkex.rs

+41-23
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ pub fn get_external_asset_id(oracle_name: &str, pair_id: &str) -> Result<String,
1717
let pair_id = cairo_short_string_to_felt(pair_id).map_err(|_| HashError::ConversionError)?;
1818
let pair_id: u128 = pair_id.try_into().map_err(|_| HashError::ConversionError)?;
1919
let pair_as_hex = format!("{:0<width$x}", pair_id, width = 32);
20-
Ok(format!("{}{}", pair_as_hex, oracle_as_hex))
20+
Ok(format!("0x{}{}", pair_as_hex, oracle_as_hex))
2121
}
2222

2323
/// Builds the second number for the hash computation based on timestamp and price.
2424
fn build_second_number(timestamp: u128, price: &BigDecimal) -> Result<FieldElement, HashError> {
2525
let price = price.to_u128().ok_or(HashError::ConversionError)?;
2626
let price_as_hex = format!("{:x}", price);
2727
let timestamp_as_hex = format!("{:x}", timestamp);
28-
let v = format!("{}{}", price_as_hex, timestamp_as_hex);
28+
let v = format!("0x{}{}", price_as_hex, timestamp_as_hex);
2929
FieldElement::from_hex_be(&v).map_err(|_| HashError::ConversionError)
3030
}
3131

@@ -51,7 +51,8 @@ pub fn get_entry_hash(
5151
timestamp: u64,
5252
price: &BigDecimal,
5353
) -> Result<FieldElement, HashError> {
54-
let external_asset_id = get_external_asset_id(oracle_name, pair_id)?;
54+
let pair_id = pair_id.replace('/', ""); // Remove the "/" from the pair_id if it exists
55+
let external_asset_id = get_external_asset_id(oracle_name, &pair_id)?;
5556
let first_number =
5657
FieldElement::from_hex_be(&external_asset_id).map_err(|_| HashError::ConversionError)?;
5758
let second_number = build_second_number(timestamp as u128, price)?;
@@ -65,27 +66,44 @@ mod tests {
6566
use super::*;
6667
use bigdecimal::BigDecimal;
6768

68-
// Example from:
69-
// https://docs.starkware.co/starkex/perpetual/becoming-an-oracle-provider-for-starkex.html#signing_prices
70-
#[test]
71-
fn test_get_entry_hash_with_example() {
72-
// 1. Setup
73-
let oracle_name = "Maker";
74-
let asset = "BTCUSD";
75-
let price = BigDecimal::from_str("11512340000000000000000").unwrap();
76-
let timestamp = 1577836800_u64;
69+
// Test case structure - ((oracle_name, pair_id, price, timestamp), expected_hash)
70+
type TestCase<'a> = ((&'a str, &'a str, &'a str, u64), &'a str);
7771

78-
// 2. Action
79-
let hashed_data =
80-
get_entry_hash(oracle_name, asset, timestamp, &price).expect("Could not build hash");
72+
#[test]
73+
fn test_get_entry_hash() {
74+
let tests_cases: Vec<TestCase> = vec![
75+
(
76+
("Maker", "BTCUSD", "11512340000000000000000", 1577836800),
77+
"3e4113feb6c403cb0c954e5c09d239bf88fedb075220270f44173ac3cd41858",
78+
),
79+
(
80+
("Maker", "BTC/USD", "11512340000000000000000", 1577836800),
81+
"3e4113feb6c403cb0c954e5c09d239bf88fedb075220270f44173ac3cd41858",
82+
),
83+
(
84+
("PRGM", "SOLUSD", "19511280076", 1577216800),
85+
"3d683d36601ab3fd05dfbfecea8971a798f3c2e418fa54594c363e6e6816979",
86+
),
87+
(
88+
("PRGM", "ETHUSD", "369511280076", 1577816800),
89+
"6641dffd4e3499051ca0cd57e5c12b203bcf184576ce72e18d832de941e9656",
90+
),
91+
(
92+
("TEST", "DOGEUSD", "51128006", 1517816800),
93+
"18320fa96c61b1d8f98e1c85ae0a5a1159a46580ad32415122661c470d8d99f",
94+
),
95+
(
96+
("TEST", "DOGE/USD", "51128006", 1517816800),
97+
"18320fa96c61b1d8f98e1c85ae0a5a1159a46580ad32415122661c470d8d99f",
98+
),
99+
];
81100

82-
// 3. Check
83-
let expected_data = FieldElement::from_hex_be(
84-
"3e4113feb6c403cb0c954e5c09d239bf88fedb075220270f44173ac3cd41858",
85-
)
86-
.unwrap();
87-
assert_eq!(hashed_data, expected_data);
101+
for ((oracle_name, pair_id, price, timestamp), expected_hash) in tests_cases {
102+
let price = BigDecimal::from_str(price).unwrap();
103+
let hashed_data = get_entry_hash(oracle_name, pair_id, timestamp, &price)
104+
.expect("Could not build hash");
105+
let expected_data = FieldElement::from_hex_be(expected_hash).unwrap();
106+
assert_eq!(hashed_data, expected_data);
107+
}
88108
}
89-
90-
// TODO(akhercha): do way more tests
91109
}

0 commit comments

Comments
 (0)