ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Transaction Data 살펴보기 (feat. ABI)
    BlockChain Tech 2019. 4. 10. 12:13

     Transaction을 구성하는 여러가지 요소들이 있다.

    대부분 쉽게 이해할 수 있는 반면, Data라는 친구는 명확하게 어떤 것을 해주는 항목인지 알기 힘들다.

     

    오늘은 Transaction의 Data가 어떤 역할을 하는지 알아보도록 하자.

     

    'etherscan.io'에서 조회한 Transaction의 모습

    Transaction의 구성요소

    • nonce: 해당 계좌에서 발생된 Transaction의 수
    • from: receive address
    • to: sender address
    • value: 수신자에게 보내는 Ether 수량
    • gas limit: 가스의 최대 사용량
    • gas price: 가스 가격
    • data: 가변길이의 바이너리 데이터
    • v, r, s: ECDSA 서명 구성 요소

    Transfer Transaction

        var transaction = {
        nonce: web3.toHex(nonce),
        gasPrice: eb3.toHex(web3.toWei(1, 'Gwei').toNumber()),
        gasLimit: web3.toHex(100000),
        to: '0xe456064545F872B311aE7432689a0fECE90C9a29',
        value: web3.toHex(web3.toWei(0.1, 'ether').toNumber()),
        data: '0x0'
    };
    

    일반적인 송금에서는 data에 아무런 값을 넣어주지 않아도 된다. (않아 보다는 할 필요가 전혀 없다.)

     

    Contract Execution Transaction

        var transaction = {
        nonce: web3.toHex(nonce),
        gasPrice: eb3.toHex(web3.toWei(1, 'Gwei').toNumber()),
        gasLimit: web3.toHex(5000000),
        to: contractAddress,
        value: '0x0',
        data: '0x18b0c3fd'
    };
    

    Contract Execution Transaction의 경우 receive address가 일반 EA(External Account )가 아닌 CA(Contract Account)인 점

    그리고, data에 어떠한 값이 들어간 점이 달라졌다.


     

    Transaction을 '어떠한 명령'을 수행하라는 주문서라고 생각해보자.

     

    Transfer

    (1)From(2)To에게 (3)Value 만큼을 (4)GasLimit * GasPrice 만큼의 수수료를 내고 수행해달라!

     

    굉장히 단순하고 쉽게 실행이 되지만, Contract Method를 호출하게될 때는 어떤 형대로 진행이 될까?

     

    Contract Execution

    (1)From (2)Contract에게 (3)Value 만큼을 (4)GasLimit * GasPrice 만큼의 수수료를 내고 (5)Data에 16진수를 수행해달라!

     


    Data에 16진수

    16진수라는 데이터를 가지고, 어떤 함수에 어떤 인자값을 넣었는지 어떻게 알 수 있을까?

    Solidity docs에서 그 해답을 찾을 수 있다. (링크)

    Contract를 호출 할 때에는 ABI Spec에 맞추어 data를 변환 해야하고, 그 data를 Transaction에 추가한다. 

    pragma solidity >=0.4.16 <0.7.0;
    
    contract Foo {
      function bar(bytes3[2] memory) public pure {}
      function baz(uint32 x, bool y) public pure returns (bool r) { r = x > 32 || y; }
      function sam(bytes memory, bool, uint[] memory) public pure {}
    }
    

    (1) CA(Contract Account)의 Contract Address를 통하여 'Foo' Contract의 접근

     

    (2) 호출하고 싶은 Method ID 입력

    >  Method ID는 각 function마다 다른 값을 갖을 수 있다.

     the first 4 bytes of the Keccak hash of the ASCII form of the signature

    >  ASCII 서명 방식의 Keccak해시 값의 처음 4 bytes

    >  bytes4(keccak256('transferFrom(address,address,uint256)')) 를 통해 얻을 수 있다.

    >  정말 말 그대로 해당 함수의 interface를 해시화 하고, 앞의 4 bytes를 가지고 오면 Method ID가 된다.

    >  Solidity에서는 'selector'라는 Method를 통해 Method ID를 추출할 수 있다. (ex. this.bar.selector)

     

    bytes4(keccak256('function bar(bytes3[2])'))

    => 0xfce353f6

     

    (3) 인자값이 들어가야할 경우 32bytes 형식으로 변환하여 Method ID 뒤에 연결한다.

    >  ["abc", "def"] 라는 인자를 function bar와 함께 호출하고 싶다면

    >  abc = 0x6162630000000000000000000000000000000000000000000000000000000000

    >  def = 0x6465660000000000000000000000000000000000000000000000000000000000

    >  이대로 Method ID와 합성을 해주면 된다.

     

    Transaction에 포함시킬 Data

    "0xfce353f661626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000"

     

    Argument가 왜 저런 모습의 16진수가 되는건가요?

    - 사전에 EVM에서 약속된 ABI Spec에 따라 변환되어야 하기 때문에 그렇다.

    > Encoding 규칙에 대해서 나열할 순 없으니 (링크) 를 참조하자!

     

    https://solidity.readthedocs.io/en/v0.4.21/abi-spec.html


     

    Etheruem ABI Encoding / Decoding은 다양한 사이트에서 실험해볼 수 있다.

    https://adibas03.github.io/online-ethereum-abi-encoder-decoder/#/decode

     

    string "ryu" Encoding 결과
    Encoding 결과 값을 다시 Decoding

     

    [추가] Ethereum Contract ABI Converter

    https://abi.sonnguyen.ws/

    https://abi.hashex.org/

    댓글

Developer RyuK