code: func (h *hasher) hash(n node, db *Database, force bool) (node, node, error) {
  	// If we're not storing the node, just hashing, use available cached data
  	if hash, dirty := n.cache(); hash != nil {
  		if db == nil {
  			return hash, n, nil
  		}
  		if !dirty {
  			switch n.(type) {
  			case *fullNode, *shortNode:
  				return hash, hash, nil
  			default:
  				return hash, n, nil
  			}
  		}
  	}
  	// Trie not processed yet or needs storage, walk the children
  	collapsed, cached, err := h.hashChildren(n, db)
  	if err != nil {
  		return hashNode{}, n, err
  	}
  	hashed, err := h.store(collapsed, db, force)
  	if err != nil {
  		return hashNode{}, n, err
  	}
  	// Cache the hash of the node for later reuse and remove
  	// the dirty flag in commit mode. It's fine to assign these values directly
  	// without copying the node first because hashChildren copies it.
  	cachedHash, _ := hashed.(hashNode)
  	switch cn := cached.(type) {
  	case *shortNode:
  		cn.flags.hash = cachedHash
  		if db != nil {
  			cn.flags.dirty = false
  		}
  	case *fullNode:
  		cn.flags.hash = cachedHash
  		if db != nil {
  			cn.flags.dirty = false
  		}
  	}
  	return hashed, cached, nil
  }
docs: // hash collapses a node down into a hash node, also returning a copy of the
  // original node initialized with the computed hash to replace the original one.