From b7230006b37f998ac8d30a96f6eccdb2f597d333 Mon Sep 17 00:00:00 2001 From: czl1378 Date: Fri, 27 Nov 2020 06:19:50 +0800 Subject: [PATCH] Initial commit --- .gitignore | 2 + Cargo.toml | 24 +++++++ Xargo.toml | 2 + build/flux-aggregator.so | Bin 0 -> 169232 bytes src/entrypoint.rs | 27 ++++++++ src/error.rs | 30 +++++++++ src/instruction.rs | 105 +++++++++++++++++++++++++++++++ src/lib.rs | 15 +++++ src/processor.rs | 132 +++++++++++++++++++++++++++++++++++++++ src/state.rs | 123 ++++++++++++++++++++++++++++++++++++ 10 files changed, 460 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 Xargo.toml create mode 100755 build/flux-aggregator.so create mode 100644 src/entrypoint.rs create mode 100644 src/error.rs create mode 100644 src/instruction.rs create mode 100644 src/lib.rs create mode 100644 src/processor.rs create mode 100644 src/state.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..fd9c8e7 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "flux-aggregator" +version = "0.1.0" +authors = ["czl1378 "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +solana-program = "1.4.8" +byteorder = "1.3" +thiserror = "1.0" +num-derive = "0.3" +num-traits = "0.2" +arrayref = "0.3.6" + +[lib] +crate-type = ["cdylib", "lib"] + +[features] +program = [] + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] \ No newline at end of file diff --git a/Xargo.toml b/Xargo.toml new file mode 100644 index 0000000..1744f09 --- /dev/null +++ b/Xargo.toml @@ -0,0 +1,2 @@ +[target.bpfel-unknown-unknown.dependencies.std] +features = [] \ No newline at end of file diff --git a/build/flux-aggregator.so b/build/flux-aggregator.so new file mode 100755 index 0000000000000000000000000000000000000000..deb1b27389fe905a22a774fbad49a571aa53c1f3 GIT binary patch literal 169232 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 literal 0 HcmV?d00001 diff --git a/src/entrypoint.rs b/src/entrypoint.rs new file mode 100644 index 0000000..9be291d --- /dev/null +++ b/src/entrypoint.rs @@ -0,0 +1,27 @@ +//! Program entrypoint + +use crate::{error::Error, processor::Processor}; + +use solana_program::{ + account_info::{AccountInfo}, + entrypoint, + program_error::PrintProgramError, + entrypoint::ProgramResult, + pubkey::Pubkey, +}; + +entrypoint!(process_instruction); + +// Program entrypoint's implementation +fn process_instruction( + program_id: &Pubkey, + accounts: &[AccountInfo], + instruction_data: &[u8], +) -> ProgramResult { + if let Err(error) = Processor::process(program_id, accounts, instruction_data) { + // catch the error so we can print it + error.print::(); + return Err(error); + } + Ok(()) +} \ No newline at end of file diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..fd4efff --- /dev/null +++ b/src/error.rs @@ -0,0 +1,30 @@ +//! Error types + +use num_derive::FromPrimitive; +use solana_program::{decode_error::DecodeError, program_error::ProgramError}; +use thiserror::Error; + +/// Errors that may be returned by the program. +#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)] +pub enum Error { + /// Invalid instruction + #[error("Invalid instruction")] + InvalidInstruction, + /// Already in use + #[error("Already in use")] + AlreadyInUse, + /// Not rent exempt + #[error("Not rent exempt")] + NotRentExempt, +} + +impl From for ProgramError { + fn from(e: Error) -> Self { + ProgramError::Custom(e as u32) + } +} +impl DecodeError for Error { + fn type_of() -> &'static str { + "Error" + } +} \ No newline at end of file diff --git a/src/instruction.rs b/src/instruction.rs new file mode 100644 index 0000000..18a4b8d --- /dev/null +++ b/src/instruction.rs @@ -0,0 +1,105 @@ +//! Instruction types + +use crate::error::Error; + +use solana_program::{ + program_error::ProgramError, + pubkey::Pubkey, +}; + +use std::convert::TryInto; + +/// Maximum number of oracles +pub const MAX_ORACLES: usize = 21; + +/// Instructions supported by the program. +#[repr(C)] +#[derive(Clone, Debug, PartialEq)] +pub enum Instruction { + /// Initializes a new Aggregator + Initialize { + /// The authority/multisignature + authority: Pubkey, + /// A short description of what is being reported + description: [u8; 32], + /// min submission value + min_submission_value: u64, + /// max submission value + max_submission_value: u64, + }, + + /// Add an oracle + AddOracle { + + }, + + /// Remove an oracle + RemoveOracle { + + }, + + /// Called by oracles when they have witnessed a need to update + Submit { + /// submission is the updated data that the oracle is submitting + submission: u64, + }, + +} + +impl Instruction { + /// Unpacks a byte buffer into a [Instruction](enum.Instruction.html). + pub fn unpack(input: &[u8]) -> Result { + use Error::InvalidInstruction; + + let (&tag, rest) = input.split_first().ok_or(InvalidInstruction)?; + Ok(match tag { + 0 => { + let (authority, rest) = Self::unpack_pubkey(rest)?; + let description = rest + .get(..32) + .and_then(|slice| slice.try_into().ok()) + .ok_or(InvalidInstruction)?; + + let (min_submission_value, rest) = rest.split_at(8); + let min_submission_value = min_submission_value + .try_into() + .ok() + .map(u64::from_le_bytes) + .ok_or(InvalidInstruction)?; + + let (max_submission_value, _rest) = rest.split_at(8); + let max_submission_value = max_submission_value + .try_into() + .ok() + .map(u64::from_le_bytes) + .ok_or(InvalidInstruction)?; + + Self::Initialize { + authority, + description, + min_submission_value: min_submission_value, + max_submission_value: max_submission_value, + } + }, + 1 => { + let submission = rest + .get(..8) + .and_then(|slice| slice.try_into().ok()) + .map(u64::from_le_bytes) + .ok_or(InvalidInstruction)?; + Self::Submit { submission } + }, + _ => return Err(Error::InvalidInstruction.into()), + }) + } + + fn unpack_pubkey(input: &[u8]) -> Result<(Pubkey, &[u8]), ProgramError> { + if input.len() >= 32 { + let (key, rest) = input.split_at(32); + let pk = Pubkey::new(key); + Ok((pk, rest)) + } else { + Err(Error::InvalidInstruction.into()) + } + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..72a149f --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,15 @@ +#![deny(missing_docs)] +#![forbid(unsafe_code)] + +//! An Flux Aggregator program for the Solana blockchain + +pub mod instruction; +pub mod processor; +pub mod error; +pub mod state; + +#[cfg(not(feature = "no-entrypoint"))] +pub mod entrypoint; + +// Export current sdk types for downstream users building with a different sdk version +pub use solana_program; diff --git a/src/processor.rs b/src/processor.rs new file mode 100644 index 0000000..dd31c92 --- /dev/null +++ b/src/processor.rs @@ -0,0 +1,132 @@ +//! Program state processor + +use crate::{ + error::Error, + instruction::{Instruction, MAX_ORACLES}, + state::{Aggregator}, +}; +use num_traits::FromPrimitive; +use solana_program::{ + account_info::{next_account_info, AccountInfo}, + decode_error::DecodeError, + entrypoint::ProgramResult, + info, + program_pack::{Pack}, + program_error::{PrintProgramError}, + pubkey::Pubkey, + sysvar::{rent::Rent, Sysvar}, +}; + +/// Program state handler. +pub struct Processor {} + +impl Processor { + /// Processes an [Instruction](enum.Instruction.html). + pub fn process(_program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> ProgramResult { + let instruction = Instruction::unpack(input)?; + + match instruction { + Instruction::Initialize { + authority, + description, + min_submission_value, + max_submission_value, + } => { + info!("Instruction: Initialize"); + info!(&format!("description: {:?}", description)[..]); + + Self::process_initialize( + accounts, authority, description, min_submission_value, max_submission_value + ) + }, + Instruction::AddOracle { + } => { + info!("Instruction: AddOracle"); + Self::process_add_oracle() + }, + Instruction::RemoveOracle { + } => { + info!("Instruction: RemoveOracle"); + Self::process_remove_oracle() + }, + Instruction::Submit { + submission, + } => { + info!("Instruction: Submit"); + Self::process_submit(submission) + }, + } + } + + /// Processes an [Initialize](enum.Instruction.html) instruction. + pub fn process_initialize( + accounts: &[AccountInfo], + authority: Pubkey, + description: [u8; 32], + min_submission_value: u64, + max_submission_value: u64, + ) -> ProgramResult { + + let account_info_iter = &mut accounts.iter(); + let aggregator_info = next_account_info(account_info_iter)?; + let _aggregator_data_len = aggregator_info.data_len(); + + let rent = &Rent::from_account_info(next_account_info(account_info_iter)?)?; + + let mut aggregator = Aggregator::unpack_unchecked(&aggregator_info.data.borrow())?; + if aggregator.is_initialized { + return Err(Error::AlreadyInUse.into()); + } + + if !rent.is_exempt(aggregator_info.lamports(), _aggregator_data_len) { + return Err(Error::NotRentExempt.into()); + } + + aggregator.min_submission_value = min_submission_value; + aggregator.max_submission_value = max_submission_value; + aggregator.description = description; + aggregator.is_initialized = true; + aggregator.answer = 123; + aggregator.submissions = [0; MAX_ORACLES]; + aggregator.authority = authority; + + Aggregator::pack(aggregator, &mut aggregator_info.data.borrow_mut())?; + + Ok(()) + } + + /// Processes an [AddOracle](enum.Instruction.html) instruction. + pub fn process_add_oracle( + + ) -> ProgramResult { + Ok(()) + } + + /// Processes an [RemoveOracle](enum.Instruction.html) instruction. + pub fn process_remove_oracle( + + ) -> ProgramResult { + Ok(()) + } + + /// Processes an [Submit](enum.Instruction.html) instruction. + pub fn process_submit( + _submission: u64, + ) -> ProgramResult { + Ok(()) + } +} + + +impl PrintProgramError for Error { + fn print(&self) + where + E: 'static + std::error::Error + DecodeError + PrintProgramError + FromPrimitive, + { + match self { + Error::InvalidInstruction => info!("Error: Invalid instruction"), + Error::AlreadyInUse => info!("Error: Already in use"), + Error::NotRentExempt => info!("Error: No rent exempt"), + } + } +} \ No newline at end of file diff --git a/src/state.rs b/src/state.rs new file mode 100644 index 0000000..b4fb4ec --- /dev/null +++ b/src/state.rs @@ -0,0 +1,123 @@ +//! State transition types + +use crate::instruction::MAX_ORACLES; + +use arrayref::{array_mut_ref, array_ref, array_refs, mut_array_refs}; + +use solana_program::{ + program_error::ProgramError, + program_pack::{IsInitialized, Pack, Sealed}, + clock::UnixTimestamp, + pubkey::Pubkey, +}; + +/// Aggregator data. +#[repr(C)] +#[derive(Clone, Debug, Copy, Default, PartialEq)] +pub struct Aggregator { + /// min submission value + pub min_submission_value: u64, + /// max submission value + pub max_submission_value: u64, + /// description + pub description: [u8; 32], + /// is initialized + pub is_initialized: bool, + /// answer + pub answer: u64, + /// authority + pub authority: Pubkey, + /// submissions + pub submissions: [u64; MAX_ORACLES], +} + +impl IsInitialized for Aggregator { + fn is_initialized(&self) -> bool { + self.is_initialized + } +} + +impl Sealed for Aggregator {} +impl Pack for Aggregator { + const LEN: usize = 89 + MAX_ORACLES*8; + fn unpack_from_slice(src: &[u8]) -> Result { + let src = array_ref![src, 0, 89 + MAX_ORACLES*8]; + let ( + min_submission_value, max_submission_value, + description, is_initialized, answer, authority, sub_rem, + ) = array_refs![src, 8, 8, 32, 1, 8, 32; ..;]; + + let is_initialized = match is_initialized { + [0] => false, + [1] => true, + _ => return Err(ProgramError::InvalidAccountData), + }; + + Ok(Aggregator { + min_submission_value: u64::from_le_bytes(*min_submission_value), + max_submission_value: u64::from_le_bytes(*max_submission_value), + description: *description, + is_initialized, + answer: u64::from_le_bytes(*answer), + authority: Pubkey::new_from_array(*authority), + submissions: unpack_submissions(sub_rem), + }) + } + fn pack_into_slice(&self, dst: &mut [u8]) { + let dst = array_mut_ref![dst, 0, 89 + MAX_ORACLES*8]; + let ( + min_submission_value_dst, + max_submission_value_dst, + description_dst, + is_initialized_dst, + answer_dst, + authority_dst, + sub_rem, + ) = mut_array_refs![dst, 8, 8, 32, 1, 8, 32; ..;]; + + let &Aggregator { + min_submission_value, + max_submission_value, + description, + is_initialized, + answer, + ref authority, + ref submissions, + } = self; + + *min_submission_value_dst = min_submission_value.to_le_bytes(); + *max_submission_value_dst = max_submission_value.to_le_bytes(); + *description_dst = description; + is_initialized_dst[0] = is_initialized as u8; + *answer_dst = answer.to_le_bytes(); + authority_dst.copy_from_slice(authority.as_ref()); + pack_submissions(submissions, sub_rem); + } +} + +/// Oracle data. +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub struct Oracle { + /// next submit time + pub next_submit_time: UnixTimestamp, +} + +// Helpers +fn unpack_submissions(mut dst: &[u8]) -> [u64; MAX_ORACLES] { + let mut arr = [0u64; MAX_ORACLES]; + for i in 0 .. MAX_ORACLES { + let (s, rem) = array_refs![dst, 8; ..;]; + arr[i] = u64::from_le_bytes(*s); + dst = rem; + } + arr +} + +fn pack_submissions(src: &[u64; MAX_ORACLES], mut dst: &mut [u8]) { + for i in 0 .. MAX_ORACLES { + let (s, rem) = mut_array_refs![dst, 8; ..;]; + *s = src[i].to_le_bytes(); + dst = rem; + } +} \ No newline at end of file