Skip to content

Commit a58e5cf

Browse files
authored
Removed Borsh (#224)
* Removed Borsh
1 parent 608d2ed commit a58e5cf

File tree

12 files changed

+98
-142
lines changed

12 files changed

+98
-142
lines changed

program/rust/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ bindgen = "0.60.1"
1010

1111
[dependencies]
1212
solana-program = "=1.10.29"
13-
borsh = "0.9"
1413
bytemuck = "1.11.0"
1514
thiserror = "1.0"
1615

program/rust/build.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,8 @@ use bindgen::Builder;
44
fn main() {
55
println!("cargo:rustc-link-search=./program/c/target");
66

7-
let borsh_derives = ["BorshSerialize".to_string(), "BorshDeserialize".to_string()];
8-
97
//make a parser and to it type, traits pairs
10-
let mut parser = build_utils::DeriveAdderParserCallback::new();
11-
parser.register_traits("cmd_hdr", borsh_derives.to_vec());
12-
parser.register_traits("pc_acc", borsh_derives.to_vec());
13-
parser.register_traits("pc_price_info", borsh_derives.to_vec());
14-
parser.register_traits("cmd_upd_price", borsh_derives.to_vec());
15-
parser.register_traits("pc_ema", borsh_derives.to_vec());
8+
let parser = build_utils::DeriveAdderParserCallback::new();
169

1710
//generate and write bindings
1811
let bindings = Builder::default()

program/rust/build_utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ impl<'a> DeriveAdderParserCallback<'a> {
1818
Default::default()
1919
}
2020
//add pairs of types and their desired traits
21+
#[allow(dead_code)]
2122
pub fn register_traits(&mut self, type_name: &'a str, traits: Vec<String>) {
2223
self.types_to_traits.insert(type_name, traits);
2324
}

program/rust/src/bindings.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,3 @@ typedef signed long int int64_t;
1212
typedef unsigned long int uint64_t;
1313

1414
#include "../../c/src/oracle/oracle.h"
15-
#include "price_t_offsets.h"

program/rust/src/c_oracle_header.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
//we do not use all the variables in oracle.h, so this helps with the warnings
44
#![allow(dead_code)]
55
//All the custom trait imports should go here
6-
use borsh::{
7-
BorshDeserialize,
8-
BorshSerialize,
9-
};
106
use bytemuck::{
117
Pod,
128
Zeroable,
@@ -57,6 +53,30 @@ unsafe impl Pod for cmd_hdr {
5753
}
5854

5955
#[cfg(target_endian = "little")]
56+
57+
unsafe impl Zeroable for pc_price_info {
58+
}
59+
60+
#[cfg(target_endian = "little")]
61+
unsafe impl Pod for pc_price_info {
62+
}
63+
64+
#[cfg(target_endian = "little")]
65+
unsafe impl Zeroable for cmd_upd_price {
66+
}
67+
68+
#[cfg(target_endian = "little")]
69+
unsafe impl Pod for cmd_upd_price {
70+
}
71+
72+
#[cfg(target_endian = "little")]
73+
unsafe impl Zeroable for pc_ema {
74+
}
75+
76+
#[cfg(target_endian = "little")]
77+
unsafe impl Pod for pc_ema {
78+
}
79+
6080
unsafe impl Zeroable for cmd_add_price_t {
6181
}
6282

program/rust/src/deserialize.rs

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,47 @@
1-
use crate::c_oracle_header::size_t;
2-
use crate::error::OracleError;
3-
use borsh::BorshDeserialize;
1+
use std::mem::size_of;
2+
3+
use bytemuck::{
4+
try_from_bytes,
5+
try_from_bytes_mut,
6+
Pod,
7+
};
8+
9+
use std::cell::{
10+
Ref,
11+
RefMut,
12+
};
13+
414
use solana_program::account_info::AccountInfo;
515
use solana_program::program_error::ProgramError;
6-
use std::mem::size_of;
7-
use std::result::Result;
8-
9-
/// Deserialize field in `source` with offset `offset`
10-
pub fn deserialize_single_field_from_buffer<T: BorshDeserialize>(
11-
source: &[u8],
12-
offset: Option<size_t>,
13-
) -> Result<T, ProgramError> {
14-
let start: usize = offset
15-
.unwrap_or(0)
16-
.try_into()
17-
.map_err(|_| OracleError::IntegerCastingError)?;
18-
19-
let res: T = T::try_from_slice(&source[start..(start + size_of::<T>())])?;
20-
Ok(res)
16+
17+
/// Interpret the bytes in `data` as a value of type `T`
18+
pub fn load<T: Pod>(data: &[u8]) -> Result<&T, ProgramError> {
19+
try_from_bytes(&data[0..size_of::<T>()]).map_err(|_| ProgramError::InvalidArgument)
2120
}
2221

23-
/// Deserialize field in `i` rank of `accounts` with offset `offset`
24-
pub fn deserialize_single_field_from_account<T: BorshDeserialize>(
25-
accounts: &[AccountInfo],
26-
i: usize,
27-
offset: Option<size_t>,
28-
) -> Result<T, ProgramError> {
29-
deserialize_single_field_from_buffer::<T>(
30-
&accounts
31-
.get(i)
32-
.ok_or(ProgramError::NotEnoughAccountKeys)?
33-
.try_borrow_data()?,
34-
offset,
35-
)
22+
/// Interpret the bytes in `data` as a mutable value of type `T`
23+
#[allow(unused)]
24+
pub fn load_mut<T: Pod>(data: &mut [u8]) -> Result<&mut T, ProgramError> {
25+
try_from_bytes_mut(&mut data[0..size_of::<T>()]).map_err(|_| ProgramError::InvalidArgument)
26+
}
27+
28+
/// Get the data stored in `account` as a value of type `T`
29+
pub fn load_account_as<'a, T: Pod>(account: &'a AccountInfo) -> Result<Ref<'a, T>, ProgramError> {
30+
let data = account.try_borrow_data()?;
31+
32+
Ok(Ref::map(data, |data| {
33+
bytemuck::from_bytes(&data[0..size_of::<T>()])
34+
}))
35+
}
36+
37+
/// Mutably borrow the data in `account` as a value of type `T`.
38+
/// Any mutations to the returned value will be reflected in the account data.
39+
pub fn load_account_as_mut<'a, T: Pod>(
40+
account: &'a AccountInfo,
41+
) -> Result<RefMut<'a, T>, ProgramError> {
42+
let data = account.try_borrow_mut_data()?;
43+
44+
Ok(RefMut::map(data, |data| {
45+
bytemuck::from_bytes_mut(&mut data[0..size_of::<T>()])
46+
}))
3647
}

program/rust/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::error::{
1919
OracleError,
2020
OracleResult,
2121
};
22+
2223
use crate::log::{
2324
post_log,
2425
pre_log,
@@ -92,6 +93,7 @@ pub extern "C" fn entrypoint(input: *mut u8) -> u64 {
9293
return error.into();
9394
}
9495

96+
9597
if c_ret_val == SUCCESSFULLY_UPDATED_AGGREGATE {
9698
//0 is the SUCCESS value for solana
9799
0

program/rust/src/log.rs

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
use crate::c_oracle_header::*;
22
use crate::deserialize::{
3-
deserialize_single_field_from_account,
4-
deserialize_single_field_from_buffer,
3+
load,
4+
load_account_as,
55
};
66
use crate::error::OracleError;
7-
use borsh::BorshDeserialize;
87
use solana_program::account_info::AccountInfo;
98
use solana_program::clock::Clock;
109
use solana_program::entrypoint::ProgramResult;
@@ -15,8 +14,7 @@ use solana_program::sysvar::Sysvar;
1514
pub fn pre_log(accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResult {
1615
msg!("Pyth oracle contract");
1716

18-
let instruction_header: cmd_hdr =
19-
deserialize_single_field_from_buffer::<cmd_hdr>(instruction_data, None)?;
17+
let instruction_header: &cmd_hdr = load::<cmd_hdr>(instruction_data)?;
2018
let instruction_id: u32 = instruction_header
2119
.cmd_
2220
.try_into()
@@ -25,13 +23,9 @@ pub fn pre_log(accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResu
2523

2624
match instruction_id {
2725
command_t_e_cmd_upd_price | command_t_e_cmd_agg_price => {
28-
let instruction: cmd_upd_price = cmd_upd_price::try_from_slice(instruction_data)?;
26+
let instruction: &cmd_upd_price = load::<cmd_upd_price>(instruction_data)?;
2927
// Account 1 is price_info in this instruction
30-
let expo: i32 = deserialize_single_field_from_account::<i32>(
31-
accounts,
32-
1,
33-
Some(PRICE_T_EXPO_OFFSET),
34-
)?;
28+
let price_account = load_account_as::<pc_price_t>(&accounts[1])?;
3529
msg!(
3630
"UpdatePrice: publisher={:}, price_account={:}, price={:}, conf={:}, expo={:}, status={:}, slot={:}, solana_time={:}",
3731
accounts.get(0)
@@ -40,20 +34,16 @@ pub fn pre_log(accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResu
4034
.ok_or(ProgramError::NotEnoughAccountKeys)?.key,
4135
instruction.price_,
4236
instruction.conf_,
43-
expo,
37+
price_account.expo_,
4438
instruction.status_,
4539
instruction.pub_slot_,
4640
Clock::get()?.unix_timestamp
4741
);
4842
}
4943
command_t_e_cmd_upd_price_no_fail_on_error => {
50-
let instruction: cmd_upd_price = cmd_upd_price::try_from_slice(instruction_data)?;
44+
let instruction: &cmd_upd_price = load::<cmd_upd_price>(instruction_data)?;
5145
// Account 1 is price_info in this instruction
52-
let expo: i32 = deserialize_single_field_from_account::<i32>(
53-
accounts,
54-
1,
55-
Some(PRICE_T_EXPO_OFFSET),
56-
)?;
46+
let price_account = load_account_as::<pc_price_t>(&accounts[1])?;
5747
msg!(
5848
"UpdatePriceNoFailOnError: publisher={:}, price_account={:}, price={:}, conf={:}, expo={:}, status={:}, slot={:}, solana_time={:}",
5949
accounts.get(0)
@@ -62,7 +52,7 @@ pub fn pre_log(accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResu
6252
.ok_or(ProgramError::NotEnoughAccountKeys)?.key,
6353
instruction.price_,
6454
instruction.conf_,
65-
expo,
55+
price_account.expo_,
6656
instruction.status_,
6757
instruction.pub_slot_,
6858
Clock::get()?.unix_timestamp
@@ -104,31 +94,23 @@ pub fn pre_log(accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResu
10494
Ok(())
10595
}
10696

97+
10798
pub fn post_log(c_ret_val: u64, accounts: &[AccountInfo]) -> ProgramResult {
10899
if c_ret_val == SUCCESSFULLY_UPDATED_AGGREGATE {
109100
// We trust that the C oracle has properly checked account 1, we can only get here through
110101
// the update price instructions
111-
let aggregate_price_info: pc_price_info = deserialize_single_field_from_account::<
112-
pc_price_info,
113-
>(
114-
accounts, 1, Some(PRICE_T_AGGREGATE_OFFSET)
115-
)?;
116-
let ema_info: pc_ema =
117-
deserialize_single_field_from_account::<pc_ema>(accounts, 1, Some(PRICE_T_EMA_OFFSET))?;
118-
let expo: i32 =
119-
deserialize_single_field_from_account::<i32>(accounts, 1, Some(PRICE_T_EXPO_OFFSET))?;
120-
102+
let price_account = load_account_as::<pc_price_t>(&accounts[1])?;
121103
msg!(
122104
"UpdateAggregate : price_account={:}, price={:}, conf={:}, expo={:}, status={:}, slot={:}, solana_time={:}, ema={:}",
123105
accounts.get(1)
124106
.ok_or(ProgramError::NotEnoughAccountKeys)?.key,
125-
aggregate_price_info.price_,
126-
aggregate_price_info.conf_,
127-
expo,
128-
aggregate_price_info.status_,
129-
aggregate_price_info.pub_slot_,
107+
price_account.agg_.price_,
108+
price_account.agg_.conf_,
109+
price_account.expo_,
110+
price_account.agg_.status_,
111+
price_account.agg_.pub_slot_,
130112
Clock::get()?.unix_timestamp,
131-
ema_info.val_
113+
price_account.twap_.val_
132114
);
133115
}
134116
Ok(())

program/rust/src/price_t_offsets.h

Lines changed: 0 additions & 15 deletions
This file was deleted.

program/rust/src/processor.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::mem::size_of;
22

3-
use borsh::BorshDeserialize;
43
use solana_program::program_error::ProgramError;
54
use solana_program::pubkey::Pubkey;
65
use solana_program::sysvar::slot_history::AccountInfo;
@@ -29,6 +28,7 @@ use crate::rust_oracle::{
2928
update_version,
3029
};
3130

31+
use crate::deserialize::load;
3232
///dispatch to the right instruction in the oracle
3333
pub fn process_instruction(
3434
program_id: &Pubkey,
@@ -40,7 +40,7 @@ pub fn process_instruction(
4040
if instruction_data.len() < cmd_hdr_size {
4141
return Err(ProgramError::InvalidArgument);
4242
}
43-
let cmd_data = cmd_hdr::try_from_slice(&instruction_data[..cmd_hdr_size])?;
43+
let cmd_data = load::<cmd_hdr>(&instruction_data[..cmd_hdr_size])?;
4444

4545
if cmd_data.ver_ != PC_VERSION {
4646
//FIXME: I am not sure what's best to do here (this is copied from C)

0 commit comments

Comments
 (0)