github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/database/utxo_view.go (about) 1 package database 2 3 import ( 4 "github.com/bytom/bytom/database/storage" 5 "github.com/bytom/bytom/errors" 6 "github.com/bytom/bytom/protocol/bc" 7 "github.com/bytom/bytom/protocol/state" 8 "github.com/golang/protobuf/proto" 9 dbm "github.com/bytom/bytom/database/leveldb" 10 ) 11 12 const UtxoPreFix = "UT:" 13 14 func CalcUtxoKey(hash *bc.Hash) []byte { 15 return []byte(UtxoPreFix + hash.String()) 16 } 17 18 func getTransactionsUtxo(db dbm.DB, view *state.UtxoViewpoint, txs []*bc.Tx) error { 19 for _, tx := range txs { 20 for _, prevout := range tx.SpentOutputIDs { 21 if view.HasUtxo(&prevout) { 22 continue 23 } 24 25 data := db.Get(CalcUtxoKey(&prevout)) 26 if data == nil { 27 continue 28 } 29 30 var utxo storage.UtxoEntry 31 if err := proto.Unmarshal(data, &utxo); err != nil { 32 return errors.Wrap(err, "unmarshaling utxo entry") 33 } 34 35 view.Entries[prevout] = &utxo 36 } 37 } 38 39 return nil 40 } 41 42 func getUtxo(db dbm.DB, hash *bc.Hash) (*storage.UtxoEntry, error) { 43 var utxo storage.UtxoEntry 44 data := db.Get(CalcUtxoKey(hash)) 45 if data == nil { 46 return nil, errors.New("can't find utxo in db") 47 } 48 if err := proto.Unmarshal(data, &utxo); err != nil { 49 return nil, errors.Wrap(err, "unmarshaling utxo entry") 50 } 51 return &utxo, nil 52 } 53 54 func saveUtxoView(batch dbm.Batch, view *state.UtxoViewpoint) error { 55 for key, entry := range view.Entries { 56 if entry.Spent && !entry.IsCoinBase { 57 batch.Delete(CalcUtxoKey(&key)) 58 continue 59 } 60 61 b, err := proto.Marshal(entry) 62 if err != nil { 63 return errors.Wrap(err, "marshaling utxo entry") 64 } 65 batch.Set(CalcUtxoKey(&key), b) 66 } 67 return nil 68 } 69 70 func SaveUtxoView(batch dbm.Batch, view *state.UtxoViewpoint) error { 71 return saveUtxoView(batch, view) 72 }