OSDN Git Service

update GetTransaction
[bytom/vapor.git] / wallet / indexer.go
index f3b7d57..d3db27a 100644 (file)
@@ -2,6 +2,7 @@ package wallet
 
 import (
        "encoding/binary"
+       "encoding/hex"
        "encoding/json"
        "fmt"
        "sort"
@@ -9,10 +10,9 @@ import (
        log "github.com/sirupsen/logrus"
 
        "github.com/vapor/account"
-       "github.com/vapor/asset"
        "github.com/vapor/blockchain/query"
+       "github.com/vapor/consensus"
        "github.com/vapor/crypto/sha3pool"
-       dbm "github.com/vapor/database/leveldb"
        chainjson "github.com/vapor/encoding/json"
        "github.com/vapor/errors"
        "github.com/vapor/protocol/bc"
@@ -65,33 +65,16 @@ func parseGlobalTxIdx(globalTxIdx []byte) (*bc.Hash, uint64) {
        return &hash, position
 }
 
-// deleteTransaction delete transactions when orphan block rollback
-func (w *Wallet) deleteTransactions(batch dbm.Batch, height uint64) {
-       tmpTx := query.AnnotatedTx{}
-       txIter := w.DB.IteratorPrefix(calcDeleteKey(height))
-       defer txIter.Release()
-
-       for txIter.Next() {
-               if err := json.Unmarshal(txIter.Value(), &tmpTx); err == nil {
-                       batch.Delete(calcTxIndexKey(tmpTx.ID.String()))
-               }
-               batch.Delete(txIter.Key())
-       }
-}
-
 // saveExternalAssetDefinition save external and local assets definition,
 // when query ,query local first and if have no then query external
 // details see getAliasDefinition
-func saveExternalAssetDefinition(b *types.Block, walletDB dbm.DB) {
-       storeBatch := walletDB.NewBatch()
-       defer storeBatch.Write()
-
+func saveExternalAssetDefinition(b *types.Block, store Store) {
        for _, tx := range b.Transactions {
                for _, orig := range tx.Inputs {
                        if cci, ok := orig.TypedInput.(*types.CrossChainInput); ok {
                                assetID := cci.AssetId
-                               if assetExist := walletDB.Get(asset.ExtAssetKey(assetID)); assetExist == nil {
-                                       storeBatch.Set(asset.ExtAssetKey(assetID), cci.AssetDefinition)
+                               if assetExist := store.GetAssetDefinition(assetID); assetExist == nil {
+                                       store.SetAssetDefinition(assetID, cci.AssetDefinition)
                                }
                        }
                }
@@ -118,10 +101,10 @@ type TxSummary struct {
 }
 
 // indexTransactions saves all annotated transactions to the database.
-func (w *Wallet) indexTransactions(batch dbm.Batch, b *types.Block, txStatus *bc.TransactionStatus) error {
+func (w *Wallet) indexTransactions(b *types.Block, txStatus *bc.TransactionStatus) error {
        annotatedTxs := w.filterAccountTxs(b, txStatus)
-       saveExternalAssetDefinition(b, w.DB)
-       annotateTxsAccount(annotatedTxs, w.DB)
+       saveExternalAssetDefinition(b, w.store)
+       annotateTxsAccount(annotatedTxs, w.store)
 
        for _, tx := range annotatedTxs {
                rawTx, err := json.Marshal(tx)
@@ -130,11 +113,8 @@ func (w *Wallet) indexTransactions(batch dbm.Batch, b *types.Block, txStatus *bc
                        return err
                }
 
-               batch.Set(calcAnnotatedKey(formatKey(b.Height, uint32(tx.Position))), rawTx)
-               batch.Set(calcTxIndexKey(tx.ID.String()), []byte(formatKey(b.Height, uint32(tx.Position))))
-
-               // delete unconfirmed transaction
-               batch.Delete(calcUnconfirmedTxKey(tx.ID.String()))
+               w.store.SetTransaction(b.Height, tx.Position, tx.ID.String(), rawTx)
+               w.store.DeleteUnconfirmedTransaction(tx.ID.String())
        }
 
        if !w.TxIndexFlag {
@@ -143,7 +123,7 @@ func (w *Wallet) indexTransactions(batch dbm.Batch, b *types.Block, txStatus *bc
 
        for position, globalTx := range b.Transactions {
                blockHash := b.BlockHeader.Hash()
-               batch.Set(calcGlobalTxIndexKey(globalTx.ID.String()), calcGlobalTxIndex(&blockHash, uint64(position)))
+               w.store.SetGlobalTransactionIndex(globalTx.ID.String(), &blockHash, uint64(position))
        }
 
        return nil
@@ -160,7 +140,7 @@ transactionLoop:
                        var hash [32]byte
                        sha3pool.Sum256(hash[:], v.ControlProgram())
 
-                       if bytes := w.DB.Get(account.ContractKey(hash)); bytes != nil {
+                       if bytes := w.store.GetRawProgramByHash(hash); bytes != nil {
                                annotatedTxs = append(annotatedTxs, w.buildAnnotatedTransaction(tx, b, statusFail, pos))
                                continue transactionLoop
                        }
@@ -171,7 +151,7 @@ transactionLoop:
                        if err != nil {
                                continue
                        }
-                       if bytes := w.DB.Get(account.StandardUTXOKey(outid)); bytes != nil {
+                       if bytes := w.store.GetStandardUTXO(outid); bytes != nil {
                                annotatedTxs = append(annotatedTxs, w.buildAnnotatedTransaction(tx, b, statusFail, pos))
                                continue transactionLoop
                        }
@@ -194,12 +174,11 @@ func (w *Wallet) GetTransactionByTxID(txID string) (*query.AnnotatedTx, error) {
 
 func (w *Wallet) getAccountTxByTxID(txID string) (*query.AnnotatedTx, error) {
        annotatedTx := &query.AnnotatedTx{}
-       formatKey := w.DB.Get(calcTxIndexKey(txID))
-       if formatKey == nil {
-               return nil, errAccntTxIDNotFound
+       txInfo, err := w.store.GetTransaction(txID)
+       if err != nil {
+               return nil, err
        }
 
-       txInfo := w.DB.Get(calcAnnotatedKey(string(formatKey)))
        if err := json.Unmarshal(txInfo, annotatedTx); err != nil {
                return nil, err
        }
@@ -209,7 +188,7 @@ func (w *Wallet) getAccountTxByTxID(txID string) (*query.AnnotatedTx, error) {
 }
 
 func (w *Wallet) getGlobalTxByTxID(txID string) (*query.AnnotatedTx, error) {
-       globalTxIdx := w.DB.Get(calcGlobalTxIndexKey(txID))
+       globalTxIdx := w.store.GetGlobalTransaction(txID)
        if globalTxIdx == nil {
                return nil, fmt.Errorf("No transaction(tx_id=%s) ", txID)
        }
@@ -289,27 +268,25 @@ func findTransactionsByAccount(annotatedTx *query.AnnotatedTx, accountID string)
 // GetTransactions get all walletDB transactions, and filter transactions by accountID optional
 func (w *Wallet) GetTransactions(accountID string) ([]*query.AnnotatedTx, error) {
        annotatedTxs := []*query.AnnotatedTx{}
+       annotatedTxs, err := w.store.GetTransactions()
+       if err != nil {
+               return nil, err
+       }
 
-       txIter := w.DB.IteratorPrefix([]byte(TxPrefix))
-       defer txIter.Release()
-       for txIter.Next() {
-               annotatedTx := &query.AnnotatedTx{}
-               if err := json.Unmarshal(txIter.Value(), &annotatedTx); err != nil {
-                       return nil, err
-               }
-
+       newAnnotatedTxs := []*query.AnnotatedTx{}
+       for _, annotatedTx := range annotatedTxs {
                if accountID == "" || findTransactionsByAccount(annotatedTx, accountID) {
                        annotateTxsAsset(w, []*query.AnnotatedTx{annotatedTx})
-                       annotatedTxs = append([]*query.AnnotatedTx{annotatedTx}, annotatedTxs...)
+                       newAnnotatedTxs = append([]*query.AnnotatedTx{annotatedTx}, newAnnotatedTxs...)
                }
        }
 
-       return annotatedTxs, nil
+       return newAnnotatedTxs, nil
 }
 
 // GetAccountBalances return all account balances
 func (w *Wallet) GetAccountBalances(accountID string, id string) ([]AccountBalance, error) {
-       return w.indexBalances(w.GetAccountUtxos(accountID, "", false, false))
+       return w.indexBalances(w.GetAccountUtxos(accountID, "", false, false, false))
 }
 
 // AccountBalance account balance
@@ -373,3 +350,72 @@ func (w *Wallet) indexBalances(accountUTXOs []*account.UTXO) ([]AccountBalance,
 
        return balances, nil
 }
+
+// GetAccountVotes return all account votes
+func (w *Wallet) GetAccountVotes(accountID string, id string) ([]AccountVotes, error) {
+       return w.indexVotes(w.GetAccountUtxos(accountID, "", false, false, true))
+}
+
+type voteDetail struct {
+       Vote       string `json:"vote"`
+       VoteNumber uint64 `json:"vote_number"`
+}
+
+// AccountVotes account vote
+type AccountVotes struct {
+       AccountID       string       `json:"account_id"`
+       Alias           string       `json:"account_alias"`
+       TotalVoteNumber uint64       `json:"total_vote_number"`
+       VoteDetails     []voteDetail `json:"vote_details"`
+}
+
+func (w *Wallet) indexVotes(accountUTXOs []*account.UTXO) ([]AccountVotes, error) {
+       accVote := make(map[string]map[string]uint64)
+       votes := []AccountVotes{}
+
+       for _, accountUTXO := range accountUTXOs {
+               if accountUTXO.AssetID != *consensus.BTMAssetID || accountUTXO.Vote == nil {
+                       continue
+               }
+               xpub := hex.EncodeToString(accountUTXO.Vote)
+               if _, ok := accVote[accountUTXO.AccountID]; ok {
+                       accVote[accountUTXO.AccountID][xpub] += accountUTXO.Amount
+               } else {
+                       accVote[accountUTXO.AccountID] = map[string]uint64{xpub: accountUTXO.Amount}
+
+               }
+       }
+
+       var sortedAccount []string
+       for k := range accVote {
+               sortedAccount = append(sortedAccount, k)
+       }
+       sort.Strings(sortedAccount)
+
+       for _, id := range sortedAccount {
+               var sortedXpub []string
+               for k := range accVote[id] {
+                       sortedXpub = append(sortedXpub, k)
+               }
+               sort.Strings(sortedXpub)
+
+               voteDetails := []voteDetail{}
+               voteTotal := uint64(0)
+               for _, xpub := range sortedXpub {
+                       voteDetails = append(voteDetails, voteDetail{
+                               Vote:       xpub,
+                               VoteNumber: accVote[id][xpub],
+                       })
+                       voteTotal += accVote[id][xpub]
+               }
+               alias := w.AccountMgr.GetAliasByID(id)
+               votes = append(votes, AccountVotes{
+                       Alias:           alias,
+                       AccountID:       id,
+                       VoteDetails:     voteDetails,
+                       TotalVoteNumber: voteTotal,
+               })
+       }
+
+       return votes, nil
+}