본문 바로가기
BlockChain/Solidity

[blockchain] view 함수는 정말 가스비가 무료일까? (view function cost?)

by gamxong 2023. 3. 12.

0. intro

처음에 솔리디티를 배우게 되면 view라는 예약어를 배우게 된다. 함수에 사용하면 가스가 소모되지 않는다고 보통 배울 것이다.

하지만 한 층 더 깊은 블록체인 개발자가 되기 위해서는 정확히 어떤 상황에서 가스가 소모되지 않는지 명확히 알 필요가 있다.

 

1. view 함수

솔리디티에서, "view" 키워드는 스토리지를 변경하거나 할당하지 않는 기능에 사용됩니다.

즉, "읽기 전용"입니다.

 

 

2. Gas consumption

 

일반적으로 'view' 함수는 가스 소모가 없는 것으로 알려져 있습니다.

결과적으로 틀린 말은 아닙니다. 그러나 우리는 더 명확하게 알아야 합니다.

 

 'view' 함수는 자체 블록체인 사본을 사용하여 로컬 노드의 하드웨어에서 실행됩니다. 이렇게 하면 작업이 실제로 네트워크에 브로드캐스트되지 않기 때문에 본질적으로 읽기 전용이 됩니다.

(storage에 변화를 주지 않기 때문에 → 네트워크에 broadcast 하지 않음)

 

 

내가 "Hello" 라는 view 함수를 가진 컨트랙트를 가지고 있다고 가정해 봅시다. estimateGas() 호출할 함수가 view 함수이면 0 반환해야 합니다. 그러나 23301 돌아옵니다.

truffle> contractObj.Hello.estimateGas(web3.eth.accounts[0])

23301

 

아래는 솔리디티 코드입니다.

function Hello(address account) public view returns(bool) {
    return  _test[account];  
}

 

따라서 위의 예시를 통해 가스를 소비한다는 것이 증명되었습니다.
그러나 storage의 변화가 없고, broadcast 되지 않았기 때문에 결과적으로 가스가 무료입니다.

 

 

 

3. Deep dive

contract calculateTotal{
    
   uint256 balance;

  constructor(uint256 _initialBalance){
       balance=_initialBalance;
       }
  function  purchaseSmth(uint256 _cost) external {
    balance=balance-_cost;
   }
  function getBalance() external view returns(uint256){
     return balance;
   }

}

 

좀 더 자세히 알아보겠습니다. 예시로 위의 컨트랙트 코드가 있습니다.

 

먼저 이 컨트랙트를 생성할 때 잔액을 설정합니다. 그렇게 하면 잔액이 이미 계산되었으며 동일하기 때문에 다시 계산할 필요가 없습니다.

 

'purchaseSmth'로 잔액 값을 변경하면 잔액이 다시 계산되고, 잔액의 저장 값이 변경됩니다. 즉, 함수가 블록체인의 스토리지를 변경한다는 의미입니다. 그러나 블록체인을 변경해야 하기 때문에 이러한 실행에 대한 비용을 다시 지불하게 됩니다. 그러나 view 함수는 스토리지 값을 변경하지 않습니다. 그들은 이미 블록체인에 존재하는 이전에 계산된 값을 얻고 있을 뿐입니다.

view 함수에서 몇 가지 계산을 수행할 때, 예를 들어 'return balance*10' 의 실행은 블록체인에 영향을 미치지 않습니다. 그것의 계산은 miner가 수행하는 것이 아닌 나의 컴퓨터에서 수행됩니다.


view 함수를 바로(독립적으로) 호출하면 자체적으로 가스를 소모하지 않습니다. 항상 이전에 계산된 값을 그저 불러오기 때문입니다.

(독립적으로 : 다른 함수를 실행하지 않고, 오직 view 함수만 단일 실행하는 행위)

 

 

contract Example{
    
   uint256 proof[50];

  constructor(uint256 _initialproof[50]){
       proof = _initialproof;
  }


  function  addProof(uint256 _proof) external {
    	hasProof();
        proof[1] = _proof;  // proof 배열 요소 변경
   }


  function hasProof() external view returns(bool){
  		return (proof 있는지 없는지 확인);
   }

}

 

다른 컨트랙트로 예를 들어보겠습니다. (솔리디티 문법은 틀렸을 수도 있습니다. 의미만 이해하시면 되겠습니다.)

 

먼저 생성자는 빈 배열로 생성합니다. 그런 다음 'hasProof'라는 함수를 호출하면 빈 배열이 표시됩니다. 그런 다음 'addProof'를 사용하면 proof 배열이 변경됩니다. 그러나 코드 상 변경 전에 'hasProof' 함수를 사용하고 있기 때문에 가스 가격은 더 높아집니다. hasProof 함수를 사용하는 코드가 계속 존재한다면 가스 가격은 내려가지 않을 것입니다.

왜냐하면 "2.Gas consumption"에서 다룬 것처럼 함수를 실행하는 것 자체로서 가스 비용이 발생하기 때문입니다.

 

그러나 hasProof 함수를 수동으로(hasProof 함수만 독립적으로) 호출하면 컴퓨터는 해당 함수는 있는지 여부에 관계없이 로컬에서 해당 루프를 실행합니다. 따라서 비용이 발생하지 않습니다.

 

모든 storage, 상태 변경 실행은 블록체인의 논리에 인해 채굴자(miner)에게 전달됩니다. 채굴자(miner)가 해당 코드를 실행하고 해당 트랜잭션에서 해당 변경이 가능한지, 코드에 오류가 없는지 확인해야 하기 때문입니다.

 

 

4. 결론

 

1. view 함수도 계산 및 코드를 실행하기 때문에 가스비가 측정된다.

 

2. 하지만 view 함수를 독립적으로 실행하는 것은 결과적으로 체인에 변화가 없기 때문에 가스비는 측정되더라도 비용을 내진 않는다.

 

3. 따라서 view 함수가 아닌 상태 변경이 있는 일반적인 함수 내부에서 사용하는 view 함수에는 가스 비용이 발생한다.

 

 

 

 

 

출처

https://stackoverflow.com/questions/48755578/read-only-functions-iteration-cost

 

댓글