solana-flux-aggregator/src/instruction.rs

114 lines
3.3 KiB
Rust
Raw Normal View History

2020-11-26 14:19:50 -08:00
//! Instruction types
use crate::error::Error;
use solana_program::{
program_error::ProgramError,
pubkey::Pubkey,
};
use std::convert::TryInto;
/// Maximum number of oracles
2020-11-27 01:38:49 -08:00
pub const MAX_ORACLES: usize = 18;
2020-11-26 14:19:50 -08:00
/// Instructions supported by the program.
#[repr(C)]
#[derive(Clone, Debug, PartialEq)]
pub enum Instruction {
/// Initializes a new Aggregator
Initialize {
2020-11-27 01:38:49 -08:00
/// The aggregator authority
2020-11-26 14:19:50 -08:00
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 {
2020-11-27 01:38:49 -08:00
/// The oracle authority
authority: Pubkey,
2020-11-26 14:19:50 -08:00
},
/// 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<Self, ProgramError> {
use Error::InvalidInstruction;
let (&tag, rest) = input.split_first().ok_or(InvalidInstruction)?;
Ok(match tag {
0 => {
let (authority, rest) = Self::unpack_pubkey(rest)?;
2020-11-26 16:46:24 -08:00
let (description, rest) = rest.split_at(32);
let description = description
.try_into()
.ok()
2020-11-26 14:19:50 -08:00
.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 => {
2020-11-27 01:38:49 -08:00
let (authority, _rest) = Self::unpack_pubkey(rest)?;
Self::AddOracle {
authority,
}
2020-11-26 14:19:50 -08:00
},
2020-11-27 01:38:49 -08:00
// 1 => {
// let submission = rest
// .get(..8)
// .and_then(|slice| slice.try_into().ok())
// .map(u64::from_le_bytes)
// .ok_or(InvalidInstruction)?;
// Self::Submit { submission }
// },
2020-11-26 14:19:50 -08:00
_ => 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())
}
}
}