func NewStateObjectFromBytes(address common.Address, data []byte, db ethdb.Database) *StateObject { var extobject struct { Nonce uint64 Balance *big.Int Root common.Hash CodeHash []byte } err := rlp.Decode(bytes.NewReader(data), &extobject) if err != nil { glog.Errorf("can't decode state object %x: %v", address, err) return nil } trie, err := trie.NewSecure(extobject.Root, db) if err != nil { // TODO: bubble this up or panic glog.Errorf("can't create account trie with root %x: %v", extobject.Root[:], err) return nil } object := &StateObject{address: address, db: db} object.nonce = extobject.Nonce object.balance = extobject.Balance object.codeHash = extobject.CodeHash object.trie = trie object.storage = make(map[string]common.Hash) object.code, _ = db.Get(extobject.CodeHash) return object }
// reportBlock reports the given block and error using the canonical block // reporting tool. Reporting the block to the service is handled in a separate // goroutine. func reportBlock(block *types.Block, err error) { if glog.V(logger.Error) { glog.Errorf("Bad block #%v (%s)\n", block.Number(), block.Hash().Hex()) glog.Errorf(" %v", err) } go ReportBlock(block, err) }
// Get returns the value for key stored in the trie. // The value bytes must not be modified by the caller. func (t *SecureTrie) Get(key []byte) []byte { res, err := t.TryGet(key) if err != nil && glog.V(logger.Error) { glog.Errorf("Unhandled trie error: %v", err) } return res }
func handle(id int, conn net.Conn, api shared.ExpanseApi, c codec.Codec) { codec := c.New(conn) defer func() { if r := recover(); r != nil { glog.Errorf("panic: %v\n", r) } codec.Close() }() for { requests, isBatch, err := codec.ReadRequest() if err == io.EOF { return } else if err != nil { glog.V(logger.Debug).Infof("Closed IPC Conn %06d recv err - %v\n", id, err) return } if isBatch { responses := make([]*interface{}, len(requests)) responseCount := 0 for _, req := range requests { res, err := api.Execute(req) if req.Id != nil { rpcResponse := shared.NewRpcResponse(req.Id, req.Jsonrpc, res, err) responses[responseCount] = rpcResponse responseCount += 1 } } err = codec.WriteResponse(responses[:responseCount]) if err != nil { glog.V(logger.Debug).Infof("Closed IPC Conn %06d send err - %v\n", id, err) return } } else { var rpcResponse interface{} res, err := api.Execute(requests[0]) rpcResponse = shared.NewRpcResponse(requests[0].Id, requests[0].Jsonrpc, res, err) err = codec.WriteResponse(rpcResponse) if err != nil { glog.V(logger.Debug).Infof("Closed IPC Conn %06d send err - %v\n", id, err) return } } } }
// Prove constructs a merkle proof for key. The result contains all // encoded nodes on the path to the value at key. The value itself is // also included in the last node and can be retrieved by verifying // the proof. // // If the trie does not contain a value for key, the returned proof // contains all nodes of the longest existing prefix of the key // (at least the root node), ending with the node that proves the // absence of the key. func (t *Trie) Prove(key []byte) []rlp.RawValue { // Collect all nodes on the path to key. key = compactHexDecode(key) nodes := []node{} tn := t.root for len(key) > 0 && tn != nil { switch n := tn.(type) { case shortNode: if len(key) < len(n.Key) || !bytes.Equal(n.Key, key[:len(n.Key)]) { // The trie doesn't contain the key. tn = nil } else { tn = n.Val key = key[len(n.Key):] } nodes = append(nodes, n) case fullNode: tn = n.Children[key[0]] key = key[1:] nodes = append(nodes, n) case hashNode: var err error tn, err = t.resolveHash(n, nil, nil) if err != nil { if glog.V(logger.Error) { glog.Errorf("Unhandled trie error: %v", err) } return nil } default: panic(fmt.Sprintf("%T: invalid node: %v", tn, tn)) } } hasher := newHasher() proof := make([]rlp.RawValue, 0, len(nodes)) for i, n := range nodes { // Don't bother checking for errors here since hasher panics // if encoding doesn't work and we're not writing to any database. n, _, _ = hasher.hashChildren(n, nil) hn, _ := hasher.store(n, nil, false) if _, ok := hn.(hashNode); ok || i == 0 { // If the node's database encoding is a hash (or is the // root node), it becomes a proof element. enc, _ := rlp.EncodeToBytes(n) proof = append(proof, enc) } } return proof }
// reload caches addresses of existing accounts. // Callers must hold ac.mu. func (ac *addrCache) reload() { accounts, err := ac.scan() if err != nil && glog.V(logger.Debug) { glog.Errorf("can't load keys: %v", err) } ac.all = accounts sort.Sort(ac.all) for k := range ac.byAddr { delete(ac.byAddr, k) } for _, a := range accounts { ac.byAddr[a.Address] = append(ac.byAddr[a.Address], a) } glog.V(logger.Debug).Infof("reloaded keys, cache has %d accounts", len(ac.all)) }
// reads the next node record from the iterator, skipping over other // database entries. func nextNode(it iterator.Iterator) *Node { for end := false; !end; end = !it.Next() { id, field := splitKey(it.Key()) if field != nodeDBDiscoverRoot { continue } var n Node if err := rlp.DecodeBytes(it.Value(), &n); err != nil { if glog.V(logger.Warn) { glog.Errorf("invalid node %x: %v", id, err) } continue } return &n } return nil }
func (self *LDBDatabase) Close() { // Stop the metrics collection to avoid internal database races self.quitLock.Lock() defer self.quitLock.Unlock() if self.quitChan != nil { errc := make(chan error) self.quitChan <- errc if err := <-errc; err != nil { glog.V(logger.Error).Infof("metrics failure in '%s': %v\n", self.fn, err) } } err := self.db.Close() if glog.V(logger.Error) { if err == nil { glog.Infoln("closed db:", self.fn) } else { glog.Errorf("error closing db %s: %v", self.fn, err) } } }
func (t *Trie) resolveHash(n hashNode) node { if v, ok := globalCache.Get(n); ok { return v } enc, err := t.db.Get(n) if err != nil || enc == nil { // TODO: This needs to be improved to properly distinguish errors. // Disk I/O errors shouldn't produce nil (and cause a // consensus failure or weird crash), but it is unclear how // they could be handled because the entire stack above the trie isn't // prepared to cope with missing state nodes. if glog.V(logger.Error) { glog.Errorf("Dangling hash node ref %x: %v", n, err) } return nil } dec := mustDecodeNode(n, enc) if dec != nil { globalCache.Put(n, dec) } return dec }
// Retrieve a state object given my the address. Returns nil if not found. func (self *StateDB) GetStateObject(addr common.Address) (stateObject *StateObject) { // Prefer 'live' objects. if obj := self.stateObjects[addr]; obj != nil { if obj.deleted { return nil } return obj } // Load the object from the database. enc := self.trie.Get(addr[:]) if len(enc) == 0 { return nil } var data Account if err := rlp.DecodeBytes(enc, &data); err != nil { glog.Errorf("can't decode object at %x: %v", addr[:], err) return nil } // Insert into the live set. obj := newObject(self, addr, data, self.MarkStateObjectDirty) self.setStateObject(obj) return obj }
// promoteExecutables moves transactions that have become processable from the // future queue to the set of pending transactions. During this process, all // invalidated transactions (low nonce, low balance) are deleted. func (pool *TxPool) promoteExecutables() { // Init delayed since tx pool could have been started before any state sync if pool.pendingState == nil { pool.resetState() } // Retrieve the current state to allow nonce and balance checking state, err := pool.currentState() if err != nil { glog.Errorf("Could not get current state: %v", err) return } // Iterate over all accounts and promote any executable transactions queued := uint64(0) for addr, list := range pool.queue { // Drop all transactions that are deemed too old (low nonce) for _, tx := range list.Forward(state.GetNonce(addr)) { if glog.V(logger.Core) { glog.Infof("Removed old queued transaction: %v", tx) } delete(pool.all, tx.Hash()) } // Drop all transactions that are too costly (low balance) drops, _ := list.Filter(state.GetBalance(addr)) for _, tx := range drops { if glog.V(logger.Core) { glog.Infof("Removed unpayable queued transaction: %v", tx) } delete(pool.all, tx.Hash()) } // Gather all executable transactions and promote them for _, tx := range list.Ready(pool.pendingState.GetNonce(addr)) { if glog.V(logger.Core) { glog.Infof("Promoting queued transaction: %v", tx) } pool.promoteTx(addr, tx.Hash(), tx) } // Drop all transactions over the allowed limit for _, tx := range list.Cap(int(maxQueuedPerAccount)) { if glog.V(logger.Core) { glog.Infof("Removed cap-exceeding queued transaction: %v", tx) } delete(pool.all, tx.Hash()) } queued += uint64(list.Len()) // Delete the entire queue entry if it became empty. if list.Empty() { delete(pool.queue, addr) } } // If we've queued more transactions than the hard limit, drop oldest ones if queued > maxQueuedInTotal { // Sort all accounts with queued transactions by heartbeat addresses := make(addresssByHeartbeat, 0, len(pool.queue)) for addr, _ := range pool.queue { addresses = append(addresses, addressByHeartbeat{addr, pool.beats[addr]}) } sort.Sort(addresses) // Drop transactions until the total is below the limit for drop := queued - maxQueuedInTotal; drop > 0; { addr := addresses[len(addresses)-1] list := pool.queue[addr.address] addresses = addresses[:len(addresses)-1] // Drop all transactions if they are less than the overflow if size := uint64(list.Len()); size <= drop { for _, tx := range list.Flatten() { pool.removeTx(tx.Hash()) } drop -= size continue } // Otherwise drop only last few transactions txs := list.Flatten() for i := len(txs) - 1; i >= 0 && drop > 0; i-- { pool.removeTx(txs[i].Hash()) drop-- } } } }
// checkQueue moves transactions that have become processable to main pool. func (pool *TxPool) checkQueue() { // init delayed since tx pool could have been started before any state sync if pool.pendingState == nil { pool.resetState() } var promote txQueue for address, txs := range pool.queue { currentState, err := pool.currentState() if err != nil { glog.Errorf("could not get current state: %v", err) return } balance := currentState.GetBalance(address) var ( guessedNonce = pool.pendingState.GetNonce(address) // nonce currently kept by the tx pool (pending state) trueNonce = currentState.GetNonce(address) // nonce known by the last state ) promote = promote[:0] for hash, tx := range txs { // Drop processed or out of fund transactions if tx.Nonce() < trueNonce || balance.Cmp(tx.Cost()) < 0 { if glog.V(logger.Core) { glog.Infof("removed tx (%v) from pool queue: low tx nonce or out of funds\n", tx) } delete(txs, hash) continue } // Collect the remaining transactions for the next pass. promote = append(promote, txQueueEntry{hash, address, tx}) } // Find the next consecutive nonce range starting at the current account nonce, // pushing the guessed nonce forward if we add consecutive transactions. sort.Sort(promote) for i, entry := range promote { // If we reached a gap in the nonces, enforce transaction limit and stop if entry.Nonce() > guessedNonce { if len(promote)-i > maxQueued { if glog.V(logger.Debug) { glog.Infof("Queued tx limit exceeded for %s. Tx %s removed\n", common.PP(address[:]), common.PP(entry.hash[:])) } for _, drop := range promote[i+maxQueued:] { delete(txs, drop.hash) } } break } // Otherwise promote the transaction and move the guess nonce if needed pool.addTx(entry.hash, address, entry.Transaction) delete(txs, entry.hash) if entry.Nonce() == guessedNonce { guessedNonce++ } } // Delete the entire queue entry if it became empty. if len(txs) == 0 { delete(pool.queue, address) } } }
// Update associates key with value in the trie. Subsequent calls to // Get will return value. If value has length zero, any existing value // is deleted from the trie and calls to Get will return nil. // // The value bytes must not be modified by the caller while they are // stored in the trie. func (t *SecureTrie) Update(key, value []byte) { if err := t.TryUpdate(key, value); err != nil && glog.V(logger.Error) { glog.Errorf("Unhandled trie error: %v", err) } }
// Delete removes any existing value for key from the trie. func (t *SecureTrie) Delete(key []byte) { if err := t.TryDelete(key); err != nil && glog.V(logger.Error) { glog.Errorf("Unhandled trie error: %v", err) } }