github.com/annchain/OG@v0.0.9/arefactor_core/core/confirm_batch.go (about) 1 package core 2 3 import ( 4 ogTypes "github.com/annchain/OG/arefactor/og_interface" 5 "github.com/annchain/OG/arefactor/types" 6 "github.com/annchain/OG/arefactor_core/core/state" 7 "github.com/annchain/OG/common/math" 8 "github.com/annchain/OG/ogdb" 9 ) 10 11 type CachedConfirms struct { 12 //highest *ConfirmBatch 13 fronts []*ConfirmBatch 14 batches map[ogTypes.HashKey]*ConfirmBatch 15 } 16 17 func newCachedConfirms() *CachedConfirms { 18 return &CachedConfirms{ 19 //highest: nil, 20 fronts: make([]*ConfirmBatch, 0), 21 batches: make(map[ogTypes.HashKey]*ConfirmBatch), 22 } 23 } 24 25 func (c *CachedConfirms) stop() { 26 for _, batch := range c.batches { 27 batch.stop() 28 } 29 } 30 31 func (c *CachedConfirms) getConfirmBatch(seqHash ogTypes.Hash) *ConfirmBatch { 32 return c.batches[seqHash.HashKey()] 33 } 34 35 //func (c *CachedConfirms) existTx(seqHash ogTypes.Hash, txHash ogTypes.Hash) bool { 36 // batch := c.batches[seqHash.HashKey()] 37 // if batch != nil { 38 // return batch.existTx(txHash) 39 // } 40 // //return c.ledger.GetTx(txHash) != nil 41 // return false 42 //} 43 44 func (c *CachedConfirms) existTx(baseBatchHash ogTypes.Hash, hash ogTypes.Hash) bool { 45 baseBatch := c.getConfirmBatch(baseBatchHash) 46 for baseBatch != nil { 47 if baseBatch.existCurrentTx(hash) { 48 return true 49 } 50 baseBatch = baseBatch.parent 51 } 52 return false 53 } 54 55 func (c *CachedConfirms) getTxAndReceipt(hash ogTypes.Hash) (types.Txi, *Receipt) { 56 for _, batch := range c.batches { 57 if batch.existCurrentTx(hash) { 58 return batch.getCurrentTx(hash), batch.getCurrentReceipt(hash) 59 } 60 } 61 return nil, nil 62 } 63 64 func (c *CachedConfirms) getTxByNonce(baseBatchHash ogTypes.Hash, addr ogTypes.Address, nonce uint64) types.Txi { 65 baseBatch := c.getConfirmBatch(baseBatchHash) 66 for baseBatch != nil { 67 txi := baseBatch.getCurrentTxByNonce(addr, nonce) 68 if txi != nil { 69 return txi 70 } 71 baseBatch = baseBatch.parent 72 } 73 return nil 74 } 75 76 // getTxsByHeight searching txs by sequencer height, traverse from leaf to root 77 func (c *CachedConfirms) getTxsByHeight(baseBatchHash ogTypes.Hash, height uint64) []types.Txi { 78 baseBatch := c.getConfirmBatch(baseBatchHash) 79 for baseBatch != nil { 80 if baseBatch.seq.GetHeight() < height { 81 return nil 82 } 83 if baseBatch.seq.GetHeight() == height { 84 return baseBatch.elders 85 } 86 baseBatch = baseBatch.parent 87 } 88 return nil 89 } 90 91 // getSeqByHeight searching sequencer by sequencer height, traverse from leaf to root 92 func (c *CachedConfirms) getSeqByHeight(baseBatchHash ogTypes.Hash, height uint64) *types.Sequencer { 93 baseBatch := c.getConfirmBatch(baseBatchHash) 94 for baseBatch != nil { 95 if baseBatch.seq.GetHeight() < height { 96 return nil 97 } 98 if baseBatch.seq.GetHeight() == height { 99 return baseBatch.seq 100 } 101 baseBatch = baseBatch.parent 102 } 103 return nil 104 } 105 106 func (c *CachedConfirms) push(hashKey ogTypes.Hash, batch *ConfirmBatch) { 107 parentBatch := c.getConfirmBatch(batch.seq.GetParentSeqHash()) 108 if parentBatch == nil { 109 c.fronts = append(c.fronts, batch) 110 } else { 111 parentBatch.bindChildren(batch) 112 batch.bindParent(parentBatch) 113 } 114 c.batches[hashKey.HashKey()] = batch 115 116 //// set highest batch 117 //if c.highest != nil && c.highest.seq.GetHeight() >= batch.seq.GetHeight() { 118 // return 119 //} 120 //c.highest = batch 121 } 122 123 // purePush only store the ConfirmBatch to the batch map, regardless the fronts 124 func (c *CachedConfirms) purePush(hash ogTypes.Hash, batch *ConfirmBatch) { 125 c.batches[hash.HashKey()] = batch 126 } 127 128 // pureDelete only delete the ConfirmBatch from batch map, regardless fronts 129 func (c *CachedConfirms) pureDelete(hash ogTypes.Hash) { 130 delete(c.batches, hash.HashKey()) 131 } 132 133 func (c *CachedConfirms) confirm(batch *ConfirmBatch) { 134 // delete conflicts batches 135 for _, batchToDelete := range c.fronts { 136 //batchToDelete := c.fronts[i] 137 if batchToDelete.isSame(batch) { 138 continue 139 } 140 c.traverseFromRoot(batchToDelete, func(b *ConfirmBatch) { 141 delete(c.batches, b.seq.GetTxHash().HashKey()) 142 }) 143 } 144 c.fronts = batch.children 145 146 // unbind children's parent to nil 147 for _, childBatch := range batch.children { 148 childBatch.confirmParent(batch) 149 } 150 } 151 152 // traverseFromRoot traverse the cached ConfirmBatch trees and process the function "f" for 153 // every found confirm batches. 154 func (c *CachedConfirms) traverseFromRoot(root *ConfirmBatch, f func(b *ConfirmBatch)) { 155 seekingPool := make([]*ConfirmBatch, 0) 156 seekingPool = append(seekingPool, root) 157 158 seeked := make(map[ogTypes.HashKey]struct{}) 159 for len(seekingPool) > 0 { 160 batch := seekingPool[0] 161 seekingPool = seekingPool[1:] 162 163 f(batch) 164 for _, newBatch := range batch.children { 165 if _, alreadySeeked := seeked[newBatch.seq.GetTxHash().HashKey()]; alreadySeeked { 166 continue 167 } 168 seekingPool = append(seekingPool, newBatch) 169 } 170 seeked[batch.seq.GetTxHash().HashKey()] = struct{}{} 171 } 172 } 173 174 func (c *CachedConfirms) traverseFromLeaf(leaf *ConfirmBatch, f func(b *ConfirmBatch)) { 175 seekingPool := make([]*ConfirmBatch, 0) 176 seekingPool = append(seekingPool, leaf) 177 178 for len(seekingPool) > 0 { 179 batch := seekingPool[0] 180 seekingPool = seekingPool[1:] 181 182 f(batch) 183 seekingPool = append(seekingPool, batch.parent) 184 } 185 } 186 187 type ConfirmBatch struct { 188 //tempLedger Ledger 189 //ledger Ledger 190 191 parent *ConfirmBatch 192 children []*ConfirmBatch 193 194 db *state.StateDB 195 seq *types.Sequencer 196 seqReceipt *Receipt 197 txReceipts ReceiptSet 198 elders []types.Txi 199 eldersQueryMap map[ogTypes.HashKey]types.Txi 200 eldersQueryNonce map[ogTypes.AddressKey]*TxList 201 202 //db map[ogTypes.AddressKey]*accountDetail 203 } 204 205 func newConfirmBatch(seq *types.Sequencer, db ogdb.Database, baseRoot ogTypes.Hash) (*ConfirmBatch, error) { 206 stateDB, err := state.NewStateDB(state.DefaultStateDBConfig(), state.NewDatabase(db), baseRoot) 207 if err != nil { 208 return nil, err 209 } 210 c := &ConfirmBatch{ 211 parent: nil, 212 children: make([]*ConfirmBatch, 0), 213 db: stateDB, 214 seq: seq, 215 seqReceipt: nil, 216 txReceipts: nil, 217 elders: make([]types.Txi, 0), 218 eldersQueryMap: make(map[ogTypes.HashKey]types.Txi), 219 } 220 return c, nil 221 } 222 223 func (c *ConfirmBatch) stop() { 224 c.db.Stop() 225 } 226 227 //func (c *ConfirmBatch) construct(elders map[ogTypes.HashKey]types.Txi) error { 228 // for _, txi := range elders { 229 // // return error if a sequencer confirm a tx that has same nonce as itself. 230 // if txi.Sender() == c.seq.Sender() && txi.GetNonce() == c.seq.GetNonce() { 231 // return fmt.Errorf("seq's nonce is the same as a tx it confirmed, nonce: %d, tx hash: %s", 232 // c.seq.GetNonce(), txi.GetTxHash()) 233 // } 234 // 235 // switch tx := txi.(type) { 236 // case *types.Sequencer: 237 // break 238 // case *types.Tx: 239 // //c.processTx(tx) 240 // // TODO 241 // default: 242 // c.addTx(tx) 243 // } 244 // } 245 // return nil 246 //} 247 248 //func (c *ConfirmBatch) isValid() error { 249 // // verify balance and nonce 250 // for _, accountDetail := range c.getDetails() { 251 // err := accountDetail.isValid() 252 // if err != nil { 253 // return err 254 // } 255 // } 256 // return nil 257 //} 258 259 func (c *ConfirmBatch) isSame(cb *ConfirmBatch) bool { 260 return c.seq.GetTxHash().Cmp(cb.seq.GetTxHash()) == 0 261 } 262 263 //func (c *ConfirmBatch) getOrCreateDetail(addr ogTypes.Address) *accountDetail { 264 // detailCost := c.getDetail(addr) 265 // if detailCost == nil { 266 // detailCost = c.createDetail(addr) 267 // } 268 // return detailCost 269 //} 270 // 271 //func (c *ConfirmBatch) getDetail(addr ogTypes.Address) *accountDetail { 272 // return c.db[addr.AddressKey()] 273 //} 274 // 275 //func (c *ConfirmBatch) getDetails() map[ogTypes.AddressKey]*accountDetail { 276 // return c.db 277 //} 278 // 279 //func (c *ConfirmBatch) createDetail(addr ogTypes.Address) *accountDetail { 280 // c.db[addr.AddressKey()] = newBatchDetail(addr, c) 281 // return c.db[addr.AddressKey()] 282 //} 283 // 284 //func (c *ConfirmBatch) setDetail(detail *accountDetail) { 285 // c.db[detail.address.AddressKey()] = detail 286 //} 287 288 //func (c *ConfirmBatch) processTx(txi types.Txi) { 289 // if txi.GetType() != types.TxBaseTypeNormal { 290 // return 291 // } 292 // tx := txi.(*types.Tx) 293 // 294 // detailCost := c.getOrCreateDetail(tx.From) 295 // detailCost.addCost(tx.TokenId, tx.Value) 296 // detailCost.addTx(tx) 297 // c.setDetail(detailCost) 298 // 299 // detailEarn := c.getOrCreateDetail(tx.To) 300 // detailEarn.addEarn(tx.TokenId, tx.Value) 301 // c.setDetail(detailEarn) 302 // 303 // c.addTxToElders(tx) 304 //} 305 306 // addTx adds tx only without any processing. 307 func (c *ConfirmBatch) addTx(tx types.Txi) { 308 //detailSender := c.getOrCreateDetail(tx.Sender()) 309 //detailSender.addTx(tx) 310 311 c.addTxToElders(tx) 312 } 313 314 func (c *ConfirmBatch) addTxToElders(tx types.Txi) { 315 c.elders = append(c.elders, tx) 316 c.eldersQueryMap[tx.GetTxHash().HashKey()] = tx 317 318 txList := c.eldersQueryNonce[tx.Sender().AddressKey()] 319 if txList == nil { 320 txList = NewTxList() 321 } 322 txList.Put(tx) 323 c.eldersQueryNonce[tx.Sender().AddressKey()] = txList 324 } 325 326 func (c *ConfirmBatch) existCurrentTx(hash ogTypes.Hash) bool { 327 return c.eldersQueryMap[hash.HashKey()] != nil 328 } 329 330 // existTx checks if input tx exists in current confirm batch. If not 331 // exists, then check parents confirm batch and check DAG ledger at last. 332 func (c *ConfirmBatch) existTx(hash ogTypes.Hash) bool { 333 exists := c.existCurrentTx(hash) 334 if exists { 335 return exists 336 } 337 if c.parent != nil { 338 return c.parent.existTx(hash) 339 } 340 return false 341 } 342 343 func (c *ConfirmBatch) getCurrentTx(hash ogTypes.Hash) types.Txi { 344 return c.eldersQueryMap[hash.HashKey()] 345 } 346 347 func (c *ConfirmBatch) getCurrentTxByNonce(addr ogTypes.Address, nonce uint64) types.Txi { 348 txList := c.eldersQueryNonce[addr.AddressKey()] 349 if txList == nil { 350 return nil 351 } 352 return txList.Get(nonce) 353 } 354 355 func (c *ConfirmBatch) existSeq(seqHash ogTypes.Hash) bool { 356 if c.seq.GetTxHash().Cmp(seqHash) == 0 { 357 return true 358 } 359 if c.parent != nil { 360 return c.parent.existSeq(seqHash) 361 } 362 //return c.ledger.GetTx(seqHash) != nil 363 return false 364 } 365 366 func (c *ConfirmBatch) getCurrentReceipt(hash ogTypes.Hash) *Receipt { 367 if c.seq.GetTxHash().Cmp(hash) == 0 { 368 return c.seqReceipt 369 } 370 return c.txReceipts[hash.HashKey()] 371 } 372 373 //func (c *ConfirmBatch) getCurrentBalance(addr ogTypes.Address, tokenID int32) *math.BigInt { 374 // detail := c.getDetail(addr) 375 // if detail == nil { 376 // return nil 377 // } 378 // return detail.getBalance(tokenID) 379 //} 380 381 // getBalance get balance from its own StateDB 382 func (c *ConfirmBatch) getBalance(addr ogTypes.Address, tokenID int32) *math.BigInt { 383 return c.db.GetTokenBalance(addr, tokenID) 384 385 //blc := c.getCurrentBalance(addr, tokenID) 386 //if blc != nil { 387 // return blc 388 //} 389 //return c.getConfirmedBalance(addr, tokenID) 390 } 391 392 //func (c *ConfirmBatch) getConfirmedBalance(addr ogTypes.Address, tokenID int32) *math.BigInt { 393 // if c.parent != nil { 394 // return c.parent.getBalance(addr, tokenID) 395 // } 396 // return c.ledger.GetBalance(addr, tokenID) 397 //} 398 399 //func (c *ConfirmBatch) getCurrentLatestNonce(addr ogTypes.Address) (uint64, error) { 400 // detail := c.getDetail(addr) 401 // if detail == nil { 402 // return 0, fmt.Errorf("can't find latest nonce for addr: %s", addr.Hex()) 403 // } 404 // return detail.getNonce() 405 //} 406 407 // getLatestNonce get latest nonce from its own StateDB 408 func (c *ConfirmBatch) getLatestNonce(addr ogTypes.Address) uint64 { 409 return c.db.GetNonce(addr) 410 411 //nonce, err := c.getCurrentLatestNonce(addr) 412 //if err == nil { 413 // return nonce, nil 414 //} 415 //return c.getConfirmedLatestNonce(addr) 416 } 417 418 //// getConfirmedLatestNonce get latest nonce from parents and DAG ledger. Note 419 //// that this confirm batch itself is not included in this nonce search. 420 //func (c *ConfirmBatch) getConfirmedLatestNonce(addr ogTypes.Address) (uint64, error) { 421 // if c.parent != nil { 422 // return c.parent.getLatestNonce(addr) 423 // } 424 // return c.ledger.GetLatestNonce(addr) 425 //} 426 427 func (c *ConfirmBatch) bindParent(parent *ConfirmBatch) { 428 c.parent = parent 429 } 430 431 func (c *ConfirmBatch) bindChildren(child *ConfirmBatch) { 432 c.children = append(c.children, child) 433 } 434 435 func (c *ConfirmBatch) confirmParent(confirmed *ConfirmBatch) { 436 if c.parent.seq.Hash.Cmp(confirmed.seq.Hash) != 0 { 437 return 438 } 439 c.parent = nil 440 }