mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-05 23:03:06 +00:00
Merge branch 'schouhy/add-init-function-to-token-program' into schouhy/implement-pda-for-public-accounts
This commit is contained in:
commit
ed00876800
@ -3,7 +3,7 @@ use nssa_core::{
|
||||
program::{ProgramInput, read_nssa_inputs, write_nssa_outputs},
|
||||
};
|
||||
|
||||
// The token program has two functions:
|
||||
// The token program has three functions:
|
||||
// 1. New token definition.
|
||||
// Arguments to this function are:
|
||||
// * Two **default** accounts: [definition_account, holding_account].
|
||||
@ -18,6 +18,11 @@ use nssa_core::{
|
||||
// * Two accounts: [sender_account, recipient_account].
|
||||
// * An instruction data byte string of length 23, indicating the total supply with the following layout
|
||||
// [0x01 || amount (little-endian 16 bytes) || 0x00 || 0x00 || 0x00 || 0x00 || 0x00 || 0x00].
|
||||
// 3. Initialize account with zero balance
|
||||
// Arguments to this function are:
|
||||
// * Two accounts: [definition_account, account_to_initialize].
|
||||
// * An dummy byte string of length 23, with the following layout
|
||||
// [0x02 || 0x00 || 0x00 || 0x00 || ... || 0x00 || 0x00].
|
||||
|
||||
const TOKEN_DEFINITION_TYPE: u8 = 0;
|
||||
const TOKEN_DEFINITION_DATA_SIZE: usize = 23;
|
||||
@ -52,7 +57,11 @@ impl TokenDefinition {
|
||||
} else {
|
||||
let account_type = data[0];
|
||||
let name = data[1..7].try_into().unwrap();
|
||||
let total_supply = u128::from_le_bytes(data[7..].try_into().unwrap());
|
||||
let total_supply = u128::from_le_bytes(
|
||||
data[7..]
|
||||
.try_into()
|
||||
.expect("Total supply must be 16 bytes little-endian"),
|
||||
);
|
||||
Some(Self {
|
||||
account_type,
|
||||
name,
|
||||
@ -76,8 +85,16 @@ impl TokenHolding {
|
||||
None
|
||||
} else {
|
||||
let account_type = data[0];
|
||||
let definition_id = AccountId::new(data[1..33].try_into().unwrap());
|
||||
let balance = u128::from_le_bytes(data[33..].try_into().unwrap());
|
||||
let definition_id = AccountId::new(
|
||||
data[1..33]
|
||||
.try_into()
|
||||
.expect("Defintion ID must be 32 bytes long"),
|
||||
);
|
||||
let balance = u128::from_le_bytes(
|
||||
data[33..]
|
||||
.try_into()
|
||||
.expect("balance must be 16 bytes little-endian"),
|
||||
);
|
||||
Some(Self {
|
||||
definition_id,
|
||||
balance,
|
||||
@ -182,46 +199,7 @@ fn new_definition(
|
||||
vec![definition_target_account_post, holding_target_account_post]
|
||||
}
|
||||
|
||||
type Instruction = [u8; 23];
|
||||
|
||||
fn main() {
|
||||
let ProgramInput {
|
||||
pre_states,
|
||||
instruction,
|
||||
} = read_nssa_inputs::<Instruction>();
|
||||
|
||||
match instruction[0] {
|
||||
0 => {
|
||||
// Parse instruction
|
||||
let total_supply = u128::from_le_bytes(instruction[1..17].try_into().unwrap());
|
||||
let name: [u8; 6] = instruction[17..].try_into().unwrap();
|
||||
assert_ne!(name, [0; 6]);
|
||||
|
||||
// Execute
|
||||
let post_states = new_definition(&pre_states, name, total_supply);
|
||||
write_nssa_outputs(pre_states, post_states);
|
||||
}
|
||||
1 => {
|
||||
// Parse instruction
|
||||
let balance_to_move = u128::from_le_bytes(instruction[1..17].try_into().unwrap());
|
||||
let name: [u8; 6] = instruction[17..].try_into().unwrap();
|
||||
assert_eq!(name, [0; 6]);
|
||||
|
||||
// Execute
|
||||
let post_states = transfer(&pre_states, balance_to_move);
|
||||
write_nssa_outputs(pre_states, post_states);
|
||||
}
|
||||
2 => {
|
||||
// Initialize account
|
||||
assert_eq!(instruction[1..], [0; 22]);
|
||||
let post_states = initialize(&pre_states);
|
||||
write_nssa_outputs(pre_states, post_states);
|
||||
}
|
||||
_ => panic!("Invalid instruction"),
|
||||
};
|
||||
}
|
||||
|
||||
fn initialize(pre_states: &[AccountWithMetadata]) -> Vec<Account> {
|
||||
fn initialize_account(pre_states: &[AccountWithMetadata]) -> Vec<Account> {
|
||||
if pre_states.len() != 2 {
|
||||
panic!("Invalid number of accounts");
|
||||
}
|
||||
@ -235,23 +213,80 @@ fn initialize(pre_states: &[AccountWithMetadata]) -> Vec<Account> {
|
||||
|
||||
// TODO: We should check that this is an account owned by the token program.
|
||||
// This check can't be done here since the ID of the program is known only after compiling it
|
||||
//
|
||||
// Check definition account is valid
|
||||
let _definition_values =
|
||||
TokenDefinition::parse(&definition.account.data).expect("Definition account must be valid");
|
||||
let holding_for_definition = TokenHolding::new(&definition.account_id);
|
||||
let holding_values = TokenHolding::new(&definition.account_id);
|
||||
|
||||
let definition_post = definition.account.clone();
|
||||
let mut account_to_initialize_post = account_to_initialize.account.clone();
|
||||
account_to_initialize_post.data = holding_for_definition.into_data();
|
||||
account_to_initialize_post.data = holding_values.into_data();
|
||||
|
||||
vec![definition_post, account_to_initialize_post]
|
||||
}
|
||||
|
||||
type Instruction = [u8; 23];
|
||||
|
||||
fn main() {
|
||||
let ProgramInput {
|
||||
pre_states,
|
||||
instruction,
|
||||
} = read_nssa_inputs::<Instruction>();
|
||||
|
||||
let post_states = match instruction[0] {
|
||||
0 => {
|
||||
// Parse instruction
|
||||
let total_supply = u128::from_le_bytes(
|
||||
instruction[1..17]
|
||||
.try_into()
|
||||
.expect("Total supply must be 16 bytes little-endian"),
|
||||
);
|
||||
let name: [u8; 6] = instruction[17..]
|
||||
.try_into()
|
||||
.expect("Name must be 6 bytes long");
|
||||
assert_ne!(name, [0; 6]);
|
||||
|
||||
// Execute
|
||||
new_definition(&pre_states, name, total_supply)
|
||||
}
|
||||
1 => {
|
||||
// Parse instruction
|
||||
let balance_to_move = u128::from_le_bytes(
|
||||
instruction[1..17]
|
||||
.try_into()
|
||||
.expect("Balance to move must be 16 bytes little-endian"),
|
||||
);
|
||||
let name: [u8; 6] = instruction[17..]
|
||||
.try_into()
|
||||
.expect("Name must be 6 bytes long");
|
||||
assert_eq!(name, [0; 6]);
|
||||
|
||||
// Execute
|
||||
transfer(&pre_states, balance_to_move)
|
||||
}
|
||||
2 => {
|
||||
// Initialize account
|
||||
if instruction[1..] != [0; 22] {
|
||||
panic!("Invalid instruction for initialize account");
|
||||
}
|
||||
initialize_account(&pre_states)
|
||||
}
|
||||
_ => panic!("Invalid instruction"),
|
||||
};
|
||||
|
||||
write_nssa_outputs(pre_states, post_states);
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use nssa_core::account::{Account, AccountId, AccountWithMetadata};
|
||||
|
||||
use crate::{TOKEN_HOLDING_DATA_SIZE, TOKEN_HOLDING_TYPE, new_definition, transfer};
|
||||
use crate::{
|
||||
TOKEN_DEFINITION_DATA_SIZE, TOKEN_HOLDING_DATA_SIZE, TOKEN_HOLDING_TYPE,
|
||||
initialize_account, new_definition, transfer,
|
||||
};
|
||||
|
||||
#[should_panic(expected = "Invalid number of input accounts")]
|
||||
#[test]
|
||||
@ -598,4 +633,37 @@ mod tests {
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_token_initialize_account_succeeds() {
|
||||
let pre_states = vec![
|
||||
AccountWithMetadata {
|
||||
account: Account {
|
||||
// Definition ID with
|
||||
data: vec![0; TOKEN_DEFINITION_DATA_SIZE - 16]
|
||||
.into_iter()
|
||||
.chain(u128::to_le_bytes(1000))
|
||||
.collect(),
|
||||
..Account::default()
|
||||
},
|
||||
is_authorized: false,
|
||||
account_id: AccountId::new([1; 32]),
|
||||
},
|
||||
AccountWithMetadata {
|
||||
account: Account::default(),
|
||||
is_authorized: false,
|
||||
account_id: AccountId::new([2; 32]),
|
||||
},
|
||||
];
|
||||
let post_states = initialize_account(&pre_states);
|
||||
let [definition, holding] = post_states.try_into().ok().unwrap();
|
||||
assert_eq!(definition.data, pre_states[0].account.data);
|
||||
assert_eq!(
|
||||
holding.data,
|
||||
vec![
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2299,6 +2299,9 @@ pub mod tests {
|
||||
state.transition_from_public_transaction(&tx).unwrap();
|
||||
|
||||
let winner_token_holding_post = state.get_account_by_id(&winner_token_holding_id);
|
||||
assert_eq!(winner_token_holding_post, expected_winner_token_holding_post);
|
||||
assert_eq!(
|
||||
winner_token_holding_post,
|
||||
expected_winner_token_holding_post
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user