Simplify the process

This commit is contained in:
czl1378 2020-12-04 20:11:10 +08:00
parent e76a7e6cf6
commit 5525a5d506
4 changed files with 44 additions and 196 deletions

View File

@ -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 {

View File

@ -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()),
})
}

View File

@ -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"),
}
}
}

View File

@ -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;
}
}