github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/store/mainchain/storages/account_store.go (about) 1 package storages 2 3 import ( 4 "math/big" 5 6 "bytes" 7 8 "encoding/binary" 9 10 "github.com/syndtr/goleveldb/leveldb/util" 11 "github.com/sixexorg/magnetic-ring/common" 12 "github.com/sixexorg/magnetic-ring/store/db" 13 mcom "github.com/sixexorg/magnetic-ring/store/mainchain/common" 14 "github.com/sixexorg/magnetic-ring/store/mainchain/states" 15 ) 16 17 var ( 18 zero = big.NewInt(0) 19 ) 20 21 //prototype pattern 22 type AccountStore struct { 23 enableCache bool 24 dbDir string 25 store *db.LevelDBStore 26 //cache *AccountCache 27 } 28 29 func NewAccoutStore(dbDir string, enableCache bool) (*AccountStore, error) { 30 var err error 31 store, err := db.NewLevelDBStore(dbDir) 32 if err != nil { 33 return nil, err 34 } 35 accountStore := &AccountStore{ 36 dbDir: dbDir, 37 store: store, 38 enableCache: enableCache, 39 } 40 /* if enableCache { 41 cache, err := NewAccountCache() 42 if err != nil { 43 return nil, err 44 } 45 accountStore.cache = cache 46 }*/ 47 return accountStore, nil 48 } 49 50 //NewBatch start a commit batch 51 func (this *AccountStore) NewBatch() { 52 this.store.NewBatch() 53 } 54 func (this *AccountStore) CommitTo() error { 55 return this.store.BatchCommit() 56 } 57 58 func (this *AccountStore) GetByHeight(height uint64, account common.Address) (*states.AccountState, error) { 59 key := this.getKey(account, height) 60 v, err := this.store.Get(key) 61 if err != nil { 62 return nil, err 63 } 64 bf := bytes.NewBuffer(key) 65 bf.Write(v) 66 as := &states.AccountState{} 67 err = as.Deserialize(bf) 68 if err != nil { 69 return nil, err 70 } 71 return as, nil 72 } 73 func (this *AccountStore) GetAccountRange(start, end uint64, account common.Address) (states.AccountStates, error) { 74 s := this.getKey(account, start) 75 l := this.getKey(account, end) 76 iter := this.store.NewSeniorIterator(&util.Range{Start: s, Limit: l}) 77 ass := states.AccountStates{} 78 bf := bytes.NewBuffer(nil) 79 var err error 80 for iter.Next() { 81 bf.Write(iter.Key()) 82 bf.Write(iter.Value()) 83 as := &states.AccountState{} 84 err = as.Deserialize(bf) 85 if err != nil { 86 return nil, err 87 } 88 ass = append(ass, as) 89 bf.Reset() 90 } 91 iter.Release() 92 return ass, nil 93 } 94 func (this *AccountStore) GetPrev(height uint64, account common.Address) (*states.AccountState, error) { 95 key := this.getKey(account, height) 96 iter := this.store.NewIterator(nil) 97 buff := bytes.NewBuffer(nil) 98 flag := true 99 if iter.Seek(key) { 100 if bytes.Compare(iter.Key(), key) == 0 { 101 buff.Write(iter.Key()) 102 buff.Write(iter.Value()) 103 flag = false 104 } 105 } 106 if flag && iter.Prev() { 107 buff.Write(iter.Key()) 108 buff.Write(iter.Value()) 109 } 110 iter.Release() 111 err := iter.Error() 112 if err != nil { 113 return nil, err 114 } 115 if buff.Len() == 0 { 116 return &states.AccountState{ 117 Address: account, 118 Data: &states.Account{ 119 Balance: big.NewInt(0), 120 EnergyBalance: big.NewInt(0), 121 }, 122 }, nil 123 } 124 as := &states.AccountState{} 125 err = as.Deserialize(buff) 126 if err != nil { 127 return nil, err 128 } 129 130 if as.Address.Equals(account) { 131 return as, nil 132 } 133 return &states.AccountState{ 134 Address: account, 135 Data: &states.Account{ 136 Balance: big.NewInt(0), 137 EnergyBalance: big.NewInt(0), 138 }, 139 }, nil 140 } 141 142 //SaveBlock persist block to store 143 func (this *AccountStore) Save(account *states.AccountState) error { 144 key := account.GetKey() 145 buff := new(bytes.Buffer) 146 err := account.Serialize(buff) 147 if err != nil { 148 return err 149 } 150 err = this.store.Put(key, buff.Bytes()) 151 if err != nil { 152 return err 153 154 } 155 return nil 156 } 157 func (this *AccountStore) BatchSave(states states.AccountStates) error { 158 for _, v := range states { 159 key := v.GetKey() 160 buff := new(bytes.Buffer) 161 err := v.Serialize(buff) 162 if err != nil { 163 return err 164 } 165 this.store.BatchPut(key, buff.Bytes()) 166 167 } 168 return nil 169 } 170 171 func (this *AccountStore) getKey(account common.Address, height uint64) []byte { 172 buff := make([]byte, 1+common.AddrLength+8) 173 buff[0] = byte(mcom.ST_ACCOUNT) 174 copy(buff[1:common.AddrLength+1], account[:]) 175 binary.LittleEndian.PutUint64(buff[common.AddrLength+1:], height) 176 return buff 177 }