1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#![forbid(unsafe_code)]
use {
bytemuck::Pod,
solana_program_runtime::{ic_msg, invoke_context::InvokeContext},
solana_sdk::instruction::{InstructionError, TRANSACTION_LEVEL_STACK_HEIGHT},
safe_zk_token_sdk::zk_token_proof_instruction::*,
std::result::Result,
};
fn verify<T: Pod + Verifiable>(invoke_context: &mut InvokeContext) -> Result<(), InstructionError> {
let transaction_context = &invoke_context.transaction_context;
let instruction_context = transaction_context.get_current_instruction_context()?;
let instruction_data = instruction_context.get_instruction_data();
let instruction = ProofInstruction::decode_data::<T>(instruction_data);
let proof = instruction.ok_or_else(|| {
ic_msg!(invoke_context, "invalid proof data");
InstructionError::InvalidInstructionData
})?;
proof.verify().map_err(|err| {
ic_msg!(invoke_context, "proof verification failed: {:?}", err);
InstructionError::InvalidInstructionData
})
}
pub fn process_instruction(
_first_instruction_account: usize,
invoke_context: &mut InvokeContext,
) -> Result<(), InstructionError> {
if invoke_context.get_stack_height() != TRANSACTION_LEVEL_STACK_HEIGHT {
return Err(InstructionError::UnsupportedProgramId);
}
{
let compute_meter = invoke_context.get_compute_meter();
compute_meter.borrow_mut().consume(100_000)?;
}
let transaction_context = &invoke_context.transaction_context;
let instruction_context = transaction_context.get_current_instruction_context()?;
let instruction_data = instruction_context.get_instruction_data();
let instruction = ProofInstruction::decode_type(instruction_data);
match instruction.ok_or(InstructionError::InvalidInstructionData)? {
ProofInstruction::VerifyCloseAccount => {
ic_msg!(invoke_context, "VerifyCloseAccount");
verify::<CloseAccountData>(invoke_context)
}
ProofInstruction::VerifyWithdraw => {
ic_msg!(invoke_context, "VerifyWithdraw");
verify::<WithdrawData>(invoke_context)
}
ProofInstruction::VerifyWithdrawWithheldTokens => {
ic_msg!(invoke_context, "VerifyWithdrawWithheldTokens");
verify::<WithdrawWithheldTokensData>(invoke_context)
}
ProofInstruction::VerifyTransfer => {
ic_msg!(invoke_context, "VerifyTransfer");
verify::<TransferData>(invoke_context)
}
ProofInstruction::VerifyTransferWithFee => {
ic_msg!(invoke_context, "VerifyTransferWithFee");
verify::<TransferWithFeeData>(invoke_context)
}
ProofInstruction::VerifyPubkeyValidity => {
ic_msg!(invoke_context, "VerifyPubkeyValidity");
verify::<PubkeyValidityData>(invoke_context)
}
}
}