github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/store/mainchain/extstorages/league_ledger_store.go (about) 1 package extstorages 2 3 import ( 4 "fmt" 5 "os" 6 "sync" 7 8 "path" 9 10 "math/big" 11 12 "github.com/sixexorg/magnetic-ring/common" 13 "github.com/sixexorg/magnetic-ring/core/mainchain/types" 14 orgtypes "github.com/sixexorg/magnetic-ring/core/orgchain/types" 15 "github.com/sixexorg/magnetic-ring/errors" 16 scom "github.com/sixexorg/magnetic-ring/store/mainchain/common" 17 "github.com/sixexorg/magnetic-ring/store/mainchain/extstates" 18 "github.com/sixexorg/magnetic-ring/store/mainchain/storages" 19 orgStorages "github.com/sixexorg/magnetic-ring/store/orgchain/storages" 20 "github.com/sixexorg/magnetic-ring/store/storelaw" 21 ) 22 23 var ( 24 //Storage save path. 25 DBDirBlock = "extblock" 26 DBDirState = "extstates" 27 DBDirMainTx = "extmain" 28 DBDirAccIdx = "extaccidx" 29 DBDirVote = "extvote" 30 DBDirFullTx = "extfull" 31 DBDirUT = "extut" 32 MerkleTreeStorePath = "extmerkle_tree.db" 33 //radarActor *actor.PID 34 ) 35 36 /*func initActor() { 37 if radarActor == nil { 38 actor, err := bactor.GetActorPid(bactor.MAINRADARACTOR) 39 if err != nil { 40 panic(fmt.Errorf("extstorages init radarActor failed,error: %s", err.Error())) 41 } 42 radarActor = actor 43 } 44 } 45 */ 46 //LedgerStoreImp is main store struct fo ledger 47 type LedgerStoreImp struct { 48 blockStore *ExternalLeagueBlock 49 accountStore *ExternalLeague 50 mainTxUsedStore *MainTxUsed 51 acctIdxStore *ExtAccIndexStore 52 voteStore *orgStorages.VoteStore 53 fullTxStore *ExtFullTXStore 54 utStore *ExtUTStore 55 56 LightLedger *storages.LightLedger 57 currBlockHeader map[common.Address]*orgtypes.Header //BlockHash => Header 58 savingBlock bool //is saving block now 59 60 bonusCache map[common.Address]map[uint64]uint64 61 destroyedEnergy map[common.Address]*big.Int 62 lock sync.RWMutex 63 } 64 65 var ledgerStore *LedgerStoreImp 66 67 func (this *LedgerStoreImp) NewBlockBatch() { 68 this.blockStore.NewBatch() 69 } 70 71 func (this *LedgerStoreImp) BlockBatchCommit() error { 72 err := this.blockStore.CommitTo() 73 if err != nil { 74 return err 75 } 76 return nil 77 } 78 func GetLedgerStoreInstance() *LedgerStoreImp { 79 return ledgerStore 80 } 81 82 //NewLedgerStore return LedgerStoreImp instance 83 func NewLedgerStore(dataDir string) (*LedgerStoreImp, error) { 84 if ledgerStore != nil { 85 return ledgerStore, nil 86 } 87 ledgerStore = &LedgerStoreImp{ 88 currBlockHeader: make(map[common.Address]*orgtypes.Header), 89 bonusCache: make(map[common.Address]map[uint64]uint64), 90 destroyedEnergy: make(map[common.Address]*big.Int), 91 } 92 93 accountStore, err := NewExternalLeague(path.Join(dataDir, DBDirState), false) 94 if err != nil { 95 fmt.Fprintf(os.Stderr, "NewExtAccoutStore error %s\n", err) 96 return nil, err 97 } 98 99 ledgerStore.accountStore = accountStore 100 101 blockStore, err := NewExternalLeagueBlock(path.Join(dataDir, DBDirBlock), true) 102 if err != nil { 103 return nil, fmt.Errorf("NewExtBlockStore error %s", err) 104 } 105 ledgerStore.blockStore = blockStore 106 107 mainTxUsed, err := NewMainTxUsed(path.Join(dataDir, DBDirMainTx)) 108 if err != nil { 109 return nil, fmt.Errorf("NewExtMainTxUsedStore error %s", err) 110 } 111 ledgerStore.mainTxUsedStore = mainTxUsed 112 113 accIdxStore, err := NewExtAccIndexStore(path.Join(dataDir, DBDirAccIdx), false) 114 if err != nil { 115 return nil, fmt.Errorf("NewExtAccIndexStore error %s", err) 116 } 117 ledgerStore.acctIdxStore = accIdxStore 118 119 voteStore, err := orgStorages.NewVoteStore(path.Join(dataDir, DBDirVote), byte(scom.EXT_VOTE_STATE), byte(scom.EXT_VOTE_RECORD)) 120 if err != nil { 121 return nil, fmt.Errorf("NewVoteStore error %s", err) 122 } 123 ledgerStore.voteStore = voteStore 124 125 utStore, err := NewExtUTStore(path.Join(dataDir, DBDirUT)) 126 if err != nil { 127 return nil, fmt.Errorf("NewExtUTStore error %s", err) 128 } 129 ledgerStore.utStore = utStore 130 131 fullTxStore, err := NewExtFullTX(path.Join(dataDir, DBDirFullTx)) 132 if err != nil { 133 return nil, fmt.Errorf("NewExtFullTX error %s", err) 134 } 135 ledgerStore.fullTxStore = fullTxStore 136 137 ledgerStore.LightLedger = storages.GetLightLedger() 138 return ledgerStore, nil 139 } 140 func (this *LedgerStoreImp) getCurrentBlockHeader(leagueId common.Address) *orgtypes.Header { 141 this.lock.RLock() 142 defer this.lock.RUnlock() 143 return this.currBlockHeader[leagueId] 144 } 145 146 func (this *LedgerStoreImp) MainTxUsedExist(txHash common.Hash) bool { 147 this.lock.RLock() 148 defer this.lock.RUnlock() 149 return this.mainTxUsedStore.Exist(txHash) 150 } 151 func (this *LedgerStoreImp) GetBlockHashSpan(leagueId common.Address, start, end uint64) (hashArr common.HashArray, gasUsedSum *big.Int, err error) { 152 this.lock.RLock() 153 defer this.lock.RUnlock() 154 return this.blockStore.GetBlockHashSpan(leagueId, start, end) 155 156 } 157 func (this *LedgerStoreImp) GetExtDataByHeight(leagueId common.Address, height uint64) (*extstates.ExtData, error) { 158 this.lock.RLock() 159 defer this.lock.RUnlock() 160 fmt.Printf("🚫 💿 GetExtDataByHeight part0 leagueId:%s,height:%d\n", leagueId.ToString(), height) 161 block, err := this.blockStore.GetBlock(leagueId, height) 162 if err != nil { 163 fmt.Printf("🚫 💿 GetExtDataByHeight part1 err:%s,leagueId:%s,height:%d\n", err, leagueId.ToString(), height) 164 return nil, err 165 } 166 addrs, hashes, err := this.acctIdxStore.Get(height, leagueId) 167 if err != nil { 168 fmt.Printf("🚫 💿 GetExtDataByHeight part2 err:%s,leagueId:%s,height:%d\n", err, leagueId.ToString(), height) 169 return nil, err 170 } 171 accountStates := make([]*extstates.EasyLeagueAccount, len(addrs)) 172 if len(addrs) > 0 { 173 for _, acc := range addrs { 174 extAcc, err := this.accountStore.GetAccountByHeight(acc, leagueId, height) 175 if err != nil { 176 fmt.Printf("🚫 💿 GetExtDataByHeight part3 err:%s,leagueId:%s,height:%d,account:%s\n", err, leagueId.ToString(), height, acc.ToString()) 177 return nil, err 178 } 179 accountStates = append(accountStates, &extstates.EasyLeagueAccount{acc, extAcc}) 180 } //3 181 } 182 ed := new(extstates.ExtData) 183 ed.Height = height 184 ed.LeagueBlock = block 185 ed.MainTxUsed = hashes //2 186 ed.AccountStates = accountStates 187 return ed, nil 188 } 189 190 /*func (this *LedgerStoreImp) GetExtDataMapByHeight(leagueHeight map[common.Address]uint64) []*extstates.ExtData { 191 this.lock.RLock() 192 defer this.lock.RUnlock() 193 wg := new(sync.WaitGroup) 194 wg.Add(len(leagueHeight)) 195 etdCh := make(chan *extstates.ExtData, 1) 196 etds := make([]*extstates.ExtData, 0, len(leagueHeight)) 197 for k, v := range leagueHeight { 198 go func(league common.Address, height uint64) { 199 ed := new(extstates.ExtData) 200 ed.Height = height 201 block, err := this.blockStore.GetBlock(league, height) 202 if err != nil { 203 ed.Err = err 204 etdCh <- ed 205 return 206 } 207 ed.LeagueBlock = block //1 208 addrs, hashes, err := this.acctIdxStore.Get(height, league) 209 if err != nil { 210 etdCh <- ed 211 return 212 } 213 ed.MainTxUsed = hashes //2 214 ed.AccountStates = make(map[common.Address]*extstates.Account, len(addrs)) 215 for _, acc := range addrs { 216 extAcc, err := this.accountStore.GetAccountByHeight(acc, league, height) 217 if err != nil { 218 ed.Err = err 219 } 220 ed.AccountStates[acc] = extAcc 221 } //3 222 etdCh <- ed 223 return 224 }(k, v) 225 } 226 go func() { 227 for ch := range etdCh { 228 etds = append(etds, ch) 229 wg.Done() 230 } 231 }() 232 close(etdCh) 233 return etds 234 }*/ 235 func (this *LedgerStoreImp) SaveAll(blkInfo *storelaw.OrgBlockInfo, mainTxUsed common.HashArray) error { 236 if this.isSavingBlock() { 237 return nil 238 } 239 defer this.resetSavingBlock() 240 if blkInfo.Block == nil { 241 return errors.ERR_COMMON_REFERENCE_EMPTY 242 } 243 currentHeight := this.GetCurrentBlockHeight4V(blkInfo.Block.Header.LeagueId) 244 blockHeight := blkInfo.Block.Header.Height 245 if blockHeight <= currentHeight { 246 return nil 247 } 248 nextBlockHeight := currentHeight + 1 249 if blockHeight != nextBlockHeight { 250 return fmt.Errorf("block height %d not equal next block height %d", blockHeight, nextBlockHeight) 251 } 252 253 leagueBlock := extstates.Block2LeagueBlock(blkInfo.Block) 254 this.blockStore.NewBatch() 255 err := this.blockStore.Save(leagueBlock) 256 if err != nil { 257 return fmt.Errorf("saveBlock error %s", err) 258 } 259 err = this.blockStore.CommitTo() 260 if err != nil { 261 return fmt.Errorf("saveBlock error %s", err) 262 } 263 err = this.saveFullTxs(blkInfo.Block.Header.LeagueId, blkInfo.Block.Header.Height, blkInfo.Block.Transactions) 264 if err != nil { 265 return fmt.Errorf("saveFullTxs error %s", err) 266 } 267 err = this.acctIdxStore.Save(blockHeight, blkInfo.Block.Header.LeagueId, blkInfo.AccStates.GetAccounts(), mainTxUsed) 268 if err != nil { 269 return fmt.Errorf("saveAccIdx error %s", err) 270 } 271 this.accountStore.NewBatch() 272 if err = this.accountStore.BatchSave(blkInfo.AccStates); err != nil { 273 return fmt.Errorf("saveAccountState error %s", err) 274 } 275 if err = this.accountStore.CommitTo(); err != nil { 276 return fmt.Errorf("saveAccountState error %s", err) 277 } 278 this.mainTxUsedStore.NewBatch() 279 if err = this.mainTxUsedStore.BatchSave(mainTxUsed, blkInfo.Block.Header.Height); err != nil { 280 return err 281 } 282 if err = this.mainTxUsedStore.CommitTo(); err != nil { 283 return err 284 } 285 err = this.saveVotes(blkInfo.VoteStates, blkInfo.AccountVoteds, blkInfo.Block.Header.Height) 286 if err != nil { 287 return err 288 } 289 err = this.saveUT(blkInfo.UT, blkInfo.Block.Header.LeagueId, blkInfo.Block.Header.Height) 290 if err != nil { 291 return err 292 } 293 this.setCurrentBlock(blkInfo.Block.Header) 294 this.setDestroyedEnergy(blkInfo.Block.Header, blkInfo.FeeSum) 295 fmt.Printf("🚫 -----S---A---V---E----A---L---L--- Height:%d TxLen:%d blockHash:%s bonus:%d \n", 296 blkInfo.Block.Header.Height, 297 blkInfo.Block.Transactions.Len(), 298 blkInfo.Block.Hash().String(), 299 blkInfo.Block.Header.Bonus, 300 ) 301 return nil 302 } 303 func (this *LedgerStoreImp) saveVotes(voteStates []*storelaw.VoteState, AccountVoteds []*storelaw.AccountVoted, height uint64) error { 304 this.voteStore.NewBatch() 305 this.voteStore.SaveVotes(voteStates) 306 this.voteStore.SaveAccountVoted(AccountVoteds, height) 307 err := this.voteStore.CommitTo() 308 return err 309 } 310 func (this *LedgerStoreImp) saveUT(ut *big.Int, leagueId common.Address, height uint64) error { 311 fmt.Println("🚫 mainchain saveUT ", ut.Uint64(), leagueId.ToString(), height) 312 amount := this.utStore.GetUTByHeight(height, leagueId) 313 if amount.Cmp(ut) == 0 { 314 return nil 315 } 316 return this.utStore.Save(height, leagueId, ut) 317 } 318 func (this *LedgerStoreImp) saveFullTxs(leagueId common.Address, height uint64, txs orgtypes.Transactions) error { 319 voteSources := make(orgtypes.Transactions, 0) 320 for _, v := range txs { 321 if v.TxType == orgtypes.VoteIncreaseUT { 322 voteSources = append(voteSources, v) 323 } 324 } 325 if voteSources.Len() > 0 { 326 err := this.fullTxStore.SaveTxs(leagueId, height, voteSources) 327 return err 328 } 329 return nil 330 } 331 332 func (this *LedgerStoreImp) isSavingBlock() bool { 333 this.lock.Lock() 334 defer this.lock.Unlock() 335 336 if !this.savingBlock { 337 this.savingBlock = true 338 return false 339 } 340 return true 341 } 342 343 func (this *LedgerStoreImp) resetSavingBlock() { 344 this.lock.Lock() 345 defer this.lock.Unlock() 346 this.savingBlock = false 347 } 348 349 func (this *LedgerStoreImp) setCurrentBlock(header *orgtypes.Header) { 350 this.lock.Lock() 351 defer this.lock.Unlock() 352 this.currBlockHeader[header.LeagueId] = header 353 if header.Height%types.HWidth == 0 { 354 if this.bonusCache[header.LeagueId] == nil { 355 this.bonusCache[header.LeagueId] = make(map[uint64]uint64) 356 } 357 this.bonusCache[header.LeagueId][header.Height] = header.Bonus 358 } 359 return 360 } 361 362 func (this *LedgerStoreImp) setDestroyedEnergy(header *orgtypes.Header, feeSum *big.Int) { 363 this.lock.Lock() 364 defer this.lock.Unlock() 365 if header.Height%types.HWidth == 0 { 366 if this.destroyedEnergy[header.LeagueId] == nil { 367 this.destroyedEnergy[header.LeagueId] = big.NewInt(0) 368 } 369 this.destroyedEnergy[header.LeagueId].SetUint64(0) 370 } 371 rat := new(big.Rat).Set(orgtypes.BonusRate) 372 rat.Mul(rat, new(big.Rat).SetInt(feeSum)) 373 rfTmp := big.NewFloat(0).SetRat(rat) 374 integer, _ := rfTmp.Uint64() 375 this.destroyedEnergy[header.LeagueId].Add(this.destroyedEnergy[header.LeagueId], big.NewInt(int64(integer))) 376 } 377 378 ////////////////////Ledger4Validation/////////////////// 379 func (this *LedgerStoreImp) GetBlockHashByHeight4V(leagueId common.Address, height uint64) (common.Hash, error) { 380 this.lock.RLock() 381 defer this.lock.RUnlock() 382 return this.blockStore.GetBlockHash(leagueId, height) 383 } 384 func (this *LedgerStoreImp) GetCurrentBlockHeight4V(leagueId common.Address) uint64 { 385 this.lock.RLock() 386 defer this.lock.RUnlock() 387 if this.currBlockHeader[leagueId] == nil { 388 return 0 389 } 390 return this.currBlockHeader[leagueId].Height 391 } 392 func (this *LedgerStoreImp) GetPrevAccount4V(height uint64, account, leagueId common.Address) (storelaw.AccountStater, error) { 393 this.lock.RLock() 394 defer this.lock.RUnlock() 395 return this.accountStore.GetPrev(height, account, leagueId) 396 } 397 398 func (this *LedgerStoreImp) GetCurrentHeaderHash4V(leagueId common.Address) common.Hash { 399 this.lock.RLock() 400 defer this.lock.RUnlock() 401 if this.currBlockHeader[leagueId] == nil { 402 return common.Hash{} 403 } 404 return this.currBlockHeader[leagueId].Hash() 405 } 406 func (this *LedgerStoreImp) ContainTx4V(txHash common.Hash) bool { 407 return true 408 } 409 410 func (this *LedgerStoreImp) GetVoteState(voteId common.Hash, height uint64) (*storelaw.VoteState, error) { 411 return this.voteStore.GetVoteState(voteId, height) 412 } 413 func (this *LedgerStoreImp) AlreadyVoted(voteId common.Hash, account common.Address) bool { 414 return this.voteStore.AlreadyVoted(voteId, account) 415 } 416 func (this *LedgerStoreImp) GetUTByHeight(height uint64, leagueId common.Address) *big.Int { 417 return this.utStore.GetUTByHeight(height, leagueId) 418 /*this.utStore.GetUTByHeight(height, leagueId) 419 fmt.Println("💗 💗 💗 💗 💗 💗 p1", height, leagueId.ToString()) 420 ls, err := this.lightLedger.GetLeagueByHeight(height, leagueId) 421 fmt.Println("💗 💗 💗 💗 💗 💗 p1.5", ls, err) 422 rate := uint32(0) 423 if err != nil { 424 return big.NewInt(0) 425 fmt.Println("💗 💗 💗 💗 💗 💗 p2") 426 } else { 427 rate, _, _, err = this.lightLedger.GetMetaData(leagueId) 428 fmt.Println("💗 💗 💗 💗 💗 💗 p3", rate, err) 429 } 430 fmt.Printf("💗 💗 💗 💗 💗 💗 p4 %v", ls) 431 ut := big.NewInt(0) 432 ut.Mul(ls.Data.FrozenBox, big.NewInt(0).SetUint64(uint64(rate)))*/ 433 } 434 func (this *LedgerStoreImp) GetBonus(leagueId common.Address) map[uint64]uint64 { 435 return this.bonusCache[leagueId] 436 } 437 func (this *LedgerStoreImp) GetTransaction(txHash common.Hash, leagueId common.Address) (*orgtypes.Transaction, uint64, error) { 438 return this.fullTxStore.GetTx(leagueId, txHash) 439 } 440 func (this *LedgerStoreImp) GetHeaderBonus(leagueId common.Address) *big.Int { 441 b := this.destroyedEnergy[leagueId] 442 if b == nil { 443 return big.NewInt(0) 444 } 445 return b 446 } 447 func (this *LedgerStoreImp) GetAccountRange(start, end uint64, account, leagueId common.Address) (storelaw.AccountStaters, error) { 448 return this.accountStore.GetAccountRange(start, end, account, leagueId) 449 } 450 451 ////////////////////Ledger4Validation///////////////////