From ff0033e54039b04a7fc0787977ebc86a27c55538 Mon Sep 17 00:00:00 2001 From: De Facto Date: Thu, 18 Feb 2021 11:12:50 +0800 Subject: [PATCH] store median in Answer struct --- program/src/error.rs | 3 +++ program/src/lib.rs | 38 +++----------------------------------- program/src/processor.rs | 3 +++ program/src/state.rs | 35 +++++++++++++++++++++++++++++++++++ src/schema.ts | 4 +++- 5 files changed, 47 insertions(+), 36 deletions(-) diff --git a/program/src/error.rs b/program/src/error.rs index d9e7d26..ba578fa 100644 --- a/program/src/error.rs +++ b/program/src/error.rs @@ -37,6 +37,9 @@ pub enum Error { #[error("No resolve answer")] NoResolvedAnswer, + #[error("No submitted value")] + NoSubmission, + #[error("Unknown error")] UnknownError, } diff --git a/program/src/lib.rs b/program/src/lib.rs index 2bb2481..43b9033 100644 --- a/program/src/lib.rs +++ b/program/src/lib.rs @@ -14,54 +14,22 @@ use borsh_state::InitBorshState; use solana_program::{ account_info::AccountInfo, program_error::ProgramError, program_pack::IsInitialized, }; -use state::Aggregator; +use state::{Aggregator, Answer}; #[cfg(not(feature = "no-entrypoint"))] pub mod entrypoint; -pub struct ResolvedMedian { - pub value: u64, - pub updated_at: u64, - pub created_at: u64, -} - /// Read resolved median value from the aggregator answer submissions pub fn read_median( aggregator_info: &AccountInfo, - answer_submissions_info: &AccountInfo, -) -> Result { +) -> Result { let aggregator = Aggregator::load_initialized(&aggregator_info)?; if !aggregator.answer.is_initialized() { return Err(Error::NoResolvedAnswer)?; } - let submissions = aggregator.answer_submissions(answer_submissions_info)?; - - let mut values: Vec<_> = submissions - .data - .iter() - .filter(|s| s.is_initialized()) - .map(|s| s.value) - .collect(); - - // get median value - values.sort(); - - let median: u64; - let l = values.len(); - let i = l / 2; - if l % 2 == 0 { - median = (values[i] + values[i - 1]) / 2; - } else { - median = values[i]; - } - - Ok(ResolvedMedian { - value: median, - updated_at: aggregator.answer.updated_at, - created_at: aggregator.answer.created_at, - }) + Ok(aggregator.answer) } // Export current sdk types for downstream users building with a different diff --git a/program/src/processor.rs b/program/src/processor.rs index 46f0e05..9bb4198 100644 --- a/program/src/processor.rs +++ b/program/src/processor.rs @@ -258,11 +258,13 @@ impl<'a> SubmitContext<'a> { answer.created_at = now; answer.updated_at = now; answer_submissions.data = round_submissions.data; + } else { answer.updated_at = now; answer_submissions.data[i] = new_submission; } + answer.median = answer_submissions.median()?; answer_submissions.save(self.answer_submissions)?; Ok(()) @@ -833,6 +835,7 @@ mod tests { assert_eq!(answer.round_id, 1); assert_eq!(answer.updated_at, time); assert_eq!(answer.created_at, time); + assert_eq!(answer.median, 15); assert_eq!(tt.answer_submission(0)?.value, 10); assert_eq!(tt.answer_submission(1)?.value, 20); diff --git a/program/src/state.rs b/program/src/state.rs index c91b6f2..b5f1230 100644 --- a/program/src/state.rs +++ b/program/src/state.rs @@ -66,6 +66,40 @@ pub struct Submissions { // pub data: Vec, } +pub struct ResolvedMedian { + pub value: u64, + pub updated_at: u64, + pub created_at: u64, +} + +impl Submissions { + pub fn median(&self) -> Result { + let mut values: Vec<_> = self.data + .iter() + .filter(|s| s.is_initialized()) + .map(|s| s.value) + .collect(); + + if values.is_empty() { + return Err(Error::NoSubmission)?; + } + + // get median value + values.sort(); + + let median: u64; + let l = values.len(); + let i = l / 2; + if l % 2 == 0 { + median = (values[i] + values[i - 1]) / 2; + } else { + median = values[i]; + } + + Ok(median) + } +} + impl IsInitialized for Submissions { fn is_initialized(&self) -> bool { self.is_initialized @@ -84,6 +118,7 @@ pub struct Round { #[derive(Clone, Debug, BorshSerialize, BorshDeserialize, BorshSchema, Default, PartialEq)] pub struct Answer { pub round_id: u64, + pub median: u64, pub created_at: u64, pub updated_at: u64, } diff --git a/src/schema.ts b/src/schema.ts index 45b3209..e385845 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -161,6 +161,7 @@ class Round extends Serialization { class Answer extends Serialization { public round_id!: BN + public median!: BN public created_at!: BN public updated_at!: BN @@ -168,6 +169,7 @@ class Answer extends Serialization { kind: "struct", fields: [ ["round_id", "u64"], + ["median", "u64"], ["created_at", "u64"], ["updated_at", "u64"], ], @@ -175,7 +177,7 @@ class Answer extends Serialization { } export class Aggregator extends Serialization { - public static size = 189 + public static size = 197 public config!: AggregatorConfig public roundSubmissions!: PublicKey