Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 95194c3

Browse files
committed
add support for reading proofs from record program
1 parent 3a260d6 commit 95194c3

File tree

7 files changed

+233
-78
lines changed

7 files changed

+233
-78
lines changed

token/program-2022/Cargo.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@ bytemuck = { version = "1.16.1", features = ["derive"] }
2222
num-derive = "0.4"
2323
num-traits = "0.2"
2424
num_enum = "0.7.2"
25-
solana-program = "2.0.0"
25+
solana-program = "2.1.0"
2626
solana-security-txt = "1.1.1"
27-
solana-zk-token-sdk = "2.0.0"
27+
solana-zk-token-sdk = "2.1.0"
2828
spl-memo = { version = "5.0", path = "../../memo/program", features = [ "no-entrypoint" ] }
29+
spl-record = { version = "0.2.0", path = "../../record/program", features = [ "no-entrypoint" ]}
2930
spl-token = { version = "6.0", path = "../program", features = ["no-entrypoint"] }
3031
spl-token-group-interface = { version = "0.3.0", path = "../../token-group/interface" }
3132
spl-token-metadata-interface = { version = "0.4.0", path = "../../token-metadata/interface" }
@@ -41,8 +42,8 @@ base64 = { version = "0.22.1", optional = true }
4142
lazy_static = "1.5.0"
4243
proptest = "1.5"
4344
serial_test = "3.1.1"
44-
solana-program-test = "2.0.0"
45-
solana-sdk = "2.0.0"
45+
solana-program-test = "2.1.0"
46+
solana-sdk = "2.1.0"
4647
spl-tlv-account-resolution = { version = "0.7.0", path = "../../libraries/tlv-account-resolution" }
4748
serde_json = "1.0.120"
4849

token/program-2022/src/extension/confidential_transfer/instruction.rs

Lines changed: 85 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use {
1313
check_program_account,
1414
extension::confidential_transfer::{ciphertext_extraction::SourceDecryptHandles, *},
1515
instruction::{encode_instruction, TokenInstruction},
16-
proof::ProofLocation,
16+
proof::{ProofData, ProofLocation},
1717
},
1818
bytemuck::Zeroable, // `Pod` comes from zk_token_proof_instruction
1919
num_enum::{IntoPrimitive, TryFromPrimitive},
@@ -90,7 +90,9 @@ pub enum ConfidentialTransferInstruction {
9090
/// in the same transaction or context state account if
9191
/// `VerifyPubkeyValidityProof` is pre-verified into a context state
9292
/// account.
93-
/// 3. `[signer]` The single source account owner.
93+
/// 3. `[]` (Optional) Record account if the accompanying proof is to be
94+
/// read from a record account.
95+
/// 4. `[signer]` The single source account owner.
9496
///
9597
/// * Multisignature owner/delegate
9698
/// 0. `[writeable]` The SPL Token account.
@@ -99,8 +101,10 @@ pub enum ConfidentialTransferInstruction {
99101
/// in the same transaction or context state account if
100102
/// `VerifyPubkeyValidityProof` is pre-verified into a context state
101103
/// account.
102-
/// 3. `[]` The multisig source account owner.
103-
/// 4.. `[signer]` Required M signer accounts for the SPL Token Multisig
104+
/// 3. `[]` (Optional) Record account if the accompanying proof is to be
105+
/// read from a record account.
106+
/// 4. `[]` The multisig source account owner.
107+
/// 5.. `[signer]` Required M signer accounts for the SPL Token Multisig
104108
/// account.
105109
///
106110
/// Data expected by this instruction:
@@ -151,16 +155,20 @@ pub enum ConfidentialTransferInstruction {
151155
/// the same transaction or context state account if
152156
/// `VerifyZeroBalanceProof` is pre-verified into a context state
153157
/// account.
154-
/// 2. `[signer]` The single account owner.
158+
/// 2. `[]` (Optional) Record account if the accompanying proof is to be
159+
/// read from a record account.
160+
/// 3. `[signer]` The single account owner.
155161
///
156162
/// * Multisignature owner/delegate
157163
/// 0. `[writable]` The SPL Token account.
158164
/// 1. `[]` Instructions sysvar if `VerifyZeroBalanceProof` is included in
159165
/// the same transaction or context state account if
160166
/// `VerifyZeroBalanceProof` is pre-verified into a context state
161167
/// account.
162-
/// 2. `[]` The multisig account owner.
163-
/// 3.. `[signer]` Required M signer accounts for the SPL Token Multisig
168+
/// 2. `[]` (Optional) Record account if the accompanying proof is to be
169+
/// read from a record account.
170+
/// 3. `[]` The multisig account owner.
171+
/// 4.. `[signer]` Required M signer accounts for the SPL Token Multisig
164172
/// account.
165173
///
166174
/// Data expected by this instruction:
@@ -214,16 +222,20 @@ pub enum ConfidentialTransferInstruction {
214222
/// 2. `[]` Instructions sysvar if `VerifyWithdraw` is included in the
215223
/// same transaction or context state account if `VerifyWithdraw` is
216224
/// pre-verified into a context state account.
217-
/// 3. `[signer]` The single source account owner.
225+
/// 3. `[]` (Optional) Record account if the accompanying proof is to be
226+
/// read from a record account.
227+
/// 4. `[signer]` The single source account owner.
218228
///
219229
/// * Multisignature owner/delegate
220230
/// 0. `[writable]` The SPL Token account.
221231
/// 1. `[]` The token mint.
222232
/// 2. `[]` Instructions sysvar if `VerifyWithdraw` is included in the
223233
/// same transaction or context state account if `VerifyWithdraw` is
224234
/// pre-verified into a context state account.
225-
/// 3. `[]` The multisig source account owner.
226-
/// 4.. `[signer]` Required M signer accounts for the SPL Token Multisig
235+
/// 3. `[]` (Optional) Record account if the accompanying proof is to be
236+
/// read from a record account.
237+
/// 4. `[]` The multisig source account owner.
238+
/// 5.. `[signer]` Required M signer accounts for the SPL Token Multisig
227239
/// account.
228240
///
229241
/// Data expected by this instruction:
@@ -248,7 +260,9 @@ pub enum ConfidentialTransferInstruction {
248260
/// `VerifyTransferWithFee` is included in the same transaction or
249261
/// context state account if these proofs are pre-verified into a
250262
/// context state account.
251-
/// 5. `[signer]` The single source account owner.
263+
/// 5. `[]` (Optional) Record account if the accompanying proof is to be
264+
/// read from a record account.
265+
/// 6. `[signer]` The single source account owner.
252266
///
253267
/// * Multisignature owner/delegate
254268
/// 1. `[writable]` The source SPL Token account.
@@ -258,8 +272,10 @@ pub enum ConfidentialTransferInstruction {
258272
/// `VerifyTransferWithFee` is included in the same transaction or
259273
/// context state account if these proofs are pre-verified into a
260274
/// context state account.
261-
/// 5. `[]` The multisig source account owner.
262-
/// 6.. `[signer]` Required M signer accounts for the SPL Token Multisig
275+
/// 5. `[]` (Optional) Record account if the accompanying proof is to be
276+
/// read from a record account.
277+
/// 6. `[]` The multisig source account owner.
278+
/// 7.. `[signer]` Required M signer accounts for the SPL Token Multisig
263279
/// account.
264280
///
265281
/// Data expected by this instruction:
@@ -715,8 +731,11 @@ pub fn inner_configure_account(
715731
];
716732

717733
let proof_instruction_offset = match proof_data_location {
718-
ProofLocation::InstructionOffset(proof_instruction_offset, _) => {
734+
ProofLocation::InstructionOffset(proof_instruction_offset, proof_data) => {
719735
accounts.push(AccountMeta::new_readonly(sysvar::instructions::id(), false));
736+
if let ProofData::RecordAccount(record_address, _) = proof_data {
737+
accounts.push(AccountMeta::new_readonly(*record_address, false));
738+
}
720739
proof_instruction_offset.into()
721740
}
722741
ProofLocation::ContextStateAccount(context_state_account) => {
@@ -781,8 +800,14 @@ pub fn configure_account(
781800
if proof_instruction_offset != 1 {
782801
return Err(TokenError::InvalidProofInstructionOffset.into());
783802
}
784-
instructions.push(verify_pubkey_validity(None, proof_data));
785-
};
803+
match proof_data {
804+
ProofData::ProofData(data) => instructions.push(verify_pubkey_validity(None, data)),
805+
ProofData::RecordAccount(address, offset) => instructions.push(
806+
ProofInstruction::VerifyPubkeyValidity
807+
.encode_verify_proof_from_account(None, address, offset),
808+
),
809+
};
810+
}
786811

787812
Ok(instructions)
788813
}
@@ -827,8 +852,11 @@ pub fn inner_empty_account(
827852
let mut accounts = vec![AccountMeta::new(*token_account, false)];
828853

829854
let proof_instruction_offset = match proof_data_location {
830-
ProofLocation::InstructionOffset(proof_instruction_offset, _) => {
855+
ProofLocation::InstructionOffset(proof_instruction_offset, proof_data) => {
831856
accounts.push(AccountMeta::new_readonly(sysvar::instructions::id(), false));
857+
if let ProofData::RecordAccount(record_address, _) = proof_data {
858+
accounts.push(AccountMeta::new_readonly(*record_address, false));
859+
}
832860
proof_instruction_offset.into()
833861
}
834862
ProofLocation::ContextStateAccount(context_state_account) => {
@@ -884,7 +912,13 @@ pub fn empty_account(
884912
if proof_instruction_offset != 1 {
885913
return Err(TokenError::InvalidProofInstructionOffset.into());
886914
}
887-
instructions.push(verify_zero_balance(None, proof_data));
915+
match proof_data {
916+
ProofData::ProofData(data) => instructions.push(verify_zero_balance(None, data)),
917+
ProofData::RecordAccount(address, offset) => instructions.push(
918+
ProofInstruction::VerifyZeroBalance
919+
.encode_verify_proof_from_account(None, address, offset),
920+
),
921+
};
888922
};
889923

890924
Ok(instructions)
@@ -946,8 +980,11 @@ pub fn inner_withdraw(
946980
];
947981

948982
let proof_instruction_offset = match proof_data_location {
949-
ProofLocation::InstructionOffset(proof_instruction_offset, _) => {
983+
ProofLocation::InstructionOffset(proof_instruction_offset, proof_data) => {
950984
accounts.push(AccountMeta::new_readonly(sysvar::instructions::id(), false));
985+
if let ProofData::RecordAccount(record_address, _) = proof_data {
986+
accounts.push(AccountMeta::new_readonly(*record_address, false));
987+
}
951988
proof_instruction_offset.into()
952989
}
953990
ProofLocation::ContextStateAccount(context_state_account) => {
@@ -1015,7 +1052,13 @@ pub fn withdraw(
10151052
if proof_instruction_offset != 1 {
10161053
return Err(TokenError::InvalidProofInstructionOffset.into());
10171054
}
1018-
instructions.push(verify_withdraw(None, proof_data));
1055+
match proof_data {
1056+
ProofData::ProofData(data) => instructions.push(verify_withdraw(None, data)),
1057+
ProofData::RecordAccount(address, offset) => instructions.push(
1058+
ProofInstruction::VerifyWithdraw
1059+
.encode_verify_proof_from_account(None, address, offset),
1060+
),
1061+
};
10191062
};
10201063

10211064
Ok(instructions)
@@ -1043,8 +1086,11 @@ pub fn inner_transfer(
10431086
];
10441087

10451088
let proof_instruction_offset = match proof_data_location {
1046-
ProofLocation::InstructionOffset(proof_instruction_offset, _) => {
1089+
ProofLocation::InstructionOffset(proof_instruction_offset, proof_data) => {
10471090
accounts.push(AccountMeta::new_readonly(sysvar::instructions::id(), false));
1091+
if let ProofData::RecordAccount(record_address, _) = proof_data {
1092+
accounts.push(AccountMeta::new_readonly(*record_address, false));
1093+
}
10481094
proof_instruction_offset.into()
10491095
}
10501096
ProofLocation::ContextStateAccount(context_state_account) => {
@@ -1108,7 +1154,13 @@ pub fn transfer(
11081154
if proof_instruction_offset != 1 {
11091155
return Err(TokenError::InvalidProofInstructionOffset.into());
11101156
}
1111-
instructions.push(verify_transfer(None, proof_data));
1157+
match proof_data {
1158+
ProofData::ProofData(data) => instructions.push(verify_transfer(None, data)),
1159+
ProofData::RecordAccount(address, offset) => instructions.push(
1160+
ProofInstruction::VerifyTransfer
1161+
.encode_verify_proof_from_account(None, address, offset),
1162+
),
1163+
};
11121164
};
11131165

11141166
Ok(instructions)
@@ -1136,8 +1188,11 @@ pub fn inner_transfer_with_fee(
11361188
];
11371189

11381190
let proof_instruction_offset = match proof_data_location {
1139-
ProofLocation::InstructionOffset(proof_instruction_offset, _) => {
1191+
ProofLocation::InstructionOffset(proof_instruction_offset, proof_data) => {
11401192
accounts.push(AccountMeta::new_readonly(sysvar::instructions::id(), false));
1193+
if let ProofData::RecordAccount(record_address, _) = proof_data {
1194+
accounts.push(AccountMeta::new_readonly(*record_address, false));
1195+
}
11411196
proof_instruction_offset.into()
11421197
}
11431198
ProofLocation::ContextStateAccount(context_state_account) => {
@@ -1201,7 +1256,13 @@ pub fn transfer_with_fee(
12011256
if proof_instruction_offset != 1 {
12021257
return Err(TokenError::InvalidProofInstructionOffset.into());
12031258
}
1204-
instructions.push(verify_transfer_with_fee(None, proof_data));
1259+
match proof_data {
1260+
ProofData::ProofData(data) => instructions.push(verify_transfer_with_fee(None, data)),
1261+
ProofData::RecordAccount(address, offset) => instructions.push(
1262+
ProofInstruction::VerifyTransferWithFee
1263+
.encode_verify_proof_from_account(None, address, offset),
1264+
),
1265+
};
12051266
};
12061267

12071268
Ok(instructions)

token/program-2022/src/extension/confidential_transfer/verify_proof.rs

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,13 @@ pub fn verify_configure_account_proof(
4343
let sysvar_account_info = next_account_info(account_info_iter)?;
4444
let zkp_instruction =
4545
get_instruction_relative(proof_instruction_offset, sysvar_account_info)?;
46-
Ok(*decode_proof_instruction_context::<
46+
Ok(decode_proof_instruction_context::<
4747
PubkeyValidityData,
4848
PubkeyValidityProofContext,
4949
>(
50-
ProofInstruction::VerifyPubkeyValidity, &zkp_instruction
50+
account_info_iter,
51+
ProofInstruction::VerifyPubkeyValidity,
52+
&zkp_instruction,
5153
)?)
5254
}
5355
}
@@ -77,11 +79,13 @@ pub fn verify_empty_account_proof(
7779
let sysvar_account_info = next_account_info(account_info_iter)?;
7880
let zkp_instruction =
7981
get_instruction_relative(proof_instruction_offset, sysvar_account_info)?;
80-
Ok(*decode_proof_instruction_context::<
82+
Ok(decode_proof_instruction_context::<
8183
ZeroBalanceProofData,
8284
ZeroBalanceProofContext,
8385
>(
84-
ProofInstruction::VerifyZeroBalance, &zkp_instruction
86+
account_info_iter,
87+
ProofInstruction::VerifyZeroBalance,
88+
&zkp_instruction,
8589
)?)
8690
}
8791
}
@@ -110,11 +114,13 @@ pub fn verify_withdraw_proof(
110114
let sysvar_account_info = next_account_info(account_info_iter)?;
111115
let zkp_instruction =
112116
get_instruction_relative(proof_instruction_offset, sysvar_account_info)?;
113-
Ok(*decode_proof_instruction_context::<
117+
Ok(decode_proof_instruction_context::<
114118
WithdrawData,
115119
WithdrawProofContext,
116120
>(
117-
ProofInstruction::VerifyWithdraw, &zkp_instruction
121+
account_info_iter,
122+
ProofInstruction::VerifyWithdraw,
123+
&zkp_instruction,
118124
)?)
119125
}
120126
}
@@ -259,11 +265,13 @@ pub fn verify_transfer_proof(
259265
let sysvar_account_info = next_account_info(account_info_iter)?;
260266
let zkp_instruction =
261267
get_instruction_relative(proof_instruction_offset, sysvar_account_info)?;
262-
let proof_context = (*decode_proof_instruction_context::<
263-
TransferData,
264-
TransferProofContext,
265-
>(ProofInstruction::VerifyTransfer, &zkp_instruction)?)
266-
.into();
268+
let proof_context =
269+
(decode_proof_instruction_context::<TransferData, TransferProofContext>(
270+
account_info_iter,
271+
ProofInstruction::VerifyTransfer,
272+
&zkp_instruction,
273+
)?)
274+
.into();
267275

268276
Ok(Some(proof_context))
269277
}
@@ -490,10 +498,12 @@ pub fn verify_transfer_with_fee_proof(
490498
let sysvar_account_info = next_account_info(account_info_iter)?;
491499
let zkp_instruction =
492500
get_instruction_relative(proof_instruction_offset, sysvar_account_info)?;
493-
let proof_context = decode_proof_instruction_context::<
494-
TransferWithFeeData,
495-
TransferWithFeeProofContext,
496-
>(ProofInstruction::VerifyTransferWithFee, &zkp_instruction)?;
501+
let proof_context =
502+
decode_proof_instruction_context::<TransferWithFeeData, TransferWithFeeProofContext>(
503+
account_info_iter,
504+
ProofInstruction::VerifyTransferWithFee,
505+
&zkp_instruction,
506+
)?;
497507

498508
let proof_tranfer_fee_basis_points: u16 =
499509
proof_context.fee_parameters.fee_rate_basis_points.into();
@@ -509,7 +519,7 @@ pub fn verify_transfer_with_fee_proof(
509519
return Err(TokenError::FeeParametersMismatch.into());
510520
}
511521

512-
Ok(Some((*proof_context).into()))
522+
Ok(Some(proof_context.into()))
513523
}
514524
}
515525

0 commit comments

Comments
 (0)