diff --git a/parser/types.go b/parser/types.go index 22242f8f..f3cf5353 100644 --- a/parser/types.go +++ b/parser/types.go @@ -8,6 +8,7 @@ import ( "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/lotus/api" "github.com/ipfs/go-cid" + "math/big" ) type ControlAddress struct { @@ -78,6 +79,11 @@ type BurnFee struct { Amount string } +type FeeData struct { + FeesMetadata + Amount *big.Int `json:"amount"` +} + type FeesMetadata struct { TxType string MinerFee MinerFee diff --git a/parser/v1/parser.go b/parser/v1/parser.go index 77ffefa5..c0766211 100644 --- a/parser/v1/parser.go +++ b/parser/v1/parser.go @@ -3,6 +3,8 @@ package v1 import ( "encoding/json" "errors" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/api" "math/big" "strings" @@ -119,7 +121,7 @@ func (p *Parser) ParseTransactions(traces []byte, tipset *types.ExtendedTipSet, } // Main transaction - transaction, err := p.parseTrace(trace.ExecutionTrace, trace.MsgCid, tipset, ethLogs, uuid.Nil.String()) + transaction, err := p.parseTrace(trace.ExecutionTrace, trace.MsgCid, tipset, ethLogs, trace.GasCost, uuid.Nil.String()) if err != nil { continue } @@ -134,12 +136,6 @@ func (p *Parser) ParseTransactions(traces []byte, tipset *types.ExtendedTipSet, transactions = append(transactions, subTxs...) } } - - // Fees - if trace.GasCost.TotalCost.Uint64() > 0 { - feeTx := p.feesTransactions(trace, tipset, transaction.TxType, transaction.Id) - transactions = append(transactions, feeTx) - } } transactions = tools.SetNodeMetadataOnTxs(transactions, metadata, Version) @@ -182,8 +178,10 @@ func (p *Parser) GetBaseFee(traces []byte, tipset *types.ExtendedTipSet) (uint64 func (p *Parser) parseSubTxs(subTxs []typesV1.ExecutionTraceV1, mainMsgCid cid.Cid, tipSet *types.ExtendedTipSet, ethLogs []types.EthLog, txHash string, parentId string, level uint16) (txs []*types.Transaction) { level++ + gasCost := api.MsgGasCost{TotalCost: abi.NewTokenAmount(0)} // It is necessary to avoid adding fees to transactions with level != 0 + for _, subTx := range subTxs { - subTransaction, err := p.parseTrace(subTx, mainMsgCid, tipSet, ethLogs, parentId) + subTransaction, err := p.parseTrace(subTx, mainMsgCid, tipSet, ethLogs, gasCost, parentId) if err != nil { continue } @@ -195,7 +193,7 @@ func (p *Parser) parseSubTxs(subTxs []typesV1.ExecutionTraceV1, mainMsgCid cid.C return } -func (p *Parser) parseTrace(trace typesV1.ExecutionTraceV1, mainMsgCid cid.Cid, tipset *types.ExtendedTipSet, ethLogs []types.EthLog, parentId string) (*types.Transaction, error) { +func (p *Parser) parseTrace(trace typesV1.ExecutionTraceV1, mainMsgCid cid.Cid, tipset *types.ExtendedTipSet, ethLogs []types.EthLog, gasCost api.MsgGasCost, parentId string) (*types.Transaction, error) { txType, err := p.helper.GetMethodName(&parser.LotusMessage{ To: trace.Msg.To, From: trace.Msg.From, @@ -244,7 +242,7 @@ func (p *Parser) parseTrace(trace typesV1.ExecutionTraceV1, mainMsgCid cid.Cid, messageUuid := tools.BuildMessageId(tipsetCid, blockCid, mainMsgCid.String(), trace.Msg.Cid().String(), parentId) - return &types.Transaction{ + tx := &types.Transaction{ TxBasicBlockData: types.TxBasicBlockData{ BasicBlockData: types.BasicBlockData{ Height: uint64(tipset.Height()), @@ -262,59 +260,13 @@ func (p *Parser) parseTrace(trace typesV1.ExecutionTraceV1, mainMsgCid cid.Cid, Status: parser.GetExitCodeStatus(trace.MsgRct.ExitCode), TxType: txType, TxMetadata: string(jsonMetadata), - }, nil -} - -func (p *Parser) feesTransactions(msg *typesV1.InvocResultV1, tipset *types.ExtendedTipSet, txType, parentTxId string) *types.Transaction { - timestamp := parser.GetTimestamp(tipset.MinTimestamp()) - appTools := tools.Tools{Logger: p.logger} - blockCid, err := appTools.GetBlockCidFromMsgCid(msg.MsgCid.String(), txType, nil, tipset) - if err != nil { - p.logger.Sugar().Errorf("Error when trying to get block cid from message, txType '%s': %v", txType, err) - } - - minerAddress, err := tipset.GetBlockMiner(blockCid) - if err != nil { - p.logger.Sugar().Errorf("Error when trying to get miner address from block cid '%s': %v", blockCid, err) } - feesMetadata := parser.FeesMetadata{ - TxType: txType, - MinerFee: parser.MinerFee{ - MinerAddress: minerAddress, - Amount: msg.GasCost.MinerTip.String(), - }, - OverEstimationBurnFee: parser.OverEstimationBurnFee{ - BurnAddress: parser.BurnAddress, - Amount: msg.GasCost.OverEstimationBurn.String(), - }, - BurnFee: parser.BurnFee{ - BurnAddress: parser.BurnAddress, - Amount: msg.GasCost.BaseFeeBurn.String(), - }, - } - - metadata, _ := json.Marshal(feesMetadata) - feeID := tools.BuildFeeId(tipset.GetCidString(), blockCid, msg.MsgCid.String()) - - return &types.Transaction{ - TxBasicBlockData: types.TxBasicBlockData{ - BasicBlockData: types.BasicBlockData{ - Height: uint64(tipset.Height()), - TipsetCid: tipset.GetCidString(), - }, - BlockCid: blockCid, - }, - Id: feeID, - ParentId: parentTxId, - TxTimestamp: timestamp, - TxCid: msg.MsgCid.String(), - TxFrom: msg.Msg.From.String(), - Amount: msg.GasCost.TotalCost.Int, - Status: "Ok", - TxType: parser.TotalFeeOp, - TxMetadata: string(metadata), + if gasCost.TotalCost.Uint64() > 0 { + transactionFeesJson := p.calculateTransactionFees(gasCost, tipset, blockCid) + tx.FeeData = string(transactionFeesJson) } + return tx, nil } func hasMessage(trace *typesV1.InvocResultV1) bool { @@ -338,3 +290,32 @@ func (p *Parser) appendAddressInfo(msg *filTypes.Message, key filTypes.TipSetKey toAdd := p.helper.GetActorAddressInfo(msg.To, key) parser.AppendToAddressesMap(p.addresses, fromAdd, toAdd) } + +func (p *Parser) calculateTransactionFees(gasCost api.MsgGasCost, tipset *types.ExtendedTipSet, blockCid string) []byte { + minerAddress, err := tipset.GetBlockMiner(blockCid) + if err != nil { + p.logger.Sugar().Errorf("Error when trying to get miner address from block cid '%s': %v", blockCid, err) + } + + feeData := parser.FeeData{ + FeesMetadata: parser.FeesMetadata{ + MinerFee: parser.MinerFee{ + MinerAddress: minerAddress, + Amount: gasCost.MinerTip.String(), + }, + OverEstimationBurnFee: parser.OverEstimationBurnFee{ + BurnAddress: parser.BurnAddress, + Amount: gasCost.OverEstimationBurn.String(), + }, + BurnFee: parser.BurnFee{ + BurnAddress: parser.BurnAddress, + Amount: gasCost.BaseFeeBurn.String(), + }, + }, + Amount: gasCost.TotalCost.Int, + } + + data, _ := json.Marshal(feeData) + + return data +} diff --git a/parser/v2/parser.go b/parser/v2/parser.go index 3063fdc5..309d6ab1 100644 --- a/parser/v2/parser.go +++ b/parser/v2/parser.go @@ -3,6 +3,8 @@ package v2 import ( "encoding/json" "errors" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/api" "math/big" "strings" @@ -80,7 +82,7 @@ func (p *Parser) ParseTransactions(traces []byte, tipset *types.ExtendedTipSet, } // Main transaction - transaction, err := p.parseTrace(trace.ExecutionTrace, trace.MsgCid, tipset, ethLogs, uuid.Nil.String()) + transaction, err := p.parseTrace(trace.ExecutionTrace, trace.MsgCid, tipset, ethLogs, trace.GasCost, uuid.Nil.String()) if err != nil { continue } @@ -99,12 +101,6 @@ func (p *Parser) ParseTransactions(traces []byte, tipset *types.ExtendedTipSet, transactions = append(transactions, subTxs...) } } - - // Fees - if trace.GasCost.TotalCost.Uint64() > 0 { - feeTx := p.feesTransactions(trace, tipset, transaction.TxType, transaction.Id) - transactions = append(transactions, feeTx) - } } transactions = tools.SetNodeMetadataOnTxs(transactions, metadata, Version) @@ -147,8 +143,10 @@ func (p *Parser) GetBaseFee(traces []byte, tipset *types.ExtendedTipSet) (uint64 func (p *Parser) parseSubTxs(subTxs []typesV2.ExecutionTraceV2, mainMsgCid cid.Cid, tipSet *types.ExtendedTipSet, ethLogs []types.EthLog, txHash string, parentId string, level uint16) (txs []*types.Transaction) { level++ + gasCost := api.MsgGasCost{TotalCost: abi.NewTokenAmount(0)} // It is necessary to avoid adding fees to transactions with level != 0 + for _, subTx := range subTxs { - subTransaction, err := p.parseTrace(subTx, mainMsgCid, tipSet, ethLogs, parentId) + subTransaction, err := p.parseTrace(subTx, mainMsgCid, tipSet, ethLogs, gasCost, parentId) if err != nil { continue } @@ -160,7 +158,7 @@ func (p *Parser) parseSubTxs(subTxs []typesV2.ExecutionTraceV2, mainMsgCid cid.C return } -func (p *Parser) parseTrace(trace typesV2.ExecutionTraceV2, mainMsgCid cid.Cid, tipset *types.ExtendedTipSet, ethLogs []types.EthLog, parentId string) (*types.Transaction, error) { +func (p *Parser) parseTrace(trace typesV2.ExecutionTraceV2, mainMsgCid cid.Cid, tipset *types.ExtendedTipSet, ethLogs []types.EthLog, gasCost api.MsgGasCost, parentId string) (*types.Transaction, error) { txType, err := p.helper.GetMethodName(&parser.LotusMessage{ To: trace.Msg.To, From: trace.Msg.From, @@ -220,7 +218,7 @@ func (p *Parser) parseTrace(trace typesV2.ExecutionTraceV2, mainMsgCid cid.Cid, tipsetCid := tipset.GetCidString() messageUuid := tools.BuildMessageId(tipsetCid, blockCid, mainMsgCid.String(), msgCid, parentId) - return &types.Transaction{ + tx := &types.Transaction{ TxBasicBlockData: types.TxBasicBlockData{ BasicBlockData: types.BasicBlockData{ Height: uint64(tipset.Height()), @@ -238,59 +236,42 @@ func (p *Parser) parseTrace(trace typesV2.ExecutionTraceV2, mainMsgCid cid.Cid, Status: parser.GetExitCodeStatus(trace.MsgRct.ExitCode), TxType: txType, TxMetadata: string(jsonMetadata), - }, nil -} + } -func (p *Parser) feesTransactions(msg *typesV2.InvocResultV2, tipset *types.ExtendedTipSet, txType, parentTxId string) *types.Transaction { - timestamp := parser.GetTimestamp(tipset.MinTimestamp()) - appTools := tools.Tools{Logger: p.logger} - blockCid, err := appTools.GetBlockCidFromMsgCid(msg.MsgCid.String(), txType, nil, tipset) - if err != nil { - p.logger.Sugar().Errorf("Error when trying to get block cid from message, txType '%s': %v", txType, err) + if gasCost.TotalCost.Uint64() > 0 { + transactionFeesJson := p.calculateTransactionFees(gasCost, tipset, blockCid) + tx.FeeData = string(transactionFeesJson) } + return tx, nil +} +func (p *Parser) calculateTransactionFees(gasCost api.MsgGasCost, tipset *types.ExtendedTipSet, blockCid string) []byte { minerAddress, err := tipset.GetBlockMiner(blockCid) if err != nil { p.logger.Sugar().Errorf("Error when trying to get miner address from block cid '%s': %v", blockCid, err) } - feesMetadata := parser.FeesMetadata{ - TxType: txType, - MinerFee: parser.MinerFee{ - MinerAddress: minerAddress, - Amount: msg.GasCost.MinerTip.String(), - }, - OverEstimationBurnFee: parser.OverEstimationBurnFee{ - BurnAddress: parser.BurnAddress, - Amount: msg.GasCost.OverEstimationBurn.String(), - }, - BurnFee: parser.BurnFee{ - BurnAddress: parser.BurnAddress, - Amount: msg.GasCost.BaseFeeBurn.String(), + feeData := parser.FeeData{ + FeesMetadata: parser.FeesMetadata{ + MinerFee: parser.MinerFee{ + MinerAddress: minerAddress, + Amount: gasCost.MinerTip.String(), + }, + OverEstimationBurnFee: parser.OverEstimationBurnFee{ + BurnAddress: parser.BurnAddress, + Amount: gasCost.OverEstimationBurn.String(), + }, + BurnFee: parser.BurnFee{ + BurnAddress: parser.BurnAddress, + Amount: gasCost.BaseFeeBurn.String(), + }, }, + Amount: gasCost.TotalCost.Int, } - metadata, _ := json.Marshal(feesMetadata) - feeID := tools.BuildFeeId(tipset.GetCidString(), blockCid, msg.MsgCid.String()) + data, _ := json.Marshal(feeData) - return &types.Transaction{ - TxBasicBlockData: types.TxBasicBlockData{ - BasicBlockData: types.BasicBlockData{ - Height: uint64(tipset.Height()), - TipsetCid: tipset.GetCidString(), - }, - BlockCid: blockCid, - }, - Id: feeID, - ParentId: parentTxId, - TxTimestamp: timestamp, - TxCid: msg.MsgCid.String(), - TxFrom: msg.Msg.From.String(), - Amount: msg.GasCost.TotalCost.Int, - Status: "Ok", - TxType: parser.TotalFeeOp, - TxMetadata: string(metadata), - } + return data } func (p *Parser) appendAddressInfo(msg *parser.LotusMessage, key filTypes.TipSetKey) { diff --git a/parser_test.go b/parser_test.go index 745caf25..9cc7429b 100644 --- a/parser_test.go +++ b/parser_test.go @@ -140,7 +140,7 @@ func TestParser_ParseTransactions(t *testing.T) { url: nodeUrl, height: "2907480", results: expectedResults{ - totalTraces: 650, + totalTraces: 551, totalAddress: 98, }, }, @@ -150,7 +150,7 @@ func TestParser_ParseTransactions(t *testing.T) { url: nodeUrl, height: "845259", results: expectedResults{ - totalTraces: 31, + totalTraces: 26, totalAddress: 3, }, }, @@ -160,7 +160,7 @@ func TestParser_ParseTransactions(t *testing.T) { url: nodeUrl, height: "2907520", results: expectedResults{ - totalTraces: 907, + totalTraces: 760, totalAddress: 88, }, }, @@ -170,7 +170,7 @@ func TestParser_ParseTransactions(t *testing.T) { url: nodeUrl, height: "3573062", results: expectedResults{ - totalTraces: 773, + totalTraces: 655, totalAddress: 70, }, }, @@ -180,7 +180,7 @@ func TestParser_ParseTransactions(t *testing.T) { url: nodeUrl, height: "3573064", results: expectedResults{ - totalTraces: 734, + totalTraces: 637, totalAddress: 75, }, }, @@ -190,7 +190,7 @@ func TestParser_ParseTransactions(t *testing.T) { url: nodeUrl, height: "3573066", results: expectedResults{ - totalTraces: 1118, + totalTraces: 941, totalAddress: 102, }, }, diff --git a/types/transaction.go b/types/transaction.go index 89f8659d..79b7074c 100644 --- a/types/transaction.go +++ b/types/transaction.go @@ -39,6 +39,8 @@ type Transaction struct { TxMetadata string `json:"tx_metadata"` // ParserVersion is the parser version used to parse this tx ParserVersion string `json:"parser_version"` + // FeeData is the fee data + FeeData string `json:"fee_data"` NodeInfo }