Skip to content

Commit 5bc59f6

Browse files
authored
feat: assign addresses (#1695)
* feat: assign addresses to compressed accounts * feat: make tx hash optional * chore: bump photon commit hash
1 parent de38147 commit 5bc59f6

File tree

19 files changed

+416
-172
lines changed

19 files changed

+416
-172
lines changed

program-libs/compressed-account/src/address.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ use super::compressed_account::{
88
use crate::{
99
hash_to_bn254_field_size_be,
1010
instruction_data::data::{
11-
NewAddressParams, NewAddressParamsPacked, PackedReadOnlyAddress, ReadOnlyAddress,
11+
pack_pubkey_usize, NewAddressParams, NewAddressParamsAssigned,
12+
NewAddressParamsAssignedPacked, NewAddressParamsPacked, PackedReadOnlyAddress,
13+
ReadOnlyAddress,
1214
},
1315
CompressedAccountError, Pubkey,
1416
};
@@ -57,6 +59,31 @@ pub fn add_and_get_remaining_account_indices(
5759
vec
5860
}
5961

62+
pub fn pack_new_address_params_assigned(
63+
new_address_params: &[NewAddressParamsAssigned],
64+
remaining_accounts: &mut HashMap<Pubkey, usize>,
65+
) -> Vec<NewAddressParamsAssignedPacked> {
66+
let mut vec = Vec::new();
67+
for new_address_param in new_address_params.iter() {
68+
let address_merkle_tree_account_index = pack_pubkey_usize(
69+
&new_address_param.address_merkle_tree_pubkey,
70+
remaining_accounts,
71+
);
72+
let address_queue_account_index =
73+
pack_pubkey_usize(&new_address_param.address_queue_pubkey, remaining_accounts);
74+
vec.push(NewAddressParamsAssignedPacked {
75+
seed: new_address_param.seed,
76+
address_queue_account_index,
77+
address_merkle_tree_root_index: new_address_param.address_merkle_tree_root_index,
78+
address_merkle_tree_account_index,
79+
assigned_to_account: new_address_param.assigned_account_index.is_some(),
80+
assigned_account_index: new_address_param.assigned_account_index.unwrap_or_default(),
81+
});
82+
}
83+
84+
vec
85+
}
86+
6087
// Helper function to pack new address params for instruction data in rust clients
6188
pub fn pack_new_address_params(
6289
new_address_params: &[NewAddressParams],

program-libs/compressed-account/src/instruction_data/data.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,37 @@ pub struct NewAddressParamsPacked {
3838
pub address_merkle_tree_root_index: u16,
3939
}
4040

41+
#[derive(Debug, PartialEq, Default, Clone, Copy, AnchorDeserialize, AnchorSerialize)]
42+
pub struct NewAddressParamsAssignedPacked {
43+
pub seed: [u8; 32],
44+
pub address_queue_account_index: u8,
45+
pub address_merkle_tree_account_index: u8,
46+
pub address_merkle_tree_root_index: u16,
47+
pub assigned_to_account: bool,
48+
pub assigned_account_index: u8,
49+
}
50+
51+
impl NewAddressParamsAssignedPacked {
52+
pub fn new(address_params: NewAddressParamsPacked, index: Option<u8>) -> Self {
53+
Self {
54+
seed: address_params.seed,
55+
address_queue_account_index: address_params.address_queue_account_index,
56+
address_merkle_tree_account_index: address_params.address_merkle_tree_account_index,
57+
address_merkle_tree_root_index: address_params.address_merkle_tree_root_index,
58+
assigned_to_account: index.is_some(),
59+
assigned_account_index: index.unwrap_or_default(),
60+
}
61+
}
62+
63+
pub fn assigned_account_index(&self) -> Option<u8> {
64+
if self.assigned_to_account {
65+
Some(self.assigned_account_index)
66+
} else {
67+
None
68+
}
69+
}
70+
}
71+
4172
#[derive(Debug, PartialEq, Default, Clone, AnchorDeserialize, AnchorSerialize)]
4273
pub struct NewAddressParams {
4374
pub seed: [u8; 32],
@@ -46,6 +77,15 @@ pub struct NewAddressParams {
4677
pub address_merkle_tree_root_index: u16,
4778
}
4879

80+
#[derive(Debug, PartialEq, Default, Clone, AnchorDeserialize, AnchorSerialize)]
81+
pub struct NewAddressParamsAssigned {
82+
pub seed: [u8; 32],
83+
pub address_queue_pubkey: Pubkey,
84+
pub address_merkle_tree_pubkey: Pubkey,
85+
pub address_merkle_tree_root_index: u16,
86+
pub assigned_account_index: Option<u8>,
87+
}
88+
4989
#[derive(Debug, PartialEq, Default, Clone, Copy, AnchorDeserialize, AnchorSerialize)]
5090
pub struct PackedReadOnlyAddress {
5191
pub address: [u8; 32],
@@ -59,7 +99,7 @@ pub struct ReadOnlyAddress {
5999
pub address_merkle_tree_pubkey: Pubkey,
60100
pub address_merkle_tree_root_index: u16,
61101
}
62-
102+
// TODO: move
63103
pub fn pack_pubkey(pubkey: &Pubkey, hash_set: &mut HashMap<Pubkey, u8>) -> u8 {
64104
match hash_set.get(pubkey) {
65105
Some(index) => *index,
@@ -70,3 +110,14 @@ pub fn pack_pubkey(pubkey: &Pubkey, hash_set: &mut HashMap<Pubkey, u8>) -> u8 {
70110
}
71111
}
72112
}
113+
114+
pub fn pack_pubkey_usize(pubkey: &Pubkey, hash_set: &mut HashMap<Pubkey, usize>) -> u8 {
115+
match hash_set.get(pubkey) {
116+
Some(index) => (*index) as u8,
117+
None => {
118+
let index = hash_set.len();
119+
hash_set.insert(*pubkey, index);
120+
index as u8
121+
}
122+
}
123+
}

program-libs/compressed-account/src/instruction_data/traits.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,13 @@ use zerocopy::Ref;
55
use super::{
66
compressed_proof::CompressedProof,
77
cpi_context::CompressedCpiContext,
8-
zero_copy::{
9-
ZNewAddressParamsPacked, ZPackedMerkleContext, ZPackedReadOnlyAddress,
10-
ZPackedReadOnlyCompressedAccount,
11-
},
8+
zero_copy::{ZPackedMerkleContext, ZPackedReadOnlyAddress, ZPackedReadOnlyCompressedAccount},
129
};
1310
use crate::{compressed_account::CompressedAccountData, pubkey::Pubkey, CompressedAccountError};
1411

1512
pub trait InstructionDataTrait<'a> {
1613
fn owner(&self) -> Pubkey;
17-
fn new_addresses(&self) -> &[ZNewAddressParamsPacked];
14+
fn new_addresses(&self) -> &[impl NewAddressParamsTrait<'a>];
1815
fn input_accounts(&self) -> &[impl InputAccountTrait<'a>];
1916
fn output_accounts(&self) -> &[impl OutputAccountTrait<'a>];
2017
fn read_only_accounts(&self) -> Option<&[ZPackedReadOnlyCompressedAccount]>;
@@ -25,6 +22,18 @@ pub trait InstructionDataTrait<'a> {
2522
fn cpi_context(&self) -> Option<CompressedCpiContext>;
2623
fn bump(&self) -> Option<u8>;
2724
fn account_option_config(&self) -> AccountOptions;
25+
fn with_transaction_hash(&self) -> bool;
26+
}
27+
28+
pub trait NewAddressParamsTrait<'a>
29+
where
30+
Self: Debug,
31+
{
32+
fn seed(&self) -> [u8; 32];
33+
fn address_queue_index(&self) -> u8;
34+
fn address_merkle_tree_account_index(&self) -> u8;
35+
fn address_merkle_tree_root_index(&self) -> u16;
36+
fn assigned_compressed_account_index(&self) -> Option<usize>;
2837
}
2938

3039
pub trait InputAccountTrait<'a>

program-libs/compressed-account/src/instruction_data/with_account_info.rs

Lines changed: 20 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@ use zerocopy::{
99
use super::{
1010
compressed_proof::CompressedProof,
1111
cpi_context::CompressedCpiContext,
12-
data::{NewAddressParamsPacked, PackedReadOnlyAddress},
13-
traits::{AccountOptions, InputAccountTrait, InstructionDataTrait, OutputAccountTrait},
12+
data::{NewAddressParamsAssignedPacked, PackedReadOnlyAddress},
13+
traits::{
14+
AccountOptions, InputAccountTrait, InstructionDataTrait, NewAddressParamsTrait,
15+
OutputAccountTrait,
16+
},
17+
with_readonly::ZInstructionDataInvokeCpiWithReadOnlyMeta,
1418
zero_copy::{
15-
ZCompressedCpiContext, ZNewAddressParamsPacked, ZPackedMerkleContext,
16-
ZPackedReadOnlyAddress, ZPackedReadOnlyCompressedAccount,
19+
ZNewAddressParamsAssignedPacked, ZPackedMerkleContext, ZPackedReadOnlyAddress,
20+
ZPackedReadOnlyCompressedAccount,
1721
},
1822
};
1923
use crate::{
@@ -285,9 +289,10 @@ pub struct InstructionDataInvokeCpiWithAccountInfo {
285289
/// -> expect account decompression_recipient
286290
pub is_decompress: bool,
287291
pub with_cpi_context: bool,
292+
pub with_transaction_hash: bool,
288293
pub cpi_context: CompressedCpiContext,
289294
pub proof: Option<CompressedProof>,
290-
pub new_address_params: Vec<NewAddressParamsPacked>,
295+
pub new_address_params: Vec<NewAddressParamsAssignedPacked>,
291296
pub account_infos: Vec<CompressedAccountInfo>,
292297
pub read_only_addresses: Vec<PackedReadOnlyAddress>,
293298
pub read_only_accounts: Vec<PackedReadOnlyCompressedAccount>,
@@ -307,6 +312,10 @@ impl<'a> InstructionDataTrait<'a> for ZInstructionDataInvokeCpiWithAccountInfo<'
307312
}
308313
}
309314

315+
fn with_transaction_hash(&self) -> bool {
316+
self.meta.with_transaction_hash()
317+
}
318+
310319
fn read_only_accounts(&self) -> Option<&[ZPackedReadOnlyCompressedAccount]> {
311320
Some(self.read_only_accounts.as_slice())
312321
}
@@ -319,7 +328,7 @@ impl<'a> InstructionDataTrait<'a> for ZInstructionDataInvokeCpiWithAccountInfo<'
319328
self.meta.invoking_program_id
320329
}
321330

322-
fn new_addresses(&self) -> &[ZNewAddressParamsPacked] {
331+
fn new_addresses(&self) -> &[impl NewAddressParamsTrait<'a>] {
323332
self.new_address_params.as_slice()
324333
}
325334

@@ -360,44 +369,17 @@ impl<'a> InstructionDataTrait<'a> for ZInstructionDataInvokeCpiWithAccountInfo<'
360369
}
361370
}
362371

363-
#[repr(C)]
364-
#[derive(
365-
Debug, Default, PartialEq, Clone, Copy, FromBytes, IntoBytes, Unaligned, Immutable, KnownLayout,
366-
)]
367-
pub struct ZInstructionDataInvokeCpiWithAccountInfoMeta {
368-
/// 0 With program ids
369-
/// 1 without program ids
370-
pub mode: u8,
371-
pub bump: u8,
372-
pub invoking_program_id: Pubkey,
373-
/// If compress_or_decompress_lamports > 0 -> expect sol_pool_pda
374-
pub compress_or_decompress_lamports: U64,
375-
/// -> expect account decompression_recipient
376-
is_decompress: u8,
377-
with_cpi_context: u8,
378-
pub cpi_context: ZCompressedCpiContext,
379-
}
380-
381-
impl ZInstructionDataInvokeCpiWithAccountInfoMeta {
382-
pub fn is_decompress(&self) -> bool {
383-
self.is_decompress > 0
384-
}
385-
pub fn with_cpi_context(&self) -> bool {
386-
self.with_cpi_context > 0
387-
}
388-
}
389-
390372
pub struct ZInstructionDataInvokeCpiWithAccountInfo<'a> {
391-
meta: Ref<&'a [u8], ZInstructionDataInvokeCpiWithAccountInfoMeta>,
373+
meta: Ref<&'a [u8], ZInstructionDataInvokeCpiWithReadOnlyMeta>,
392374
pub proof: Option<Ref<&'a [u8], CompressedProof>>,
393-
pub new_address_params: ZeroCopySliceBorsh<'a, ZNewAddressParamsPacked>,
375+
pub new_address_params: ZeroCopySliceBorsh<'a, ZNewAddressParamsAssignedPacked>,
394376
pub account_infos: Vec<ZCAccountInfo<'a>>,
395377
pub read_only_addresses: ZeroCopySliceBorsh<'a, ZPackedReadOnlyAddress>,
396378
pub read_only_accounts: ZeroCopySliceBorsh<'a, ZPackedReadOnlyCompressedAccount>,
397379
}
398380

399381
impl<'a> Deref for ZInstructionDataInvokeCpiWithAccountInfo<'a> {
400-
type Target = Ref<&'a [u8], ZInstructionDataInvokeCpiWithAccountInfoMeta>;
382+
type Target = Ref<&'a [u8], ZInstructionDataInvokeCpiWithReadOnlyMeta>;
401383

402384
fn deref(&self) -> &Self::Target {
403385
&self.meta
@@ -408,10 +390,10 @@ impl<'a> Deserialize<'a> for InstructionDataInvokeCpiWithAccountInfo {
408390
type Output = ZInstructionDataInvokeCpiWithAccountInfo<'a>;
409391
fn zero_copy_at(bytes: &'a [u8]) -> Result<(Self::Output, &'a [u8]), ZeroCopyError> {
410392
let (meta, bytes) =
411-
Ref::<&[u8], ZInstructionDataInvokeCpiWithAccountInfoMeta>::from_prefix(bytes)?;
393+
Ref::<&[u8], ZInstructionDataInvokeCpiWithReadOnlyMeta>::from_prefix(bytes)?;
412394
let (proof, bytes) = Option::<Ref<&[u8], CompressedProof>>::zero_copy_at(bytes)?;
413395
let (new_address_params, bytes) =
414-
ZeroCopySliceBorsh::<'a, ZNewAddressParamsPacked>::from_bytes_at(bytes)?;
396+
ZeroCopySliceBorsh::<'a, ZNewAddressParamsAssignedPacked>::from_bytes_at(bytes)?;
415397
let (account_infos, bytes) = {
416398
let (num_slices, mut bytes) = Ref::<&[u8], U32>::from_prefix(bytes)?;
417399
let num_slices = u32::from(*num_slices) as usize;

program-libs/compressed-account/src/instruction_data/with_readonly.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ use super::{
1010
compressed_proof::CompressedProof,
1111
cpi_context::CompressedCpiContext,
1212
data::{
13-
NewAddressParamsPacked, OutputCompressedAccountWithPackedContext, PackedReadOnlyAddress,
13+
NewAddressParamsAssignedPacked, OutputCompressedAccountWithPackedContext,
14+
PackedReadOnlyAddress,
1415
},
15-
traits::{AccountOptions, InputAccountTrait, InstructionDataTrait},
16+
traits::{AccountOptions, InputAccountTrait, InstructionDataTrait, NewAddressParamsTrait},
1617
zero_copy::{
17-
ZCompressedCpiContext, ZNewAddressParamsPacked, ZOutputCompressedAccountWithPackedContext,
18-
ZPackedMerkleContext, ZPackedReadOnlyAddress, ZPackedReadOnlyCompressedAccount,
18+
ZCompressedCpiContext, ZNewAddressParamsAssignedPacked,
19+
ZOutputCompressedAccountWithPackedContext, ZPackedMerkleContext, ZPackedReadOnlyAddress,
20+
ZPackedReadOnlyCompressedAccount,
1921
},
2022
};
2123
use crate::{
@@ -199,9 +201,10 @@ pub struct InstructionDataInvokeCpiWithReadOnly {
199201
/// -> expect account decompression_recipient
200202
pub is_decompress: bool,
201203
pub with_cpi_context: bool,
204+
pub with_transaction_hash: bool,
202205
pub cpi_context: CompressedCpiContext,
203206
pub proof: Option<CompressedProof>,
204-
pub new_address_params: Vec<NewAddressParamsPacked>,
207+
pub new_address_params: Vec<NewAddressParamsAssignedPacked>,
205208
pub input_compressed_accounts: Vec<InAccount>,
206209
pub output_compressed_accounts: Vec<OutputCompressedAccountWithPackedContext>,
207210
pub read_only_addresses: Vec<PackedReadOnlyAddress>,
@@ -223,6 +226,7 @@ pub struct ZInstructionDataInvokeCpiWithReadOnlyMeta {
223226
/// -> expect account decompression_recipient
224227
is_decompress: u8,
225228
with_cpi_context: u8,
229+
with_transaction_hash: u8,
226230
pub cpi_context: ZCompressedCpiContext,
227231
}
228232

@@ -233,13 +237,16 @@ impl ZInstructionDataInvokeCpiWithReadOnlyMeta {
233237
pub fn with_cpi_context(&self) -> bool {
234238
self.with_cpi_context > 0
235239
}
240+
pub fn with_transaction_hash(&self) -> bool {
241+
self.with_transaction_hash > 0
242+
}
236243
}
237244

238245
#[derive(Debug, PartialEq)]
239246
pub struct ZInstructionDataInvokeCpiWithReadOnly<'a> {
240247
meta: Ref<&'a [u8], ZInstructionDataInvokeCpiWithReadOnlyMeta>,
241248
pub proof: Option<Ref<&'a [u8], CompressedProof>>,
242-
pub new_address_params: ZeroCopySliceBorsh<'a, ZNewAddressParamsPacked>,
249+
pub new_address_params: ZeroCopySliceBorsh<'a, ZNewAddressParamsAssignedPacked>,
243250
pub input_compressed_accounts: Vec<ZInAccount<'a>>,
244251
pub output_compressed_accounts: Vec<ZOutputCompressedAccountWithPackedContext<'a>>,
245252
pub read_only_addresses: ZeroCopySliceBorsh<'a, ZPackedReadOnlyAddress>,
@@ -256,6 +263,10 @@ impl<'a> InstructionDataTrait<'a> for ZInstructionDataInvokeCpiWithReadOnly<'a>
256263
}
257264
}
258265

266+
fn with_transaction_hash(&self) -> bool {
267+
self.meta.with_transaction_hash()
268+
}
269+
259270
fn bump(&self) -> Option<u8> {
260271
Some(self.bump)
261272
}
@@ -271,7 +282,7 @@ impl<'a> InstructionDataTrait<'a> for ZInstructionDataInvokeCpiWithReadOnly<'a>
271282
self.meta.invoking_program_id
272283
}
273284

274-
fn new_addresses(&self) -> &[ZNewAddressParamsPacked] {
285+
fn new_addresses(&self) -> &[impl NewAddressParamsTrait<'a>] {
275286
self.new_address_params.as_slice()
276287
}
277288

@@ -328,7 +339,7 @@ impl<'a> Deserialize<'a> for InstructionDataInvokeCpiWithReadOnly {
328339
Ref::<&[u8], ZInstructionDataInvokeCpiWithReadOnlyMeta>::from_prefix(bytes)?;
329340
let (proof, bytes) = Option::<Ref<&[u8], CompressedProof>>::zero_copy_at(bytes)?;
330341
let (new_address_params, bytes) =
331-
ZeroCopySliceBorsh::<'a, ZNewAddressParamsPacked>::from_bytes_at(bytes)?;
342+
ZeroCopySliceBorsh::<'a, ZNewAddressParamsAssignedPacked>::from_bytes_at(bytes)?;
332343
let (input_compressed_accounts, bytes) = {
333344
let (num_slices, mut bytes) = Ref::<&[u8], U32>::from_prefix(bytes)?;
334345
let num_slices = u32::from(*num_slices) as usize;
@@ -417,6 +428,7 @@ impl PartialEq<InstructionDataInvokeCpiWithReadOnly> for ZInstructionDataInvokeC
417428
}
418429
}
419430

431+
// TODO: add randomized tests.
420432
#[test]
421433
fn test_read_only_zero_copy() {
422434
let borsh_struct = InstructionDataInvokeCpiWithReadOnly {
@@ -426,17 +438,20 @@ fn test_read_only_zero_copy() {
426438
compress_or_decompress_lamports: 0,
427439
is_decompress: false,
428440
with_cpi_context: false,
441+
with_transaction_hash: true,
429442
cpi_context: CompressedCpiContext {
430443
set_context: false,
431444
first_set_context: false,
432445
cpi_context_account_index: 0,
433446
},
434447
proof: None,
435-
new_address_params: vec![NewAddressParamsPacked {
448+
new_address_params: vec![NewAddressParamsAssignedPacked {
436449
seed: [1; 32],
437450
address_merkle_tree_account_index: 1,
438451
address_queue_account_index: 2,
439452
address_merkle_tree_root_index: 3,
453+
assigned_to_account: true,
454+
assigned_account_index: 2,
440455
}],
441456
input_compressed_accounts: vec![InAccount {
442457
discriminator: [1, 2, 3, 4, 5, 6, 7, 8],

0 commit comments

Comments
 (0)