Skip to content

Commit

Permalink
[fortuna] support multiple random value encodings (#1129)
Browse files Browse the repository at this point in the history
  • Loading branch information
jayantk authored Nov 1, 2023
1 parent f36e868 commit 46b597e
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 9 deletions.
126 changes: 126 additions & 0 deletions fortuna/Cargo.lock

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

1 change: 1 addition & 0 deletions fortuna/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ reqwest = { version = "0.11.22", features = ["json", "blocking"] }
serde = { version = "1.0.188", features = ["derive"] }
serde_qs = { version = "0.12.0", features = ["axum"] }
serde_json = "1.0.107"
serde_with = { version = "3.4.0", features = ["hex", "base64"] }
serde_yaml = "0.9.25"
sha3 = "0.10.8"
tokio = { version = "1.33.0", features = ["full"] }
Expand Down
70 changes: 63 additions & 7 deletions fortuna/src/api/revelation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@ use {
axum::{
extract::{
Path,
Query,
State,
},
Json,
},
pythnet_sdk::wire::array,
serde_with::serde_as,
utoipa::{
IntoParams,
ToSchema,
},
};

// TODO: this should probably take path parameters /v1/revelation/<chain_id>/<sequence_number>
/// Reveal the random value for a given sequence number and blockchain.
///
/// Given a sequence number, retrieve the corresponding random value that this provider has committed to.
Expand All @@ -34,11 +35,12 @@ responses(
(status = 200, description = "Random value successfully retrieved", body = GetRandomValueResponse),
(status = 403, description = "Random value cannot currently be retrieved", body = String)
),
params(GetRandomValueQueryParams)
params(RevelationPathParams, RevelationQueryParams)
)]
pub async fn revelation(
State(state): State<crate::api::ApiState>,
Path(GetRandomValueQueryParams { chain_id, sequence }): Path<GetRandomValueQueryParams>,
Path(RevelationPathParams { chain_id, sequence }): Path<RevelationPathParams>,
Query(RevelationQueryParams { encoding }): Query<RevelationQueryParams>,
) -> Result<Json<GetRandomValueResponse>, RestError> {
state
.metrics
Expand Down Expand Up @@ -70,8 +72,10 @@ pub async fn revelation(
.state
.reveal(sequence)
.map_err(|_| RestError::Unknown)?;
let encoded_value = Blob::new(encoding.unwrap_or(BinaryEncoding::Hex), value.clone());

Ok(Json(GetRandomValueResponse {
value: (*value).clone(),
value: encoded_value,
}))
} else {
Err(RestError::NoPendingRequest)
Expand All @@ -80,15 +84,67 @@ pub async fn revelation(

#[derive(Debug, serde::Serialize, serde::Deserialize, IntoParams)]
#[into_params(parameter_in=Path)]
pub struct GetRandomValueQueryParams {
pub struct RevelationPathParams {
#[param(value_type = String)]
pub chain_id: ChainId,
pub sequence: u64,
}

#[derive(Debug, serde::Serialize, serde::Deserialize, IntoParams)]
#[into_params(parameter_in=Query)]
pub struct RevelationQueryParams {
pub encoding: Option<BinaryEncoding>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize, ToSchema)]
#[serde(rename_all = "kebab-case")]
pub enum BinaryEncoding {
#[serde(rename = "hex")]
Hex,
#[serde(rename = "base64")]
Base64,
#[serde(rename = "array")]
Array,
}

#[derive(Debug, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct GetRandomValueResponse {
// TODO: choose serialization format
#[serde(with = "array")]
pub value: [u8; 32],
pub value: Blob,
}

#[serde_as]
#[derive(Debug, serde::Serialize, serde::Deserialize, ToSchema)]
#[serde(tag = "encoding", rename_all = "kebab-case")]
pub enum Blob {
Hex {
#[serde_as(as = "serde_with::hex::Hex")]
data: [u8; 32],
},
Base64 {
#[serde_as(as = "serde_with::base64::Base64")]
data: [u8; 32],
},
Array {
#[serde(with = "array")]
data: [u8; 32],
},
}

impl Blob {
pub fn new(encoding: BinaryEncoding, data: [u8; 32]) -> Blob {
match encoding {
BinaryEncoding::Hex => Blob::Hex { data },
BinaryEncoding::Base64 => Blob::Base64 { data },
BinaryEncoding::Array => Blob::Array { data },
}
}

pub fn data(&self) -> &[u8; 32] {
match self {
Blob::Hex { data } => data,
Blob::Base64 { data } => data,
Blob::Array { data } => data,
}
}
}
4 changes: 2 additions & 2 deletions fortuna/src/command/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ pub async fn generate(opts: &GenerateOptions) -> Result<()> {
.await?;

tracing::info!(
response = base64_standard_engine.encode(resp.value),
response = base64_standard_engine.encode(resp.value.data()),
"Retrieved the provider's random value.",
);
let provider_randomness = resp.value;
let provider_randomness = resp.value.data();

// Submit the provider's and our values to the contract to reveal the random number.
let random_value = contract
Expand Down
2 changes: 2 additions & 0 deletions fortuna/src/command/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub async fn run(opts: &RunOptions) -> Result<()> {
components(
schemas(
crate::api::GetRandomValueResponse,
crate::api::Blob,
crate::api::BinaryEncoding,
)
),
tags(
Expand Down

0 comments on commit 46b597e

Please sign in to comment.