[Solana] System Program Account

심현보·2022년 6월 23일
0

Core-concept

목록 보기
2/2
post-thumbnail

System Program Account

지난 시간에 잠깐 다뤘던 System Program에 대해서 알아보는 시간을 가져보겠습니다. System Program은 Native Program Accounts 중 한가지 입니다. Solana에서 모든 Account는 일부 Program에 의해서 소유되어야 하기 때문에, Native Program의 존재는 필연적입니다. 이로 인해 Native Program이 Account들의 Owner로 존재하게 되어 Transfer(자산이체), 계정생성, 스테이킹(stake)등을 할 수 있는 Instruction(명령, 스마트 컨트랙트)을 소유하고 있어 솔라나 전반을 구성하는 기본적인 역할을 하게 됩니다.

[Fact]
System program은 지갑을 생성할 경우, 가지게 되는 Owner Program 입니다.

Solana에서 Account를 공부하다보면 계정 생성시, 기본적으로 Owner는 System Program이라는 글을 보게됩니다. 계정을 생성하는 순간부터 Owner가 할당되기 까지 과정을 살펴보겠습니다.

Account가 Owner로 System Program이 되는 과정 톺아보기

계정을 생성만 하고 Account를 조회할 경우 아무런 결과를 얻을 수 없습니다. Phantom Wallet이나 아래와 같이 CLI를 통해 지갑을 만드는 행위는 네트워크에 연결하지 않은 상태로, 오프라인으로 진행되어 네트워크에서는 이 계정에 대해 알지 못합니다. 온체인 상에는 존재하지 않는 계정이란 뜻이 됩니다.

그렇다면 언제 온체인에 기록이 될까?

지금 만든 이 계정에 자산이 이체되거나, 온체인상에 이벤트가 발생하는, 즉 트랜잭션이 발생할 경우에 비로소 생성됩니다. Flow는 아래처럼 그려보았습니다.

누군가가 새 계정으로 Transfer(자산이체) 하는 상황을 가정합니다.

트랜잭션이 발생하게 되면 해당 트랜잭션이 올바르게 생성되었는지 검증하기 위해, 트랜잭션상 표시되어있는 Program으로 유효성 검사를 위임하여 진행하게 됩니다. 자산이체(Sol-Transfer) 같은 경우, System Program에서 관리하고 있는 Instruction이기 때문에, System Program으로 전달하게 되는 것이죠

다시 말해, Network는 System Program으로 검증을 요청하게 되고, System Program은 이체할 lamports, payer, receiver 등 검증하는 과정에서 receiver의 계정이 온체인상에 존재하지 않을 경우, 계정 생성을 요청하게 됩니다. 이때 Owner가 System Program이 됩니다.
(System Program id: 11111111111111111111111111111111 )


자산 이체후 Owner가 SystemProgram 이 된 모습

[Fact]
Program은 자신을 Owner로 가지는 Account만 수정할 수 있습니다.

System Program이 할 수 있는 Instruction

  • Create Account
  • Transfer Lamports(sol)
  • Assign accounts to owning programs
  • ...

Latest Official Docs

System Program을 활용하는 사례 살펴보기

Staking

먼저 Staking을 하기전에 준비해야 할 것들이 있습니다. Solana 에서 모든 Account는 Stateless 하기 때문에 데이터 저장을 위해 Account를 다시 만들어 그 계정에서 관리한다고 이전 POST에서 다뤘습니다. 즉, 스테이킹에 사용할 자산을 빼는 메인 계정과 스테이킹 관리용으로 사용할 서브 계정, 총 2가지의 계정이 필요합니다.

아래는 Staking Instruction::create_account, Initialize Code 입니다. 스테이킹 로직보다는 System Account의 메소드를 어떻게 활용하는지 중점적으로 보시면 좋을 것 같습니다.

CODE

pub fn create_account(
    from_pubkey: &Pubkey,
    stake_pubkey: &Pubkey,
    authorized: &Authorized,
    lockup: &Lockup,
    lamports: u64,
) -> Vec<Instruction> {
    vec![
        system_instruction::create_account(
            from_pubkey,
            stake_pubkey,
            lamports,
            std::mem::size_of::<StakeState>() as u64,
            &id(),
        ),
        initialize(stake_pubkey, authorized, lockup),
    ]
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub enum StakeInstruction {
    /// Initialize a stake with lockup and authorization information
    ///
    /// # Account references
    ///   0. `[WRITE]` Uninitialized stake account
    ///   1. `[]` Rent sysvar
    ///
    /// Authorized carries pubkeys that must sign staker transactions
    ///   and withdrawer transactions.
    /// Lockup carries information about withdrawal restrictions
    Initialize(Authorized, Lockup),

	...
}

중간에 보시면 system_instruction::create_account 을 호출하는 부분이 이 섹션에서 다루고자 하는 내용입니다. 계정을 생성하는 부분은 System Program이 담당하는 부분이기 때문에 이 부분만 System Program에 책임을 넘겨 계정을 생성하게 합니다.

최종 생성된 Account 구조

Staking Transaction 분석


Instruction 목록에 첫번째로 Account를 만드는 과정을 볼 수 있습니다. System Program이 계정을 만들고 8AA~ 계정으로 0.5 SOL을 이체시킨다음, 마지막엔 이 계정의 Owner를 Stake Program으로 변경시켜주는 것까지 확인할 수 있습니다.

두번째로 Stake Program이 방금 생성된 계정에 Initialize 하는 과정을 담고 있습니다. 아까 만들어 전달했던 8AA 계정은 Stake Account로 초기화 되었습니다.

최종 Program들이 동작한 로그에 대한 정보입니다.

profile
develop something new

1개의 댓글

comment-user-thumbnail
2023년 2월 13일

글을 이해하기 쉽게 잘 쓰시네요 ㅎㅎ

답글 달기