diff --git a/nssa/core/Cargo.toml b/nssa/core/Cargo.toml index 6b59885..a8d640c 100644 --- a/nssa/core/Cargo.toml +++ b/nssa/core/Cargo.toml @@ -7,7 +7,7 @@ edition = "2024" risc0-zkvm = { version = "3.0.3", features = ['std'] } serde = { version = "1.0", default-features = false } thiserror = { version = "2.0.12" } -bytemuck = { version = "1.13" } +bytemuck = "1.24.0" chacha20 = { version = "0.9", default-features = false } k256 = { version = "0.13.3", optional = true } base58 = { version = "0.2.0", optional = true } diff --git a/nssa/core/src/account.rs b/nssa/core/src/account.rs index d3512d6..5a2a71f 100644 --- a/nssa/core/src/account.rs +++ b/nssa/core/src/account.rs @@ -32,6 +32,7 @@ pub struct AccountWithMetadata { pub is_authorized: bool, pub account_id: AccountId, } + #[cfg(feature = "host")] impl AccountWithMetadata { pub fn new(account: Account, is_authorized: bool, account_id: impl Into) -> Self { @@ -44,7 +45,7 @@ impl AccountWithMetadata { } #[derive( - Serialize, Deserialize, Clone, PartialEq, Eq, Hash, BorshSerialize, BorshDeserialize, Default, + Serialize, Deserialize, Clone, Default, PartialEq, Eq, Hash, BorshSerialize, BorshDeserialize, )] #[cfg_attr(any(feature = "host", test), derive(Debug, Copy, PartialOrd, Ord))] pub struct AccountId { diff --git a/nssa/core/src/program.rs b/nssa/core/src/program.rs index 22d1ebc..03fe163 100644 --- a/nssa/core/src/program.rs +++ b/nssa/core/src/program.rs @@ -20,8 +20,8 @@ pub struct ProgramInput { /// Each program can derive up to `2^256` unique account IDs by choosing different /// seeds. PDAs allow programs to control namespaced account identifiers without /// collisions between programs. -#[derive(Serialize, Deserialize, Clone, PartialEq)] -#[cfg_attr(any(feature = "host", test), derive(Debug, Eq))] +#[derive(Serialize, Deserialize, Clone, Eq, PartialEq)] +#[cfg_attr(any(feature = "host", test), derive(Debug))] pub struct PdaSeed([u8; 32]); impl PdaSeed { @@ -51,8 +51,8 @@ impl From<(&ProgramId, &PdaSeed)> for AccountId { } } -#[derive(Serialize, Deserialize, Clone, PartialEq)] -#[cfg_attr(any(feature = "host", test), derive(Debug, Eq))] +#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)] +#[cfg_attr(any(feature = "host", test), derive(Debug,))] pub struct ChainedCall { /// The program ID of the program to execute pub program_id: ProgramId, diff --git a/nssa/program_methods/guest/Cargo.toml b/nssa/program_methods/guest/Cargo.toml index 0861989..9e5f543 100644 --- a/nssa/program_methods/guest/Cargo.toml +++ b/nssa/program_methods/guest/Cargo.toml @@ -8,4 +8,4 @@ edition = "2024" [dependencies] risc0-zkvm = { version = "3.0.3", features = ['std'] } nssa-core = { path = "../../core" } -serde = { version = "1.0.219", default-features = false } \ No newline at end of file +serde = { version = "1.0.219", default-features = false } diff --git a/nssa/program_methods/guest/src/bin/amm.rs b/nssa/program_methods/guest/src/bin/amm.rs index 0b1ced3..0882a0d 100644 --- a/nssa/program_methods/guest/src/bin/amm.rs +++ b/nssa/program_methods/guest/src/bin/amm.rs @@ -73,7 +73,7 @@ struct PoolDefinition{ } impl PoolDefinition { - fn into_data(self) -> Vec { + fn into_data(self) -> Data { let mut bytes = [0; POOL_DEFINITION_DATA_SIZE]; bytes[0..32].copy_from_slice(&self.definition_token_a_id.to_bytes()); bytes[32..64].copy_from_slice(&self.definition_token_b_id.to_bytes()); @@ -85,7 +85,11 @@ impl PoolDefinition { bytes[192..208].copy_from_slice(&self.reserve_b.to_le_bytes()); bytes[208..224].copy_from_slice(&self.fees.to_le_bytes()); bytes[224] = self.active as u8; - bytes.into() + + bytes + .to_vec() + .try_into() + .expect("225 bytes should fit into Data") } fn parse(data: &[u8]) -> Option { @@ -144,14 +148,18 @@ struct TokenHolding { } impl TokenDefinition { - fn into_data(self) -> Vec { + fn into_data(self) -> Data { let mut bytes = [0; TOKEN_DEFINITION_DATA_SIZE]; bytes[0] = self.account_type; bytes[1..7].copy_from_slice(&self.name); bytes[7..].copy_from_slice(&self.total_supply.to_le_bytes()); - bytes.into() + bytes + .to_vec() + .try_into() + .expect("23 bytes should fit into Data") } + fn parse(data: &[u8]) -> Option { if data.len() != TOKEN_DEFINITION_DATA_SIZE || data[0] != TOKEN_DEFINITION_TYPE { None @@ -209,17 +217,21 @@ impl TokenHolding { bytes[0] = self.account_type; bytes[1..33].copy_from_slice(&self.definition_id.to_bytes()); bytes[33..].copy_from_slice(&self.balance.to_le_bytes()); - bytes.to_vec().try_into().expect("Data too big") + + bytes + .to_vec() + .try_into() + .expect("49 bytes should fit into Data") } } type Instruction = Vec; fn main() { - let ( ProgramInput { + let (ProgramInput { pre_states, instruction, - }, instruction_data) = read_nssa_inputs::(); + }, instruction_words) = read_nssa_inputs::(); let (post_states, chained_calls) = match instruction[0] { 0 => { @@ -266,7 +278,7 @@ fn main() { _ => panic!("Invalid instruction"), }; - write_nssa_outputs_with_chained_call(instruction_data, pre_states, post_states, chained_calls); + write_nssa_outputs_with_chained_call(instruction_words, pre_states, post_states, chained_calls); } diff --git a/nssa/src/state.rs b/nssa/src/state.rs index bcc8382..ab802c7 100644 --- a/nssa/src/state.rs +++ b/nssa/src/state.rs @@ -2241,14 +2241,16 @@ pub mod tests { definition_id: AccountId, balance: u128, } - impl TokenDefinition { - fn into_data(self) -> Vec { + fn into_data(self) -> Data { let mut bytes = [0; TOKEN_DEFINITION_DATA_SIZE]; bytes[0] = self.account_type; bytes[1..7].copy_from_slice(&self.name); bytes[7..].copy_from_slice(&self.total_supply.to_le_bytes()); - bytes.into() + bytes + .to_vec() + .try_into() + .expect("23 bytes should fit into Data") } } @@ -2258,7 +2260,10 @@ pub mod tests { bytes[0] = self.account_type; bytes[1..33].copy_from_slice(&self.definition_id.to_bytes()); bytes[33..].copy_from_slice(&self.balance.to_le_bytes()); - bytes.to_vec().try_into().expect("Data too big") + bytes + .to_vec() + .try_into() + .expect("33 bytes should fit into Data") } } @@ -2355,14 +2360,14 @@ pub mod tests { .expect("Hash output must be exactly 32 bytes long"), ) } - const POOL_DEFINITION_DATA_SIZE: usize = 225; + #[derive(Default)] struct PoolDefinition { definition_token_a_id: AccountId, definition_token_b_id: AccountId, - vault_a_addr: AccountId, - vault_b_addr: AccountId, + vault_a_id: AccountId, + vault_b_id: AccountId, liquidity_pool_id: AccountId, liquidity_pool_supply: u128, reserve_a: u128, @@ -2372,19 +2377,69 @@ pub mod tests { } impl PoolDefinition { - fn into_data(self) -> Vec { + fn into_data(self) -> Data { let mut bytes = [0; POOL_DEFINITION_DATA_SIZE]; bytes[0..32].copy_from_slice(&self.definition_token_a_id.to_bytes()); bytes[32..64].copy_from_slice(&self.definition_token_b_id.to_bytes()); - bytes[64..96].copy_from_slice(&self.vault_a_addr.to_bytes()); - bytes[96..128].copy_from_slice(&self.vault_b_addr.to_bytes()); + bytes[64..96].copy_from_slice(&self.vault_a_id.to_bytes()); + bytes[96..128].copy_from_slice(&self.vault_b_id.to_bytes()); bytes[128..160].copy_from_slice(&self.liquidity_pool_id.to_bytes()); bytes[160..176].copy_from_slice(&self.liquidity_pool_supply.to_le_bytes()); bytes[176..192].copy_from_slice(&self.reserve_a.to_le_bytes()); bytes[192..208].copy_from_slice(&self.reserve_b.to_le_bytes()); bytes[208..224].copy_from_slice(&self.fees.to_le_bytes()); bytes[224] = self.active as u8; - bytes.into() + + bytes + .to_vec() + .try_into() + .expect("225 bytes should fit into Data") + } + + fn parse(data: &[u8]) -> Option { + if data.len() != POOL_DEFINITION_DATA_SIZE { + None + } else { + let definition_token_a_id = AccountId::new(data[0..32].try_into().expect("Parse data: The AMM program must be provided a valid AccountId for Token A definition")); + let definition_token_b_id = AccountId::new(data[32..64].try_into().expect("Parse data: The AMM program must be provided a valid AccountId for Vault B definition")); + let vault_a_id = AccountId::new(data[64..96].try_into().expect( + "Parse data: The AMM program must be provided a valid AccountId for Vault A", + )); + let vault_b_id = AccountId::new(data[96..128].try_into().expect( + "Parse data: The AMM program must be provided a valid AccountId for Vault B", + )); + let liquidity_pool_id = AccountId::new(data[128..160].try_into().expect("Parse data: The AMM program must be provided a valid AccountId for Token liquidity pool definition")); + let liquidity_pool_supply = u128::from_le_bytes(data[160..176].try_into().expect( + "Parse data: The AMM program must be provided a valid u128 for liquidity cap", + )); + let reserve_a = u128::from_le_bytes(data[176..192].try_into().expect("Parse data: The AMM program must be provided a valid u128 for reserve A balance")); + let reserve_b = u128::from_le_bytes(data[192..208].try_into().expect("Parse data: The AMM program must be provided a valid u128 for reserve B balance")); + let fees = + u128::from_le_bytes(data[208..224].try_into().expect( + "Parse data: The AMM program must be provided a valid u128 for fees", + )); + + let active = match data[224] { + 0 => false, + 1 => true, + _ => panic!( + "Parse data: The AMM program must be provided a valid bool for active" + ), + }; + + Some(Self { + definition_token_a_id, + definition_token_b_id, + vault_a_id, + vault_b_id, + liquidity_pool_id, + liquidity_pool_supply, + reserve_a, + reserve_b, + fees, + active, + }) + } } } @@ -2615,8 +2670,8 @@ pub mod tests { data: PoolDefinition::into_data(PoolDefinition { definition_token_a_id: helper_id_constructor(IdEnum::TokenADefinitionId), definition_token_b_id: helper_id_constructor(IdEnum::TokenBDefinitionId), - vault_a_addr: helper_id_constructor(IdEnum::VaultAId), - vault_b_addr: helper_id_constructor(IdEnum::VaultBId), + vault_a_id: helper_id_constructor(IdEnum::VaultAId), + vault_b_id: helper_id_constructor(IdEnum::VaultBId), liquidity_pool_id: helper_id_constructor(IdEnum::TokenLPDefinitionId), liquidity_pool_supply: helper_balances_constructor( BalancesEnum::PoolLPSupplyInit, @@ -2722,8 +2777,8 @@ pub mod tests { data: PoolDefinition::into_data(PoolDefinition { definition_token_a_id: helper_id_constructor(IdEnum::TokenADefinitionId), definition_token_b_id: helper_id_constructor(IdEnum::TokenBDefinitionId), - vault_a_addr: helper_id_constructor(IdEnum::VaultAId), - vault_b_addr: helper_id_constructor(IdEnum::VaultBId), + vault_a_id: helper_id_constructor(IdEnum::VaultAId), + vault_b_id: helper_id_constructor(IdEnum::VaultBId), liquidity_pool_id: helper_id_constructor(IdEnum::TokenLPDefinitionId), liquidity_pool_supply: helper_balances_constructor( BalancesEnum::PoolLPSupplyInit, @@ -2783,8 +2838,8 @@ pub mod tests { data: PoolDefinition::into_data(PoolDefinition { definition_token_a_id: helper_id_constructor(IdEnum::TokenADefinitionId), definition_token_b_id: helper_id_constructor(IdEnum::TokenBDefinitionId), - vault_a_addr: helper_id_constructor(IdEnum::VaultAId), - vault_b_addr: helper_id_constructor(IdEnum::VaultBId), + vault_a_id: helper_id_constructor(IdEnum::VaultAId), + vault_b_id: helper_id_constructor(IdEnum::VaultBId), liquidity_pool_id: helper_id_constructor(IdEnum::TokenLPDefinitionId), liquidity_pool_supply: helper_balances_constructor( BalancesEnum::PoolLPSupplyInit, @@ -2844,8 +2899,8 @@ pub mod tests { data: PoolDefinition::into_data(PoolDefinition { definition_token_a_id: helper_id_constructor(IdEnum::TokenADefinitionId), definition_token_b_id: helper_id_constructor(IdEnum::TokenBDefinitionId), - vault_a_addr: helper_id_constructor(IdEnum::VaultAId), - vault_b_addr: helper_id_constructor(IdEnum::VaultBId), + vault_a_id: helper_id_constructor(IdEnum::VaultAId), + vault_b_id: helper_id_constructor(IdEnum::VaultBId), liquidity_pool_id: helper_id_constructor(IdEnum::TokenLPDefinitionId), liquidity_pool_supply: helper_balances_constructor( BalancesEnum::TokenLPSupplyAdd, @@ -2927,8 +2982,8 @@ pub mod tests { data: PoolDefinition::into_data(PoolDefinition { definition_token_a_id: helper_id_constructor(IdEnum::TokenADefinitionId), definition_token_b_id: helper_id_constructor(IdEnum::TokenBDefinitionId), - vault_a_addr: helper_id_constructor(IdEnum::VaultAId), - vault_b_addr: helper_id_constructor(IdEnum::VaultBId), + vault_a_id: helper_id_constructor(IdEnum::VaultAId), + vault_b_id: helper_id_constructor(IdEnum::VaultBId), liquidity_pool_id: helper_id_constructor(IdEnum::TokenLPDefinitionId), liquidity_pool_supply: helper_balances_constructor( BalancesEnum::TokenLPSupplyRemove, @@ -3022,8 +3077,8 @@ pub mod tests { data: PoolDefinition::into_data(PoolDefinition { definition_token_a_id: helper_id_constructor(IdEnum::TokenADefinitionId), definition_token_b_id: helper_id_constructor(IdEnum::TokenBDefinitionId), - vault_a_addr: helper_id_constructor(IdEnum::VaultAId), - vault_b_addr: helper_id_constructor(IdEnum::VaultBId), + vault_a_id: helper_id_constructor(IdEnum::VaultAId), + vault_b_id: helper_id_constructor(IdEnum::VaultBId), liquidity_pool_id: helper_id_constructor(IdEnum::TokenLPDefinitionId), liquidity_pool_supply: 0, reserve_a: 0, @@ -3083,8 +3138,8 @@ pub mod tests { data: PoolDefinition::into_data(PoolDefinition { definition_token_a_id: helper_id_constructor(IdEnum::TokenADefinitionId), definition_token_b_id: helper_id_constructor(IdEnum::TokenBDefinitionId), - vault_a_addr: helper_id_constructor(IdEnum::VaultAId), - vault_b_addr: helper_id_constructor(IdEnum::VaultBId), + vault_a_id: helper_id_constructor(IdEnum::VaultAId), + vault_b_id: helper_id_constructor(IdEnum::VaultBId), liquidity_pool_id: helper_id_constructor(IdEnum::TokenLPDefinitionId), liquidity_pool_supply: helper_balances_constructor( BalancesEnum::UserTokenAHoldingNewDef, diff --git a/nssa/test_program_methods/guest/Cargo.lock b/nssa/test_program_methods/guest/Cargo.lock index c7ef17a..433fab6 100644 --- a/nssa/test_program_methods/guest/Cargo.lock +++ b/nssa/test_program_methods/guest/Cargo.lock @@ -419,18 +419,18 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytemuck" -version = "1.23.1" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.8.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", diff --git a/wallet/Cargo.toml b/wallet/Cargo.toml index c93b357..3ea6cd1 100644 --- a/wallet/Cargo.toml +++ b/wallet/Cargo.toml @@ -14,7 +14,7 @@ tempfile.workspace = true clap.workspace = true nssa-core = { path = "../nssa/core" } base64.workspace = true -bytemuck = "1.23.2" +bytemuck = "1.24.0" borsh.workspace = true base58.workspace = true hex = "0.4.3"