github.com/ylsGit/go-ethereum@v1.6.5/light/txpool.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package light 18 19 import ( 20 "context" 21 "fmt" 22 "sync" 23 "time" 24 25 "github.com/ethereum/go-ethereum/common" 26 "github.com/ethereum/go-ethereum/core" 27 "github.com/ethereum/go-ethereum/core/types" 28 "github.com/ethereum/go-ethereum/ethdb" 29 "github.com/ethereum/go-ethereum/event" 30 "github.com/ethereum/go-ethereum/log" 31 "github.com/ethereum/go-ethereum/params" 32 "github.com/ethereum/go-ethereum/rlp" 33 ) 34 35 // txPermanent is the number of mined blocks after a mined transaction is 36 // considered permanent and no rollback is expected 37 var txPermanent = uint64(500) 38 39 // TxPool implements the transaction pool for light clients, which keeps track 40 // of the status of locally created transactions, detecting if they are included 41 // in a block (mined) or rolled back. There are no queued transactions since we 42 // always receive all locally signed transactions in the same order as they are 43 // created. 44 type TxPool struct { 45 config *params.ChainConfig 46 signer types.Signer 47 quit chan bool 48 eventMux *event.TypeMux 49 events *event.TypeMuxSubscription 50 mu sync.RWMutex 51 chain *LightChain 52 odr OdrBackend 53 chainDb ethdb.Database 54 relay TxRelayBackend 55 head common.Hash 56 nonce map[common.Address]uint64 // "pending" nonce 57 pending map[common.Hash]*types.Transaction // pending transactions by tx hash 58 mined map[common.Hash][]*types.Transaction // mined transactions by block hash 59 clearIdx uint64 // earliest block nr that can contain mined tx info 60 61 homestead bool 62 } 63 64 // TxRelayBackend provides an interface to the mechanism that forwards transacions 65 // to the ETH network. The implementations of the functions should be non-blocking. 66 // 67 // Send instructs backend to forward new transactions 68 // NewHead notifies backend about a new head after processed by the tx pool, 69 // including mined and rolled back transactions since the last event 70 // Discard notifies backend about transactions that should be discarded either 71 // because they have been replaced by a re-send or because they have been mined 72 // long ago and no rollback is expected 73 type TxRelayBackend interface { 74 Send(txs types.Transactions) 75 NewHead(head common.Hash, mined []common.Hash, rollback []common.Hash) 76 Discard(hashes []common.Hash) 77 } 78 79 // NewTxPool creates a new light transaction pool 80 func NewTxPool(config *params.ChainConfig, eventMux *event.TypeMux, chain *LightChain, relay TxRelayBackend) *TxPool { 81 pool := &TxPool{ 82 config: config, 83 signer: types.HomesteadSigner{}, 84 nonce: make(map[common.Address]uint64), 85 pending: make(map[common.Hash]*types.Transaction), 86 mined: make(map[common.Hash][]*types.Transaction), 87 quit: make(chan bool), 88 eventMux: eventMux, 89 events: eventMux.Subscribe(core.ChainHeadEvent{}), 90 chain: chain, 91 relay: relay, 92 odr: chain.Odr(), 93 chainDb: chain.Odr().Database(), 94 head: chain.CurrentHeader().Hash(), 95 clearIdx: chain.CurrentHeader().Number.Uint64(), 96 } 97 go pool.eventLoop() 98 99 return pool 100 } 101 102 // currentState returns the light state of the current head header 103 func (pool *TxPool) currentState() *LightState { 104 return NewLightState(StateTrieID(pool.chain.CurrentHeader()), pool.odr) 105 } 106 107 // GetNonce returns the "pending" nonce of a given address. It always queries 108 // the nonce belonging to the latest header too in order to detect if another 109 // client using the same key sent a transaction. 110 func (pool *TxPool) GetNonce(ctx context.Context, addr common.Address) (uint64, error) { 111 nonce, err := pool.currentState().GetNonce(ctx, addr) 112 if err != nil { 113 return 0, err 114 } 115 sn, ok := pool.nonce[addr] 116 if ok && sn > nonce { 117 nonce = sn 118 } 119 if !ok || sn < nonce { 120 pool.nonce[addr] = nonce 121 } 122 return nonce, nil 123 } 124 125 type txBlockData struct { 126 BlockHash common.Hash 127 BlockIndex uint64 128 Index uint64 129 } 130 131 // storeTxBlockData stores the block position of a mined tx in the local db 132 func (pool *TxPool) storeTxBlockData(txh common.Hash, tbd txBlockData) { 133 //fmt.Println("storeTxBlockData", txh, tbd) 134 data, _ := rlp.EncodeToBytes(tbd) 135 pool.chainDb.Put(append(txh[:], byte(1)), data) 136 } 137 138 // removeTxBlockData removes the stored block position of a rolled back tx 139 func (pool *TxPool) removeTxBlockData(txh common.Hash) { 140 //fmt.Println("removeTxBlockData", txh) 141 pool.chainDb.Delete(append(txh[:], byte(1))) 142 } 143 144 // txStateChanges stores the recent changes between pending/mined states of 145 // transactions. True means mined, false means rolled back, no entry means no change 146 type txStateChanges map[common.Hash]bool 147 148 // setState sets the status of a tx to either recently mined or recently rolled back 149 func (txc txStateChanges) setState(txHash common.Hash, mined bool) { 150 val, ent := txc[txHash] 151 if ent && (val != mined) { 152 delete(txc, txHash) 153 } else { 154 txc[txHash] = mined 155 } 156 } 157 158 // getLists creates lists of mined and rolled back tx hashes 159 func (txc txStateChanges) getLists() (mined []common.Hash, rollback []common.Hash) { 160 for hash, val := range txc { 161 if val { 162 mined = append(mined, hash) 163 } else { 164 rollback = append(rollback, hash) 165 } 166 } 167 return 168 } 169 170 // checkMinedTxs checks newly added blocks for the currently pending transactions 171 // and marks them as mined if necessary. It also stores block position in the db 172 // and adds them to the received txStateChanges map. 173 func (pool *TxPool) checkMinedTxs(ctx context.Context, hash common.Hash, idx uint64, txc txStateChanges) error { 174 //fmt.Println("checkMinedTxs") 175 if len(pool.pending) == 0 { 176 return nil 177 } 178 //fmt.Println("len(pool) =", len(pool.pending)) 179 180 block, err := GetBlock(ctx, pool.odr, hash, idx) 181 var receipts types.Receipts 182 if err != nil { 183 //fmt.Println(err) 184 return err 185 } 186 //fmt.Println("len(block.Transactions()) =", len(block.Transactions())) 187 188 list := pool.mined[hash] 189 for i, tx := range block.Transactions() { 190 txHash := tx.Hash() 191 //fmt.Println(" txHash:", txHash) 192 if tx, ok := pool.pending[txHash]; ok { 193 //fmt.Println("TX FOUND") 194 if receipts == nil { 195 receipts, err = GetBlockReceipts(ctx, pool.odr, hash, idx) 196 if err != nil { 197 return err 198 } 199 if len(receipts) != len(block.Transactions()) { 200 panic(nil) // should never happen if hashes did match 201 } 202 core.SetReceiptsData(pool.config, block, receipts) 203 } 204 //fmt.Println("WriteReceipt", receipts[i].TxHash) 205 core.WriteReceipt(pool.chainDb, receipts[i]) 206 pool.storeTxBlockData(txHash, txBlockData{hash, idx, uint64(i)}) 207 delete(pool.pending, txHash) 208 list = append(list, tx) 209 txc.setState(txHash, true) 210 } 211 } 212 if list != nil { 213 pool.mined[hash] = list 214 } 215 return nil 216 } 217 218 // rollbackTxs marks the transactions contained in recently rolled back blocks 219 // as rolled back. It also removes block position info from the db and adds them 220 // to the received txStateChanges map. 221 func (pool *TxPool) rollbackTxs(hash common.Hash, txc txStateChanges) { 222 if list, ok := pool.mined[hash]; ok { 223 for _, tx := range list { 224 txHash := tx.Hash() 225 pool.removeTxBlockData(txHash) 226 pool.pending[txHash] = tx 227 txc.setState(txHash, false) 228 } 229 delete(pool.mined, hash) 230 } 231 } 232 233 // reorgOnNewHead sets a new head header, processing (and rolling back if necessary) 234 // the blocks since the last known head and returns a txStateChanges map containing 235 // the recently mined and rolled back transaction hashes. If an error (context 236 // timeout) occurs during checking new blocks, it leaves the locally known head 237 // at the latest checked block and still returns a valid txStateChanges, making it 238 // possible to continue checking the missing blocks at the next chain head event 239 func (pool *TxPool) reorgOnNewHead(ctx context.Context, newHeader *types.Header) (txStateChanges, error) { 240 txc := make(txStateChanges) 241 oldh := pool.chain.GetHeaderByHash(pool.head) 242 newh := newHeader 243 // find common ancestor, create list of rolled back and new block hashes 244 var oldHashes, newHashes []common.Hash 245 for oldh.Hash() != newh.Hash() { 246 if oldh.Number.Uint64() >= newh.Number.Uint64() { 247 oldHashes = append(oldHashes, oldh.Hash()) 248 oldh = pool.chain.GetHeader(oldh.ParentHash, oldh.Number.Uint64()-1) 249 } 250 if oldh.Number.Uint64() < newh.Number.Uint64() { 251 newHashes = append(newHashes, newh.Hash()) 252 newh = pool.chain.GetHeader(newh.ParentHash, newh.Number.Uint64()-1) 253 if newh == nil { 254 // happens when CHT syncing, nothing to do 255 newh = oldh 256 } 257 } 258 } 259 if oldh.Number.Uint64() < pool.clearIdx { 260 pool.clearIdx = oldh.Number.Uint64() 261 } 262 // roll back old blocks 263 for _, hash := range oldHashes { 264 pool.rollbackTxs(hash, txc) 265 } 266 pool.head = oldh.Hash() 267 // check mined txs of new blocks (array is in reversed order) 268 for i := len(newHashes) - 1; i >= 0; i-- { 269 hash := newHashes[i] 270 if err := pool.checkMinedTxs(ctx, hash, newHeader.Number.Uint64()-uint64(i), txc); err != nil { 271 return txc, err 272 } 273 pool.head = hash 274 } 275 276 // clear old mined tx entries of old blocks 277 if idx := newHeader.Number.Uint64(); idx > pool.clearIdx+txPermanent { 278 idx2 := idx - txPermanent 279 if len(pool.mined) > 0 { 280 for i := pool.clearIdx; i < idx2; i++ { 281 hash := core.GetCanonicalHash(pool.chainDb, i) 282 if list, ok := pool.mined[hash]; ok { 283 hashes := make([]common.Hash, len(list)) 284 for i, tx := range list { 285 hashes[i] = tx.Hash() 286 } 287 pool.relay.Discard(hashes) 288 delete(pool.mined, hash) 289 } 290 } 291 } 292 pool.clearIdx = idx2 293 } 294 295 return txc, nil 296 } 297 298 // blockCheckTimeout is the time limit for checking new blocks for mined 299 // transactions. Checking resumes at the next chain head event if timed out. 300 const blockCheckTimeout = time.Second * 3 301 302 // eventLoop processes chain head events and also notifies the tx relay backend 303 // about the new head hash and tx state changes 304 func (pool *TxPool) eventLoop() { 305 for ev := range pool.events.Chan() { 306 switch ev.Data.(type) { 307 case core.ChainHeadEvent: 308 pool.setNewHead(ev.Data.(core.ChainHeadEvent).Block.Header()) 309 // hack in order to avoid hogging the lock; this part will 310 // be replaced by a subsequent PR. 311 time.Sleep(time.Millisecond) 312 } 313 } 314 } 315 316 func (pool *TxPool) setNewHead(head *types.Header) { 317 pool.mu.Lock() 318 defer pool.mu.Unlock() 319 320 ctx, cancel := context.WithTimeout(context.Background(), blockCheckTimeout) 321 defer cancel() 322 323 txc, _ := pool.reorgOnNewHead(ctx, head) 324 m, r := txc.getLists() 325 pool.relay.NewHead(pool.head, m, r) 326 pool.homestead = pool.config.IsHomestead(head.Number) 327 pool.signer = types.MakeSigner(pool.config, head.Number) 328 } 329 330 // Stop stops the light transaction pool 331 func (pool *TxPool) Stop() { 332 close(pool.quit) 333 pool.events.Unsubscribe() 334 log.Info("Transaction pool stopped") 335 } 336 337 // Stats returns the number of currently pending (locally created) transactions 338 func (pool *TxPool) Stats() (pending int) { 339 pool.mu.RLock() 340 defer pool.mu.RUnlock() 341 342 pending = len(pool.pending) 343 return 344 } 345 346 // validateTx checks whether a transaction is valid according to the consensus rules. 347 func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error { 348 // Validate sender 349 var ( 350 from common.Address 351 err error 352 ) 353 354 // Validate the transaction sender and it's sig. Throw 355 // if the from fields is invalid. 356 if from, err = types.Sender(pool.signer, tx); err != nil { 357 return core.ErrInvalidSender 358 } 359 // Last but not least check for nonce errors 360 currentState := pool.currentState() 361 if n, err := currentState.GetNonce(ctx, from); err == nil { 362 if n > tx.Nonce() { 363 return core.ErrNonce 364 } 365 } else { 366 return err 367 } 368 369 // Check the transaction doesn't exceed the current 370 // block limit gas. 371 header := pool.chain.GetHeaderByHash(pool.head) 372 if header.GasLimit.Cmp(tx.Gas()) < 0 { 373 return core.ErrGasLimit 374 } 375 376 // Transactions can't be negative. This may never happen 377 // using RLP decoded transactions but may occur if you create 378 // a transaction using the RPC for example. 379 if tx.Value().Sign() < 0 { 380 return core.ErrNegativeValue 381 } 382 383 // Transactor should have enough funds to cover the costs 384 // cost == V + GP * GL 385 if b, err := currentState.GetBalance(ctx, from); err == nil { 386 if b.Cmp(tx.Cost()) < 0 { 387 return core.ErrInsufficientFunds 388 } 389 } else { 390 return err 391 } 392 393 // Should supply enough intrinsic gas 394 if tx.Gas().Cmp(core.IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)) < 0 { 395 return core.ErrIntrinsicGas 396 } 397 398 return nil 399 } 400 401 // add validates a new transaction and sets its state pending if processable. 402 // It also updates the locally stored nonce if necessary. 403 func (self *TxPool) add(ctx context.Context, tx *types.Transaction) error { 404 hash := tx.Hash() 405 406 if self.pending[hash] != nil { 407 return fmt.Errorf("Known transaction (%x)", hash[:4]) 408 } 409 err := self.validateTx(ctx, tx) 410 if err != nil { 411 return err 412 } 413 414 if _, ok := self.pending[hash]; !ok { 415 self.pending[hash] = tx 416 417 nonce := tx.Nonce() + 1 418 419 addr, _ := types.Sender(self.signer, tx) 420 if nonce > self.nonce[addr] { 421 self.nonce[addr] = nonce 422 } 423 424 // Notify the subscribers. This event is posted in a goroutine 425 // because it's possible that somewhere during the post "Remove transaction" 426 // gets called which will then wait for the global tx pool lock and deadlock. 427 go self.eventMux.Post(core.TxPreEvent{Tx: tx}) 428 } 429 430 // Print a log message if low enough level is set 431 log.Debug("Pooled new transaction", "hash", hash, "from", log.Lazy{Fn: func() common.Address { from, _ := types.Sender(self.signer, tx); return from }}, "to", tx.To()) 432 return nil 433 } 434 435 // Add adds a transaction to the pool if valid and passes it to the tx relay 436 // backend 437 func (self *TxPool) Add(ctx context.Context, tx *types.Transaction) error { 438 self.mu.Lock() 439 defer self.mu.Unlock() 440 441 data, err := rlp.EncodeToBytes(tx) 442 if err != nil { 443 return err 444 } 445 446 if err := self.add(ctx, tx); err != nil { 447 return err 448 } 449 //fmt.Println("Send", tx.Hash()) 450 self.relay.Send(types.Transactions{tx}) 451 452 self.chainDb.Put(tx.Hash().Bytes(), data) 453 return nil 454 } 455 456 // AddTransactions adds all valid transactions to the pool and passes them to 457 // the tx relay backend 458 func (self *TxPool) AddBatch(ctx context.Context, txs []*types.Transaction) { 459 self.mu.Lock() 460 defer self.mu.Unlock() 461 var sendTx types.Transactions 462 463 for _, tx := range txs { 464 if err := self.add(ctx, tx); err == nil { 465 sendTx = append(sendTx, tx) 466 } 467 } 468 if len(sendTx) > 0 { 469 self.relay.Send(sendTx) 470 } 471 } 472 473 // GetTransaction returns a transaction if it is contained in the pool 474 // and nil otherwise. 475 func (tp *TxPool) GetTransaction(hash common.Hash) *types.Transaction { 476 // check the txs first 477 if tx, ok := tp.pending[hash]; ok { 478 return tx 479 } 480 return nil 481 } 482 483 // GetTransactions returns all currently processable transactions. 484 // The returned slice may be modified by the caller. 485 func (self *TxPool) GetTransactions() (txs types.Transactions, err error) { 486 self.mu.RLock() 487 defer self.mu.RUnlock() 488 489 txs = make(types.Transactions, len(self.pending)) 490 i := 0 491 for _, tx := range self.pending { 492 txs[i] = tx 493 i++ 494 } 495 return txs, nil 496 } 497 498 // Content retrieves the data content of the transaction pool, returning all the 499 // pending as well as queued transactions, grouped by account and nonce. 500 func (self *TxPool) Content() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) { 501 self.mu.RLock() 502 defer self.mu.RUnlock() 503 504 // Retrieve all the pending transactions and sort by account and by nonce 505 pending := make(map[common.Address]types.Transactions) 506 for _, tx := range self.pending { 507 account, _ := types.Sender(self.signer, tx) 508 pending[account] = append(pending[account], tx) 509 } 510 // There are no queued transactions in a light pool, just return an empty map 511 queued := make(map[common.Address]types.Transactions) 512 return pending, queued 513 } 514 515 // RemoveTransactions removes all given transactions from the pool. 516 func (self *TxPool) RemoveTransactions(txs types.Transactions) { 517 self.mu.Lock() 518 defer self.mu.Unlock() 519 var hashes []common.Hash 520 for _, tx := range txs { 521 //self.RemoveTx(tx.Hash()) 522 hash := tx.Hash() 523 delete(self.pending, hash) 524 self.chainDb.Delete(hash[:]) 525 hashes = append(hashes, hash) 526 } 527 self.relay.Discard(hashes) 528 } 529 530 // RemoveTx removes the transaction with the given hash from the pool. 531 func (pool *TxPool) RemoveTx(hash common.Hash) { 532 pool.mu.Lock() 533 defer pool.mu.Unlock() 534 // delete from pending pool 535 delete(pool.pending, hash) 536 pool.chainDb.Delete(hash[:]) 537 pool.relay.Discard([]common.Hash{hash}) 538 }