github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/store/mainchain/extstorages/league_block.go (about) 1 package extstorages 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 7 "math/big" 8 9 "io" 10 11 "github.com/syndtr/goleveldb/leveldb/util" 12 "github.com/sixexorg/magnetic-ring/common" 13 "github.com/sixexorg/magnetic-ring/common/sink" 14 "github.com/sixexorg/magnetic-ring/store/db" 15 scom "github.com/sixexorg/magnetic-ring/store/mainchain/common" 16 "github.com/sixexorg/magnetic-ring/store/mainchain/extstates" 17 ) 18 19 type ExternalLeagueBlock struct { 20 enableCache bool 21 dbDir string 22 store *db.LevelDBStore 23 } 24 25 func NewExternalLeagueBlock(dbDir string, enableCache bool) (*ExternalLeagueBlock, error) { 26 store, err := db.NewLevelDBStore(dbDir) 27 if err != nil { 28 return nil, err 29 } 30 el := new(ExternalLeagueBlock) 31 32 el.enableCache = enableCache 33 el.dbDir = dbDir 34 el.store = store 35 return el, nil 36 } 37 38 //NewBatch start a commit batch 39 func (this *ExternalLeagueBlock) NewBatch() { 40 this.store.NewBatch() 41 } 42 func (this *ExternalLeagueBlock) CommitTo() error { 43 return this.store.BatchCommit() 44 } 45 46 func (this *ExternalLeagueBlock) GetBlockHash(leagueId common.Address, height uint64) (common.Hash, error) { 47 key := this.getBlockHashKey(leagueId, height) 48 value, err := this.store.Get(key) 49 if err != nil { 50 return common.Hash{}, err 51 } 52 sk := sink.NewZeroCopySource(value) 53 blockHash, eof := sk.NextHash() 54 if eof { 55 return common.Hash{}, io.ErrUnexpectedEOF 56 } 57 return blockHash, nil 58 } 59 60 func (this *ExternalLeagueBlock) GetBlock(leagueId common.Address, height uint64) (*extstates.LeagueBlockSimple, error) { 61 hash, err := this.GetBlockHash(leagueId, height) 62 if err != nil { 63 return nil, err 64 } 65 key := this.getHeaderKey(hash) 66 val, err := this.store.Get(key) 67 if err != nil { 68 return nil, err 69 } 70 block := &extstates.LeagueBlockSimple{} 71 buff := bytes.NewBuffer(val) 72 err = block.Deserialize(buff) 73 if err != nil { 74 return nil, err 75 } 76 return block, nil 77 } 78 79 func (this *ExternalLeagueBlock) GetBlockHashSpan(leagueId common.Address, left, right uint64) (hashArr common.HashArray, gasUsedSum *big.Int, err error) { 80 leftKey := this.getBlockHashKey(leagueId, left) 81 rightKey := this.getBlockHashKey(leagueId, right+1) 82 iter := this.store.NewSeniorIterator(&util.Range{ 83 Start: leftKey, 84 Limit: rightKey, 85 }) 86 hashes := make(common.HashArray, 0, right-left+1) 87 gasSum := big.NewInt(0) 88 for iter.Next() { 89 value := iter.Value() 90 sk := sink.NewZeroCopySource(value) 91 blockHash, eof := sk.NextHash() 92 if eof { 93 return nil, nil, io.ErrUnexpectedEOF 94 } 95 cp, eof := sk.NextComplex() 96 if eof { 97 return nil, nil, io.ErrUnexpectedEOF 98 } 99 gasUsed, err := cp.ComplexToBigInt() 100 if err != nil { 101 return nil, nil, err 102 } 103 gasSum.Add(gasSum, gasUsed) 104 hashes = append(hashes, blockHash) 105 } 106 iter.Release() 107 err = iter.Error() 108 if err != nil { 109 return nil, nil, err 110 } 111 return hashes, gasSum, nil 112 } 113 114 //SaveBlock persist block to store 115 func (this *ExternalLeagueBlock) Save(block *extstates.LeagueBlockSimple) error { 116 blockHash := block.Header.Hash() 117 err := this.saveBlockHash(block.Header.LeagueId, block.Header.Height, blockHash, block.EnergyUsed) 118 if err != nil { 119 return err 120 } 121 buff := new(bytes.Buffer) 122 err = block.Serialize(buff) 123 if err != nil { 124 return err 125 } 126 key := this.getHeaderKey(blockHash) 127 this.store.BatchPut(key, buff.Bytes()) 128 return nil 129 } 130 func (this *ExternalLeagueBlock) BatchSave(blocks []*extstates.LeagueBlockSimple) error { 131 leagueKey := make(map[common.Address]bool) 132 for _, v := range blocks { 133 leagueKey[v.Header.LeagueId] = true 134 } 135 var err error 136 for _, v := range blocks { 137 blockHash := v.Header.Hash() 138 err = this.saveBlockHash(v.Header.LeagueId, v.Header.Height, blockHash, v.EnergyUsed) 139 if err != nil { 140 return err 141 } 142 buff := new(bytes.Buffer) 143 err = v.Serialize(buff) 144 if err != nil { 145 return err 146 } 147 key := this.getHeaderKey(blockHash) 148 this.store.BatchPut(key, buff.Bytes()) 149 } 150 return nil 151 } 152 153 func (this *ExternalLeagueBlock) saveBlockHash(leagueId common.Address, height uint64, blockHash common.Hash, gasUsed *big.Int) error { 154 key := this.getBlockHashKey(leagueId, height) 155 sk := sink.NewZeroCopySink(nil) 156 sk.WriteBytes(blockHash[:]) 157 cp, err := sink.BigIntToComplex(gasUsed) 158 if err != nil { 159 return err 160 } 161 sk.WriteComplex(cp) 162 this.store.BatchPut(key, sk.Bytes()) 163 return nil 164 } 165 func (this *ExternalLeagueBlock) getHeaderKey(blockHash common.Hash) []byte { 166 buff := make([]byte, 1+common.HashLength) 167 buff[0] = byte(scom.EXT_LEAGUE_DATA_HEADER) 168 copy(buff[1:common.HashLength+1], blockHash[:]) 169 return buff 170 } 171 func (this *ExternalLeagueBlock) getBlockHashKey(leagueId common.Address, height uint64) []byte { 172 buff := make([]byte, 1+common.AddrLength+8) 173 buff[0] = byte(scom.EXT_LEAGUE_DATA_BLOCK) 174 copy(buff[1:common.AddrLength+1], leagueId[:]) 175 binary.LittleEndian.PutUint64(buff[common.AddrLength+1:], height) 176 return buff 177 }