Simplify the process
This commit is contained in:
parent
e76a7e6cf6
commit
5525a5d506
|
@ -25,9 +25,6 @@ pub enum Error {
|
|||
/// Oracle added
|
||||
#[error("Owner mismatch")]
|
||||
OwnerMismatch,
|
||||
/// Seat already taken
|
||||
#[error("Seat already been taken")]
|
||||
SeatAlreadyBeenTaken,
|
||||
/// Not found oracle
|
||||
#[error("Not found oracle")]
|
||||
NotFoundOracle,
|
||||
|
@ -40,9 +37,6 @@ pub enum Error {
|
|||
/// Insufficient withdrawable
|
||||
#[error("Insufficient withdrawable")]
|
||||
InsufficientWithdrawable,
|
||||
/// Program key not match
|
||||
#[error("Program key not match")]
|
||||
ProgramKeyNotMatch
|
||||
}
|
||||
|
||||
impl From<Error> for ProgramError {
|
||||
|
|
|
@ -8,10 +8,7 @@ use solana_program::{
|
|||
};
|
||||
|
||||
use std::convert::TryInto;
|
||||
use std::mem::size_of;
|
||||
|
||||
/// Maximum number of aggregators in this program
|
||||
pub const MAX_AGGREGATORS: usize = 32;
|
||||
/// Maximum number of oracles
|
||||
pub const MAX_ORACLES: usize = 21;
|
||||
/// The interval(seconds) of an oracle's each submission
|
||||
|
@ -62,33 +59,9 @@ pub enum Instruction {
|
|||
///
|
||||
seed: Vec<u8>,
|
||||
},
|
||||
|
||||
/// Update program account data
|
||||
PutAggregator {
|
||||
/// aggregator key
|
||||
aggregator: Pubkey,
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
/// Packs a [Instruction](enum.Instruction.html) into a byte buffer.
|
||||
pub fn pack(&self) -> Vec<u8> {
|
||||
let mut buf = Vec::with_capacity(size_of::<Self>());
|
||||
match self {
|
||||
&Self::PutAggregator {
|
||||
ref aggregator,
|
||||
} => {
|
||||
buf.push(5);
|
||||
buf.extend_from_slice(aggregator.as_ref());
|
||||
},
|
||||
_ => {
|
||||
|
||||
}
|
||||
};
|
||||
buf
|
||||
}
|
||||
|
||||
/// Unpacks a byte buffer into a [Instruction](enum.Instruction.html).
|
||||
pub fn unpack(input: &[u8]) -> Result<Self, ProgramError> {
|
||||
use Error::InvalidInstruction;
|
||||
|
@ -164,12 +137,6 @@ impl Instruction {
|
|||
amount, seed: rest.to_vec(),
|
||||
}
|
||||
},
|
||||
5 => {
|
||||
let (aggregator, _rest) = Self::unpack_pubkey(rest)?;
|
||||
Self::PutAggregator {
|
||||
aggregator,
|
||||
}
|
||||
},
|
||||
_ => return Err(Error::InvalidInstruction.into()),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -3,19 +3,18 @@
|
|||
use crate::{
|
||||
error::Error,
|
||||
instruction::{Instruction, SUBMIT_INTERVAL, PAYMENT_AMOUNT},
|
||||
state::{Aggregator, Oracle, Program},
|
||||
state::{Aggregator, Oracle},
|
||||
};
|
||||
|
||||
use num_traits::FromPrimitive;
|
||||
use solana_program::{
|
||||
instruction::{AccountMeta, Instruction as SolInstruction},
|
||||
account_info::{next_account_info, AccountInfo},
|
||||
clock::{Clock},
|
||||
decode_error::DecodeError,
|
||||
entrypoint::ProgramResult,
|
||||
info,
|
||||
program_pack::{Pack},
|
||||
program::{invoke, invoke_signed},
|
||||
program::{invoke_signed},
|
||||
program_error::{PrintProgramError, ProgramError},
|
||||
pubkey::Pubkey,
|
||||
sysvar::{rent::Rent, Sysvar},
|
||||
|
@ -74,14 +73,6 @@ impl Processor {
|
|||
accounts, amount, seed.as_slice(),
|
||||
)
|
||||
},
|
||||
Instruction::PutAggregator {
|
||||
aggregator,
|
||||
} => {
|
||||
info!("Instruction: Put aggregator");
|
||||
Self::put_aggregator(
|
||||
accounts, &aggregator,
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,10 +80,8 @@ impl Processor {
|
|||
///
|
||||
/// Accounts expected by this instruction:
|
||||
///
|
||||
/// 0. `[writable]` The aggregator
|
||||
/// 1. `[]` The program id, to `invoke` need this
|
||||
/// 2. `[]` Sysvar rent
|
||||
/// 3. `[writable, signer]` The program owner
|
||||
/// 1. `[]` Sysvar rent
|
||||
/// 2. `[writable, signer]` The aggregator autority
|
||||
pub fn process_initialize(
|
||||
program_id: &Pubkey,
|
||||
accounts: &[AccountInfo],
|
||||
|
@ -103,17 +92,11 @@ impl Processor {
|
|||
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
|
||||
let aggregator_info = next_account_info(account_info_iter)?;
|
||||
let program_info = next_account_info(account_info_iter)?;
|
||||
let rent_info = next_account_info(account_info_iter)?;
|
||||
let program_owner_info = next_account_info(account_info_iter)?;
|
||||
|
||||
if program_info.key != program_id {
|
||||
return Err(Error::ProgramKeyNotMatch.into());
|
||||
}
|
||||
|
||||
let aggregator_info = next_account_info(account_info_iter)?;
|
||||
|
||||
// check signer
|
||||
if !program_owner_info.is_signer {
|
||||
if !aggregator_info.is_signer {
|
||||
return Err(ProgramError::MissingRequiredSignature);
|
||||
}
|
||||
|
||||
|
@ -133,23 +116,7 @@ impl Processor {
|
|||
aggregator.description = description;
|
||||
aggregator.is_initialized = true;
|
||||
|
||||
aggregator.authority = *aggregator_info.key;
|
||||
|
||||
Aggregator::pack(aggregator, &mut aggregator_info.data.borrow_mut())?;
|
||||
|
||||
// call put aggregator instruction, to minimize stack size
|
||||
invoke(&SolInstruction {
|
||||
program_id: *program_info.key,
|
||||
accounts: vec![
|
||||
AccountMeta::new(*program_owner_info.key, false),
|
||||
],
|
||||
data: Instruction::PutAggregator {
|
||||
aggregator: *aggregator_info.key,
|
||||
}.pack(),
|
||||
}, &[
|
||||
program_info.clone(),
|
||||
program_owner_info.clone(),
|
||||
])?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -183,25 +150,29 @@ impl Processor {
|
|||
return Err(Error::NotFoundAggregator.into());
|
||||
}
|
||||
|
||||
|
||||
let mut oracle = Oracle::unpack_unchecked(&oracle_info.data.borrow())?;
|
||||
if oracle.is_initialized {
|
||||
return Err(Error::AlreadyInUse.into());
|
||||
}
|
||||
|
||||
let mut oracles = aggregator.oracles;
|
||||
|
||||
// append
|
||||
for o in oracles.iter_mut() {
|
||||
if o == &Pubkey::default() {
|
||||
*o = *oracle_info.key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
aggregator.oracles = oracles;
|
||||
Aggregator::pack(aggregator, &mut aggregator_info.data.borrow_mut())?;
|
||||
|
||||
let mut oracle = Oracle::unpack_unchecked(&oracle_info.data.borrow())?;
|
||||
|
||||
let clock = &Clock::from_account_info(clock_sysvar_info)?;
|
||||
|
||||
oracle.submission = 0;
|
||||
oracle.next_submit_time = clock.unix_timestamp;
|
||||
oracle.authority = *oracle_info.key;
|
||||
oracle.description = description;
|
||||
oracle.is_initialized = true;
|
||||
oracle.withdrawable = 0;
|
||||
|
@ -237,12 +208,19 @@ impl Processor {
|
|||
|
||||
let mut oracles = aggregator.oracles;
|
||||
|
||||
let mut found = false;
|
||||
for o in oracles.iter_mut() {
|
||||
if o == &oracle {
|
||||
*o = Pubkey::default();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
return Err(Error::NotFoundOracle.into());
|
||||
}
|
||||
|
||||
aggregator.oracles = oracles;
|
||||
Aggregator::pack(aggregator, &mut aggregator_info.data.borrow_mut())?;
|
||||
|
||||
|
@ -374,38 +352,6 @@ impl Processor {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Put aggregator key to program account data
|
||||
fn put_aggregator(
|
||||
accounts: &[AccountInfo],
|
||||
aggregator: &Pubkey
|
||||
) -> ProgramResult {
|
||||
let account_info_iter = &mut accounts.iter();
|
||||
let program_info = next_account_info(account_info_iter)?;
|
||||
info!(&format!("{:?}", program_info));
|
||||
let mut program = Program::unpack_unchecked(&program_info.data.borrow())?;
|
||||
|
||||
for p in program.aggregators.iter_mut() {
|
||||
if p == &Pubkey::default() {
|
||||
*p = *aggregator;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Program::pack(program, &mut program_info.data.borrow_mut())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Helpers
|
||||
|
||||
/// Generates seed bump for stake pool authorities
|
||||
pub fn find_authority_bump_seed(
|
||||
program_id: &Pubkey,
|
||||
my_info: &Pubkey,
|
||||
authority_type: &[u8],
|
||||
) -> (Pubkey, u8) {
|
||||
Pubkey::find_program_address(&[&my_info.to_bytes()[..32], authority_type], program_id)
|
||||
}
|
||||
|
||||
impl PrintProgramError for Error {
|
||||
|
@ -420,12 +366,10 @@ impl PrintProgramError for Error {
|
|||
Error::NotFoundAggregator => info!("Error: no found aggregator"),
|
||||
Error::OracleAdded => info!("Error: Oracle added"),
|
||||
Error::OwnerMismatch => info!("Error: Owner mismatch"),
|
||||
Error::SeatAlreadyBeenTaken => info!("Error: Seat already been taken"),
|
||||
Error::NotFoundOracle => info!("Error: Not found oracle"),
|
||||
Error::SubmissonValueOutOfRange => info!("Error: Submisson value out of range"),
|
||||
Error::SubmissonCooling => info!("Submission cooling"),
|
||||
Error::InsufficientWithdrawable => info!("Insufficient withdrawable"),
|
||||
Error::ProgramKeyNotMatch => info!("Program key not match"),
|
||||
}
|
||||
}
|
||||
}
|
103
src/state.rs
103
src/state.rs
|
@ -1,6 +1,6 @@
|
|||
//! State transition types
|
||||
|
||||
use crate::instruction::{MAX_ORACLES, MAX_AGGREGATORS};
|
||||
use crate::instruction::{MAX_ORACLES};
|
||||
use arrayref::{array_mut_ref, array_ref, array_refs, mut_array_refs};
|
||||
|
||||
use solana_program::{
|
||||
|
@ -11,37 +11,6 @@ use solana_program::{
|
|||
clock::{UnixTimestamp},
|
||||
};
|
||||
|
||||
/// Program data
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, Copy, PartialEq)]
|
||||
pub struct Program {
|
||||
/// All aggregators
|
||||
pub aggregators: [Pubkey; MAX_AGGREGATORS],
|
||||
}
|
||||
|
||||
impl Sealed for Program {}
|
||||
impl Pack for Program {
|
||||
const LEN: usize = MAX_AGGREGATORS*32;
|
||||
fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError> {
|
||||
let src = array_ref![src, 0, MAX_AGGREGATORS*32];
|
||||
info!("unpack aggregators");
|
||||
Ok(Program {
|
||||
aggregators: unpack_aggregators(src),
|
||||
})
|
||||
}
|
||||
|
||||
fn pack_into_slice(&self, dst: &mut [u8]) {
|
||||
let dst = array_mut_ref![dst, 0, MAX_AGGREGATORS*32];
|
||||
let (_, rem) = mut_array_refs![dst, 0;..;];
|
||||
|
||||
let &Program {
|
||||
ref aggregators,
|
||||
} = self;
|
||||
|
||||
pack_aggregators(aggregators, rem);
|
||||
}
|
||||
}
|
||||
|
||||
/// Aggregator data.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, Copy, Default, PartialEq)]
|
||||
|
@ -54,8 +23,6 @@ pub struct Aggregator {
|
|||
pub description: [u8; 32],
|
||||
/// is initialized
|
||||
pub is_initialized: bool,
|
||||
/// authority
|
||||
pub authority: Pubkey,
|
||||
/// oracles
|
||||
pub oracles: [Pubkey; MAX_ORACLES],
|
||||
}
|
||||
|
@ -68,13 +35,16 @@ impl IsInitialized for Aggregator {
|
|||
|
||||
impl Sealed for Aggregator {}
|
||||
impl Pack for Aggregator {
|
||||
const LEN: usize = 81 + MAX_ORACLES*32;
|
||||
const LEN: usize = 49 + MAX_ORACLES*32;
|
||||
fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError> {
|
||||
let src = array_ref![src, 0, 81 + MAX_ORACLES*32];
|
||||
let src = array_ref![src, 0, 49 + MAX_ORACLES*32];
|
||||
let (
|
||||
min_submission_value, max_submission_value, description,
|
||||
is_initialized, authority, rem,
|
||||
) = array_refs![src, 8, 8, 32, 1, 32; ..;];
|
||||
min_submission_value,
|
||||
max_submission_value,
|
||||
description,
|
||||
is_initialized,
|
||||
rem,
|
||||
) = array_refs![src, 8, 8, 32, 1; ..;];
|
||||
|
||||
let is_initialized = match is_initialized {
|
||||
[0] => false,
|
||||
|
@ -87,29 +57,26 @@ impl Pack for Aggregator {
|
|||
max_submission_value: u64::from_le_bytes(*max_submission_value),
|
||||
description: *description,
|
||||
is_initialized,
|
||||
authority: Pubkey::new_from_array(*authority),
|
||||
oracles: unpack_oracles(rem),
|
||||
})
|
||||
}
|
||||
|
||||
fn pack_into_slice(&self, dst: &mut [u8]) {
|
||||
|
||||
let dst = array_mut_ref![dst, 0, 81 + MAX_ORACLES*32];
|
||||
let dst = array_mut_ref![dst, 0, 49 + MAX_ORACLES*32];
|
||||
let (
|
||||
min_submission_value_dst,
|
||||
max_submission_value_dst,
|
||||
description_dst,
|
||||
is_initialized_dst,
|
||||
authority_dst,
|
||||
rem,
|
||||
) = mut_array_refs![dst, 8, 8, 32, 1, 32; ..;];
|
||||
) = mut_array_refs![dst, 8, 8, 32, 1; ..;];
|
||||
|
||||
let &Aggregator {
|
||||
min_submission_value,
|
||||
max_submission_value,
|
||||
description,
|
||||
is_initialized,
|
||||
ref authority,
|
||||
ref oracles,
|
||||
} = self;
|
||||
|
||||
|
@ -117,8 +84,7 @@ impl Pack for Aggregator {
|
|||
*max_submission_value_dst = max_submission_value.to_le_bytes();
|
||||
*description_dst = description;
|
||||
is_initialized_dst[0] = is_initialized as u8;
|
||||
authority_dst.copy_from_slice(authority.as_ref());
|
||||
|
||||
|
||||
pack_oracles(oracles, rem);
|
||||
}
|
||||
}
|
||||
|
@ -131,8 +97,6 @@ pub struct Oracle {
|
|||
pub submission: u64,
|
||||
/// submit times
|
||||
pub next_submit_time: UnixTimestamp,
|
||||
/// oracle authority
|
||||
pub authority: Pubkey,
|
||||
/// is usually the oracle name
|
||||
pub description: [u8; 32],
|
||||
/// is initialized
|
||||
|
@ -149,13 +113,13 @@ impl IsInitialized for Oracle {
|
|||
|
||||
impl Sealed for Oracle {}
|
||||
impl Pack for Oracle {
|
||||
const LEN: usize = 89;
|
||||
const LEN: usize = 57;
|
||||
fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError> {
|
||||
|
||||
let src = array_ref![src, 0, 89];
|
||||
let src = array_ref![src, 0, 57];
|
||||
let (
|
||||
submission, next_submit_time, authority, description, is_initialized, withdrawable,
|
||||
) = array_refs![src, 8, 8, 32, 32, 1, 8];
|
||||
submission, next_submit_time, description, is_initialized, withdrawable,
|
||||
) = array_refs![src, 8, 8, 32, 1, 8];
|
||||
|
||||
let is_initialized = match is_initialized {
|
||||
[0] => false,
|
||||
|
@ -166,7 +130,6 @@ impl Pack for Oracle {
|
|||
Ok(Oracle {
|
||||
submission: u64::from_le_bytes(*submission),
|
||||
next_submit_time: i64::from_le_bytes(*next_submit_time),
|
||||
authority: Pubkey::new_from_array(*authority),
|
||||
description: *description,
|
||||
is_initialized,
|
||||
withdrawable: u64::from_le_bytes(*withdrawable),
|
||||
|
@ -175,16 +138,18 @@ impl Pack for Oracle {
|
|||
|
||||
fn pack_into_slice(&self, dst: &mut [u8]) {
|
||||
|
||||
let dst = array_mut_ref![dst, 0, 89];
|
||||
let dst = array_mut_ref![dst, 0, 57];
|
||||
let (
|
||||
submission_dst, next_submit_time_dst, authority_dst,
|
||||
description_dst, is_initialized_dst, withdrawable_dst,
|
||||
) = mut_array_refs![dst, 8, 8, 32, 32, 1, 8];
|
||||
submission_dst,
|
||||
next_submit_time_dst,
|
||||
description_dst,
|
||||
is_initialized_dst,
|
||||
withdrawable_dst,
|
||||
) = mut_array_refs![dst, 8, 8, 32, 1, 8];
|
||||
|
||||
let &Oracle {
|
||||
submission,
|
||||
next_submit_time,
|
||||
ref authority,
|
||||
description,
|
||||
is_initialized,
|
||||
withdrawable,
|
||||
|
@ -193,7 +158,6 @@ impl Pack for Oracle {
|
|||
*submission_dst = submission.to_le_bytes();
|
||||
*next_submit_time_dst = next_submit_time.to_le_bytes();
|
||||
*description_dst = description;
|
||||
authority_dst.copy_from_slice(authority.as_ref());
|
||||
is_initialized_dst[0] = is_initialized as u8;
|
||||
*withdrawable_dst = withdrawable.to_le_bytes();
|
||||
}
|
||||
|
@ -217,27 +181,6 @@ fn pack_oracles(src: &[Pubkey; MAX_ORACLES], mut dst: &mut [u8]) {
|
|||
|
||||
s.copy_from_slice(src[i].as_ref());
|
||||
|
||||
dst = rem;
|
||||
}
|
||||
}
|
||||
|
||||
fn unpack_aggregators(mut dst: &[u8]) -> [Pubkey; MAX_AGGREGATORS] {
|
||||
let mut arr = [Pubkey::default(); MAX_AGGREGATORS];
|
||||
for i in 0 .. MAX_AGGREGATORS {
|
||||
let ( pubkey, rem ) = array_refs![dst, 32; ..;];
|
||||
arr[i] = Pubkey::new_from_array(*pubkey);
|
||||
info!(&format!("{:?}", i));
|
||||
dst = rem;
|
||||
}
|
||||
arr
|
||||
}
|
||||
|
||||
fn pack_aggregators(src: &[Pubkey; MAX_AGGREGATORS], mut dst: &mut [u8]) {
|
||||
for i in 0 .. MAX_AGGREGATORS {
|
||||
let (s, rem) = mut_array_refs![dst, 32; ..;];
|
||||
|
||||
s.copy_from_slice(src[i].as_ref());
|
||||
|
||||
dst = rem;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue