diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 4ef9ce3ac48982ea8172209ea17e54b6dc59b6ef..46d60b0883cf8a6df44411fc75e56f1339d1f1cb 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -26,17 +26,17 @@
 		},
 		{
 			"ImportPath": "github.com/gorilla/websocket",
-			"Rev": "a3ec486e6a7a41858210b0fc5d7b5df593b3c4a3"
+			"Rev": "1f87405cd9755fc388e111c4003caca4a2f52fa6"
 		},
 		{
 			"ImportPath": "github.com/inconshreveable/log15/stack",
-			"Comment": "v2.3-42-gee210fc",
-			"Rev": "ee210fc98cc7756aa0cf55d8d554148828e8e658"
+			"Comment": "v2.3-38-g352fceb",
+			"Rev": "352fceb48e895bd1dd0b9f5d3ae8f8516c49af0f"
 		},
 		{
 			"ImportPath": "github.com/inconshreveable/log15/term",
-			"Comment": "v2.3-42-gee210fc",
-			"Rev": "ee210fc98cc7756aa0cf55d8d554148828e8e658"
+			"Comment": "v2.3-38-g352fceb",
+			"Rev": "352fceb48e895bd1dd0b9f5d3ae8f8516c49af0f"
 		},
 		{
 			"ImportPath": "github.com/manucorporat/sse",
@@ -44,7 +44,7 @@
 		},
 		{
 			"ImportPath": "github.com/mattn/go-colorable",
-			"Rev": "d67e0b7d1797975196499f79bcc322c08b9f218b"
+			"Rev": "043ae16291351db8465272edf465c9f388161627"
 		},
 		{
 			"ImportPath": "github.com/naoina/go-stringutil",
@@ -52,7 +52,7 @@
 		},
 		{
 			"ImportPath": "github.com/naoina/toml",
-			"Rev": "5667c316ee9576e9d5bca793ce4ec813a88ce7d3"
+			"Rev": "7b2dffbeaee47506726f29e36d19cf4ee90d361b"
 		},
 		{
 			"ImportPath": "github.com/sfreiberg/gotwilio",
@@ -75,7 +75,7 @@
 		},
 		{
 			"ImportPath": "github.com/syndtr/goleveldb/leveldb",
-			"Rev": "a06509502ca32565bdf74afc1e573050023f261c"
+			"Rev": "63c9e642efad852f49e20a6f90194cae112fd2ac"
 		},
 		{
 			"ImportPath": "github.com/syndtr/gosnappy/snappy",
@@ -87,103 +87,103 @@
 		},
 		{
 			"ImportPath": "github.com/tendermint/log15",
-			"Comment": "v2.3-36-gc65281b",
-			"Rev": "c65281bb703b7612f60558e75b07c434c06e2636"
+			"Comment": "v2.3-36-g6e46075",
+			"Rev": "6e460758f10ef42a4724b8e4a82fee59aaa0e41d"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/account",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/alert",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/blockchain",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/common",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/config",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/consensus",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/db",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/events",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/logger",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/mempool",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/merkle",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/node",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/p2p",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/permission/types",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/rpc",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/state",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/types",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/vm",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tendermint/tendermint/wire",
-			"Comment": "0.1-26-g85d5b16",
-			"Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6"
+			"Comment": "0.1-56-gd51741d",
+			"Rev": "d51741df7220f7506334ab43563bfa98f5062058"
 		},
 		{
 			"ImportPath": "github.com/tommy351/gin-cors",
@@ -191,40 +191,40 @@
 		},
 		{
 			"ImportPath": "golang.org/x/crypto/curve25519",
-			"Rev": "02a186af8b62cb007f392270669b91be5527d39c"
+			"Rev": "4d8f0cfeca8290cfc0091edf678a138ce669b1bb"
 		},
 		{
 			"ImportPath": "golang.org/x/crypto/nacl/box",
-			"Rev": "02a186af8b62cb007f392270669b91be5527d39c"
+			"Rev": "4d8f0cfeca8290cfc0091edf678a138ce669b1bb"
 		},
 		{
 			"ImportPath": "golang.org/x/crypto/nacl/secretbox",
-			"Rev": "02a186af8b62cb007f392270669b91be5527d39c"
+			"Rev": "4d8f0cfeca8290cfc0091edf678a138ce669b1bb"
 		},
 		{
 			"ImportPath": "golang.org/x/crypto/poly1305",
-			"Rev": "02a186af8b62cb007f392270669b91be5527d39c"
+			"Rev": "4d8f0cfeca8290cfc0091edf678a138ce669b1bb"
 		},
 		{
 			"ImportPath": "golang.org/x/crypto/ripemd160",
-			"Rev": "02a186af8b62cb007f392270669b91be5527d39c"
+			"Rev": "4d8f0cfeca8290cfc0091edf678a138ce669b1bb"
 		},
 		{
 			"ImportPath": "golang.org/x/crypto/salsa20/salsa",
-			"Rev": "02a186af8b62cb007f392270669b91be5527d39c"
+			"Rev": "4d8f0cfeca8290cfc0091edf678a138ce669b1bb"
 		},
 		{
 			"ImportPath": "golang.org/x/net/context",
-			"Rev": "02a186af8b62cb007f392270669b91be5527d39c"
+			"Rev": "2cba614e8ff920c60240d2677bc019af32ee04e5"
 		},
 		{
 			"ImportPath": "golang.org/x/net/netutil",
-			"Rev": "10576091dc82c9c109dddfb5ed77bdbbc87a9af8"
+			"Rev": "2cba614e8ff920c60240d2677bc019af32ee04e5"
 		},
 		{
 			"ImportPath": "gopkg.in/bluesuncorp/validator.v5",
-			"Comment": "v5.8",
-			"Rev": "c06d47f593d786142436a43334f724d819093c04"
+			"Comment": "v5.12",
+			"Rev": "d5acf1dac43705f8bfbb71d878e290e2bed3950b"
 		},
 		{
 			"ImportPath": "gopkg.in/fatih/set.v0",
diff --git a/Godeps/_workspace/src/github.com/gin-gonic/gin/context.go b/Godeps/_workspace/src/github.com/gin-gonic/gin/context.go
index 0455c0db4ba18653acb86e97144098bb1c27266c..a5e946ccc5655dc498b5866c0da8cc2fb1b34f49 100644
--- a/Godeps/_workspace/src/github.com/gin-gonic/gin/context.go
+++ b/Godeps/_workspace/src/github.com/gin-gonic/gin/context.go
@@ -14,8 +14,8 @@ import (
 
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gin-gonic/gin/binding"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gin-gonic/gin/render"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/manucorporat/sse"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/net/context"
-	"github.com/manucorporat/sse"
 )
 
 const (
diff --git a/Godeps/_workspace/src/github.com/gin-gonic/gin/context_test.go b/Godeps/_workspace/src/github.com/gin-gonic/gin/context_test.go
index e31411e84c7e4fce0f800dcd50145c00f73ea40b..9e9f3dda4b8ea983c96fd42c1b3ff4a302d07414 100644
--- a/Godeps/_workspace/src/github.com/gin-gonic/gin/context_test.go
+++ b/Godeps/_workspace/src/github.com/gin-gonic/gin/context_test.go
@@ -14,8 +14,8 @@ import (
 	"testing"
 	"time"
 
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/manucorporat/sse"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/stretchr/testify/assert"
-	"github.com/manucorporat/sse"
 )
 
 // Unit tests TODO
diff --git a/Godeps/_workspace/src/github.com/gin-gonic/gin/middleware_test.go b/Godeps/_workspace/src/github.com/gin-gonic/gin/middleware_test.go
index 61535de2101687579494bc04eb0cb0687a802611..8af80d333d5b88142131abf6673c550775adc7f6 100644
--- a/Godeps/_workspace/src/github.com/gin-gonic/gin/middleware_test.go
+++ b/Godeps/_workspace/src/github.com/gin-gonic/gin/middleware_test.go
@@ -9,8 +9,8 @@ import (
 
 	"testing"
 
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/manucorporat/sse"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/stretchr/testify/assert"
-	"github.com/manucorporat/sse"
 )
 
 func TestMiddlewareGeneralCase(t *testing.T) {
diff --git a/Godeps/_workspace/src/github.com/gin-gonic/gin/mode.go b/Godeps/_workspace/src/github.com/gin-gonic/gin/mode.go
index f563ae8192bd8400f4f031cd668a7f0649d281d1..5dcf4e85a2385fdbf6c4f5f61af2485236b84b5b 100644
--- a/Godeps/_workspace/src/github.com/gin-gonic/gin/mode.go
+++ b/Godeps/_workspace/src/github.com/gin-gonic/gin/mode.go
@@ -9,7 +9,7 @@ import (
 	"os"
 
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gin-gonic/gin/binding"
-	"github.com/mattn/go-colorable"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/mattn/go-colorable"
 )
 
 const ENV_GIN_MODE = "GIN_MODE"
diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/client.go b/Godeps/_workspace/src/github.com/gorilla/websocket/client.go
index 93db8ddc320df9489edf64271ef2188ab793d93e..c25d24f80421a422f130045a04754d90d261f4f9 100644
--- a/Godeps/_workspace/src/github.com/gorilla/websocket/client.go
+++ b/Godeps/_workspace/src/github.com/gorilla/websocket/client.go
@@ -5,11 +5,8 @@
 package websocket
 
 import (
-	"bytes"
 	"crypto/tls"
 	"errors"
-	"io"
-	"io/ioutil"
 	"net"
 	"net/http"
 	"net/url"
@@ -130,11 +127,6 @@ func parseURL(s string) (*url.URL, error) {
 		u.Opaque = s[i:]
 	}
 
-	if strings.Contains(u.Host, "@") {
-		// WebSocket URIs do not contain user information.
-		return nil, errMalformedURL
-	}
-
 	return &u, nil
 }
 
@@ -163,8 +155,7 @@ var DefaultDialer *Dialer
 //
 // If the WebSocket handshake fails, ErrBadHandshake is returned along with a
 // non-nil *http.Response so that callers can handle redirects, authentication,
-// etcetera. The response body may not contain the entire response and does not
-// need to be closed by the application.
+// etc.
 func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Response, error) {
 	u, err := parseURL(urlStr)
 	if err != nil {
@@ -233,33 +224,8 @@ func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Re
 		requestHeader = h
 	}
 
-	if len(requestHeader["Host"]) > 0 {
-		// This can be used to supply a Host: header which is different from
-		// the dial address.
-		u.Host = requestHeader.Get("Host")
-
-		// Drop "Host" header
-		h := http.Header{}
-		for k, v := range requestHeader {
-			if k == "Host" {
-				continue
-			}
-			h[k] = v
-		}
-		requestHeader = h
-	}
-
 	conn, resp, err := NewClient(netConn, u, requestHeader, d.ReadBufferSize, d.WriteBufferSize)
-
 	if err != nil {
-		if err == ErrBadHandshake {
-			// Before closing the network connection on return from this
-			// function, slurp up some of the response to aid application
-			// debugging.
-			buf := make([]byte, 1024)
-			n, _ := io.ReadFull(resp.Body, buf)
-			resp.Body = ioutil.NopCloser(bytes.NewReader(buf[:n]))
-		}
 		return nil, resp, err
 	}
 
diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/client_server_test.go b/Godeps/_workspace/src/github.com/gorilla/websocket/client_server_test.go
index 749ef20509ccb54418fee9f78e1d57067d1e4a08..8c608f68c4b41fbd6c920ffcc5c0f31ab482dcb4 100644
--- a/Godeps/_workspace/src/github.com/gorilla/websocket/client_server_test.go
+++ b/Godeps/_workspace/src/github.com/gorilla/websocket/client_server_test.go
@@ -8,13 +8,11 @@ import (
 	"crypto/tls"
 	"crypto/x509"
 	"io"
-	"io/ioutil"
 	"net"
 	"net/http"
 	"net/http/httptest"
 	"net/url"
 	"reflect"
-	"strings"
 	"testing"
 	"time"
 )
@@ -36,22 +34,22 @@ var cstDialer = Dialer{
 
 type cstHandler struct{ *testing.T }
 
-type cstServer struct {
+type Server struct {
 	*httptest.Server
 	URL string
 }
 
-func newServer(t *testing.T) *cstServer {
-	var s cstServer
+func newServer(t *testing.T) *Server {
+	var s Server
 	s.Server = httptest.NewServer(cstHandler{t})
-	s.URL = makeWsProto(s.Server.URL)
+	s.URL = "ws" + s.Server.URL[len("http"):]
 	return &s
 }
 
-func newTLSServer(t *testing.T) *cstServer {
-	var s cstServer
+func newTLSServer(t *testing.T) *Server {
+	var s Server
 	s.Server = httptest.NewTLSServer(cstHandler{t})
-	s.URL = makeWsProto(s.Server.URL)
+	s.URL = "ws" + s.Server.URL[len("http"):]
 	return &s
 }
 
@@ -99,10 +97,6 @@ func (t cstHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	}
 }
 
-func makeWsProto(s string) string {
-	return "ws" + strings.TrimPrefix(s, "http")
-}
-
 func sendRecv(t *testing.T, ws *Conn) {
 	const message = "Hello World!"
 	if err := ws.SetWriteDeadline(time.Now().Add(time.Second)); err != nil {
@@ -163,7 +157,6 @@ func TestDialTLS(t *testing.T) {
 }
 
 func xTestDialTLSBadCert(t *testing.T) {
-	// This test is deactivated because of noisy logging from the net/http package.
 	s := newTLSServer(t)
 	defer s.Close()
 
@@ -254,70 +247,3 @@ func TestHandshake(t *testing.T) {
 	}
 	sendRecv(t, ws)
 }
-
-func TestRespOnBadHandshake(t *testing.T) {
-	const expectedStatus = http.StatusGone
-	const expectedBody = "This is the response body."
-
-	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		w.WriteHeader(expectedStatus)
-		io.WriteString(w, expectedBody)
-	}))
-	defer s.Close()
-
-	ws, resp, err := cstDialer.Dial(makeWsProto(s.URL), nil)
-	if err == nil {
-		ws.Close()
-		t.Fatalf("Dial: nil")
-	}
-
-	if resp == nil {
-		t.Fatalf("resp=nil, err=%v", err)
-	}
-
-	if resp.StatusCode != expectedStatus {
-		t.Errorf("resp.StatusCode=%d, want %d", resp.StatusCode, expectedStatus)
-	}
-
-	p, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		t.Fatalf("ReadFull(resp.Body) returned error %v", err)
-	}
-
-	if string(p) != expectedBody {
-		t.Errorf("resp.Body=%s, want %s", p, expectedBody)
-	}
-}
-
-// If the Host header is specified in `Dial()`, the server must receive it as
-// the `Host:` header.
-func TestHostHeader(t *testing.T) {
-	s := newServer(t)
-	defer s.Close()
-
-	specifiedHost := make(chan string, 1)
-	origHandler := s.Server.Config.Handler
-
-	// Capture the request Host header.
-	s.Server.Config.Handler = http.HandlerFunc(
-		func(w http.ResponseWriter, r *http.Request) {
-			specifiedHost <- r.Host
-			origHandler.ServeHTTP(w, r)
-		})
-
-	ws, resp, err := cstDialer.Dial(s.URL, http.Header{"Host": {"testhost"}})
-	if err != nil {
-		t.Fatalf("Dial: %v", err)
-	}
-	defer ws.Close()
-
-	if resp.StatusCode != http.StatusSwitchingProtocols {
-		t.Fatalf("resp.StatusCode = %v, want http.StatusSwitchingProtocols", resp.StatusCode)
-	}
-
-	if gotHost := <-specifiedHost; gotHost != "testhost" {
-		t.Fatalf("gotHost = %q, want \"testhost\"", gotHost)
-	}
-
-	sendRecv(t, ws)
-}
diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/client_test.go b/Godeps/_workspace/src/github.com/gorilla/websocket/client_test.go
index 07a9cb453ed7353dbbfa098a6a7020b8d82b4615..d2f2ebd798b2f1834fa2d19b6508b82eb2a77b01 100644
--- a/Godeps/_workspace/src/github.com/gorilla/websocket/client_test.go
+++ b/Godeps/_workspace/src/github.com/gorilla/websocket/client_test.go
@@ -20,7 +20,6 @@ var parseURLTests = []struct {
 	{"wss://example.com/", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/"}},
 	{"wss://example.com/a/b", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/a/b"}},
 	{"ss://example.com/a/b", nil},
-	{"ws://webmaster@example.com/", nil},
 }
 
 func TestParseURL(t *testing.T) {
diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/conn.go b/Godeps/_workspace/src/github.com/gorilla/websocket/conn.go
index e719f1ce63eee37e332a244960df9b126cd407a3..86c35e5fc06136f5a3d712dcc282640883cd08e7 100644
--- a/Godeps/_workspace/src/github.com/gorilla/websocket/conn.go
+++ b/Godeps/_workspace/src/github.com/gorilla/websocket/conn.go
@@ -801,7 +801,7 @@ func (c *Conn) SetPingHandler(h func(string) error) {
 	c.handlePing = h
 }
 
-// SetPongHandler sets the handler for pong messages received from the peer.
+// SetPongHandler sets then handler for pong messages received from the peer.
 // The default pong handler does nothing.
 func (c *Conn) SetPongHandler(h func(string) error) {
 	if h == nil {
diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/doc.go b/Godeps/_workspace/src/github.com/gorilla/websocket/doc.go
index f52925dd11a50a9b5d01fe85c73f0e774f31fc7e..0d2bd912b3e475e4acff7291130d6b76f9a08d93 100644
--- a/Godeps/_workspace/src/github.com/gorilla/websocket/doc.go
+++ b/Godeps/_workspace/src/github.com/gorilla/websocket/doc.go
@@ -24,7 +24,7 @@
 //      ... Use conn to send and receive messages.
 //  }
 //
-// Call the connection's WriteMessage and ReadMessage methods to send and
+// Call the connection WriteMessage and ReadMessages methods to send and
 // receive messages as a slice of bytes. This snippet of code shows how to echo
 // messages using these methods:
 //
diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/examples/autobahn/server.go b/Godeps/_workspace/src/github.com/gorilla/websocket/examples/autobahn/server.go
index d96ac84dbf282d639c2619f233e124cedcb7a0d0..b7eed0da47c4cddf21b7fd9d37fc1f6e6dce0218 100644
--- a/Godeps/_workspace/src/github.com/gorilla/websocket/examples/autobahn/server.go
+++ b/Godeps/_workspace/src/github.com/gorilla/websocket/examples/autobahn/server.go
@@ -8,7 +8,7 @@ package main
 import (
 	"errors"
 	"flag"
-	"github.com/gorilla/websocket"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gorilla/websocket"
 	"io"
 	"log"
 	"net/http"
diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/examples/chat/conn.go b/Godeps/_workspace/src/github.com/gorilla/websocket/examples/chat/conn.go
index 7cc0496c3e05d930ce8e47b218b696af3cad33d4..00b4645a47bb9ea0790e2cebf7b3bcd766d720e4 100644
--- a/Godeps/_workspace/src/github.com/gorilla/websocket/examples/chat/conn.go
+++ b/Godeps/_workspace/src/github.com/gorilla/websocket/examples/chat/conn.go
@@ -5,7 +5,7 @@
 package main
 
 import (
-	"github.com/gorilla/websocket"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gorilla/websocket"
 	"log"
 	"net/http"
 	"time"
diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/examples/filewatch/main.go b/Godeps/_workspace/src/github.com/gorilla/websocket/examples/filewatch/main.go
index a2c7b85fab38b96b19c9c6145b80f95cd5262dea..37d7433ebf93f58856211f2050caf3ade9059ded 100644
--- a/Godeps/_workspace/src/github.com/gorilla/websocket/examples/filewatch/main.go
+++ b/Godeps/_workspace/src/github.com/gorilla/websocket/examples/filewatch/main.go
@@ -14,7 +14,7 @@ import (
 	"text/template"
 	"time"
 
-	"github.com/gorilla/websocket"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gorilla/websocket"
 )
 
 const (
diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/json.go b/Godeps/_workspace/src/github.com/gorilla/websocket/json.go
index 18e62f2256cbff262fe9273884b59e853c03a0bb..e0668f25e15fc65279662c32269ea677127e91d8 100644
--- a/Godeps/_workspace/src/github.com/gorilla/websocket/json.go
+++ b/Godeps/_workspace/src/github.com/gorilla/websocket/json.go
@@ -6,7 +6,6 @@ package websocket
 
 import (
 	"encoding/json"
-	"io"
 )
 
 // WriteJSON is deprecated, use c.WriteJSON instead.
@@ -46,12 +45,5 @@ func (c *Conn) ReadJSON(v interface{}) error {
 	if err != nil {
 		return err
 	}
-	err = json.NewDecoder(r).Decode(v)
-	if err == io.EOF {
-		// Decode returns io.EOF when the message is empty or all whitespace.
-		// Convert to io.ErrUnexpectedEOF so that application can distinguish
-		// between an error reading the JSON value and the connection closing.
-		err = io.ErrUnexpectedEOF
-	}
-	return err
+	return json.NewDecoder(r).Decode(v)
 }
diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/json_test.go b/Godeps/_workspace/src/github.com/gorilla/websocket/json_test.go
index 1b7a5ec8bd08f5ec4fd101f53a2b9d51476711f9..2edb28d2f876298f0e7dce0a37db827503eb8c96 100644
--- a/Godeps/_workspace/src/github.com/gorilla/websocket/json_test.go
+++ b/Godeps/_workspace/src/github.com/gorilla/websocket/json_test.go
@@ -6,8 +6,6 @@ package websocket
 
 import (
 	"bytes"
-	"encoding/json"
-	"io"
 	"reflect"
 	"testing"
 )
@@ -38,60 +36,6 @@ func TestJSON(t *testing.T) {
 	}
 }
 
-func TestPartialJsonRead(t *testing.T) {
-	var buf bytes.Buffer
-	c := fakeNetConn{&buf, &buf}
-	wc := newConn(c, true, 1024, 1024)
-	rc := newConn(c, false, 1024, 1024)
-
-	var v struct {
-		A int
-		B string
-	}
-	v.A = 1
-	v.B = "hello"
-
-	messageCount := 0
-
-	// Partial JSON values.
-
-	data, err := json.Marshal(v)
-	if err != nil {
-		t.Fatal(err)
-	}
-	for i := len(data) - 1; i >= 0; i-- {
-		if err := wc.WriteMessage(TextMessage, data[:i]); err != nil {
-			t.Fatal(err)
-		}
-		messageCount++
-	}
-
-	// Whitespace.
-
-	if err := wc.WriteMessage(TextMessage, []byte(" ")); err != nil {
-		t.Fatal(err)
-	}
-	messageCount++
-
-	// Close.
-
-	if err := wc.WriteMessage(CloseMessage, FormatCloseMessage(CloseNormalClosure, "")); err != nil {
-		t.Fatal(err)
-	}
-
-	for i := 0; i < messageCount; i++ {
-		err := rc.ReadJSON(&v)
-		if err != io.ErrUnexpectedEOF {
-			t.Error("read", i, err)
-		}
-	}
-
-	err = rc.ReadJSON(&v)
-	if err != io.EOF {
-		t.Error("final", err)
-	}
-}
-
 func TestDeprecatedJSON(t *testing.T) {
 	var buf bytes.Buffer
 	c := fakeNetConn{&buf, &buf}
diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/server.go b/Godeps/_workspace/src/github.com/gorilla/websocket/server.go
index e56a004933ad31a9846eda5f8942f11e40990ddd..349e5b997ab951174e5dfa6d9b7a27f19e662e1d 100644
--- a/Godeps/_workspace/src/github.com/gorilla/websocket/server.go
+++ b/Godeps/_workspace/src/github.com/gorilla/websocket/server.go
@@ -98,11 +98,11 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
 	}
 
 	if !tokenListContainsValue(r.Header, "Connection", "upgrade") {
-		return u.returnError(w, r, http.StatusBadRequest, "websocket: could not find connection header with token 'upgrade'")
+		return u.returnError(w, r, http.StatusBadRequest, "websocket: connection header != upgrade")
 	}
 
 	if !tokenListContainsValue(r.Header, "Upgrade", "websocket") {
-		return u.returnError(w, r, http.StatusBadRequest, "websocket: could not find upgrade header with token 'websocket'")
+		return u.returnError(w, r, http.StatusBadRequest, "websocket: upgrade != websocket")
 	}
 
 	checkOrigin := u.CheckOrigin
diff --git a/Godeps/_workspace/src/github.com/inconshreveable/log15/stack/stack_test.go b/Godeps/_workspace/src/github.com/inconshreveable/log15/stack/stack_test.go
index 52371b1e45ab1ac08469a56607133e18cc6716d5..64cd7d08075a7c43b884ce6076545c30a0564990 100644
--- a/Godeps/_workspace/src/github.com/inconshreveable/log15/stack/stack_test.go
+++ b/Godeps/_workspace/src/github.com/inconshreveable/log15/stack/stack_test.go
@@ -9,7 +9,7 @@ import (
 	"runtime"
 	"testing"
 
-	"github.com/inconshreveable/log15/stack"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/inconshreveable/log15/stack"
 )
 
 type testType struct{}
diff --git a/Godeps/_workspace/src/github.com/inconshreveable/log15/term/terminal_notwindows.go b/Godeps/_workspace/src/github.com/inconshreveable/log15/term/terminal_notwindows.go
index 87df7d5b0290d5297cf32cfc482e7282e3886c16..c0b201a5308991fe68a003c3684805fcb34fa556 100644
--- a/Godeps/_workspace/src/github.com/inconshreveable/log15/term/terminal_notwindows.go
+++ b/Godeps/_workspace/src/github.com/inconshreveable/log15/term/terminal_notwindows.go
@@ -3,7 +3,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build linux,!appengine darwin freebsd openbsd
+// +build linux,!appengine darwin freebsd
 
 package term
 
diff --git a/Godeps/_workspace/src/github.com/inconshreveable/log15/term/terminal_openbsd.go b/Godeps/_workspace/src/github.com/inconshreveable/log15/term/terminal_openbsd.go
deleted file mode 100644
index 571ece3d139223c8fc9687e1ff140697d8cc39ae..0000000000000000000000000000000000000000
--- a/Godeps/_workspace/src/github.com/inconshreveable/log15/term/terminal_openbsd.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package term
-
-import "syscall"
-
-const ioctlReadTermios = syscall.TIOCGETA
-
-type Termios syscall.Termios
diff --git a/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_bench_test.go b/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_bench_test.go
index 90c280bda102f6cf23c7370fdf43231d4c880eb6..9e9dbc45133be54bae72d4c567d91b5624d9bc46 100644
--- a/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_bench_test.go
+++ b/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_bench_test.go
@@ -3,7 +3,7 @@ package stringutil_test
 import (
 	"testing"
 
-	"github.com/naoina/go-stringutil"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/go-stringutil"
 )
 
 var benchcaseForCamelCase = "the_quick_brown_fox_jumps_over_the_lazy_dog"
diff --git a/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_test.go b/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_test.go
index 69c831e1238ca7e1068090be1b121b96573b05a2..89384c2c0b3c822d4868f1092507b1cc72c57862 100644
--- a/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_test.go
+++ b/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_test.go
@@ -4,7 +4,7 @@ import (
 	"reflect"
 	"testing"
 
-	"github.com/naoina/go-stringutil"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/go-stringutil"
 )
 
 func TestToUpperCamelCase(t *testing.T) {
diff --git a/Godeps/_workspace/src/github.com/naoina/toml/decode.go b/Godeps/_workspace/src/github.com/naoina/toml/decode.go
index c5446fe922d5fbd2e3ca6816f6bcccd268a19e5a..4bc86a4e47eedcc4d4e7db680c5f1a308f3bd1ec 100644
--- a/Godeps/_workspace/src/github.com/naoina/toml/decode.go
+++ b/Godeps/_workspace/src/github.com/naoina/toml/decode.go
@@ -2,13 +2,11 @@ package toml
 
 import (
 	"fmt"
-	"io"
-	"io/ioutil"
 	"reflect"
 	"strconv"
 	"strings"
 
-	"github.com/naoina/toml/ast"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/toml/ast"
 )
 
 const (
@@ -51,29 +49,6 @@ func Unmarshal(data []byte, v interface{}) error {
 	return nil
 }
 
-// A Decoder reads and decodes TOML from an input stream.
-type Decoder struct {
-	r io.Reader
-}
-
-// NewDecoder returns a new Decoder that reads from r.
-// Note that it reads all from r before parsing it.
-func NewDecoder(r io.Reader) *Decoder {
-	return &Decoder{
-		r: r,
-	}
-}
-
-// Decode parses the TOML data from its input and stores it in the value pointed to by v.
-// See the documentation for Unmarshal for details about the conversion of TOML into a Go value.
-func (d *Decoder) Decode(v interface{}) error {
-	b, err := ioutil.ReadAll(d.r)
-	if err != nil {
-		return err
-	}
-	return Unmarshal(b, v)
-}
-
 // Unmarshaler is the interface implemented by objects that can unmarshal a
 // TOML description of themselves.
 // The input can be assumed to be a valid encoding of a TOML value.
diff --git a/Godeps/_workspace/src/github.com/naoina/toml/decode_bench_test.go b/Godeps/_workspace/src/github.com/naoina/toml/decode_bench_test.go
index b85c1c680ffc50bd35f9789434ac820140d6fb3d..94ffdfb365ba1f69ecb48a0a9a098956abe5a2b0 100644
--- a/Godeps/_workspace/src/github.com/naoina/toml/decode_bench_test.go
+++ b/Godeps/_workspace/src/github.com/naoina/toml/decode_bench_test.go
@@ -4,7 +4,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/naoina/toml"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/toml"
 )
 
 func BenchmarkUnmarshal(b *testing.B) {
diff --git a/Godeps/_workspace/src/github.com/naoina/toml/decode_test.go b/Godeps/_workspace/src/github.com/naoina/toml/decode_test.go
index 1fcae9b7abcd64a96572e7640fcd449536d415ad..17dd2e79b56155af3609167becb7975ffafe5b66 100644
--- a/Godeps/_workspace/src/github.com/naoina/toml/decode_test.go
+++ b/Godeps/_workspace/src/github.com/naoina/toml/decode_test.go
@@ -8,7 +8,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/naoina/toml"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/toml"
 )
 
 const (
diff --git a/Godeps/_workspace/src/github.com/naoina/toml/encode.go b/Godeps/_workspace/src/github.com/naoina/toml/encode.go
index 1932538e67b9e4f6c3db7b14e85a49a48517d09a..7465a7a2b996ea2a35f4f16e278dd91c785e5ff9 100644
--- a/Godeps/_workspace/src/github.com/naoina/toml/encode.go
+++ b/Godeps/_workspace/src/github.com/naoina/toml/encode.go
@@ -2,14 +2,13 @@ package toml
 
 import (
 	"fmt"
-	"io"
 	"reflect"
 	"strconv"
 	"time"
 
 	"go/ast"
 
-	"github.com/naoina/go-stringutil"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/go-stringutil"
 )
 
 const (
@@ -44,29 +43,6 @@ func Marshal(v interface{}) ([]byte, error) {
 	return marshal(nil, "", reflect.ValueOf(v), false, false)
 }
 
-// A Encoder writes TOML to an output stream.
-type Encoder struct {
-	w io.Writer
-}
-
-// NewEncoder returns a new Encoder that writes to w.
-func NewEncoder(w io.Writer) *Encoder {
-	return &Encoder{
-		w: w,
-	}
-}
-
-// Encode writes the TOML of v to the stream.
-// See the documentation for Marshal for details about the conversion of Go values to TOML.
-func (e *Encoder) Encode(v interface{}) error {
-	b, err := Marshal(v)
-	if err != nil {
-		return err
-	}
-	_, err = e.w.Write(b)
-	return err
-}
-
 // Marshaler is the interface implemented by objects that can marshal themshelves into valid TOML.
 type Marshaler interface {
 	MarshalTOML() ([]byte, error)
diff --git a/Godeps/_workspace/src/github.com/naoina/toml/encode_test.go b/Godeps/_workspace/src/github.com/naoina/toml/encode_test.go
index 17e04fd0a9d501d30e905db2f93333040f4c1c5e..3445c879e5756aab000beca1931bdcf125daac35 100644
--- a/Godeps/_workspace/src/github.com/naoina/toml/encode_test.go
+++ b/Godeps/_workspace/src/github.com/naoina/toml/encode_test.go
@@ -5,7 +5,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/naoina/toml"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/toml"
 )
 
 func TestMarshal(t *testing.T) {
diff --git a/Godeps/_workspace/src/github.com/naoina/toml/parse.go b/Godeps/_workspace/src/github.com/naoina/toml/parse.go
index e0186662525a4ae11660a97a6c16b6c683132331..f7a3c83cdb47604ca716a0da17fd2e33b4b0ff0d 100644
--- a/Godeps/_workspace/src/github.com/naoina/toml/parse.go
+++ b/Godeps/_workspace/src/github.com/naoina/toml/parse.go
@@ -3,7 +3,7 @@ package toml
 import (
 	"fmt"
 
-	"github.com/naoina/toml/ast"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/toml/ast"
 )
 
 // Parse returns an AST representation of TOML.
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch.go
index ccf390c9cff4bd120180dd47b5b58e9a0c00b102..354ebe4fee5f2bfd622b5ec8700f5de7cc45af56 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch.go
@@ -10,8 +10,8 @@ import (
 	"encoding/binary"
 	"fmt"
 
-	"github.com/syndtr/goleveldb/leveldb/errors"
-	"github.com/syndtr/goleveldb/leveldb/memdb"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb"
 )
 
 type ErrBatchCorrupted struct {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch_test.go
index 7fc842f4fedd6f8dbd9902945d6098d4d556b6f4..e98b683cde11ad97fa83134167be6b7f74eb6b13 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch_test.go
@@ -10,8 +10,8 @@ import (
 	"bytes"
 	"testing"
 
-	"github.com/syndtr/goleveldb/leveldb/comparer"
-	"github.com/syndtr/goleveldb/leveldb/memdb"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb"
 )
 
 type tbRec struct {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/bench2_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/bench2_test.go
deleted file mode 100644
index 0dd60fd829bb83fbe497a9838e6c73e462729c6b..0000000000000000000000000000000000000000
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/bench2_test.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
-// All rights reserved.
-//
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// +build !go1.2
-
-package leveldb
-
-import (
-	"sync/atomic"
-	"testing"
-)
-
-func BenchmarkDBReadConcurrent(b *testing.B) {
-	p := openDBBench(b, false)
-	p.populate(b.N)
-	p.fill()
-	p.gc()
-	defer p.close()
-
-	b.ResetTimer()
-	b.SetBytes(116)
-
-	b.RunParallel(func(pb *testing.PB) {
-		iter := p.newIter()
-		defer iter.Release()
-		for pb.Next() && iter.Next() {
-		}
-	})
-}
-
-func BenchmarkDBReadConcurrent2(b *testing.B) {
-	p := openDBBench(b, false)
-	p.populate(b.N)
-	p.fill()
-	p.gc()
-	defer p.close()
-
-	b.ResetTimer()
-	b.SetBytes(116)
-
-	var dir uint32
-	b.RunParallel(func(pb *testing.PB) {
-		iter := p.newIter()
-		defer iter.Release()
-		if atomic.AddUint32(&dir, 1)%2 == 0 {
-			for pb.Next() && iter.Next() {
-			}
-		} else {
-			if pb.Next() && iter.Last() {
-				for pb.Next() && iter.Prev() {
-				}
-			}
-		}
-	})
-}
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/bench_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/bench_test.go
index 91b426709d59a8fb0860cec31ba601f9daca3605..621e52db283da81202a19a0f464ae3ab0b0a0fb4 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/bench_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/bench_test.go
@@ -15,9 +15,9 @@ import (
 	"runtime"
 	"testing"
 
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/storage"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage"
 )
 
 func randomString(r *rand.Rand, n int) []byte {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/bench2_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/bench2_test.go
deleted file mode 100644
index 175e2220323c8428957d1cad24aa9e8604f8a23e..0000000000000000000000000000000000000000
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/bench2_test.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
-// All rights reserved.
-//
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// +build !go1.2
-
-package cache
-
-import (
-	"math/rand"
-	"testing"
-)
-
-func BenchmarkLRUCache(b *testing.B) {
-	c := NewCache(NewLRU(10000))
-
-	b.SetParallelism(10)
-	b.RunParallel(func(pb *testing.PB) {
-		r := rand.New(rand.NewSource(time.Now().UnixNano()))
-
-		for pb.Next() {
-			key := uint64(r.Intn(1000000))
-			c.Get(0, key, func() (int, Value) {
-				return 1, key
-			}).Release()
-		}
-	})
-}
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache.go
index c9670de5de6f70f4ba905df39776f67a42ff32d1..9ae499311026ce392b16b641577337f946754ef0 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache.go
@@ -12,7 +12,7 @@ import (
 	"sync/atomic"
 	"unsafe"
 
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 // Cacher provides interface to implements a caching functionality.
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache_test.go
index c2a50156f0472c99d3b60022781435fc18cf8947..5575583dcef4c151badda08a1d9009888884157e 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache_test.go
@@ -552,3 +552,19 @@ func TestLRUCache_Close(t *testing.T) {
 		t.Errorf("delFunc isn't called 1 times: got=%d", delFuncCalled)
 	}
 }
+
+func BenchmarkLRUCache(b *testing.B) {
+	c := NewCache(NewLRU(10000))
+
+	b.SetParallelism(10)
+	b.RunParallel(func(pb *testing.PB) {
+		r := rand.New(rand.NewSource(time.Now().UnixNano()))
+
+		for pb.Next() {
+			key := uint64(r.Intn(1000000))
+			c.Get(0, key, func() (int, Value) {
+				return 1, key
+			}).Release()
+		}
+	})
+}
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer.go
index d33d5e9c78fcf566114dce757ffe4ea6e0f0ba46..6e57fab707a08b08c1bd088dac3088c7bd6e48a9 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer.go
@@ -6,7 +6,7 @@
 
 package leveldb
 
-import "github.com/syndtr/goleveldb/leveldb/comparer"
+import "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer"
 
 type iComparer struct {
 	ucmp comparer.Comparer
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/corrupt_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/corrupt_test.go
index a351874ed4351f6d0abf67719bf7698d4228216a..f1ef0743e955f114cea9018d051e45d898787464 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/corrupt_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/corrupt_test.go
@@ -9,9 +9,9 @@ package leveldb
 import (
 	"bytes"
 	"fmt"
-	"github.com/syndtr/goleveldb/leveldb/filter"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/storage"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage"
 	"io"
 	"math/rand"
 	"testing"
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db.go
index def86bc1aa8240e30aba67c204f0e0c311a48b37..03c6a06867327b8ab74a9c91acc6bc0200efb05b 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db.go
@@ -17,14 +17,14 @@ import (
 	"sync/atomic"
 	"time"
 
-	"github.com/syndtr/goleveldb/leveldb/errors"
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/journal"
-	"github.com/syndtr/goleveldb/leveldb/memdb"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/storage"
-	"github.com/syndtr/goleveldb/leveldb/table"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 // DB is a LevelDB database.
@@ -63,14 +63,13 @@ type DB struct {
 	journalAckC  chan error
 
 	// Compaction.
-	tcompCmdC        chan cCmd
-	tcompPauseC      chan chan<- struct{}
-	mcompCmdC        chan cCmd
-	compErrC         chan error
-	compPerErrC      chan error
-	compErrSetC      chan error
-	compWriteLocking bool
-	compStats        []cStats
+	tcompCmdC   chan cCmd
+	tcompPauseC chan chan<- struct{}
+	mcompCmdC   chan cCmd
+	compErrC    chan error
+	compPerErrC chan error
+	compErrSetC chan error
+	compStats   []cStats
 
 	// Close.
 	closeW sync.WaitGroup
@@ -109,44 +108,28 @@ func openDB(s *session) (*DB, error) {
 		closeC: make(chan struct{}),
 	}
 
-	// Read-only mode.
-	readOnly := s.o.GetReadOnly()
-
-	if readOnly {
-		// Recover journals (read-only mode).
-		if err := db.recoverJournalRO(); err != nil {
-			return nil, err
-		}
-	} else {
-		// Recover journals.
-		if err := db.recoverJournal(); err != nil {
-			return nil, err
-		}
+	if err := db.recoverJournal(); err != nil {
+		return nil, err
+	}
 
-		// Remove any obsolete files.
-		if err := db.checkAndCleanFiles(); err != nil {
-			// Close journal.
-			if db.journal != nil {
-				db.journal.Close()
-				db.journalWriter.Close()
-			}
-			return nil, err
+	// Remove any obsolete files.
+	if err := db.checkAndCleanFiles(); err != nil {
+		// Close journal.
+		if db.journal != nil {
+			db.journal.Close()
+			db.journalWriter.Close()
 		}
-
+		return nil, err
 	}
 
 	// Doesn't need to be included in the wait group.
 	go db.compactionError()
 	go db.mpoolDrain()
 
-	if readOnly {
-		db.SetReadOnly()
-	} else {
-		db.closeW.Add(3)
-		go db.tCompaction()
-		go db.mCompaction()
-		go db.jWriter()
-	}
+	db.closeW.Add(3)
+	go db.tCompaction()
+	go db.mCompaction()
+	go db.jWriter()
 
 	s.logf("db@open done T·%v", time.Since(start))
 
@@ -292,7 +275,7 @@ func recoverTable(s *session, o *opt.Options) error {
 		// We will drop corrupted table.
 		strict = o.GetStrict(opt.StrictRecovery)
 
-		rec   = &sessionRecord{}
+		rec   = &sessionRecord{numLevel: o.GetNumLevel()}
 		bpool = util.NewBufferPool(o.GetBlockSize() + 5)
 	)
 	buildTable := func(iter iterator.Iterator) (tmp storage.File, size int64, err error) {
@@ -364,14 +347,12 @@ func recoverTable(s *session, o *opt.Options) error {
 			return err
 		}
 		iter := tr.NewIterator(nil, nil)
-		if itererr, ok := iter.(iterator.ErrorCallbackSetter); ok {
-			itererr.SetErrorCallback(func(err error) {
-				if errors.IsCorrupted(err) {
-					s.logf("table@recovery block corruption @%d %q", file.Num(), err)
-					tcorruptedBlock++
-				}
-			})
-		}
+		iter.(iterator.ErrorCallbackSetter).SetErrorCallback(func(err error) {
+			if errors.IsCorrupted(err) {
+				s.logf("table@recovery block corruption @%d %q", file.Num(), err)
+				tcorruptedBlock++
+			}
+		})
 
 		// Scan the table.
 		for iter.Next() {
@@ -467,136 +448,132 @@ func recoverTable(s *session, o *opt.Options) error {
 }
 
 func (db *DB) recoverJournal() error {
-	// Get all journals and sort it by file number.
-	allJournalFiles, err := db.s.getFiles(storage.TypeJournal)
+	// Get all tables and sort it by file number.
+	journalFiles_, err := db.s.getFiles(storage.TypeJournal)
 	if err != nil {
 		return err
 	}
-	files(allJournalFiles).sort()
+	journalFiles := files(journalFiles_)
+	journalFiles.sort()
 
-	// Journals that will be recovered.
-	var recJournalFiles []storage.File
-	for _, jf := range allJournalFiles {
-		if jf.Num() >= db.s.stJournalNum || jf.Num() == db.s.stPrevJournalNum {
-			recJournalFiles = append(recJournalFiles, jf)
+	// Discard older journal.
+	prev := -1
+	for i, file := range journalFiles {
+		if file.Num() >= db.s.stJournalNum {
+			if prev >= 0 {
+				i--
+				journalFiles[i] = journalFiles[prev]
+			}
+			journalFiles = journalFiles[i:]
+			break
+		} else if file.Num() == db.s.stPrevJournalNum {
+			prev = i
+		}
+	}
+
+	var jr *journal.Reader
+	var of storage.File
+	var mem *memdb.DB
+	batch := new(Batch)
+	cm := newCMem(db.s)
+	buf := new(util.Buffer)
+	// Options.
+	strict := db.s.o.GetStrict(opt.StrictJournal)
+	checksum := db.s.o.GetStrict(opt.StrictJournalChecksum)
+	writeBuffer := db.s.o.GetWriteBuffer()
+	recoverJournal := func(file storage.File) error {
+		db.logf("journal@recovery recovering @%d", file.Num())
+		reader, err := file.Open()
+		if err != nil {
+			return err
 		}
-	}
+		defer reader.Close()
 
-	var (
-		of  storage.File // Obsolete file.
-		rec = &sessionRecord{}
-	)
-
-	// Recover journals.
-	if len(recJournalFiles) > 0 {
-		db.logf("journal@recovery F·%d", len(recJournalFiles))
-
-		// Mark file number as used.
-		db.s.markFileNum(recJournalFiles[len(recJournalFiles)-1].Num())
-
-		var (
-			// Options.
-			strict      = db.s.o.GetStrict(opt.StrictJournal)
-			checksum    = db.s.o.GetStrict(opt.StrictJournalChecksum)
-			writeBuffer = db.s.o.GetWriteBuffer()
-
-			jr    *journal.Reader
-			mdb   = memdb.New(db.s.icmp, writeBuffer)
-			buf   = &util.Buffer{}
-			batch = &Batch{}
-		)
-
-		for _, jf := range recJournalFiles {
-			db.logf("journal@recovery recovering @%d", jf.Num())
+		// Create/reset journal reader instance.
+		if jr == nil {
+			jr = journal.NewReader(reader, dropper{db.s, file}, strict, checksum)
+		} else {
+			jr.Reset(reader, dropper{db.s, file}, strict, checksum)
+		}
 
-			fr, err := jf.Open()
-			if err != nil {
+		// Flush memdb and remove obsolete journal file.
+		if of != nil {
+			if mem.Len() > 0 {
+				if err := cm.flush(mem, 0); err != nil {
+					return err
+				}
+			}
+			if err := cm.commit(file.Num(), db.seq); err != nil {
 				return err
 			}
+			cm.reset()
+			of.Remove()
+			of = nil
+		}
 
-			// Create or reset journal reader instance.
-			if jr == nil {
-				jr = journal.NewReader(fr, dropper{db.s, jf}, strict, checksum)
-			} else {
-				jr.Reset(fr, dropper{db.s, jf}, strict, checksum)
+		// Replay journal to memdb.
+		mem.Reset()
+		for {
+			r, err := jr.Next()
+			if err != nil {
+				if err == io.EOF {
+					break
+				}
+				return errors.SetFile(err, file)
 			}
 
-			// Flush memdb and remove obsolete journal file.
-			if of != nil {
-				if mdb.Len() > 0 {
-					if _, err := db.s.flushMemdb(rec, mdb, -1); err != nil {
-						fr.Close()
-						return err
-					}
+			buf.Reset()
+			if _, err := buf.ReadFrom(r); err != nil {
+				if err == io.ErrUnexpectedEOF {
+					// This is error returned due to corruption, with strict == false.
+					continue
+				} else {
+					return errors.SetFile(err, file)
 				}
-
-				rec.setJournalNum(jf.Num())
-				rec.setSeqNum(db.seq)
-				if err := db.s.commit(rec); err != nil {
-					fr.Close()
-					return err
+			}
+			if err := batch.memDecodeAndReplay(db.seq, buf.Bytes(), mem); err != nil {
+				if strict || !errors.IsCorrupted(err) {
+					return errors.SetFile(err, file)
+				} else {
+					db.s.logf("journal error: %v (skipped)", err)
+					// We won't apply sequence number as it might be corrupted.
+					continue
 				}
-				rec.resetAddedTables()
-
-				of.Remove()
-				of = nil
 			}
 
-			// Replay journal to memdb.
-			mdb.Reset()
-			for {
-				r, err := jr.Next()
-				if err != nil {
-					if err == io.EOF {
-						break
-					}
+			// Save sequence number.
+			db.seq = batch.seq + uint64(batch.Len())
 
-					fr.Close()
-					return errors.SetFile(err, jf)
+			// Flush it if large enough.
+			if mem.Size() >= writeBuffer {
+				if err := cm.flush(mem, 0); err != nil {
+					return err
 				}
+				mem.Reset()
+			}
+		}
 
-				buf.Reset()
-				if _, err := buf.ReadFrom(r); err != nil {
-					if err == io.ErrUnexpectedEOF {
-						// This is error returned due to corruption, with strict == false.
-						continue
-					}
-
-					fr.Close()
-					return errors.SetFile(err, jf)
-				}
-				if err := batch.memDecodeAndReplay(db.seq, buf.Bytes(), mdb); err != nil {
-					if !strict && errors.IsCorrupted(err) {
-						db.s.logf("journal error: %v (skipped)", err)
-						// We won't apply sequence number as it might be corrupted.
-						continue
-					}
-
-					fr.Close()
-					return errors.SetFile(err, jf)
-				}
+		of = file
+		return nil
+	}
 
-				// Save sequence number.
-				db.seq = batch.seq + uint64(batch.Len())
+	// Recover all journals.
+	if len(journalFiles) > 0 {
+		db.logf("journal@recovery F·%d", len(journalFiles))
 
-				// Flush it if large enough.
-				if mdb.Size() >= writeBuffer {
-					if _, err := db.s.flushMemdb(rec, mdb, 0); err != nil {
-						fr.Close()
-						return err
-					}
+		// Mark file number as used.
+		db.s.markFileNum(journalFiles[len(journalFiles)-1].Num())
 
-					mdb.Reset()
-				}
+		mem = memdb.New(db.s.icmp, writeBuffer)
+		for _, file := range journalFiles {
+			if err := recoverJournal(file); err != nil {
+				return err
 			}
-
-			fr.Close()
-			of = jf
 		}
 
-		// Flush the last memdb.
-		if mdb.Len() > 0 {
-			if _, err := db.s.flushMemdb(rec, mdb, 0); err != nil {
+		// Flush the last journal.
+		if mem.Len() > 0 {
+			if err := cm.flush(mem, 0); err != nil {
 				return err
 			}
 		}
@@ -608,10 +585,8 @@ func (db *DB) recoverJournal() error {
 	}
 
 	// Commit.
-	rec.setJournalNum(db.journalFile.Num())
-	rec.setSeqNum(db.seq)
-	if err := db.s.commit(rec); err != nil {
-		// Close journal on error.
+	if err := cm.commit(db.journalFile.Num(), db.seq); err != nil {
+		// Close journal.
 		if db.journal != nil {
 			db.journal.Close()
 			db.journalWriter.Close()
@@ -627,103 +602,6 @@ func (db *DB) recoverJournal() error {
 	return nil
 }
 
-func (db *DB) recoverJournalRO() error {
-	// Get all journals and sort it by file number.
-	allJournalFiles, err := db.s.getFiles(storage.TypeJournal)
-	if err != nil {
-		return err
-	}
-	files(allJournalFiles).sort()
-
-	// Journals that will be recovered.
-	var recJournalFiles []storage.File
-	for _, jf := range allJournalFiles {
-		if jf.Num() >= db.s.stJournalNum || jf.Num() == db.s.stPrevJournalNum {
-			recJournalFiles = append(recJournalFiles, jf)
-		}
-	}
-
-	var (
-		// Options.
-		strict      = db.s.o.GetStrict(opt.StrictJournal)
-		checksum    = db.s.o.GetStrict(opt.StrictJournalChecksum)
-		writeBuffer = db.s.o.GetWriteBuffer()
-
-		mdb = memdb.New(db.s.icmp, writeBuffer)
-	)
-
-	// Recover journals.
-	if len(recJournalFiles) > 0 {
-		db.logf("journal@recovery RO·Mode F·%d", len(recJournalFiles))
-
-		var (
-			jr    *journal.Reader
-			buf   = &util.Buffer{}
-			batch = &Batch{}
-		)
-
-		for _, jf := range recJournalFiles {
-			db.logf("journal@recovery recovering @%d", jf.Num())
-
-			fr, err := jf.Open()
-			if err != nil {
-				return err
-			}
-
-			// Create or reset journal reader instance.
-			if jr == nil {
-				jr = journal.NewReader(fr, dropper{db.s, jf}, strict, checksum)
-			} else {
-				jr.Reset(fr, dropper{db.s, jf}, strict, checksum)
-			}
-
-			// Replay journal to memdb.
-			for {
-				r, err := jr.Next()
-				if err != nil {
-					if err == io.EOF {
-						break
-					}
-
-					fr.Close()
-					return errors.SetFile(err, jf)
-				}
-
-				buf.Reset()
-				if _, err := buf.ReadFrom(r); err != nil {
-					if err == io.ErrUnexpectedEOF {
-						// This is error returned due to corruption, with strict == false.
-						continue
-					}
-
-					fr.Close()
-					return errors.SetFile(err, jf)
-				}
-				if err := batch.memDecodeAndReplay(db.seq, buf.Bytes(), mdb); err != nil {
-					if !strict && errors.IsCorrupted(err) {
-						db.s.logf("journal error: %v (skipped)", err)
-						// We won't apply sequence number as it might be corrupted.
-						continue
-					}
-
-					fr.Close()
-					return errors.SetFile(err, jf)
-				}
-
-				// Save sequence number.
-				db.seq = batch.seq + uint64(batch.Len())
-			}
-
-			fr.Close()
-		}
-	}
-
-	// Set memDB.
-	db.mem = &memDB{db: db, DB: mdb, ref: 1}
-
-	return nil
-}
-
 func (db *DB) get(key []byte, seq uint64, ro *opt.ReadOptions) (value []byte, err error) {
 	ikey := newIkey(key, seq, ktSeek)
 
@@ -734,7 +612,7 @@ func (db *DB) get(key []byte, seq uint64, ro *opt.ReadOptions) (value []byte, er
 		}
 		defer m.decref()
 
-		mk, mv, me := m.Find(ikey)
+		mk, mv, me := m.mdb.Find(ikey)
 		if me == nil {
 			ukey, _, kt, kerr := parseIkey(mk)
 			if kerr != nil {
@@ -772,7 +650,7 @@ func (db *DB) has(key []byte, seq uint64, ro *opt.ReadOptions) (ret bool, err er
 		}
 		defer m.decref()
 
-		mk, _, me := m.Find(ikey)
+		mk, _, me := m.mdb.Find(ikey)
 		if me == nil {
 			ukey, _, kt, kerr := parseIkey(mk)
 			if kerr != nil {
@@ -904,7 +782,7 @@ func (db *DB) GetProperty(name string) (value string, err error) {
 
 	const prefix = "leveldb."
 	if !strings.HasPrefix(name, prefix) {
-		return "", ErrNotFound
+		return "", errors.New("leveldb: GetProperty: unknown property: " + name)
 	}
 	p := name[len(prefix):]
 
@@ -918,7 +796,7 @@ func (db *DB) GetProperty(name string) (value string, err error) {
 		var rest string
 		n, _ := fmt.Sscanf(p[len(numFilesPrefix):], "%d%s", &level, &rest)
 		if n != 1 || int(level) >= db.s.o.GetNumLevel() {
-			err = ErrNotFound
+			err = errors.New("leveldb: GetProperty: invalid property: " + name)
 		} else {
 			value = fmt.Sprint(v.tLen(int(level)))
 		}
@@ -957,7 +835,7 @@ func (db *DB) GetProperty(name string) (value string, err error) {
 	case p == "aliveiters":
 		value = fmt.Sprintf("%d", atomic.LoadInt32(&db.aliveIters))
 	default:
-		err = ErrNotFound
+		err = errors.New("leveldb: GetProperty: unknown property: " + name)
 	}
 
 	return
@@ -1020,9 +898,6 @@ func (db *DB) Close() error {
 	var err error
 	select {
 	case err = <-db.compErrC:
-		if err == ErrReadOnly {
-			err = nil
-		}
 	default:
 	}
 
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_compaction.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_compaction.go
index 26003106ead5ad7436db63da0f49dbfcd1c2cdf1..2f14a588fec1b697d89073853761c3184047ea88 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_compaction.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_compaction.go
@@ -10,8 +10,9 @@ import (
 	"sync"
 	"time"
 
-	"github.com/syndtr/goleveldb/leveldb/errors"
-	"github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
 )
 
 var (
@@ -61,8 +62,58 @@ func (p *cStatsStaging) stopTimer() {
 	}
 }
 
+type cMem struct {
+	s     *session
+	level int
+	rec   *sessionRecord
+}
+
+func newCMem(s *session) *cMem {
+	return &cMem{s: s, rec: &sessionRecord{numLevel: s.o.GetNumLevel()}}
+}
+
+func (c *cMem) flush(mem *memdb.DB, level int) error {
+	s := c.s
+
+	// Write memdb to table.
+	iter := mem.NewIterator(nil)
+	defer iter.Release()
+	t, n, err := s.tops.createFrom(iter)
+	if err != nil {
+		return err
+	}
+
+	// Pick level.
+	if level < 0 {
+		v := s.version()
+		level = v.pickLevel(t.imin.ukey(), t.imax.ukey())
+		v.release()
+	}
+	c.rec.addTableFile(level, t)
+
+	s.logf("mem@flush created L%d@%d N·%d S·%s %q:%q", level, t.file.Num(), n, shortenb(int(t.size)), t.imin, t.imax)
+
+	c.level = level
+	return nil
+}
+
+func (c *cMem) reset() {
+	c.rec = &sessionRecord{numLevel: c.s.o.GetNumLevel()}
+}
+
+func (c *cMem) commit(journal, seq uint64) error {
+	c.rec.setJournalNum(journal)
+	c.rec.setSeqNum(seq)
+
+	// Commit changes.
+	return c.s.commit(c.rec)
+}
+
 func (db *DB) compactionError() {
-	var err error
+	var (
+		err     error
+		wlocked bool
+	)
 noerr:
 	// No error.
 	for {
@@ -70,7 +121,7 @@ noerr:
 		case err = <-db.compErrSetC:
 			switch {
 			case err == nil:
-			case err == ErrReadOnly, errors.IsCorrupted(err):
+			case errors.IsCorrupted(err):
 				goto hasperr
 			default:
 				goto haserr
@@ -88,7 +139,7 @@ haserr:
 			switch {
 			case err == nil:
 				goto noerr
-			case err == ErrReadOnly, errors.IsCorrupted(err):
+			case errors.IsCorrupted(err):
 				goto hasperr
 			default:
 			}
@@ -104,9 +155,9 @@ hasperr:
 		case db.compPerErrC <- err:
 		case db.writeLockC <- struct{}{}:
 			// Hold write lock, so that write won't pass-through.
-			db.compWriteLocking = true
+			wlocked = true
 		case _, _ = <-db.closeC:
-			if db.compWriteLocking {
+			if wlocked {
 				// We should release the lock or Close will hang.
 				<-db.writeLockC
 			}
@@ -236,18 +287,21 @@ func (db *DB) compactionExitTransact() {
 }
 
 func (db *DB) memCompaction() {
-	mdb := db.getFrozenMem()
-	if mdb == nil {
+	mem := db.getFrozenMem()
+	if mem == nil {
 		return
 	}
-	defer mdb.decref()
+	defer mem.decref()
+
+	c := newCMem(db.s)
+	stats := new(cStatsStaging)
 
-	db.logf("memdb@flush N·%d S·%s", mdb.Len(), shortenb(mdb.Size()))
+	db.logf("mem@flush N·%d S·%s", mem.mdb.Len(), shortenb(mem.mdb.Size()))
 
 	// Don't compact empty memdb.
-	if mdb.Len() == 0 {
-		db.logf("memdb@flush skipping")
-		// drop frozen memdb
+	if mem.mdb.Len() == 0 {
+		db.logf("mem@flush skipping")
+		// drop frozen mem
 		db.dropFrozenMem()
 		return
 	}
@@ -263,20 +317,13 @@ func (db *DB) memCompaction() {
 		return
 	}
 
-	var (
-		rec        = &sessionRecord{}
-		stats      = &cStatsStaging{}
-		flushLevel int
-	)
-
-	db.compactionTransactFunc("memdb@flush", func(cnt *compactionTransactCounter) (err error) {
+	db.compactionTransactFunc("mem@flush", func(cnt *compactionTransactCounter) (err error) {
 		stats.startTimer()
-		flushLevel, err = db.s.flushMemdb(rec, mdb.DB, -1)
-		stats.stopTimer()
-		return
+		defer stats.stopTimer()
+		return c.flush(mem.mdb, -1)
 	}, func() error {
-		for _, r := range rec.addedTables {
-			db.logf("memdb@flush revert @%d", r.num)
+		for _, r := range c.rec.addedTables {
+			db.logf("mem@flush revert @%d", r.num)
 			f := db.s.getTableFile(r.num)
 			if err := f.Remove(); err != nil {
 				return err
@@ -285,23 +332,20 @@ func (db *DB) memCompaction() {
 		return nil
 	})
 
-	db.compactionTransactFunc("memdb@commit", func(cnt *compactionTransactCounter) (err error) {
+	db.compactionTransactFunc("mem@commit", func(cnt *compactionTransactCounter) (err error) {
 		stats.startTimer()
-		rec.setJournalNum(db.journalFile.Num())
-		rec.setSeqNum(db.frozenSeq)
-		err = db.s.commit(rec)
-		stats.stopTimer()
-		return
+		defer stats.stopTimer()
+		return c.commit(db.journalFile.Num(), db.frozenSeq)
 	}, nil)
 
-	db.logf("memdb@flush committed F·%d T·%v", len(rec.addedTables), stats.duration)
+	db.logf("mem@flush committed F·%d T·%v", len(c.rec.addedTables), stats.duration)
 
-	for _, r := range rec.addedTables {
+	for _, r := range c.rec.addedTables {
 		stats.write += r.size
 	}
-	db.compStats[flushLevel].add(stats)
+	db.compStats[c.level].add(stats)
 
-	// Drop frozen memdb.
+	// Drop frozen mem.
 	db.dropFrozenMem()
 
 	// Resume table compaction.
@@ -513,7 +557,7 @@ func (b *tableCompactionBuilder) revert() error {
 func (db *DB) tableCompaction(c *compaction, noTrivial bool) {
 	defer c.release()
 
-	rec := &sessionRecord{}
+	rec := &sessionRecord{numLevel: db.s.o.GetNumLevel()}
 	rec.addCompPtr(c.level, c.imax)
 
 	if !noTrivial && c.trivial() {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_iter.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_iter.go
index 656ae98567f38ecae293500a2649021ec9fd525f..626369271785310282175947f10a2b473a47c5d4 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_iter.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_iter.go
@@ -8,14 +8,13 @@ package leveldb
 
 import (
 	"errors"
-	"math/rand"
 	"runtime"
 	"sync"
 	"sync/atomic"
 
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 var (
@@ -40,11 +39,11 @@ func (db *DB) newRawIterator(slice *util.Range, ro *opt.ReadOptions) iterator.It
 	ti := v.getIterators(slice, ro)
 	n := len(ti) + 2
 	i := make([]iterator.Iterator, 0, n)
-	emi := em.NewIterator(slice)
+	emi := em.mdb.NewIterator(slice)
 	emi.SetReleaser(&memdbReleaser{m: em})
 	i = append(i, emi)
 	if fm != nil {
-		fmi := fm.NewIterator(slice)
+		fmi := fm.mdb.NewIterator(slice)
 		fmi.SetReleaser(&memdbReleaser{m: fm})
 		i = append(i, fmi)
 	}
@@ -81,10 +80,6 @@ func (db *DB) newIterator(seq uint64, slice *util.Range, ro *opt.ReadOptions) *d
 	return iter
 }
 
-func (db *DB) iterSamplingRate() int {
-	return rand.Intn(2 * db.s.o.GetIteratorSamplingRate())
-}
-
 type dir int
 
 const (
@@ -103,21 +98,11 @@ type dbIter struct {
 	seq    uint64
 	strict bool
 
-	smaplingGap int
-	dir         dir
-	key         []byte
-	value       []byte
-	err         error
-	releaser    util.Releaser
-}
-
-func (i *dbIter) sampleSeek() {
-	ikey := i.iter.Key()
-	i.smaplingGap -= len(ikey) + len(i.iter.Value())
-	for i.smaplingGap < 0 {
-		i.smaplingGap += i.db.iterSamplingRate()
-		i.db.sampleSeek(ikey)
-	}
+	dir      dir
+	key      []byte
+	value    []byte
+	err      error
+	releaser util.Releaser
 }
 
 func (i *dbIter) setErr(err error) {
@@ -190,7 +175,6 @@ func (i *dbIter) Seek(key []byte) bool {
 func (i *dbIter) next() bool {
 	for {
 		if ukey, seq, kt, kerr := parseIkey(i.iter.Key()); kerr == nil {
-			i.sampleSeek()
 			if seq <= i.seq {
 				switch kt {
 				case ktDel:
@@ -241,7 +225,6 @@ func (i *dbIter) prev() bool {
 	if i.iter.Valid() {
 		for {
 			if ukey, seq, kt, kerr := parseIkey(i.iter.Key()); kerr == nil {
-				i.sampleSeek()
 				if seq <= i.seq {
 					if !del && i.icmp.uCompare(ukey, i.key) < 0 {
 						return true
@@ -283,7 +266,6 @@ func (i *dbIter) Prev() bool {
 	case dirForward:
 		for i.iter.Prev() {
 			if ukey, _, _, kerr := parseIkey(i.iter.Key()); kerr == nil {
-				i.sampleSeek()
 				if i.icmp.uCompare(ukey, i.key) < 0 {
 					goto cont
 				}
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_snapshot.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_snapshot.go
index 0372848ff1e4f62ececce67d9abe04d8e08121bd..4af7403317888b03177c989614003cff84009589 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_snapshot.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_snapshot.go
@@ -13,9 +13,9 @@ import (
 	"sync"
 	"sync/atomic"
 
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 type snapshotElement struct {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_state.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_state.go
index 24671dd39ede09ec35cc01a5f0e9bdec926a11bc..ddad4d4a9bcb7b4631c37910443719bd8e033ada 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_state.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_state.go
@@ -10,13 +10,13 @@ import (
 	"sync/atomic"
 	"time"
 
-	"github.com/syndtr/goleveldb/leveldb/journal"
-	"github.com/syndtr/goleveldb/leveldb/memdb"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb"
 )
 
 type memDB struct {
-	db *DB
-	*memdb.DB
+	db  *DB
+	mdb *memdb.DB
 	ref int32
 }
 
@@ -27,12 +27,12 @@ func (m *memDB) incref() {
 func (m *memDB) decref() {
 	if ref := atomic.AddInt32(&m.ref, -1); ref == 0 {
 		// Only put back memdb with std capacity.
-		if m.Capacity() == m.db.s.o.GetWriteBuffer() {
-			m.Reset()
-			m.db.mpoolPut(m.DB)
+		if m.mdb.Capacity() == m.db.s.o.GetWriteBuffer() {
+			m.mdb.Reset()
+			m.db.mpoolPut(m.mdb)
 		}
 		m.db = nil
-		m.DB = nil
+		m.mdb = nil
 	} else if ref < 0 {
 		panic("negative memdb ref")
 	}
@@ -48,15 +48,6 @@ func (db *DB) addSeq(delta uint64) {
 	atomic.AddUint64(&db.seq, delta)
 }
 
-func (db *DB) sampleSeek(ikey iKey) {
-	v := db.s.version()
-	if v.sampleSeek(ikey) {
-		// Trigger table compaction.
-		db.compSendTrigger(db.tcompCmdC)
-	}
-	v.release()
-}
-
 func (db *DB) mpoolPut(mem *memdb.DB) {
 	defer func() {
 		recover()
@@ -126,7 +117,7 @@ func (db *DB) newMem(n int) (mem *memDB, err error) {
 	}
 	mem = &memDB{
 		db:  db,
-		DB:  mdb,
+		mdb: mdb,
 		ref: 2,
 	}
 	db.mem = mem
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_test.go
index 9d91ebf1a80e78e399b745edeb8e61bbaa3bf0c8..b2e0fb36f2eca1271313ef1a5c3df75f0c2f9ca3 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_test.go
@@ -23,13 +23,13 @@ import (
 	"time"
 	"unsafe"
 
-	"github.com/syndtr/goleveldb/leveldb/comparer"
-	"github.com/syndtr/goleveldb/leveldb/errors"
-	"github.com/syndtr/goleveldb/leveldb/filter"
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/storage"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 func tkey(i int) []byte {
@@ -405,21 +405,19 @@ func (h *dbHarness) compactRange(min, max string) {
 	t.Log("DB range compaction done")
 }
 
-func (h *dbHarness) sizeOf(start, limit string) uint64 {
-	sz, err := h.db.SizeOf([]util.Range{
+func (h *dbHarness) sizeAssert(start, limit string, low, hi uint64) {
+	t := h.t
+	db := h.db
+
+	s, err := db.SizeOf([]util.Range{
 		{[]byte(start), []byte(limit)},
 	})
 	if err != nil {
-		h.t.Error("SizeOf: got error: ", err)
+		t.Error("SizeOf: got error: ", err)
 	}
-	return sz.Sum()
-}
-
-func (h *dbHarness) sizeAssert(start, limit string, low, hi uint64) {
-	sz := h.sizeOf(start, limit)
-	if sz < low || sz > hi {
-		h.t.Errorf("sizeOf %q to %q not in range, want %d - %d, got %d",
-			shorten(start), shorten(limit), low, hi, sz)
+	if s.Sum() < low || s.Sum() > hi {
+		t.Errorf("sizeof %q to %q not in range, want %d - %d, got %d",
+			shorten(start), shorten(limit), low, hi, s.Sum())
 	}
 }
 
@@ -2445,7 +2443,7 @@ func TestDB_TableCompactionBuilder(t *testing.T) {
 		if err != nil {
 			t.Fatal(err)
 		}
-		rec := &sessionRecord{}
+		rec := &sessionRecord{numLevel: s.o.GetNumLevel()}
 		rec.addTableFile(i, tf)
 		if err := s.commit(rec); err != nil {
 			t.Fatal(err)
@@ -2455,7 +2453,7 @@ func TestDB_TableCompactionBuilder(t *testing.T) {
 	// Build grandparent.
 	v := s.version()
 	c := newCompaction(s, v, 1, append(tFiles{}, v.tables[1]...))
-	rec := &sessionRecord{}
+	rec := &sessionRecord{numLevel: s.o.GetNumLevel()}
 	b := &tableCompactionBuilder{
 		s:         s,
 		c:         c,
@@ -2479,7 +2477,7 @@ func TestDB_TableCompactionBuilder(t *testing.T) {
 	// Build level-1.
 	v = s.version()
 	c = newCompaction(s, v, 0, append(tFiles{}, v.tables[0]...))
-	rec = &sessionRecord{}
+	rec = &sessionRecord{numLevel: s.o.GetNumLevel()}
 	b = &tableCompactionBuilder{
 		s:         s,
 		c:         c,
@@ -2523,7 +2521,7 @@ func TestDB_TableCompactionBuilder(t *testing.T) {
 	// Compaction with transient error.
 	v = s.version()
 	c = newCompaction(s, v, 1, append(tFiles{}, v.tables[1]...))
-	rec = &sessionRecord{}
+	rec = &sessionRecord{numLevel: s.o.GetNumLevel()}
 	b = &tableCompactionBuilder{
 		s:         s,
 		c:         c,
@@ -2579,123 +2577,3 @@ func TestDB_TableCompactionBuilder(t *testing.T) {
 	}
 	v.release()
 }
-
-func testDB_IterTriggeredCompaction(t *testing.T, limitDiv int) {
-	const (
-		vSize = 200 * opt.KiB
-		tSize = 100 * opt.MiB
-		mIter = 100
-		n     = tSize / vSize
-	)
-
-	h := newDbHarnessWopt(t, &opt.Options{
-		Compression:       opt.NoCompression,
-		DisableBlockCache: true,
-	})
-	defer h.close()
-
-	key := func(x int) string {
-		return fmt.Sprintf("v%06d", x)
-	}
-
-	// Fill.
-	value := strings.Repeat("x", vSize)
-	for i := 0; i < n; i++ {
-		h.put(key(i), value)
-	}
-	h.compactMem()
-
-	// Delete all.
-	for i := 0; i < n; i++ {
-		h.delete(key(i))
-	}
-	h.compactMem()
-
-	var (
-		limit = n / limitDiv
-
-		startKey = key(0)
-		limitKey = key(limit)
-		maxKey   = key(n)
-		slice    = &util.Range{Limit: []byte(limitKey)}
-
-		initialSize0 = h.sizeOf(startKey, limitKey)
-		initialSize1 = h.sizeOf(limitKey, maxKey)
-	)
-
-	t.Logf("inital size %s [rest %s]", shortenb(int(initialSize0)), shortenb(int(initialSize1)))
-
-	for r := 0; true; r++ {
-		if r >= mIter {
-			t.Fatal("taking too long to compact")
-		}
-
-		// Iterates.
-		iter := h.db.NewIterator(slice, h.ro)
-		for iter.Next() {
-		}
-		if err := iter.Error(); err != nil {
-			t.Fatalf("Iter err: %v", err)
-		}
-		iter.Release()
-
-		// Wait compaction.
-		h.waitCompaction()
-
-		// Check size.
-		size0 := h.sizeOf(startKey, limitKey)
-		size1 := h.sizeOf(limitKey, maxKey)
-		t.Logf("#%03d size %s [rest %s]", r, shortenb(int(size0)), shortenb(int(size1)))
-		if size0 < initialSize0/10 {
-			break
-		}
-	}
-
-	if initialSize1 > 0 {
-		h.sizeAssert(limitKey, maxKey, initialSize1/4-opt.MiB, initialSize1+opt.MiB)
-	}
-}
-
-func TestDB_IterTriggeredCompaction(t *testing.T) {
-	testDB_IterTriggeredCompaction(t, 1)
-}
-
-func TestDB_IterTriggeredCompactionHalf(t *testing.T) {
-	testDB_IterTriggeredCompaction(t, 2)
-}
-
-func TestDB_ReadOnly(t *testing.T) {
-	h := newDbHarness(t)
-	defer h.close()
-
-	h.put("foo", "v1")
-	h.put("bar", "v2")
-	h.compactMem()
-
-	h.put("xfoo", "v1")
-	h.put("xbar", "v2")
-
-	t.Log("Trigger read-only")
-	if err := h.db.SetReadOnly(); err != nil {
-		h.close()
-		t.Fatalf("SetReadOnly error: %v", err)
-	}
-
-	h.stor.SetEmuErr(storage.TypeAll, tsOpCreate, tsOpReplace, tsOpRemove, tsOpWrite, tsOpWrite, tsOpSync)
-
-	ro := func(key, value, wantValue string) {
-		if err := h.db.Put([]byte(key), []byte(value), h.wo); err != ErrReadOnly {
-			t.Fatalf("unexpected error: %v", err)
-		}
-		h.getVal(key, wantValue)
-	}
-
-	ro("foo", "vx", "v1")
-
-	h.o.ReadOnly = true
-	h.reopenDB()
-
-	ro("foo", "vx", "v1")
-	ro("bar", "vx", "v2")
-	h.assertNumKeys(4)
-}
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_util.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_util.go
index a8a2bdf72e173d592b4eba894a2996595cb1af12..0cd4a99ec78d217d0e84d14e5f1eafece9903ade 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_util.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_util.go
@@ -7,11 +7,11 @@
 package leveldb
 
 import (
-	"github.com/syndtr/goleveldb/leveldb/errors"
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/storage"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 // Reader is the interface that wraps basic Get and NewIterator methods.
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_write.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_write.go
index 176ee893f10c6896ceb5e2cabaa2f38426c7c1c8..0f7ba29892ba34ba2badbd5d84d876a1e4ef9a74 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_write.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_write.go
@@ -9,9 +9,9 @@ package leveldb
 import (
 	"time"
 
-	"github.com/syndtr/goleveldb/leveldb/memdb"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 func (db *DB) writeJournal(b *Batch) error {
@@ -63,24 +63,24 @@ func (db *DB) rotateMem(n int) (mem *memDB, err error) {
 	return
 }
 
-func (db *DB) flush(n int) (mdb *memDB, mdbFree int, err error) {
+func (db *DB) flush(n int) (mem *memDB, nn int, err error) {
 	delayed := false
 	flush := func() (retry bool) {
 		v := db.s.version()
 		defer v.release()
-		mdb = db.getEffectiveMem()
+		mem = db.getEffectiveMem()
 		defer func() {
 			if retry {
-				mdb.decref()
-				mdb = nil
+				mem.decref()
+				mem = nil
 			}
 		}()
-		mdbFree = mdb.Free()
+		nn = mem.mdb.Free()
 		switch {
 		case v.tLen(0) >= db.s.o.GetWriteL0SlowdownTrigger() && !delayed:
 			delayed = true
 			time.Sleep(time.Millisecond)
-		case mdbFree >= n:
+		case nn >= n:
 			return false
 		case v.tLen(0) >= db.s.o.GetWriteL0PauseTrigger():
 			delayed = true
@@ -90,15 +90,15 @@ func (db *DB) flush(n int) (mdb *memDB, mdbFree int, err error) {
 			}
 		default:
 			// Allow memdb to grow if it has no entry.
-			if mdb.Len() == 0 {
-				mdbFree = n
+			if mem.mdb.Len() == 0 {
+				nn = n
 			} else {
-				mdb.decref()
-				mdb, err = db.rotateMem(n)
+				mem.decref()
+				mem, err = db.rotateMem(n)
 				if err == nil {
-					mdbFree = mdb.Free()
+					nn = mem.mdb.Free()
 				} else {
-					mdbFree = 0
+					nn = 0
 				}
 			}
 			return false
@@ -157,18 +157,18 @@ func (db *DB) Write(b *Batch, wo *opt.WriteOptions) (err error) {
 		}
 	}()
 
-	mdb, mdbFree, err := db.flush(b.size())
+	mem, memFree, err := db.flush(b.size())
 	if err != nil {
 		return
 	}
-	defer mdb.decref()
+	defer mem.decref()
 
 	// Calculate maximum size of the batch.
 	m := 1 << 20
 	if x := b.size(); x <= 128<<10 {
 		m = x + (128 << 10)
 	}
-	m = minInt(m, mdbFree)
+	m = minInt(m, memFree)
 
 	// Merge with other batch.
 drain:
@@ -197,7 +197,7 @@ drain:
 		select {
 		case db.journalC <- b:
 			// Write into memdb
-			if berr := b.memReplay(mdb.DB); berr != nil {
+			if berr := b.memReplay(mem.mdb); berr != nil {
 				panic(berr)
 			}
 		case err = <-db.compPerErrC:
@@ -211,7 +211,7 @@ drain:
 		case err = <-db.journalAckC:
 			if err != nil {
 				// Revert memdb if error detected
-				if berr := b.revertMemReplay(mdb.DB); berr != nil {
+				if berr := b.revertMemReplay(mem.mdb); berr != nil {
 					panic(berr)
 				}
 				return
@@ -225,7 +225,7 @@ drain:
 		if err != nil {
 			return
 		}
-		if berr := b.memReplay(mdb.DB); berr != nil {
+		if berr := b.memReplay(mem.mdb); berr != nil {
 			panic(berr)
 		}
 	}
@@ -233,7 +233,7 @@ drain:
 	// Set last seq number.
 	db.addSeq(uint64(b.Len()))
 
-	if b.size() >= mdbFree {
+	if b.size() >= memFree {
 		db.rotateMem(0)
 	}
 	return
@@ -249,7 +249,8 @@ func (db *DB) Put(key, value []byte, wo *opt.WriteOptions) error {
 	return db.Write(b, wo)
 }
 
-// Delete deletes the value for the given key.
+// Delete deletes the value for the given key. It returns ErrNotFound if
+// the DB does not contain the key.
 //
 // It is safe to modify the contents of the arguments after Delete returns.
 func (db *DB) Delete(key []byte, wo *opt.WriteOptions) error {
@@ -289,9 +290,9 @@ func (db *DB) CompactRange(r util.Range) error {
 	}
 
 	// Check for overlaps in memdb.
-	mdb := db.getEffectiveMem()
-	defer mdb.decref()
-	if isMemOverlaps(db.s.icmp, mdb.DB, r.Start, r.Limit) {
+	mem := db.getEffectiveMem()
+	defer mem.decref()
+	if isMemOverlaps(db.s.icmp, mem.mdb, r.Start, r.Limit) {
 		// Memdb compaction.
 		if _, err := db.rotateMem(0); err != nil {
 			<-db.writeLockC
@@ -308,31 +309,3 @@ func (db *DB) CompactRange(r util.Range) error {
 	// Table compaction.
 	return db.compSendRange(db.tcompCmdC, -1, r.Start, r.Limit)
 }
-
-// SetReadOnly makes DB read-only. It will stay read-only until reopened.
-func (db *DB) SetReadOnly() error {
-	if err := db.ok(); err != nil {
-		return err
-	}
-
-	// Lock writer.
-	select {
-	case db.writeLockC <- struct{}{}:
-		db.compWriteLocking = true
-	case err := <-db.compPerErrC:
-		return err
-	case _, _ = <-db.closeC:
-		return ErrClosed
-	}
-
-	// Set compaction read-only.
-	select {
-	case db.compErrSetC <- ErrReadOnly:
-	case perr := <-db.compPerErrC:
-		return perr
-	case _, _ = <-db.closeC:
-		return ErrClosed
-	}
-
-	return nil
-}
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors.go
index c8bd66a5aa9ab6aded8e4782358e4621c3e019e7..d5ba768413b5d23b0ddbb4a4343a232e7bdd8d52 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors.go
@@ -7,12 +7,11 @@
 package leveldb
 
 import (
-	"github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
 )
 
 var (
 	ErrNotFound         = errors.ErrNotFound
-	ErrReadOnly         = errors.New("leveldb: read-only mode")
 	ErrSnapshotReleased = errors.New("leveldb: snapshot released")
 	ErrIterReleased     = errors.New("leveldb: iterator released")
 	ErrClosed           = errors.New("leveldb: closed")
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors/errors.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors/errors.go
index 84b5d6b7b2149744c0098d7ca31b0669554be8ed..a22b4b9d5722df1336e8b14dffeb97d019140681 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors/errors.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors/errors.go
@@ -11,8 +11,8 @@ import (
 	"errors"
 	"fmt"
 
-	"github.com/syndtr/goleveldb/leveldb/storage"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 var (
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/external_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/external_test.go
index b328ece4e2caffe0b1004bed2047d3a3cb56eb4d..8ae2e50e8ea41980e5a5e2a7c3e8fb147fe67a98 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/external_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/external_test.go
@@ -10,8 +10,8 @@ import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/testutil"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil"
 )
 
 var _ = testutil.Defer(func() {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter.go
index 37c1e146bcc088a5f7dc7ba621d68f3a9c7c8509..fcad1fbf8474328d7b01dd20f33e357f40176b40 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter.go
@@ -7,7 +7,7 @@
 package leveldb
 
 import (
-	"github.com/syndtr/goleveldb/leveldb/filter"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter"
 )
 
 type iFilter struct {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom.go
index bab0e99705f59201d6920633893012938dc8a592..68c925522f4fa25ced117d2b78a4785b53dcb51c 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom.go
@@ -7,7 +7,7 @@
 package filter
 
 import (
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 func bloomHash(key []byte) uint32 {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom_test.go
index 1fb56f07136f23a4314455852a242109587fbcd6..70bfdaa54ea848419067098e7978a8f61cb9d94a 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom_test.go
@@ -8,7 +8,7 @@ package filter
 
 import (
 	"encoding/binary"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 	"testing"
 )
 
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter.go
index a23ab05f70fe8e45c0c0a8e0e4617884219a0cbf..3050fb86ae651d0dbf9de64f39df378b122825ba 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter.go
@@ -7,7 +7,7 @@
 package iterator
 
 import (
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 // BasicArray is the interface that wraps basic Len and Search method.
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter_test.go
index 1ed6d07cbb6e041e4e999112fa3ccf0ec1328c6b..9c9c27a686462b1afa5b2a2ffbacfba8292d7c14 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter_test.go
@@ -9,8 +9,8 @@ package iterator_test
 import (
 	. "github.com/onsi/ginkgo"
 
-	. "github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/testutil"
+	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil"
 )
 
 var _ = testutil.Defer(func() {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter.go
index 939adbb9332bcc2ce462303b9f95c9601fada105..71843607f34ae43d607f25712c91feee5ff7d950 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter.go
@@ -7,8 +7,8 @@
 package iterator
 
 import (
-	"github.com/syndtr/goleveldb/leveldb/errors"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 // IteratorIndexer is the interface that wraps CommonIterator and basic Get
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter_test.go
index 72a7978924ebf0aaa52eefd16ef79ac57a40f086..8d64ed8b4ad803a45f777107ebd51f695f5c692e 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter_test.go
@@ -11,9 +11,9 @@ import (
 
 	. "github.com/onsi/ginkgo"
 
-	"github.com/syndtr/goleveldb/leveldb/comparer"
-	. "github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/testutil"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer"
+	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil"
 )
 
 type keyValue struct {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter.go
index c2522860b0b8c0477fec8d54068053e22de6a1d4..f6876eea87fbfd824c77831de93b911c06084f21 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter.go
@@ -11,7 +11,7 @@ package iterator
 import (
 	"errors"
 
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 var (
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter_suite_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter_suite_test.go
index 5ef8d5bafb3f265754c74562d987ed2858bb174f..3e54f8b1977d9e29bf744acc78d28163231e77a5 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter_suite_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter_suite_test.go
@@ -3,7 +3,7 @@ package iterator_test
 import (
 	"testing"
 
-	"github.com/syndtr/goleveldb/leveldb/testutil"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil"
 )
 
 func TestIterator(t *testing.T) {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter.go
index 1a7e29df8fbd975902e5042031cd777b9a9764ce..df1daffa352f21c63c16e6c6a2429f90be74ec88 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter.go
@@ -7,9 +7,9 @@
 package iterator
 
 import (
-	"github.com/syndtr/goleveldb/leveldb/comparer"
-	"github.com/syndtr/goleveldb/leveldb/errors"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 type dir int
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter_test.go
index e523b63e4b6694cf6e0a016b06830aefdf8e8831..8ef775f31657728ff39962dfda0f6fe890d130da 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter_test.go
@@ -10,9 +10,9 @@ import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 
-	"github.com/syndtr/goleveldb/leveldb/comparer"
-	. "github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/testutil"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer"
+	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil"
 )
 
 var _ = testutil.Defer(func() {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal/journal.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal/journal.go
index 6519ec660eb7110425d545d6e7154c0a447a869f..4e4aae982c72c8148dd3253050e6c02bc7f8c636 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal/journal.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal/journal.go
@@ -82,8 +82,8 @@ import (
 	"fmt"
 	"io"
 
-	"github.com/syndtr/goleveldb/leveldb/errors"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 // These constants are part of the wire format and should not be changed.
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key.go
index 572ae8150c792dd43a3cc0477d1ff44075a51db3..eeff53321e810198c67d6920ea6c437bd22eab99 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key.go
@@ -10,7 +10,7 @@ import (
 	"encoding/binary"
 	"fmt"
 
-	"github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
 )
 
 type ErrIkeyCorrupted struct {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key_test.go
index 30eadf7847ed9b35495c2ee56f800de9fff79b84..eb9526f751f320238b90945a2dd4e8db359247cb 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key_test.go
@@ -10,7 +10,7 @@ import (
 	"bytes"
 	"testing"
 
-	"github.com/syndtr/goleveldb/leveldb/comparer"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer"
 )
 
 var defaultIComparer = &iComparer{comparer.DefaultComparer}
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/leveldb_suite_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/leveldb_suite_test.go
index fefa007a7047c7c0f5dcf69769db92d74702a087..33be15d6b59ec77c8b2ff71f8e9bf146c9b106fa 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/leveldb_suite_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/leveldb_suite_test.go
@@ -3,7 +3,7 @@ package leveldb
 import (
 	"testing"
 
-	"github.com/syndtr/goleveldb/leveldb/testutil"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil"
 )
 
 func TestLevelDB(t *testing.T) {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/bench_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/bench_test.go
index b05084caa65eb0a607b796d8819dcd0656acdf3f..51ca66ba7d1b1125136ff074d13f2b314f0d78a1 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/bench_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/bench_test.go
@@ -11,7 +11,7 @@ import (
 	"math/rand"
 	"testing"
 
-	"github.com/syndtr/goleveldb/leveldb/comparer"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer"
 )
 
 func BenchmarkPut(b *testing.B) {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb.go
index 1395bd928080f5514643e2c7d24a53d57025c702..67c7254c482f543afc91ef6ca2353cd488a39c87 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb.go
@@ -11,10 +11,10 @@ import (
 	"math/rand"
 	"sync"
 
-	"github.com/syndtr/goleveldb/leveldb/comparer"
-	"github.com/syndtr/goleveldb/leveldb/errors"
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 var (
@@ -206,7 +206,6 @@ func (p *DB) randHeight() (h int) {
 	return
 }
 
-// Must hold RW-lock if prev == true, as it use shared prevNode slice.
 func (p *DB) findGE(key []byte, prev bool) (int, bool) {
 	node := 0
 	h := p.maxHeight - 1
@@ -303,7 +302,7 @@ func (p *DB) Put(key []byte, value []byte) error {
 	node := len(p.nodeData)
 	p.nodeData = append(p.nodeData, kvOffset, len(key), len(value), h)
 	for i, n := range p.prevNode[:h] {
-		m := n + nNext + i
+		m := n + 4 + i
 		p.nodeData = append(p.nodeData, p.nodeData[m])
 		p.nodeData[m] = node
 	}
@@ -435,22 +434,20 @@ func (p *DB) Len() int {
 
 // Reset resets the DB to initial empty state. Allows reuse the buffer.
 func (p *DB) Reset() {
-	p.mu.Lock()
 	p.rnd = rand.New(rand.NewSource(0xdeadbeef))
 	p.maxHeight = 1
 	p.n = 0
 	p.kvSize = 0
 	p.kvData = p.kvData[:0]
-	p.nodeData = p.nodeData[:nNext+tMaxHeight]
+	p.nodeData = p.nodeData[:4+tMaxHeight]
 	p.nodeData[nKV] = 0
 	p.nodeData[nKey] = 0
 	p.nodeData[nVal] = 0
 	p.nodeData[nHeight] = tMaxHeight
 	for n := 0; n < tMaxHeight; n++ {
-		p.nodeData[nNext+n] = 0
+		p.nodeData[4+n] = 0
 		p.prevNode[n] = 0
 	}
-	p.mu.Unlock()
 }
 
 // New creates a new initalized in-memory key/value DB. The capacity
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_suite_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_suite_test.go
index 18c304b7f19a6c66b008e7fe2f6d879cf0a0a6ad..7be1214f39d1186edb10e096581599af7b08f5b7 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_suite_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_suite_test.go
@@ -3,7 +3,7 @@ package memdb
 import (
 	"testing"
 
-	"github.com/syndtr/goleveldb/leveldb/testutil"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil"
 )
 
 func TestMemDB(t *testing.T) {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_test.go
index 5dd6dbc7b7bbdb1d3e252c3cc1bb1995eb99ae4a..131333c16a033197f9ba0da6b7fdcd6a6bbbf39f 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_test.go
@@ -10,10 +10,10 @@ import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 
-	"github.com/syndtr/goleveldb/leveldb/comparer"
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/testutil"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 func (p *DB) TestFindLT(key []byte) (rkey, value []byte, err error) {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt/options.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt/options.go
index f9a309dac6f499fffaee3138179b1c0b46bd2912..abf0f7ea72ba55afa228e6986c92583d13a89572 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt/options.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt/options.go
@@ -8,9 +8,9 @@
 package opt
 
 import (
-	"github.com/syndtr/goleveldb/leveldb/cache"
-	"github.com/syndtr/goleveldb/leveldb/comparer"
-	"github.com/syndtr/goleveldb/leveldb/filter"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter"
 	"math"
 )
 
@@ -34,11 +34,10 @@ var (
 	DefaultCompactionTotalSize           = 10 * MiB
 	DefaultCompactionTotalSizeMultiplier = 10.0
 	DefaultCompressionType               = SnappyCompression
-	DefaultIteratorSamplingRate          = 1 * MiB
-	DefaultMaxMemCompationLevel          = 2
-	DefaultNumLevel                      = 7
 	DefaultOpenFilesCacher               = LRUCacher
 	DefaultOpenFilesCacheCapacity        = 500
+	DefaultMaxMemCompationLevel          = 2
+	DefaultNumLevel                      = 7
 	DefaultWriteBuffer                   = 4 * MiB
 	DefaultWriteL0PauseTrigger           = 12
 	DefaultWriteL0SlowdownTrigger        = 8
@@ -154,7 +153,7 @@ type Options struct {
 	BlockCacher Cacher
 
 	// BlockCacheCapacity defines the capacity of the 'sorted table' block caching.
-	// Use -1 for zero, this has same effect as specifying NoCacher to BlockCacher.
+	// Use -1 for zero, this has same effect with specifying NoCacher to BlockCacher.
 	//
 	// The default value is 8MiB.
 	BlockCacheCapacity int
@@ -250,11 +249,6 @@ type Options struct {
 	// The default value (DefaultCompression) uses snappy compression.
 	Compression Compression
 
-	// DisableBufferPool allows disable use of util.BufferPool functionality.
-	//
-	// The default value is false.
-	DisableBufferPool bool
-
 	// DisableBlockCache allows disable use of cache.Cache functionality on
 	// 'sorted table' block.
 	//
@@ -294,13 +288,6 @@ type Options struct {
 	// The default value is nil.
 	Filter filter.Filter
 
-	// IteratorSamplingRate defines approximate gap (in bytes) between read
-	// sampling of an iterator. The samples will be used to determine when
-	// compaction should be triggered.
-	//
-	// The default is 1MiB.
-	IteratorSamplingRate int
-
 	// MaxMemCompationLevel defines maximum level a newly compacted 'memdb'
 	// will be pushed into if doesn't creates overlap. This should less than
 	// NumLevel. Use -1 for level-0.
@@ -321,16 +308,11 @@ type Options struct {
 	OpenFilesCacher Cacher
 
 	// OpenFilesCacheCapacity defines the capacity of the open files caching.
-	// Use -1 for zero, this has same effect as specifying NoCacher to OpenFilesCacher.
+	// Use -1 for zero, this has same effect with specifying NoCacher to OpenFilesCacher.
 	//
 	// The default value is 500.
 	OpenFilesCacheCapacity int
 
-	// If true then opens DB in read-only mode.
-	//
-	// The default value is false.
-	ReadOnly bool
-
 	// Strict defines the DB strict level.
 	Strict Strict
 
@@ -373,9 +355,9 @@ func (o *Options) GetBlockCacher() Cacher {
 }
 
 func (o *Options) GetBlockCacheCapacity() int {
-	if o == nil || o.BlockCacheCapacity == 0 {
+	if o == nil || o.BlockCacheCapacity <= 0 {
 		return DefaultBlockCacheCapacity
-	} else if o.BlockCacheCapacity < 0 {
+	} else if o.BlockCacheCapacity == -1 {
 		return 0
 	}
 	return o.BlockCacheCapacity
@@ -482,20 +464,6 @@ func (o *Options) GetCompression() Compression {
 	return o.Compression
 }
 
-func (o *Options) GetDisableBufferPool() bool {
-	if o == nil {
-		return false
-	}
-	return o.DisableBufferPool
-}
-
-func (o *Options) GetDisableBlockCache() bool {
-	if o == nil {
-		return false
-	}
-	return o.DisableBlockCache
-}
-
 func (o *Options) GetDisableCompactionBackoff() bool {
 	if o == nil {
 		return false
@@ -524,19 +492,12 @@ func (o *Options) GetFilter() filter.Filter {
 	return o.Filter
 }
 
-func (o *Options) GetIteratorSamplingRate() int {
-	if o == nil || o.IteratorSamplingRate <= 0 {
-		return DefaultIteratorSamplingRate
-	}
-	return o.IteratorSamplingRate
-}
-
 func (o *Options) GetMaxMemCompationLevel() int {
 	level := DefaultMaxMemCompationLevel
 	if o != nil {
 		if o.MaxMemCompationLevel > 0 {
 			level = o.MaxMemCompationLevel
-		} else if o.MaxMemCompationLevel < 0 {
+		} else if o.MaxMemCompationLevel == -1 {
 			level = 0
 		}
 	}
@@ -564,21 +525,14 @@ func (o *Options) GetOpenFilesCacher() Cacher {
 }
 
 func (o *Options) GetOpenFilesCacheCapacity() int {
-	if o == nil || o.OpenFilesCacheCapacity == 0 {
+	if o == nil || o.OpenFilesCacheCapacity <= 0 {
 		return DefaultOpenFilesCacheCapacity
-	} else if o.OpenFilesCacheCapacity < 0 {
+	} else if o.OpenFilesCacheCapacity == -1 {
 		return 0
 	}
 	return o.OpenFilesCacheCapacity
 }
 
-func (o *Options) GetReadOnly() bool {
-	if o == nil {
-		return false
-	}
-	return o.ReadOnly
-}
-
 func (o *Options) GetStrict(strict Strict) bool {
 	if o == nil || o.Strict == 0 {
 		return DefaultStrict&strict != 0
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/options.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/options.go
index a3d84ef60d53d4afb73ba7bdf1f848ebbb202808..a13abb675a960c430b5acb5084812c3794922d9e 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/options.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/options.go
@@ -7,8 +7,8 @@
 package leveldb
 
 import (
-	"github.com/syndtr/goleveldb/leveldb/filter"
-	"github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
 )
 
 func dupOptions(o *opt.Options) *opt.Options {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session.go
index f0bba4602ca528493576243aaef1da156556cb58..e8c81572a542c1b0b14698e5b761beeca27e7d53 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session.go
@@ -11,12 +11,14 @@ import (
 	"io"
 	"os"
 	"sync"
+	"sync/atomic"
 
-	"github.com/syndtr/goleveldb/leveldb/errors"
-	"github.com/syndtr/goleveldb/leveldb/journal"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/storage"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 type ErrManifestCorrupted struct {
@@ -125,16 +127,11 @@ func (s *session) recover() (err error) {
 		return
 	}
 	defer reader.Close()
+	strict := s.o.GetStrict(opt.StrictManifest)
+	jr := journal.NewReader(reader, dropper{s, m}, strict, true)
 
-	var (
-		// Options.
-		numLevel = s.o.GetNumLevel()
-		strict   = s.o.GetStrict(opt.StrictManifest)
-
-		jr      = journal.NewReader(reader, dropper{s, m}, strict, true)
-		rec     = &sessionRecord{}
-		staging = s.stVersion.newStaging()
-	)
+	staging := s.stVersion.newStaging()
+	rec := &sessionRecord{numLevel: s.o.GetNumLevel()}
 	for {
 		var r io.Reader
 		r, err = jr.Next()
@@ -146,7 +143,7 @@ func (s *session) recover() (err error) {
 			return errors.SetFile(err, m)
 		}
 
-		err = rec.decode(r, numLevel)
+		err = rec.decode(r)
 		if err == nil {
 			// save compact pointers
 			for _, r := range rec.compPtrs {
@@ -209,3 +206,250 @@ func (s *session) commit(r *sessionRecord) (err error) {
 
 	return
 }
+
+// Pick a compaction based on current state; need external synchronization.
+func (s *session) pickCompaction() *compaction {
+	v := s.version()
+
+	var level int
+	var t0 tFiles
+	if v.cScore >= 1 {
+		level = v.cLevel
+		cptr := s.stCompPtrs[level]
+		tables := v.tables[level]
+		for _, t := range tables {
+			if cptr == nil || s.icmp.Compare(t.imax, cptr) > 0 {
+				t0 = append(t0, t)
+				break
+			}
+		}
+		if len(t0) == 0 {
+			t0 = append(t0, tables[0])
+		}
+	} else {
+		if p := atomic.LoadPointer(&v.cSeek); p != nil {
+			ts := (*tSet)(p)
+			level = ts.level
+			t0 = append(t0, ts.table)
+		} else {
+			v.release()
+			return nil
+		}
+	}
+
+	return newCompaction(s, v, level, t0)
+}
+
+// Create compaction from given level and range; need external synchronization.
+func (s *session) getCompactionRange(level int, umin, umax []byte) *compaction {
+	v := s.version()
+
+	t0 := v.tables[level].getOverlaps(nil, s.icmp, umin, umax, level == 0)
+	if len(t0) == 0 {
+		v.release()
+		return nil
+	}
+
+	// Avoid compacting too much in one shot in case the range is large.
+	// But we cannot do this for level-0 since level-0 files can overlap
+	// and we must not pick one file and drop another older file if the
+	// two files overlap.
+	if level > 0 {
+		limit := uint64(v.s.o.GetCompactionSourceLimit(level))
+		total := uint64(0)
+		for i, t := range t0 {
+			total += t.size
+			if total >= limit {
+				s.logf("table@compaction limiting F·%d -> F·%d", len(t0), i+1)
+				t0 = t0[:i+1]
+				break
+			}
+		}
+	}
+
+	return newCompaction(s, v, level, t0)
+}
+
+func newCompaction(s *session, v *version, level int, t0 tFiles) *compaction {
+	c := &compaction{
+		s:             s,
+		v:             v,
+		level:         level,
+		tables:        [2]tFiles{t0, nil},
+		maxGPOverlaps: uint64(s.o.GetCompactionGPOverlaps(level)),
+		tPtrs:         make([]int, s.o.GetNumLevel()),
+	}
+	c.expand()
+	c.save()
+	return c
+}
+
+// compaction represent a compaction state.
+type compaction struct {
+	s *session
+	v *version
+
+	level         int
+	tables        [2]tFiles
+	maxGPOverlaps uint64
+
+	gp                tFiles
+	gpi               int
+	seenKey           bool
+	gpOverlappedBytes uint64
+	imin, imax        iKey
+	tPtrs             []int
+	released          bool
+
+	snapGPI               int
+	snapSeenKey           bool
+	snapGPOverlappedBytes uint64
+	snapTPtrs             []int
+}
+
+func (c *compaction) save() {
+	c.snapGPI = c.gpi
+	c.snapSeenKey = c.seenKey
+	c.snapGPOverlappedBytes = c.gpOverlappedBytes
+	c.snapTPtrs = append(c.snapTPtrs[:0], c.tPtrs...)
+}
+
+func (c *compaction) restore() {
+	c.gpi = c.snapGPI
+	c.seenKey = c.snapSeenKey
+	c.gpOverlappedBytes = c.snapGPOverlappedBytes
+	c.tPtrs = append(c.tPtrs[:0], c.snapTPtrs...)
+}
+
+func (c *compaction) release() {
+	if !c.released {
+		c.released = true
+		c.v.release()
+	}
+}
+
+// Expand compacted tables; need external synchronization.
+func (c *compaction) expand() {
+	limit := uint64(c.s.o.GetCompactionExpandLimit(c.level))
+	vt0, vt1 := c.v.tables[c.level], c.v.tables[c.level+1]
+
+	t0, t1 := c.tables[0], c.tables[1]
+	imin, imax := t0.getRange(c.s.icmp)
+	// We expand t0 here just incase ukey hop across tables.
+	t0 = vt0.getOverlaps(t0, c.s.icmp, imin.ukey(), imax.ukey(), c.level == 0)
+	if len(t0) != len(c.tables[0]) {
+		imin, imax = t0.getRange(c.s.icmp)
+	}
+	t1 = vt1.getOverlaps(t1, c.s.icmp, imin.ukey(), imax.ukey(), false)
+	// Get entire range covered by compaction.
+	amin, amax := append(t0, t1...).getRange(c.s.icmp)
+
+	// See if we can grow the number of inputs in "level" without
+	// changing the number of "level+1" files we pick up.
+	if len(t1) > 0 {
+		exp0 := vt0.getOverlaps(nil, c.s.icmp, amin.ukey(), amax.ukey(), c.level == 0)
+		if len(exp0) > len(t0) && t1.size()+exp0.size() < limit {
+			xmin, xmax := exp0.getRange(c.s.icmp)
+			exp1 := vt1.getOverlaps(nil, c.s.icmp, xmin.ukey(), xmax.ukey(), false)
+			if len(exp1) == len(t1) {
+				c.s.logf("table@compaction expanding L%d+L%d (F·%d S·%s)+(F·%d S·%s) -> (F·%d S·%s)+(F·%d S·%s)",
+					c.level, c.level+1, len(t0), shortenb(int(t0.size())), len(t1), shortenb(int(t1.size())),
+					len(exp0), shortenb(int(exp0.size())), len(exp1), shortenb(int(exp1.size())))
+				imin, imax = xmin, xmax
+				t0, t1 = exp0, exp1
+				amin, amax = append(t0, t1...).getRange(c.s.icmp)
+			}
+		}
+	}
+
+	// Compute the set of grandparent files that overlap this compaction
+	// (parent == level+1; grandparent == level+2)
+	if c.level+2 < c.s.o.GetNumLevel() {
+		c.gp = c.v.tables[c.level+2].getOverlaps(c.gp, c.s.icmp, amin.ukey(), amax.ukey(), false)
+	}
+
+	c.tables[0], c.tables[1] = t0, t1
+	c.imin, c.imax = imin, imax
+}
+
+// Check whether compaction is trivial.
+func (c *compaction) trivial() bool {
+	return len(c.tables[0]) == 1 && len(c.tables[1]) == 0 && c.gp.size() <= c.maxGPOverlaps
+}
+
+func (c *compaction) baseLevelForKey(ukey []byte) bool {
+	for level, tables := range c.v.tables[c.level+2:] {
+		for c.tPtrs[level] < len(tables) {
+			t := tables[c.tPtrs[level]]
+			if c.s.icmp.uCompare(ukey, t.imax.ukey()) <= 0 {
+				// We've advanced far enough.
+				if c.s.icmp.uCompare(ukey, t.imin.ukey()) >= 0 {
+					// Key falls in this file's range, so definitely not base level.
+					return false
+				}
+				break
+			}
+			c.tPtrs[level]++
+		}
+	}
+	return true
+}
+
+func (c *compaction) shouldStopBefore(ikey iKey) bool {
+	for ; c.gpi < len(c.gp); c.gpi++ {
+		gp := c.gp[c.gpi]
+		if c.s.icmp.Compare(ikey, gp.imax) <= 0 {
+			break
+		}
+		if c.seenKey {
+			c.gpOverlappedBytes += gp.size
+		}
+	}
+	c.seenKey = true
+
+	if c.gpOverlappedBytes > c.maxGPOverlaps {
+		// Too much overlap for current output; start new output.
+		c.gpOverlappedBytes = 0
+		return true
+	}
+	return false
+}
+
+// Creates an iterator.
+func (c *compaction) newIterator() iterator.Iterator {
+	// Creates iterator slice.
+	icap := len(c.tables)
+	if c.level == 0 {
+		// Special case for level-0
+		icap = len(c.tables[0]) + 1
+	}
+	its := make([]iterator.Iterator, 0, icap)
+
+	// Options.
+	ro := &opt.ReadOptions{
+		DontFillCache: true,
+		Strict:        opt.StrictOverride,
+	}
+	strict := c.s.o.GetStrict(opt.StrictCompaction)
+	if strict {
+		ro.Strict |= opt.StrictReader
+	}
+
+	for i, tables := range c.tables {
+		if len(tables) == 0 {
+			continue
+		}
+
+		// Level-0 is not sorted and may overlaps each other.
+		if c.level+i == 0 {
+			for _, t := range tables {
+				its = append(its, c.s.tops.newIterator(t, nil, ro))
+			}
+		} else {
+			it := iterator.NewIndexedIterator(tables.newIndexIterator(c.s.tops, c.s.icmp, nil, ro), strict)
+			its = append(its, it)
+		}
+	}
+
+	return iterator.NewMergedIterator(its, c.s.icmp, strict)
+}
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_compaction.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_compaction.go
deleted file mode 100644
index 7c5a79418cc4bb2a3bf70ba7314c4804e04349f9..0000000000000000000000000000000000000000
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_compaction.go
+++ /dev/null
@@ -1,287 +0,0 @@
-// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
-// All rights reserved.
-//
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package leveldb
-
-import (
-	"sync/atomic"
-
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/memdb"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-)
-
-func (s *session) pickMemdbLevel(umin, umax []byte) int {
-	v := s.version()
-	defer v.release()
-	return v.pickMemdbLevel(umin, umax)
-}
-
-func (s *session) flushMemdb(rec *sessionRecord, mdb *memdb.DB, level int) (level_ int, err error) {
-	// Create sorted table.
-	iter := mdb.NewIterator(nil)
-	defer iter.Release()
-	t, n, err := s.tops.createFrom(iter)
-	if err != nil {
-		return level, err
-	}
-
-	// Pick level and add to record.
-	if level < 0 {
-		level = s.pickMemdbLevel(t.imin.ukey(), t.imax.ukey())
-	}
-	rec.addTableFile(level, t)
-
-	s.logf("memdb@flush created L%d@%d N·%d S·%s %q:%q", level, t.file.Num(), n, shortenb(int(t.size)), t.imin, t.imax)
-	return level, nil
-}
-
-// Pick a compaction based on current state; need external synchronization.
-func (s *session) pickCompaction() *compaction {
-	v := s.version()
-
-	var level int
-	var t0 tFiles
-	if v.cScore >= 1 {
-		level = v.cLevel
-		cptr := s.stCompPtrs[level]
-		tables := v.tables[level]
-		for _, t := range tables {
-			if cptr == nil || s.icmp.Compare(t.imax, cptr) > 0 {
-				t0 = append(t0, t)
-				break
-			}
-		}
-		if len(t0) == 0 {
-			t0 = append(t0, tables[0])
-		}
-	} else {
-		if p := atomic.LoadPointer(&v.cSeek); p != nil {
-			ts := (*tSet)(p)
-			level = ts.level
-			t0 = append(t0, ts.table)
-		} else {
-			v.release()
-			return nil
-		}
-	}
-
-	return newCompaction(s, v, level, t0)
-}
-
-// Create compaction from given level and range; need external synchronization.
-func (s *session) getCompactionRange(level int, umin, umax []byte) *compaction {
-	v := s.version()
-
-	t0 := v.tables[level].getOverlaps(nil, s.icmp, umin, umax, level == 0)
-	if len(t0) == 0 {
-		v.release()
-		return nil
-	}
-
-	// Avoid compacting too much in one shot in case the range is large.
-	// But we cannot do this for level-0 since level-0 files can overlap
-	// and we must not pick one file and drop another older file if the
-	// two files overlap.
-	if level > 0 {
-		limit := uint64(v.s.o.GetCompactionSourceLimit(level))
-		total := uint64(0)
-		for i, t := range t0 {
-			total += t.size
-			if total >= limit {
-				s.logf("table@compaction limiting F·%d -> F·%d", len(t0), i+1)
-				t0 = t0[:i+1]
-				break
-			}
-		}
-	}
-
-	return newCompaction(s, v, level, t0)
-}
-
-func newCompaction(s *session, v *version, level int, t0 tFiles) *compaction {
-	c := &compaction{
-		s:             s,
-		v:             v,
-		level:         level,
-		tables:        [2]tFiles{t0, nil},
-		maxGPOverlaps: uint64(s.o.GetCompactionGPOverlaps(level)),
-		tPtrs:         make([]int, s.o.GetNumLevel()),
-	}
-	c.expand()
-	c.save()
-	return c
-}
-
-// compaction represent a compaction state.
-type compaction struct {
-	s *session
-	v *version
-
-	level         int
-	tables        [2]tFiles
-	maxGPOverlaps uint64
-
-	gp                tFiles
-	gpi               int
-	seenKey           bool
-	gpOverlappedBytes uint64
-	imin, imax        iKey
-	tPtrs             []int
-	released          bool
-
-	snapGPI               int
-	snapSeenKey           bool
-	snapGPOverlappedBytes uint64
-	snapTPtrs             []int
-}
-
-func (c *compaction) save() {
-	c.snapGPI = c.gpi
-	c.snapSeenKey = c.seenKey
-	c.snapGPOverlappedBytes = c.gpOverlappedBytes
-	c.snapTPtrs = append(c.snapTPtrs[:0], c.tPtrs...)
-}
-
-func (c *compaction) restore() {
-	c.gpi = c.snapGPI
-	c.seenKey = c.snapSeenKey
-	c.gpOverlappedBytes = c.snapGPOverlappedBytes
-	c.tPtrs = append(c.tPtrs[:0], c.snapTPtrs...)
-}
-
-func (c *compaction) release() {
-	if !c.released {
-		c.released = true
-		c.v.release()
-	}
-}
-
-// Expand compacted tables; need external synchronization.
-func (c *compaction) expand() {
-	limit := uint64(c.s.o.GetCompactionExpandLimit(c.level))
-	vt0, vt1 := c.v.tables[c.level], c.v.tables[c.level+1]
-
-	t0, t1 := c.tables[0], c.tables[1]
-	imin, imax := t0.getRange(c.s.icmp)
-	// We expand t0 here just incase ukey hop across tables.
-	t0 = vt0.getOverlaps(t0, c.s.icmp, imin.ukey(), imax.ukey(), c.level == 0)
-	if len(t0) != len(c.tables[0]) {
-		imin, imax = t0.getRange(c.s.icmp)
-	}
-	t1 = vt1.getOverlaps(t1, c.s.icmp, imin.ukey(), imax.ukey(), false)
-	// Get entire range covered by compaction.
-	amin, amax := append(t0, t1...).getRange(c.s.icmp)
-
-	// See if we can grow the number of inputs in "level" without
-	// changing the number of "level+1" files we pick up.
-	if len(t1) > 0 {
-		exp0 := vt0.getOverlaps(nil, c.s.icmp, amin.ukey(), amax.ukey(), c.level == 0)
-		if len(exp0) > len(t0) && t1.size()+exp0.size() < limit {
-			xmin, xmax := exp0.getRange(c.s.icmp)
-			exp1 := vt1.getOverlaps(nil, c.s.icmp, xmin.ukey(), xmax.ukey(), false)
-			if len(exp1) == len(t1) {
-				c.s.logf("table@compaction expanding L%d+L%d (F·%d S·%s)+(F·%d S·%s) -> (F·%d S·%s)+(F·%d S·%s)",
-					c.level, c.level+1, len(t0), shortenb(int(t0.size())), len(t1), shortenb(int(t1.size())),
-					len(exp0), shortenb(int(exp0.size())), len(exp1), shortenb(int(exp1.size())))
-				imin, imax = xmin, xmax
-				t0, t1 = exp0, exp1
-				amin, amax = append(t0, t1...).getRange(c.s.icmp)
-			}
-		}
-	}
-
-	// Compute the set of grandparent files that overlap this compaction
-	// (parent == level+1; grandparent == level+2)
-	if c.level+2 < c.s.o.GetNumLevel() {
-		c.gp = c.v.tables[c.level+2].getOverlaps(c.gp, c.s.icmp, amin.ukey(), amax.ukey(), false)
-	}
-
-	c.tables[0], c.tables[1] = t0, t1
-	c.imin, c.imax = imin, imax
-}
-
-// Check whether compaction is trivial.
-func (c *compaction) trivial() bool {
-	return len(c.tables[0]) == 1 && len(c.tables[1]) == 0 && c.gp.size() <= c.maxGPOverlaps
-}
-
-func (c *compaction) baseLevelForKey(ukey []byte) bool {
-	for level, tables := range c.v.tables[c.level+2:] {
-		for c.tPtrs[level] < len(tables) {
-			t := tables[c.tPtrs[level]]
-			if c.s.icmp.uCompare(ukey, t.imax.ukey()) <= 0 {
-				// We've advanced far enough.
-				if c.s.icmp.uCompare(ukey, t.imin.ukey()) >= 0 {
-					// Key falls in this file's range, so definitely not base level.
-					return false
-				}
-				break
-			}
-			c.tPtrs[level]++
-		}
-	}
-	return true
-}
-
-func (c *compaction) shouldStopBefore(ikey iKey) bool {
-	for ; c.gpi < len(c.gp); c.gpi++ {
-		gp := c.gp[c.gpi]
-		if c.s.icmp.Compare(ikey, gp.imax) <= 0 {
-			break
-		}
-		if c.seenKey {
-			c.gpOverlappedBytes += gp.size
-		}
-	}
-	c.seenKey = true
-
-	if c.gpOverlappedBytes > c.maxGPOverlaps {
-		// Too much overlap for current output; start new output.
-		c.gpOverlappedBytes = 0
-		return true
-	}
-	return false
-}
-
-// Creates an iterator.
-func (c *compaction) newIterator() iterator.Iterator {
-	// Creates iterator slice.
-	icap := len(c.tables)
-	if c.level == 0 {
-		// Special case for level-0.
-		icap = len(c.tables[0]) + 1
-	}
-	its := make([]iterator.Iterator, 0, icap)
-
-	// Options.
-	ro := &opt.ReadOptions{
-		DontFillCache: true,
-		Strict:        opt.StrictOverride,
-	}
-	strict := c.s.o.GetStrict(opt.StrictCompaction)
-	if strict {
-		ro.Strict |= opt.StrictReader
-	}
-
-	for i, tables := range c.tables {
-		if len(tables) == 0 {
-			continue
-		}
-
-		// Level-0 is not sorted and may overlaps each other.
-		if c.level+i == 0 {
-			for _, t := range tables {
-				its = append(its, c.s.tops.newIterator(t, nil, ro))
-			}
-		} else {
-			it := iterator.NewIndexedIterator(tables.newIndexIterator(c.s.tops, c.s.icmp, nil, ro), strict)
-			its = append(its, it)
-		}
-	}
-
-	return iterator.NewMergedIterator(its, c.s.icmp, strict)
-}
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record.go
index 405e07bef4f1f7b881044a7e449d96b99c4bd68e..5fad6105b36eda1a7237e2007878e0110e955607 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record.go
@@ -12,7 +12,7 @@ import (
 	"io"
 	"strings"
 
-	"github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
 )
 
 type byteReader interface {
@@ -52,6 +52,8 @@ type dtRecord struct {
 }
 
 type sessionRecord struct {
+	numLevel int
+
 	hasRec         int
 	comparer       string
 	journalNum     uint64
@@ -228,7 +230,7 @@ func (p *sessionRecord) readBytes(field string, r byteReader) []byte {
 	return x
 }
 
-func (p *sessionRecord) readLevel(field string, r io.ByteReader, numLevel int) int {
+func (p *sessionRecord) readLevel(field string, r io.ByteReader) int {
 	if p.err != nil {
 		return 0
 	}
@@ -236,14 +238,14 @@ func (p *sessionRecord) readLevel(field string, r io.ByteReader, numLevel int) i
 	if p.err != nil {
 		return 0
 	}
-	if x >= uint64(numLevel) {
+	if x >= uint64(p.numLevel) {
 		p.err = errors.NewErrCorrupted(nil, &ErrManifestCorrupted{field, "invalid level number"})
 		return 0
 	}
 	return int(x)
 }
 
-func (p *sessionRecord) decode(r io.Reader, numLevel int) error {
+func (p *sessionRecord) decode(r io.Reader) error {
 	br, ok := r.(byteReader)
 	if !ok {
 		br = bufio.NewReader(r)
@@ -284,13 +286,13 @@ func (p *sessionRecord) decode(r io.Reader, numLevel int) error {
 				p.setSeqNum(x)
 			}
 		case recCompPtr:
-			level := p.readLevel("comp-ptr.level", br, numLevel)
+			level := p.readLevel("comp-ptr.level", br)
 			ikey := p.readBytes("comp-ptr.ikey", br)
 			if p.err == nil {
 				p.addCompPtr(level, iKey(ikey))
 			}
 		case recAddTable:
-			level := p.readLevel("add-table.level", br, numLevel)
+			level := p.readLevel("add-table.level", br)
 			num := p.readUvarint("add-table.num", br)
 			size := p.readUvarint("add-table.size", br)
 			imin := p.readBytes("add-table.imin", br)
@@ -299,7 +301,7 @@ func (p *sessionRecord) decode(r io.Reader, numLevel int) error {
 				p.addTable(level, num, size, imin, imax)
 			}
 		case recDelTable:
-			level := p.readLevel("del-table.level", br, numLevel)
+			level := p.readLevel("del-table.level", br)
 			num := p.readUvarint("del-table.num", br)
 			if p.err == nil {
 				p.delTable(level, num)
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record_test.go
index 33c14875618b53cd0408e77f4819c47adf9a1994..ba3864b20828dd0452324765ddba8c780b91c73d 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record_test.go
@@ -10,7 +10,7 @@ import (
 	"bytes"
 	"testing"
 
-	"github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
 )
 
 func decodeEncode(v *sessionRecord) (res bool, err error) {
@@ -19,8 +19,8 @@ func decodeEncode(v *sessionRecord) (res bool, err error) {
 	if err != nil {
 		return
 	}
-	v2 := &sessionRecord{}
-	err = v.decode(b, opt.DefaultNumLevel)
+	v2 := &sessionRecord{numLevel: opt.DefaultNumLevel}
+	err = v.decode(b)
 	if err != nil {
 		return
 	}
@@ -34,7 +34,7 @@ func decodeEncode(v *sessionRecord) (res bool, err error) {
 
 func TestSessionRecord_EncodeDecode(t *testing.T) {
 	big := uint64(1) << 50
-	v := &sessionRecord{}
+	v := &sessionRecord{numLevel: opt.DefaultNumLevel}
 	i := uint64(0)
 	test := func() {
 		res, err := decodeEncode(v)
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_util.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_util.go
index 399a788bad2de7b07974e09f14e400f99e484d06..23f3d80fab2b57e0fb7ac3ac3d42b3743e32d478 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_util.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_util.go
@@ -10,8 +10,8 @@ import (
 	"fmt"
 	"sync/atomic"
 
-	"github.com/syndtr/goleveldb/leveldb/journal"
-	"github.com/syndtr/goleveldb/leveldb/storage"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage"
 )
 
 // Logging.
@@ -182,7 +182,7 @@ func (s *session) newManifest(rec *sessionRecord, v *version) (err error) {
 		defer v.release()
 	}
 	if rec == nil {
-		rec = &sessionRecord{}
+		rec = &sessionRecord{numLevel: s.o.GetNumLevel()}
 	}
 	s.fillRecord(rec, true)
 	v.fillRecord(rec)
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/file_storage.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/file_storage.go
index 46cc9d07012e91141cae7c08903f8421c394c412..9329faf7a7676b75572f4ef612e6d7e320272858 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/file_storage.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/file_storage.go
@@ -18,7 +18,7 @@ import (
 	"sync"
 	"time"
 
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 var errFileOpen = errors.New("leveldb/storage: file still open")
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/mem_storage.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/mem_storage.go
index fc1c8165df1a0d05d432e47889fe8ccb0b943c7f..8952193112728a24485df4d5cfca73ebae92ca6d 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/mem_storage.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/mem_storage.go
@@ -11,7 +11,7 @@ import (
 	"os"
 	"sync"
 
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 const typeShift = 3
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/storage.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/storage.go
index 85dd70b06f9f6c8955d60b382d4a8652b1ba1292..bdda8c447e241d497b6dfc41fa6812b26ae157e2 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/storage.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/storage.go
@@ -12,7 +12,7 @@ import (
 	"fmt"
 	"io"
 
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 type FileType uint32
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage_test.go
index 08be0bab3da3b28e9c889c50ef813f6c0603d29b..768dfc88ec200c74acadd8ef02acc6f399a02b42 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage_test.go
@@ -17,8 +17,8 @@ import (
 	"sync"
 	"testing"
 
-	"github.com/syndtr/goleveldb/leveldb/storage"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 const typeShift = 4
@@ -42,8 +42,6 @@ type tsOp uint
 const (
 	tsOpOpen tsOp = iota
 	tsOpCreate
-	tsOpReplace
-	tsOpRemove
 	tsOpRead
 	tsOpReadAt
 	tsOpWrite
@@ -243,10 +241,6 @@ func (tf tsFile) Replace(newfile storage.File) (err error) {
 	if err != nil {
 		return
 	}
-	if tf.shouldErr(tsOpReplace) {
-		err = errors.New("leveldb.testStorage: emulated create error")
-		return
-	}
 	err = tf.File.Replace(newfile.(tsFile).File)
 	if err != nil {
 		ts.t.Errorf("E: cannot replace file, num=%d type=%v: %v", tf.Num(), tf.Type(), err)
@@ -264,10 +258,6 @@ func (tf tsFile) Remove() (err error) {
 	if err != nil {
 		return
 	}
-	if tf.shouldErr(tsOpRemove) {
-		err = errors.New("leveldb.testStorage: emulated create error")
-		return
-	}
 	err = tf.File.Remove()
 	if err != nil {
 		ts.t.Errorf("E: cannot remove file, num=%d type=%v: %v", tf.Num(), tf.Type(), err)
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table.go
index db386f3b5465b68faff4b7f709482bdfdb830b6f..357e51845d1618453e65117b1f80f09726ee0a23 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table.go
@@ -11,12 +11,12 @@ import (
 	"sort"
 	"sync/atomic"
 
-	"github.com/syndtr/goleveldb/leveldb/cache"
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/storage"
-	"github.com/syndtr/goleveldb/leveldb/table"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 // tFile holds basic information about a table.
@@ -441,26 +441,22 @@ func newTableOps(s *session) *tOps {
 	var (
 		cacher cache.Cacher
 		bcache *cache.Cache
-		bpool  *util.BufferPool
 	)
 	if s.o.GetOpenFilesCacheCapacity() > 0 {
 		cacher = cache.NewLRU(s.o.GetOpenFilesCacheCapacity())
 	}
-	if !s.o.GetDisableBlockCache() {
+	if !s.o.DisableBlockCache {
 		var bcacher cache.Cacher
 		if s.o.GetBlockCacheCapacity() > 0 {
 			bcacher = cache.NewLRU(s.o.GetBlockCacheCapacity())
 		}
 		bcache = cache.NewCache(bcacher)
 	}
-	if !s.o.GetDisableBufferPool() {
-		bpool = util.NewBufferPool(s.o.GetBlockSize() + 5)
-	}
 	return &tOps{
 		s:      s,
 		cache:  cache.NewCache(cacher),
 		bcache: bcache,
-		bpool:  bpool,
+		bpool:  util.NewBufferPool(s.o.GetBlockSize() + 5),
 	}
 }
 
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/block_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/block_test.go
index 00e6f9eea0dd97ae892eab1934d4f096f73a1b65..a8580cf324784e3d1122680de1e26477db26a4f2 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/block_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/block_test.go
@@ -13,10 +13,10 @@ import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 
-	"github.com/syndtr/goleveldb/leveldb/comparer"
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/testutil"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 type blockTesting struct {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/reader.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/reader.go
index 691ffc2aa8118f7e5c864853d34580ddbbf9b9aa..1bfc3978768c2126690c6aa9f707532539e1a8f0 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/reader.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/reader.go
@@ -14,16 +14,16 @@ import (
 	"strings"
 	"sync"
 
-	"github.comgoogle/go-snappy/snappy"
-
-	"github.com/syndtr/goleveldb/leveldb/cache"
-	"github.com/syndtr/goleveldb/leveldb/comparer"
-	"github.com/syndtr/goleveldb/leveldb/errors"
-	"github.com/syndtr/goleveldb/leveldb/filter"
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/storage"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/gosnappy/snappy"
+
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 var (
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_suite_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_suite_test.go
index 6465da6e3707c48ab28ebc176c33b80b66c0c8b3..d35a13051497c79133aa293560897c9b63276e67 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_suite_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_suite_test.go
@@ -3,7 +3,7 @@ package table
 import (
 	"testing"
 
-	"github.com/syndtr/goleveldb/leveldb/testutil"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil"
 )
 
 func TestTable(t *testing.T) {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_test.go
index 4b59b31f52b42f12e8e098ea3a20d3b10d6b334e..5429c465b6938b75d1f7e39662b66f1d4a507797 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_test.go
@@ -12,10 +12,10 @@ import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/testutil"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 type tableWrapper struct {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/writer.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/writer.go
index 42285b5f29e98be0f40528bae2625e26d8fe1648..51f9fc7173978511abb9ab83a1e91bfd5b60197e 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/writer.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/writer.go
@@ -12,12 +12,12 @@ import (
 	"fmt"
 	"io"
 
-	"github.comgoogle/go-snappy/snappy"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/gosnappy/snappy"
 
-	"github.com/syndtr/goleveldb/leveldb/comparer"
-	"github.com/syndtr/goleveldb/leveldb/filter"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 func sharedPrefixLen(a, b []byte) int {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/db.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/db.go
index ec3f177a12febb5259fb9d88a5b8b58e7d37dca7..a0995a4b7b7c83efb955bb97f46b319b35b69d3b 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/db.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/db.go
@@ -12,9 +12,9 @@ import (
 
 	. "github.com/onsi/gomega"
 
-	"github.com/syndtr/goleveldb/leveldb/errors"
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 type DB interface{}
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/iter.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/iter.go
index df6d9db6a335bf388ba844ee0af918707e9caf34..5e3cbb160d543800a09960a01c63b1c60e6ed4fd 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/iter.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/iter.go
@@ -12,7 +12,7 @@ import (
 
 	. "github.com/onsi/gomega"
 
-	"github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
 )
 
 type IterAct int
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kv.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kv.go
index 471d5708c37d826d7c5e75139f209c816b13f7c5..83a01a4719b84ab5da4aa0e23258fa9e057089bb 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kv.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kv.go
@@ -12,7 +12,7 @@ import (
 	"sort"
 	"strings"
 
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 type KeyValueEntry struct {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kvtest.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kvtest.go
index a0b58f0e7252b632651a6480f32fc47e973cca01..78d981c7dcd38fc198fa4c70fd3b46a9c134d83a 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kvtest.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kvtest.go
@@ -13,8 +13,8 @@ import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 
-	"github.com/syndtr/goleveldb/leveldb/errors"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 func KeyValueTesting(rnd *rand.Rand, kv KeyValue, p DB, setup func(KeyValue) DB, teardown func(DB)) {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/storage.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/storage.go
index 59c496d54c62e90afe4cd057d81f412b10edef6b..d515438b175e1ae785a6ae3ee500808dc7c62cdb 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/storage.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/storage.go
@@ -18,8 +18,8 @@ import (
 
 	. "github.com/onsi/gomega"
 
-	"github.com/syndtr/goleveldb/leveldb/storage"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 var (
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/util.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/util.go
index 97c5294b1b5dd0c16162cd49fb55ad27274cb89a..7ac261ddba2bd4c5056f737f2af07dd0cdca1f61 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/util.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/util.go
@@ -15,7 +15,7 @@ import (
 
 	"github.com/onsi/ginkgo/config"
 
-	"github.com/syndtr/goleveldb/leveldb/comparer"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer"
 )
 
 var (
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil_test.go
index 25bf2b29f99310e6af6ab1532ccfc9cdf1621e87..868f7ffab3e0df8ba7c583e05b1960529148e8ad 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil_test.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil_test.go
@@ -9,10 +9,10 @@ package leveldb
 import (
 	. "github.com/onsi/gomega"
 
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/testutil"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 type testingDB struct {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util.go
index 1a5bf71a3254044964beba9aee5362e5da1ed763..7de9260d0d38eb3b21e5e2c5d2841695bda8a4ad 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util.go
@@ -10,7 +10,7 @@ import (
 	"fmt"
 	"sort"
 
-	"github.com/syndtr/goleveldb/leveldb/storage"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage"
 )
 
 func shorten(str string) string {
diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/version.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/version.go
index 011d982da82c13eaf18b9b2abb9c106f2c4a012e..e8268286f1938ed25cfcb5371cd7708a59f6b273 100644
--- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/version.go
+++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/version.go
@@ -10,9 +10,9 @@ import (
 	"sync/atomic"
 	"unsafe"
 
-	"github.com/syndtr/goleveldb/leveldb/iterator"
-	"github.com/syndtr/goleveldb/leveldb/opt"
-	"github.com/syndtr/goleveldb/leveldb/util"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util"
 )
 
 type tSet struct {
@@ -136,8 +136,9 @@ func (v *version) get(ikey iKey, ro *opt.ReadOptions, noValue bool) (value []byt
 		if !tseek {
 			if tset == nil {
 				tset = &tSet{level, t}
-			} else {
+			} else if tset.table.consumeSeek() <= 0 {
 				tseek = true
+				tcomp = atomic.CompareAndSwapPointer(&v.cSeek, nil, unsafe.Pointer(tset))
 			}
 		}
 
@@ -202,28 +203,6 @@ func (v *version) get(ikey iKey, ro *opt.ReadOptions, noValue bool) (value []byt
 		return true
 	})
 
-	if tseek && tset.table.consumeSeek() <= 0 {
-		tcomp = atomic.CompareAndSwapPointer(&v.cSeek, nil, unsafe.Pointer(tset))
-	}
-
-	return
-}
-
-func (v *version) sampleSeek(ikey iKey) (tcomp bool) {
-	var tset *tSet
-
-	v.walkOverlapping(ikey, func(level int, t *tFile) bool {
-		if tset == nil {
-			tset = &tSet{level, t}
-			return true
-		} else {
-			if tset.table.consumeSeek() <= 0 {
-				tcomp = atomic.CompareAndSwapPointer(&v.cSeek, nil, unsafe.Pointer(tset))
-			}
-			return false
-		}
-	}, nil)
-
 	return
 }
 
@@ -300,7 +279,7 @@ func (v *version) offsetOf(ikey iKey) (n uint64, err error) {
 	return
 }
 
-func (v *version) pickMemdbLevel(umin, umax []byte) (level int) {
+func (v *version) pickLevel(umin, umax []byte) (level int) {
 	if !v.tables[0].overlaps(v.s.icmp, umin, umax, true) {
 		var overlaps tFiles
 		maxLevel := v.s.o.GetMaxMemCompationLevel()
diff --git a/Godeps/_workspace/src/github.com/tendermint/ed25519/ed25519.go b/Godeps/_workspace/src/github.com/tendermint/ed25519/ed25519.go
index 48ac4a423ec0452caf979154573e15485834a25a..6c7e5cbc4109740ed3d2ecb517d02d63e89b84cd 100644
--- a/Godeps/_workspace/src/github.com/tendermint/ed25519/ed25519.go
+++ b/Godeps/_workspace/src/github.com/tendermint/ed25519/ed25519.go
@@ -14,7 +14,7 @@ import (
 	"crypto/subtle"
 	"io"
 
-	"github.com/agl/ed25519/edwards25519"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/agl/ed25519/edwards25519"
 )
 
 const (
diff --git a/Godeps/_workspace/src/github.com/tendermint/ed25519/extra25519/extra25519.go b/Godeps/_workspace/src/github.com/tendermint/ed25519/extra25519/extra25519.go
index 571218f5516f5f679364e57cb3db1fcbf3fb3225..bbda91686372ac2982d68a41dac8b7fb446eb67a 100644
--- a/Godeps/_workspace/src/github.com/tendermint/ed25519/extra25519/extra25519.go
+++ b/Godeps/_workspace/src/github.com/tendermint/ed25519/extra25519/extra25519.go
@@ -7,7 +7,7 @@ package extra25519
 import (
 	"crypto/sha512"
 
-	"github.com/agl/ed25519/edwards25519"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/agl/ed25519/edwards25519"
 )
 
 // PrivateKeyToCurve25519 converts an ed25519 private key into a corresponding
diff --git a/Godeps/_workspace/src/github.com/tendermint/log15/handler.go b/Godeps/_workspace/src/github.com/tendermint/log15/handler.go
index 4c771b4ba65c25eddec2741d29863af9cb17222b..5dc7299843978865fec11d9103ea519e1ee5af89 100644
--- a/Godeps/_workspace/src/github.com/tendermint/log15/handler.go
+++ b/Godeps/_workspace/src/github.com/tendermint/log15/handler.go
@@ -11,7 +11,7 @@ import (
 	"sync/atomic"
 	"unsafe"
 
-	"github.com/inconshreveable/log15/stack"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/inconshreveable/log15/stack"
 )
 
 // A Logger prints its log records by writing to a Handler.
diff --git a/Godeps/_workspace/src/github.com/tendermint/log15/logger.go b/Godeps/_workspace/src/github.com/tendermint/log15/logger.go
index 325448d218b1d476af1efca14ec11845ff8a6dfc..8ddf3ffd05e32b43d93bffa8748119de9665a512 100644
--- a/Godeps/_workspace/src/github.com/tendermint/log15/logger.go
+++ b/Godeps/_workspace/src/github.com/tendermint/log15/logger.go
@@ -30,7 +30,7 @@ func (l Lvl) String() string {
 	case LvlInfo:
 		return "info"
 	case LvlNotice:
-		return "notice"
+		return "note"
 	case LvlWarn:
 		return "warn"
 	case LvlError:
@@ -50,7 +50,7 @@ func LvlFromString(lvlString string) (Lvl, error) {
 		return LvlDebug, nil
 	case "info":
 		return LvlInfo, nil
-	case "notice", "note":
+	case "note", "notice":
 		return LvlNotice, nil
 	case "warn":
 		return LvlWarn, nil
diff --git a/Godeps/_workspace/src/github.com/tendermint/log15/root.go b/Godeps/_workspace/src/github.com/tendermint/log15/root.go
index 98103173063315850752f8c4752b70d09799325b..7034447afaeab3524567b74eb98c7bd3c65f7d7e 100644
--- a/Godeps/_workspace/src/github.com/tendermint/log15/root.go
+++ b/Godeps/_workspace/src/github.com/tendermint/log15/root.go
@@ -3,8 +3,8 @@ package log15
 import (
 	"os"
 
-	"github.com/inconshreveable/log15/term"
-	"github.com/mattn/go-colorable"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/inconshreveable/log15/term"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/mattn/go-colorable"
 )
 
 var (
diff --git a/Godeps/_workspace/src/github.com/tendermint/log15/stack/stack_test.go b/Godeps/_workspace/src/github.com/tendermint/log15/stack/stack_test.go
index 52371b1e45ab1ac08469a56607133e18cc6716d5..64cd7d08075a7c43b884ce6076545c30a0564990 100644
--- a/Godeps/_workspace/src/github.com/tendermint/log15/stack/stack_test.go
+++ b/Godeps/_workspace/src/github.com/tendermint/log15/stack/stack_test.go
@@ -9,7 +9,7 @@ import (
 	"runtime"
 	"testing"
 
-	"github.com/inconshreveable/log15/stack"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/inconshreveable/log15/stack"
 )
 
 type testType struct{}
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/alert/alert.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/alert/alert.go
index c47633091d786c9c51ed40861ce8b890de856de0..497be012cd64708407554ad46cf04fbf7209ea46 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/alert/alert.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/alert/alert.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"time"
 
-	"github.com/sfreiberg/gotwilio"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/sfreiberg/gotwilio"
 )
 
 var lastAlertUnix int64 = 0
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/pool.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/pool.go
index 66be4dc820cd983b702ddd6349473fd8a5192c76..b781dd3dc0973a15ad850157c770506a6f9ee58b 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/pool.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/pool.go
@@ -12,8 +12,8 @@ import (
 
 const (
 	requestIntervalMS         = 250
-	maxTotalRequests          = 300
-	maxPendingRequests        = maxTotalRequests
+	maxTotalRequesters        = 300
+	maxPendingRequests        = maxTotalRequesters
 	maxPendingRequestsPerPeer = 75
 	peerTimeoutSeconds        = 15
 	minRecvRate               = 10240 // 10Kb/s
@@ -36,8 +36,8 @@ type BlockPool struct {
 
 	// block requests
 	mtx        sync.Mutex
-	requests   map[int]*bpRequester
-	height     int   // the lowest key in requests.
+	requesters map[int]*bpRequester
+	height     int   // the lowest key in requesters.
 	numPending int32 // number of requests pending assignment or block response
 
 	// peers
@@ -52,7 +52,7 @@ func NewBlockPool(start int, requestsCh chan<- BlockRequest, timeoutsCh chan<- s
 	bp := &BlockPool{
 		peers: make(map[string]*bpPeer),
 
-		requests:   make(map[int]*bpRequester),
+		requesters: make(map[int]*bpRequester),
 		height:     start,
 		numPending: 0,
 
@@ -65,7 +65,7 @@ func NewBlockPool(start int, requestsCh chan<- BlockRequest, timeoutsCh chan<- s
 
 func (pool *BlockPool) OnStart() error {
 	pool.QuitService.OnStart()
-	go pool.makeRequestsRoutine()
+	go pool.makeRequestersRoutine()
 	pool.startTime = time.Now()
 	return nil
 }
@@ -74,8 +74,8 @@ func (pool *BlockPool) OnStop() {
 	pool.QuitService.OnStop()
 }
 
-// Run spawns requests as needed.
-func (pool *BlockPool) makeRequestsRoutine() {
+// Run spawns requesters as needed.
+func (pool *BlockPool) makeRequestersRoutine() {
 	for {
 		if !pool.IsRunning() {
 			break
@@ -86,14 +86,14 @@ func (pool *BlockPool) makeRequestsRoutine() {
 			time.Sleep(requestIntervalMS * time.Millisecond)
 			// check for timed out peers
 			pool.removeTimedoutPeers()
-		} else if len(pool.requests) >= maxTotalRequests {
+		} else if len(pool.requesters) >= maxTotalRequesters {
 			// sleep for a bit.
 			time.Sleep(requestIntervalMS * time.Millisecond)
 			// check for timed out peers
 			pool.removeTimedoutPeers()
 		} else {
 			// request for more blocks.
-			pool.makeNextRequest()
+			pool.makeNextRequester()
 		}
 	}
 }
@@ -147,10 +147,10 @@ func (pool *BlockPool) PeekTwoBlocks() (first *types.Block, second *types.Block)
 	pool.mtx.Lock() // Lock
 	defer pool.mtx.Unlock()
 
-	if r := pool.requests[pool.height]; r != nil {
+	if r := pool.requesters[pool.height]; r != nil {
 		first = r.getBlock()
 	}
-	if r := pool.requests[pool.height+1]; r != nil {
+	if r := pool.requesters[pool.height+1]; r != nil {
 		second = r.getBlock()
 	}
 	return
@@ -162,14 +162,18 @@ func (pool *BlockPool) PopRequest() {
 	pool.mtx.Lock() // Lock
 	defer pool.mtx.Unlock()
 
-	/*  The block can disappear at any time, due to removePeer().
-	if r := pool.requests[pool.height]; r == nil || r.block == nil {
-		PanicSanity("PopRequest() requires a valid block")
+	if r := pool.requesters[pool.height]; r != nil {
+		/*  The block can disappear at any time, due to removePeer().
+		if r := pool.requesters[pool.height]; r == nil || r.block == nil {
+			PanicSanity("PopRequest() requires a valid block")
+		}
+		*/
+		r.Stop()
+		delete(pool.requesters, pool.height)
+		pool.height++
+	} else {
+		PanicSanity(Fmt("Expected requester to pop, got nothing at height %v", pool.height))
 	}
-	*/
-
-	delete(pool.requests, pool.height)
-	pool.height++
 }
 
 // Invalidates the block at pool.height,
@@ -178,11 +182,11 @@ func (pool *BlockPool) RedoRequest(height int) {
 	pool.mtx.Lock() // Lock
 	defer pool.mtx.Unlock()
 
-	request := pool.requests[height]
+	request := pool.requesters[height]
 	if request.block == nil {
 		PanicSanity("Expected block to be non-nil")
 	}
-	// RemovePeer will redo all requests associated with this peer.
+	// RemovePeer will redo all requesters associated with this peer.
 	// TODO: record this malfeasance
 	pool.RemovePeer(request.peerID) // Lock on peersMtx.
 }
@@ -192,12 +196,12 @@ func (pool *BlockPool) AddBlock(peerID string, block *types.Block, blockSize int
 	pool.mtx.Lock() // Lock
 	defer pool.mtx.Unlock()
 
-	request := pool.requests[block.Height]
-	if request == nil {
+	requester := pool.requesters[block.Height]
+	if requester == nil {
 		return
 	}
 
-	if request.setBlock(block, peerID) {
+	if requester.setBlock(block, peerID) {
 		pool.numPending--
 		peer := pool.getPeer(peerID)
 		peer.decrPending(blockSize)
@@ -228,10 +232,10 @@ func (pool *BlockPool) RemovePeer(peerID string) {
 }
 
 func (pool *BlockPool) removePeer(peerID string) {
-	for _, request := range pool.requests {
-		if request.getPeerID() == peerID {
+	for _, requester := range pool.requesters {
+		if requester.getPeerID() == peerID {
 			pool.numPending++
-			go request.redo() // pick another peer and ...
+			go requester.redo() // pick another peer and ...
 		}
 	}
 	delete(pool.peers, peerID)
@@ -269,14 +273,14 @@ func (pool *BlockPool) pickIncrAvailablePeer(minHeight int) *bpPeer {
 	return nil
 }
 
-func (pool *BlockPool) makeNextRequest() {
+func (pool *BlockPool) makeNextRequester() {
 	pool.mtx.Lock() // Lock
 	defer pool.mtx.Unlock()
 
-	nextHeight := pool.height + len(pool.requests)
+	nextHeight := pool.height + len(pool.requesters)
 	request := newBPRequester(pool, nextHeight)
 
-	pool.requests[nextHeight] = request
+	pool.requesters[nextHeight] = request
 	pool.numPending++
 
 	request.Start()
@@ -301,12 +305,12 @@ func (pool *BlockPool) debug() string {
 	defer pool.mtx.Unlock()
 
 	str := ""
-	for h := pool.height; h < pool.height+len(pool.requests); h++ {
-		if pool.requests[h] == nil {
+	for h := pool.height; h < pool.height+len(pool.requesters); h++ {
+		if pool.requesters[h] == nil {
 			str += Fmt("H(%v):X ", h)
 		} else {
 			str += Fmt("H(%v):", h)
-			str += Fmt("B?(%v) ", pool.requests[h].block != nil)
+			str += Fmt("B?(%v) ", pool.requesters[h].block != nil)
 		}
 	}
 	return str
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/reactor.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/reactor.go
index bd50d5a679588550e537f29b1f174fe6089831db..1cab4ce61093eefd3fecc1631d45fe7f255071e3 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/reactor.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/reactor.go
@@ -192,7 +192,7 @@ FOR_LOOP:
 		case _ = <-switchToConsensusTicker.C:
 			height, numPending := bcR.pool.GetStatus()
 			outbound, inbound, _ := bcR.Switch.NumPeers()
-			log.Info("Consensus ticker", "numPending", numPending, "total", len(bcR.pool.requests),
+			log.Info("Consensus ticker", "numPending", numPending, "total", len(bcR.pool.requesters),
 				"outbound", outbound, "inbound", inbound)
 			if bcR.pool.IsCaughtUp() {
 				log.Notice("Time to switch to consensus reactor!", "height", height)
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/common/io.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/common/io.go
index 0c33b07569c3977bab84e037a7c567a759ebd923..378c19fc6a7361e9ba49877f2e2df471db19a40c 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/common/io.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/common/io.go
@@ -1,6 +1,8 @@
 package common
 
 import (
+	"bytes"
+	"errors"
 	"io"
 )
 
@@ -22,3 +24,52 @@ func (pr *PrefixedReader) Read(p []byte) (n int, err error) {
 		return pr.reader.Read(p)
 	}
 }
+
+// NOTE: Not goroutine safe
+type BufferCloser struct {
+	bytes.Buffer
+	Closed bool
+}
+
+func NewBufferCloser(buf []byte) *BufferCloser {
+	return &BufferCloser{
+		*bytes.NewBuffer(buf),
+		false,
+	}
+}
+
+func (bc *BufferCloser) Close() error {
+	if bc.Closed {
+		return errors.New("BufferCloser already closed")
+	}
+	bc.Closed = true
+	return nil
+}
+
+func (bc *BufferCloser) Write(p []byte) (n int, err error) {
+	if bc.Closed {
+		return 0, errors.New("Cannot write to closed BufferCloser")
+	}
+	return bc.Buffer.Write(p)
+}
+
+func (bc *BufferCloser) WriteByte(c byte) error {
+	if bc.Closed {
+		return errors.New("Cannot write to closed BufferCloser")
+	}
+	return bc.Buffer.WriteByte(c)
+}
+
+func (bc *BufferCloser) WriteRune(r rune) (n int, err error) {
+	if bc.Closed {
+		return 0, errors.New("Cannot write to closed BufferCloser")
+	}
+	return bc.Buffer.WriteRune(r)
+}
+
+func (bc *BufferCloser) WriteString(s string) (n int, err error) {
+	if bc.Closed {
+		return 0, errors.New("Cannot write to closed BufferCloser")
+	}
+	return bc.Buffer.WriteString(s)
+}
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint/config.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint/config.go
index 1a6b0225d78e20ab574f839f8acfc207723eec96..503af24fc26a0d1a89de5dc32f75d04971f0147e 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint/config.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint/config.go
@@ -1,7 +1,7 @@
 package tendermint
 
 import (
-	"github.com/naoina/toml"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/toml"
 	"os"
 	"path"
 	"strings"
@@ -25,7 +25,6 @@ func initTMRoot(rootDir string) {
 	EnsureDir(rootDir)
 
 	configFilePath := path.Join(rootDir, "config.toml")
-	genesisFilePath := path.Join(rootDir, "genesis.json")
 
 	// Write default config file if missing.
 	if !FileExists(configFilePath) {
@@ -33,9 +32,6 @@ func initTMRoot(rootDir string) {
 		// moniker := cfg.Prompt("Type hostname: ", "anonymous")
 		MustWriteFile(configFilePath, []byte(defaultConfig("anonymous")))
 	}
-	if !FileExists(genesisFilePath) {
-		MustWriteFile(genesisFilePath, []byte(defaultGenesis))
-	}
 }
 
 func GetConfig(rootDir string) cfg.Config {
@@ -54,7 +50,10 @@ func GetConfig(rootDir string) cfg.Config {
 	if mapConfig.IsSet("chain_id") {
 		Exit("Cannot set 'chain_id' via config.toml")
 	}
-	mapConfig.SetDefault("chain_id", "tendermint_testnet_10")
+	if mapConfig.IsSet("revision_file") {
+		Exit("Cannot set 'revision_file' via config.toml. It must match what's in the Makefile")
+	}
+	mapConfig.SetDefault("chain_id", "tendermint_testnet_11.c") // TODO ALSO UPDATE GENESIS BELOW!!!
 	mapConfig.SetDefault("genesis_file", rootDir+"/genesis.json")
 	mapConfig.SetDefault("moniker", "anonymous")
 	mapConfig.SetDefault("node_laddr", "0.0.0.0:46656")
@@ -65,9 +64,12 @@ func GetConfig(rootDir string) cfg.Config {
 	mapConfig.SetDefault("priv_validator_file", rootDir+"/priv_validator.json")
 	mapConfig.SetDefault("db_backend", "leveldb")
 	mapConfig.SetDefault("db_dir", rootDir+"/data")
+	mapConfig.SetDefault("vm_log", true)
 	mapConfig.SetDefault("log_level", "info")
 	mapConfig.SetDefault("rpc_laddr", "0.0.0.0:46657")
-	mapConfig.SetDefault("revisions_file", rootDir+"/revisions")
+	mapConfig.SetDefault("prof_laddr", "")
+	mapConfig.SetDefault("revision_file", rootDir+"/revision")
+	mapConfig.SetDefault("local_routing", false)
 	return mapConfig
 }
 
@@ -82,7 +84,7 @@ var defaultConfigTmpl = `# This is a TOML config file.
 
 moniker = "__MONIKER__"
 node_laddr = "0.0.0.0:46656"
-seeds = "goldenalchemist.chaintest.net:46656"
+seeds = ""
 fast_sync = true
 db_backend = "leveldb"
 log_level = "notice"
@@ -93,63 +95,3 @@ func defaultConfig(moniker string) (defaultConfig string) {
 	defaultConfig = strings.Replace(defaultConfigTmpl, "__MONIKER__", moniker, -1)
 	return
 }
-
-var defaultGenesis = `{
-    "chain_id": "tendermint_testnet_11",
-    "accounts": [
-        {
-            "address": "9FCBA7F840A0BFEBBE755E853C9947270A912D04",
-            "amount": 1995999998000000
-        },
-        {
-            "address": "964B1493BBE3312278B7DEB94C39149F7899A345",
-            "amount": 100000000000000
-        },
-        {
-            "address": "B9FA4AB462B9C6BF6A62DB4AE77C9E7087209A04",
-            "amount": 1000000000000
-        },
-        {
-            "address": "F171824590D69386F709E7B6704B369C5A370D60",
-            "amount": 1000000000000
-        },
-        {
-            "address": "56EFE746A13D9A6054AC89C3E2A361C2DB8B9EAE",
-            "amount": 1000000000000
-        },
-        {
-            "address": "7C2E032D8407EDF66A04D88CF0E1D9B15D98AE2D",
-            "amount": 1000000000000
-        },
-        {
-            "address": "A88A61069B6660F30F65E8786AFDD4F1D8F625E9",
-            "amount": 1000000
-        },
-        {
-            "address": "EE2EE9247973B4AFC3867CFE5F415410AC251B61",
-            "amount": 1000000
-        }
-    ],
-    "validators": [
-        {
-            "pub_key": [1, "178EC6008A4364508979C70CBF100BD4BCBAA12DDE6251F5F486B4FD09014F06"],
-            "amount": 100000000000
-        },
-        {
-            "pub_key": [1, "2A77777CC51467DE42350D4A8F34720D527734189BE64C7A930DD169E1FED3C6"],
-            "amount": 100000000000
-        },
-        {
-            "pub_key": [1, "3718E69D09B11B3AD3FA31AEF07EC416D2AEED241CACE7B0F30AE9803FFB0F08"],
-            "amount": 100000000000
-        },
-        {
-            "pub_key": [1, "C6B0440DEACD1E4CF1C736CEB8E38E788B700BA2B2045A55CB657A455CF5F889"],
-            "amount": 100000000000
-        },
-        {
-            "pub_key": [1, "3BA1190D54F91EFBF8B0125F7EC116AD4BA2894B6EE38564A5D5FD3230D91F7B"],
-            "amount": 100000000000
-        }
-    ]
-}`
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint_test/config.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint_test/config.go
index 108d37a3f9ac8fd758fbcfc3ed14c374ef45c432..150bc64ffd8866e4d3aa54c7140bdfffebca0f00 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint_test/config.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint_test/config.go
@@ -3,7 +3,7 @@
 package tendermint_test
 
 import (
-	"github.com/naoina/toml"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/toml"
 	"os"
 	"path"
 	"strings"
@@ -70,8 +70,11 @@ func GetConfig(rootDir string) cfg.Config {
 	mapConfig.SetDefault("db_backend", "memdb")
 	mapConfig.SetDefault("db_dir", rootDir+"/data")
 	mapConfig.SetDefault("log_level", "debug")
+	mapConfig.SetDefault("vm_log", true)
 	mapConfig.SetDefault("rpc_laddr", "0.0.0.0:36657")
-	mapConfig.SetDefault("revisions_file", rootDir+"/revisions")
+	mapConfig.SetDefault("prof_laddr", "")
+	mapConfig.SetDefault("revision_file", rootDir+"/revision")
+	mapConfig.SetDefault("local_routing", false)
 	return mapConfig
 }
 
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/reactor.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/reactor.go
index 0b4378ee0fe4570c2a74a96d640df4d83a1a84ba..ad79bf52fa43f426c794b1b1810dd28e37e1dfba 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/reactor.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/reactor.go
@@ -22,8 +22,6 @@ const (
 	DataChannel  = byte(0x21)
 	VoteChannel  = byte(0x22)
 
-	PeerStateKey = "ConsensusReactor.peerState"
-
 	peerGossipSleepDuration = 100 * time.Millisecond // Time to sleep if there's nothing to send.
 )
 
@@ -107,7 +105,7 @@ func (conR *ConsensusReactor) AddPeer(peer *p2p.Peer) {
 
 	// Create peerState for peer
 	peerState := NewPeerState(peer)
-	peer.Data.Set(PeerStateKey, peerState)
+	peer.Data.Set(types.PeerStateKey, peerState)
 
 	// Begin gossip routines for this peer.
 	go conR.gossipDataRoutine(peer, peerState)
@@ -138,7 +136,7 @@ func (conR *ConsensusReactor) Receive(chID byte, peer *p2p.Peer, msgBytes []byte
 	}
 
 	// Get peer states
-	ps := peer.Data.Get(PeerStateKey).(*PeerState)
+	ps := peer.Data.Get(types.PeerStateKey).(*PeerState)
 	_, msg, err := DecodeMessage(msgBytes)
 	if err != nil {
 		log.Warn("Error decoding message", "channel", chID, "peer", peer, "msg", msg, "error", err, "bytes", msgBytes)
@@ -455,35 +453,21 @@ OUTER_LOOP:
 				}
 			}
 			// If there are prevotes to send...
-			if rs.Round == prs.Round && prs.Step <= RoundStepPrevote {
-				if ps.PickSendVote(rs.Votes.Prevotes(rs.Round)) {
-					log.Info("Picked rs.Prevotes(rs.Round) to send")
-					continue OUTER_LOOP
-				}
-			}
-			// If there are precommits to send...
-			if rs.Round == prs.Round && prs.Step <= RoundStepPrecommit {
-				if ps.PickSendVote(rs.Votes.Precommits(rs.Round)) {
-					log.Info("Picked rs.Precommits(rs.Round) to send")
-					continue OUTER_LOOP
-				}
-			}
-			// If there are prevotes to send for the last round...
-			if rs.Round == prs.Round+1 && prs.Step <= RoundStepPrevote {
+			if prs.Step <= RoundStepPrevote && prs.Round != -1 && prs.Round <= rs.Round {
 				if ps.PickSendVote(rs.Votes.Prevotes(prs.Round)) {
 					log.Info("Picked rs.Prevotes(prs.Round) to send")
 					continue OUTER_LOOP
 				}
 			}
-			// If there are precommits to send for the last round...
-			if rs.Round == prs.Round+1 && prs.Step <= RoundStepPrecommit {
+			// If there are precommits to send...
+			if prs.Step <= RoundStepPrecommit && prs.Round != -1 && prs.Round <= rs.Round {
 				if ps.PickSendVote(rs.Votes.Precommits(prs.Round)) {
 					log.Info("Picked rs.Precommits(prs.Round) to send")
 					continue OUTER_LOOP
 				}
 			}
 			// If there are POLPrevotes to send...
-			if 0 <= prs.ProposalPOLRound {
+			if prs.ProposalPOLRound != -1 {
 				if polPrevotes := rs.Votes.Prevotes(prs.ProposalPOLRound); polPrevotes != nil {
 					if ps.PickSendVote(polPrevotes) {
 						log.Info("Picked rs.Prevotes(prs.ProposalPOLRound) to send")
@@ -548,8 +532,8 @@ type PeerRoundState struct {
 	Precommits               *BitArray           // All precommits peer has for this round
 	LastCommitRound          int                 // Round of commit for last height. -1 if none.
 	LastCommit               *BitArray           // All commit precommits of commit for last height.
-	CatchupCommitRound       int                 // Round that we believe commit round is. -1 if none.
-	CatchupCommit            *BitArray           // All commit precommits peer has for this height
+	CatchupCommitRound       int                 // Round that we have commit for. Not necessarily unique. -1 if none.
+	CatchupCommit            *BitArray           // All commit precommits peer has for this height & CatchupCommitRound
 }
 
 //-----------------------------------------------------------------------------
@@ -588,6 +572,14 @@ func (ps *PeerState) GetRoundState() *PeerRoundState {
 	return &prs
 }
 
+// Returns an atomic snapshot of the PeerRoundState's height
+// used by the mempool to ensure peers are caught up before broadcasting new txs
+func (ps *PeerState) GetHeight() int {
+	ps.mtx.Lock()
+	defer ps.mtx.Unlock()
+	return ps.PeerRoundState.Height
+}
+
 func (ps *PeerState) SetHasProposal(proposal *types.Proposal) {
 	ps.mtx.Lock()
 	defer ps.mtx.Unlock()
@@ -696,14 +688,18 @@ func (ps *PeerState) getVoteBitArray(height, round int, type_ byte) *BitArray {
 	return nil
 }
 
-// NOTE: 'round' is what we know to be the commit round for height.
+// 'round': A round for which we have a +2/3 commit.
 func (ps *PeerState) ensureCatchupCommitRound(height, round int, numValidators int) {
 	if ps.Height != height {
 		return
 	}
-	if ps.CatchupCommitRound != -1 && ps.CatchupCommitRound != round {
-		PanicSanity(Fmt("Conflicting CatchupCommitRound. Height: %v, Orig: %v, New: %v", height, ps.CatchupCommitRound, round))
-	}
+	/*
+		NOTE: This is wrong, 'round' could change.
+		e.g. if orig round is not the same as block LastValidation round.
+		if ps.CatchupCommitRound != -1 && ps.CatchupCommitRound != round {
+			PanicSanity(Fmt("Conflicting CatchupCommitRound. Height: %v, Orig: %v, New: %v", height, ps.CatchupCommitRound, round))
+		}
+	*/
 	if ps.CatchupCommitRound == round {
 		return // Nothing to do!
 	}
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/state.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/state.go
index 72ec17c6b4bb0df9a0e86900bc755e5f7d941f9c..2f8c5e746880374abe125e4901e65c24bf0b5b98 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/state.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/state.go
@@ -1308,14 +1308,12 @@ func (cs *ConsensusState) saveBlock(block *types.Block, blockParts *types.PartSe
 	cs.stagedState.Save()
 
 	// Update mempool.
-	cs.mempoolReactor.Mempool.ResetForBlockAndState(block, cs.stagedState)
+	cs.mempoolReactor.ResetForBlockAndState(block, cs.stagedState)
 
 	// Fire off event
 	if cs.evsw != nil && cs.evc != nil {
-		go func(block *types.Block) {
-			cs.evsw.FireEvent(types.EventStringNewBlock(), types.EventDataNewBlock{block})
-			cs.evc.Flush()
-		}(block)
+		cs.evsw.FireEvent(types.EventStringNewBlock(), types.EventDataNewBlock{block})
+		go cs.evc.Flush()
 	}
 
 }
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/test.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/test.go
index eb5ac9391afa748238672187cccd1df2d81e6aba..6c4b7d38a308f037bba8bc03df999417656e9e9f 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/test.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/test.go
@@ -8,6 +8,7 @@ import (
 
 	bc "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain"
 	dbm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/db"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/events"
 	mempl "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p"
 	sm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state"
@@ -206,6 +207,9 @@ func simpleConsensusState(nValidators int) ([]*ConsensusState, []*types.PrivVali
 		cs := NewConsensusState(state, blockStore, mempoolReactor)
 		cs.SetPrivValidator(privVals[i])
 
+		evsw := events.NewEventSwitch()
+		cs.SetFireable(evsw)
+
 		// read off the NewHeightStep
 		<-cs.NewStepCh()
 
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/db/level_db.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/db/level_db.go
index 587c3ee3f0c70306225280c0c8ae12d5ce771409..66cf9190a9f773a6b432bd379ab9ddcaead54415 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/db/level_db.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/db/level_db.go
@@ -2,9 +2,9 @@ package db
 
 import (
 	"fmt"
-	"github.com/syndtr/goleveldb/leveldb"
-	"github.com/syndtr/goleveldb/leveldb/errors"
-	"github.com/syndtr/goleveldb/leveldb/opt"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt"
 	"path"
 
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/mempool.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/mempool.go
index c1b580f481742ec2a078a971e329749f5f372140..625b56010117b9dcc1783a339070884b1b2aeae3 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/mempool.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/mempool.go
@@ -19,7 +19,7 @@ type Mempool struct {
 	mtx   sync.Mutex
 	state *sm.State
 	cache *sm.BlockCache
-	txs   []types.Tx
+	txs   []types.Tx // TODO: we need to add a map to facilitate replace-by-fee
 }
 
 func NewMempool(state *sm.State) *Mempool {
@@ -37,6 +37,12 @@ func (mem *Mempool) GetCache() *sm.BlockCache {
 	return mem.cache
 }
 
+func (mem *Mempool) GetHeight() int {
+	mem.mtx.Lock()
+	defer mem.mtx.Unlock()
+	return mem.state.LastBlockHeight
+}
+
 // Apply tx to the state and remember it.
 func (mem *Mempool) AddTx(tx types.Tx) (err error) {
 	mem.mtx.Lock()
@@ -59,11 +65,23 @@ func (mem *Mempool) GetProposalTxs() []types.Tx {
 	return mem.txs
 }
 
+// We use this to inform peer routines of how the mempool has been updated
+type ResetInfo struct {
+	Height   int
+	Included []Range
+	Invalid  []Range
+}
+
+type Range struct {
+	Start  int
+	Length int
+}
+
 // "block" is the new block being committed.
 // "state" is the result of state.AppendBlock("block").
 // Txs that are present in "block" are discarded from mempool.
 // Txs that have become invalid in the new "state" are also discarded.
-func (mem *Mempool) ResetForBlockAndState(block *types.Block, state *sm.State) {
+func (mem *Mempool) ResetForBlockAndState(block *types.Block, state *sm.State) ResetInfo {
 	mem.mtx.Lock()
 	defer mem.mtx.Unlock()
 	mem.state = state.Copy()
@@ -75,33 +93,51 @@ func (mem *Mempool) ResetForBlockAndState(block *types.Block, state *sm.State) {
 		blockTxsMap[string(types.TxID(state.ChainID, tx))] = struct{}{}
 	}
 
-	// Next, filter all txs from mem.txs that are in blockTxsMap
-	txs := []types.Tx{}
-	for _, tx := range mem.txs {
+	// Now we filter all txs from mem.txs that are in blockTxsMap,
+	// and ExecTx on what remains. Only valid txs are kept.
+	// We track the ranges of txs included in the block and invalidated by it
+	// so we can tell peer routines
+	var ri = ResetInfo{Height: block.Height}
+	var validTxs []types.Tx
+	includedStart, invalidStart := -1, -1
+	for i, tx := range mem.txs {
 		txID := types.TxID(state.ChainID, tx)
 		if _, ok := blockTxsMap[string(txID)]; ok {
+			startRange(&includedStart, i)           // start counting included txs
+			endRange(&invalidStart, i, &ri.Invalid) // stop counting invalid txs
 			log.Info("Filter out, already committed", "tx", tx, "txID", txID)
-			continue
-		} else {
-			log.Info("Filter in, still new", "tx", tx, "txID", txID)
-			txs = append(txs, tx)
-		}
-	}
-
-	// Next, filter all txs that aren't valid given new state.
-	validTxs := []types.Tx{}
-	for _, tx := range txs {
-		err := sm.ExecTx(mem.cache, tx, false, nil)
-		if err == nil {
-			log.Info("Filter in, valid", "tx", tx)
-			validTxs = append(validTxs, tx)
 		} else {
-			// tx is no longer valid.
-			log.Info("Filter out, no longer valid", "tx", tx, "error", err)
+			endRange(&includedStart, i, &ri.Included) // stop counting included txs
+			err := sm.ExecTx(mem.cache, tx, false, nil)
+			if err != nil {
+				startRange(&invalidStart, i) // start counting invalid txs
+				log.Info("Filter out, no longer valid", "tx", tx, "error", err)
+			} else {
+				endRange(&invalidStart, i, &ri.Invalid) // stop counting invalid txs
+				log.Info("Filter in, new, valid", "tx", tx, "txID", txID)
+				validTxs = append(validTxs, tx)
+			}
 		}
 	}
+	endRange(&includedStart, len(mem.txs)-1, &ri.Included) // stop counting included txs
+	endRange(&invalidStart, len(mem.txs)-1, &ri.Invalid)   // stop counting invalid txs
 
 	// We're done!
 	log.Info("New txs", "txs", validTxs, "oldTxs", mem.txs)
 	mem.txs = validTxs
+	return ri
+}
+
+func startRange(start *int, i int) {
+	if *start < 0 {
+		*start = i
+	}
+}
+
+func endRange(start *int, i int, ranger *[]Range) {
+	if *start >= 0 {
+		length := i - *start
+		*ranger = append(*ranger, Range{*start, length})
+		*start = -1
+	}
 }
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/reactor.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/reactor.go
index fb3ff7d74cb6b7eaa235a5868fc0c527a2884b6c..01d714666a0c45a0432eff26bf6643e689470e1d 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/reactor.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/reactor.go
@@ -2,18 +2,25 @@ package mempool
 
 import (
 	"bytes"
+	"errors"
 	"fmt"
 	"reflect"
+	"time"
 
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/events"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p"
+	sm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire"
 )
 
 var (
 	MempoolChannel = byte(0x30)
+
+	checkExecutedTxsMilliseconds = 1   // check for new mempool txs to send to peer
+	txsToSendPerCheck            = 64  // send up to this many txs from the mempool per check
+	newBlockChCapacity           = 100 // queue to process this many ResetInfos per peer
 )
 
 // MempoolReactor handles mempool tx broadcasting amongst peers.
@@ -44,11 +51,17 @@ func (memR *MempoolReactor) GetChannels() []*p2p.ChannelDescriptor {
 }
 
 // Implements Reactor
-func (pexR *MempoolReactor) AddPeer(peer *p2p.Peer) {
+func (memR *MempoolReactor) AddPeer(peer *p2p.Peer) {
+	// Each peer gets a go routine on which we broadcast transactions in the same order we applied them to our state.
+	newBlockChan := make(chan ResetInfo, newBlockChCapacity)
+	peer.Data.Set(types.PeerMempoolChKey, newBlockChan)
+	timer := time.NewTicker(time.Millisecond * time.Duration(checkExecutedTxsMilliseconds))
+	go memR.broadcastTxRoutine(timer.C, newBlockChan, peer)
 }
 
 // Implements Reactor
-func (pexR *MempoolReactor) RemovePeer(peer *p2p.Peer, reason interface{}) {
+func (memR *MempoolReactor) RemovePeer(peer *p2p.Peer, reason interface{}) {
+	// broadcast routine checks if peer is gone and returns
 }
 
 // Implements Reactor
@@ -70,29 +83,128 @@ func (memR *MempoolReactor) Receive(chID byte, src *p2p.Peer, msgBytes []byte) {
 		} else {
 			log.Info("Added valid tx", "tx", msg.Tx)
 		}
-		// Share tx.
-		// We use a simple shotgun approach for now.
-		// TODO: improve efficiency
-		for _, peer := range memR.Switch.Peers().List() {
-			if peer.Key == src.Key {
+		// broadcasting happens from go routines per peer
+	default:
+		log.Warn(Fmt("Unknown message type %v", reflect.TypeOf(msg)))
+	}
+}
+
+// "block" is the new block being committed.
+// "state" is the result of state.AppendBlock("block").
+// Txs that are present in "block" are discarded from mempool.
+// Txs that have become invalid in the new "state" are also discarded.
+func (memR *MempoolReactor) ResetForBlockAndState(block *types.Block, state *sm.State) {
+	ri := memR.Mempool.ResetForBlockAndState(block, state)
+	for _, peer := range memR.Switch.Peers().List() {
+		peerMempoolCh := peer.Data.Get(types.PeerMempoolChKey).(chan ResetInfo)
+		select {
+		case peerMempoolCh <- ri:
+		default:
+			memR.Switch.StopPeerForError(peer, errors.New("Peer's mempool push channel full"))
+		}
+	}
+}
+
+// Just an alias for AddTx since broadcasting happens in peer routines
+func (memR *MempoolReactor) BroadcastTx(tx types.Tx) error {
+	return memR.Mempool.AddTx(tx)
+}
+
+type PeerState interface {
+	GetHeight() int
+}
+
+type Peer interface {
+	IsRunning() bool
+	Send(byte, interface{}) bool
+	Get(string) interface{}
+}
+
+// send new mempool txs to peer, strictly in order we applied them to our state.
+// new blocks take chunks out of the mempool, but we've already sent some txs to the peer.
+// so we wait to hear that the peer has progressed to the new height, and then continue sending txs from where we left off
+func (memR *MempoolReactor) broadcastTxRoutine(tickerChan <-chan time.Time, newBlockChan chan ResetInfo, peer Peer) {
+	var height = memR.Mempool.GetHeight()
+	var txsSent int // new txs sent for height. (reset every new height)
+
+	for {
+		select {
+		case <-tickerChan:
+			if !peer.IsRunning() {
+				return
+			}
+
+			// make sure the peer is up to date
+			if peerState_i := peer.Get(types.PeerStateKey); peerState_i != nil {
+				peerState := peerState_i.(PeerState)
+				if peerState.GetHeight() < height {
+					continue
+				}
+			} else {
 				continue
 			}
-			peer.TrySend(MempoolChannel, msg)
+
+			// check the mempool for new transactions
+			newTxs := memR.getNewTxs(height)
+			txsSentLoop := 0
+			start := time.Now()
+
+		TX_LOOP:
+			for i := txsSent; i < len(newTxs) && txsSentLoop < txsToSendPerCheck; i++ {
+				tx := newTxs[i]
+				msg := &TxMessage{Tx: tx}
+				success := peer.Send(MempoolChannel, msg)
+				if !success {
+					break TX_LOOP
+				} else {
+					txsSentLoop += 1
+				}
+			}
+
+			if txsSentLoop > 0 {
+				txsSent += txsSentLoop
+				log.Info("Sent txs to peer", "txsSentLoop", txsSentLoop,
+					"took", time.Since(start), "txsSent", txsSent, "newTxs", len(newTxs))
+			}
+
+		case ri := <-newBlockChan:
+			height = ri.Height
+
+			// find out how many txs below what we've sent were included in a block and how many became invalid
+			included := tallyRangesUpTo(ri.Included, txsSent)
+			invalidated := tallyRangesUpTo(ri.Invalid, txsSent)
+
+			txsSent -= included + invalidated
 		}
+	}
+}
 
-	default:
-		log.Warn(Fmt("Unknown message type %v", reflect.TypeOf(msg)))
+// fetch new txs from the mempool
+func (memR *MempoolReactor) getNewTxs(height int) (txs []types.Tx) {
+	memR.Mempool.mtx.Lock()
+	defer memR.Mempool.mtx.Unlock()
+
+	// if the mempool got ahead of us just return empty txs
+	if memR.Mempool.state.LastBlockHeight != height {
+		return
 	}
+	return memR.Mempool.txs
 }
 
-func (memR *MempoolReactor) BroadcastTx(tx types.Tx) error {
-	err := memR.Mempool.AddTx(tx)
-	if err != nil {
-		return err
+// return the size of ranges less than upTo
+func tallyRangesUpTo(ranger []Range, upTo int) int {
+	totalUpTo := 0
+	for _, r := range ranger {
+		if r.Start >= upTo {
+			break
+		}
+		if r.Start+r.Length >= upTo {
+			totalUpTo += upTo - r.Start
+			break
+		}
+		totalUpTo += r.Length
 	}
-	msg := &TxMessage{Tx: tx}
-	memR.Switch.Broadcast(MempoolChannel, msg)
-	return nil
+	return totalUpTo
 }
 
 // implements events.Eventable
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go
index c30a958ce03dbcf8b1912a8c3b17693dd0f64f9e..92ef5aafe25004bff6f5711ea6006377c56f017d 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go
@@ -5,7 +5,6 @@ import (
 	"math/rand"
 	"net"
 	"net/http"
-	"os"
 	"strconv"
 	"strings"
 	"time"
@@ -24,6 +23,7 @@ import (
 	sm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state"
 	stypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/vm"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire"
 )
 
@@ -75,18 +75,8 @@ func NewNode() *Node {
 	config.Set("chain_id", state.ChainID)
 
 	// Get PrivValidator
-	var privValidator *types.PrivValidator
 	privValidatorFile := config.GetString("priv_validator_file")
-	if _, err := os.Stat(privValidatorFile); err == nil {
-		privValidator = types.LoadPrivValidator(privValidatorFile)
-		log.Notice("Loaded PrivValidator",
-			"file", privValidatorFile, "privValidator", privValidator)
-	} else {
-		privValidator = types.GenPrivValidator()
-		privValidator.SetFile(privValidatorFile)
-		privValidator.Save()
-		log.Notice("Generated PrivValidator", "file", privValidatorFile)
-	}
+	privValidator := types.LoadOrGenPrivValidator(privValidatorFile)
 
 	// Generate node PrivKey
 	privKey := acm.GenPrivKeyEd25519()
@@ -127,6 +117,17 @@ func NewNode() *Node {
 	// they should all satisfy events.Eventable
 	SetFireable(eventSwitch, pexReactor, bcReactor, mempoolReactor, consensusReactor)
 
+	// run the profile server
+	profileHost := config.GetString("prof_laddr")
+	if profileHost != "" {
+		go func() {
+			log.Warn("Profile server", "error", http.ListenAndServe(profileHost, nil))
+		}()
+	}
+
+	// set vm log level
+	vm.SetDebug(config.GetBool("vm_log"))
+
 	return &Node{
 		sw:               sw,
 		evsw:             eventSwitch,
@@ -256,7 +257,7 @@ func makeNodeInfo(sw *p2p.Switch, privKey acm.PrivKeyEd25519) *types.NodeInfo {
 	}
 
 	// include git hash in the nodeInfo if available
-	if rev, err := ReadFile(config.GetString("revisions_file")); err == nil {
+	if rev, err := ReadFile(config.GetString("revision_file")); err == nil {
 		nodeInfo.Version.Revision = string(rev)
 	}
 
@@ -286,6 +287,19 @@ func makeNodeInfo(sw *p2p.Switch, privKey acm.PrivKeyEd25519) *types.NodeInfo {
 //------------------------------------------------------------------------------
 
 func RunNode() {
+
+	// Wait until the genesis doc becomes available
+	genDocFile := config.GetString("genesis_file")
+	if !FileExists(genDocFile) {
+		log.Notice(Fmt("Waiting for genesis file %v...", genDocFile))
+		for {
+			time.Sleep(time.Second)
+			if FileExists(genDocFile) {
+				break
+			}
+		}
+	}
+
 	// Create & start node
 	n := NewNode()
 	l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"))
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/netaddress.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/netaddress.go
index 8588ff73b82a3f2276698b1f8127a652f726e5c6..983cda622219e16c1c680dfb0e5b5d62ba254840 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/netaddress.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/netaddress.go
@@ -110,6 +110,10 @@ func (na *NetAddress) DialTimeout(timeout time.Duration) (net.Conn, error) {
 }
 
 func (na *NetAddress) Routable() bool {
+	if config.GetBool("local_routing") {
+		return na.Valid()
+	}
+
 	// TODO(oga) bitcoind doesn't include RFC3849 here, but should we?
 	return na.Valid() && !(na.RFC1918() || na.RFC3927() || na.RFC4862() ||
 		na.RFC4193() || na.RFC4843() || na.Local())
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/peer.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/peer.go
index 82ff986b917618ac1f9b5c5e74a27e522d3e2570..7b291f80371e69647de9ca4b87e3be741f9f0d20 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/peer.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/peer.go
@@ -128,3 +128,7 @@ func (p *Peer) String() string {
 func (p *Peer) Equals(other *Peer) bool {
 	return p.Key == other.Key
 }
+
+func (p *Peer) Get(key string) interface{} {
+	return p.Data.Get(key)
+}
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/consensus.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/consensus.go
index d0f3a71e52bd4e7d1aac6f6a68769331137014c4..4bec4e620a86cf98da448f49724155cff80e8bc4 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/consensus.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/consensus.go
@@ -31,7 +31,7 @@ func DumpConsensusState() (*ctypes.ResultDumpConsensusState, error) {
 	peerRoundStates := []string{}
 	for _, peer := range p2pSwitch.Peers().List() {
 		// TODO: clean this up?
-		peerState := peer.Data.Get(cm.PeerStateKey).(*cm.PeerState)
+		peerState := peer.Data.Get(types.PeerStateKey).(*cm.PeerState)
 		peerRoundState := peerState.GetRoundState()
 		peerRoundStateStr := peer.Key + ":" + string(wire.JSONBytes(peerRoundState))
 		peerRoundStates = append(peerRoundStates, peerRoundStateStr)
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/mempool.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/mempool.go
index 61cd4b95ed0e592c09531515e7370db77e9c0039..c2c7f95f0842c6b095623332cc293955132b9a8d 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/mempool.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/mempool.go
@@ -30,5 +30,6 @@ func BroadcastTx(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
 }
 
 func ListUnconfirmedTxs() (*ctypes.ResultListUnconfirmedTxs, error) {
-	return &ctypes.ResultListUnconfirmedTxs{mempoolReactor.Mempool.GetProposalTxs()}, nil
+	txs := mempoolReactor.Mempool.GetProposalTxs()
+	return &ctypes.ResultListUnconfirmedTxs{len(txs), txs}, nil
 }
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types/responses.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types/responses.go
index bfc35523094de0ec21731046fac236a28fc845d3..45d4a2f305d1854efc5a612761465045e4cf3cfc 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types/responses.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types/responses.go
@@ -98,6 +98,7 @@ type Receipt struct {
 }
 
 type ResultListUnconfirmedTxs struct {
+	N   int        `json:"n_txs"`
 	Txs []types.Tx `json:"txs"`
 }
 
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core_client/ws_client.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core_client/ws_client.go
index 2ca57bc7b9b8eaa4bbd6b3188f507861486b06bd..e150e001af96fe692ecbbfef864a58c58eba62be 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core_client/ws_client.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core_client/ws_client.go
@@ -5,11 +5,11 @@ import (
 	"strings"
 	"time"
 
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gorilla/websocket"
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
 	ctypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire"
-	"github.com/gorilla/websocket"
 )
 
 const (
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/server/handlers.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/server/handlers.go
index 51473b2def1705a142eb6d0fddc6ed0e26803d11..b57be3057caaad545faa161a4585abc2f1a54aee 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/server/handlers.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/server/handlers.go
@@ -11,13 +11,13 @@ import (
 	"sort"
 	"time"
 
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gorilla/websocket"
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/events"
 	ctypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types"
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire"
-	"github.com/gorilla/websocket"
 )
 
 func RegisterRPCFuncs(mux *http.ServeMux, funcMap map[string]*RPCFunc) {
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/test/ws_helpers.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/test/ws_helpers.go
index fce8b1332b40cb1891dbde38ad84a32cd0196c09..bce4efe6b43173efc0deaf700027edfe8b141383 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/test/ws_helpers.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/test/ws_helpers.go
@@ -7,12 +7,12 @@ import (
 	"testing"
 	"time"
 
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gorilla/websocket"
 	_ "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint_test"
 	ctypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire"
-	"github.com/gorilla/websocket"
 )
 
 //--------------------------------------------------------------------------------
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/state.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/state.go
index 4abbc242e6481bca9515cec4a7c6372d13e9d3e1..a5cfc458bde8ff1361aaa3202f910eea77614cbb 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/state.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/state.go
@@ -473,3 +473,11 @@ func MakeGenesisState(db dbm.DB, genDoc *GenesisDoc) *State {
 		nameReg:              nameReg,
 	}
 }
+
+func RandGenesisState(numAccounts int, randBalance bool, minBalance int64, numValidators int, randBonded bool, minBonded int64) (*State, []*acm.PrivAccount, []*types.PrivValidator) {
+	db := dbm.NewMemDB()
+	genDoc, privAccounts, privValidators := RandGenesisDoc(numAccounts, randBalance, minBalance, numValidators, randBonded, minBonded)
+	s0 := MakeGenesisState(db, genDoc)
+	s0.Save()
+	return s0, privAccounts, privValidators
+}
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/test.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/test.go
deleted file mode 100644
index ca6eae68c62a593e0d0292a26d5edb59a7a604f3..0000000000000000000000000000000000000000
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/test.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package state
-
-import (
-	"sort"
-	"time"
-
-	acm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account"
-	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
-	dbm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/db"
-	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types"
-	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types"
-	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types"
-)
-
-func RandAccount(randBalance bool, minBalance int64) (*acm.Account, *acm.PrivAccount) {
-	privAccount := acm.GenPrivAccount()
-	perms := ptypes.DefaultAccountPermissions
-	acc := &acm.Account{
-		Address:     privAccount.PubKey.Address(),
-		PubKey:      privAccount.PubKey,
-		Sequence:    RandInt(),
-		Balance:     minBalance,
-		Permissions: perms,
-	}
-	if randBalance {
-		acc.Balance += int64(RandUint32())
-	}
-	return acc, privAccount
-}
-
-func RandGenesisDoc(numAccounts int, randBalance bool, minBalance int64, numValidators int, randBonded bool, minBonded int64) (*GenesisDoc, []*acm.PrivAccount, []*types.PrivValidator) {
-	accounts := make([]GenesisAccount, numAccounts)
-	privAccounts := make([]*acm.PrivAccount, numAccounts)
-	defaultPerms := ptypes.DefaultAccountPermissions
-	for i := 0; i < numAccounts; i++ {
-		account, privAccount := RandAccount(randBalance, minBalance)
-		accounts[i] = GenesisAccount{
-			Address:     account.Address,
-			Amount:      account.Balance,
-			Permissions: &defaultPerms, // This will get copied into each state.Account.
-		}
-		privAccounts[i] = privAccount
-	}
-	validators := make([]GenesisValidator, numValidators)
-	privValidators := make([]*types.PrivValidator, numValidators)
-	for i := 0; i < numValidators; i++ {
-		valInfo, _, privVal := types.RandValidator(randBonded, minBonded)
-		validators[i] = GenesisValidator{
-			PubKey: valInfo.PubKey,
-			Amount: valInfo.FirstBondAmount,
-			UnbondTo: []BasicAccount{
-				{
-					Address: valInfo.PubKey.Address(),
-					Amount:  valInfo.FirstBondAmount,
-				},
-			},
-		}
-		privValidators[i] = privVal
-	}
-	sort.Sort(types.PrivValidatorsByAddress(privValidators))
-	return &GenesisDoc{
-		GenesisTime: time.Now(),
-		ChainID:     "tendermint_test",
-		Accounts:    accounts,
-		Validators:  validators,
-	}, privAccounts, privValidators
-
-}
-
-func RandGenesisState(numAccounts int, randBalance bool, minBalance int64, numValidators int, randBonded bool, minBonded int64) (*State, []*acm.PrivAccount, []*types.PrivValidator) {
-	db := dbm.NewMemDB()
-	genDoc, privAccounts, privValidators := RandGenesisDoc(numAccounts, randBalance, minBalance, numValidators, randBonded, minBonded)
-	s0 := MakeGenesisState(db, genDoc)
-	s0.Save()
-	return s0, privAccounts, privValidators
-}
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/tx_cache_test.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/tx_cache_test.go
index ef6544925948eab6ddaad9b681f4331bf2454cfa..ee8e96a058a61d51211cbed37de5a33b8a6b619f 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/tx_cache_test.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/tx_cache_test.go
@@ -4,11 +4,12 @@ import (
 	"bytes"
 	"testing"
 
+	stypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire"
 )
 
 func TestStateToFromVMAccount(t *testing.T) {
-	acmAcc1, _ := RandAccount(true, 456)
+	acmAcc1, _ := stypes.RandAccount(true, 456)
 	vmAcc := toVMAccount(acmAcc1)
 	acmAcc2 := toStateAccount(vmAcc)
 
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types/genesis.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types/genesis.go
index ed90b01bf6623ac4079194db7876d513480b9aef..d850fcb1a3a877b83384808fa3f4b449d2d551c4 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types/genesis.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types/genesis.go
@@ -1,11 +1,13 @@
 package types
 
 import (
+	"sort"
 	"time"
 
 	acm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account"
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
 	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire"
 )
 
@@ -59,3 +61,61 @@ func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) {
 	}
 	return
 }
+
+//------------------------------------------------------------
+// Make random genesis state
+
+func RandAccount(randBalance bool, minBalance int64) (*acm.Account, *acm.PrivAccount) {
+	privAccount := acm.GenPrivAccount()
+	perms := ptypes.DefaultAccountPermissions
+	acc := &acm.Account{
+		Address:     privAccount.PubKey.Address(),
+		PubKey:      privAccount.PubKey,
+		Sequence:    RandInt(),
+		Balance:     minBalance,
+		Permissions: perms,
+	}
+	if randBalance {
+		acc.Balance += int64(RandUint32())
+	}
+	return acc, privAccount
+}
+
+func RandGenesisDoc(numAccounts int, randBalance bool, minBalance int64, numValidators int, randBonded bool, minBonded int64) (*GenesisDoc, []*acm.PrivAccount, []*types.PrivValidator) {
+	accounts := make([]GenesisAccount, numAccounts)
+	privAccounts := make([]*acm.PrivAccount, numAccounts)
+	defaultPerms := ptypes.DefaultAccountPermissions
+	for i := 0; i < numAccounts; i++ {
+		account, privAccount := RandAccount(randBalance, minBalance)
+		accounts[i] = GenesisAccount{
+			Address:     account.Address,
+			Amount:      account.Balance,
+			Permissions: &defaultPerms, // This will get copied into each state.Account.
+		}
+		privAccounts[i] = privAccount
+	}
+	validators := make([]GenesisValidator, numValidators)
+	privValidators := make([]*types.PrivValidator, numValidators)
+	for i := 0; i < numValidators; i++ {
+		valInfo, _, privVal := types.RandValidator(randBonded, minBonded)
+		validators[i] = GenesisValidator{
+			PubKey: valInfo.PubKey,
+			Amount: valInfo.FirstBondAmount,
+			UnbondTo: []BasicAccount{
+				{
+					Address: valInfo.PubKey.Address(),
+					Amount:  valInfo.FirstBondAmount,
+				},
+			},
+		}
+		privValidators[i] = privVal
+	}
+	sort.Sort(types.PrivValidatorsByAddress(privValidators))
+	return &GenesisDoc{
+		GenesisTime: time.Now(),
+		ChainID:     "tendermint_test",
+		Accounts:    accounts,
+		Validators:  validators,
+	}, privAccounts, privValidators
+
+}
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/node.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/node.go
index e548a5779c46c7e2515bd67355705f4ee9613250..8e320cba28f249fc9c44e357f474ab21273773fe 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/node.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/node.go
@@ -19,7 +19,7 @@ type NodeInfo struct {
 
 type Versions struct {
 	Revision   string `json:"revision"`
-	Tendermint string `json"tendermint"`
+	Tendermint string `json:"tendermint"`
 	P2P        string `json:"p2p"`
 	RPC        string `json:"rpc"`
 	Wire       string `json:"wire"`
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go
index aad8d118c9561fd4931e89b77f71fbef5036154b..e97befbcbbc6dd39e07a87e711b084082f1fcf9c 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go
@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"io/ioutil"
 	"math"
+	"os"
 	"sync"
 
 	acm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account"
@@ -79,6 +80,21 @@ func LoadPrivValidator(filePath string) *PrivValidator {
 	return privVal
 }
 
+func LoadOrGenPrivValidator(filePath string) *PrivValidator {
+	var privValidator *PrivValidator
+	if _, err := os.Stat(filePath); err == nil {
+		privValidator = LoadPrivValidator(filePath)
+		log.Notice("Loaded PrivValidator",
+			"file", filePath, "privValidator", privValidator)
+	} else {
+		privValidator = GenPrivValidator()
+		privValidator.SetFile(filePath)
+		privValidator.Save()
+		log.Notice("Generated PrivValidator", "file", filePath)
+	}
+	return privValidator
+}
+
 func (privVal *PrivValidator) SetFile(filePath string) {
 	privVal.mtx.Lock()
 	defer privVal.mtx.Unlock()
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/tx.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/tx.go
index e6d572ab693c61ada3ff4f8615e8bbbb1a265bfe..ff2534e518f3e371fda0c96c0b23b53acfebbf0d 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/tx.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/tx.go
@@ -4,7 +4,9 @@ import (
 	"encoding/json"
 	"errors"
 	"io"
+
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/crypto/ripemd160"
+
 	acm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account"
 	. "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common"
 	ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types"
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/vote_set.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/vote_set.go
index a1c551e9202f7b7fcf16fdaadd8b42ab143c7f5e..4aaa772fc0ca4d85ed34912f2260cdcf96083c7f 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/vote_set.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/vote_set.go
@@ -204,6 +204,9 @@ func (voteSet *VoteSet) IsCommit() bool {
 	if voteSet == nil {
 		return false
 	}
+	if voteSet.type_ != VoteTypePrecommit {
+		return false
+	}
 	voteSet.mtx.Lock()
 	defer voteSet.mtx.Unlock()
 	return len(voteSet.maj23Hash) > 0
diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go
index 38ce23f7919d9bf453d2e40945314ef0a6b5825a..410d433ef0994a5e26ec7c154e2e381bd98b95bf 100644
--- a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go
+++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go
@@ -36,15 +36,20 @@ func (err ErrPermission) Error() string {
 	return fmt.Sprintf("Contract does not have permission to %s", err.typ)
 }
 
-type Debug bool
-
 const (
-	dataStackCapacity       = 1024
-	callStackCapacity       = 100         // TODO ensure usage.
-	memoryCapacity          = 1024 * 1024 // 1 MB
-	dbg               Debug = true
+	dataStackCapacity = 1024
+	callStackCapacity = 100         // TODO ensure usage.
+	memoryCapacity    = 1024 * 1024 // 1 MB
 )
 
+type Debug bool
+
+var dbg Debug
+
+func SetDebug(d bool) {
+	dbg = Debug(d)
+}
+
 func (d Debug) Printf(s string, a ...interface{}) {
 	if d {
 		fmt.Printf(s, a...)
@@ -109,6 +114,8 @@ func (vm *VM) fireCallEvent(exception *string, output *[]byte, caller, callee *A
 }
 
 // CONTRACT appState is aware of caller and callee, so we can just mutate them.
+// CONTRACT code and input are not mutated.
+// CONTRACT returned 'ret' is a new compact slice.
 // value: To be transferred from caller to callee. Refunded upon error.
 // gas:   Available gas. No refunds for gas.
 // code: May be nil, since the CALL opcode may be used to send value from contracts to accounts
@@ -691,6 +698,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			if !ok {
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
 			}
+			data = copyslice(data)
 			if vm.evc != nil {
 				eventID := types.EventStringLogEvent(callee.Address.Postfix(20))
 				fmt.Printf("eventID: %s\n", eventID)
@@ -724,11 +732,12 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 
 			newAccount := vm.appState.CreateAccount(callee)
 			// Run the input to get the contract code.
+			// NOTE: no need to copy 'input' as per Call contract.
 			ret, err_ := vm.Call(callee, newAccount, input, input, contractValue, gas)
 			if err_ != nil {
 				stack.Push(Zero256)
 			} else {
-				newAccount.Code = ret // Set the code
+				newAccount.Code = ret // Set the code (ret need not be copied as per Call contract)
 				stack.Push(newAccount.Address)
 			}
 
@@ -747,6 +756,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 			if !ok {
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
 			}
+			args = copyslice(args)
 
 			// Ensure that gasLimit is reasonable
 			if *gas < gasLimit {
@@ -827,7 +837,8 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
 				return nil, firstErr(err, ErrMemoryOutOfBounds)
 			}
 			dbg.Printf(" => [%v, %v] (%d) 0x%X\n", offset, size, len(ret), ret)
-			return ret, nil
+			output = copyslice(ret)
+			return output, nil
 
 		case SUICIDE: // 0xFF
 			addr := stack.Pop()
@@ -870,10 +881,15 @@ func subslice(data []byte, offset, length int64) (ret []byte, ok bool) {
 	} else {
 		ret, ok = data[offset:offset+length], true
 	}
-
 	return
 }
 
+func copyslice(src []byte) (dest []byte) {
+	dest = make([]byte, len(src))
+	copy(dest, src)
+	return dest
+}
+
 func rightMostBytes(data []byte, n int) []byte {
 	size := MinInt(len(data), n)
 	offset := len(data) - size
diff --git a/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box.go b/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box.go
index a940f516926f7d99847410cec8a582d5e0d3da1c..05868b65ca1572d12c1dde0a9301ec795a12ea58 100644
--- a/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box.go
+++ b/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box.go
@@ -18,9 +18,9 @@ This package is interoperable with NaCl: http://nacl.cr.yp.to/box.html.
 package box
 
 import (
-	"github.com/tendermint/tendermint/Godeps/_workspace/src/golang.org/x/crypto/curve25519"
-	"github.com/tendermint/tendermint/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox"
-	"github.com/tendermint/tendermint/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/crypto/curve25519"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa"
 	"io"
 )
 
diff --git a/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box_test.go b/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box_test.go
index 5d48f3b0a65d7d84c2b8fcceb36c48d04ac96482..dbae504ecf475d63ca29a46ec0a8b50b67b9b07c 100644
--- a/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box_test.go
+++ b/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box_test.go
@@ -10,7 +10,7 @@ import (
 	"encoding/hex"
 	"testing"
 
-	"github.com/tendermint/tendermint/Godeps/_workspace/src/golang.org/x/crypto/curve25519"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/crypto/curve25519"
 )
 
 func TestSealOpen(t *testing.T) {
diff --git a/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox.go b/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox.go
index fc4a6f5b7d0dae013624b5b870cb3ff67d273e7c..800cc5b5ccfb91a7cbeb974e7d53b5c880e49ae0 100644
--- a/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox.go
+++ b/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox.go
@@ -18,8 +18,8 @@ This package is interoperable with NaCl: http://nacl.cr.yp.to/secretbox.html.
 package secretbox
 
 import (
-	"github.com/tendermint/tendermint/Godeps/_workspace/src/golang.org/x/crypto/poly1305"
-	"github.com/tendermint/tendermint/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/crypto/poly1305"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa"
 )
 
 // Overhead is the number of bytes of overhead when boxing a message.
diff --git a/Godeps/_workspace/src/golang.org/x/net/context/context_test.go b/Godeps/_workspace/src/golang.org/x/net/context/context_test.go
index faf67722a0f975f8b60ee314e3ef2b84f0dc1a5f..05345fc5e5fb856499057fef5d1b9ea59bdb69ef 100644
--- a/Godeps/_workspace/src/golang.org/x/net/context/context_test.go
+++ b/Godeps/_workspace/src/golang.org/x/net/context/context_test.go
@@ -375,7 +375,7 @@ func TestAllocs(t *testing.T) {
 				<-c.Done()
 			},
 			limit:      8,
-			gccgoLimit: 13,
+			gccgoLimit: 15,
 		},
 		{
 			desc: "WithCancel(bg)",
@@ -536,7 +536,7 @@ func testLayers(t *testing.T, seed int64, testTimeout bool) {
 	if testTimeout {
 		select {
 		case <-ctx.Done():
-		case <-time.After(timeout + timeout/10):
+		case <-time.After(timeout + 100*time.Millisecond):
 			errorf("ctx should have timed out")
 		}
 		checkValues("after timeout")
diff --git a/Godeps/_workspace/src/golang.org/x/net/netutil/listen_test.go b/Godeps/_workspace/src/golang.org/x/net/netutil/listen_test.go
index ac87e0ee4a9a688622541088d0f77f9d8ffcd03e..c0d5bc2a70f6877a7a5c8cdc9855b5d0f0175ce9 100644
--- a/Godeps/_workspace/src/golang.org/x/net/netutil/listen_test.go
+++ b/Godeps/_workspace/src/golang.org/x/net/netutil/listen_test.go
@@ -20,17 +20,20 @@ import (
 	"sync/atomic"
 	"testing"
 	"time"
+
+	"golang.org/x/net/internal/nettest"
 )
 
 func TestLimitListener(t *testing.T) {
-	const (
-		max = 5
-		num = 200
-	)
+	const max = 5
+	attempts := (nettest.MaxOpenFiles() - max) / 2
+	if attempts > 256 { // maximum length of accept queue is 128 by default
+		attempts = 256
+	}
 
 	l, err := net.Listen("tcp", "127.0.0.1:0")
 	if err != nil {
-		t.Fatalf("Listen: %v", err)
+		t.Fatal(err)
 	}
 	defer l.Close()
 	l = LimitListener(l, max)
@@ -47,14 +50,14 @@ func TestLimitListener(t *testing.T) {
 
 	var wg sync.WaitGroup
 	var failed int32
-	for i := 0; i < num; i++ {
+	for i := 0; i < attempts; i++ {
 		wg.Add(1)
 		go func() {
 			defer wg.Done()
 			c := http.Client{Timeout: 3 * time.Second}
 			r, err := c.Get("http://" + l.Addr().String())
 			if err != nil {
-				t.Logf("Get: %v", err)
+				t.Log(err)
 				atomic.AddInt32(&failed, 1)
 				return
 			}
@@ -66,8 +69,8 @@ func TestLimitListener(t *testing.T) {
 
 	// We expect some Gets to fail as the kernel's accept queue is filled,
 	// but most should succeed.
-	if failed >= num/2 {
-		t.Errorf("too many Gets failed: %v", failed)
+	if int(failed) >= attempts/2 {
+		t.Errorf("%d requests failed within %d attempts", failed, attempts)
 	}
 }
 
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.gitignore b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.gitignore
index 415902041c853f9d77290ef92c94043b0d30abfc..7e9b50032d207cedcd10de2796dc4203d9889332 100644
--- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.gitignore
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.gitignore
@@ -23,4 +23,6 @@ _testmain.go
 *.test
 *.prof
 *.test
-*.out
\ No newline at end of file
+*.out
+cover.html
+README.html
\ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.travis.yml b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.travis.yml
deleted file mode 100644
index 68398d9f152d5b07e90a55adc00e5006436e58dd..0000000000000000000000000000000000000000
--- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.travis.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-language: go
-
-notificaitons:
-  email:
-    recipients: bluesuncorp01@gmail.com
-    on_success: change
-    on_failure: always
-
-go:
-  - 1.2
-  - 1.3
-  - 1.4
-  - tip
\ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/README.md b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/README.md
index c1e9d00cfddae372708ada9681bf588026df55f9..1a78bec3c3f0b07dcb9b7a56083558362817b247 100644
--- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/README.md
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/README.md
@@ -1,33 +1,143 @@
 Package validator
 ================
-[![Build Status](https://travis-ci.org/bluesuncorp/validator.svg?branch=v5.1)](https://travis-ci.org/bluesuncorp/validator)
-[![GoDoc](https://godoc.org/gopkg.in/bluesuncorp/validator.v5?status.svg)](https://godoc.org/gopkg.in/bluesuncorp/validator.v5)
+
+[![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[![Build Status](https://semaphoreci.com/api/v1/projects/ec20115f-ef1b-4c7d-9393-cc76aba74eb4/487382/badge.svg)](https://semaphoreci.com/joeybloggs/validator)
+[![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=v5)](https://coveralls.io/r/go-playground/validator?branch=v5)
+[![GoDoc](https://godoc.org/gopkg.in/go-playground/validator.v5?status.svg)](https://godoc.org/gopkg.in/go-playground/validator.v5)
 
 Package validator implements value validations for structs and individual fields based on tags.
-It is also capable of Cross Field and Cross Struct validations.
+
+It has the following **unique** features:
+
+-   Cross Field and Cross Struct validations.  
+-   Slice, Array and Map diving, which allows any or all levels of a multidimensional field to be validated.  
+-   Handles type interface by determining it's underlying type prior to validation.  
 
 Installation
-============
+------------
 
 Use go get.
 
-	go get gopkg.in/bluesuncorp/validator.v5
+	go get gopkg.in/go-playground/validator.v5
 
 or to update
 
-	go get -u gopkg.in/bluesuncorp/validator.v5
+	go get -u gopkg.in/go-playground/validator.v5
 
 Then import the validator package into your own code.
 
-	import "gopkg.in/bluesuncorp/validator.v5"
+	import "gopkg.in/go-playground/validator.v5"
 
 Usage and documentation
-=======================
+------
+
+Please see http://godoc.org/gopkg.in/go-playground/validator.v5 for detailed usage docs.
+
+##### Example:
+```go
+package main
+
+import (
+	"fmt"
+
+	"gopkg.in/go-playground/validator.v5"
+)
+
+// User contains user information
+type User struct {
+	FirstName      string     `validate:"required"`
+	LastName       string     `validate:"required"`
+	Age            uint8      `validate:"gte=0,lte=130"`
+	Email          string     `validate:"required,email"`
+	FavouriteColor string     `validate:"hexcolor|rgb|rgba"`
+	Addresses      []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
+}
+
+// Address houses a users address information
+type Address struct {
+	Street string `validate:"required"`
+	City   string `validate:"required"`
+	Planet string `validate:"required"`
+	Phone  string `validate:"required"`
+}
+
+var validate *validator.Validate
+
+func main() {
+
+	validate = validator.New("validate", validator.BakedInValidators)
+
+	address := &Address{
+		Street: "Eavesdown Docks",
+		Planet: "Persphone",
+		Phone:  "none",
+	}
+
+	user := &User{
+		FirstName:      "Badger",
+		LastName:       "Smith",
+		Age:            135,
+		Email:          "Badger.Smith@gmail.com",
+		FavouriteColor: "#000",
+		Addresses:      []*Address{address},
+	}
+
+	// returns nil or *StructErrors
+	errs := validate.Struct(user)
+
+	if errs != nil {
+
+		// err will be of type *FieldError
+		err := errs.Errors["Age"]
+		fmt.Println(err.Error()) // output: Field validation for "Age" failed on the "lte" tag
+		fmt.Println(err.Field)   // output: Age
+		fmt.Println(err.Tag)     // output: lte
+		fmt.Println(err.Kind)    // output: uint8
+		fmt.Println(err.Type)    // output: uint8
+		fmt.Println(err.Param)   // output: 130
+		fmt.Println(err.Value)   // output: 135
+
+		// or if you prefer you can use the Flatten function
+		// NOTE: I find this usefull when using a more hard static approach of checking field errors.
+		// The above, is best for passing to some generic code to say parse the errors. i.e. I pass errs
+		// to a routine which loops through the errors, creates and translates the error message into the
+		// users locale and returns a map of map[string]string // field and error which I then use
+		// within the HTML rendering.
+
+		flat := errs.Flatten()
+		fmt.Println(flat) // output: map[Age:Field validation for "Age" failed on the "lte" tag Addresses[0].Address.City:Field validation for "City" failed on the "required" tag]
+		err = flat["Addresses[0].Address.City"]
+		fmt.Println(err.Field) // output: City
+		fmt.Println(err.Tag)   // output: required
+		fmt.Println(err.Kind)  // output: string
+		fmt.Println(err.Type)  // output: string
+		fmt.Println(err.Param) // output:
+		fmt.Println(err.Value) // output:
+
+		// from here you can create your own error messages in whatever language you wish
+		return
+	}
+
+	// save user to database
+}
+```
 
-Please see http://godoc.org/gopkg.in/bluesuncorp/validator.v5 for detailed usage docs.
+Benchmarks
+------
+###### Run on MacBook Pro (Retina, 15-inch, Late 2013) 2.6 GHz Intel Core i7 16 GB 1600 MHz DDR3
+```go
+$ go test -cpu=4 -bench=. -benchmem=true
+PASS
+BenchmarkValidateField-4	 		 3000000	       429 ns/op	     192 B/op	       2 allocs/op
+BenchmarkValidateStructSimple-4	  	  500000	      2877 ns/op	     657 B/op	      10 allocs/op
+BenchmarkTemplateParallelSimple-4	  500000	      3097 ns/op	     657 B/op	      10 allocs/op
+BenchmarkValidateStructLarge-4	  	  100000	     15228 ns/op	    4350 B/op	      62 allocs/op
+BenchmarkTemplateParallelLarge-4	  100000	     14257 ns/op	    4354 B/op	      62 allocs/op
+```
 
 How to Contribute
-=================
+------
 
 There will always be a development branch for each version i.e. `v1-development`. In order to contribute, 
 please make your pull requests against those branches.
@@ -40,5 +150,5 @@ I strongly encourage everyone whom creates a custom validation function to contr
 help make this package even better.
 
 License
-=======
+------
 Distributed under MIT License, please see license file in code for more details.
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/baked_in.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/baked_in.go
index 22746adae10d34f704f7cc9f63203de3264bc4ec..82868ccfd0f09d83819f9d23b86eae002a2e8ce0 100644
--- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/baked_in.go
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/baked_in.go
@@ -424,10 +424,12 @@ func hasValue(top interface{}, current interface{}, field interface{}, param str
 	st := reflect.ValueOf(field)
 
 	switch st.Kind() {
-
-	case reflect.Slice, reflect.Map, reflect.Array:
-		return field != nil && int64(st.Len()) > 0
-
+	case reflect.Invalid:
+		return false
+	case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
+		return !st.IsNil()
+	case reflect.Array:
+		return field != reflect.Zero(reflect.TypeOf(field)).Interface()
 	default:
 		return field != nil && field != reflect.Zero(reflect.TypeOf(field)).Interface()
 	}
@@ -592,7 +594,7 @@ func isGte(top interface{}, current interface{}, field interface{}, param string
 	case reflect.String:
 		p := asInt(param)
 
-		return int64(len(st.String())) >= p
+		return int64(utf8.RuneCountInString(st.String())) >= p
 
 	case reflect.Slice, reflect.Map, reflect.Array:
 		p := asInt(param)
@@ -637,7 +639,7 @@ func isGt(top interface{}, current interface{}, field interface{}, param string)
 	case reflect.String:
 		p := asInt(param)
 
-		return int64(len(st.String())) > p
+		return int64(utf8.RuneCountInString(st.String())) > p
 
 	case reflect.Slice, reflect.Map, reflect.Array:
 		p := asInt(param)
@@ -681,7 +683,7 @@ func hasLengthOf(top interface{}, current interface{}, field interface{}, param
 	case reflect.String:
 		p := asInt(param)
 
-		return int64(len(st.String())) == p
+		return int64(utf8.RuneCountInString(st.String())) == p
 
 	case reflect.Slice, reflect.Map, reflect.Array:
 		p := asInt(param)
@@ -875,7 +877,7 @@ func isLte(top interface{}, current interface{}, field interface{}, param string
 	case reflect.String:
 		p := asInt(param)
 
-		return int64(len(st.String())) <= p
+		return int64(utf8.RuneCountInString(st.String())) <= p
 
 	case reflect.Slice, reflect.Map, reflect.Array:
 		p := asInt(param)
@@ -920,7 +922,7 @@ func isLt(top interface{}, current interface{}, field interface{}, param string)
 	case reflect.String:
 		p := asInt(param)
 
-		return int64(len(st.String())) < p
+		return int64(utf8.RuneCountInString(st.String())) < p
 
 	case reflect.Slice, reflect.Map, reflect.Array:
 		p := asInt(param)
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/benchmarks_test.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/benchmarks_test.go
index 25172092b937f1c26596c7adc7551f82bef5fcd8..ee836c288be215917335d3ddb28914e3f3b2426a 100644
--- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/benchmarks_test.go
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/benchmarks_test.go
@@ -24,23 +24,23 @@ func BenchmarkValidateStructSimple(b *testing.B) {
 	}
 }
 
-// func BenchmarkTemplateParallelSimple(b *testing.B) {
+func BenchmarkTemplateParallelSimple(b *testing.B) {
 
-// 	type Foo struct {
-// 		StringValue string `validate:"min=5,max=10"`
-// 		IntValue    int    `validate:"min=5,max=10"`
-// 	}
+	type Foo struct {
+		StringValue string `validate:"min=5,max=10"`
+		IntValue    int    `validate:"min=5,max=10"`
+	}
 
-// 	validFoo := &Foo{StringValue: "Foobar", IntValue: 7}
-// 	invalidFoo := &Foo{StringValue: "Fo", IntValue: 3}
+	validFoo := &Foo{StringValue: "Foobar", IntValue: 7}
+	invalidFoo := &Foo{StringValue: "Fo", IntValue: 3}
 
-// 	b.RunParallel(func(pb *testing.PB) {
-// 		for pb.Next() {
-// 			validate.Struct(validFoo)
-// 			validate.Struct(invalidFoo)
-// 		}
-// 	})
-// }
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			validate.Struct(validFoo)
+			validate.Struct(invalidFoo)
+		}
+	})
+}
 
 func BenchmarkValidateStructLarge(b *testing.B) {
 
@@ -101,63 +101,63 @@ func BenchmarkValidateStructLarge(b *testing.B) {
 	}
 }
 
-// func BenchmarkTemplateParallelLarge(b *testing.B) {
-
-// 	tFail := &TestString{
-// 		Required:  "",
-// 		Len:       "",
-// 		Min:       "",
-// 		Max:       "12345678901",
-// 		MinMax:    "",
-// 		Lt:        "0123456789",
-// 		Lte:       "01234567890",
-// 		Gt:        "1",
-// 		Gte:       "1",
-// 		OmitEmpty: "12345678901",
-// 		Sub: &SubTest{
-// 			Test: "",
-// 		},
-// 		Anonymous: struct {
-// 			A string `validate:"required"`
-// 		}{
-// 			A: "",
-// 		},
-// 		Iface: &Impl{
-// 			F: "12",
-// 		},
-// 	}
-
-// 	tSuccess := &TestString{
-// 		Required:  "Required",
-// 		Len:       "length==10",
-// 		Min:       "min=1",
-// 		Max:       "1234567890",
-// 		MinMax:    "12345",
-// 		Lt:        "012345678",
-// 		Lte:       "0123456789",
-// 		Gt:        "01234567890",
-// 		Gte:       "0123456789",
-// 		OmitEmpty: "",
-// 		Sub: &SubTest{
-// 			Test: "1",
-// 		},
-// 		SubIgnore: &SubTest{
-// 			Test: "",
-// 		},
-// 		Anonymous: struct {
-// 			A string `validate:"required"`
-// 		}{
-// 			A: "1",
-// 		},
-// 		Iface: &Impl{
-// 			F: "123",
-// 		},
-// 	}
-
-// 	b.RunParallel(func(pb *testing.PB) {
-// 		for pb.Next() {
-// 			validate.Struct(tSuccess)
-// 			validate.Struct(tFail)
-// 		}
-// 	})
-// }
+func BenchmarkTemplateParallelLarge(b *testing.B) {
+
+	tFail := &TestString{
+		Required:  "",
+		Len:       "",
+		Min:       "",
+		Max:       "12345678901",
+		MinMax:    "",
+		Lt:        "0123456789",
+		Lte:       "01234567890",
+		Gt:        "1",
+		Gte:       "1",
+		OmitEmpty: "12345678901",
+		Sub: &SubTest{
+			Test: "",
+		},
+		Anonymous: struct {
+			A string `validate:"required"`
+		}{
+			A: "",
+		},
+		Iface: &Impl{
+			F: "12",
+		},
+	}
+
+	tSuccess := &TestString{
+		Required:  "Required",
+		Len:       "length==10",
+		Min:       "min=1",
+		Max:       "1234567890",
+		MinMax:    "12345",
+		Lt:        "012345678",
+		Lte:       "0123456789",
+		Gt:        "01234567890",
+		Gte:       "0123456789",
+		OmitEmpty: "",
+		Sub: &SubTest{
+			Test: "1",
+		},
+		SubIgnore: &SubTest{
+			Test: "",
+		},
+		Anonymous: struct {
+			A string `validate:"required"`
+		}{
+			A: "1",
+		},
+		Iface: &Impl{
+			F: "123",
+		},
+	}
+
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			validate.Struct(tSuccess)
+			validate.Struct(tFail)
+		}
+	})
+}
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/doc.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/doc.go
index 89142e0751e120d75529a1fd6c785ede43ab057d..74db756f954c5304994be5ed36a62dee4d1f229d 100644
--- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/doc.go
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/doc.go
@@ -167,16 +167,44 @@ Here is a list of the current built in validators:
 		inside of you program you know the struct will be valid, but need to
 		verify it has been assigned.
 
+	exists
+		Is a special tag without a validation function attached. It is used when a field
+		is a Pointer, Interface or Invalid and you wish to validate that it exists.
+		Example: want to ensure a bool exists if you define the bool as a pointer and
+		use exists it will ensure there is a value; couldn't use required as it would
+		fail when the bool was false. exists will fail is the value is a Pointer, Interface
+		or Invalid and is nil. (Usage: exists)
+
 	omitempty
 		Allows conditional validation, for example if a field is not set with
 		a value (Determined by the required validator) then other validation
 		such as min or max won't run, but if a value is set validation will run.
 		(Usage: omitempty)
 
+	dive
+		This tells the validator to dive into a slice, array or map and validate that
+		level of the slice, array or map with the validation tags that follow.
+		Multidimensional nesting is also supported, each level you wish to dive will
+		require another dive tag. (Usage: dive)
+		Example: [][]string with validation tag "gt=0,dive,len=1,dive,required"
+		gt=0 will be applied to []
+		len=1 will be applied to []string
+		required will be applied to string
+		Example2: [][]string with validation tag "gt=0,dive,dive,required"
+		gt=0 will be applied to []
+		[]string will be spared validation
+		required will be applied to string
+		NOTE: in Example2 if the required validation failed, but all others passed
+		the hierarchy of FieldError's in the middle with have their IsPlaceHolder field
+		set to true. If a FieldError has IsSliceOrMap=true or IsMap=true then the
+		FieldError is a Slice or Map field and if IsPlaceHolder=true then contains errors
+		within its SliceOrArrayErrs or MapErrs fields.
+
 	required
-		This validates that the value is not the data types default value.
+		This validates that the value is not the data types default zero value.
 		For numbers ensures value is not zero. For strings ensures value is
-		not "". For slices, arrays, and maps, ensures the length is not zero.
+		not "". For slices, maps, pointers, interfaces, channels and functions
+		ensures the value is not nil.
 		(Usage: required)
 
 	len
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/examples_test.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/examples_test.go
index c5dd3517d1812ba8559a31783860971df2079555..0acdaa0c2d35a7ead14e7f02e846dd36bd2ea2f1 100644
--- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/examples_test.go
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/examples_test.go
@@ -3,7 +3,7 @@ package validator_test
 import (
 	"fmt"
 
-	"../validator"
+	"gopkg.in/go-playground/validator.v5"
 )
 
 func ExampleValidate_new() {
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator.go
index 5f0c18afa0100c890106b93a0ffa307dc6ec25d4..f195647baed6d1d24c03f8c0c9259cd1b654c74d 100644
--- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator.go
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator.go
@@ -20,56 +20,31 @@ import (
 )
 
 const (
-	utf8HexComma    = "0x2C"
-	tagSeparator    = ","
-	orSeparator     = "|"
-	noValidationTag = "-"
-	tagKeySeparator = "="
-	structOnlyTag   = "structonly"
-	omitempty       = "omitempty"
-	fieldErrMsg     = "Field validation for \"%s\" failed on the \"%s\" tag"
-	structErrMsg    = "Struct:%s\n"
+	utf8HexComma        = "0x2C"
+	tagSeparator        = ","
+	orSeparator         = "|"
+	noValidationTag     = "-"
+	tagKeySeparator     = "="
+	structOnlyTag       = "structonly"
+	omitempty           = "omitempty"
+	required            = "required"
+	fieldErrMsg         = "Field validation for \"%s\" failed on the \"%s\" tag"
+	sliceErrMsg         = "Field validation for \"%s\" failed at index \"%d\" with error(s): %s"
+	mapErrMsg           = "Field validation for \"%s\" failed on key \"%v\" with error(s): %s"
+	structErrMsg        = "Struct:%s\n"
+	diveTag             = "dive"
+	existsTag           = "exists"
+	arrayIndexFieldName = "%s[%d]"
+	mapIndexFieldName   = "%s[%v]"
 )
 
-var structPool *pool
+var structPool *sync.Pool
 
-// Pool holds a channelStructErrors.
-type pool struct {
-	pool chan *StructErrors
-}
-
-// NewPool creates a new pool of Clients.
-func newPool(max int) *pool {
-	return &pool{
-		pool: make(chan *StructErrors, max),
-	}
-}
-
-// Borrow a StructErrors from the pool.
-func (p *pool) Borrow() *StructErrors {
-	var c *StructErrors
-
-	select {
-	case c = <-p.pool:
-	default:
-		c = &StructErrors{
-			Errors:       map[string]*FieldError{},
-			StructErrors: map[string]*StructErrors{},
-		}
-	}
-
-	return c
-}
-
-// Return returns a StructErrors to the pool.
-func (p *pool) Return(c *StructErrors) {
-
-	// c.Struct = ""
-
-	select {
-	case p.pool <- c:
-	default:
-		// let it go, let it go...
+// returns new *StructErrors to the pool
+func newStructErrors() interface{} {
+	return &StructErrors{
+		Errors:       map[string]*FieldError{},
+		StructErrors: map[string]*StructErrors{},
 	}
 }
 
@@ -79,13 +54,22 @@ type cachedTags struct {
 }
 
 type cachedField struct {
-	index  int
-	name   string
-	tags   []*cachedTags
-	tag    string
-	kind   reflect.Kind
-	typ    reflect.Type
-	isTime bool
+	index          int
+	name           string
+	tags           []*cachedTags
+	tag            string
+	kind           reflect.Kind
+	typ            reflect.Type
+	isTime         bool
+	isSliceOrArray bool
+	isMap          bool
+	isTimeSubtype  bool
+	sliceSubtype   reflect.Type
+	mapSubtype     reflect.Type
+	sliceSubKind   reflect.Kind
+	mapSubKind     reflect.Kind
+	dive           bool
+	diveTag        string
 }
 
 type cachedStruct struct {
@@ -138,20 +122,123 @@ var fieldsCache = &fieldsCacheMap{m: map[string][]*cachedTags{}}
 // FieldError contains a single field's validation error along
 // with other properties that may be needed for error message creation
 type FieldError struct {
-	Field string
-	Tag   string
-	Kind  reflect.Kind
-	Type  reflect.Type
-	Param string
-	Value interface{}
+	Field            string
+	Tag              string
+	Kind             reflect.Kind
+	Type             reflect.Type
+	Param            string
+	Value            interface{}
+	IsPlaceholderErr bool
+	IsSliceOrArray   bool
+	IsMap            bool
+	SliceOrArrayErrs map[int]error         // counld be FieldError, StructErrors
+	MapErrs          map[interface{}]error // counld be FieldError, StructErrors
 }
 
 // This is intended for use in development + debugging and not intended to be a production error message.
 // it also allows FieldError to be used as an Error interface
 func (e *FieldError) Error() string {
+
+	if e.IsPlaceholderErr {
+
+		buff := bytes.NewBufferString("")
+
+		if e.IsSliceOrArray {
+
+			for j, err := range e.SliceOrArrayErrs {
+				buff.WriteString("\n")
+				buff.WriteString(fmt.Sprintf(sliceErrMsg, e.Field, j, "\n"+err.Error()))
+			}
+
+		} else if e.IsMap {
+
+			for key, err := range e.MapErrs {
+				buff.WriteString(fmt.Sprintf(mapErrMsg, e.Field, key, "\n"+err.Error()))
+			}
+		}
+
+		return strings.TrimSpace(buff.String())
+	}
+
 	return fmt.Sprintf(fieldErrMsg, e.Field, e.Tag)
 }
 
+// Flatten flattens the FieldError hierarchical structure into a flat namespace style field name
+// for those that want/need it.
+// This is now needed because of the new dive functionality
+func (e *FieldError) Flatten() map[string]*FieldError {
+
+	errs := map[string]*FieldError{}
+
+	if e.IsPlaceholderErr {
+
+		if e.IsSliceOrArray {
+			for key, err := range e.SliceOrArrayErrs {
+
+				fe, ok := err.(*FieldError)
+
+				if ok {
+
+					if flat := fe.Flatten(); flat != nil && len(flat) > 0 {
+						for k, v := range flat {
+							if fe.IsPlaceholderErr {
+								errs[fmt.Sprintf("[%#v]%s", key, k)] = v
+							} else {
+								errs[fmt.Sprintf("[%#v]", key)] = v
+							}
+
+						}
+					}
+				} else {
+
+					se := err.(*StructErrors)
+
+					if flat := se.Flatten(); flat != nil && len(flat) > 0 {
+						for k, v := range flat {
+							errs[fmt.Sprintf("[%#v].%s.%s", key, se.Struct, k)] = v
+						}
+					}
+				}
+			}
+		}
+
+		if e.IsMap {
+			for key, err := range e.MapErrs {
+
+				fe, ok := err.(*FieldError)
+
+				if ok {
+
+					if flat := fe.Flatten(); flat != nil && len(flat) > 0 {
+						for k, v := range flat {
+							if fe.IsPlaceholderErr {
+								errs[fmt.Sprintf("[%#v]%s", key, k)] = v
+							} else {
+								errs[fmt.Sprintf("[%#v]", key)] = v
+							}
+						}
+					}
+				} else {
+
+					se := err.(*StructErrors)
+
+					if flat := se.Flatten(); flat != nil && len(flat) > 0 {
+						for k, v := range flat {
+							errs[fmt.Sprintf("[%#v].%s.%s", key, se.Struct, k)] = v
+						}
+					}
+				}
+			}
+		}
+
+		return errs
+	}
+
+	errs[e.Field] = e
+
+	return errs
+}
+
 // StructErrors is hierarchical list of field and struct validation errors
 // for a non hierarchical representation please see the Flatten method for StructErrors
 type StructErrors struct {
@@ -178,7 +265,7 @@ func (e *StructErrors) Error() string {
 		buff.WriteString(err.Error())
 	}
 
-	return buff.String()
+	return strings.TrimSpace(buff.String())
 }
 
 // Flatten flattens the StructErrors hierarchical structure into a flat namespace style field name
@@ -193,7 +280,17 @@ func (e *StructErrors) Flatten() map[string]*FieldError {
 
 	for _, f := range e.Errors {
 
-		errs[f.Field] = f
+		if flat := f.Flatten(); flat != nil && len(flat) > 0 {
+
+			for k, fe := range flat {
+
+				if f.IsPlaceholderErr {
+					errs[f.Field+k] = fe
+				} else {
+					errs[k] = fe
+				}
+			}
+		}
 	}
 
 	for key, val := range e.StructErrors {
@@ -231,7 +328,7 @@ type Validate struct {
 // New creates a new Validate instance for use.
 func New(tagName string, funcs map[string]Func) *Validate {
 
-	structPool = newPool(10)
+	structPool = &sync.Pool{New: newStructErrors}
 
 	return &Validate{
 		tagName:         tagName,
@@ -251,9 +348,8 @@ func (v *Validate) SetTag(tagName string) {
 // nearly all cases. only increase if you have a deeply nested struct structure.
 // NOTE: this method is not thread-safe
 // NOTE: this is only here to keep compatibility with v5, in v6 the method will be removed
-// and the max pool size will be passed into the New function
 func (v *Validate) SetMaxStructPoolSize(max int) {
-	structPool = newPool(max)
+	structPool = &sync.Pool{New: newStructErrors}
 }
 
 // AddFunction adds a validation Func to a Validate's map of validators denoted by the key
@@ -312,10 +408,9 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
 		structName = structType.Name()
 		numFields = structValue.NumField()
 		cs = &cachedStruct{name: structName, children: numFields}
-		structCache.Set(structType, cs)
 	}
 
-	validationErrors := structPool.Borrow()
+	validationErrors := structPool.Get().(*StructErrors)
 	validationErrors.Struct = structName
 
 	for i := 0; i < numFields; i++ {
@@ -340,7 +435,7 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
 
 			typeField = structType.Field(i)
 
-			cField = &cachedField{index: i, tag: typeField.Tag.Get(v.tagName)}
+			cField = &cachedField{index: i, tag: typeField.Tag.Get(v.tagName), isTime: (valueField.Type() == reflect.TypeOf(time.Time{}) || valueField.Type() == reflect.TypeOf(&time.Time{}))}
 
 			if cField.tag == noValidationTag {
 				cs.children--
@@ -373,9 +468,7 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
 				continue
 			}
 
-			if cField.isTime || valueField.Type() == reflect.TypeOf(time.Time{}) {
-
-				cField.isTime = true
+			if cField.isTime {
 
 				if fieldError := v.fieldWithNameAndValue(top, current, valueField.Interface(), cField.tag, cField.name, false, cField); fieldError != nil {
 					validationErrors.Errors[fieldError.Field] = fieldError
@@ -390,6 +483,62 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
 					continue
 				}
 
+				if (valueField.Kind() == reflect.Ptr || cField.kind == reflect.Interface) && valueField.IsNil() {
+
+					if strings.Contains(cField.tag, omitempty) {
+						goto CACHEFIELD
+					}
+
+					tags := strings.Split(cField.tag, tagSeparator)
+
+					if len(tags) > 0 {
+
+						var param string
+						vals := strings.SplitN(tags[0], tagKeySeparator, 2)
+
+						if len(vals) > 1 {
+							param = vals[1]
+						}
+
+						validationErrors.Errors[cField.name] = &FieldError{
+							Field: cField.name,
+							Tag:   vals[0],
+							Param: param,
+							Value: valueField.Interface(),
+							Kind:  valueField.Kind(),
+							Type:  valueField.Type(),
+						}
+
+						goto CACHEFIELD
+					}
+				}
+
+				// if we get here, the field is interface and could be a struct or a field
+				// and we need to check the inner type and validate
+				if cField.kind == reflect.Interface {
+
+					valueField = valueField.Elem()
+
+					if valueField.Kind() == reflect.Ptr && !valueField.IsNil() {
+						valueField = valueField.Elem()
+					}
+
+					if valueField.Kind() == reflect.Struct {
+						goto VALIDATESTRUCT
+					}
+
+					// sending nil for cField as it was type interface and could be anything
+					// each time and so must be calculated each time and can't be cached reliably
+					if fieldError := v.fieldWithNameAndValue(top, current, valueField.Interface(), cField.tag, cField.name, false, nil); fieldError != nil {
+						validationErrors.Errors[fieldError.Field] = fieldError
+						// free up memory reference
+						fieldError = nil
+					}
+
+					goto CACHEFIELD
+				}
+
+			VALIDATESTRUCT:
 				if structErrors := v.structRecursive(top, valueField.Interface(), valueField.Interface()); structErrors != nil {
 					validationErrors.StructErrors[cField.name] = structErrors
 					// free up memory map no longer needed
@@ -397,22 +546,48 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
 				}
 			}
 
-		default:
+		case reflect.Slice, reflect.Array:
+			cField.isSliceOrArray = true
+			cField.sliceSubtype = cField.typ.Elem()
+			cField.isTimeSubtype = (cField.sliceSubtype == reflect.TypeOf(time.Time{}) || cField.sliceSubtype == reflect.TypeOf(&time.Time{}))
+			cField.sliceSubKind = cField.sliceSubtype.Kind()
 
 			if fieldError := v.fieldWithNameAndValue(top, current, valueField.Interface(), cField.tag, cField.name, false, cField); fieldError != nil {
 				validationErrors.Errors[fieldError.Field] = fieldError
 				// free up memory reference
 				fieldError = nil
 			}
+
+		case reflect.Map:
+			cField.isMap = true
+			cField.mapSubtype = cField.typ.Elem()
+			cField.isTimeSubtype = (cField.mapSubtype == reflect.TypeOf(time.Time{}) || cField.mapSubtype == reflect.TypeOf(&time.Time{}))
+			cField.mapSubKind = cField.mapSubtype.Kind()
+
+			if fieldError := v.fieldWithNameAndValue(top, current, valueField.Interface(), cField.tag, cField.name, false, cField); fieldError != nil {
+				validationErrors.Errors[fieldError.Field] = fieldError
+				// free up memory reference
+				fieldError = nil
+			}
+
+		default:
+			if fieldError := v.fieldWithNameAndValue(top, current, valueField.Interface(), cField.tag, cField.name, false, cField); fieldError != nil {
+				validationErrors.Errors[fieldError.Field] = fieldError
+				// free up memory reference
+				fieldError = nil
+			}
 		}
 
+	CACHEFIELD:
 		if !isCached {
 			cs.fields = append(cs.fields, cField)
 		}
 	}
 
+	structCache.Set(structType, cs)
+
 	if len(validationErrors.Errors) == 0 && len(validationErrors.StructErrors) == 0 {
-		structPool.Return(validationErrors)
+		structPool.Put(validationErrors)
 		return nil
 	}
 
@@ -421,13 +596,11 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
 
 // Field allows validation of a single field, still using tag style validation to check multiple errors
 func (v *Validate) Field(f interface{}, tag string) *FieldError {
-
 	return v.FieldWithValue(nil, f, tag)
 }
 
 // FieldWithValue allows validation of a single field, possibly even against another fields value, still using tag style validation to check multiple errors
 func (v *Validate) FieldWithValue(val interface{}, f interface{}, tag string) *FieldError {
-
 	return v.fieldWithNameAndValue(nil, val, f, tag, "", true, nil)
 }
 
@@ -435,9 +608,10 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f
 
 	var cField *cachedField
 	var isCached bool
+	var valueField reflect.Value
 
 	// This is a double check if coming from validate.Struct but need to be here in case function is called directly
-	if tag == noValidationTag {
+	if tag == noValidationTag || tag == "" {
 		return nil
 	}
 
@@ -445,25 +619,51 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f
 		return nil
 	}
 
+	valueField = reflect.ValueOf(f)
+
 	if cacheField == nil {
-		valueField := reflect.ValueOf(f)
 
 		if valueField.Kind() == reflect.Ptr && !valueField.IsNil() {
 			valueField = valueField.Elem()
 			f = valueField.Interface()
 		}
 
-		cField = &cachedField{name: name, kind: valueField.Kind(), tag: tag, typ: valueField.Type()}
+		cField = &cachedField{name: name, kind: valueField.Kind(), tag: tag}
+
+		if cField.kind != reflect.Invalid {
+			cField.typ = valueField.Type()
+		}
+
+		switch cField.kind {
+		case reflect.Slice, reflect.Array:
+			isSingleField = false // cached tags mean nothing because it will be split up while diving
+			cField.isSliceOrArray = true
+			cField.sliceSubtype = cField.typ.Elem()
+			cField.isTimeSubtype = (cField.sliceSubtype == reflect.TypeOf(time.Time{}) || cField.sliceSubtype == reflect.TypeOf(&time.Time{}))
+			cField.sliceSubKind = cField.sliceSubtype.Kind()
+		case reflect.Map:
+			isSingleField = false // cached tags mean nothing because it will be split up while diving
+			cField.isMap = true
+			cField.mapSubtype = cField.typ.Elem()
+			cField.isTimeSubtype = (cField.mapSubtype == reflect.TypeOf(time.Time{}) || cField.mapSubtype == reflect.TypeOf(&time.Time{}))
+			cField.mapSubKind = cField.mapSubtype.Kind()
+		}
 	} else {
 		cField = cacheField
 	}
 
 	switch cField.kind {
+	case reflect.Invalid:
+		return &FieldError{
+			Field: cField.name,
+			Tag:   cField.tag,
+			Kind:  cField.kind,
+		}
 
-	case reflect.Struct, reflect.Interface, reflect.Invalid:
+	case reflect.Struct, reflect.Interface:
 
 		if cField.typ != reflect.TypeOf(time.Time{}) {
-			panic("Invalid field passed to ValidateFieldWithTag")
+			panic("Invalid field passed to fieldWithNameAndValue")
 		}
 	}
 
@@ -477,6 +677,13 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f
 
 			for _, t := range strings.Split(tag, tagSeparator) {
 
+				if t == diveTag {
+
+					cField.dive = true
+					cField.diveTag = strings.TrimLeft(strings.SplitN(tag, diveTag, 2)[1], ",")
+					break
+				}
+
 				orVals := strings.Split(t, orSeparator)
 				cTag := &cachedTags{isOrVal: len(orVals) > 1, keyVals: make([][]string, len(orVals))}
 				cField.tags = append(cField.tags, cTag)
@@ -516,7 +723,22 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f
 
 			for _, val := range cTag.keyVals {
 
+				// if (idxField.Kind() == reflect.Ptr || idxField.Kind() == reflect.Interface) && idxField.IsNil() {
+				// if val[0] == existsTag {
+				// 	if (cField.kind == reflect.Ptr || cField.kind == reflect.Interface) && valueField.IsNil() {
+				// 		fieldErr = &FieldError{
+				// 			Field: name,
+				// 			Tag:   val[0],
+				// 			Value: f,
+				// 			Param: val[1],
+				// 		}
+				// 		err = errors.New(fieldErr.Tag)
+				// 	}
+
+				// } else {
+
 				fieldErr, err = v.fieldWithNameAndSingleTag(val, current, f, val[0], val[1], name)
+				// }
 
 				if err == nil {
 					return nil
@@ -534,6 +756,18 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f
 			return fieldErr
 		}
 
+		if cTag.keyVals[0][0] == existsTag {
+			if (cField.kind == reflect.Ptr || cField.kind == reflect.Interface) && valueField.IsNil() {
+				return &FieldError{
+					Field: name,
+					Tag:   cTag.keyVals[0][0],
+					Value: f,
+					Param: cTag.keyVals[0][1],
+				}
+			}
+			continue
+		}
+
 		if fieldErr, err = v.fieldWithNameAndSingleTag(val, current, f, cTag.keyVals[0][0], cTag.keyVals[0][1], name); err != nil {
 
 			fieldErr.Kind = cField.kind
@@ -543,9 +777,231 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f
 		}
 	}
 
+	if cField.dive {
+
+		if cField.isSliceOrArray {
+
+			if errs := v.traverseSliceOrArray(val, current, valueField, cField); errs != nil && len(errs) > 0 {
+
+				return &FieldError{
+					Field:            cField.name,
+					Kind:             cField.kind,
+					Type:             cField.typ,
+					Value:            f,
+					IsPlaceholderErr: true,
+					IsSliceOrArray:   true,
+					SliceOrArrayErrs: errs,
+				}
+			}
+
+		} else if cField.isMap {
+			if errs := v.traverseMap(val, current, valueField, cField); errs != nil && len(errs) > 0 {
+
+				return &FieldError{
+					Field:            cField.name,
+					Kind:             cField.kind,
+					Type:             cField.typ,
+					Value:            f,
+					IsPlaceholderErr: true,
+					IsMap:            true,
+					MapErrs:          errs,
+				}
+			}
+		} else {
+			// throw error, if not a slice or map then should not have gotten here
+			panic("dive error! can't dive on a non slice or map")
+		}
+	}
+
 	return nil
 }
 
+func (v *Validate) traverseMap(val interface{}, current interface{}, valueField reflect.Value, cField *cachedField) map[interface{}]error {
+
+	errs := map[interface{}]error{}
+
+	for _, key := range valueField.MapKeys() {
+
+		idxField := valueField.MapIndex(key)
+
+		if cField.mapSubKind == reflect.Ptr && !idxField.IsNil() {
+			idxField = idxField.Elem()
+			cField.mapSubKind = idxField.Kind()
+		}
+
+		switch cField.mapSubKind {
+		case reflect.Struct, reflect.Interface:
+
+			if cField.isTimeSubtype {
+
+				if fieldError := v.fieldWithNameAndValue(val, current, idxField.Interface(), cField.diveTag, fmt.Sprintf(mapIndexFieldName, cField.name, key.Interface()), false, nil); fieldError != nil {
+					errs[key.Interface()] = fieldError
+				}
+
+				continue
+			}
+
+			if (idxField.Kind() == reflect.Ptr || idxField.Kind() == reflect.Interface) && idxField.IsNil() {
+
+				if strings.Contains(cField.diveTag, omitempty) {
+					continue
+				}
+
+				tags := strings.Split(cField.diveTag, tagSeparator)
+
+				if len(tags) > 0 {
+
+					var param string
+					vals := strings.SplitN(tags[0], tagKeySeparator, 2)
+
+					if len(vals) > 1 {
+						param = vals[1]
+					}
+
+					errs[key.Interface()] = &FieldError{
+						Field: fmt.Sprintf(mapIndexFieldName, cField.name, key.Interface()),
+						Tag:   vals[0],
+						Param: param,
+						Value: idxField.Interface(),
+						Kind:  idxField.Kind(),
+						Type:  cField.mapSubtype,
+					}
+				}
+
+				continue
+			}
+
+			// if we get here, the field is interface and could be a struct or a field
+			// and we need to check the inner type and validate
+			if idxField.Kind() == reflect.Interface {
+
+				idxField = idxField.Elem()
+
+				if idxField.Kind() == reflect.Ptr && !idxField.IsNil() {
+					idxField = idxField.Elem()
+				}
+
+				if idxField.Kind() == reflect.Struct {
+					goto VALIDATESTRUCT
+				}
+
+				// sending nil for cField as it was type interface and could be anything
+				// each time and so must be calculated each time and can't be cached reliably
+				if fieldError := v.fieldWithNameAndValue(val, current, idxField.Interface(), cField.diveTag, fmt.Sprintf(mapIndexFieldName, cField.name, key.Interface()), false, nil); fieldError != nil {
+					errs[key.Interface()] = fieldError
+				}
+
+				continue
+			}
+
+		VALIDATESTRUCT:
+			if structErrors := v.structRecursive(val, current, idxField.Interface()); structErrors != nil {
+				errs[key.Interface()] = structErrors
+			}
+
+		default:
+			if fieldError := v.fieldWithNameAndValue(val, current, idxField.Interface(), cField.diveTag, fmt.Sprintf(mapIndexFieldName, cField.name, key.Interface()), false, nil); fieldError != nil {
+				errs[key.Interface()] = fieldError
+			}
+		}
+	}
+
+	return errs
+}
+
+func (v *Validate) traverseSliceOrArray(val interface{}, current interface{}, valueField reflect.Value, cField *cachedField) map[int]error {
+
+	errs := map[int]error{}
+
+	for i := 0; i < valueField.Len(); i++ {
+
+		idxField := valueField.Index(i)
+
+		if cField.sliceSubKind == reflect.Ptr && !idxField.IsNil() {
+			idxField = idxField.Elem()
+			cField.sliceSubKind = idxField.Kind()
+		}
+
+		switch cField.sliceSubKind {
+		case reflect.Struct, reflect.Interface:
+
+			if cField.isTimeSubtype {
+
+				if fieldError := v.fieldWithNameAndValue(val, current, idxField.Interface(), cField.diveTag, fmt.Sprintf(arrayIndexFieldName, cField.name, i), false, nil); fieldError != nil {
+					errs[i] = fieldError
+				}
+
+				continue
+			}
+
+			if (idxField.Kind() == reflect.Ptr || idxField.Kind() == reflect.Interface) && idxField.IsNil() {
+
+				if strings.Contains(cField.diveTag, omitempty) {
+					continue
+				}
+
+				tags := strings.Split(cField.diveTag, tagSeparator)
+
+				if len(tags) > 0 {
+
+					var param string
+					vals := strings.SplitN(tags[0], tagKeySeparator, 2)
+
+					if len(vals) > 1 {
+						param = vals[1]
+					}
+
+					errs[i] = &FieldError{
+						Field: fmt.Sprintf(arrayIndexFieldName, cField.name, i),
+						Tag:   vals[0],
+						Param: param,
+						Value: idxField.Interface(),
+						Kind:  idxField.Kind(),
+						Type:  cField.sliceSubtype,
+					}
+				}
+
+				continue
+			}
+
+			// if we get here, the field is interface and could be a struct or a field
+			// and we need to check the inner type and validate
+			if idxField.Kind() == reflect.Interface {
+
+				idxField = idxField.Elem()
+
+				if idxField.Kind() == reflect.Ptr && !idxField.IsNil() {
+					idxField = idxField.Elem()
+				}
+
+				if idxField.Kind() == reflect.Struct {
+					goto VALIDATESTRUCT
+				}
+
+				// sending nil for cField as it was type interface and could be anything
+				// each time and so must be calculated each time and can't be cached reliably
+				if fieldError := v.fieldWithNameAndValue(val, current, idxField.Interface(), cField.diveTag, fmt.Sprintf(arrayIndexFieldName, cField.name, i), false, nil); fieldError != nil {
+					errs[i] = fieldError
+				}
+
+				continue
+			}
+
+		VALIDATESTRUCT:
+			if structErrors := v.structRecursive(val, current, idxField.Interface()); structErrors != nil {
+				errs[i] = structErrors
+			}
+
+		default:
+			if fieldError := v.fieldWithNameAndValue(val, current, idxField.Interface(), cField.diveTag, fmt.Sprintf(arrayIndexFieldName, cField.name, i), false, nil); fieldError != nil {
+				errs[i] = fieldError
+			}
+		}
+	}
+
+	return errs
+}
+
 func (v *Validate) fieldWithNameAndSingleTag(val interface{}, current interface{}, f interface{}, key string, param string, name string) (*FieldError, error) {
 
 	// OK to continue because we checked it's existance before getting into this loop
@@ -553,6 +1009,10 @@ func (v *Validate) fieldWithNameAndSingleTag(val interface{}, current interface{
 		return nil, nil
 	}
 
+	// if key == existsTag {
+	// 	continue
+	// }
+
 	valFunc, ok := v.validationFuncs[key]
 	if !ok {
 		panic(fmt.Sprintf("Undefined validation function on field %s", name))
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator_test.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator_test.go
index a2d5394a54ff7fd5ddd4db55ec88ac82ab35795a..0752932e13175ef597a18744612c88c34e687e4e 100644
--- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator_test.go
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator_test.go
@@ -1,6 +1,7 @@
 package validator
 
 import (
+	"encoding/json"
 	"fmt"
 	"path"
 	"reflect"
@@ -14,6 +15,11 @@ import (
 // - Run "gocov test | gocov report" to report on test converage by file
 // - Run "gocov test | gocov annotate -" to report on all code and functions, those ,marked with "MISS" were never called
 //
+// or
+//
+// -- may be a good idea to change to output path to somewherelike /tmp
+// go test -coverprofile cover.out && go tool cover -html=cover.out -o cover.html
+//
 //
 // go test -cpuprofile cpu.out
 // ./validator.test -test.bench=. -test.cpuprofile=cpu.prof
@@ -226,6 +232,1116 @@ func AssertMapFieldError(t *testing.T, s map[string]*FieldError, field string, e
 	EqualSkip(t, 2, val.Tag, expectedTag)
 }
 
+func TestExistsValidation(t *testing.T) {
+
+	jsonText := "{ \"truthiness2\": true }"
+
+	type Thing struct {
+		Truthiness *bool `json:"truthiness" validate:"exists,required"`
+	}
+
+	var ting Thing
+
+	err := json.Unmarshal([]byte(jsonText), &ting)
+	Equal(t, err, nil)
+	NotEqual(t, ting, nil)
+	Equal(t, ting.Truthiness, nil)
+
+	errs := validate.Struct(ting)
+	NotEqual(t, errs, nil)
+	AssertFieldError(t, errs, "Truthiness", "exists")
+
+	jsonText = "{ \"truthiness\": true }"
+
+	err = json.Unmarshal([]byte(jsonText), &ting)
+	Equal(t, err, nil)
+	NotEqual(t, ting, nil)
+	Equal(t, ting.Truthiness, true)
+
+	errs = validate.Struct(ting)
+	Equal(t, errs, nil)
+}
+
+func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) {
+
+	var m map[string]string
+
+	errs := validate.Field(m, "required")
+	NotEqual(t, errs, nil)
+	// AssertError(t, errs, "", "", "required")
+
+	m = map[string]string{}
+	errs = validate.Field(m, "required")
+	Equal(t, errs, nil)
+
+	var arr [5]string
+	errs = validate.Field(arr, "required")
+	NotEqual(t, errs, nil)
+	// AssertError(t, errs, "", "", "required")
+
+	arr[0] = "ok"
+	errs = validate.Field(arr, "required")
+	Equal(t, errs, nil)
+
+	var s []string
+	errs = validate.Field(s, "required")
+	NotEqual(t, errs, nil)
+	// AssertError(t, errs, "", "", "required")
+
+	s = []string{}
+	errs = validate.Field(s, "required")
+	Equal(t, errs, nil)
+
+	var c chan string
+	errs = validate.Field(c, "required")
+	NotEqual(t, errs, nil)
+	// AssertError(t, errs, "", "", "required")
+
+	c = make(chan string)
+	errs = validate.Field(c, "required")
+	Equal(t, errs, nil)
+
+	var tst *int
+	errs = validate.Field(tst, "required")
+	NotEqual(t, errs, nil)
+	// AssertError(t, errs, "", "", "required")
+
+	one := 1
+	tst = &one
+	errs = validate.Field(tst, "required")
+	Equal(t, errs, nil)
+
+	var iface interface{}
+
+	errs = validate.Field(iface, "required")
+	NotEqual(t, errs, nil)
+	// AssertError(t, errs, "", "", "required")
+
+	errs = validate.Field(iface, "omitempty,required")
+	Equal(t, errs, nil)
+
+	errs = validate.Field(iface, "")
+	Equal(t, errs, nil)
+
+	errs = validate.Field(iface, "len=1")
+	NotEqual(t, errs, nil)
+
+	var f func(string)
+
+	errs = validate.Field(f, "required")
+	NotEqual(t, errs, nil)
+	// AssertError(t, errs, "", "", "required")
+
+	f = func(name string) {}
+
+	errs = validate.Field(f, "required")
+	Equal(t, errs, nil)
+}
+
+func TestBadKeyValidation(t *testing.T) {
+	type Test struct {
+		Name string `validate:"required, "`
+	}
+
+	tst := &Test{
+		Name: "test",
+	}
+
+	PanicMatches(t, func() { validate.Struct(tst) }, "Invalid validation tag on field Name")
+}
+
+func TestFlattenValidation(t *testing.T) {
+
+	type Inner struct {
+		Name string `validate:"required"`
+	}
+
+	type TestMultiDimensionalStructsPtr struct {
+		Errs [][]*Inner `validate:"gt=0,dive,dive,required"`
+	}
+
+	var errStructPtrArray [][]*Inner
+
+	errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {"ok"}})
+
+	tmsp := &TestMultiDimensionalStructsPtr{
+		Errs: errStructPtrArray,
+	}
+
+	errs := validate.Struct(tmsp)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+	// for full test coverage
+	fmt.Sprint(errs.Error())
+
+	fieldErr := errs.Errors["Errs"]
+	Equal(t, fieldErr.IsPlaceholderErr, true)
+	Equal(t, fieldErr.IsSliceOrArray, true)
+	Equal(t, fieldErr.Field, "Errs")
+	Equal(t, len(fieldErr.SliceOrArrayErrs), 1)
+
+	innerSlice1, ok := fieldErr.SliceOrArrayErrs[0].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, innerSlice1.IsPlaceholderErr, true)
+	Equal(t, innerSlice1.Field, "Errs[0]")
+
+	flatFieldErr, ok := fieldErr.Flatten()["[0][1].Inner.Name"]
+	Equal(t, ok, true)
+	Equal(t, flatFieldErr.Field, "Name")
+	Equal(t, flatFieldErr.Tag, "required")
+
+	structErrFlatten, ok := errs.Flatten()["Errs[0][1].Inner.Name"]
+	Equal(t, ok, true)
+	Equal(t, structErrFlatten.Field, "Name")
+	Equal(t, structErrFlatten.Tag, "required")
+
+	errStructPtrArray = [][]*Inner{}
+	errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, nil, {"ok"}})
+
+	tmsp = &TestMultiDimensionalStructsPtr{
+		Errs: errStructPtrArray,
+	}
+
+	errs = validate.Struct(tmsp)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+	// for full test coverage
+	fmt.Sprint(errs.Error())
+
+	fieldErr = errs.Errors["Errs"]
+	Equal(t, fieldErr.IsPlaceholderErr, true)
+	Equal(t, fieldErr.IsSliceOrArray, true)
+	Equal(t, fieldErr.Field, "Errs")
+	Equal(t, len(fieldErr.SliceOrArrayErrs), 1)
+
+	innerSlice1, ok = fieldErr.SliceOrArrayErrs[0].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, innerSlice1.IsPlaceholderErr, true)
+	Equal(t, innerSlice1.Field, "Errs[0]")
+
+	flatFieldErr, ok = fieldErr.Flatten()["[0][1]"]
+	Equal(t, ok, true)
+	Equal(t, flatFieldErr.Field, "Errs[0][1]")
+	Equal(t, flatFieldErr.Tag, "required")
+
+	type TestMapStructPtr struct {
+		Errs map[int]*Inner `validate:"gt=0,dive,required"`
+	}
+
+	mip := map[int]*Inner{0: {"ok"}, 3: {""}, 4: {"ok"}}
+
+	msp := &TestMapStructPtr{
+		Errs: mip,
+	}
+
+	errs = validate.Struct(msp)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	fieldError := errs.Errors["Errs"]
+	Equal(t, fieldError.IsPlaceholderErr, true)
+	Equal(t, fieldError.IsMap, true)
+	Equal(t, len(fieldError.MapErrs), 1)
+
+	innerStructError, ok := fieldError.MapErrs[3].(*StructErrors)
+	Equal(t, ok, true)
+	Equal(t, innerStructError.Struct, "Inner")
+	Equal(t, len(innerStructError.Errors), 1)
+
+	innerInnerFieldError, ok := innerStructError.Errors["Name"]
+	Equal(t, ok, true)
+	Equal(t, innerInnerFieldError.IsPlaceholderErr, false)
+	Equal(t, innerInnerFieldError.IsSliceOrArray, false)
+	Equal(t, innerInnerFieldError.Field, "Name")
+	Equal(t, innerInnerFieldError.Tag, "required")
+
+	flatErrs, ok := errs.Flatten()["Errs[3].Inner.Name"]
+	Equal(t, ok, true)
+	Equal(t, flatErrs.Field, "Name")
+	Equal(t, flatErrs.Tag, "required")
+
+	mip2 := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}}
+
+	msp2 := &TestMapStructPtr{
+		Errs: mip2,
+	}
+
+	errs = validate.Struct(msp2)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	fieldError = errs.Errors["Errs"]
+	Equal(t, fieldError.IsPlaceholderErr, true)
+	Equal(t, fieldError.IsMap, true)
+	Equal(t, len(fieldError.MapErrs), 1)
+
+	innerFieldError, ok := fieldError.MapErrs[3].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, innerFieldError.IsPlaceholderErr, false)
+	Equal(t, innerFieldError.IsSliceOrArray, false)
+	Equal(t, innerFieldError.Field, "Errs[3]")
+	Equal(t, innerFieldError.Tag, "required")
+
+	flatErrs, ok = errs.Flatten()["Errs[3]"]
+	Equal(t, ok, true)
+	Equal(t, flatErrs.Field, "Errs[3]")
+	Equal(t, flatErrs.Tag, "required")
+
+	type TestMapInnerArrayStruct struct {
+		Errs map[int][]string `validate:"gt=0,dive,dive,required"`
+	}
+
+	mias := map[int][]string{0: {"ok"}, 3: {"ok", ""}, 4: {"ok"}}
+
+	mia := &TestMapInnerArrayStruct{
+		Errs: mias,
+	}
+
+	errs = validate.Struct(mia)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	flatErrs, ok = errs.Flatten()["Errs[3][1]"]
+	Equal(t, ok, true)
+	Equal(t, flatErrs.Field, "Errs[3][1]")
+	Equal(t, flatErrs.Tag, "required")
+}
+
+func TestInterfaceErrValidation(t *testing.T) {
+
+	var v1 interface{}
+	var v2 interface{}
+
+	v2 = 1
+	v1 = v2
+
+	err := validate.Field(v1, "len=1")
+	Equal(t, err, nil)
+	err = validate.Field(v2, "len=1")
+	Equal(t, err, nil)
+
+	type ExternalCMD struct {
+		Userid string      `json:"userid"`
+		Action uint32      `json:"action"`
+		Data   interface{} `json:"data,omitempty" validate:"required"`
+	}
+
+	s := &ExternalCMD{
+		Userid: "123456",
+		Action: 10000,
+		// Data:   1,
+	}
+
+	errs := validate.Struct(s)
+	NotEqual(t, errs, nil)
+	Equal(t, errs.Errors["Data"].Field, "Data")
+	Equal(t, errs.Errors["Data"].Tag, "required")
+
+	type ExternalCMD2 struct {
+		Userid string      `json:"userid"`
+		Action uint32      `json:"action"`
+		Data   interface{} `json:"data,omitempty" validate:"len=1"`
+	}
+
+	s2 := &ExternalCMD2{
+		Userid: "123456",
+		Action: 10000,
+		// Data:   1,
+	}
+
+	errs = validate.Struct(s2)
+	NotEqual(t, errs, nil)
+	Equal(t, errs.Errors["Data"].Field, "Data")
+	Equal(t, errs.Errors["Data"].Tag, "len")
+	Equal(t, errs.Errors["Data"].Param, "1")
+
+	s3 := &ExternalCMD2{
+		Userid: "123456",
+		Action: 10000,
+		Data:   2,
+	}
+
+	errs = validate.Struct(s3)
+	NotEqual(t, errs, nil)
+	Equal(t, errs.Errors["Data"].Field, "Data")
+	Equal(t, errs.Errors["Data"].Tag, "len")
+	Equal(t, errs.Errors["Data"].Param, "1")
+
+	type Inner struct {
+		Name string `validate:"required"`
+	}
+
+	inner := &Inner{
+		Name: "",
+	}
+
+	s4 := &ExternalCMD{
+		Userid: "123456",
+		Action: 10000,
+		Data:   inner,
+	}
+
+	errs = validate.Struct(s4)
+	NotEqual(t, errs, nil)
+	Equal(t, errs.StructErrors["Data"].Struct, "Inner")
+	Equal(t, errs.StructErrors["Data"].Errors["Name"].Field, "Name")
+	Equal(t, errs.StructErrors["Data"].Errors["Name"].Tag, "required")
+
+	type TestMapStructPtr struct {
+		Errs map[int]interface{} `validate:"gt=0,dive,len=2"`
+	}
+
+	mip := map[int]interface{}{0: &Inner{"ok"}, 3: nil, 4: &Inner{"ok"}}
+
+	msp := &TestMapStructPtr{
+		Errs: mip,
+	}
+
+	errs = validate.Struct(msp)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	fieldError := errs.Errors["Errs"]
+	Equal(t, fieldError.IsPlaceholderErr, true)
+	Equal(t, fieldError.IsMap, true)
+	Equal(t, len(fieldError.MapErrs), 1)
+
+	innerFieldError, ok := fieldError.MapErrs[3].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, innerFieldError.IsPlaceholderErr, false)
+	Equal(t, innerFieldError.IsMap, false)
+	Equal(t, len(innerFieldError.MapErrs), 0)
+	Equal(t, innerFieldError.Field, "Errs[3]")
+	Equal(t, innerFieldError.Tag, "len")
+
+	type TestMultiDimensionalStructs struct {
+		Errs [][]interface{} `validate:"gt=0,dive,dive,len=2"`
+	}
+
+	var errStructArray [][]interface{}
+
+	errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}})
+	errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}})
+
+	tms := &TestMultiDimensionalStructs{
+		Errs: errStructArray,
+	}
+
+	errs = validate.Struct(tms)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	fieldErr, ok := errs.Errors["Errs"]
+	Equal(t, ok, true)
+	Equal(t, fieldErr.IsPlaceholderErr, true)
+	Equal(t, fieldErr.IsSliceOrArray, true)
+	Equal(t, len(fieldErr.SliceOrArrayErrs), 2)
+
+	sliceError1, ok := fieldErr.SliceOrArrayErrs[0].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, sliceError1.IsPlaceholderErr, true)
+	Equal(t, sliceError1.IsSliceOrArray, true)
+	Equal(t, len(sliceError1.SliceOrArrayErrs), 2)
+
+	innerSliceStructError1, ok := sliceError1.SliceOrArrayErrs[1].(*StructErrors)
+	Equal(t, ok, true)
+	Equal(t, len(innerSliceStructError1.Errors), 1)
+
+	innerInnersliceError1 := innerSliceStructError1.Errors["Name"]
+	Equal(t, innerInnersliceError1.IsPlaceholderErr, false)
+	Equal(t, innerInnersliceError1.IsSliceOrArray, false)
+	Equal(t, len(innerInnersliceError1.SliceOrArrayErrs), 0)
+
+	type TestMultiDimensionalStructsPtr2 struct {
+		Errs [][]*Inner `validate:"gt=0,dive,dive,len=2"`
+	}
+
+	var errStructPtr2Array [][]*Inner
+
+	errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
+	errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
+	errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil})
+
+	tmsp2 := &TestMultiDimensionalStructsPtr2{
+		Errs: errStructPtr2Array,
+	}
+
+	errs = validate.Struct(tmsp2)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	fieldErr, ok = errs.Errors["Errs"]
+	Equal(t, ok, true)
+	Equal(t, fieldErr.IsPlaceholderErr, true)
+	Equal(t, fieldErr.IsSliceOrArray, true)
+	Equal(t, len(fieldErr.SliceOrArrayErrs), 3)
+
+	sliceError1, ok = fieldErr.SliceOrArrayErrs[2].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, sliceError1.IsPlaceholderErr, true)
+	Equal(t, sliceError1.IsSliceOrArray, true)
+	Equal(t, len(sliceError1.SliceOrArrayErrs), 2)
+
+	innerSliceStructError1, ok = sliceError1.SliceOrArrayErrs[1].(*StructErrors)
+	Equal(t, ok, true)
+	Equal(t, len(innerSliceStructError1.Errors), 1)
+
+	innerSliceStructError2, ok := sliceError1.SliceOrArrayErrs[2].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, innerSliceStructError2.IsPlaceholderErr, false)
+	Equal(t, innerSliceStructError2.IsSliceOrArray, false)
+	Equal(t, len(innerSliceStructError2.SliceOrArrayErrs), 0)
+	Equal(t, innerSliceStructError2.Field, "Errs[2][2]")
+
+	innerInnersliceError1 = innerSliceStructError1.Errors["Name"]
+	Equal(t, innerInnersliceError1.IsPlaceholderErr, false)
+	Equal(t, innerInnersliceError1.IsSliceOrArray, false)
+	Equal(t, len(innerInnersliceError1.SliceOrArrayErrs), 0)
+
+	m := map[int]interface{}{0: "ok", 3: "", 4: "ok"}
+
+	err = validate.Field(m, "len=3,dive,len=2")
+	NotEqual(t, err, nil)
+	Equal(t, err.IsPlaceholderErr, true)
+	Equal(t, err.IsMap, true)
+	Equal(t, len(err.MapErrs), 1)
+
+	err = validate.Field(m, "len=2,dive,required")
+	NotEqual(t, err, nil)
+	Equal(t, err.IsPlaceholderErr, false)
+	Equal(t, err.IsMap, false)
+	Equal(t, len(err.MapErrs), 0)
+
+	arr := []interface{}{"ok", "", "ok"}
+
+	err = validate.Field(arr, "len=3,dive,len=2")
+	NotEqual(t, err, nil)
+	Equal(t, err.IsPlaceholderErr, true)
+	Equal(t, err.IsSliceOrArray, true)
+	Equal(t, len(err.SliceOrArrayErrs), 1)
+
+	err = validate.Field(arr, "len=2,dive,required")
+	NotEqual(t, err, nil)
+	Equal(t, err.IsPlaceholderErr, false)
+	Equal(t, err.IsSliceOrArray, false)
+	Equal(t, len(err.SliceOrArrayErrs), 0)
+
+	type MyStruct struct {
+		A, B string
+		C    interface{}
+	}
+
+	var a MyStruct
+
+	a.A = "value"
+	a.C = "nu"
+
+	errs = validate.Struct(a)
+	Equal(t, errs, nil)
+}
+
+func TestMapDiveValidation(t *testing.T) {
+
+	n := map[int]interface{}{0: nil}
+	err := validate.Field(n, "omitempty,required")
+
+	m := map[int]string{0: "ok", 3: "", 4: "ok"}
+
+	err = validate.Field(m, "len=3,dive,required")
+	NotEqual(t, err, nil)
+	Equal(t, err.IsPlaceholderErr, true)
+	Equal(t, err.IsMap, true)
+	Equal(t, len(err.MapErrs), 1)
+
+	err = validate.Field(m, "len=2,dive,required")
+	NotEqual(t, err, nil)
+	Equal(t, err.IsPlaceholderErr, false)
+	Equal(t, err.IsMap, false)
+	Equal(t, len(err.MapErrs), 0)
+
+	type Inner struct {
+		Name string `validate:"required"`
+	}
+
+	type TestMapStruct struct {
+		Errs map[int]Inner `validate:"gt=0,dive"`
+	}
+
+	mi := map[int]Inner{0: {"ok"}, 3: {""}, 4: {"ok"}}
+
+	ms := &TestMapStruct{
+		Errs: mi,
+	}
+
+	errs := validate.Struct(ms)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+	// for full test coverage
+	fmt.Sprint(errs.Error())
+
+	fieldError := errs.Errors["Errs"]
+	Equal(t, fieldError.IsPlaceholderErr, true)
+	Equal(t, fieldError.IsMap, true)
+	Equal(t, len(fieldError.MapErrs), 1)
+
+	structErr, ok := fieldError.MapErrs[3].(*StructErrors)
+	Equal(t, ok, true)
+	Equal(t, len(structErr.Errors), 1)
+
+	innerErr := structErr.Errors["Name"]
+	Equal(t, innerErr.IsPlaceholderErr, false)
+	Equal(t, innerErr.IsMap, false)
+	Equal(t, len(innerErr.MapErrs), 0)
+	Equal(t, innerErr.Field, "Name")
+	Equal(t, innerErr.Tag, "required")
+
+	type TestMapTimeStruct struct {
+		Errs map[int]*time.Time `validate:"gt=0,dive,required"`
+	}
+
+	t1 := time.Now().UTC()
+
+	mta := map[int]*time.Time{0: &t1, 3: nil, 4: nil}
+
+	mt := &TestMapTimeStruct{
+		Errs: mta,
+	}
+
+	errs = validate.Struct(mt)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	fieldError = errs.Errors["Errs"]
+	Equal(t, fieldError.IsPlaceholderErr, true)
+	Equal(t, fieldError.IsMap, true)
+	Equal(t, len(fieldError.MapErrs), 2)
+
+	innerErr, ok = fieldError.MapErrs[3].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, innerErr.IsPlaceholderErr, false)
+	Equal(t, innerErr.IsMap, false)
+	Equal(t, len(innerErr.MapErrs), 0)
+	Equal(t, innerErr.Field, "Errs[3]")
+	Equal(t, innerErr.Tag, "required")
+
+	type TestMapStructPtr struct {
+		Errs map[int]*Inner `validate:"gt=0,dive,required"`
+	}
+
+	mip := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}}
+
+	msp := &TestMapStructPtr{
+		Errs: mip,
+	}
+
+	errs = validate.Struct(msp)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	fieldError = errs.Errors["Errs"]
+	Equal(t, fieldError.IsPlaceholderErr, true)
+	Equal(t, fieldError.IsMap, true)
+	Equal(t, len(fieldError.MapErrs), 1)
+
+	innerFieldError, ok := fieldError.MapErrs[3].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, innerFieldError.IsPlaceholderErr, false)
+	Equal(t, innerFieldError.IsMap, false)
+	Equal(t, len(innerFieldError.MapErrs), 0)
+	Equal(t, innerFieldError.Field, "Errs[3]")
+	Equal(t, innerFieldError.Tag, "required")
+
+	type TestMapStructPtr2 struct {
+		Errs map[int]*Inner `validate:"gt=0,dive,omitempty,required"`
+	}
+
+	mip2 := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}}
+
+	msp2 := &TestMapStructPtr2{
+		Errs: mip2,
+	}
+
+	errs = validate.Struct(msp2)
+	Equal(t, errs, nil)
+}
+
+func TestArrayDiveValidation(t *testing.T) {
+
+	arr := []string{"ok", "", "ok"}
+
+	err := validate.Field(arr, "len=3,dive,required")
+	NotEqual(t, err, nil)
+	Equal(t, err.IsPlaceholderErr, true)
+	Equal(t, err.IsSliceOrArray, true)
+	Equal(t, len(err.SliceOrArrayErrs), 1)
+
+	// flat := err.Flatten()
+	// fe, ok := flat["[1]"]
+	// Equal(t, ok, true)
+	// Equal(t, fe.Tag, "required")
+
+	err = validate.Field(arr, "len=2,dive,required")
+	NotEqual(t, err, nil)
+	Equal(t, err.IsPlaceholderErr, false)
+	Equal(t, err.IsSliceOrArray, false)
+	Equal(t, len(err.SliceOrArrayErrs), 0)
+
+	type BadDive struct {
+		Name string `validate:"dive"`
+	}
+
+	bd := &BadDive{
+		Name: "TEST",
+	}
+
+	PanicMatches(t, func() { validate.Struct(bd) }, "dive error! can't dive on a non slice or map")
+
+	type Test struct {
+		Errs []string `validate:"gt=0,dive,required"`
+	}
+
+	test := &Test{
+		Errs: []string{"ok", "", "ok"},
+	}
+
+	errs := validate.Struct(test)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	// flat = errs.Flatten()
+	// me, ok := flat["Errs[1]"]
+	// Equal(t, ok, true)
+	// Equal(t, me.Field, "Errs[1]")
+	// Equal(t, me.Tag, "required")
+
+	fieldErr, ok := errs.Errors["Errs"]
+	Equal(t, ok, true)
+	Equal(t, fieldErr.IsPlaceholderErr, true)
+	Equal(t, fieldErr.IsSliceOrArray, true)
+	Equal(t, len(fieldErr.SliceOrArrayErrs), 1)
+
+	innerErr, ok := fieldErr.SliceOrArrayErrs[1].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, innerErr.Tag, required)
+	Equal(t, innerErr.IsPlaceholderErr, false)
+	Equal(t, innerErr.Field, "Errs[1]")
+
+	test = &Test{
+		Errs: []string{"ok", "ok", ""},
+	}
+
+	errs = validate.Struct(test)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	fieldErr, ok = errs.Errors["Errs"]
+	Equal(t, ok, true)
+	Equal(t, fieldErr.IsPlaceholderErr, true)
+	Equal(t, fieldErr.IsSliceOrArray, true)
+	Equal(t, len(fieldErr.SliceOrArrayErrs), 1)
+
+	innerErr, ok = fieldErr.SliceOrArrayErrs[2].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, innerErr.Tag, required)
+	Equal(t, innerErr.IsPlaceholderErr, false)
+	Equal(t, innerErr.Field, "Errs[2]")
+
+	type TestMultiDimensional struct {
+		Errs [][]string `validate:"gt=0,dive,dive,required"`
+	}
+
+	var errArray [][]string
+
+	errArray = append(errArray, []string{"ok", "", ""})
+	errArray = append(errArray, []string{"ok", "", ""})
+
+	tm := &TestMultiDimensional{
+		Errs: errArray,
+	}
+
+	errs = validate.Struct(tm)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	fieldErr, ok = errs.Errors["Errs"]
+	Equal(t, ok, true)
+	Equal(t, fieldErr.IsPlaceholderErr, true)
+	Equal(t, fieldErr.IsSliceOrArray, true)
+	Equal(t, len(fieldErr.SliceOrArrayErrs), 2)
+
+	sliceError1, ok := fieldErr.SliceOrArrayErrs[0].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, sliceError1.IsPlaceholderErr, true)
+	Equal(t, sliceError1.IsSliceOrArray, true)
+	Equal(t, len(sliceError1.SliceOrArrayErrs), 2)
+	Equal(t, sliceError1.Field, "Errs[0]")
+
+	innerSliceError1, ok := sliceError1.SliceOrArrayErrs[1].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, innerSliceError1.IsPlaceholderErr, false)
+	Equal(t, innerSliceError1.Tag, required)
+	Equal(t, innerSliceError1.IsSliceOrArray, false)
+	Equal(t, len(innerSliceError1.SliceOrArrayErrs), 0)
+	Equal(t, innerSliceError1.Field, "Errs[0][1]")
+
+	type Inner struct {
+		Name string `validate:"required"`
+	}
+
+	type TestMultiDimensionalStructs struct {
+		Errs [][]Inner `validate:"gt=0,dive,dive"`
+	}
+
+	var errStructArray [][]Inner
+
+	errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}})
+	errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}})
+
+	tms := &TestMultiDimensionalStructs{
+		Errs: errStructArray,
+	}
+
+	errs = validate.Struct(tms)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	fieldErr, ok = errs.Errors["Errs"]
+	Equal(t, ok, true)
+	Equal(t, fieldErr.IsPlaceholderErr, true)
+	Equal(t, fieldErr.IsSliceOrArray, true)
+	Equal(t, len(fieldErr.SliceOrArrayErrs), 2)
+
+	sliceError1, ok = fieldErr.SliceOrArrayErrs[0].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, sliceError1.IsPlaceholderErr, true)
+	Equal(t, sliceError1.IsSliceOrArray, true)
+	Equal(t, len(sliceError1.SliceOrArrayErrs), 2)
+
+	innerSliceStructError1, ok := sliceError1.SliceOrArrayErrs[1].(*StructErrors)
+	Equal(t, ok, true)
+	Equal(t, len(innerSliceStructError1.Errors), 1)
+
+	innerInnersliceError1 := innerSliceStructError1.Errors["Name"]
+	Equal(t, innerInnersliceError1.IsPlaceholderErr, false)
+	Equal(t, innerInnersliceError1.IsSliceOrArray, false)
+	Equal(t, len(innerInnersliceError1.SliceOrArrayErrs), 0)
+
+	type TestMultiDimensionalStructsPtr struct {
+		Errs [][]*Inner `validate:"gt=0,dive,dive"`
+	}
+
+	var errStructPtrArray [][]*Inner
+
+	errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}})
+	errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}})
+	errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, nil})
+
+	tmsp := &TestMultiDimensionalStructsPtr{
+		Errs: errStructPtrArray,
+	}
+
+	errs = validate.Struct(tmsp)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+	// for full test coverage
+	fmt.Sprint(errs.Error())
+
+	// flat := errs.Flatten()
+	// // fmt.Println(errs)
+	// fmt.Println(flat)
+	// expect Errs[0][1].Inner.Name
+	// me, ok := flat["Errs[1]"]
+	// Equal(t, ok, true)
+	// Equal(t, me.Field, "Errs[1]")
+	// Equal(t, me.Tag, "required")
+
+	fieldErr, ok = errs.Errors["Errs"]
+	Equal(t, ok, true)
+	Equal(t, fieldErr.IsPlaceholderErr, true)
+	Equal(t, fieldErr.IsSliceOrArray, true)
+	Equal(t, len(fieldErr.SliceOrArrayErrs), 3)
+
+	// flat := fieldErr.Flatten()
+	// fmt.Println(errs)
+	// fmt.Println(flat)
+
+	sliceError1, ok = fieldErr.SliceOrArrayErrs[0].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, sliceError1.IsPlaceholderErr, true)
+	Equal(t, sliceError1.IsSliceOrArray, true)
+	Equal(t, len(sliceError1.SliceOrArrayErrs), 2)
+
+	innerSliceStructError1, ok = sliceError1.SliceOrArrayErrs[1].(*StructErrors)
+	Equal(t, ok, true)
+	Equal(t, len(innerSliceStructError1.Errors), 1)
+
+	innerInnersliceError1 = innerSliceStructError1.Errors["Name"]
+	Equal(t, innerInnersliceError1.IsPlaceholderErr, false)
+	Equal(t, innerInnersliceError1.IsSliceOrArray, false)
+	Equal(t, len(innerInnersliceError1.SliceOrArrayErrs), 0)
+
+	type TestMultiDimensionalStructsPtr2 struct {
+		Errs [][]*Inner `validate:"gt=0,dive,dive,required"`
+	}
+
+	var errStructPtr2Array [][]*Inner
+
+	errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
+	errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}})
+	errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil})
+
+	tmsp2 := &TestMultiDimensionalStructsPtr2{
+		Errs: errStructPtr2Array,
+	}
+
+	errs = validate.Struct(tmsp2)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	fieldErr, ok = errs.Errors["Errs"]
+	Equal(t, ok, true)
+	Equal(t, fieldErr.IsPlaceholderErr, true)
+	Equal(t, fieldErr.IsSliceOrArray, true)
+	Equal(t, len(fieldErr.SliceOrArrayErrs), 3)
+
+	sliceError1, ok = fieldErr.SliceOrArrayErrs[2].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, sliceError1.IsPlaceholderErr, true)
+	Equal(t, sliceError1.IsSliceOrArray, true)
+	Equal(t, len(sliceError1.SliceOrArrayErrs), 2)
+
+	innerSliceStructError1, ok = sliceError1.SliceOrArrayErrs[1].(*StructErrors)
+	Equal(t, ok, true)
+	Equal(t, len(innerSliceStructError1.Errors), 1)
+
+	innerSliceStructError2, ok := sliceError1.SliceOrArrayErrs[2].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, innerSliceStructError2.IsPlaceholderErr, false)
+	Equal(t, innerSliceStructError2.IsSliceOrArray, false)
+	Equal(t, len(innerSliceStructError2.SliceOrArrayErrs), 0)
+	Equal(t, innerSliceStructError2.Field, "Errs[2][2]")
+
+	innerInnersliceError1 = innerSliceStructError1.Errors["Name"]
+	Equal(t, innerInnersliceError1.IsPlaceholderErr, false)
+	Equal(t, innerInnersliceError1.IsSliceOrArray, false)
+	Equal(t, len(innerInnersliceError1.SliceOrArrayErrs), 0)
+
+	type TestMultiDimensionalStructsPtr3 struct {
+		Errs [][]*Inner `validate:"gt=0,dive,dive,omitempty"`
+	}
+
+	var errStructPtr3Array [][]*Inner
+
+	errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}})
+	errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}})
+	errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, nil})
+
+	tmsp3 := &TestMultiDimensionalStructsPtr3{
+		Errs: errStructPtr3Array,
+	}
+
+	errs = validate.Struct(tmsp3)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	fieldErr, ok = errs.Errors["Errs"]
+	Equal(t, ok, true)
+	Equal(t, fieldErr.IsPlaceholderErr, true)
+	Equal(t, fieldErr.IsSliceOrArray, true)
+	Equal(t, len(fieldErr.SliceOrArrayErrs), 3)
+
+	sliceError1, ok = fieldErr.SliceOrArrayErrs[0].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, sliceError1.IsPlaceholderErr, true)
+	Equal(t, sliceError1.IsSliceOrArray, true)
+	Equal(t, len(sliceError1.SliceOrArrayErrs), 2)
+
+	innerSliceStructError1, ok = sliceError1.SliceOrArrayErrs[1].(*StructErrors)
+	Equal(t, ok, true)
+	Equal(t, len(innerSliceStructError1.Errors), 1)
+
+	innerInnersliceError1 = innerSliceStructError1.Errors["Name"]
+	Equal(t, innerInnersliceError1.IsPlaceholderErr, false)
+	Equal(t, innerInnersliceError1.IsSliceOrArray, false)
+	Equal(t, len(innerInnersliceError1.SliceOrArrayErrs), 0)
+
+	type TestMultiDimensionalTimeTime struct {
+		Errs [][]*time.Time `validate:"gt=0,dive,dive,required"`
+	}
+
+	var errTimePtr3Array [][]*time.Time
+
+	t1 := time.Now().UTC()
+	t2 := time.Now().UTC()
+	t3 := time.Now().UTC().Add(time.Hour * 24)
+
+	errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, &t3})
+	errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, nil})
+	errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, nil, nil})
+
+	tmtp3 := &TestMultiDimensionalTimeTime{
+		Errs: errTimePtr3Array,
+	}
+
+	errs = validate.Struct(tmtp3)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	fieldErr, ok = errs.Errors["Errs"]
+	Equal(t, ok, true)
+	Equal(t, fieldErr.IsPlaceholderErr, true)
+	Equal(t, fieldErr.IsSliceOrArray, true)
+	Equal(t, len(fieldErr.SliceOrArrayErrs), 2)
+
+	sliceError1, ok = fieldErr.SliceOrArrayErrs[2].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, sliceError1.IsPlaceholderErr, true)
+	Equal(t, sliceError1.IsSliceOrArray, true)
+	Equal(t, len(sliceError1.SliceOrArrayErrs), 2)
+
+	innerSliceError1, ok = sliceError1.SliceOrArrayErrs[1].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, innerSliceError1.IsPlaceholderErr, false)
+	Equal(t, innerSliceError1.IsSliceOrArray, false)
+	Equal(t, len(innerSliceError1.SliceOrArrayErrs), 0)
+	Equal(t, innerSliceError1.Field, "Errs[2][1]")
+	Equal(t, innerSliceError1.Tag, required)
+
+	type TestMultiDimensionalTimeTime2 struct {
+		Errs [][]*time.Time `validate:"gt=0,dive,dive,required"`
+	}
+
+	var errTimeArray [][]*time.Time
+
+	t1 = time.Now().UTC()
+	t2 = time.Now().UTC()
+	t3 = time.Now().UTC().Add(time.Hour * 24)
+
+	errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, &t3})
+	errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, nil})
+	errTimeArray = append(errTimeArray, []*time.Time{&t1, nil, nil})
+
+	tmtp := &TestMultiDimensionalTimeTime2{
+		Errs: errTimeArray,
+	}
+
+	errs = validate.Struct(tmtp)
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs.Errors), 1)
+
+	fieldErr, ok = errs.Errors["Errs"]
+	Equal(t, ok, true)
+	Equal(t, fieldErr.IsPlaceholderErr, true)
+	Equal(t, fieldErr.IsSliceOrArray, true)
+	Equal(t, len(fieldErr.SliceOrArrayErrs), 2)
+
+	sliceError1, ok = fieldErr.SliceOrArrayErrs[2].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, sliceError1.IsPlaceholderErr, true)
+	Equal(t, sliceError1.IsSliceOrArray, true)
+	Equal(t, len(sliceError1.SliceOrArrayErrs), 2)
+
+	innerSliceError1, ok = sliceError1.SliceOrArrayErrs[1].(*FieldError)
+	Equal(t, ok, true)
+	Equal(t, innerSliceError1.IsPlaceholderErr, false)
+	Equal(t, innerSliceError1.IsSliceOrArray, false)
+	Equal(t, len(innerSliceError1.SliceOrArrayErrs), 0)
+	Equal(t, innerSliceError1.Field, "Errs[2][1]")
+	Equal(t, innerSliceError1.Tag, required)
+}
+
+func TestNilStructPointerValidation(t *testing.T) {
+	type Inner struct {
+		Data string
+	}
+
+	type Outer struct {
+		Inner *Inner `validate:"omitempty"`
+	}
+
+	inner := &Inner{
+		Data: "test",
+	}
+
+	outer := &Outer{
+		Inner: inner,
+	}
+
+	errs := validate.Struct(outer)
+	Equal(t, errs, nil)
+
+	outer = &Outer{
+		Inner: nil,
+	}
+
+	errs = validate.Struct(outer)
+	Equal(t, errs, nil)
+
+	type Inner2 struct {
+		Data string
+	}
+
+	type Outer2 struct {
+		Inner2 *Inner2 `validate:"required"`
+	}
+
+	inner2 := &Inner2{
+		Data: "test",
+	}
+
+	outer2 := &Outer2{
+		Inner2: inner2,
+	}
+
+	errs = validate.Struct(outer2)
+	Equal(t, errs, nil)
+
+	outer2 = &Outer2{
+		Inner2: nil,
+	}
+
+	errs = validate.Struct(outer2)
+	NotEqual(t, errs, nil)
+
+	type Inner3 struct {
+		Data string
+	}
+
+	type Outer3 struct {
+		Inner3 *Inner3
+	}
+
+	inner3 := &Inner3{
+		Data: "test",
+	}
+
+	outer3 := &Outer3{
+		Inner3: inner3,
+	}
+
+	errs = validate.Struct(outer3)
+	Equal(t, errs, nil)
+
+	type Inner4 struct {
+		Data string
+	}
+
+	type Outer4 struct {
+		Inner4 *Inner4 `validate:"-"`
+	}
+
+	inner4 := &Inner4{
+		Data: "test",
+	}
+
+	outer4 := &Outer4{
+		Inner4: inner4,
+	}
+
+	errs = validate.Struct(outer4)
+	Equal(t, errs, nil)
+}
+
 func TestSSNValidation(t *testing.T) {
 	tests := []struct {
 		param    string
@@ -1100,7 +2216,7 @@ func TestStructOnlyValidation(t *testing.T) {
 		InnerStruct: nil,
 	}
 
-	errs := validate.Struct(outer).Flatten()
+	errs := validate.Struct(outer)
 	NotEqual(t, errs, nil)
 
 	inner := &Inner{
@@ -1111,9 +2227,8 @@ func TestStructOnlyValidation(t *testing.T) {
 		InnerStruct: inner,
 	}
 
-	errs = validate.Struct(outer).Flatten()
-	NotEqual(t, errs, nil)
-	Equal(t, len(errs), 0)
+	errs = validate.Struct(outer)
+	Equal(t, errs, nil)
 }
 
 func TestGtField(t *testing.T) {
@@ -2727,14 +3842,14 @@ func TestStructSliceValidation(t *testing.T) {
 		Min:       []int{1, 2},
 		Max:       []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
 		MinMax:    []int{1, 2, 3, 4, 5},
-		OmitEmpty: []int{},
+		OmitEmpty: nil,
 	}
 
 	err := validate.Struct(tSuccess)
 	Equal(t, err, nil)
 
 	tFail := &TestSlice{
-		Required:  []int{},
+		Required:  nil,
 		Len:       []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
 		Min:       []int{},
 		Max:       []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
@@ -2772,7 +3887,7 @@ func TestInvalidField(t *testing.T) {
 		Test: "1",
 	}
 
-	PanicMatches(t, func() { validate.Field(s, "required") }, "Invalid field passed to ValidateFieldWithTag")
+	PanicMatches(t, func() { validate.Field(s, "required") }, "Invalid field passed to fieldWithNameAndValue")
 }
 
 func TestInvalidTagField(t *testing.T) {
@@ -2790,3 +3905,23 @@ func TestInvalidValidatorFunction(t *testing.T) {
 
 	PanicMatches(t, func() { validate.Field(s.Test, "zzxxBadFunction") }, fmt.Sprintf("Undefined validation function on field %s", ""))
 }
+
+func TestPoolObjectMaxSizeValidation(t *testing.T) {
+	// this will ensure that the pool objects are let go
+	// when the pool is saturated
+	validate.SetMaxStructPoolSize(0)
+
+	tSuccess := &TestSlice{
+		Required:  []int{1},
+		Len:       []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
+		Min:       []int{1, 2},
+		Max:       []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
+		MinMax:    []int{1, 2, 3, 4, 5},
+		OmitEmpty: nil,
+	}
+
+	for i := 0; i < 2; i++ {
+		err := validate.Struct(tSuccess)
+		Equal(t, err, nil)
+	}
+}