Use keyed_account index names (#3555)

This commit is contained in:
Jack May
2019-04-03 15:57:26 -07:00
committed by GitHub
parent 35298e01a8
commit 9323a3e257
3 changed files with 130 additions and 100 deletions

View File

@ -46,7 +46,7 @@ pub enum ExchangeInstruction {
/// Trade cancellation /// Trade cancellation
/// key 0 - Signer /// key 0 - Signer
/// key 1 -Ttrade order to cancel /// key 1 - Trade order to cancel
TradeCancellation, TradeCancellation,
/// Trade swap request /// Trade swap request

View File

@ -20,34 +20,31 @@ impl ExchangeProcessor {
fn is_account_unallocated(data: &[u8]) -> Result<(), InstructionError> { fn is_account_unallocated(data: &[u8]) -> Result<(), InstructionError> {
let state: ExchangeState = bincode::deserialize(data).map_err(Self::map_to_invalid_arg)?; let state: ExchangeState = bincode::deserialize(data).map_err(Self::map_to_invalid_arg)?;
match state { if let ExchangeState::Unallocated = state {
ExchangeState::Unallocated => Ok(()), Ok(())
_ => { } else {
error!("New account is already in use"); error!("New account is already in use");
Err(InstructionError::InvalidAccountData)? Err(InstructionError::InvalidAccountData)?
}
} }
} }
fn deserialize_account(data: &[u8]) -> Result<(TokenAccountInfo), InstructionError> { fn deserialize_account(data: &[u8]) -> Result<TokenAccountInfo, InstructionError> {
let state: ExchangeState = bincode::deserialize(data).map_err(Self::map_to_invalid_arg)?; let state: ExchangeState = bincode::deserialize(data).map_err(Self::map_to_invalid_arg)?;
match state { if let ExchangeState::Account(account) = state {
ExchangeState::Account(account) => Ok(account), Ok(account)
_ => { } else {
error!("Not a valid account"); error!("Not a valid account");
Err(InstructionError::InvalidAccountData)? Err(InstructionError::InvalidAccountData)?
}
} }
} }
fn deserialize_trade(data: &[u8]) -> Result<(TradeOrderInfo), InstructionError> { fn deserialize_trade(data: &[u8]) -> Result<TradeOrderInfo, InstructionError> {
let state: ExchangeState = bincode::deserialize(data).map_err(Self::map_to_invalid_arg)?; let state: ExchangeState = bincode::deserialize(data).map_err(Self::map_to_invalid_arg)?;
match state { if let ExchangeState::Trade(info) = state {
ExchangeState::Trade(info) => Ok(info), Ok(info)
_ => { } else {
error!("Not a valid trade"); error!("Not a valid trade");
Err(InstructionError::InvalidAccountData)? Err(InstructionError::InvalidAccountData)?
}
} }
} }
@ -154,41 +151,50 @@ impl ExchangeProcessor {
Ok(()) Ok(())
} }
fn do_account_request(ka: &mut [KeyedAccount]) -> Result<(), InstructionError> { fn do_account_request(keyed_accounts: &mut [KeyedAccount]) -> Result<(), InstructionError> {
if ka.len() < 2 { const OWNER_INDEX: usize = 0;
const NEW_ACCOUNT_INDEX: usize = 1;
if keyed_accounts.len() < 2 {
error!("Not enough accounts"); error!("Not enough accounts");
Err(InstructionError::InvalidArgument)? Err(InstructionError::InvalidArgument)?
} }
Self::is_account_unallocated(&ka[1].account.data[..])?; Self::is_account_unallocated(&keyed_accounts[NEW_ACCOUNT_INDEX].account.data)?;
Self::serialize( Self::serialize(
&ExchangeState::Account( &ExchangeState::Account(
TokenAccountInfo::default() TokenAccountInfo::default()
.owner(&ka[0].unsigned_key()) .owner(&keyed_accounts[OWNER_INDEX].unsigned_key())
.tokens(100_000, 100_000, 100_000, 100_000), .tokens(100_000, 100_000, 100_000, 100_000),
), ),
&mut ka[1].account.data[..], &mut keyed_accounts[NEW_ACCOUNT_INDEX].account.data,
) )
} }
fn do_transfer_request( fn do_transfer_request(
ka: &mut [KeyedAccount], keyed_accounts: &mut [KeyedAccount],
token: Token, token: Token,
tokens: u64, tokens: u64,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
if ka.len() < 3 { const OWNER_INDEX: usize = 0;
const TO_ACCOUNT_INDEX: usize = 1;
const FROM_ACCOUNT_INDEX: usize = 2;
if keyed_accounts.len() < 3 {
error!("Not enough accounts"); error!("Not enough accounts");
Err(InstructionError::InvalidArgument)? Err(InstructionError::InvalidArgument)?
} }
let mut to_account = Self::deserialize_account(&ka[1].account.data[..])?; let mut to_account =
Self::deserialize_account(&keyed_accounts[TO_ACCOUNT_INDEX].account.data)?;
if &id() == ka[2].unsigned_key() { if &id() == keyed_accounts[FROM_ACCOUNT_INDEX].unsigned_key() {
to_account.tokens[token] += tokens; to_account.tokens[token] += tokens;
} else { } else {
let mut from_account = Self::deserialize_account(&ka[2].account.data[..])?; let mut from_account =
Self::deserialize_account(&keyed_accounts[FROM_ACCOUNT_INDEX].account.data)?;
if &from_account.owner != ka[0].unsigned_key() { if &from_account.owner != keyed_accounts[OWNER_INDEX].unsigned_key() {
error!("Signer does not own from account"); error!("Signer does not own from account");
Err(InstructionError::GenericError)? Err(InstructionError::GenericError)?
} }
@ -203,30 +209,34 @@ impl ExchangeProcessor {
Self::serialize( Self::serialize(
&ExchangeState::Account(from_account), &ExchangeState::Account(from_account),
&mut ka[1].account.data[..], &mut keyed_accounts[FROM_ACCOUNT_INDEX].account.data,
)?; )?;
} }
Self::serialize( Self::serialize(
&ExchangeState::Account(to_account), &ExchangeState::Account(to_account),
&mut ka[1].account.data[..], &mut keyed_accounts[TO_ACCOUNT_INDEX].account.data,
) )
} }
fn do_trade_request( fn do_trade_request(
ka: &mut [KeyedAccount], keyed_accounts: &mut [KeyedAccount],
info: TradeRequestInfo, info: &TradeRequestInfo,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
if ka.len() < 3 { const OWNER_INDEX: usize = 0;
const TRADE_INDEX: usize = 1;
const ACCOUNT_INDEX: usize = 2;
if keyed_accounts.len() < 3 {
error!("Not enough accounts"); error!("Not enough accounts");
Err(InstructionError::InvalidArgument)? Err(InstructionError::InvalidArgument)?
} }
Self::is_account_unallocated(&ka[1].account.data[..])?; Self::is_account_unallocated(&keyed_accounts[TRADE_INDEX].account.data)?;
let mut account = Self::deserialize_account(&ka[2].account.data[..])?; let mut account = Self::deserialize_account(&keyed_accounts[ACCOUNT_INDEX].account.data)?;
if &account.owner != ka[0].unsigned_key() { if &account.owner != keyed_accounts[OWNER_INDEX].unsigned_key() {
error!("Signer does not own account"); error!("Signer does not own account");
Err(InstructionError::GenericError)? Err(InstructionError::GenericError)?
} }
@ -248,36 +258,41 @@ impl ExchangeProcessor {
Self::serialize( Self::serialize(
&ExchangeState::Trade(TradeOrderInfo { &ExchangeState::Trade(TradeOrderInfo {
owner: *ka[0].unsigned_key(), owner: *keyed_accounts[OWNER_INDEX].unsigned_key(),
direction: info.direction, direction: info.direction,
pair: info.pair, pair: info.pair,
tokens: info.tokens, tokens: info.tokens,
price: info.price, price: info.price,
src_account: *ka[2].unsigned_key(), src_account: *keyed_accounts[ACCOUNT_INDEX].unsigned_key(),
dst_account: info.dst_account, dst_account: info.dst_account,
}), }),
&mut ka[1].account.data[..], &mut keyed_accounts[TRADE_INDEX].account.data,
)?; )?;
Self::serialize( Self::serialize(
&ExchangeState::Account(account), &ExchangeState::Account(account),
&mut ka[2].account.data[..], &mut keyed_accounts[ACCOUNT_INDEX].account.data,
) )
} }
fn do_trade_cancellation(ka: &mut [KeyedAccount]) -> Result<(), InstructionError> { fn do_trade_cancellation(keyed_accounts: &mut [KeyedAccount]) -> Result<(), InstructionError> {
if ka.len() < 3 { const OWNER_INDEX: usize = 0;
const TRADE_INDEX: usize = 1;
const ACCOUNT_INDEX: usize = 2;
if keyed_accounts.len() < 3 {
error!("Not enough accounts"); error!("Not enough accounts");
Err(InstructionError::InvalidArgument)? Err(InstructionError::InvalidArgument)?
} }
let mut trade = Self::deserialize_trade(&ka[1].account.data[..])?;
let mut account = Self::deserialize_account(&ka[2].account.data[..])?;
if &trade.owner != ka[0].unsigned_key() { let mut trade = Self::deserialize_trade(&keyed_accounts[TRADE_INDEX].account.data)?;
let mut account = Self::deserialize_account(&keyed_accounts[ACCOUNT_INDEX].account.data)?;
if &trade.owner != keyed_accounts[OWNER_INDEX].unsigned_key() {
error!("Signer does not own trade"); error!("Signer does not own trade");
Err(InstructionError::GenericError)? Err(InstructionError::GenericError)?
} }
if &account.owner != ka[0].unsigned_key() { if &account.owner != keyed_accounts[OWNER_INDEX].unsigned_key() {
error!("Signer does not own account"); error!("Signer does not own account");
Err(InstructionError::GenericError)? Err(InstructionError::GenericError)?
} }
@ -292,30 +307,45 @@ impl ExchangeProcessor {
// Trade becomes invalid // Trade becomes invalid
trade.tokens = 0; trade.tokens = 0;
Self::serialize(&ExchangeState::Trade(trade), &mut ka[1].account.data[..])?; Self::serialize(
&ExchangeState::Trade(trade),
&mut keyed_accounts[TRADE_INDEX].account.data,
)?;
Self::serialize( Self::serialize(
&ExchangeState::Account(account), &ExchangeState::Account(account),
&mut ka[2].account.data[..], &mut keyed_accounts[ACCOUNT_INDEX].account.data,
) )
} }
fn do_swap_request(ka: &mut [KeyedAccount]) -> Result<(), InstructionError> { fn do_swap_request(keyed_accounts: &mut [KeyedAccount]) -> Result<(), InstructionError> {
if ka.len() < 7 { const SWAP_ACCOUNT_INDEX: usize = 1;
const TO_TRADE_INDEX: usize = 2;
const FROM_TRADE_INDEX: usize = 3;
const TO_ACCOUNT_INDEX: usize = 4;
const FROM_ACCOUNT_INDEX: usize = 5;
const PROFIT_ACCOUNT_INDEX: usize = 6;
if keyed_accounts.len() < 7 {
error!("Not enough accounts"); error!("Not enough accounts");
Err(InstructionError::InvalidArgument)? Err(InstructionError::InvalidArgument)?
} }
Self::is_account_unallocated(&ka[1].account.data[..])?;
let mut to_trade = Self::deserialize_trade(&ka[2].account.data[..])?;
let mut from_trade = Self::deserialize_trade(&ka[3].account.data[..])?;
let mut to_trade_account = Self::deserialize_account(&ka[4].account.data[..])?;
let mut from_trade_account = Self::deserialize_account(&ka[5].account.data[..])?;
let mut profit_account = Self::deserialize_account(&ka[6].account.data[..])?;
if &to_trade.dst_account != ka[4].unsigned_key() { Self::is_account_unallocated(&keyed_accounts[SWAP_ACCOUNT_INDEX].account.data)?;
let mut to_trade = Self::deserialize_trade(&keyed_accounts[TO_TRADE_INDEX].account.data)?;
let mut from_trade =
Self::deserialize_trade(&keyed_accounts[FROM_TRADE_INDEX].account.data)?;
let mut to_trade_account =
Self::deserialize_account(&keyed_accounts[TO_ACCOUNT_INDEX].account.data)?;
let mut from_trade_account =
Self::deserialize_account(&keyed_accounts[FROM_ACCOUNT_INDEX].account.data)?;
let mut profit_account =
Self::deserialize_account(&keyed_accounts[PROFIT_ACCOUNT_INDEX].account.data)?;
if &to_trade.dst_account != keyed_accounts[TO_ACCOUNT_INDEX].unsigned_key() {
error!("To trade account and to account differ"); error!("To trade account and to account differ");
Err(InstructionError::InvalidArgument)? Err(InstructionError::InvalidArgument)?
} }
if &from_trade.dst_account != ka[5].unsigned_key() { if &from_trade.dst_account != keyed_accounts[FROM_ACCOUNT_INDEX].unsigned_key() {
error!("From trade account and from account differ"); error!("From trade account and from account differ");
Err(InstructionError::InvalidArgument)? Err(InstructionError::InvalidArgument)?
} }
@ -337,8 +367,8 @@ impl ExchangeProcessor {
} }
let mut swap = TradeSwapInfo::default(); let mut swap = TradeSwapInfo::default();
swap.to_trade_order = *ka[2].unsigned_key(); swap.to_trade_order = *keyed_accounts[TO_TRADE_INDEX].unsigned_key();
swap.from_trade_order = *ka[3].unsigned_key(); swap.from_trade_order = *keyed_accounts[FROM_TRADE_INDEX].unsigned_key();
if let Err(e) = Self::calculate_swap( if let Err(e) = Self::calculate_swap(
SCALER, SCALER,
@ -356,23 +386,29 @@ impl ExchangeProcessor {
Err(e)? Err(e)?
} }
Self::serialize(&ExchangeState::Swap(swap), &mut ka[1].account.data[..])?; Self::serialize(
Self::serialize(&ExchangeState::Trade(to_trade), &mut ka[2].account.data[..])?; &ExchangeState::Swap(swap),
&mut keyed_accounts[SWAP_ACCOUNT_INDEX].account.data,
)?;
Self::serialize(
&ExchangeState::Trade(to_trade),
&mut keyed_accounts[TO_TRADE_INDEX].account.data,
)?;
Self::serialize( Self::serialize(
&ExchangeState::Trade(from_trade), &ExchangeState::Trade(from_trade),
&mut ka[3].account.data[..], &mut keyed_accounts[FROM_TRADE_INDEX].account.data,
)?; )?;
Self::serialize( Self::serialize(
&ExchangeState::Account(to_trade_account), &ExchangeState::Account(to_trade_account),
&mut ka[4].account.data[..], &mut keyed_accounts[TO_ACCOUNT_INDEX].account.data,
)?; )?;
Self::serialize( Self::serialize(
&ExchangeState::Account(from_trade_account), &ExchangeState::Account(from_trade_account),
&mut ka[5].account.data[..], &mut keyed_accounts[FROM_ACCOUNT_INDEX].account.data,
)?; )?;
Self::serialize( Self::serialize(
&ExchangeState::Account(profit_account), &ExchangeState::Account(profit_account),
&mut ka[6].account.data[..], &mut keyed_accounts[PROFIT_ACCOUNT_INDEX].account.data,
) )
} }
} }
@ -400,7 +436,7 @@ pub fn process_instruction(
ExchangeProcessor::do_transfer_request(keyed_accounts, token, tokens) ExchangeProcessor::do_transfer_request(keyed_accounts, token, tokens)
} }
ExchangeInstruction::TradeRequest(info) => { ExchangeInstruction::TradeRequest(info) => {
ExchangeProcessor::do_trade_request(keyed_accounts, info) ExchangeProcessor::do_trade_request(keyed_accounts, &info)
} }
ExchangeInstruction::TradeCancellation => { ExchangeInstruction::TradeCancellation => {
ExchangeProcessor::do_trade_cancellation(keyed_accounts) ExchangeProcessor::do_trade_cancellation(keyed_accounts)
@ -623,7 +659,7 @@ mod test {
TokenAccountInfo::default() TokenAccountInfo::default()
.owner(&owner.pubkey()) .owner(&owner.pubkey())
.tokens(100_000, 100_000, 100_000, 100_000), .tokens(100_000, 100_000, 100_000, 100_000),
ExchangeProcessor::deserialize_account(&new_account.data[..]).unwrap() ExchangeProcessor::deserialize_account(&new_account.data).unwrap()
); );
} }
@ -662,7 +698,7 @@ mod test {
TokenAccountInfo::default() TokenAccountInfo::default()
.owner(&owner.pubkey()) .owner(&owner.pubkey())
.tokens(100_042, 100_000, 100_000, 100_000), .tokens(100_042, 100_000, 100_000, 100_000),
ExchangeProcessor::deserialize_account(&new_account.data[..]).unwrap() ExchangeProcessor::deserialize_account(&new_account.data).unwrap()
); );
} }
@ -699,19 +735,19 @@ mod test {
src_account: src, src_account: src,
dst_account: dst dst_account: dst
}, },
ExchangeProcessor::deserialize_trade(&trade_account.data[..]).unwrap() ExchangeProcessor::deserialize_trade(&trade_account.data).unwrap()
); );
assert_eq!( assert_eq!(
TokenAccountInfo::default() TokenAccountInfo::default()
.owner(&owner.pubkey()) .owner(&owner.pubkey())
.tokens(100_040, 100_000, 100_000, 100_000), .tokens(100_040, 100_000, 100_000, 100_000),
ExchangeProcessor::deserialize_account(&src_account.data[..]).unwrap() ExchangeProcessor::deserialize_account(&src_account.data).unwrap()
); );
assert_eq!( assert_eq!(
TokenAccountInfo::default() TokenAccountInfo::default()
.owner(&owner.pubkey()) .owner(&owner.pubkey())
.tokens(100_000, 100_000, 100_000, 100_000), .tokens(100_000, 100_000, 100_000, 100_000),
ExchangeProcessor::deserialize_account(&dst_account.data[..]).unwrap() ExchangeProcessor::deserialize_account(&dst_account.data).unwrap()
); );
} }
@ -778,19 +814,19 @@ mod test {
src_account: to_src, src_account: to_src,
dst_account: to_dst dst_account: to_dst
}, },
ExchangeProcessor::deserialize_trade(&to_trade_account.data[..]).unwrap() ExchangeProcessor::deserialize_trade(&to_trade_account.data).unwrap()
); );
assert_eq!( assert_eq!(
TokenAccountInfo::default() TokenAccountInfo::default()
.owner(&owner.pubkey()) .owner(&owner.pubkey())
.tokens(100_000, 100_000, 100_000, 100_000), .tokens(100_000, 100_000, 100_000, 100_000),
ExchangeProcessor::deserialize_account(&to_src_account.data[..]).unwrap() ExchangeProcessor::deserialize_account(&to_src_account.data).unwrap()
); );
assert_eq!( assert_eq!(
TokenAccountInfo::default() TokenAccountInfo::default()
.owner(&owner.pubkey()) .owner(&owner.pubkey())
.tokens(100_000, 100_002, 100_000, 100_000), .tokens(100_000, 100_002, 100_000, 100_000),
ExchangeProcessor::deserialize_account(&to_dst_account.data[..]).unwrap() ExchangeProcessor::deserialize_account(&to_dst_account.data).unwrap()
); );
assert_eq!( assert_eq!(
TradeOrderInfo { TradeOrderInfo {
@ -802,25 +838,25 @@ mod test {
src_account: from_src, src_account: from_src,
dst_account: from_dst dst_account: from_dst
}, },
ExchangeProcessor::deserialize_trade(&from_trade_account.data[..]).unwrap() ExchangeProcessor::deserialize_trade(&from_trade_account.data).unwrap()
); );
assert_eq!( assert_eq!(
TokenAccountInfo::default() TokenAccountInfo::default()
.owner(&owner.pubkey()) .owner(&owner.pubkey())
.tokens(100_000, 100_000, 100_000, 100_000), .tokens(100_000, 100_000, 100_000, 100_000),
ExchangeProcessor::deserialize_account(&from_src_account.data[..]).unwrap() ExchangeProcessor::deserialize_account(&from_src_account.data).unwrap()
); );
assert_eq!( assert_eq!(
TokenAccountInfo::default() TokenAccountInfo::default()
.owner(&owner.pubkey()) .owner(&owner.pubkey())
.tokens(100_001, 100_000, 100_000, 100_000), .tokens(100_001, 100_000, 100_000, 100_000),
ExchangeProcessor::deserialize_account(&from_dst_account.data[..]).unwrap() ExchangeProcessor::deserialize_account(&from_dst_account.data).unwrap()
); );
assert_eq!( assert_eq!(
TokenAccountInfo::default() TokenAccountInfo::default()
.owner(&owner.pubkey()) .owner(&owner.pubkey())
.tokens(100_000, 100_001, 100_000, 100_000), .tokens(100_000, 100_001, 100_000, 100_000),
ExchangeProcessor::deserialize_account(&profit_account.data[..]).unwrap() ExchangeProcessor::deserialize_account(&profit_account.data).unwrap()
); );
assert_eq!( assert_eq!(
TradeSwapInfo { TradeSwapInfo {
@ -832,7 +868,7 @@ mod test {
secondary_tokens: 3, secondary_tokens: 3,
secondary_price: 3000, secondary_price: 3000,
}, },
deserialize_swap(&swap_account.data[..]) deserialize_swap(&swap_account.data)
); );
} }
} }

View File

@ -28,7 +28,7 @@ pub enum Token {
D, D,
} }
impl Default for Token { impl Default for Token {
fn default() -> Token { fn default() -> Self {
Token::A Token::A
} }
} }
@ -44,7 +44,7 @@ pub struct Tokens {
} }
impl Tokens { impl Tokens {
pub fn new(a: u64, b: u64, c: u64, d: u64) -> Self { pub fn new(a: u64, b: u64, c: u64, d: u64) -> Self {
Tokens { Self {
A: a, A: a,
B: b, B: b,
C: c, C: c,
@ -85,29 +85,23 @@ pub enum TokenPair {
CD, CD,
} }
impl Default for TokenPair { impl Default for TokenPair {
fn default() -> TokenPair { fn default() -> Self {
TokenPair::AB TokenPair::AB
} }
} }
impl TokenPair { impl TokenPair {
pub fn primary(self) -> Token { pub fn primary(self) -> Token {
match self { match self {
TokenPair::AB => Token::A, TokenPair::AB | TokenPair::AC | TokenPair::AD => Token::A,
TokenPair::AC => Token::A, TokenPair::BC | TokenPair::BD => Token::B,
TokenPair::AD => Token::A,
TokenPair::BC => Token::B,
TokenPair::BD => Token::B,
TokenPair::CD => Token::C, TokenPair::CD => Token::C,
} }
} }
pub fn secondary(self) -> Token { pub fn secondary(self) -> Token {
match self { match self {
TokenPair::AB => Token::B, TokenPair::AB => Token::B,
TokenPair::AC => Token::C, TokenPair::AC | TokenPair::BC => Token::C,
TokenPair::AD => Token::D, TokenPair::AD | TokenPair::BD | TokenPair::CD => Token::D,
TokenPair::BC => Token::C,
TokenPair::BD => Token::D,
TokenPair::CD => Token::D,
} }
} }
} }
@ -175,8 +169,8 @@ pub struct TradeOrderInfo {
pub dst_account: Pubkey, pub dst_account: Pubkey,
} }
impl Default for TradeOrderInfo { impl Default for TradeOrderInfo {
fn default() -> TradeOrderInfo { fn default() -> Self {
TradeOrderInfo { Self {
owner: Pubkey::default(), owner: Pubkey::default(),
pair: TokenPair::AB, pair: TokenPair::AB,
direction: Direction::To, direction: Direction::To,
@ -261,7 +255,7 @@ pub enum ExchangeState {
Invalid, Invalid,
} }
impl Default for ExchangeState { impl Default for ExchangeState {
fn default() -> ExchangeState { fn default() -> Self {
ExchangeState::Unallocated ExchangeState::Unallocated
} }
} }