4

In the code from the project here, the processing logic is as follows:

pub struct Processor {}

impl Processor {
    pub fn process_instruction(
        _program_id: &Pubkey,
        accounts: &[AccountInfo],
        instruction_data: &[u8],
    ) -> ProgramResult {
        let instruction = CounterInstruction::try_from_slice(instruction_data)
            .map_err(|_| ProgramError::InvalidInstructionData)?;

        match instruction {
            CounterInstruction::Increment => {
                msg!("Instruction: Increment");
                let accounts_iter = &mut accounts.iter();
                let counter_ai = next_account_info(accounts_iter)?;
                let mut counter = Counter::try_from_slice(&counter_ai.try_borrow_mut_data()?)?;
                counter.count += 1;
                counter.serialize(&mut *counter_ai.data.borrow_mut())?;
            }
            CounterInstruction::Decrement => {
                msg!("Instruction: Decrement");
                let accounts_iter = &mut accounts.iter();
                let counter_ai = next_account_info(accounts_iter)?;
                let mut counter = Counter::try_from_slice(&counter_ai.try_borrow_mut_data()?)?;
                counter.count = counter.count.saturating_sub(1);
                counter.serialize(&mut *counter_ai.data.borrow_mut())?;
            }
        }
        Ok(())
    }
}

I understand this code is where the data in the counter account is being updated. Specifically for the increment this code:

counter.count += 1;
counter.serialize(&mut *counter_ai.data.borrow_mut())?;

What I do not understand is how this code actually leads to changes in the counter data and how that get saved.

If it were a typical program using a database, the pseudo code could look something like this:

counter.count += 1; // updated the count
dbClient.save(counter) // use a client to the db to persist the updated value

but in the Solana code base I see:

counter.serialize(&mut *counter_ai.data.borrow_mut())?;

How exactly does calling serialize on the counter object, while passing it &mut *counter_ai.data.borrow_mut() causes the solana runtime to update the data value?

1 Answer 1

1

counter_ai is an AccountInfo object provided by the runtime to the program, and it contains the accounts lamports (SOL) as a mutable reference &mut u64 and data as a mutable slice of bytes &mut [u8].

If a program owns the account, then the program can change the bytes in that slice. When you call counter.serialize(&mut *counter_ai.data.borrow_mut())?;, you're writing counter into the mutable byte slice of the account.

After the instruction, the runtime checks if the account data was changed, and then propagates those changes to the validator's accounts database. After you do the serialize call, the contents of the byte slice will change.

1
  • > After the instruction, the runtime checks if the account data was changed, and then propagates those changes to the validator's accounts database - I think that was the part I was missing. Thanks Commented Sep 16, 2022 at 16:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.