Subscription Method


개인 스터디 차원에서 Chainlink VRF - Subscription Method 를 번역하고 이해를 돕고자 내용을 보충하여 정리하였습니다.

Subscriptions

VRF v2 요청은 Subscription 계정을 통해 LINK Token을 받습니다. Subscription 계정 하나를 관리자로 사용하면 사용자가 만든 애플리케이션이 무작위로 요청할 때마다 매번 LINK Token을 입금하지 않아도됩니다. 한번에 LINK Token을 입금하면 Gas Fee를 한번만 제공하여 수수료를 절약할 수 있습니다.

마치 PC방과 비슷합니다.
PC방에서 회원가입 후 시간을 미리 충전하면, 필요할 때마다 그 시간을 사용하는 것과 비슷하게 VRF v2도 미리 돈을 충전하고 필요할 때 사용하는 구조입니다. 이렇게 하면 매번 돈을 내는 번거로움 없이 서비스를 이용할 수 있습니다.

Subscription에는 다음과 같은 핵심 개념이 있습니다.

  • Subscription id: Subscription 계정의 고유 식별자입니다. 64bit의 부호 없는 정수입니다

  • Subscription accounts: LINK Token을 보관하고 Chainlink VRF v2 coordinators에게 LINK Token 보낼 수 있도록 하는 계정입니다.

    Coordinators
    Chainlink에서 coordinators는 사용자의 요청을 받아 VRF v2 시스템과 소통하면서 랜덤한 숫자나 그 숫자가 어떻게 생성되었는지에 대한 증명을 생성하고 전달하는 역할을 합니다. 즉, 사용자와 Chainlink VRF v2 시스템 사이의 중개자 역할을 하는 것이 coordinators입니다.
    단순한 컨트랙트입니다.
    https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol

  • Subscription owner: Subscription 계정을 생성하고 관리하는 지갑 주소입니다. 모든 계정은 Subscription 계정에 LINK Token을 입금할 수 있지만, 소유자만 승인된 Consuming 컨트랙트를 추가하거나 자금을 인출할 수 있습니다.

  • Consumers: Subscription 계정에서 LINK Token을 사용하도록 승인된 Consuming 컨트랙트입니다.

  • Subscription balance: 정기 Subscription 계정에서 유지되는 LINK Token의 양입니다. Consuming 컨트랙트의 요청은 LINK Token이 소진될 때까지 계속 소비되므로, 요청에 대한 비용을 지불하고 애플리케이션을 계속 실행할 수 있도록 하기위해선 Subscription balance에 충분한 LINK Token을 유지하고 있어야합니다.

Chainlink VRF v2가 받은 요청을 정상적으로 이행하려면 Subscription balance에 충분한 양의 LINK Token을 유지해야합니다. Gas 비용에는 다음과 같은 변수가 있을 수 있습니다.

  • Gas price: 네트워크 상태에 따라 변동하는 현재의 Gas Price입니다.
  • Callback gas: 사용자가 요청한 값을 반환하는 콜백 요청에 사용되는 가스의 양입니다.
  • Verification gas: 온체인에서 임의의 값에 대해 무작위성을 검증하는데 사용되는 가스의 양입니다.

Gas Price는 현재 네트워크의 상태에 따라 달라집니다. Callback gas의 경우 콜백 함수와 요청에 포함된 임의 값의 수에 따라 달라집니다. 각 요청의 비용은 트랜잭션이 완료된 후에야 최종적으로 결정되지만, 다음 변수를 사용하여 요청에 대해 지출할 한도를 정의할 수 있습니다. 이 값을 설정함으로써 사용자는 비용을 미리 예측하고, 과도한 비용이 발생하는 것을 방지할 수 있습니다.

  • Gas lane: 사용자가 랜덤한 값 생성 요청에 지불할 의향이 있는 최대 Gas Price입니다.
    • 요청에 적절한 keyHash를 지정하여 이 한도를 정의할 수 있습니다. 각 Gas lane의 한도는 Chainlink VRF가 사용자의 요청을 빠르게 처리하기 위해 Gas Price를 인상할 때 Gas Price가 갑작스럽게 올라가는 상황을 처리하는데 중요합니다.
  • Callback gas limit: 콜백 과정에서 사용할 수 있는 최대 Gas Price 양을 지정합니다. 이 limit은 요청에 콜백 Gas Limit 값을 지정하여 정의할 수 있습니다.
    • Chainlink VRF가 랜덤한 값을 사용자(애플리케이션)에게 다시 보내줄 때 사용하는 가스의 양을 제한하는 값입니다.

Request and receive data

Chainlink VRF v2에 대한 랜덤 값 요청은 요청 및 수신 데이터 주기를 따릅니다. 아래 End to End 다이어그램은 VRF Subscription 요청의 LifeCycle과 스마트 컨트랙트를 VRF Subscription 계정에 등록하는 각단계를 보여줍니다.

이더리움 생태계에는 두 가지 유형의 계정이 존재하며, 두 계정 모두 VRF에서 사용됩니다.

  • EOA(Externally Owned Account): 개인 키가 있고 스마트 컨트랙트(CA)를 제어할 수 있는 외부 소유 계정입니다. 트랜잭션은 EOA에 의해서만 시작될 수 있습니다.
  • CA(Contract Account, Smart Contract): 개인 키가 없고 탈중앙화된 애플리케이션으로 설계된 것을 실행하는 컨트랙트입니다.

Chainlink VRF v2 솔루션은 오프체인과 온체인 모두를 사용합니다.

  • VRF v2 Coordinator(온체인): VRF Service와 상호작용하도록 설계된 컨트랙트입니다. 랜덤한 값에 대한 요청이 있을 때 특정 Event를 발생시키고, VRF Service에서 생성된 랜덤한 값과 랜덤한 값을 생성한 방법에 대한 증명을 검증합니다.
  • VRF service(오프체인) : VRF Coordinator 컨트랙트에 있는 Event Log를 Subscription하여 해당 Event log를 수신합니다. Event log가 수신되면 Block Hash와 nonce를 기반으로 랜덤한 값을 계산합니다. 그런 다음 VRF service는 랜덤한 값과 랜덤한 값을 생성하는 방법에 대한 증명이 포함된 트랜잭션을 VRF Coordinator로 전송합니다.

Set up your contract and request

consuming 컨트랙트를 설정합니다.

  1. 사용하려는 컨트랙트는 VRFConsumerBaseV2를 상속해야합니다.
    VRFConsumerBaseV2.sol
    import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
    import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol";
    
    contract VRFTest is VRFConsumerBaseV2 {
    }
  1. 사용하려는 컨트랙트에 Callback VRF 함수인 fulfillRandomWords 함수를 구현해야합니다.
    여기에 임의의 값이 컨트랙트에 반환된 후 이를 처리하는 로직을 추가합니다.

    아래 함수는 VRF Coordinator로 부터 무작위 숫자를 받아서, 그 값을 1 부터 20 사이의 숫자로 변환하고, 이 값을 저장한 후에 이벤트를 발생시킵니다.

    contract VRFTest is VRFConsumerBaseV2 {
    	...
    	...
    	function fulfillRandomWords(
            uint256 requestId,
            uint256[] memory randomWords
        ) internal override {
            uint256 d20Value = (randomWords[0] % 20) + 1;
            s_results[s_rollers[requestId]] = d20Value;
            emit DiceLanded(requestId, d20Value);
        }
    	...
    }
  • fulfillRandomWords(uint256 requestId, uint256[] memory randomWords)
    • 함수 선언부
      • requestId: 랜덤한 숫자를 요청할 때 사용되는 고유한 식별자입니다.
      • randomWords: 오라클(Chainlink VRF)로 부터 반환받은 랜덤한 숫자들의 배열입니다.
    • 함수 구현부
      1. uint256 d20Value = (randomWords[0] % 20) + 1;: randomWords 배열의 첫 번째 요소를 20으로 나눈 나머지에 1을 더해서 d20Value 변수에 저장합니다. 결과값은 1부터 20 사이의 숫자가됩니다.
      2. s_results[s_rollers[requestId]] = d20Value;: s_rollers라는 매핑에서 requestId에 해당하는 값을 찾아, 그 값에 대응되는 s_results의 위치에 d20Value를 저장합니다.
      3. emit DiceLanded(requestId, d20Value);: DiceLanded라는 이벤트를 발생시키며, requestId와 d20Value를 함께 전송합니다.
  1. VRF Coordinator의 requestRandWords를 호출하여 VRF 요청을 제출하세요. 요청에는 다음 매개변수를 포함하세요:
    • keyHash: VRF Service에서 Job과 개인 키에 매핑되며 지정된 gas lane을 나타내는 식별자입니다. 긴급한 요청인 경우 Gas Price Limit가 더 높은 gas lane을 지정하세요.
    • s_subscriptionId: consuming 컨트랙트가 등록된 Subscription ID입니다. 이 Subscription에서 LINK Token이 차감됩니다.
    • requestConfirmations: VRF Service가 응답할 때까지 기다리는 Block Confirmations 횟수입니다.
    • callbackGasLimit: 사용자가 Callback VRF 기능을 완료하기 위해 지불할 수 있는 최대 Gas Price입니다. VRF Coordinator 컨트랙트의 maxGasLimit 보다 큰 값을 입력할 수 없습니다.
    • numWords: 요청할 난수의 개수입니다.

How VRF Processes your request

사용자가 요청을 제출하면 데이터 요청 및 수신 주기에 따라 요청이 처리됩니다. VRF Coordinator가 요청을 처리하고 다음 단계에 따라 Subscription에 대한 최종 청구 금액을 결정합니다.

  1. VRF Coordinator가 Event를 발생시킵니다.
  2. VRF Service는 Event를 감지하고 특정 수의 블록 확인(block confirmations)이 완료될 때까지 기다립니다. 블록 확인이란 특정 트랜잭션이 블록체인에 올바르게 기록되었는지 확인하는 과정입니다.
  3. 블록 확인이 완료되면, VRF Service는 랜덤한 값과 그 값이 어떻게 생성되었는지 증명하는 “proof”를 VRF coordinator에게 보냅니다. 여기서 requestConfirmations는 필요한 블록 확인의 수를 나타냅니다.
  4. VRF coordinator는 이 증명을 블록체인 상(온체인)에서 검증합니다.
  5. 증명이 올바르면 VRF coordinator는 사용자의 스마트 컨트랙트에 있는 fulfillRandomWords함수를 호출하여 랜덤한 값을 반환합니다.
profile
좋은 개발자가 되고싶은

0개의 댓글