1use crate::consts::{
4 SCENE_BONUS_FLAT_100K, SCENE_BONUS_FLAT_50K, SCENE_BONUS_PCT_2, SCENE_BONUS_PCT_3,
5 SCENE_BONUS_PCT_5,
6};
7use solana_program::account_info::AccountInfo;
8use solana_program::ed25519_program;
9use solana_program::pubkey::Pubkey;
10use solana_program::instruction::Instruction;
11use solana_program::program_error::ProgramError;
12use solana_program::sysvar::instructions::{load_current_index_checked, load_instruction_at_checked};
13
14use crate::consts::{
15 ADMIN_ADDRESS, CLAIM_TASK_PREFIX, ED25519_DATA_START, ED25519_PUBKEY_SIZE, ED25519_SIGNATURE_SIZE,
16 TASK_VERIFIER,
17};
18use crate::error::DojosError;
19
20pub fn new_ed25519_instruction_with_signature(
23 message: &[u8],
24 signature: &[u8; 64],
25 pubkey: &[u8; 32],
26) -> Instruction {
27 let public_key_offset = ED25519_DATA_START;
28 let signature_offset = public_key_offset + ED25519_PUBKEY_SIZE;
29 let message_data_offset = signature_offset + ED25519_SIGNATURE_SIZE;
30
31 let mut data = Vec::with_capacity(message_data_offset + message.len());
32 data.extend_from_slice(&[1u8, 0u8]); data.extend_from_slice(&(signature_offset as u16).to_le_bytes());
34 data.extend_from_slice(&u16::MAX.to_le_bytes()); data.extend_from_slice(&(public_key_offset as u16).to_le_bytes());
36 data.extend_from_slice(&u16::MAX.to_le_bytes()); data.extend_from_slice(&(message_data_offset as u16).to_le_bytes());
38 data.extend_from_slice(&(message.len() as u16).to_le_bytes());
39 data.extend_from_slice(&u16::MAX.to_le_bytes()); data.extend_from_slice(pubkey);
41 data.extend_from_slice(signature);
42 data.extend_from_slice(message);
43
44 Instruction {
45 program_id: ed25519_program::id(),
46 accounts: vec![],
47 data,
48 }
49}
50
51pub fn verify_signed_task_via_introspection(
55 dojo_pda: Pubkey,
56 task_id: u64,
57 signature: &[u8; 64],
58 instructions_sysvar_info: &AccountInfo,
59) -> Result<(), ProgramError> {
60 let current_index = load_current_index_checked(instructions_sysvar_info)?;
61 let prev_index = current_index.checked_sub(1).ok_or(ProgramError::InvalidInstructionData)?;
62 let prev_ix = load_instruction_at_checked(prev_index as usize, instructions_sysvar_info)?;
63
64 if prev_ix.program_id != ed25519_program::id() {
65 return Err(ProgramError::InvalidInstructionData);
66 }
67
68 let data = &prev_ix.data;
69 if data.len() < ED25519_DATA_START + ED25519_PUBKEY_SIZE + ED25519_SIGNATURE_SIZE {
70 return Err(ProgramError::InvalidInstructionData);
71 }
72
73 let verifier_bytes: [u8; 32] = TASK_VERIFIER.to_bytes();
74 if data[ED25519_DATA_START..ED25519_DATA_START + ED25519_PUBKEY_SIZE] != verifier_bytes[..] {
75 return Err(ProgramError::InvalidInstructionData);
76 }
77 let sig_start = ED25519_DATA_START + ED25519_PUBKEY_SIZE;
78 if data[sig_start..sig_start + ED25519_SIGNATURE_SIZE] != signature[..] {
79 return Err(ProgramError::InvalidInstructionData);
80 }
81
82 let mut expected_message = Vec::with_capacity(CLAIM_TASK_PREFIX.len() + 32 + 8);
83 expected_message.extend_from_slice(CLAIM_TASK_PREFIX);
84 expected_message.extend_from_slice(dojo_pda.as_ref());
85 expected_message.extend_from_slice(&task_id.to_le_bytes());
86
87 let msg_start = sig_start + ED25519_SIGNATURE_SIZE;
88 if data.len() < msg_start + expected_message.len() || data[msg_start..msg_start + expected_message.len()] != expected_message[..] {
89 return Err(ProgramError::InvalidInstructionData);
90 }
91
92 Ok(())
93}
94
95pub fn assert_key(info: &AccountInfo, expected: &Pubkey) -> Result<(), ProgramError> {
97 if info.key != expected {
98 return Err(ProgramError::InvalidAccountData);
99 }
100 Ok(())
101}
102
103pub fn assert_admin(authority: &AccountInfo) -> Result<(), ProgramError> {
105 if authority.key != &ADMIN_ADDRESS {
106 return Err(DojosError::UnauthorizedAdmin.into());
107 }
108 Ok(())
109}
110
111pub fn scene_bonus(scene_id: u64) -> (u64, u64) {
115 match scene_id {
116 0 => (0, 0),
117 1 | 6 | 7 | 8 => (SCENE_BONUS_FLAT_50K, 0),
118 2 => (SCENE_BONUS_FLAT_100K, 0),
119 3 => (0, SCENE_BONUS_PCT_2),
120 4 => (0, SCENE_BONUS_PCT_3),
121 5 => (0, SCENE_BONUS_PCT_5),
122 _ => (0, 0),
123 }
124}
125