Skip to content

Commit

Permalink
Merge branch 'main' into cyr/decimals
Browse files Browse the repository at this point in the history
  • Loading branch information
brittcyr authored Aug 26, 2024
2 parents 79f1624 + 4db335f commit eeb141d
Show file tree
Hide file tree
Showing 19 changed files with 82 additions and 180 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-code-review-rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }}
files: lcov.info
verbose: true
fail_ci_if_error: true
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-code-review-ts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }}
files: lcov.info
verbose: true
fail_ci_if_error: true
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

Expand Down
3 changes: 3 additions & 0 deletions client/idl/generateIdl.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ function modifyIdlCore(programName) {
return field;
});
}
if (idlAccount.name == "QuoteAtomsPerBaseAtom") {
idlAccount.type.fields[0].type = "u128";
}
}

for (const instruction of idl.instructions) {
Expand Down
8 changes: 5 additions & 3 deletions client/idl/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -1228,9 +1228,6 @@
{
"name": "PostOnly"
},
{
"name": "PostOnlySlide"
},
{
"name": "Global"
}
Expand Down Expand Up @@ -1323,6 +1320,11 @@
"code": 16,
"name": "GlobalInsufficient",
"msg": "Insufficient funds on global account to rest an order"
},
{
"code": 17,
"name": "IncorrectAccount",
"msg": "Account key did not match expected"
}
],
"metadata": {
Expand Down
11 changes: 6 additions & 5 deletions client/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ mod test {
quantities::{BaseAtoms, GlobalAtoms},
state::{
constants::NO_EXPIRATION_LAST_VALID_SLOT, AddOrderToMarketArgs, GlobalFixed,
GlobalValue, OrderType, BLOCK_SIZE, GLOBAL_FIXED_SIZE, MARKET_FIXED_SIZE,
GlobalValue, OrderType, GLOBAL_BLOCK_SIZE, GLOBAL_FIXED_SIZE, MARKET_BLOCK_SIZE,
MARKET_FIXED_SIZE,
},
validation::{
loaders::GlobalTradeAccounts, ManifestAccountInfo, MintAccountInfo, TokenAccountInfo,
Expand Down Expand Up @@ -273,7 +274,7 @@ mod test {
let mut market_value: DynamicAccount<MarketFixed, Vec<u8>> = MarketValue {
fixed: MarketFixed::new_empty(&base_mint, &quote_mint, &market_key),
// 4 because 1 extra, 1 seat, 2 orders.
dynamic: vec![0; BLOCK_SIZE * 4],
dynamic: vec![0; MARKET_BLOCK_SIZE * 4],
};
let trader_key: Pubkey =
Pubkey::from_str("GCtjtH2ehL6BZTjismuZ8JhQnuM6U3bmtxVoFyiHMHGc").unwrap();
Expand Down Expand Up @@ -434,7 +435,7 @@ mod test {
let mut market_value: DynamicAccount<MarketFixed, Vec<u8>> = MarketValue {
fixed: MarketFixed::new_empty(&base_mint, &quote_mint, &market_key),
// 4 because 1 extra, 1 seat, 2 orders.
dynamic: vec![0; BLOCK_SIZE * 4],
dynamic: vec![0; MARKET_BLOCK_SIZE * 4],
};
let trader_key: Pubkey =
Pubkey::from_str("GCtjtH2ehL6BZTjismuZ8JhQnuM6U3bmtxVoFyiHMHGc").unwrap();
Expand Down Expand Up @@ -611,7 +612,7 @@ mod test {
let mut market_value: DynamicAccount<MarketFixed, Vec<u8>> = MarketValue {
fixed: MarketFixed::new_empty(&base_mint, &quote_mint_info, &market_key),
// 4 because 1 extra, 1 seat, 2 orders.
dynamic: vec![0; BLOCK_SIZE * 4],
dynamic: vec![0; MARKET_BLOCK_SIZE * 4],
};
let trader_key: Pubkey =
Pubkey::from_str("GCtjtH2ehL6BZTjismuZ8JhQnuM6U3bmtxVoFyiHMHGc").unwrap();
Expand All @@ -625,7 +626,7 @@ mod test {
let global_account_info: AccountInfo = {
let mut global_value: DynamicAccount<GlobalFixed, Vec<u8>> = GlobalValue {
fixed: GlobalFixed::new_empty(&quote_mint_key),
dynamic: vec![0; BLOCK_SIZE * 2],
dynamic: vec![0; GLOBAL_BLOCK_SIZE * 2],
};
global_value.global_expand().unwrap();
global_value.add_trader(&trader_key).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion client/ts/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export const FIXED_MANIFEST_HEADER_SIZE: number = 512;
export const FIXED_MANIFEST_HEADER_SIZE: number = 256;
export const FIXED_WRAPPER_HEADER_SIZE: number = 64;
export const NIL = 4_294_967_295;
23 changes: 23 additions & 0 deletions client/ts/src/manifest/errors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,29 @@ createErrorFromNameLookup.set(
() => new GlobalInsufficientError(),
);

/**
* IncorrectAccount: 'Account key did not match expected'
*
* @category Errors
* @category generated
*/
export class IncorrectAccountError extends Error {
readonly code: number = 0x11;
readonly name: string = 'IncorrectAccount';
constructor() {
super('Account key did not match expected');
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, IncorrectAccountError);
}
}
}

createErrorFromCodeLookup.set(0x11, () => new IncorrectAccountError());
createErrorFromNameLookup.set(
'IncorrectAccount',
() => new IncorrectAccountError(),
);

/**
* Attempts to resolve a custom program error from the provided error code.
* @category Errors
Expand Down
1 change: 0 additions & 1 deletion client/ts/src/manifest/types/OrderType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export enum OrderType {
Limit,
ImmediateOrCancel,
PostOnly,
PostOnlySlide,
Global,
}

Expand Down
3 changes: 1 addition & 2 deletions client/ts/src/market.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,7 @@ export class Market {
offset += 4;

// _padding2: [u32; 3],
// _padding3: [u64; 32],
// _padding4: [u64; 8],
// _padding3: [u64; 8],

const bids: RestingOrder[] =
bidsRootIndex != NIL
Expand Down
4 changes: 2 additions & 2 deletions programs/manifest/src/program/processor/batch_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
quantities::{BaseAtoms, PriceConversionError, QuoteAtomsPerBaseAtom, WrapperU64},
state::{
AddOrderToMarketArgs, AddOrderToMarketResult, MarketRefMut, OrderType, RestingOrder,
BLOCK_SIZE,
MARKET_BLOCK_SIZE,
},
validation::loaders::BatchUpdateContext,
};
Expand Down Expand Up @@ -182,7 +182,7 @@ pub(crate) fn process_batch_update(
// aligns with block boundaries. We do a check that it is an
// order owned by the payer inside the handler.
assert_with_msg(
trader_index % (BLOCK_SIZE as DataIndex) == 0
trader_index % (MARKET_BLOCK_SIZE as DataIndex) == 0
&& trader_index == order.get_trader_index(),
ManifestError::WrongIndexHintParams,
&format!("Invalid cancel hint index {}", hinted_cancel_index),
Expand Down
10 changes: 7 additions & 3 deletions programs/manifest/src/program/processor/create_market.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,14 @@ pub(crate) fn process_create_market(
}
}

// Do not need to initialize with the system program because it is assumed
// that it is done already and loaded with rent.
// Do not need to initialize with the system program because it is
// assumed that it is done already and loaded with rent. That is not at
// a PDA because we do not want to be restricted to a single market for
// a pair. If there is lock contention and hotspotting for one market,
// it could be useful to have a second where it is easier to land
// transactions. That protection is worth the possibility that users
// would use an inactive market when multiple exist.

// TODO: Make the market be at a PDA to enforce only 1 market per Base/Quote pair.
// Setup the empty market
let empty_market_fixed: MarketFixed =
MarketFixed::new_empty(&base_mint, &quote_mint, market.key);
Expand Down
4 changes: 2 additions & 2 deletions programs/manifest/src/program/processor/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{
};

use crate::{
state::{constants::BLOCK_SIZE, DynamicAccount, GlobalFixed, MarketFixed},
state::{constants::MARKET_BLOCK_SIZE, DynamicAccount, GlobalFixed, MarketFixed},
validation::{ManifestAccount, ManifestAccountInfo, Program, Signer},
};
use bytemuck::Pod;
Expand Down Expand Up @@ -52,7 +52,7 @@ fn expand_dynamic<'a, 'info, T: ManifestAccount + Pod + Clone>(
// Account types were already validated, so do not need to reverify that the
// accounts are in order: payer, expandable_account, system_program, ...
let expandable_account: &AccountInfo = manifest_account.info;
let new_size: usize = expandable_account.data_len() + BLOCK_SIZE;
let new_size: usize = expandable_account.data_len() + MARKET_BLOCK_SIZE;

let rent: Rent = Rent::get()?;
let new_minimum_balance: u64 = rent.minimum_balance(new_size);
Expand Down
19 changes: 10 additions & 9 deletions programs/manifest/src/state/constants.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
use hypertree::RBTREE_OVERHEAD_BYTES;

pub const MARKET_FIXED_SIZE: usize = 512;
pub const MARKET_FIXED_SIZE: usize = 256;
pub const GLOBAL_FIXED_SIZE: usize = 88;

// Red black tree overhead is 16 bytes. If each block is 80 bytes, then we get
// 64 bytes for a RestingOrder or ClaimedSeat.
// TODO: Separate constants for global block size and market block size.
pub const BLOCK_SIZE: usize = 80;
const BLOCK_PAYLOAD_SIZE: usize = BLOCK_SIZE - RBTREE_OVERHEAD_BYTES;
pub const RESTING_ORDER_SIZE: usize = BLOCK_PAYLOAD_SIZE;
pub const CLAIMED_SEAT_SIZE: usize = BLOCK_PAYLOAD_SIZE;
pub const GLOBAL_TRADER_SIZE: usize = BLOCK_PAYLOAD_SIZE;
pub const GLOBAL_TRADER_MARKET_INFO_SIZE: usize = BLOCK_PAYLOAD_SIZE;
pub const GLOBAL_BLOCK_SIZE: usize = 80;
pub const MARKET_BLOCK_SIZE: usize = 80;
const MARKET_BLOCK_PAYLOAD_SIZE: usize = MARKET_BLOCK_SIZE - RBTREE_OVERHEAD_BYTES;
pub const RESTING_ORDER_SIZE: usize = MARKET_BLOCK_PAYLOAD_SIZE;
pub const CLAIMED_SEAT_SIZE: usize = MARKET_BLOCK_PAYLOAD_SIZE;
const GLOBAL_BLOCK_PAYLOAD_SIZE: usize = GLOBAL_BLOCK_SIZE - RBTREE_OVERHEAD_BYTES;
pub const GLOBAL_TRADER_SIZE: usize = GLOBAL_BLOCK_PAYLOAD_SIZE;
pub const GLOBAL_TRADER_MARKET_INFO_SIZE: usize = GLOBAL_BLOCK_PAYLOAD_SIZE;
const FREE_LIST_OVERHEAD: usize = 4;
pub const FREE_LIST_BLOCK_SIZE: usize = BLOCK_SIZE - FREE_LIST_OVERHEAD;
pub const FREE_LIST_BLOCK_SIZE: usize = MARKET_BLOCK_SIZE - FREE_LIST_OVERHEAD;

pub const NO_EXPIRATION_LAST_VALID_SLOT: u32 = 0;

Expand Down
6 changes: 3 additions & 3 deletions programs/manifest/src/state/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ use crate::{
};

use super::{
DerefOrBorrow, DerefOrBorrowMut, DynamicAccount, RestingOrder, BLOCK_SIZE,
FREE_LIST_BLOCK_SIZE, GLOBAL_FIXED_DISCRIMINANT, GLOBAL_FIXED_SIZE,
DerefOrBorrow, DerefOrBorrowMut, DynamicAccount, RestingOrder, FREE_LIST_BLOCK_SIZE,
GLOBAL_BLOCK_SIZE, GLOBAL_FIXED_DISCRIMINANT, GLOBAL_FIXED_SIZE,
GLOBAL_TRADER_MARKET_INFO_SIZE, GLOBAL_TRADER_SIZE,
};

Expand Down Expand Up @@ -282,7 +282,7 @@ impl<Fixed: DerefOrBorrowMut<GlobalFixed>, Dynamic: DerefOrBorrowMut<[u8]>>
FreeList::new(dynamic, fixed.free_list_head_index);

free_list.add(fixed.num_bytes_allocated);
fixed.num_bytes_allocated += BLOCK_SIZE as u32;
fixed.num_bytes_allocated += GLOBAL_BLOCK_SIZE as u32;
fixed.free_list_head_index = free_list.get_head();
Ok(())
}
Expand Down
28 changes: 9 additions & 19 deletions programs/manifest/src/state/market.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::{

use super::{
claimed_seat::ClaimedSeat,
constants::{BLOCK_SIZE, MARKET_FIXED_SIZE},
constants::{MARKET_BLOCK_SIZE, MARKET_FIXED_SIZE},
order_type_can_rest,
utils::{assert_not_already_expired, get_now_slot, try_to_add_to_global},
DerefOrBorrow, DerefOrBorrowMut, DynamicAccount, RestingOrder, FREE_LIST_BLOCK_SIZE,
Expand Down Expand Up @@ -107,9 +107,11 @@ pub struct MarketFixed {
/// LinkedList representing all free blocks that could be used for ClaimedSeats or RestingOrders
free_list_head_index: DataIndex,

// Unused padding. Saved in case a later version wants to be backwards
// compatible. Also, it is nice to have the fixed size be a round number,
// 256 bytes.
_padding2: [u32; 3],
_padding3: [u64; 32],
_padding4: [u64; 8],
_padding3: [u64; 8],
}
const_assert_eq!(
size_of::<MarketFixed>(),
Expand All @@ -134,7 +136,6 @@ const_assert_eq!(
4 + // claimed_seats_best_index
4 + // free_list_head_index
8 + // padding2
256 + // padding3
64 // padding4
);
const_assert_eq!(size_of::<MarketFixed>(), MARKET_FIXED_SIZE);
Expand Down Expand Up @@ -169,8 +170,7 @@ impl MarketFixed {
claimed_seats_root_index: NIL,
free_list_head_index: NIL,
_padding2: [0; 3],
_padding3: [0; 32],
_padding4: [0; 8],
_padding3: [0; 8],
}
}

Expand Down Expand Up @@ -403,7 +403,7 @@ impl<Fixed: DerefOrBorrowMut<MarketFixed>, Dynamic: DerefOrBorrowMut<[u8]>>
FreeList::new(dynamic, fixed.free_list_head_index);

free_list.add(fixed.num_bytes_allocated);
fixed.num_bytes_allocated += BLOCK_SIZE as u32;
fixed.num_bytes_allocated += MARKET_BLOCK_SIZE as u32;
fixed.free_list_head_index = free_list.get_head();
Ok(())
}
Expand Down Expand Up @@ -514,10 +514,6 @@ impl<Fixed: DerefOrBorrowMut<MarketFixed>, Dynamic: DerefOrBorrowMut<[u8]>>

let DynamicAccount { fixed, dynamic } = self.borrow_mut();

// Most of the time this is the price the user inputs, but on a
// PostOnlySlide, it gets updated.
let mut maker_price: QuoteAtomsPerBaseAtom = price;

let mut current_order_index: DataIndex = if is_bid {
fixed.asks_best_index
} else {
Expand Down Expand Up @@ -586,12 +582,6 @@ impl<Fixed: DerefOrBorrowMut<MarketFixed>, Dynamic: DerefOrBorrowMut<[u8]>>
// Got a match. First make sure we are allowed to match.
assert_can_take(order_type)?;

if order_type == OrderType::PostOnlySlide {
// Post only slide creates a zero spread book.
maker_price = other_order.get_price();
break;
}

// Match the order
let other_trader_index: DataIndex = other_order.get_trader_index();
let did_fully_match_resting_order: bool =
Expand Down Expand Up @@ -778,7 +768,7 @@ impl<Fixed: DerefOrBorrowMut<MarketFixed>, Dynamic: DerefOrBorrowMut<[u8]>>
let resting_order: RestingOrder = RestingOrder::new(
trader_index,
remaining_base_atoms,
maker_price,
price,
order_sequence_number,
last_valid_slot,
is_bid,
Expand All @@ -801,7 +791,7 @@ impl<Fixed: DerefOrBorrowMut<MarketFixed>, Dynamic: DerefOrBorrowMut<[u8]>>
!is_bid,
false,
if is_bid {
(remaining_base_atoms.checked_mul(maker_price, false))
(remaining_base_atoms.checked_mul(price, false))
.unwrap()
.into()
} else {
Expand Down
5 changes: 1 addition & 4 deletions programs/manifest/src/state/resting_order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,8 @@ pub enum OrderType {
// Fails if would cross the orderbook.
PostOnly = 2,

// Like a post only but slides to a zero spread rather than fail.
PostOnlySlide = 3,

// Global orders are post only but use funds from the global account.
Global = 4,
Global = 3,
}
unsafe impl bytemuck::Zeroable for OrderType {}
unsafe impl bytemuck::Pod for OrderType {}
Expand Down
4 changes: 2 additions & 2 deletions programs/manifest/tests/cases/batch_update.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use manifest::{
program::batch_update::{CancelOrderParams, PlaceOrderParams},
state::{OrderType, BLOCK_SIZE, NO_EXPIRATION_LAST_VALID_SLOT},
state::{OrderType, MARKET_BLOCK_SIZE, NO_EXPIRATION_LAST_VALID_SLOT},
};
use solana_program_test::tokio;

Expand Down Expand Up @@ -51,7 +51,7 @@ async fn batch_update_test() -> anyhow::Result<()> {
Some(0),
vec![CancelOrderParams::new_with_hint(
0,
Some((BLOCK_SIZE * 1).try_into().unwrap()),
Some((MARKET_BLOCK_SIZE * 1).try_into().unwrap()),
)],
vec![],
&test_fixture.payer_keypair(),
Expand Down
Loading

0 comments on commit eeb141d

Please sign in to comment.