diff --git a/api/insight/apimiddleware.go b/api/insight/apimiddleware.go index 6203cf8b8..94378c671 100644 --- a/api/insight/apimiddleware.go +++ b/api/insight/apimiddleware.go @@ -268,8 +268,8 @@ func (c *insightApiContext) PostAddrsUtxoCtx(next http.Handler) http.Handler { }) } -// GetAddressCommandCtx returns a http.HandlerFunc that embeds the value at the -// url part {command} into the request context. +// AddressCommandCtx returns a http.HandlerFunc that embeds the value at the url +// part {command} into the request context. func (c *insightApiContext) AddressCommandCtx(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { command := chi.URLParam(r, "command") diff --git a/api/insight/apiroutes.go b/api/insight/apiroutes.go index 67219031c..559aa6d41 100644 --- a/api/insight/apiroutes.go +++ b/api/insight/apiroutes.go @@ -148,14 +148,14 @@ func (c *insightApiContext) getTransactionHex(w http.ResponseWriter, r *http.Req } txHex := c.BlockData.GetTransactionHex(txid) - if txHex == "" { writeInsightNotFound(w, fmt.Sprintf("Unable to get transaction (%s)", txHex)) return } - hexOutput := new(apitypes.InsightRawTx) - hexOutput.Rawtx = txHex + hexOutput := &apitypes.InsightRawTx{ + Rawtx: txHex, + } writeJSON(w, hexOutput, c.getIndentQuery(r)) } @@ -183,7 +183,7 @@ func (c *insightApiContext) getBlockSummary(w http.ResponseWriter, r *http.Reque } blockSummary := []*dcrjson.GetBlockVerboseResult{blockDcrd} - blockInsight, err := c.BlockConverter(blockSummary) + blockInsight, err := c.DcrToInsightBlock(blockSummary) if err != nil { apiLog.Errorf("Unable to process block (%s)", hash) writeInsightError(w, "Unable to Process Block") @@ -537,7 +537,7 @@ func (c *insightApiContext) getAddressesTxn(w http.ResponseWriter, r *http.Reque } // Convert to Insight API struct - txsNew, err := c.TxConverterWithParams(txsOld, noAsm, noScriptSig, noSpent) + txsNew, err := c.DcrToInsightTxns(txsOld, noAsm, noScriptSig, noSpent) if err != nil { apiLog.Error("Unable to process transactions") writeInsightError(w, fmt.Sprintf("Unable to convert transactions (%s)", err)) diff --git a/api/insight/converter.go b/api/insight/converter.go index 48acb7a9f..4c06addb1 100644 --- a/api/insight/converter.go +++ b/api/insight/converter.go @@ -6,7 +6,6 @@ package insight import ( "github.com/decred/dcrd/blockchain" - "github.com/decred/dcrd/chaincfg" "github.com/decred/dcrd/dcrjson" "github.com/decred/dcrd/dcrutil" apitypes "github.com/decred/dcrdata/api/types" @@ -14,49 +13,53 @@ import ( // TxConverter converts dcrd-tx to insight tx func (c *insightApiContext) TxConverter(txs []*dcrjson.TxRawResult) ([]apitypes.InsightTx, error) { - return c.TxConverterWithParams(txs, false, false, false) + return c.DcrToInsightTxns(txs, false, false, false) } -// TxConverterWithParams takes struct with filter params -func (c *insightApiContext) TxConverterWithParams(txs []*dcrjson.TxRawResult, noAsm bool, noScriptSig bool, noSpent bool) ([]apitypes.InsightTx, error) { - newTxs := []apitypes.InsightTx{} +// DcrToInsightTxns takes struct with filter params +func (c *insightApiContext) DcrToInsightTxns(txs []*dcrjson.TxRawResult, + noAsm, noScriptSig, noSpent bool) ([]apitypes.InsightTx, error) { + var newTxs []apitypes.InsightTx for _, tx := range txs { - vInSum := float64(0) - vOutSum := float64(0) - - // Build new model. Based on the old api responses of - txNew := apitypes.InsightTx{} - txNew.Txid = tx.Txid - txNew.Version = tx.Version - txNew.Locktime = tx.LockTime + // Build new InsightTx + txNew := apitypes.InsightTx{ + Txid: tx.Txid, + Version: tx.Version, + Locktime: tx.LockTime, + Blockhash: tx.BlockHash, + Blockheight: tx.BlockHeight, + Confirmations: tx.Confirmations, + Time: tx.Time, + Blocktime: tx.Blocktime, + Size: uint32(len(tx.Hex) / 2), + } // Vins fill + var vInSum, vOutSum float64 + for vinID, vin := range tx.Vin { - vinEmpty := &apitypes.InsightVin{} - emptySS := &apitypes.InsightScriptSig{} - txNew.Vins = append(txNew.Vins, vinEmpty) - txNew.Vins[vinID].Txid = vin.Txid - txNew.Vins[vinID].Vout = vin.Vout - txNew.Vins[vinID].Sequence = vin.Sequence - txNew.Vins[vinID].CoinBase = vin.Coinbase + InsightVin := &apitypes.InsightVin{ + Txid: vin.Txid, + Vout: vin.Vout, + Sequence: vin.Sequence, + N: vinID, + Value: vin.AmountIn, + CoinBase: vin.Coinbase, + } // init ScriptPubKey if !noScriptSig { - txNew.Vins[vinID].ScriptSig = emptySS + InsightVin.ScriptSig = new(apitypes.InsightScriptSig) if vin.ScriptSig != nil { if !noAsm { - txNew.Vins[vinID].ScriptSig.Asm = vin.ScriptSig.Asm + InsightVin.ScriptSig.Asm = vin.ScriptSig.Asm } - txNew.Vins[vinID].ScriptSig.Hex = vin.ScriptSig.Hex + InsightVin.ScriptSig.Hex = vin.ScriptSig.Hex } } - txNew.Vins[vinID].N = vinID - - txNew.Vins[vinID].Value = vin.AmountIn - // Lookup addresses OPTION 2 // Note, this only gathers information from the database which does not include mempool transactions _, addresses, value, err := c.BlockData.ChainDB.RetrieveAddressIDsByOutpoint(vin.Txid, vin.Vout) @@ -65,42 +68,37 @@ func (c *insightApiContext) TxConverterWithParams(txs []*dcrjson.TxRawResult, no // Update Vin due to DCRD AMOUNTIN - START // NOTE THIS IS ONLY USEFUL FOR INPUT AMOUNTS THAT ARE NOT ALSO FROM MEMPOOL if tx.Confirmations == 0 { - txNew.Vins[vinID].Value = dcrutil.Amount(value).ToCoin() + InsightVin.Value = dcrutil.Amount(value).ToCoin() } // Update Vin due to DCRD AMOUNTIN - END - txNew.Vins[vinID].Addr = addresses[0] + InsightVin.Addr = addresses[0] } } - dcramt, _ := dcrutil.NewAmount(txNew.Vins[vinID].Value) - txNew.Vins[vinID].ValueSat = int64(dcramt) - vInSum += txNew.Vins[vinID].Value + dcramt, _ := dcrutil.NewAmount(InsightVin.Value) + InsightVin.ValueSat = int64(dcramt) + + vInSum += InsightVin.Value + txNew.Vins = append(txNew.Vins, InsightVin) } // Vout fill for _, v := range tx.Vout { - voutEmpty := &apitypes.InsightVout{} - emptyPubKey := apitypes.InsightScriptPubKey{} - txNew.Vouts = append(txNew.Vouts, voutEmpty) - txNew.Vouts[v.N].Value = v.Value - vOutSum += v.Value - txNew.Vouts[v.N].N = v.N - // pk block - txNew.Vouts[v.N].ScriptPubKey = emptyPubKey + InsightVout := &apitypes.InsightVout{ + Value: v.Value, + N: v.N, + ScriptPubKey: apitypes.InsightScriptPubKey{ + Addresses: v.ScriptPubKey.Addresses, + Type: v.ScriptPubKey.Type, + }, + } if !noAsm { - txNew.Vouts[v.N].ScriptPubKey.Asm = v.ScriptPubKey.Asm + InsightVout.ScriptPubKey.Asm = v.ScriptPubKey.Asm } - txNew.Vouts[v.N].ScriptPubKey.Hex = v.ScriptPubKey.Hex - txNew.Vouts[v.N].ScriptPubKey.Type = v.ScriptPubKey.Type - txNew.Vouts[v.N].ScriptPubKey.Addresses = v.ScriptPubKey.Addresses - } - txNew.Blockhash = tx.BlockHash - txNew.Blockheight = tx.BlockHeight - txNew.Confirmations = tx.Confirmations - txNew.Time = tx.Time - txNew.Blocktime = tx.Blocktime - txNew.Size = uint32(len(tx.Hex) / 2) + txNew.Vouts = append(txNew.Vouts, InsightVout) + vOutSum += v.Value + } dcramt, _ := dcrutil.NewAmount(vOutSum) txNew.ValueOut = dcramt.ToCoin() @@ -112,7 +110,7 @@ func (c *insightApiContext) TxConverterWithParams(txs []*dcrjson.TxRawResult, no txNew.Fees = dcramt.ToCoin() // Return true if coinbase value is not empty, return 0 at some fields - if txNew.Vins != nil && len(txNew.Vins[0].CoinBase) > 0 { + if txNew.Vins != nil && txNew.Vins[0].CoinBase != "" { txNew.IsCoinBase = true txNew.ValueIn = 0 txNew.Fees = 0 @@ -123,7 +121,6 @@ func (c *insightApiContext) TxConverterWithParams(txs []*dcrjson.TxRawResult, no } if !noSpent { - // set of unique addresses for db query uniqAddrs := make(map[string]string) @@ -133,10 +130,11 @@ func (c *insightApiContext) TxConverterWithParams(txs []*dcrjson.TxRawResult, no } } - addresses := []string{} + var addresses []string for addr := range uniqAddrs { addresses = append(addresses, addr) } + // Note, this only gathers information from the database which does not include mempool transactions addrFull := c.BlockData.ChainDB.GetAddressSpendByFunHash(addresses, txNew.Txid) for _, dbaddr := range addrFull { @@ -150,19 +148,17 @@ func (c *insightApiContext) TxConverterWithParams(txs []*dcrjson.TxRawResult, no return newTxs, nil } -// BlockConverter converts dcrd-block to Insight block -func (c *insightApiContext) BlockConverter(inBlocks []*dcrjson.GetBlockVerboseResult) ([]*apitypes.InsightBlockResult, error) { - params := &chaincfg.MainNetParams - +// DcrToInsightBlock converts a dcrjson.GetBlockVerboseResult to Insight block. +func (c *insightApiContext) DcrToInsightBlock(inBlocks []*dcrjson.GetBlockVerboseResult) ([]*apitypes.InsightBlockResult, error) { RewardAtBlock := func(blocknum int64, voters uint16) float64 { - subsidyCache := blockchain.NewSubsidyCache(0, params) - work := blockchain.CalcBlockWorkSubsidy(subsidyCache, blocknum, voters, params) - stake := blockchain.CalcStakeVoteSubsidy(subsidyCache, blocknum, params) * int64(voters) - tax := blockchain.CalcBlockTaxSubsidy(subsidyCache, blocknum, voters, params) + subsidyCache := blockchain.NewSubsidyCache(0, c.params) + work := blockchain.CalcBlockWorkSubsidy(subsidyCache, blocknum, voters, c.params) + stake := blockchain.CalcStakeVoteSubsidy(subsidyCache, blocknum, c.params) * int64(voters) + tax := blockchain.CalcBlockTaxSubsidy(subsidyCache, blocknum, voters, c.params) return dcrutil.Amount(work + stake + tax).ToCoin() } - outBlocks := make([]*apitypes.InsightBlockResult, 0) + outBlocks := make([]*apitypes.InsightBlockResult, 0, len(inBlocks)) for _, inBlock := range inBlocks { outBlock := apitypes.InsightBlockResult{ Hash: inBlock.Hash, @@ -179,14 +175,9 @@ func (c *insightApiContext) BlockConverter(inBlocks []*dcrjson.GetBlockVerboseRe PreviousHash: inBlock.PreviousHash, NextHash: inBlock.NextHash, Reward: RewardAtBlock(inBlock.Height, inBlock.Voters), - } - if inBlock.Height > 0 { - outBlock.IsMainChain = true - } else { - outBlock.IsMainChain = false + IsMainChain: inBlock.Height > 0, } outBlocks = append(outBlocks, &outBlock) - } return outBlocks, nil }