Skip to content

Commit 40b0b59

Browse files
wip
1 parent f6d032a commit 40b0b59

File tree

2 files changed

+83
-136
lines changed

2 files changed

+83
-136
lines changed

create-and-update/programs/create-and-update/src/lib.rs

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
#![allow(deprecated)]
33

44
use anchor_lang::{prelude::*, AnchorDeserialize, AnchorSerialize};
5-
use borsh::{BorshDeserialize, BorshSerialize};
5+
use borsh::BorshSerialize;
66
use light_sdk::{
77
account::LightAccount,
88
address::v2::derive_address,
99
cpi::{v2::CpiAccounts, CpiSigner},
1010
derive_light_cpi_signer,
1111
instruction::{account_meta::CompressedAccountMeta, PackedAddressTreeInfo, ValidityProof},
12-
LightDiscriminator, LightHasher,
12+
LightDiscriminator,
1313
};
1414

1515
declare_id!("J6K7nvoVpJHfH13zn47vptnZo1JdUGCGSiVmtfkzz9NA");
@@ -45,16 +45,11 @@ pub mod create_and_update {
4545
let address_tree_pubkey = address_tree_info
4646
.get_tree_pubkey(&light_cpi_accounts)
4747
.map_err(|_| ErrorCode::AccountNotEnoughKeys)?;
48-
msg!("address_tree_pubkey: {:?}", address_tree_pubkey);
4948
let (address, address_seed) = derive_address(
5049
&[FIRST_SEED, ctx.accounts.signer.key().as_ref()],
5150
&address_tree_pubkey,
5251
&crate::ID,
5352
);
54-
msg!("first_seed: {:?}", FIRST_SEED);
55-
msg!("signer_key: {:?}", ctx.accounts.signer.key().to_bytes());
56-
msg!("address: {:?}", address);
57-
msg!("address_seed: {:?}", address_seed);
5853

5954
let mut data_account = LightAccount::<DataAccount>::new_init(
6055
&crate::ID,
@@ -64,16 +59,7 @@ pub mod create_and_update {
6459

6560
data_account.owner = ctx.accounts.signer.key();
6661
data_account.message = message;
67-
msg!(
68-
"Created compressed account with message: {}",
69-
data_account.message
70-
);
71-
msg!("packed_address_tree_info: {:?}", address_tree_info);
72-
msg!("output_state_tree_index: {:?}", output_state_tree_index);
73-
msg!(
74-
"light_cpi_accounts.tree_accounts: {:?}",
75-
light_cpi_accounts.tree_accounts()
76-
);
62+
7763
LightSystemProgramCpi::new_cpi(LIGHT_CPI_SIGNER, proof)
7864
.with_light_account(data_account)?
7965
.with_new_addresses(&[
@@ -97,16 +83,25 @@ pub mod create_and_update {
9783
crate::LIGHT_CPI_SIGNER,
9884
);
9985

86+
let new_account_address_tree_pubkey = &new_account
87+
.address_tree_info
88+
.get_tree_pubkey(&light_cpi_accounts)
89+
.map_err(|_| ErrorCode::AccountNotEnoughKeys)?;
90+
91+
msg!(
92+
"new_account_address_tree_pubkey: {:?}",
93+
new_account_address_tree_pubkey
94+
);
10095
// Create new compressed account
10196
let (new_address, new_address_seed) = derive_address(
10297
&[SECOND_SEED, ctx.accounts.signer.key().as_ref()],
103-
&new_account
104-
.address_tree_info
105-
.get_tree_pubkey(&light_cpi_accounts)
106-
.map_err(|_| ErrorCode::AccountNotEnoughKeys)?,
98+
new_account_address_tree_pubkey,
10799
&crate::ID,
108100
);
109101

102+
msg!("new_address: {:?}", new_address);
103+
msg!("new_address_seed: {:?}", new_address_seed);
104+
110105
let mut new_data_account = LightAccount::<DataAccount>::new_init(
111106
&crate::ID,
112107
Some(new_address),
@@ -273,21 +268,16 @@ pub struct GenericAnchorAccounts<'info> {
273268
pub signer: Signer<'info>,
274269
}
275270

276-
#[derive(
277-
Clone, Debug, Default, BorshSerialize, BorshDeserialize, LightDiscriminator, LightHasher,
278-
)]
271+
// #[derive(Debug, Default, BorshSerialize, BorshDeserialize, LightDiscriminator, LightHasher)]
272+
#[derive(Clone, LightDiscriminator, Default, AnchorDeserialize, AnchorSerialize)]
273+
// #[account]
279274
pub struct DataAccount {
280-
#[hash]
281275
pub owner: Pubkey,
282-
#[hash]
283276
pub message: String,
284277
}
285278

286-
#[derive(
287-
Clone, Debug, Default, BorshSerialize, BorshDeserialize, LightDiscriminator, LightHasher,
288-
)]
279+
#[derive(Clone, LightDiscriminator, Default, AnchorDeserialize, AnchorSerialize)]
289280
pub struct ByteDataAccount {
290-
#[hash]
291281
pub owner: Pubkey,
292282
pub data: [u8; 31],
293283
}
@@ -304,3 +294,10 @@ pub struct NewCompressedAccountIxData {
304294
pub address_tree_info: PackedAddressTreeInfo,
305295
pub message: String,
306296
}
297+
298+
// for idl generation.
299+
#[event]
300+
pub struct AccountTypes {
301+
pub data_account: DataAccount,
302+
pub byte_data_account: ByteDataAccount,
303+
}

create-and-update/tests/create_and_update.ts

Lines changed: 56 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,26 @@ import {
66
CompressedAccountWithMerkleContext,
77
confirmTx,
88
createRpc,
9-
defaultTestStateTreeAccounts,
10-
deriveAddress,
11-
deriveAddressSeed,
129
featureFlags,
1310
PackedAccounts,
1411
Rpc,
1512
sleep,
1613
SystemAccountMetaConfig,
17-
getLightSystemAccountMetasV2,
1814
VERSION,
1915
selectStateTreeInfo,
20-
getDefaultAddressTreeInfo,
21-
AddressTreeInfo,
2216
TreeInfo,
23-
packTreeInfos,
2417
PackedAddressTreeInfo,
2518
deriveAddressV2,
2619
deriveAddressSeedV2,
2720
buildAndSignTx,
2821
sendAndConfirmTx,
2922
} from "@lightprotocol/stateless.js";
3023
import * as assert from "assert";
31-
3224
const path = require("path");
3325
const os = require("os");
3426
require("dotenv").config();
35-
// set to V2 explicitly.
27+
28+
// v2 feature flag
3629
featureFlags.version = VERSION.V2;
3730

3831
const anchorWalletPath = path.join(os.homedir(), ".config/solana/id.json");
@@ -59,12 +52,11 @@ describe("create-and-update anchor", () => {
5952
// get tree infos
6053
const stateTreeInfos = await rpc.getStateTreeInfos();
6154
const stateTreeInfo = selectStateTreeInfo(stateTreeInfos);
62-
const addressTreeInfo = getDefaultAddressTreeInfo();
63-
console.log("addressTreeInfo", addressTreeInfo);
64-
65-
const firstSeed = new TextEncoder().encode("first");
6655

56+
// v2 address tree info
57+
const addressTreeInfo = await rpc.getAddressTreeInfoV2();
6758
// v2 derive
59+
const firstSeed = new TextEncoder().encode("first");
6860
const firstAddressSeed = deriveAddressSeedV2([
6961
firstSeed,
7062
signer.publicKey.toBytes(),
@@ -74,8 +66,6 @@ describe("create-and-update anchor", () => {
7466
addressTreeInfo.tree,
7567
program.programId
7668
);
77-
console.log("firstAddressSeed", Array.from(firstAddressSeed));
78-
console.log("firstAddress", Array.from(firstAddress.toBytes()));
7969

8070
await createCompressedAccount(
8171
rpc,
@@ -87,95 +77,45 @@ describe("create-and-update anchor", () => {
8777
"Initial message"
8878
);
8979

90-
// await waitForIndexer(rpc);
91-
9280
let firstAccount = await rpc.getCompressedAccount(
9381
bn(firstAddress.toBytes())
9482
);
9583
if (!firstAccount) {
9684
throw new Error("Failed to fetch the initial compressed account");
9785
}
9886

99-
let decoded = coder.types.decode("DataAccount", firstAccount.data.data);
87+
let decoded = coder.types.decode("dataAccount", firstAccount.data.data);
10088
assert.ok(
10189
decoded.owner.equals(signer.publicKey),
10290
"owner should match signer"
10391
);
10492
assert.strictEqual(decoded.message, "Initial message");
10593

106-
// await createAndUpdateAccounts(
107-
// rpc,
108-
// program,
109-
// signer,
110-
// firstAccount,
111-
// secondAddress,
112-
// addressTree,
113-
// addressQueue,
114-
// outputStateTree,
115-
// "Initial message",
116-
// "Hello from second account",
117-
// "Updated first message"
118-
// );
119-
120-
// await waitForIndexer(rpc);
121-
122-
// firstAccount = await rpc.getCompressedAccount(bn(initialAddress.toBytes()));
123-
// if (!firstAccount) {
124-
// throw new Error("Initial account missing after create_and_update");
125-
// }
126-
// decoded = coder.types.decode("DataAccount", firstAccount.data.data);
127-
// assert.strictEqual(decoded.message, "Updated first message");
128-
129-
// let secondAccount = await rpc.getCompressedAccount(
130-
// bn(secondAddress.toBytes())
131-
// );
132-
// if (!secondAccount) {
133-
// throw new Error("Failed to fetch the second compressed account");
134-
// }
135-
// let secondDecoded = coder.types.decode(
136-
// "DataAccount",
137-
// secondAccount.data.data
138-
// );
139-
// assert.strictEqual(secondDecoded.message, "Hello from second account");
140-
// assert.ok(
141-
// secondDecoded.owner.equals(signer.publicKey),
142-
// "new account owner should match signer"
143-
// );
144-
145-
// await updateTwoExistingAccounts(
146-
// rpc,
147-
// program,
148-
// signer,
149-
// firstAccount,
150-
// secondAccount,
151-
// outputStateTree,
152-
// "Updated first message",
153-
// "First account final message",
154-
// "Hello from second account",
155-
// "Second account final message"
156-
// );
157-
158-
// await waitForIndexer(rpc);
159-
160-
// firstAccount = await rpc.getCompressedAccount(bn(initialAddress.toBytes()));
161-
// secondAccount = await rpc.getCompressedAccount(bn(secondAddress.toBytes()));
162-
// if (!firstAccount || !secondAccount) {
163-
// throw new Error(
164-
// "One of the accounts is missing after update_two_accounts"
165-
// );
166-
// }
167-
168-
// decoded = coder.types.decode("DataAccount", firstAccount.data.data);
169-
// secondDecoded = coder.types.decode("DataAccount", secondAccount.data.data);
94+
// Derive second address
95+
const secondSeed = new TextEncoder().encode("second");
96+
const secondAddressSeed = deriveAddressSeedV2([
97+
secondSeed,
98+
signer.publicKey.toBytes(),
99+
]);
100+
const secondAddress = deriveAddressV2(
101+
secondAddressSeed,
102+
addressTreeInfo.tree,
103+
program.programId
104+
);
105+
console.log("secondAddress", Array.from(secondAddress.toBytes()));
106+
console.log("secondAddressSeed", Array.from(secondAddressSeed));
170107

171-
// assert.strictEqual(decoded.message, "First account final message");
172-
// assert.strictEqual(secondDecoded.message, "Second account final message");
173-
// assert.ok(
174-
// decoded.owner.equals(signer.publicKey) &&
175-
// secondDecoded.owner.equals(signer.publicKey),
176-
// "owners should remain the signer"
177-
// );
178-
// });
108+
await createAndUpdateAccounts(
109+
rpc,
110+
program,
111+
signer,
112+
firstAccount,
113+
secondAddress,
114+
addressTreeInfo,
115+
"Initial message",
116+
"Hello from second account",
117+
"Updated first message"
118+
);
179119
});
180120

181121
async function waitForIndexer(rpc: Rpc) {
@@ -256,9 +196,7 @@ describe("create-and-update anchor", () => {
256196
signer: anchor.web3.Keypair,
257197
existingAccount: CompressedAccountWithMerkleContext,
258198
newAddress: anchor.web3.PublicKey,
259-
addressTree: anchor.web3.PublicKey,
260-
addressQueue: anchor.web3.PublicKey,
261-
outputStateTree: anchor.web3.PublicKey,
199+
addressTreeInfo: TreeInfo,
262200
existingMessage: string,
263201
newAccountMessage: string,
264202
updatedMessage: string
@@ -275,23 +213,30 @@ describe("create-and-update anchor", () => {
275213
queue: existingAccount.treeInfo.queue,
276214
},
277215
],
216+
// new account's address
278217
[
279218
{
280-
tree: addressTree,
281-
queue: addressQueue,
219+
tree: addressTreeInfo.tree,
220+
queue: addressTreeInfo.queue,
282221
address: bn(newAddress.toBytes()),
283222
},
284223
]
285224
);
225+
226+
console.log("existing hash", existingAccount.hash.toArray());
227+
286228
const config = SystemAccountMetaConfig.new(program.programId);
287229
const packedAccounts = PackedAccounts.newWithSystemAccountsV2(config);
230+
231+
const existingQueueIndex = packedAccounts.insertOrGet(
232+
existingAccount.treeInfo.queue
233+
);
288234
const existingMerkleTreeIndex = packedAccounts.insertOrGet(
289235
existingAccount.treeInfo.tree
290236
);
291-
const existingQueueIndex = packedAccounts.insertOrGet(
237+
const outputStateTreeIndex = packedAccounts.insertOrGet(
292238
existingAccount.treeInfo.queue
293239
);
294-
const outputStateTreeIndex = packedAccounts.insertOrGet(outputStateTree);
295240

296241
const existingAccountMeta = {
297242
treeInfo: {
@@ -305,10 +250,12 @@ describe("create-and-update anchor", () => {
305250
outputStateTreeIndex,
306251
};
307252

308-
const packedAddressTreeInfo = {
253+
const addressQueueIndex = packedAccounts.insertOrGet(addressTreeInfo.queue);
254+
const addressTreeIndex = packedAccounts.insertOrGet(addressTreeInfo.tree);
255+
const packedAddressTreeInfo: PackedAddressTreeInfo = {
309256
rootIndex: proofRpcResult.rootIndices[1],
310-
addressMerkleTreePubkeyIndex: packedAccounts.insertOrGet(addressTree),
311-
addressQueuePubkeyIndex: packedAccounts.insertOrGet(addressQueue),
257+
addressMerkleTreePubkeyIndex: addressTreeIndex,
258+
addressQueuePubkeyIndex: addressQueueIndex,
312259
};
313260

314261
const proof = {
@@ -318,6 +265,10 @@ describe("create-and-update anchor", () => {
318265
units: 1000000,
319266
});
320267

268+
const remainingAccounts = packedAccounts.toAccountMetas().remainingAccounts;
269+
for (const account of remainingAccounts) {
270+
console.log("remainingAccount", account.pubkey.toBase58());
271+
}
321272
const tx = await program.methods
322273
.createAndUpdate(
323274
proof,
@@ -335,15 +286,14 @@ describe("create-and-update anchor", () => {
335286
signer: signer.publicKey,
336287
})
337288
.preInstructions([computeBudgetIx])
338-
.remainingAccounts(packedAccounts.toAccountMetas().remainingAccounts)
289+
.remainingAccounts(remainingAccounts)
339290
.signers([signer])
340291
.transaction();
341292

342-
tx.recentBlockhash = (await rpc.getRecentBlockhash()).blockhash;
343-
tx.sign(signer);
344-
345-
const sig = await rpc.sendTransaction(tx, [signer]);
346-
await confirmTx(rpc, sig);
293+
const recentBlockhash = (await rpc.getRecentBlockhash()).blockhash;
294+
const signedTx = buildAndSignTx(tx.instructions, signer, recentBlockhash);
295+
const sig = await sendAndConfirmTx(rpc, signedTx, { skipPreflight: false });
296+
console.log("createAndUpdate sig", sig);
347297
return sig;
348298
}
349299
});

0 commit comments

Comments
 (0)