이더리움에서 트랜잭션 처리 중 오류가 발생하면, 트랜잭션 영수증(receipt)의 logs 필드에 포함된 로그 객체(Log Object)를 분석하여 오류의 원인을 파악할 수 있습니다. 특히, 스마트 컨트랙트에서 발생한 이벤트와 관련된 정보를 통해 디버깅에 활용할 수 있습니다. 아래에서는 로그 객체의 구조와 Go 언어를 사용하여 이러한 로그를 디코딩하는 방법을 자세히 설명하겠습니다.

로그 객체(Log Object) 구조

로그 객체는 일반적으로 다음과 같은 필드들로 구성되어 있습니다:

  • address: 이벤트를 발생시킨 스마트 컨트랙트의 주소
  • topics: 이벤트의 식별자와 인덱스된(arguments) 정보를 포함하는 배열
  • data: 인덱스되지 않은 이벤트 파라미터의 데이터
  • blockNumber: 로그가 포함된 블록의 번호
  • transactionHash: 로그가 포함된 트랜잭션의 해시
  • transactionIndex: 트랜잭션이 블록 내에서 위치한 인덱스
  • blockHash: 로그가 포함된 블록의 해시
  • logIndex: 블록 내에서 로그의 인덱스
  • removed: 체인 재구성(reorganization)으로 인해 로그가 제거되었는지를 나타내는 불리언 값

Go 언어를 사용한 로그 디코딩 및 오류 원인 파악

Go 언어에서 이더리움의 로그 데이터를 디코딩하여 오류의 구체적인 내용을 확인하려면, go-ethereum 패키지를 활용할 수 있습니다. 아래는 그 과정에 대한 단계별 설명입니다:

  1. 스마트 컨트랙트 ABI 로드: 스마트 컨트랙트의 ABI(Application Binary Interface)를 로드하여 이벤트와 함수의 시그니처를 파싱합니다.

     import (
         "github.com/ethereum/go-ethereum/accounts/abi"
         "strings"
     )
    
     contractABI, err := abi.JSON(strings.NewReader(string(YourContractABI)))
     if err != nil {
         log.Fatalf("ABI 파싱 오류: %v", err)
     }
  2. 이벤트 정의: 스마트 컨트랙트에서 정의한 이벤트 구조체를 Go 언어의 구조체로 정의합니다.

     type ErrorEvent struct {
         Message string
     }
  3. 로그 필터링 및 수신: 특정 블록 범위나 주소를 기준으로 로그를 필터링하고 수신합니다.

     import (
         "github.com/ethereum/go-ethereum"
         "github.com/ethereum/go-ethereum/common"
         "math/big"
     )
    
     query := ethereum.FilterQuery{
         FromBlock: big.NewInt(startBlock),
         ToBlock:   big.NewInt(endBlock),
         Addresses: []common.Address{
             common.HexToAddress("0xYourContractAddress"),
         },
     }
    
     logs, err := client.FilterLogs(context.Background(), query)
     if err != nil {
         log.Fatalf("로그 필터링 오류: %v", err)
     }
  4. 로그 디코딩: 수신한 로그를 순회하며, 각 로그의 데이터를 디코딩합니다.

     import (
         "github.com/ethereum/go-ethereum/core/types"
         "encoding/hex"
     )
    
     for _, vLog := range logs {
         if len(vLog.Topics) == 0 {
             continue
         }
    
         eventID := vLog.Topics[0].Hex()
         if eventID == contractABI.Events["Error"].ID.Hex() {
             var errorEvent ErrorEvent
             err := contractABI.UnpackIntoInterface(&errorEvent, "Error", vLog.Data)
             if err != nil {
                 log.Fatalf("로그 디코딩 오류: %v", err)
             }
             log.Printf("오류 메시지: %s", errorEvent.Message)
         }
     }

위의 과정은 go-ethereum 패키지를 활용하여 이더리움 트랜잭션 로그를 디코딩하는 일반적인 방법입니다. 이를 통해 스마트 컨트랙트에서 발생한 오류 메시지를 추출하고, 문제의 원인을 파악할 수 있습니다.

참고 자료

+ Recent posts