OSDN Git Service

Merge pull request #1042 from Bytom/dev
[bytom/bytom.git] / wallet / unconfirmed.go
1 package wallet
2
3 import (
4         "encoding/json"
5         "fmt"
6         "time"
7
8         "github.com/bytom/blockchain/query"
9         "github.com/bytom/protocol/bc/types"
10         "sort"
11 )
12
13 const (
14         //UnconfirmedTxPrefix is txpool unconfirmed transactions prefix
15         UnconfirmedTxPrefix = "UTXS:"
16 )
17
18 func calcUnconfirmedTxKey(formatKey string) []byte {
19         return []byte(UnconfirmedTxPrefix + formatKey)
20 }
21
22 // SaveUnconfirmedTx save unconfirmed annotated transaction to the database
23 func (w *Wallet) SaveUnconfirmedTx(tx *types.Tx) error {
24         annotatedTx := &query.AnnotatedTx{
25                 ID:        tx.ID,
26                 Timestamp: uint64(time.Now().Unix()),
27                 Inputs:    make([]*query.AnnotatedInput, 0, len(tx.Inputs)),
28                 Outputs:   make([]*query.AnnotatedOutput, 0, len(tx.Outputs)),
29                 Size:      tx.SerializedSize,
30         }
31
32         for i := range tx.Inputs {
33                 annotatedTx.Inputs = append(annotatedTx.Inputs, w.BuildAnnotatedInput(tx, uint32(i)))
34         }
35         for i := range tx.Outputs {
36                 annotatedTx.Outputs = append(annotatedTx.Outputs, w.BuildAnnotatedOutput(tx, i))
37         }
38
39         // annotate account and asset
40         annotatedTxs := []*query.AnnotatedTx{}
41         annotatedTxs = append(annotatedTxs, annotatedTx)
42         annotateTxsAccount(annotatedTxs, w.DB)
43
44         rawTx, err := json.Marshal(annotatedTxs[0])
45         if err != nil {
46                 return err
47         }
48
49         w.DB.Set(calcUnconfirmedTxKey(tx.ID.String()), rawTx)
50         return nil
51 }
52
53 // GetUnconfirmedTxByTxID get unconfirmed transaction by txID
54 func (w *Wallet) GetUnconfirmedTxByTxID(txID string) (*query.AnnotatedTx, error) {
55         annotatedTx := &query.AnnotatedTx{}
56         txInfo := w.DB.Get(calcUnconfirmedTxKey(txID))
57         if txInfo == nil {
58                 return nil, fmt.Errorf("No transaction(tx_id=%s) from txpool", txID)
59         }
60
61         if err := json.Unmarshal(txInfo, annotatedTx); err != nil {
62                 return nil, err
63         }
64         annotateTxsAsset(w, []*query.AnnotatedTx{annotatedTx})
65
66         return annotatedTx, nil
67 }
68
69 // SortByTimestamp implements sort.Interface for AnnotatedTx slices
70 type SortByTimestamp []*query.AnnotatedTx
71
72 func (a SortByTimestamp) Len() int           { return len(a) }
73 func (a SortByTimestamp) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
74 func (a SortByTimestamp) Less(i, j int) bool { return a[i].Timestamp > a[j].Timestamp }
75
76 // GetUnconfirmedTxs get account unconfirmed transactions, filter transactions by accountID when accountID is not empty
77 func (w *Wallet) GetUnconfirmedTxs(accountID string) ([]*query.AnnotatedTx, error) {
78         annotatedTxs := []*query.AnnotatedTx{}
79
80         txIter := w.DB.IteratorPrefix([]byte(UnconfirmedTxPrefix))
81         defer txIter.Release()
82         for txIter.Next() {
83                 annotatedTx := &query.AnnotatedTx{}
84                 if err := json.Unmarshal(txIter.Value(), &annotatedTx); err != nil {
85                         return nil, err
86                 }
87
88                 if accountID == "" || findTransactionsByAccount(annotatedTx, accountID) {
89                         annotateTxsAsset(w, []*query.AnnotatedTx{annotatedTx})
90                         annotatedTxs = append([]*query.AnnotatedTx{annotatedTx}, annotatedTxs...)
91                 }
92         }
93
94         // sort SortByTimestamp by timestamp
95         sort.Sort(SortByTimestamp(annotatedTxs))
96         return annotatedTxs, nil
97 }