github.com/klaytn/klaytn@v1.12.1/datasync/dbsyncer/tx_record.go (about)

     1  // Copyright 2019 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The klaytn library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package dbsyncer
    18  
    19  import (
    20  	"strings"
    21  
    22  	"github.com/klaytn/klaytn/blockchain/types"
    23  	"github.com/klaytn/klaytn/common"
    24  	"github.com/klaytn/klaytn/common/hexutil"
    25  )
    26  
    27  type SummaryArguments struct {
    28  	from            string
    29  	txHash          string
    30  	to              string
    31  	contractAddress string
    32  
    33  	tx *types.Transaction
    34  }
    35  
    36  type TxMapArguments struct {
    37  	senderTxHash string
    38  	txHash       string
    39  }
    40  
    41  type TxReceiptArgument struct {
    42  	tx      *types.Transaction
    43  	receipt *types.Receipt
    44  }
    45  
    46  type BulkInsertQuery struct {
    47  	parameters  string
    48  	vals        []interface{}
    49  	blockNumber uint64
    50  	insertCount int
    51  }
    52  
    53  func MakeTxDBRow(block *types.Block, txKey uint64, tx *types.Transaction, receipt *types.Receipt) (string, []interface{}, TxMapArguments, SummaryArguments, error) {
    54  	cols := ""
    55  	vals := []interface{}{}
    56  
    57  	blockHash := block.Hash().Hex()
    58  	blockNumber := block.Number().Uint64()
    59  
    60  	contractAddress := ""
    61  	if (receipt.ContractAddress != common.Address{}) {
    62  		contractAddress = strings.ToLower(receipt.ContractAddress.Hex())
    63  	}
    64  
    65  	from := ""
    66  	if tx.IsEthereumTransaction() {
    67  		signer := types.LatestSignerForChainID(tx.ChainId())
    68  		addr, err := types.Sender(signer, tx)
    69  		if err != nil {
    70  			logger.Error("fail to tx.From", "err", err)
    71  			return "", []interface{}{}, TxMapArguments{}, SummaryArguments{}, err
    72  		}
    73  		from = strings.ToLower(addr.Hex())
    74  	} else {
    75  		addr, err := tx.From()
    76  		if err != nil {
    77  			logger.Error("fail to tx.From", "err", err)
    78  			return "", []interface{}{}, TxMapArguments{}, SummaryArguments{}, err
    79  		}
    80  		from = strings.ToLower(addr.Hex())
    81  	}
    82  
    83  	gas := tx.Gas()
    84  	txGasPrice := tx.GasPrice().String()
    85  	txGasUsed := receipt.GasUsed
    86  
    87  	input := hexutil.Bytes(tx.Data()).String()
    88  	if input == "0x" {
    89  		input = ""
    90  	}
    91  
    92  	nonce := tx.Nonce()
    93  	status := receipt.Status
    94  	to := "" // '' means that address doesn't exist
    95  	if tx.To() != nil {
    96  		to = strings.ToLower(tx.To().Hex())
    97  	}
    98  	timestamp := block.Time().Uint64()
    99  	txHash := tx.Hash().Hex()
   100  	txtype := tx.Type().String()
   101  	value := tx.Value().String()
   102  
   103  	feePayer := ""
   104  	feeRatio := uint8(0)
   105  	if tx.IsFeeDelegatedTransaction() {
   106  		feeAddr, err := tx.FeePayer()
   107  		if err != nil {
   108  			logger.Error("fail to tx.FeePayer", "err", err)
   109  			return "", []interface{}{}, TxMapArguments{}, SummaryArguments{}, err
   110  		}
   111  		ratio, _ := tx.FeeRatio()
   112  		// ok is false in TxTypeFeeDelegatedValueTransfer
   113  		// ok is true in TxTypeFeeDelegatedValueTransferWithRatio
   114  
   115  		feePayer = strings.ToLower(feeAddr.Hex())
   116  		feeRatio = uint8(ratio)
   117  	}
   118  
   119  	senderHash := ""
   120  	if senderTxHash, ok := tx.SenderTxHash(); ok {
   121  		senderHash = senderTxHash.Hex()
   122  	}
   123  
   124  	cols = "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
   125  	vals = append(vals, txKey, blockHash, blockNumber, contractAddress, from, gas, txGasPrice, txGasUsed, input, nonce, status, to,
   126  		timestamp, txHash, txtype, value, feePayer, feeRatio, senderHash)
   127  
   128  	TxMapArg := TxMapArguments{senderHash, txHash}
   129  	summaryArg := SummaryArguments{from, txHash, to, contractAddress, tx}
   130  
   131  	return cols, vals, TxMapArg, summaryArg, nil
   132  }
   133  
   134  func MakeSummaryDBRow(sa SummaryArguments) (cols string, vals []interface{}, count int, err error) {
   135  	// insert account summary for creation and deploy
   136  	if !sa.tx.IsEthereumTransaction() {
   137  		if sa.tx.Type().IsAccountCreation() {
   138  			accountType := 0
   139  			creator := sa.from
   140  			createdTx := sa.txHash
   141  
   142  			hra := true
   143  			// TODO-Klaytn need to use humanreable field
   144  			internalTx, ok := sa.tx.GetTxInternalData().(*types.TxInternalDataAccountCreation)
   145  			if !ok {
   146  				logger.Error("fail to convert TxInternalDataAccountCreation", "txhash", sa.tx.Hash().Hex())
   147  				hra = false
   148  			} else {
   149  				hra = internalTx.HumanReadable
   150  			}
   151  
   152  			cols = "(?,?,?,?,?)"
   153  			vals = append(vals, sa.to, accountType, creator, createdTx, hra)
   154  
   155  			count = 1
   156  
   157  		} else if sa.tx.Type().IsContractDeploy() {
   158  			accountType := 1
   159  			creator := sa.from
   160  			createdTx := sa.txHash
   161  
   162  			// TODO-Klaytn need to use humanreable field
   163  			hra := false
   164  
   165  			switch internalTx := sa.tx.GetTxInternalData().(type) {
   166  			case *types.TxInternalDataSmartContractDeploy:
   167  				hra = internalTx.HumanReadable
   168  			case *types.TxInternalDataFeeDelegatedSmartContractDeploy:
   169  				hra = internalTx.HumanReadable
   170  			case *types.TxInternalDataFeeDelegatedSmartContractDeployWithRatio:
   171  				hra = internalTx.HumanReadable
   172  			default:
   173  				logger.Error("fail to convert ", "type", internalTx, "txhash", sa.tx.Hash().Hex())
   174  			}
   175  
   176  			cols = "(?,?,?,?,?)"
   177  			vals = append(vals, sa.contractAddress, accountType, creator, createdTx, hra)
   178  
   179  			count = 1
   180  		}
   181  	} else if sa.contractAddress != "" {
   182  		// AccountCreation for LegacyTransaction
   183  		accountType := 1
   184  		creator := sa.from
   185  		createdTx := sa.txHash
   186  
   187  		cols = "(?,?,?,?,?)"
   188  		vals = append(vals, sa.contractAddress, accountType, creator, createdTx, false)
   189  
   190  		count = 1
   191  	}
   192  
   193  	return cols, vals, count, nil
   194  }
   195  
   196  func MakeTxMappingRow(tm TxMapArguments) (cols string, vals []interface{}, count int, err error) {
   197  	if tm.senderTxHash != "" {
   198  		cols = "(?,?)"
   199  		vals = append(vals, tm.senderTxHash, tm.txHash)
   200  
   201  		count = 1
   202  	}
   203  
   204  	return cols, vals, count, nil
   205  }