diff --git a/CHANGELOG.md b/CHANGELOG.md
index ff83250132ed8cde3fbec746c852d9e5aa5a1695..91e8aa257dd40117311bffcd738b142ab597aa46 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,18 @@
 # [Hyperledger Burrow](https://github.com/hyperledger/burrow) Changelog
-## [0.20.2] - 2018-08-20
+## [0.21.0] - 2018-08-21
+### Changed
+- Upgraded to Tendermint 0.23.0
+- Validator Set Power now takes Address
+- RPC/TM config renamed to RPC/Info
+
+### Added
+- Burrow deploy creates devdoc
+- Docker image has org.label-schema labels
+
 ### Fixed
 - Upgrade to IAVL 0.10.0 and load previous versions immutably on boot - for chains with a long history > 20 minute load times could be observed because every previous root was being loaded from DB rather than lightweight version references as was intended
+- Metrics server does not panic on empty block metas and recovers from other panics
+
 
 ## [0.20.1] - 2018-08-17
 ### Changed
@@ -255,7 +266,7 @@ This release marks the start of Eris-DB as the full permissioned blockchain node
   - [Blockchain] Fix getBlocks to respect block height cap.
 
 
-[0.20.2]: https://github.com/hyperledger/burrow/compare/v0.20.1...v0.20.2
+[0.21.0]: https://github.com/hyperledger/burrow/compare/v0.20.1...v0.21.0
 [0.20.1]: https://github.com/hyperledger/burrow/compare/v0.20.0...v0.20.1
 [0.20.0]: https://github.com/hyperledger/burrow/compare/v0.19.0...v0.20.0
 [0.19.0]: https://github.com/hyperledger/burrow/compare/v0.18.1...v0.19.0
diff --git a/Gopkg.lock b/Gopkg.lock
index be7d49e147101e5a4be61b71af6e74a349fb1fde..39bc61be055d7c67415bddc349cbad63666cebbc 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -495,7 +495,7 @@
   version = "v0.10.0"
 
 [[projects]]
-  digest = "1:84249e1324b5a504fd52c52c131a8abc7b36d913803e5bacc6c2c0ab9fbad045"
+  digest = "1:77fa9bc72848b93790fdad4f728f4ae36a905a51d6056dc72752889157fc37c0"
   name = "github.com/tendermint/tendermint"
   packages = [
     "abci/client",
@@ -544,8 +544,8 @@
     "version",
   ]
   pruneopts = "UT"
-  revision = "d542d2c3945116697f60451e6a407082c41c3cc9"
-  version = "v0.22.8"
+  revision = "013b9cef642f875634c614019ab13b17570778ad"
+  version = "v0.23.0"
 
 [[projects]]
   branch = "master"
@@ -565,12 +565,15 @@
 
 [[projects]]
   branch = "master"
-  digest = "1:af274e79e60e89d72d9b85b1145d330934ff2adca88a0a354886669be0b4b0cb"
+  digest = "1:fda2fde01556c582685ab0a5cf270ea0bd657f572fbdfc89b9acc31e1d48dc8a"
   name = "golang.org/x/crypto"
   packages = [
+    "chacha20poly1305",
     "curve25519",
     "ed25519",
     "ed25519/internal/edwards25519",
+    "hkdf",
+    "internal/chacha20",
     "internal/subtle",
     "nacl/box",
     "nacl/secretbox",
diff --git a/Gopkg.toml b/Gopkg.toml
index 3eda13a7ec98415ea32edfde9697d1e24b03e159..6b27396f3916bd79b9cef92f69777ba7e76fd5e1 100644
--- a/Gopkg.toml
+++ b/Gopkg.toml
@@ -16,16 +16,12 @@
 # overriding here because of IAVL
 [[override]]
   name = "github.com/tendermint/tendermint"
-  version = "=0.22.8"
+  version = "=0.23.0"
 
 [[constraint]]
   name = "github.com/tendermint/iavl"
   version = "=0.10.0"
 
-#[[constraint]]
-#  name = "github.com/prometheus/client_golang"
-#  branch = "master"
-
 # Haven't made a release since 2016.
 [[constraint]]
   name = "github.com/prometheus/client_golang"
diff --git a/NOTES.md b/NOTES.md
index 4f587969dcba5cd0a7e9c977c0c27b0aa1f8c60b..433102bc2379b725805f6a663690a31edadb6ad8 100644
--- a/NOTES.md
+++ b/NOTES.md
@@ -1,2 +1,13 @@
+### Changed
+- Upgraded to Tendermint 0.23.0
+- Validator Set Power now takes Address
+- RPC/TM config renamed to RPC/Info
+
+### Added
+- Burrow deploy creates devdoc
+- Docker image has org.label-schema labels
+
 ### Fixed
 - Upgrade to IAVL 0.10.0 and load previous versions immutably on boot - for chains with a long history > 20 minute load times could be observed because every previous root was being loaded from DB rather than lightweight version references as was intended
+- Metrics server does not panic on empty block metas and recovers from other panics
+
diff --git a/acm/validator/ring.go b/acm/validator/ring.go
index 81a0ab45e9860d27d1d9f9811404126718c1818e..635caed51296c89c6873bba2b329347970488b67 100644
--- a/acm/validator/ring.go
+++ b/acm/validator/ring.go
@@ -50,7 +50,7 @@ func NewRing(initialSet Iterable, windowSize int) *Ring {
 
 // Implement Reader
 // Get power at index from the delta bucket then falling through to the cumulative
-func (vc *Ring) PowerAt(index int64, id crypto.PublicKey) *big.Int {
+func (vc *Ring) PowerAt(index int64, id crypto.Address) *big.Int {
 	power := vc.Head().MaybePower(id)
 	if power != nil {
 		return power
@@ -58,7 +58,7 @@ func (vc *Ring) PowerAt(index int64, id crypto.PublicKey) *big.Int {
 	return vc.Cum().Power(id)
 }
 
-func (vc *Ring) Power(id crypto.PublicKey) *big.Int {
+func (vc *Ring) Power(id crypto.Address) *big.Int {
 	return vc.PowerAt(vc.head, id)
 }
 
@@ -87,7 +87,7 @@ func (vc *Ring) AlterPower(id crypto.PublicKey, power *big.Int) (*big.Int, error
 			"does not", power)
 	}
 	// if flow > maxflow then we cannot alter the power
-	flow := vc.Flow(id, power)
+	flow := vc.Flow(id.Address(), power)
 	maxFlow := vc.MaxFlow()
 	// Set flow for this id to update flow.totalPower (total flow) for comparison below, keep track of flow for each id
 	// so that we only count flow once for each id
@@ -95,13 +95,13 @@ func (vc *Ring) AlterPower(id crypto.PublicKey, power *big.Int) (*big.Int, error
 	// The totalPower of the Flow Set is the absolute value of all power changes made so far
 	if vc.flow.totalPower.Cmp(maxFlow) == 1 {
 		// Reset flow to previous value to undo update above
-		prevFlow := vc.Flow(id, vc.Head().Power(id))
+		prevFlow := vc.Flow(id.Address(), vc.Head().Power(id.Address()))
 		vc.flow.ChangePower(id, prevFlow)
 		allowable := new(big.Int).Sub(maxFlow, vc.flow.totalPower)
 		return nil, fmt.Errorf("cannot change validator power of %v from %v to %v because that would result in a flow "+
 			"greater than or equal to 1/3 of total power for the next commit: flow induced by change: %v, "+
 			"current total flow: %v/%v (cumulative/max), remaining allowable flow: %v",
-			id.Address(), vc.Cum().Power(id), power, flow, vc.flow.totalPower, maxFlow, allowable)
+			id.Address(), vc.Cum().Power(id.Address()), power, flow, vc.flow.totalPower, maxFlow, allowable)
 	}
 	// Add to total power
 	vc.Head().ChangePower(id, power)
@@ -109,7 +109,7 @@ func (vc *Ring) AlterPower(id crypto.PublicKey, power *big.Int) (*big.Int, error
 }
 
 // Returns the flow that would be induced by a validator change by comparing the head accumulater with the current set
-func (vc *Ring) Flow(id crypto.PublicKey, power *big.Int) *big.Int {
+func (vc *Ring) Flow(id crypto.Address, power *big.Int) *big.Int {
 	flow := new(big.Int)
 	return flow.Abs(flow.Sub(power, vc.Cum().Power(id)))
 }
diff --git a/acm/validator/set.go b/acm/validator/set.go
index 52bd7c83fc69bc601364ba9a68f2a77cb4a1ff24..24b68ea2604fa36b55ca5e8cfa515599d64d1619 100644
--- a/acm/validator/set.go
+++ b/acm/validator/set.go
@@ -49,7 +49,7 @@ func (vs *Set) AlterPower(id crypto.PublicKey, power *big.Int) (flow *big.Int, e
 func (vs *Set) ChangePower(id crypto.PublicKey, power *big.Int) *big.Int {
 	address := id.Address()
 	// Calculcate flow into this validator (postive means in, negative means out)
-	flow := new(big.Int).Sub(power, vs.Power(id))
+	flow := new(big.Int).Sub(power, vs.Power(id.Address()))
 	vs.totalPower.Add(vs.totalPower, flow)
 
 	if vs.trim && power.Sign() == 0 {
@@ -67,18 +67,18 @@ func (vs *Set) TotalPower() *big.Int {
 }
 
 // Returns the power of id but only if it is set
-func (vs *Set) MaybePower(id crypto.PublicKey) *big.Int {
-	if vs.powers[id.Address()] == nil {
+func (vs *Set) MaybePower(id crypto.Address) *big.Int {
+	if vs.powers[id] == nil {
 		return nil
 	}
-	return new(big.Int).Set(vs.powers[id.Address()])
+	return new(big.Int).Set(vs.powers[id])
 }
 
-func (vs *Set) Power(id crypto.PublicKey) *big.Int {
-	if vs.powers[id.Address()] == nil {
+func (vs *Set) Power(id crypto.Address) *big.Int {
+	if vs.powers[id] == nil {
 		return new(big.Int)
 	}
-	return new(big.Int).Set(vs.powers[id.Address()])
+	return new(big.Int).Set(vs.powers[id])
 }
 
 func (vs *Set) Equal(vsOther *Set) bool {
@@ -87,7 +87,7 @@ func (vs *Set) Equal(vsOther *Set) bool {
 	}
 	// Stop iteration IFF we find a non-matching validator
 	return !vs.Iterate(func(id crypto.Addressable, power *big.Int) (stop bool) {
-		otherPower := vsOther.Power(id.PublicKey())
+		otherPower := vsOther.Power(id.Address())
 		if otherPower.Cmp(power) != 0 {
 			return true
 		}
diff --git a/acm/validator/validators.go b/acm/validator/validators.go
index dece3c6677d632f33de4fdc35a86c924f7ffdaa9..efaa64f7e2cc6d940a0f613ada506944969fc4cb 100644
--- a/acm/validator/validators.go
+++ b/acm/validator/validators.go
@@ -13,7 +13,7 @@ type Writer interface {
 }
 
 type Reader interface {
-	Power(id crypto.PublicKey) *big.Int
+	Power(id crypto.Address) *big.Int
 }
 
 type Iterable interface {
@@ -51,12 +51,12 @@ func (wf WriterFunc) AlterPower(id crypto.PublicKey, power *big.Int) (flow *big.
 
 func AddPower(vs ReaderWriter, id crypto.PublicKey, power *big.Int) error {
 	// Current power + power
-	_, err := vs.AlterPower(id, new(big.Int).Add(vs.Power(id), power))
+	_, err := vs.AlterPower(id, new(big.Int).Add(vs.Power(id.Address()), power))
 	return err
 }
 
 func SubtractPower(vs ReaderWriter, id crypto.PublicKey, power *big.Int) error {
-	_, err := vs.AlterPower(id, new(big.Int).Sub(vs.Power(id), power))
+	_, err := vs.AlterPower(id, new(big.Int).Sub(vs.Power(id.Address()), power))
 	return err
 }
 
diff --git a/bcm/blockchain_test.go b/bcm/blockchain_test.go
index c5f5bc62761a1d4cbd06b1613849dad90682dc16..c2807566e19e9388799bfefdf9d2ee6a73536dbe 100644
--- a/bcm/blockchain_test.go
+++ b/bcm/blockchain_test.go
@@ -44,7 +44,7 @@ func TestBlockchain_Encode(t *testing.T) {
 
 	// Should have exponentially decayed to 0
 	assertZero(t, flow)
-	assertZero(t, bc.validatorCache.Power(id1))
+	assertZero(t, bc.validatorCache.Power(id1.Address()))
 }
 
 // Since we have -0 and 0 with big.Int due to its representation with a neg flag
diff --git a/consensus/tendermint/abci/app.go b/consensus/tendermint/abci/app.go
index cbacbc94ed70f77d13623b312376535d7173b201..6afb9b96a09f38d9a62fa4983365f876c5105b43 100644
--- a/consensus/tendermint/abci/app.go
+++ b/consensus/tendermint/abci/app.go
@@ -3,10 +3,8 @@ package abci
 import (
 	"fmt"
 	"math/big"
-	"sync"
-	"time"
-
 	"runtime/debug"
+	"sync"
 
 	"github.com/hyperledger/burrow/acm/validator"
 	"github.com/hyperledger/burrow/bcm"
@@ -116,12 +114,12 @@ func (app *App) BeginBlock(block abciTypes.RequestBeginBlock) (respBeginBlock ab
 		var err error
 		// Tendermint runs a block behind with the validators passed in here
 		previousValidators := app.blockchain.PreviousValidators()
-		if len(block.Validators) != previousValidators.Count() {
+		if len(block.LastCommitInfo.Validators) != previousValidators.Count() {
 			err = fmt.Errorf("Tendermint passes %d validators to BeginBlock but Burrow's Blockchain has %d",
-				len(block.Validators), previousValidators.Count())
+				len(block.LastCommitInfo.Validators), previousValidators.Count())
 			panic(err)
 		}
-		for _, v := range block.Validators {
+		for _, v := range block.LastCommitInfo.Validators {
 			err = app.checkValidatorMatches(previousValidators, v.Validator)
 			if err != nil {
 				panic(err)
@@ -132,14 +130,14 @@ func (app *App) BeginBlock(block abciTypes.RequestBeginBlock) (respBeginBlock ab
 }
 
 func (app *App) checkValidatorMatches(ours validator.Reader, v abciTypes.Validator) error {
-	publicKey, err := crypto.PublicKeyFromABCIPubKey(v.PubKey)
+	address, err := crypto.AddressFromBytes(v.Address)
 	if err != nil {
 		return err
 	}
-	power := ours.Power(publicKey)
+	power := ours.Power(address)
 	if power.Cmp(big.NewInt(v.Power)) != 0 {
 		return fmt.Errorf("validator %v has power %d from Tendermint but power %d from Burrow",
-			publicKey.Address(), v.Power, power)
+			address, v.Power, power)
 	}
 	return nil
 }
@@ -167,7 +165,6 @@ func (app *App) DeliverTx(txBytes []byte) abciTypes.ResponseDeliverTx {
 		Log:       ctr.Log,
 		Data:      ctr.Data,
 		Tags:      ctr.Tags,
-		Fee:       ctr.Fee,
 		GasUsed:   ctr.GasUsed,
 		GasWanted: ctr.GasWanted,
 		Info:      ctr.Info,
@@ -241,7 +238,7 @@ func (app *App) Commit() abciTypes.ResponseCommit {
 			app.panicFunc(fmt.Errorf("panic occurred in abci.App/Commit: %v\n%s", r, debug.Stack()))
 		}
 	}()
-	blockTime := time.Unix(app.block.Header.Time, 0)
+	blockTime := app.block.Header.Time
 	app.logger.InfoMsg("Committing block",
 		"tag", "Commit",
 		structure.ScopeKey, "Commit()",
diff --git a/consensus/tendermint/priv_validator_memory.go b/consensus/tendermint/priv_validator_memory.go
index 5c2c965133227083491404427b74edc8627c2e74..eda6a312a29244f65d5164eef7cfa5f24e2ee087 100644
--- a/consensus/tendermint/priv_validator_memory.go
+++ b/consensus/tendermint/priv_validator_memory.go
@@ -8,7 +8,7 @@ import (
 
 type privValidatorMemory struct {
 	crypto.Addressable
-	signer         func(msg []byte) tmCrypto.Signature
+	signer         func(msg []byte) []byte
 	lastSignedInfo *LastSignedInfo
 }
 
@@ -24,8 +24,8 @@ func NewPrivValidatorMemory(addressable crypto.Addressable, signer crypto.Signer
 	}
 }
 
-func asTendermintSigner(signer crypto.Signer) func(msg []byte) tmCrypto.Signature {
-	return func(msg []byte) tmCrypto.Signature {
+func asTendermintSigner(signer crypto.Signer) func(msg []byte) []byte {
+	return func(msg []byte) []byte {
 		sig, err := signer.Sign(msg)
 		if err != nil {
 			return nil
diff --git a/consensus/tendermint/sign_info.go b/consensus/tendermint/sign_info.go
index 1cc075ed99b73622170371b6b3946542d74b8fd0..1fce0718ad486c66cf2cb469269d514f9a58c470 100644
--- a/consensus/tendermint/sign_info.go
+++ b/consensus/tendermint/sign_info.go
@@ -8,7 +8,6 @@ import (
 	"time"
 
 	"github.com/hyperledger/burrow/binary"
-	"github.com/tendermint/tendermint/crypto"
 	"github.com/tendermint/tendermint/types"
 )
 
@@ -36,11 +35,11 @@ func voteToStep(vote *types.Vote) int8 {
 // data signed by a validator to help prevent double signing.
 type LastSignedInfo struct {
 	sync.Mutex
-	Height    int64            `json:"height"`
-	Round     int              `json:"round"`
-	Step      int8             `json:"step"`
-	Signature crypto.Signature `json:"signature,omitempty"` // so we dont lose signatures
-	SignBytes binary.HexBytes  `json:"signbytes,omitempty"` // so we dont lose signatures
+	Height    int64           `json:"height"`
+	Round     int             `json:"round"`
+	Step      int8            `json:"step"`
+	Signature []byte          `json:"signature,omitempty"` // so we dont lose signatures
+	SignBytes binary.HexBytes `json:"signbytes,omitempty"` // so we dont lose signatures
 }
 
 func NewLastSignedInfo() *LastSignedInfo {
@@ -49,7 +48,7 @@ func NewLastSignedInfo() *LastSignedInfo {
 	}
 }
 
-type tmCryptoSigner func(msg []byte) crypto.Signature
+type tmCryptoSigner func(msg []byte) []byte
 
 // SignVote signs a canonical representation of the vote, along with the
 // chainID. Implements PrivValidator.
@@ -175,7 +174,7 @@ func (lsi *LastSignedInfo) signProposal(sign tmCryptoSigner, chainID string, pro
 
 // Persist height/round/step and signature
 func (lsi *LastSignedInfo) saveSigned(height int64, round int, step int8,
-	signBytes []byte, sig crypto.Signature) {
+	signBytes []byte, sig []byte) {
 
 	lsi.Height = height
 	lsi.Round = round
diff --git a/core/kernel.go b/core/kernel.go
index 316da522473efa8bbec83bd829360de26c40ab18..4f7df7cc69365987e7c6f3895c5ea99c2e9417ce 100644
--- a/core/kernel.go
+++ b/core/kernel.go
@@ -125,7 +125,10 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy
 	app := abci.NewApp(kern.nodeInfo, kern.Blockchain, checker, committer, txCodec, kern.Panic, logger)
 	// We could use this to provide/register our own metrics (though this will register them with us). Unfortunately
 	// Tendermint currently ignores the metrics passed unless its own server is turned on.
-	metricsProvider := node.DefaultMetricsProvider
+	metricsProvider := node.DefaultMetricsProvider(&tmConfig.InstrumentationConfig{
+		Prometheus:           false,
+		PrometheusListenAddr: "",
+	})
 	kern.Node, err = tendermint.NewNode(tmConf, privValidator, tmGenesisDoc, app, metricsProvider, tmLogger)
 	if err != nil {
 		return nil, err
diff --git a/crypto/tendermint.go b/crypto/tendermint.go
index a886880391134411be47bc4d80161b99ca63b77f..f7265ba684fe11f2e0f2a5e9a790e1b29c4b616c 100644
--- a/crypto/tendermint.go
+++ b/crypto/tendermint.go
@@ -63,17 +63,6 @@ func (p PublicKey) TendermintPubKey() tmCrypto.PubKey {
 
 // Signature extensions
 
-func (sig Signature) TendermintSignature() tmCrypto.Signature {
-	switch sig.CurveType {
-	case CurveTypeEd25519:
-		s := tmEd25519.SignatureEd25519{}
-		copy(s[:], sig.Signature)
-		return s
-	case CurveTypeSecp256k1:
-		s := tmSecp256k1.SignatureSecp256k1{}
-		copy(s[:], sig.Signature)
-		return s
-	default:
-		return nil
-	}
+func (sig Signature) TendermintSignature() []byte {
+	return sig.Signature
 }
diff --git a/integration/governance/governance_test.go b/integration/governance/governance_test.go
index dfa0928b7025b313120bd8cddcceda09c2527219..8be3036e998434dbb6aea0e605e78ca01502b8f1 100644
--- a/integration/governance/governance_test.go
+++ b/integration/governance/governance_test.go
@@ -175,7 +175,7 @@ func TestChangePowerByAddress(t *testing.T) {
 	vs, err := qcli.GetValidatorSet(context.Background(), &rpcquery.GetValidatorSetParam{})
 	require.NoError(t, err)
 	set := validator.UnpersistSet(vs.Set)
-	assert.Equal(t, new(big.Int).SetUint64(power), set.Power(acc.PublicKey()))
+	assert.Equal(t, new(big.Int).SetUint64(power), set.Power(acc.Address()))
 }
 
 func TestInvalidSequenceNumber(t *testing.T) {
diff --git a/project/history.go b/project/history.go
index b4c95792b7b264b506b3c74981c2eefddfc2bf92..0e9bce2f1289ec874a91fab5abcb0143c6913600 100644
--- a/project/history.go
+++ b/project/history.go
@@ -29,9 +29,20 @@ func FullVersion() string {
 // To cut a new release add a release to the front of this slice then run the
 // release tagging script: ./scripts/tag_release.sh
 var History relic.ImmutableHistory = relic.NewHistory("Hyperledger Burrow", "https://github.com/hyperledger/burrow").
-	MustDeclareReleases("0.20.2 - 2018-08-20",
-		`### Fixed
-- Upgrade to IAVL 0.10.0 and load previous versions immutably on boot - for chains with a long history > 20 minute load times could be observed because every previous root was being loaded from DB rather than lightweight version references as was intended`,
+	MustDeclareReleases("0.21.0 - 2018-08-21",
+		`### Changed
+- Upgraded to Tendermint 0.23.0
+- Validator Set Power now takes Address
+- RPC/TM config renamed to RPC/Info
+
+### Added
+- Burrow deploy creates devdoc
+- Docker image has org.label-schema labels
+
+### Fixed
+- Upgrade to IAVL 0.10.0 and load previous versions immutably on boot - for chains with a long history > 20 minute load times could be observed because every previous root was being loaded from DB rather than lightweight version references as was intended
+- Metrics server does not panic on empty block metas and recovers from other panics
+`,
 		"0.20.1 - 2018-08-17",
 		`### Changed
 - The snatives functions have new signatures; string arguments are now string, not byte32.
diff --git a/rpc/result_test.go b/rpc/result_test.go
index bb2967f2cdd66e6c630e85fb00a0d76f6d40ea81..f086d897eaad968d58fb91b442e3fc26855fcdda 100644
--- a/rpc/result_test.go
+++ b/rpc/result_test.go
@@ -21,7 +21,6 @@ import (
 	"github.com/hyperledger/burrow/acm"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
-	tmEd25519 "github.com/tendermint/tendermint/crypto/ed25519"
 	tmTypes "github.com/tendermint/tendermint/types"
 )
 
@@ -48,7 +47,7 @@ func TestResultGetBlock(t *testing.T) {
 			LastCommit: &tmTypes.Commit{
 				Precommits: []*tmTypes.Vote{
 					{
-						Signature: tmEd25519.SignatureEd25519{1, 2, 3},
+						Signature: []byte{1, 2, 3},
 					},
 				},
 			},
diff --git a/rpc/service.go b/rpc/service.go
index 83a0c1e3ca42edbaddb6e44fdb8f5cb8dc629386..94f03baac37959f232ac7f5855cf637139feb9d5 100644
--- a/rpc/service.go
+++ b/rpc/service.go
@@ -376,7 +376,7 @@ func Status(blockchain bcm.BlockchainInfo, nodeView *tendermint.NodeView, blockT
 		ValidatorInfo: &validator.Validator{
 			Address:   &address,
 			PublicKey: publicKey,
-			Power:     blockchain.Validators().Power(publicKey).Uint64(),
+			Power:     blockchain.Validators().Power(address).Uint64(),
 		},
 	}
 
diff --git a/vendor/github.com/tendermint/tendermint/abci/client/grpc_client.go b/vendor/github.com/tendermint/tendermint/abci/client/grpc_client.go
index 502ee0fcd8d54b81158ad7e39c09ac5e0b2e7276..a1f0994684fef40076e2bb42c89dc59e0fbe5ea1 100644
--- a/vendor/github.com/tendermint/tendermint/abci/client/grpc_client.go
+++ b/vendor/github.com/tendermint/tendermint/abci/client/grpc_client.go
@@ -63,7 +63,7 @@ RETRY_LOOP:
 
 	ENSURE_CONNECTED:
 		for {
-			_, err := client.Echo(context.Background(), &types.RequestEcho{"hello"}, grpc.FailFast(true))
+			_, err := client.Echo(context.Background(), &types.RequestEcho{Message: "hello"}, grpc.FailFast(true))
 			if err == nil {
 				break ENSURE_CONNECTED
 			}
@@ -129,7 +129,7 @@ func (cli *grpcClient) EchoAsync(msg string) *ReqRes {
 	if err != nil {
 		cli.StopForError(err)
 	}
-	return cli.finishAsyncCall(req, &types.Response{&types.Response_Echo{res}})
+	return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_Echo{res}})
 }
 
 func (cli *grpcClient) FlushAsync() *ReqRes {
@@ -138,7 +138,7 @@ func (cli *grpcClient) FlushAsync() *ReqRes {
 	if err != nil {
 		cli.StopForError(err)
 	}
-	return cli.finishAsyncCall(req, &types.Response{&types.Response_Flush{res}})
+	return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_Flush{res}})
 }
 
 func (cli *grpcClient) InfoAsync(params types.RequestInfo) *ReqRes {
@@ -147,7 +147,7 @@ func (cli *grpcClient) InfoAsync(params types.RequestInfo) *ReqRes {
 	if err != nil {
 		cli.StopForError(err)
 	}
-	return cli.finishAsyncCall(req, &types.Response{&types.Response_Info{res}})
+	return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_Info{res}})
 }
 
 func (cli *grpcClient) SetOptionAsync(params types.RequestSetOption) *ReqRes {
@@ -156,7 +156,7 @@ func (cli *grpcClient) SetOptionAsync(params types.RequestSetOption) *ReqRes {
 	if err != nil {
 		cli.StopForError(err)
 	}
-	return cli.finishAsyncCall(req, &types.Response{&types.Response_SetOption{res}})
+	return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_SetOption{res}})
 }
 
 func (cli *grpcClient) DeliverTxAsync(tx []byte) *ReqRes {
@@ -165,7 +165,7 @@ func (cli *grpcClient) DeliverTxAsync(tx []byte) *ReqRes {
 	if err != nil {
 		cli.StopForError(err)
 	}
-	return cli.finishAsyncCall(req, &types.Response{&types.Response_DeliverTx{res}})
+	return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_DeliverTx{res}})
 }
 
 func (cli *grpcClient) CheckTxAsync(tx []byte) *ReqRes {
@@ -174,7 +174,7 @@ func (cli *grpcClient) CheckTxAsync(tx []byte) *ReqRes {
 	if err != nil {
 		cli.StopForError(err)
 	}
-	return cli.finishAsyncCall(req, &types.Response{&types.Response_CheckTx{res}})
+	return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_CheckTx{res}})
 }
 
 func (cli *grpcClient) QueryAsync(params types.RequestQuery) *ReqRes {
@@ -183,7 +183,7 @@ func (cli *grpcClient) QueryAsync(params types.RequestQuery) *ReqRes {
 	if err != nil {
 		cli.StopForError(err)
 	}
-	return cli.finishAsyncCall(req, &types.Response{&types.Response_Query{res}})
+	return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_Query{res}})
 }
 
 func (cli *grpcClient) CommitAsync() *ReqRes {
@@ -192,7 +192,7 @@ func (cli *grpcClient) CommitAsync() *ReqRes {
 	if err != nil {
 		cli.StopForError(err)
 	}
-	return cli.finishAsyncCall(req, &types.Response{&types.Response_Commit{res}})
+	return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_Commit{res}})
 }
 
 func (cli *grpcClient) InitChainAsync(params types.RequestInitChain) *ReqRes {
@@ -201,7 +201,7 @@ func (cli *grpcClient) InitChainAsync(params types.RequestInitChain) *ReqRes {
 	if err != nil {
 		cli.StopForError(err)
 	}
-	return cli.finishAsyncCall(req, &types.Response{&types.Response_InitChain{res}})
+	return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_InitChain{res}})
 }
 
 func (cli *grpcClient) BeginBlockAsync(params types.RequestBeginBlock) *ReqRes {
@@ -210,7 +210,7 @@ func (cli *grpcClient) BeginBlockAsync(params types.RequestBeginBlock) *ReqRes {
 	if err != nil {
 		cli.StopForError(err)
 	}
-	return cli.finishAsyncCall(req, &types.Response{&types.Response_BeginBlock{res}})
+	return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_BeginBlock{res}})
 }
 
 func (cli *grpcClient) EndBlockAsync(params types.RequestEndBlock) *ReqRes {
@@ -219,7 +219,7 @@ func (cli *grpcClient) EndBlockAsync(params types.RequestEndBlock) *ReqRes {
 	if err != nil {
 		cli.StopForError(err)
 	}
-	return cli.finishAsyncCall(req, &types.Response{&types.Response_EndBlock{res}})
+	return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_EndBlock{res}})
 }
 
 func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) *ReqRes {
diff --git a/vendor/github.com/tendermint/tendermint/abci/client/local_client.go b/vendor/github.com/tendermint/tendermint/abci/client/local_client.go
index 3d1f8d8e4162722e45d24590f6dc9e17dac29d35..3ac3b6afaded77dafd74e6b7a0b5b1ca41a6e206 100644
--- a/vendor/github.com/tendermint/tendermint/abci/client/local_client.go
+++ b/vendor/github.com/tendermint/tendermint/abci/client/local_client.go
@@ -149,7 +149,7 @@ func (app *localClient) FlushSync() error {
 }
 
 func (app *localClient) EchoSync(msg string) (*types.ResponseEcho, error) {
-	return &types.ResponseEcho{msg}, nil
+	return &types.ResponseEcho{Message: msg}, nil
 }
 
 func (app *localClient) InfoSync(req types.RequestInfo) (*types.ResponseInfo, error) {
diff --git a/vendor/github.com/tendermint/tendermint/abci/types/application.go b/vendor/github.com/tendermint/tendermint/abci/types/application.go
index ef1bc92e5e0b87537e6a867badacd3efc23f8eb6..88f8d001ec12c8a22240ed6af9303378831f847f 100644
--- a/vendor/github.com/tendermint/tendermint/abci/types/application.go
+++ b/vendor/github.com/tendermint/tendermint/abci/types/application.go
@@ -85,7 +85,7 @@ func NewGRPCApplication(app Application) *GRPCApplication {
 }
 
 func (app *GRPCApplication) Echo(ctx context.Context, req *RequestEcho) (*ResponseEcho, error) {
-	return &ResponseEcho{req.Message}, nil
+	return &ResponseEcho{Message: req.Message}, nil
 }
 
 func (app *GRPCApplication) Flush(ctx context.Context, req *RequestFlush) (*ResponseFlush, error) {
diff --git a/vendor/github.com/tendermint/tendermint/abci/types/messages.go b/vendor/github.com/tendermint/tendermint/abci/types/messages.go
index 52e4b67583de47c292a82952375a4e69c4840779..cb64a15d6973fed4bbd26d94e6ccb9fd156b57cd 100644
--- a/vendor/github.com/tendermint/tendermint/abci/types/messages.go
+++ b/vendor/github.com/tendermint/tendermint/abci/types/messages.go
@@ -71,7 +71,7 @@ func encodeVarint(w io.Writer, i int64) (err error) {
 
 func ToRequestEcho(message string) *Request {
 	return &Request{
-		Value: &Request_Echo{&RequestEcho{message}},
+		Value: &Request_Echo{&RequestEcho{Message: message}},
 	}
 }
 
@@ -95,13 +95,13 @@ func ToRequestSetOption(req RequestSetOption) *Request {
 
 func ToRequestDeliverTx(tx []byte) *Request {
 	return &Request{
-		Value: &Request_DeliverTx{&RequestDeliverTx{tx}},
+		Value: &Request_DeliverTx{&RequestDeliverTx{Tx: tx}},
 	}
 }
 
 func ToRequestCheckTx(tx []byte) *Request {
 	return &Request{
-		Value: &Request_CheckTx{&RequestCheckTx{tx}},
+		Value: &Request_CheckTx{&RequestCheckTx{Tx: tx}},
 	}
 }
 
@@ -139,13 +139,13 @@ func ToRequestEndBlock(req RequestEndBlock) *Request {
 
 func ToResponseException(errStr string) *Response {
 	return &Response{
-		Value: &Response_Exception{&ResponseException{errStr}},
+		Value: &Response_Exception{&ResponseException{Error: errStr}},
 	}
 }
 
 func ToResponseEcho(message string) *Response {
 	return &Response{
-		Value: &Response_Echo{&ResponseEcho{message}},
+		Value: &Response_Echo{&ResponseEcho{Message: message}},
 	}
 }
 
diff --git a/vendor/github.com/tendermint/tendermint/abci/types/types.pb.go b/vendor/github.com/tendermint/tendermint/abci/types/types.pb.go
index 57dd14393e9b1a67fb10641f79d9465d53532a0e..ac71d91c8f95534f2e8cd1d9f49b36cba249176b 100644
--- a/vendor/github.com/tendermint/tendermint/abci/types/types.pb.go
+++ b/vendor/github.com/tendermint/tendermint/abci/types/types.pb.go
@@ -1,48 +1,6 @@
 // Code generated by protoc-gen-gogo. DO NOT EDIT.
 // source: abci/types/types.proto
 
-/*
-	Package types is a generated protocol buffer package.
-
-	It is generated from these files:
-		abci/types/types.proto
-
-	It has these top-level messages:
-		Request
-		RequestEcho
-		RequestFlush
-		RequestInfo
-		RequestSetOption
-		RequestInitChain
-		RequestQuery
-		RequestBeginBlock
-		RequestCheckTx
-		RequestDeliverTx
-		RequestEndBlock
-		RequestCommit
-		Response
-		ResponseException
-		ResponseEcho
-		ResponseFlush
-		ResponseInfo
-		ResponseSetOption
-		ResponseInitChain
-		ResponseQuery
-		ResponseBeginBlock
-		ResponseCheckTx
-		ResponseDeliverTx
-		ResponseEndBlock
-		ResponseCommit
-		ConsensusParams
-		BlockSize
-		TxSize
-		BlockGossip
-		Header
-		Validator
-		SigningValidator
-		PubKey
-		Evidence
-*/
 //nolint
 package types
 
@@ -51,13 +9,18 @@ import golang_proto "github.com/golang/protobuf/proto"
 import fmt "fmt"
 import math "math"
 import _ "github.com/gogo/protobuf/gogoproto"
+import _ "github.com/golang/protobuf/ptypes/timestamp"
 import common "github.com/tendermint/tendermint/libs/common"
 
+import time "time"
+
 import bytes "bytes"
 
 import context "golang.org/x/net/context"
 import grpc "google.golang.org/grpc"
 
+import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
+
 import io "io"
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -65,6 +28,7 @@ var _ = proto.Marshal
 var _ = golang_proto.Marshal
 var _ = fmt.Errorf
 var _ = math.Inf
+var _ = time.Kitchen
 
 // This is a compile-time assertion to ensure that this generated file
 // is compatible with the proto package it is being compiled against.
@@ -85,13 +49,44 @@ type Request struct {
 	//	*Request_DeliverTx
 	//	*Request_EndBlock
 	//	*Request_Commit
-	Value isRequest_Value `protobuf_oneof:"value"`
+	Value                isRequest_Value `protobuf_oneof:"value"`
+	XXX_NoUnkeyedLiteral struct{}        `json:"-"`
+	XXX_unrecognized     []byte          `json:"-"`
+	XXX_sizecache        int32           `json:"-"`
+}
+
+func (m *Request) Reset()         { *m = Request{} }
+func (m *Request) String() string { return proto.CompactTextString(m) }
+func (*Request) ProtoMessage()    {}
+func (*Request) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{0}
+}
+func (m *Request) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_Request.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *Request) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Request.Merge(dst, src)
+}
+func (m *Request) XXX_Size() int {
+	return m.Size()
+}
+func (m *Request) XXX_DiscardUnknown() {
+	xxx_messageInfo_Request.DiscardUnknown(m)
 }
 
-func (m *Request) Reset()                    { *m = Request{} }
-func (m *Request) String() string            { return proto.CompactTextString(m) }
-func (*Request) ProtoMessage()               {}
-func (*Request) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{0} }
+var xxx_messageInfo_Request proto.InternalMessageInfo
 
 type isRequest_Value interface {
 	isRequest_Value()
@@ -415,57 +410,57 @@ func _Request_OneofSizer(msg proto.Message) (n int) {
 	switch x := m.Value.(type) {
 	case *Request_Echo:
 		s := proto.Size(x.Echo)
-		n += proto.SizeVarint(2<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Request_Flush:
 		s := proto.Size(x.Flush)
-		n += proto.SizeVarint(3<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Request_Info:
 		s := proto.Size(x.Info)
-		n += proto.SizeVarint(4<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Request_SetOption:
 		s := proto.Size(x.SetOption)
-		n += proto.SizeVarint(5<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Request_InitChain:
 		s := proto.Size(x.InitChain)
-		n += proto.SizeVarint(6<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Request_Query:
 		s := proto.Size(x.Query)
-		n += proto.SizeVarint(7<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Request_BeginBlock:
 		s := proto.Size(x.BeginBlock)
-		n += proto.SizeVarint(8<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Request_CheckTx:
 		s := proto.Size(x.CheckTx)
-		n += proto.SizeVarint(9<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Request_DeliverTx:
 		s := proto.Size(x.DeliverTx)
-		n += proto.SizeVarint(19<<3 | proto.WireBytes)
+		n += 2 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Request_EndBlock:
 		s := proto.Size(x.EndBlock)
-		n += proto.SizeVarint(11<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Request_Commit:
 		s := proto.Size(x.Commit)
-		n += proto.SizeVarint(12<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case nil:
@@ -476,13 +471,44 @@ func _Request_OneofSizer(msg proto.Message) (n int) {
 }
 
 type RequestEcho struct {
-	Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
+	Message              string   `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *RequestEcho) Reset()         { *m = RequestEcho{} }
+func (m *RequestEcho) String() string { return proto.CompactTextString(m) }
+func (*RequestEcho) ProtoMessage()    {}
+func (*RequestEcho) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{1}
+}
+func (m *RequestEcho) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *RequestEcho) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_RequestEcho.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *RequestEcho) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RequestEcho.Merge(dst, src)
+}
+func (m *RequestEcho) XXX_Size() int {
+	return m.Size()
+}
+func (m *RequestEcho) XXX_DiscardUnknown() {
+	xxx_messageInfo_RequestEcho.DiscardUnknown(m)
 }
 
-func (m *RequestEcho) Reset()                    { *m = RequestEcho{} }
-func (m *RequestEcho) String() string            { return proto.CompactTextString(m) }
-func (*RequestEcho) ProtoMessage()               {}
-func (*RequestEcho) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{1} }
+var xxx_messageInfo_RequestEcho proto.InternalMessageInfo
 
 func (m *RequestEcho) GetMessage() string {
 	if m != nil {
@@ -492,21 +518,83 @@ func (m *RequestEcho) GetMessage() string {
 }
 
 type RequestFlush struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *RequestFlush) Reset()         { *m = RequestFlush{} }
+func (m *RequestFlush) String() string { return proto.CompactTextString(m) }
+func (*RequestFlush) ProtoMessage()    {}
+func (*RequestFlush) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{2}
+}
+func (m *RequestFlush) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *RequestFlush) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_RequestFlush.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *RequestFlush) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RequestFlush.Merge(dst, src)
+}
+func (m *RequestFlush) XXX_Size() int {
+	return m.Size()
+}
+func (m *RequestFlush) XXX_DiscardUnknown() {
+	xxx_messageInfo_RequestFlush.DiscardUnknown(m)
 }
 
-func (m *RequestFlush) Reset()                    { *m = RequestFlush{} }
-func (m *RequestFlush) String() string            { return proto.CompactTextString(m) }
-func (*RequestFlush) ProtoMessage()               {}
-func (*RequestFlush) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{2} }
+var xxx_messageInfo_RequestFlush proto.InternalMessageInfo
 
 type RequestInfo struct {
-	Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"`
+	Version              string   `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *RequestInfo) Reset()         { *m = RequestInfo{} }
+func (m *RequestInfo) String() string { return proto.CompactTextString(m) }
+func (*RequestInfo) ProtoMessage()    {}
+func (*RequestInfo) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{3}
+}
+func (m *RequestInfo) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *RequestInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_RequestInfo.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *RequestInfo) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RequestInfo.Merge(dst, src)
+}
+func (m *RequestInfo) XXX_Size() int {
+	return m.Size()
+}
+func (m *RequestInfo) XXX_DiscardUnknown() {
+	xxx_messageInfo_RequestInfo.DiscardUnknown(m)
 }
 
-func (m *RequestInfo) Reset()                    { *m = RequestInfo{} }
-func (m *RequestInfo) String() string            { return proto.CompactTextString(m) }
-func (*RequestInfo) ProtoMessage()               {}
-func (*RequestInfo) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{3} }
+var xxx_messageInfo_RequestInfo proto.InternalMessageInfo
 
 func (m *RequestInfo) GetVersion() string {
 	if m != nil {
@@ -517,14 +605,45 @@ func (m *RequestInfo) GetVersion() string {
 
 // nondeterministic
 type RequestSetOption struct {
-	Key   string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
-	Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+	Key                  string   `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+	Value                string   `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *RequestSetOption) Reset()         { *m = RequestSetOption{} }
+func (m *RequestSetOption) String() string { return proto.CompactTextString(m) }
+func (*RequestSetOption) ProtoMessage()    {}
+func (*RequestSetOption) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{4}
+}
+func (m *RequestSetOption) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *RequestSetOption) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_RequestSetOption.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *RequestSetOption) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RequestSetOption.Merge(dst, src)
+}
+func (m *RequestSetOption) XXX_Size() int {
+	return m.Size()
+}
+func (m *RequestSetOption) XXX_DiscardUnknown() {
+	xxx_messageInfo_RequestSetOption.DiscardUnknown(m)
 }
 
-func (m *RequestSetOption) Reset()                    { *m = RequestSetOption{} }
-func (m *RequestSetOption) String() string            { return proto.CompactTextString(m) }
-func (*RequestSetOption) ProtoMessage()               {}
-func (*RequestSetOption) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{4} }
+var xxx_messageInfo_RequestSetOption proto.InternalMessageInfo
 
 func (m *RequestSetOption) GetKey() string {
 	if m != nil {
@@ -541,23 +660,54 @@ func (m *RequestSetOption) GetValue() string {
 }
 
 type RequestInitChain struct {
-	Time            int64            `protobuf:"varint,1,opt,name=time,proto3" json:"time,omitempty"`
-	ChainId         string           `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
-	ConsensusParams *ConsensusParams `protobuf:"bytes,3,opt,name=consensus_params,json=consensusParams" json:"consensus_params,omitempty"`
-	Validators      []Validator      `protobuf:"bytes,4,rep,name=validators" json:"validators"`
-	AppStateBytes   []byte           `protobuf:"bytes,5,opt,name=app_state_bytes,json=appStateBytes,proto3" json:"app_state_bytes,omitempty"`
+	Time                 time.Time        `protobuf:"bytes,1,opt,name=time,stdtime" json:"time"`
+	ChainId              string           `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
+	ConsensusParams      *ConsensusParams `protobuf:"bytes,3,opt,name=consensus_params,json=consensusParams" json:"consensus_params,omitempty"`
+	Validators           []Validator      `protobuf:"bytes,4,rep,name=validators" json:"validators"`
+	AppStateBytes        []byte           `protobuf:"bytes,5,opt,name=app_state_bytes,json=appStateBytes,proto3" json:"app_state_bytes,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
+	XXX_unrecognized     []byte           `json:"-"`
+	XXX_sizecache        int32            `json:"-"`
+}
+
+func (m *RequestInitChain) Reset()         { *m = RequestInitChain{} }
+func (m *RequestInitChain) String() string { return proto.CompactTextString(m) }
+func (*RequestInitChain) ProtoMessage()    {}
+func (*RequestInitChain) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{5}
+}
+func (m *RequestInitChain) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *RequestInitChain) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_RequestInitChain.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *RequestInitChain) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RequestInitChain.Merge(dst, src)
+}
+func (m *RequestInitChain) XXX_Size() int {
+	return m.Size()
+}
+func (m *RequestInitChain) XXX_DiscardUnknown() {
+	xxx_messageInfo_RequestInitChain.DiscardUnknown(m)
 }
 
-func (m *RequestInitChain) Reset()                    { *m = RequestInitChain{} }
-func (m *RequestInitChain) String() string            { return proto.CompactTextString(m) }
-func (*RequestInitChain) ProtoMessage()               {}
-func (*RequestInitChain) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{5} }
+var xxx_messageInfo_RequestInitChain proto.InternalMessageInfo
 
-func (m *RequestInitChain) GetTime() int64 {
+func (m *RequestInitChain) GetTime() time.Time {
 	if m != nil {
 		return m.Time
 	}
-	return 0
+	return time.Time{}
 }
 
 func (m *RequestInitChain) GetChainId() string {
@@ -589,16 +739,47 @@ func (m *RequestInitChain) GetAppStateBytes() []byte {
 }
 
 type RequestQuery struct {
-	Data   []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
-	Path   string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
-	Height int64  `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"`
-	Prove  bool   `protobuf:"varint,4,opt,name=prove,proto3" json:"prove,omitempty"`
+	Data                 []byte   `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
+	Path                 string   `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
+	Height               int64    `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"`
+	Prove                bool     `protobuf:"varint,4,opt,name=prove,proto3" json:"prove,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *RequestQuery) Reset()         { *m = RequestQuery{} }
+func (m *RequestQuery) String() string { return proto.CompactTextString(m) }
+func (*RequestQuery) ProtoMessage()    {}
+func (*RequestQuery) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{6}
+}
+func (m *RequestQuery) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *RequestQuery) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_RequestQuery.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *RequestQuery) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RequestQuery.Merge(dst, src)
+}
+func (m *RequestQuery) XXX_Size() int {
+	return m.Size()
+}
+func (m *RequestQuery) XXX_DiscardUnknown() {
+	xxx_messageInfo_RequestQuery.DiscardUnknown(m)
 }
 
-func (m *RequestQuery) Reset()                    { *m = RequestQuery{} }
-func (m *RequestQuery) String() string            { return proto.CompactTextString(m) }
-func (*RequestQuery) ProtoMessage()               {}
-func (*RequestQuery) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{6} }
+var xxx_messageInfo_RequestQuery proto.InternalMessageInfo
 
 func (m *RequestQuery) GetData() []byte {
 	if m != nil {
@@ -628,17 +809,49 @@ func (m *RequestQuery) GetProve() bool {
 	return false
 }
 
+// NOTE: validators here have empty pubkeys.
 type RequestBeginBlock struct {
-	Hash                []byte             `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
-	Header              Header             `protobuf:"bytes,2,opt,name=header" json:"header"`
-	Validators          []SigningValidator `protobuf:"bytes,3,rep,name=validators" json:"validators"`
-	ByzantineValidators []Evidence         `protobuf:"bytes,4,rep,name=byzantine_validators,json=byzantineValidators" json:"byzantine_validators"`
+	Hash                 []byte         `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
+	Header               Header         `protobuf:"bytes,2,opt,name=header" json:"header"`
+	LastCommitInfo       LastCommitInfo `protobuf:"bytes,3,opt,name=last_commit_info,json=lastCommitInfo" json:"last_commit_info"`
+	ByzantineValidators  []Evidence     `protobuf:"bytes,4,rep,name=byzantine_validators,json=byzantineValidators" json:"byzantine_validators"`
+	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
+	XXX_unrecognized     []byte         `json:"-"`
+	XXX_sizecache        int32          `json:"-"`
+}
+
+func (m *RequestBeginBlock) Reset()         { *m = RequestBeginBlock{} }
+func (m *RequestBeginBlock) String() string { return proto.CompactTextString(m) }
+func (*RequestBeginBlock) ProtoMessage()    {}
+func (*RequestBeginBlock) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{7}
+}
+func (m *RequestBeginBlock) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *RequestBeginBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_RequestBeginBlock.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *RequestBeginBlock) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RequestBeginBlock.Merge(dst, src)
+}
+func (m *RequestBeginBlock) XXX_Size() int {
+	return m.Size()
+}
+func (m *RequestBeginBlock) XXX_DiscardUnknown() {
+	xxx_messageInfo_RequestBeginBlock.DiscardUnknown(m)
 }
 
-func (m *RequestBeginBlock) Reset()                    { *m = RequestBeginBlock{} }
-func (m *RequestBeginBlock) String() string            { return proto.CompactTextString(m) }
-func (*RequestBeginBlock) ProtoMessage()               {}
-func (*RequestBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{7} }
+var xxx_messageInfo_RequestBeginBlock proto.InternalMessageInfo
 
 func (m *RequestBeginBlock) GetHash() []byte {
 	if m != nil {
@@ -654,11 +867,11 @@ func (m *RequestBeginBlock) GetHeader() Header {
 	return Header{}
 }
 
-func (m *RequestBeginBlock) GetValidators() []SigningValidator {
+func (m *RequestBeginBlock) GetLastCommitInfo() LastCommitInfo {
 	if m != nil {
-		return m.Validators
+		return m.LastCommitInfo
 	}
-	return nil
+	return LastCommitInfo{}
 }
 
 func (m *RequestBeginBlock) GetByzantineValidators() []Evidence {
@@ -669,13 +882,44 @@ func (m *RequestBeginBlock) GetByzantineValidators() []Evidence {
 }
 
 type RequestCheckTx struct {
-	Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"`
+	Tx                   []byte   `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *RequestCheckTx) Reset()         { *m = RequestCheckTx{} }
+func (m *RequestCheckTx) String() string { return proto.CompactTextString(m) }
+func (*RequestCheckTx) ProtoMessage()    {}
+func (*RequestCheckTx) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{8}
+}
+func (m *RequestCheckTx) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *RequestCheckTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_RequestCheckTx.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *RequestCheckTx) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RequestCheckTx.Merge(dst, src)
+}
+func (m *RequestCheckTx) XXX_Size() int {
+	return m.Size()
+}
+func (m *RequestCheckTx) XXX_DiscardUnknown() {
+	xxx_messageInfo_RequestCheckTx.DiscardUnknown(m)
 }
 
-func (m *RequestCheckTx) Reset()                    { *m = RequestCheckTx{} }
-func (m *RequestCheckTx) String() string            { return proto.CompactTextString(m) }
-func (*RequestCheckTx) ProtoMessage()               {}
-func (*RequestCheckTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{8} }
+var xxx_messageInfo_RequestCheckTx proto.InternalMessageInfo
 
 func (m *RequestCheckTx) GetTx() []byte {
 	if m != nil {
@@ -685,13 +929,44 @@ func (m *RequestCheckTx) GetTx() []byte {
 }
 
 type RequestDeliverTx struct {
-	Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"`
+	Tx                   []byte   `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *RequestDeliverTx) Reset()         { *m = RequestDeliverTx{} }
+func (m *RequestDeliverTx) String() string { return proto.CompactTextString(m) }
+func (*RequestDeliverTx) ProtoMessage()    {}
+func (*RequestDeliverTx) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{9}
+}
+func (m *RequestDeliverTx) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *RequestDeliverTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_RequestDeliverTx.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *RequestDeliverTx) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RequestDeliverTx.Merge(dst, src)
+}
+func (m *RequestDeliverTx) XXX_Size() int {
+	return m.Size()
+}
+func (m *RequestDeliverTx) XXX_DiscardUnknown() {
+	xxx_messageInfo_RequestDeliverTx.DiscardUnknown(m)
 }
 
-func (m *RequestDeliverTx) Reset()                    { *m = RequestDeliverTx{} }
-func (m *RequestDeliverTx) String() string            { return proto.CompactTextString(m) }
-func (*RequestDeliverTx) ProtoMessage()               {}
-func (*RequestDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{9} }
+var xxx_messageInfo_RequestDeliverTx proto.InternalMessageInfo
 
 func (m *RequestDeliverTx) GetTx() []byte {
 	if m != nil {
@@ -701,13 +976,44 @@ func (m *RequestDeliverTx) GetTx() []byte {
 }
 
 type RequestEndBlock struct {
-	Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"`
+	Height               int64    `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *RequestEndBlock) Reset()         { *m = RequestEndBlock{} }
+func (m *RequestEndBlock) String() string { return proto.CompactTextString(m) }
+func (*RequestEndBlock) ProtoMessage()    {}
+func (*RequestEndBlock) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{10}
+}
+func (m *RequestEndBlock) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *RequestEndBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_RequestEndBlock.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *RequestEndBlock) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RequestEndBlock.Merge(dst, src)
+}
+func (m *RequestEndBlock) XXX_Size() int {
+	return m.Size()
+}
+func (m *RequestEndBlock) XXX_DiscardUnknown() {
+	xxx_messageInfo_RequestEndBlock.DiscardUnknown(m)
 }
 
-func (m *RequestEndBlock) Reset()                    { *m = RequestEndBlock{} }
-func (m *RequestEndBlock) String() string            { return proto.CompactTextString(m) }
-func (*RequestEndBlock) ProtoMessage()               {}
-func (*RequestEndBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{10} }
+var xxx_messageInfo_RequestEndBlock proto.InternalMessageInfo
 
 func (m *RequestEndBlock) GetHeight() int64 {
 	if m != nil {
@@ -717,12 +1023,43 @@ func (m *RequestEndBlock) GetHeight() int64 {
 }
 
 type RequestCommit struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *RequestCommit) Reset()         { *m = RequestCommit{} }
+func (m *RequestCommit) String() string { return proto.CompactTextString(m) }
+func (*RequestCommit) ProtoMessage()    {}
+func (*RequestCommit) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{11}
+}
+func (m *RequestCommit) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *RequestCommit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_RequestCommit.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *RequestCommit) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RequestCommit.Merge(dst, src)
+}
+func (m *RequestCommit) XXX_Size() int {
+	return m.Size()
+}
+func (m *RequestCommit) XXX_DiscardUnknown() {
+	xxx_messageInfo_RequestCommit.DiscardUnknown(m)
 }
 
-func (m *RequestCommit) Reset()                    { *m = RequestCommit{} }
-func (m *RequestCommit) String() string            { return proto.CompactTextString(m) }
-func (*RequestCommit) ProtoMessage()               {}
-func (*RequestCommit) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{11} }
+var xxx_messageInfo_RequestCommit proto.InternalMessageInfo
 
 type Response struct {
 	// Types that are valid to be assigned to Value:
@@ -738,13 +1075,44 @@ type Response struct {
 	//	*Response_DeliverTx
 	//	*Response_EndBlock
 	//	*Response_Commit
-	Value isResponse_Value `protobuf_oneof:"value"`
+	Value                isResponse_Value `protobuf_oneof:"value"`
+	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
+	XXX_unrecognized     []byte           `json:"-"`
+	XXX_sizecache        int32            `json:"-"`
+}
+
+func (m *Response) Reset()         { *m = Response{} }
+func (m *Response) String() string { return proto.CompactTextString(m) }
+func (*Response) ProtoMessage()    {}
+func (*Response) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{12}
+}
+func (m *Response) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_Response.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *Response) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Response.Merge(dst, src)
+}
+func (m *Response) XXX_Size() int {
+	return m.Size()
+}
+func (m *Response) XXX_DiscardUnknown() {
+	xxx_messageInfo_Response.DiscardUnknown(m)
 }
 
-func (m *Response) Reset()                    { *m = Response{} }
-func (m *Response) String() string            { return proto.CompactTextString(m) }
-func (*Response) ProtoMessage()               {}
-func (*Response) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{12} }
+var xxx_messageInfo_Response proto.InternalMessageInfo
 
 type isResponse_Value interface {
 	isResponse_Value()
@@ -1093,62 +1461,62 @@ func _Response_OneofSizer(msg proto.Message) (n int) {
 	switch x := m.Value.(type) {
 	case *Response_Exception:
 		s := proto.Size(x.Exception)
-		n += proto.SizeVarint(1<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Response_Echo:
 		s := proto.Size(x.Echo)
-		n += proto.SizeVarint(2<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Response_Flush:
 		s := proto.Size(x.Flush)
-		n += proto.SizeVarint(3<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Response_Info:
 		s := proto.Size(x.Info)
-		n += proto.SizeVarint(4<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Response_SetOption:
 		s := proto.Size(x.SetOption)
-		n += proto.SizeVarint(5<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Response_InitChain:
 		s := proto.Size(x.InitChain)
-		n += proto.SizeVarint(6<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Response_Query:
 		s := proto.Size(x.Query)
-		n += proto.SizeVarint(7<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Response_BeginBlock:
 		s := proto.Size(x.BeginBlock)
-		n += proto.SizeVarint(8<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Response_CheckTx:
 		s := proto.Size(x.CheckTx)
-		n += proto.SizeVarint(9<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Response_DeliverTx:
 		s := proto.Size(x.DeliverTx)
-		n += proto.SizeVarint(10<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Response_EndBlock:
 		s := proto.Size(x.EndBlock)
-		n += proto.SizeVarint(11<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case *Response_Commit:
 		s := proto.Size(x.Commit)
-		n += proto.SizeVarint(12<<3 | proto.WireBytes)
+		n += 1 // tag and wire
 		n += proto.SizeVarint(uint64(s))
 		n += s
 	case nil:
@@ -1160,13 +1528,44 @@ func _Response_OneofSizer(msg proto.Message) (n int) {
 
 // nondeterministic
 type ResponseException struct {
-	Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"`
+	Error                string   `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ResponseException) Reset()         { *m = ResponseException{} }
+func (m *ResponseException) String() string { return proto.CompactTextString(m) }
+func (*ResponseException) ProtoMessage()    {}
+func (*ResponseException) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{13}
+}
+func (m *ResponseException) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ResponseException) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ResponseException.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *ResponseException) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResponseException.Merge(dst, src)
+}
+func (m *ResponseException) XXX_Size() int {
+	return m.Size()
+}
+func (m *ResponseException) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResponseException.DiscardUnknown(m)
 }
 
-func (m *ResponseException) Reset()                    { *m = ResponseException{} }
-func (m *ResponseException) String() string            { return proto.CompactTextString(m) }
-func (*ResponseException) ProtoMessage()               {}
-func (*ResponseException) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{13} }
+var xxx_messageInfo_ResponseException proto.InternalMessageInfo
 
 func (m *ResponseException) GetError() string {
 	if m != nil {
@@ -1176,13 +1575,44 @@ func (m *ResponseException) GetError() string {
 }
 
 type ResponseEcho struct {
-	Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
+	Message              string   `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ResponseEcho) Reset()         { *m = ResponseEcho{} }
+func (m *ResponseEcho) String() string { return proto.CompactTextString(m) }
+func (*ResponseEcho) ProtoMessage()    {}
+func (*ResponseEcho) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{14}
+}
+func (m *ResponseEcho) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ResponseEcho) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ResponseEcho.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *ResponseEcho) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResponseEcho.Merge(dst, src)
+}
+func (m *ResponseEcho) XXX_Size() int {
+	return m.Size()
+}
+func (m *ResponseEcho) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResponseEcho.DiscardUnknown(m)
 }
 
-func (m *ResponseEcho) Reset()                    { *m = ResponseEcho{} }
-func (m *ResponseEcho) String() string            { return proto.CompactTextString(m) }
-func (*ResponseEcho) ProtoMessage()               {}
-func (*ResponseEcho) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{14} }
+var xxx_messageInfo_ResponseEcho proto.InternalMessageInfo
 
 func (m *ResponseEcho) GetMessage() string {
 	if m != nil {
@@ -1192,24 +1622,86 @@ func (m *ResponseEcho) GetMessage() string {
 }
 
 type ResponseFlush struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ResponseFlush) Reset()         { *m = ResponseFlush{} }
+func (m *ResponseFlush) String() string { return proto.CompactTextString(m) }
+func (*ResponseFlush) ProtoMessage()    {}
+func (*ResponseFlush) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{15}
+}
+func (m *ResponseFlush) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ResponseFlush) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ResponseFlush.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *ResponseFlush) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResponseFlush.Merge(dst, src)
+}
+func (m *ResponseFlush) XXX_Size() int {
+	return m.Size()
+}
+func (m *ResponseFlush) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResponseFlush.DiscardUnknown(m)
 }
 
-func (m *ResponseFlush) Reset()                    { *m = ResponseFlush{} }
-func (m *ResponseFlush) String() string            { return proto.CompactTextString(m) }
-func (*ResponseFlush) ProtoMessage()               {}
-func (*ResponseFlush) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{15} }
+var xxx_messageInfo_ResponseFlush proto.InternalMessageInfo
 
 type ResponseInfo struct {
-	Data             string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
-	Version          string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
-	LastBlockHeight  int64  `protobuf:"varint,3,opt,name=last_block_height,json=lastBlockHeight,proto3" json:"last_block_height,omitempty"`
-	LastBlockAppHash []byte `protobuf:"bytes,4,opt,name=last_block_app_hash,json=lastBlockAppHash,proto3" json:"last_block_app_hash,omitempty"`
+	Data                 string   `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
+	Version              string   `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
+	LastBlockHeight      int64    `protobuf:"varint,3,opt,name=last_block_height,json=lastBlockHeight,proto3" json:"last_block_height,omitempty"`
+	LastBlockAppHash     []byte   `protobuf:"bytes,4,opt,name=last_block_app_hash,json=lastBlockAppHash,proto3" json:"last_block_app_hash,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ResponseInfo) Reset()         { *m = ResponseInfo{} }
+func (m *ResponseInfo) String() string { return proto.CompactTextString(m) }
+func (*ResponseInfo) ProtoMessage()    {}
+func (*ResponseInfo) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{16}
+}
+func (m *ResponseInfo) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ResponseInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ResponseInfo.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *ResponseInfo) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResponseInfo.Merge(dst, src)
+}
+func (m *ResponseInfo) XXX_Size() int {
+	return m.Size()
+}
+func (m *ResponseInfo) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResponseInfo.DiscardUnknown(m)
 }
 
-func (m *ResponseInfo) Reset()                    { *m = ResponseInfo{} }
-func (m *ResponseInfo) String() string            { return proto.CompactTextString(m) }
-func (*ResponseInfo) ProtoMessage()               {}
-func (*ResponseInfo) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{16} }
+var xxx_messageInfo_ResponseInfo proto.InternalMessageInfo
 
 func (m *ResponseInfo) GetData() string {
 	if m != nil {
@@ -1243,14 +1735,45 @@ func (m *ResponseInfo) GetLastBlockAppHash() []byte {
 type ResponseSetOption struct {
 	Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
 	// bytes data = 2;
-	Log  string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"`
-	Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"`
+	Log                  string   `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"`
+	Info                 string   `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ResponseSetOption) Reset()         { *m = ResponseSetOption{} }
+func (m *ResponseSetOption) String() string { return proto.CompactTextString(m) }
+func (*ResponseSetOption) ProtoMessage()    {}
+func (*ResponseSetOption) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{17}
+}
+func (m *ResponseSetOption) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ResponseSetOption) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ResponseSetOption.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *ResponseSetOption) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResponseSetOption.Merge(dst, src)
+}
+func (m *ResponseSetOption) XXX_Size() int {
+	return m.Size()
+}
+func (m *ResponseSetOption) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResponseSetOption.DiscardUnknown(m)
 }
 
-func (m *ResponseSetOption) Reset()                    { *m = ResponseSetOption{} }
-func (m *ResponseSetOption) String() string            { return proto.CompactTextString(m) }
-func (*ResponseSetOption) ProtoMessage()               {}
-func (*ResponseSetOption) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{17} }
+var xxx_messageInfo_ResponseSetOption proto.InternalMessageInfo
 
 func (m *ResponseSetOption) GetCode() uint32 {
 	if m != nil {
@@ -1274,14 +1797,45 @@ func (m *ResponseSetOption) GetInfo() string {
 }
 
 type ResponseInitChain struct {
-	ConsensusParams *ConsensusParams `protobuf:"bytes,1,opt,name=consensus_params,json=consensusParams" json:"consensus_params,omitempty"`
-	Validators      []Validator      `protobuf:"bytes,2,rep,name=validators" json:"validators"`
+	ConsensusParams      *ConsensusParams `protobuf:"bytes,1,opt,name=consensus_params,json=consensusParams" json:"consensus_params,omitempty"`
+	Validators           []Validator      `protobuf:"bytes,2,rep,name=validators" json:"validators"`
+	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
+	XXX_unrecognized     []byte           `json:"-"`
+	XXX_sizecache        int32            `json:"-"`
+}
+
+func (m *ResponseInitChain) Reset()         { *m = ResponseInitChain{} }
+func (m *ResponseInitChain) String() string { return proto.CompactTextString(m) }
+func (*ResponseInitChain) ProtoMessage()    {}
+func (*ResponseInitChain) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{18}
+}
+func (m *ResponseInitChain) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ResponseInitChain) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ResponseInitChain.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *ResponseInitChain) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResponseInitChain.Merge(dst, src)
+}
+func (m *ResponseInitChain) XXX_Size() int {
+	return m.Size()
+}
+func (m *ResponseInitChain) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResponseInitChain.DiscardUnknown(m)
 }
 
-func (m *ResponseInitChain) Reset()                    { *m = ResponseInitChain{} }
-func (m *ResponseInitChain) String() string            { return proto.CompactTextString(m) }
-func (*ResponseInitChain) ProtoMessage()               {}
-func (*ResponseInitChain) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{18} }
+var xxx_messageInfo_ResponseInitChain proto.InternalMessageInfo
 
 func (m *ResponseInitChain) GetConsensusParams() *ConsensusParams {
 	if m != nil {
@@ -1300,19 +1854,50 @@ func (m *ResponseInitChain) GetValidators() []Validator {
 type ResponseQuery struct {
 	Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
 	// bytes data = 2; // use "value" instead.
-	Log    string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"`
-	Info   string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"`
-	Index  int64  `protobuf:"varint,5,opt,name=index,proto3" json:"index,omitempty"`
-	Key    []byte `protobuf:"bytes,6,opt,name=key,proto3" json:"key,omitempty"`
-	Value  []byte `protobuf:"bytes,7,opt,name=value,proto3" json:"value,omitempty"`
-	Proof  []byte `protobuf:"bytes,8,opt,name=proof,proto3" json:"proof,omitempty"`
-	Height int64  `protobuf:"varint,9,opt,name=height,proto3" json:"height,omitempty"`
+	Log                  string   `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"`
+	Info                 string   `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"`
+	Index                int64    `protobuf:"varint,5,opt,name=index,proto3" json:"index,omitempty"`
+	Key                  []byte   `protobuf:"bytes,6,opt,name=key,proto3" json:"key,omitempty"`
+	Value                []byte   `protobuf:"bytes,7,opt,name=value,proto3" json:"value,omitempty"`
+	Proof                []byte   `protobuf:"bytes,8,opt,name=proof,proto3" json:"proof,omitempty"`
+	Height               int64    `protobuf:"varint,9,opt,name=height,proto3" json:"height,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ResponseQuery) Reset()         { *m = ResponseQuery{} }
+func (m *ResponseQuery) String() string { return proto.CompactTextString(m) }
+func (*ResponseQuery) ProtoMessage()    {}
+func (*ResponseQuery) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{19}
+}
+func (m *ResponseQuery) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ResponseQuery) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ResponseQuery.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *ResponseQuery) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResponseQuery.Merge(dst, src)
+}
+func (m *ResponseQuery) XXX_Size() int {
+	return m.Size()
+}
+func (m *ResponseQuery) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResponseQuery.DiscardUnknown(m)
 }
 
-func (m *ResponseQuery) Reset()                    { *m = ResponseQuery{} }
-func (m *ResponseQuery) String() string            { return proto.CompactTextString(m) }
-func (*ResponseQuery) ProtoMessage()               {}
-func (*ResponseQuery) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{19} }
+var xxx_messageInfo_ResponseQuery proto.InternalMessageInfo
 
 func (m *ResponseQuery) GetCode() uint32 {
 	if m != nil {
@@ -1371,13 +1956,44 @@ func (m *ResponseQuery) GetHeight() int64 {
 }
 
 type ResponseBeginBlock struct {
-	Tags []common.KVPair `protobuf:"bytes,1,rep,name=tags" json:"tags,omitempty"`
+	Tags                 []common.KVPair `protobuf:"bytes,1,rep,name=tags" json:"tags,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}        `json:"-"`
+	XXX_unrecognized     []byte          `json:"-"`
+	XXX_sizecache        int32           `json:"-"`
+}
+
+func (m *ResponseBeginBlock) Reset()         { *m = ResponseBeginBlock{} }
+func (m *ResponseBeginBlock) String() string { return proto.CompactTextString(m) }
+func (*ResponseBeginBlock) ProtoMessage()    {}
+func (*ResponseBeginBlock) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{20}
+}
+func (m *ResponseBeginBlock) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ResponseBeginBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ResponseBeginBlock.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *ResponseBeginBlock) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResponseBeginBlock.Merge(dst, src)
+}
+func (m *ResponseBeginBlock) XXX_Size() int {
+	return m.Size()
+}
+func (m *ResponseBeginBlock) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResponseBeginBlock.DiscardUnknown(m)
 }
 
-func (m *ResponseBeginBlock) Reset()                    { *m = ResponseBeginBlock{} }
-func (m *ResponseBeginBlock) String() string            { return proto.CompactTextString(m) }
-func (*ResponseBeginBlock) ProtoMessage()               {}
-func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{20} }
+var xxx_messageInfo_ResponseBeginBlock proto.InternalMessageInfo
 
 func (m *ResponseBeginBlock) GetTags() []common.KVPair {
 	if m != nil {
@@ -1387,20 +2003,50 @@ func (m *ResponseBeginBlock) GetTags() []common.KVPair {
 }
 
 type ResponseCheckTx struct {
-	Code      uint32          `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
-	Data      []byte          `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
-	Log       string          `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"`
-	Info      string          `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"`
-	GasWanted int64           `protobuf:"varint,5,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty"`
-	GasUsed   int64           `protobuf:"varint,6,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
-	Tags      []common.KVPair `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"`
-	Fee       common.KI64Pair `protobuf:"bytes,8,opt,name=fee" json:"fee"`
+	Code                 uint32          `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
+	Data                 []byte          `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
+	Log                  string          `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"`
+	Info                 string          `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"`
+	GasWanted            int64           `protobuf:"varint,5,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty"`
+	GasUsed              int64           `protobuf:"varint,6,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
+	Tags                 []common.KVPair `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}        `json:"-"`
+	XXX_unrecognized     []byte          `json:"-"`
+	XXX_sizecache        int32           `json:"-"`
+}
+
+func (m *ResponseCheckTx) Reset()         { *m = ResponseCheckTx{} }
+func (m *ResponseCheckTx) String() string { return proto.CompactTextString(m) }
+func (*ResponseCheckTx) ProtoMessage()    {}
+func (*ResponseCheckTx) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{21}
+}
+func (m *ResponseCheckTx) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ResponseCheckTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ResponseCheckTx.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *ResponseCheckTx) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResponseCheckTx.Merge(dst, src)
+}
+func (m *ResponseCheckTx) XXX_Size() int {
+	return m.Size()
+}
+func (m *ResponseCheckTx) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResponseCheckTx.DiscardUnknown(m)
 }
 
-func (m *ResponseCheckTx) Reset()                    { *m = ResponseCheckTx{} }
-func (m *ResponseCheckTx) String() string            { return proto.CompactTextString(m) }
-func (*ResponseCheckTx) ProtoMessage()               {}
-func (*ResponseCheckTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{21} }
+var xxx_messageInfo_ResponseCheckTx proto.InternalMessageInfo
 
 func (m *ResponseCheckTx) GetCode() uint32 {
 	if m != nil {
@@ -1451,28 +2097,51 @@ func (m *ResponseCheckTx) GetTags() []common.KVPair {
 	return nil
 }
 
-func (m *ResponseCheckTx) GetFee() common.KI64Pair {
-	if m != nil {
-		return m.Fee
+type ResponseDeliverTx struct {
+	Code                 uint32          `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
+	Data                 []byte          `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
+	Log                  string          `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"`
+	Info                 string          `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"`
+	GasWanted            int64           `protobuf:"varint,5,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty"`
+	GasUsed              int64           `protobuf:"varint,6,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
+	Tags                 []common.KVPair `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}        `json:"-"`
+	XXX_unrecognized     []byte          `json:"-"`
+	XXX_sizecache        int32           `json:"-"`
+}
+
+func (m *ResponseDeliverTx) Reset()         { *m = ResponseDeliverTx{} }
+func (m *ResponseDeliverTx) String() string { return proto.CompactTextString(m) }
+func (*ResponseDeliverTx) ProtoMessage()    {}
+func (*ResponseDeliverTx) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{22}
+}
+func (m *ResponseDeliverTx) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ResponseDeliverTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ResponseDeliverTx.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
 	}
-	return common.KI64Pair{}
 }
-
-type ResponseDeliverTx struct {
-	Code      uint32          `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
-	Data      []byte          `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
-	Log       string          `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"`
-	Info      string          `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"`
-	GasWanted int64           `protobuf:"varint,5,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty"`
-	GasUsed   int64           `protobuf:"varint,6,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
-	Tags      []common.KVPair `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"`
-	Fee       common.KI64Pair `protobuf:"bytes,8,opt,name=fee" json:"fee"`
+func (dst *ResponseDeliverTx) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResponseDeliverTx.Merge(dst, src)
+}
+func (m *ResponseDeliverTx) XXX_Size() int {
+	return m.Size()
+}
+func (m *ResponseDeliverTx) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResponseDeliverTx.DiscardUnknown(m)
 }
 
-func (m *ResponseDeliverTx) Reset()                    { *m = ResponseDeliverTx{} }
-func (m *ResponseDeliverTx) String() string            { return proto.CompactTextString(m) }
-func (*ResponseDeliverTx) ProtoMessage()               {}
-func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{22} }
+var xxx_messageInfo_ResponseDeliverTx proto.InternalMessageInfo
 
 func (m *ResponseDeliverTx) GetCode() uint32 {
 	if m != nil {
@@ -1523,23 +2192,47 @@ func (m *ResponseDeliverTx) GetTags() []common.KVPair {
 	return nil
 }
 
-func (m *ResponseDeliverTx) GetFee() common.KI64Pair {
-	if m != nil {
-		return m.Fee
-	}
-	return common.KI64Pair{}
-}
-
 type ResponseEndBlock struct {
 	ValidatorUpdates      []Validator      `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates" json:"validator_updates"`
 	ConsensusParamUpdates *ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates" json:"consensus_param_updates,omitempty"`
 	Tags                  []common.KVPair  `protobuf:"bytes,3,rep,name=tags" json:"tags,omitempty"`
+	XXX_NoUnkeyedLiteral  struct{}         `json:"-"`
+	XXX_unrecognized      []byte           `json:"-"`
+	XXX_sizecache         int32            `json:"-"`
+}
+
+func (m *ResponseEndBlock) Reset()         { *m = ResponseEndBlock{} }
+func (m *ResponseEndBlock) String() string { return proto.CompactTextString(m) }
+func (*ResponseEndBlock) ProtoMessage()    {}
+func (*ResponseEndBlock) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{23}
+}
+func (m *ResponseEndBlock) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ResponseEndBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ResponseEndBlock.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *ResponseEndBlock) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResponseEndBlock.Merge(dst, src)
+}
+func (m *ResponseEndBlock) XXX_Size() int {
+	return m.Size()
+}
+func (m *ResponseEndBlock) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResponseEndBlock.DiscardUnknown(m)
 }
 
-func (m *ResponseEndBlock) Reset()                    { *m = ResponseEndBlock{} }
-func (m *ResponseEndBlock) String() string            { return proto.CompactTextString(m) }
-func (*ResponseEndBlock) ProtoMessage()               {}
-func (*ResponseEndBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{23} }
+var xxx_messageInfo_ResponseEndBlock proto.InternalMessageInfo
 
 func (m *ResponseEndBlock) GetValidatorUpdates() []Validator {
 	if m != nil {
@@ -1564,13 +2257,44 @@ func (m *ResponseEndBlock) GetTags() []common.KVPair {
 
 type ResponseCommit struct {
 	// reserve 1
-	Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
+	Data                 []byte   `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ResponseCommit) Reset()         { *m = ResponseCommit{} }
+func (m *ResponseCommit) String() string { return proto.CompactTextString(m) }
+func (*ResponseCommit) ProtoMessage()    {}
+func (*ResponseCommit) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{24}
+}
+func (m *ResponseCommit) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ResponseCommit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ResponseCommit.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *ResponseCommit) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResponseCommit.Merge(dst, src)
+}
+func (m *ResponseCommit) XXX_Size() int {
+	return m.Size()
+}
+func (m *ResponseCommit) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResponseCommit.DiscardUnknown(m)
 }
 
-func (m *ResponseCommit) Reset()                    { *m = ResponseCommit{} }
-func (m *ResponseCommit) String() string            { return proto.CompactTextString(m) }
-func (*ResponseCommit) ProtoMessage()               {}
-func (*ResponseCommit) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{24} }
+var xxx_messageInfo_ResponseCommit proto.InternalMessageInfo
 
 func (m *ResponseCommit) GetData() []byte {
 	if m != nil {
@@ -1582,15 +2306,46 @@ func (m *ResponseCommit) GetData() []byte {
 // ConsensusParams contains all consensus-relevant parameters
 // that can be adjusted by the abci app
 type ConsensusParams struct {
-	BlockSize   *BlockSize   `protobuf:"bytes,1,opt,name=block_size,json=blockSize" json:"block_size,omitempty"`
-	TxSize      *TxSize      `protobuf:"bytes,2,opt,name=tx_size,json=txSize" json:"tx_size,omitempty"`
-	BlockGossip *BlockGossip `protobuf:"bytes,3,opt,name=block_gossip,json=blockGossip" json:"block_gossip,omitempty"`
+	BlockSize            *BlockSize   `protobuf:"bytes,1,opt,name=block_size,json=blockSize" json:"block_size,omitempty"`
+	TxSize               *TxSize      `protobuf:"bytes,2,opt,name=tx_size,json=txSize" json:"tx_size,omitempty"`
+	BlockGossip          *BlockGossip `protobuf:"bytes,3,opt,name=block_gossip,json=blockGossip" json:"block_gossip,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}     `json:"-"`
+	XXX_unrecognized     []byte       `json:"-"`
+	XXX_sizecache        int32        `json:"-"`
+}
+
+func (m *ConsensusParams) Reset()         { *m = ConsensusParams{} }
+func (m *ConsensusParams) String() string { return proto.CompactTextString(m) }
+func (*ConsensusParams) ProtoMessage()    {}
+func (*ConsensusParams) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{25}
+}
+func (m *ConsensusParams) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ConsensusParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ConsensusParams.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *ConsensusParams) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ConsensusParams.Merge(dst, src)
+}
+func (m *ConsensusParams) XXX_Size() int {
+	return m.Size()
+}
+func (m *ConsensusParams) XXX_DiscardUnknown() {
+	xxx_messageInfo_ConsensusParams.DiscardUnknown(m)
 }
 
-func (m *ConsensusParams) Reset()                    { *m = ConsensusParams{} }
-func (m *ConsensusParams) String() string            { return proto.CompactTextString(m) }
-func (*ConsensusParams) ProtoMessage()               {}
-func (*ConsensusParams) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{25} }
+var xxx_messageInfo_ConsensusParams proto.InternalMessageInfo
 
 func (m *ConsensusParams) GetBlockSize() *BlockSize {
 	if m != nil {
@@ -1613,17 +2368,48 @@ func (m *ConsensusParams) GetBlockGossip() *BlockGossip {
 	return nil
 }
 
-// BlockSize contain limits on the block size.
+// BlockSize contains limits on the block size.
 type BlockSize struct {
-	MaxBytes int32 `protobuf:"varint,1,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"`
-	MaxTxs   int32 `protobuf:"varint,2,opt,name=max_txs,json=maxTxs,proto3" json:"max_txs,omitempty"`
-	MaxGas   int64 `protobuf:"varint,3,opt,name=max_gas,json=maxGas,proto3" json:"max_gas,omitempty"`
+	MaxBytes             int32    `protobuf:"varint,1,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"`
+	MaxTxs               int32    `protobuf:"varint,2,opt,name=max_txs,json=maxTxs,proto3" json:"max_txs,omitempty"`
+	MaxGas               int64    `protobuf:"varint,3,opt,name=max_gas,json=maxGas,proto3" json:"max_gas,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *BlockSize) Reset()         { *m = BlockSize{} }
+func (m *BlockSize) String() string { return proto.CompactTextString(m) }
+func (*BlockSize) ProtoMessage()    {}
+func (*BlockSize) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{26}
+}
+func (m *BlockSize) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *BlockSize) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_BlockSize.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *BlockSize) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_BlockSize.Merge(dst, src)
+}
+func (m *BlockSize) XXX_Size() int {
+	return m.Size()
+}
+func (m *BlockSize) XXX_DiscardUnknown() {
+	xxx_messageInfo_BlockSize.DiscardUnknown(m)
 }
 
-func (m *BlockSize) Reset()                    { *m = BlockSize{} }
-func (m *BlockSize) String() string            { return proto.CompactTextString(m) }
-func (*BlockSize) ProtoMessage()               {}
-func (*BlockSize) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{26} }
+var xxx_messageInfo_BlockSize proto.InternalMessageInfo
 
 func (m *BlockSize) GetMaxBytes() int32 {
 	if m != nil {
@@ -1646,16 +2432,47 @@ func (m *BlockSize) GetMaxGas() int64 {
 	return 0
 }
 
-// TxSize contain limits on the tx size.
+// TxSize contains limits on the tx size.
 type TxSize struct {
-	MaxBytes int32 `protobuf:"varint,1,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"`
-	MaxGas   int64 `protobuf:"varint,2,opt,name=max_gas,json=maxGas,proto3" json:"max_gas,omitempty"`
+	MaxBytes             int32    `protobuf:"varint,1,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"`
+	MaxGas               int64    `protobuf:"varint,2,opt,name=max_gas,json=maxGas,proto3" json:"max_gas,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *TxSize) Reset()         { *m = TxSize{} }
+func (m *TxSize) String() string { return proto.CompactTextString(m) }
+func (*TxSize) ProtoMessage()    {}
+func (*TxSize) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{27}
+}
+func (m *TxSize) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *TxSize) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_TxSize.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *TxSize) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_TxSize.Merge(dst, src)
+}
+func (m *TxSize) XXX_Size() int {
+	return m.Size()
+}
+func (m *TxSize) XXX_DiscardUnknown() {
+	xxx_messageInfo_TxSize.DiscardUnknown(m)
 }
 
-func (m *TxSize) Reset()                    { *m = TxSize{} }
-func (m *TxSize) String() string            { return proto.CompactTextString(m) }
-func (*TxSize) ProtoMessage()               {}
-func (*TxSize) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{27} }
+var xxx_messageInfo_TxSize proto.InternalMessageInfo
 
 func (m *TxSize) GetMaxBytes() int32 {
 	if m != nil {
@@ -1675,13 +2492,44 @@ func (m *TxSize) GetMaxGas() int64 {
 // elements of how blocks are gossiped
 type BlockGossip struct {
 	// Note: must not be 0
-	BlockPartSizeBytes int32 `protobuf:"varint,1,opt,name=block_part_size_bytes,json=blockPartSizeBytes,proto3" json:"block_part_size_bytes,omitempty"`
+	BlockPartSizeBytes   int32    `protobuf:"varint,1,opt,name=block_part_size_bytes,json=blockPartSizeBytes,proto3" json:"block_part_size_bytes,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *BlockGossip) Reset()         { *m = BlockGossip{} }
+func (m *BlockGossip) String() string { return proto.CompactTextString(m) }
+func (*BlockGossip) ProtoMessage()    {}
+func (*BlockGossip) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{28}
+}
+func (m *BlockGossip) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *BlockGossip) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_BlockGossip.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *BlockGossip) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_BlockGossip.Merge(dst, src)
+}
+func (m *BlockGossip) XXX_Size() int {
+	return m.Size()
+}
+func (m *BlockGossip) XXX_DiscardUnknown() {
+	xxx_messageInfo_BlockGossip.DiscardUnknown(m)
 }
 
-func (m *BlockGossip) Reset()                    { *m = BlockGossip{} }
-func (m *BlockGossip) String() string            { return proto.CompactTextString(m) }
-func (*BlockGossip) ProtoMessage()               {}
-func (*BlockGossip) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{28} }
+var xxx_messageInfo_BlockGossip proto.InternalMessageInfo
 
 func (m *BlockGossip) GetBlockPartSizeBytes() int32 {
 	if m != nil {
@@ -1690,12 +2538,67 @@ func (m *BlockGossip) GetBlockPartSizeBytes() int32 {
 	return 0
 }
 
+type LastCommitInfo struct {
+	CommitRound          int32              `protobuf:"varint,1,opt,name=commit_round,json=commitRound,proto3" json:"commit_round,omitempty"`
+	Validators           []SigningValidator `protobuf:"bytes,2,rep,name=validators" json:"validators"`
+	XXX_NoUnkeyedLiteral struct{}           `json:"-"`
+	XXX_unrecognized     []byte             `json:"-"`
+	XXX_sizecache        int32              `json:"-"`
+}
+
+func (m *LastCommitInfo) Reset()         { *m = LastCommitInfo{} }
+func (m *LastCommitInfo) String() string { return proto.CompactTextString(m) }
+func (*LastCommitInfo) ProtoMessage()    {}
+func (*LastCommitInfo) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{29}
+}
+func (m *LastCommitInfo) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *LastCommitInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_LastCommitInfo.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *LastCommitInfo) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_LastCommitInfo.Merge(dst, src)
+}
+func (m *LastCommitInfo) XXX_Size() int {
+	return m.Size()
+}
+func (m *LastCommitInfo) XXX_DiscardUnknown() {
+	xxx_messageInfo_LastCommitInfo.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_LastCommitInfo proto.InternalMessageInfo
+
+func (m *LastCommitInfo) GetCommitRound() int32 {
+	if m != nil {
+		return m.CommitRound
+	}
+	return 0
+}
+
+func (m *LastCommitInfo) GetValidators() []SigningValidator {
+	if m != nil {
+		return m.Validators
+	}
+	return nil
+}
+
 // just the minimum the app might need
 type Header struct {
 	// basics
-	ChainID string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
-	Height  int64  `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"`
-	Time    int64  `protobuf:"varint,3,opt,name=time,proto3" json:"time,omitempty"`
+	ChainID string    `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
+	Height  int64     `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"`
+	Time    time.Time `protobuf:"bytes,3,opt,name=time,stdtime" json:"time"`
 	// txs
 	NumTxs   int32 `protobuf:"varint,4,opt,name=num_txs,json=numTxs,proto3" json:"num_txs,omitempty"`
 	TotalTxs int64 `protobuf:"varint,5,opt,name=total_txs,json=totalTxs,proto3" json:"total_txs,omitempty"`
@@ -1704,13 +2607,44 @@ type Header struct {
 	ValidatorsHash []byte `protobuf:"bytes,7,opt,name=validators_hash,json=validatorsHash,proto3" json:"validators_hash,omitempty"`
 	AppHash        []byte `protobuf:"bytes,8,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"`
 	// consensus
-	Proposer Validator `protobuf:"bytes,9,opt,name=proposer" json:"proposer"`
+	Proposer             Validator `protobuf:"bytes,9,opt,name=proposer" json:"proposer"`
+	XXX_NoUnkeyedLiteral struct{}  `json:"-"`
+	XXX_unrecognized     []byte    `json:"-"`
+	XXX_sizecache        int32     `json:"-"`
+}
+
+func (m *Header) Reset()         { *m = Header{} }
+func (m *Header) String() string { return proto.CompactTextString(m) }
+func (*Header) ProtoMessage()    {}
+func (*Header) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{30}
+}
+func (m *Header) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_Header.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *Header) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Header.Merge(dst, src)
+}
+func (m *Header) XXX_Size() int {
+	return m.Size()
+}
+func (m *Header) XXX_DiscardUnknown() {
+	xxx_messageInfo_Header.DiscardUnknown(m)
 }
 
-func (m *Header) Reset()                    { *m = Header{} }
-func (m *Header) String() string            { return proto.CompactTextString(m) }
-func (*Header) ProtoMessage()               {}
-func (*Header) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{29} }
+var xxx_messageInfo_Header proto.InternalMessageInfo
 
 func (m *Header) GetChainID() string {
 	if m != nil {
@@ -1726,11 +2660,11 @@ func (m *Header) GetHeight() int64 {
 	return 0
 }
 
-func (m *Header) GetTime() int64 {
+func (m *Header) GetTime() time.Time {
 	if m != nil {
 		return m.Time
 	}
-	return 0
+	return time.Time{}
 }
 
 func (m *Header) GetNumTxs() int32 {
@@ -1777,15 +2711,46 @@ func (m *Header) GetProposer() Validator {
 
 // Validator
 type Validator struct {
-	Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
-	PubKey  PubKey `protobuf:"bytes,2,opt,name=pub_key,json=pubKey" json:"pub_key"`
-	Power   int64  `protobuf:"varint,3,opt,name=power,proto3" json:"power,omitempty"`
+	Address              []byte   `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+	PubKey               PubKey   `protobuf:"bytes,2,opt,name=pub_key,json=pubKey" json:"pub_key"`
+	Power                int64    `protobuf:"varint,3,opt,name=power,proto3" json:"power,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Validator) Reset()         { *m = Validator{} }
+func (m *Validator) String() string { return proto.CompactTextString(m) }
+func (*Validator) ProtoMessage()    {}
+func (*Validator) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{31}
+}
+func (m *Validator) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Validator) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_Validator.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *Validator) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Validator.Merge(dst, src)
+}
+func (m *Validator) XXX_Size() int {
+	return m.Size()
+}
+func (m *Validator) XXX_DiscardUnknown() {
+	xxx_messageInfo_Validator.DiscardUnknown(m)
 }
 
-func (m *Validator) Reset()                    { *m = Validator{} }
-func (m *Validator) String() string            { return proto.CompactTextString(m) }
-func (*Validator) ProtoMessage()               {}
-func (*Validator) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{30} }
+var xxx_messageInfo_Validator proto.InternalMessageInfo
 
 func (m *Validator) GetAddress() []byte {
 	if m != nil {
@@ -1810,14 +2775,45 @@ func (m *Validator) GetPower() int64 {
 
 // Validator with an extra bool
 type SigningValidator struct {
-	Validator       Validator `protobuf:"bytes,1,opt,name=validator" json:"validator"`
-	SignedLastBlock bool      `protobuf:"varint,2,opt,name=signed_last_block,json=signedLastBlock,proto3" json:"signed_last_block,omitempty"`
+	Validator            Validator `protobuf:"bytes,1,opt,name=validator" json:"validator"`
+	SignedLastBlock      bool      `protobuf:"varint,2,opt,name=signed_last_block,json=signedLastBlock,proto3" json:"signed_last_block,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}  `json:"-"`
+	XXX_unrecognized     []byte    `json:"-"`
+	XXX_sizecache        int32     `json:"-"`
+}
+
+func (m *SigningValidator) Reset()         { *m = SigningValidator{} }
+func (m *SigningValidator) String() string { return proto.CompactTextString(m) }
+func (*SigningValidator) ProtoMessage()    {}
+func (*SigningValidator) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{32}
+}
+func (m *SigningValidator) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *SigningValidator) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_SigningValidator.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *SigningValidator) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_SigningValidator.Merge(dst, src)
+}
+func (m *SigningValidator) XXX_Size() int {
+	return m.Size()
+}
+func (m *SigningValidator) XXX_DiscardUnknown() {
+	xxx_messageInfo_SigningValidator.DiscardUnknown(m)
 }
 
-func (m *SigningValidator) Reset()                    { *m = SigningValidator{} }
-func (m *SigningValidator) String() string            { return proto.CompactTextString(m) }
-func (*SigningValidator) ProtoMessage()               {}
-func (*SigningValidator) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{31} }
+var xxx_messageInfo_SigningValidator proto.InternalMessageInfo
 
 func (m *SigningValidator) GetValidator() Validator {
 	if m != nil {
@@ -1834,14 +2830,45 @@ func (m *SigningValidator) GetSignedLastBlock() bool {
 }
 
 type PubKey struct {
-	Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
-	Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
+	Type                 string   `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
+	Data                 []byte   `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *PubKey) Reset()         { *m = PubKey{} }
+func (m *PubKey) String() string { return proto.CompactTextString(m) }
+func (*PubKey) ProtoMessage()    {}
+func (*PubKey) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{33}
+}
+func (m *PubKey) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *PubKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_PubKey.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *PubKey) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PubKey.Merge(dst, src)
+}
+func (m *PubKey) XXX_Size() int {
+	return m.Size()
+}
+func (m *PubKey) XXX_DiscardUnknown() {
+	xxx_messageInfo_PubKey.DiscardUnknown(m)
 }
 
-func (m *PubKey) Reset()                    { *m = PubKey{} }
-func (m *PubKey) String() string            { return proto.CompactTextString(m) }
-func (*PubKey) ProtoMessage()               {}
-func (*PubKey) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{32} }
+var xxx_messageInfo_PubKey proto.InternalMessageInfo
 
 func (m *PubKey) GetType() string {
 	if m != nil {
@@ -1858,17 +2885,48 @@ func (m *PubKey) GetData() []byte {
 }
 
 type Evidence struct {
-	Type             string    `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
-	Validator        Validator `protobuf:"bytes,2,opt,name=validator" json:"validator"`
-	Height           int64     `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"`
-	Time             int64     `protobuf:"varint,4,opt,name=time,proto3" json:"time,omitempty"`
-	TotalVotingPower int64     `protobuf:"varint,5,opt,name=total_voting_power,json=totalVotingPower,proto3" json:"total_voting_power,omitempty"`
+	Type                 string    `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
+	Validator            Validator `protobuf:"bytes,2,opt,name=validator" json:"validator"`
+	Height               int64     `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"`
+	Time                 time.Time `protobuf:"bytes,4,opt,name=time,stdtime" json:"time"`
+	TotalVotingPower     int64     `protobuf:"varint,5,opt,name=total_voting_power,json=totalVotingPower,proto3" json:"total_voting_power,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}  `json:"-"`
+	XXX_unrecognized     []byte    `json:"-"`
+	XXX_sizecache        int32     `json:"-"`
+}
+
+func (m *Evidence) Reset()         { *m = Evidence{} }
+func (m *Evidence) String() string { return proto.CompactTextString(m) }
+func (*Evidence) ProtoMessage()    {}
+func (*Evidence) Descriptor() ([]byte, []int) {
+	return fileDescriptor_types_d8da2202f45d32c0, []int{34}
+}
+func (m *Evidence) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *Evidence) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_Evidence.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (dst *Evidence) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Evidence.Merge(dst, src)
+}
+func (m *Evidence) XXX_Size() int {
+	return m.Size()
+}
+func (m *Evidence) XXX_DiscardUnknown() {
+	xxx_messageInfo_Evidence.DiscardUnknown(m)
 }
 
-func (m *Evidence) Reset()                    { *m = Evidence{} }
-func (m *Evidence) String() string            { return proto.CompactTextString(m) }
-func (*Evidence) ProtoMessage()               {}
-func (*Evidence) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{33} }
+var xxx_messageInfo_Evidence proto.InternalMessageInfo
 
 func (m *Evidence) GetType() string {
 	if m != nil {
@@ -1891,11 +2949,11 @@ func (m *Evidence) GetHeight() int64 {
 	return 0
 }
 
-func (m *Evidence) GetTime() int64 {
+func (m *Evidence) GetTime() time.Time {
 	if m != nil {
 		return m.Time
 	}
-	return 0
+	return time.Time{}
 }
 
 func (m *Evidence) GetTotalVotingPower() int64 {
@@ -1964,6 +3022,8 @@ func init() {
 	golang_proto.RegisterType((*TxSize)(nil), "types.TxSize")
 	proto.RegisterType((*BlockGossip)(nil), "types.BlockGossip")
 	golang_proto.RegisterType((*BlockGossip)(nil), "types.BlockGossip")
+	proto.RegisterType((*LastCommitInfo)(nil), "types.LastCommitInfo")
+	golang_proto.RegisterType((*LastCommitInfo)(nil), "types.LastCommitInfo")
 	proto.RegisterType((*Header)(nil), "types.Header")
 	golang_proto.RegisterType((*Header)(nil), "types.Header")
 	proto.RegisterType((*Validator)(nil), "types.Validator")
@@ -2003,6 +3063,9 @@ func (this *Request) Equal(that interface{}) bool {
 	} else if !this.Value.Equal(that1.Value) {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *Request_Echo) Equal(that interface{}) bool {
@@ -2291,6 +3354,9 @@ func (this *RequestEcho) Equal(that interface{}) bool {
 	if this.Message != that1.Message {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *RequestFlush) Equal(that interface{}) bool {
@@ -2312,6 +3378,9 @@ func (this *RequestFlush) Equal(that interface{}) bool {
 	} else if this == nil {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *RequestInfo) Equal(that interface{}) bool {
@@ -2336,6 +3405,9 @@ func (this *RequestInfo) Equal(that interface{}) bool {
 	if this.Version != that1.Version {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *RequestSetOption) Equal(that interface{}) bool {
@@ -2363,6 +3435,9 @@ func (this *RequestSetOption) Equal(that interface{}) bool {
 	if this.Value != that1.Value {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *RequestInitChain) Equal(that interface{}) bool {
@@ -2384,7 +3459,7 @@ func (this *RequestInitChain) Equal(that interface{}) bool {
 	} else if this == nil {
 		return false
 	}
-	if this.Time != that1.Time {
+	if !this.Time.Equal(that1.Time) {
 		return false
 	}
 	if this.ChainId != that1.ChainId {
@@ -2404,6 +3479,9 @@ func (this *RequestInitChain) Equal(that interface{}) bool {
 	if !bytes.Equal(this.AppStateBytes, that1.AppStateBytes) {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *RequestQuery) Equal(that interface{}) bool {
@@ -2437,6 +3515,9 @@ func (this *RequestQuery) Equal(that interface{}) bool {
 	if this.Prove != that1.Prove {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *RequestBeginBlock) Equal(that interface{}) bool {
@@ -2464,14 +3545,9 @@ func (this *RequestBeginBlock) Equal(that interface{}) bool {
 	if !this.Header.Equal(&that1.Header) {
 		return false
 	}
-	if len(this.Validators) != len(that1.Validators) {
+	if !this.LastCommitInfo.Equal(&that1.LastCommitInfo) {
 		return false
 	}
-	for i := range this.Validators {
-		if !this.Validators[i].Equal(&that1.Validators[i]) {
-			return false
-		}
-	}
 	if len(this.ByzantineValidators) != len(that1.ByzantineValidators) {
 		return false
 	}
@@ -2480,6 +3556,9 @@ func (this *RequestBeginBlock) Equal(that interface{}) bool {
 			return false
 		}
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *RequestCheckTx) Equal(that interface{}) bool {
@@ -2504,6 +3583,9 @@ func (this *RequestCheckTx) Equal(that interface{}) bool {
 	if !bytes.Equal(this.Tx, that1.Tx) {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *RequestDeliverTx) Equal(that interface{}) bool {
@@ -2528,6 +3610,9 @@ func (this *RequestDeliverTx) Equal(that interface{}) bool {
 	if !bytes.Equal(this.Tx, that1.Tx) {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *RequestEndBlock) Equal(that interface{}) bool {
@@ -2552,6 +3637,9 @@ func (this *RequestEndBlock) Equal(that interface{}) bool {
 	if this.Height != that1.Height {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *RequestCommit) Equal(that interface{}) bool {
@@ -2573,6 +3661,9 @@ func (this *RequestCommit) Equal(that interface{}) bool {
 	} else if this == nil {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *Response) Equal(that interface{}) bool {
@@ -2603,6 +3694,9 @@ func (this *Response) Equal(that interface{}) bool {
 	} else if !this.Value.Equal(that1.Value) {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *Response_Exception) Equal(that interface{}) bool {
@@ -2915,6 +4009,9 @@ func (this *ResponseException) Equal(that interface{}) bool {
 	if this.Error != that1.Error {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *ResponseEcho) Equal(that interface{}) bool {
@@ -2939,6 +4036,9 @@ func (this *ResponseEcho) Equal(that interface{}) bool {
 	if this.Message != that1.Message {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *ResponseFlush) Equal(that interface{}) bool {
@@ -2960,6 +4060,9 @@ func (this *ResponseFlush) Equal(that interface{}) bool {
 	} else if this == nil {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *ResponseInfo) Equal(that interface{}) bool {
@@ -2993,6 +4096,9 @@ func (this *ResponseInfo) Equal(that interface{}) bool {
 	if !bytes.Equal(this.LastBlockAppHash, that1.LastBlockAppHash) {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *ResponseSetOption) Equal(that interface{}) bool {
@@ -3023,6 +4129,9 @@ func (this *ResponseSetOption) Equal(that interface{}) bool {
 	if this.Info != that1.Info {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *ResponseInitChain) Equal(that interface{}) bool {
@@ -3055,6 +4164,9 @@ func (this *ResponseInitChain) Equal(that interface{}) bool {
 			return false
 		}
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *ResponseQuery) Equal(that interface{}) bool {
@@ -3100,6 +4212,9 @@ func (this *ResponseQuery) Equal(that interface{}) bool {
 	if this.Height != that1.Height {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *ResponseBeginBlock) Equal(that interface{}) bool {
@@ -3129,6 +4244,9 @@ func (this *ResponseBeginBlock) Equal(that interface{}) bool {
 			return false
 		}
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *ResponseCheckTx) Equal(that interface{}) bool {
@@ -3176,7 +4294,7 @@ func (this *ResponseCheckTx) Equal(that interface{}) bool {
 			return false
 		}
 	}
-	if !this.Fee.Equal(&that1.Fee) {
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
 		return false
 	}
 	return true
@@ -3226,7 +4344,7 @@ func (this *ResponseDeliverTx) Equal(that interface{}) bool {
 			return false
 		}
 	}
-	if !this.Fee.Equal(&that1.Fee) {
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
 		return false
 	}
 	return true
@@ -3269,6 +4387,9 @@ func (this *ResponseEndBlock) Equal(that interface{}) bool {
 			return false
 		}
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *ResponseCommit) Equal(that interface{}) bool {
@@ -3293,6 +4414,9 @@ func (this *ResponseCommit) Equal(that interface{}) bool {
 	if !bytes.Equal(this.Data, that1.Data) {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *ConsensusParams) Equal(that interface{}) bool {
@@ -3323,6 +4447,9 @@ func (this *ConsensusParams) Equal(that interface{}) bool {
 	if !this.BlockGossip.Equal(that1.BlockGossip) {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *BlockSize) Equal(that interface{}) bool {
@@ -3353,6 +4480,9 @@ func (this *BlockSize) Equal(that interface{}) bool {
 	if this.MaxGas != that1.MaxGas {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *TxSize) Equal(that interface{}) bool {
@@ -3380,6 +4510,9 @@ func (this *TxSize) Equal(that interface{}) bool {
 	if this.MaxGas != that1.MaxGas {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *BlockGossip) Equal(that interface{}) bool {
@@ -3404,6 +4537,44 @@ func (this *BlockGossip) Equal(that interface{}) bool {
 	if this.BlockPartSizeBytes != that1.BlockPartSizeBytes {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
+	return true
+}
+func (this *LastCommitInfo) Equal(that interface{}) bool {
+	if that == nil {
+		return this == nil
+	}
+
+	that1, ok := that.(*LastCommitInfo)
+	if !ok {
+		that2, ok := that.(LastCommitInfo)
+		if ok {
+			that1 = &that2
+		} else {
+			return false
+		}
+	}
+	if that1 == nil {
+		return this == nil
+	} else if this == nil {
+		return false
+	}
+	if this.CommitRound != that1.CommitRound {
+		return false
+	}
+	if len(this.Validators) != len(that1.Validators) {
+		return false
+	}
+	for i := range this.Validators {
+		if !this.Validators[i].Equal(&that1.Validators[i]) {
+			return false
+		}
+	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *Header) Equal(that interface{}) bool {
@@ -3431,7 +4602,7 @@ func (this *Header) Equal(that interface{}) bool {
 	if this.Height != that1.Height {
 		return false
 	}
-	if this.Time != that1.Time {
+	if !this.Time.Equal(that1.Time) {
 		return false
 	}
 	if this.NumTxs != that1.NumTxs {
@@ -3452,6 +4623,9 @@ func (this *Header) Equal(that interface{}) bool {
 	if !this.Proposer.Equal(&that1.Proposer) {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *Validator) Equal(that interface{}) bool {
@@ -3482,6 +4656,9 @@ func (this *Validator) Equal(that interface{}) bool {
 	if this.Power != that1.Power {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *SigningValidator) Equal(that interface{}) bool {
@@ -3509,6 +4686,9 @@ func (this *SigningValidator) Equal(that interface{}) bool {
 	if this.SignedLastBlock != that1.SignedLastBlock {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *PubKey) Equal(that interface{}) bool {
@@ -3536,6 +4716,9 @@ func (this *PubKey) Equal(that interface{}) bool {
 	if !bytes.Equal(this.Data, that1.Data) {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 func (this *Evidence) Equal(that interface{}) bool {
@@ -3566,12 +4749,15 @@ func (this *Evidence) Equal(that interface{}) bool {
 	if this.Height != that1.Height {
 		return false
 	}
-	if this.Time != that1.Time {
+	if !this.Time.Equal(that1.Time) {
 		return false
 	}
 	if this.TotalVotingPower != that1.TotalVotingPower {
 		return false
 	}
+	if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
+		return false
+	}
 	return true
 }
 
@@ -3609,7 +4795,7 @@ func NewABCIApplicationClient(cc *grpc.ClientConn) ABCIApplicationClient {
 
 func (c *aBCIApplicationClient) Echo(ctx context.Context, in *RequestEcho, opts ...grpc.CallOption) (*ResponseEcho, error) {
 	out := new(ResponseEcho)
-	err := grpc.Invoke(ctx, "/types.ABCIApplication/Echo", in, out, c.cc, opts...)
+	err := c.cc.Invoke(ctx, "/types.ABCIApplication/Echo", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -3618,7 +4804,7 @@ func (c *aBCIApplicationClient) Echo(ctx context.Context, in *RequestEcho, opts
 
 func (c *aBCIApplicationClient) Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) {
 	out := new(ResponseFlush)
-	err := grpc.Invoke(ctx, "/types.ABCIApplication/Flush", in, out, c.cc, opts...)
+	err := c.cc.Invoke(ctx, "/types.ABCIApplication/Flush", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -3627,7 +4813,7 @@ func (c *aBCIApplicationClient) Flush(ctx context.Context, in *RequestFlush, opt
 
 func (c *aBCIApplicationClient) Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) {
 	out := new(ResponseInfo)
-	err := grpc.Invoke(ctx, "/types.ABCIApplication/Info", in, out, c.cc, opts...)
+	err := c.cc.Invoke(ctx, "/types.ABCIApplication/Info", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -3636,7 +4822,7 @@ func (c *aBCIApplicationClient) Info(ctx context.Context, in *RequestInfo, opts
 
 func (c *aBCIApplicationClient) SetOption(ctx context.Context, in *RequestSetOption, opts ...grpc.CallOption) (*ResponseSetOption, error) {
 	out := new(ResponseSetOption)
-	err := grpc.Invoke(ctx, "/types.ABCIApplication/SetOption", in, out, c.cc, opts...)
+	err := c.cc.Invoke(ctx, "/types.ABCIApplication/SetOption", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -3645,7 +4831,7 @@ func (c *aBCIApplicationClient) SetOption(ctx context.Context, in *RequestSetOpt
 
 func (c *aBCIApplicationClient) DeliverTx(ctx context.Context, in *RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) {
 	out := new(ResponseDeliverTx)
-	err := grpc.Invoke(ctx, "/types.ABCIApplication/DeliverTx", in, out, c.cc, opts...)
+	err := c.cc.Invoke(ctx, "/types.ABCIApplication/DeliverTx", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -3654,7 +4840,7 @@ func (c *aBCIApplicationClient) DeliverTx(ctx context.Context, in *RequestDelive
 
 func (c *aBCIApplicationClient) CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) {
 	out := new(ResponseCheckTx)
-	err := grpc.Invoke(ctx, "/types.ABCIApplication/CheckTx", in, out, c.cc, opts...)
+	err := c.cc.Invoke(ctx, "/types.ABCIApplication/CheckTx", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -3663,7 +4849,7 @@ func (c *aBCIApplicationClient) CheckTx(ctx context.Context, in *RequestCheckTx,
 
 func (c *aBCIApplicationClient) Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) {
 	out := new(ResponseQuery)
-	err := grpc.Invoke(ctx, "/types.ABCIApplication/Query", in, out, c.cc, opts...)
+	err := c.cc.Invoke(ctx, "/types.ABCIApplication/Query", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -3672,7 +4858,7 @@ func (c *aBCIApplicationClient) Query(ctx context.Context, in *RequestQuery, opt
 
 func (c *aBCIApplicationClient) Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) {
 	out := new(ResponseCommit)
-	err := grpc.Invoke(ctx, "/types.ABCIApplication/Commit", in, out, c.cc, opts...)
+	err := c.cc.Invoke(ctx, "/types.ABCIApplication/Commit", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -3681,7 +4867,7 @@ func (c *aBCIApplicationClient) Commit(ctx context.Context, in *RequestCommit, o
 
 func (c *aBCIApplicationClient) InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) {
 	out := new(ResponseInitChain)
-	err := grpc.Invoke(ctx, "/types.ABCIApplication/InitChain", in, out, c.cc, opts...)
+	err := c.cc.Invoke(ctx, "/types.ABCIApplication/InitChain", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -3690,7 +4876,7 @@ func (c *aBCIApplicationClient) InitChain(ctx context.Context, in *RequestInitCh
 
 func (c *aBCIApplicationClient) BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) {
 	out := new(ResponseBeginBlock)
-	err := grpc.Invoke(ctx, "/types.ABCIApplication/BeginBlock", in, out, c.cc, opts...)
+	err := c.cc.Invoke(ctx, "/types.ABCIApplication/BeginBlock", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -3699,7 +4885,7 @@ func (c *aBCIApplicationClient) BeginBlock(ctx context.Context, in *RequestBegin
 
 func (c *aBCIApplicationClient) EndBlock(ctx context.Context, in *RequestEndBlock, opts ...grpc.CallOption) (*ResponseEndBlock, error) {
 	out := new(ResponseEndBlock)
-	err := grpc.Invoke(ctx, "/types.ABCIApplication/EndBlock", in, out, c.cc, opts...)
+	err := c.cc.Invoke(ctx, "/types.ABCIApplication/EndBlock", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -3999,6 +5185,9 @@ func (m *Request) MarshalTo(dAtA []byte) (int, error) {
 		}
 		i += nn1
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4179,6 +5368,9 @@ func (m *RequestEcho) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintTypes(dAtA, i, uint64(len(m.Message)))
 		i += copy(dAtA[i:], m.Message)
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4197,6 +5389,9 @@ func (m *RequestFlush) MarshalTo(dAtA []byte) (int, error) {
 	_ = i
 	var l int
 	_ = l
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4221,6 +5416,9 @@ func (m *RequestInfo) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintTypes(dAtA, i, uint64(len(m.Version)))
 		i += copy(dAtA[i:], m.Version)
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4251,6 +5449,9 @@ func (m *RequestSetOption) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintTypes(dAtA, i, uint64(len(m.Value)))
 		i += copy(dAtA[i:], m.Value)
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4269,11 +5470,14 @@ func (m *RequestInitChain) MarshalTo(dAtA []byte) (int, error) {
 	_ = i
 	var l int
 	_ = l
-	if m.Time != 0 {
-		dAtA[i] = 0x8
-		i++
-		i = encodeVarintTypes(dAtA, i, uint64(m.Time))
+	dAtA[i] = 0xa
+	i++
+	i = encodeVarintTypes(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Time)))
+	n13, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i:])
+	if err != nil {
+		return 0, err
 	}
+	i += n13
 	if len(m.ChainId) > 0 {
 		dAtA[i] = 0x12
 		i++
@@ -4284,11 +5488,11 @@ func (m *RequestInitChain) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x1a
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.ConsensusParams.Size()))
-		n13, err := m.ConsensusParams.MarshalTo(dAtA[i:])
+		n14, err := m.ConsensusParams.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n13
+		i += n14
 	}
 	if len(m.Validators) > 0 {
 		for _, msg := range m.Validators {
@@ -4308,6 +5512,9 @@ func (m *RequestInitChain) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintTypes(dAtA, i, uint64(len(m.AppStateBytes)))
 		i += copy(dAtA[i:], m.AppStateBytes)
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4353,6 +5560,9 @@ func (m *RequestQuery) MarshalTo(dAtA []byte) (int, error) {
 		}
 		i++
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4380,23 +5590,19 @@ func (m *RequestBeginBlock) MarshalTo(dAtA []byte) (int, error) {
 	dAtA[i] = 0x12
 	i++
 	i = encodeVarintTypes(dAtA, i, uint64(m.Header.Size()))
-	n14, err := m.Header.MarshalTo(dAtA[i:])
+	n15, err := m.Header.MarshalTo(dAtA[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n14
-	if len(m.Validators) > 0 {
-		for _, msg := range m.Validators {
-			dAtA[i] = 0x1a
-			i++
-			i = encodeVarintTypes(dAtA, i, uint64(msg.Size()))
-			n, err := msg.MarshalTo(dAtA[i:])
-			if err != nil {
-				return 0, err
-			}
-			i += n
-		}
+	i += n15
+	dAtA[i] = 0x1a
+	i++
+	i = encodeVarintTypes(dAtA, i, uint64(m.LastCommitInfo.Size()))
+	n16, err := m.LastCommitInfo.MarshalTo(dAtA[i:])
+	if err != nil {
+		return 0, err
 	}
+	i += n16
 	if len(m.ByzantineValidators) > 0 {
 		for _, msg := range m.ByzantineValidators {
 			dAtA[i] = 0x22
@@ -4409,6 +5615,9 @@ func (m *RequestBeginBlock) MarshalTo(dAtA []byte) (int, error) {
 			i += n
 		}
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4433,6 +5642,9 @@ func (m *RequestCheckTx) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintTypes(dAtA, i, uint64(len(m.Tx)))
 		i += copy(dAtA[i:], m.Tx)
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4457,6 +5669,9 @@ func (m *RequestDeliverTx) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintTypes(dAtA, i, uint64(len(m.Tx)))
 		i += copy(dAtA[i:], m.Tx)
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4480,6 +5695,9 @@ func (m *RequestEndBlock) MarshalTo(dAtA []byte) (int, error) {
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.Height))
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4498,6 +5716,9 @@ func (m *RequestCommit) MarshalTo(dAtA []byte) (int, error) {
 	_ = i
 	var l int
 	_ = l
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4517,11 +5738,14 @@ func (m *Response) MarshalTo(dAtA []byte) (int, error) {
 	var l int
 	_ = l
 	if m.Value != nil {
-		nn15, err := m.Value.MarshalTo(dAtA[i:])
+		nn17, err := m.Value.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += nn15
+		i += nn17
+	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
 	}
 	return i, nil
 }
@@ -4532,11 +5756,11 @@ func (m *Response_Exception) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0xa
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.Exception.Size()))
-		n16, err := m.Exception.MarshalTo(dAtA[i:])
+		n18, err := m.Exception.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n16
+		i += n18
 	}
 	return i, nil
 }
@@ -4546,11 +5770,11 @@ func (m *Response_Echo) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x12
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.Echo.Size()))
-		n17, err := m.Echo.MarshalTo(dAtA[i:])
+		n19, err := m.Echo.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n17
+		i += n19
 	}
 	return i, nil
 }
@@ -4560,11 +5784,11 @@ func (m *Response_Flush) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x1a
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.Flush.Size()))
-		n18, err := m.Flush.MarshalTo(dAtA[i:])
+		n20, err := m.Flush.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n18
+		i += n20
 	}
 	return i, nil
 }
@@ -4574,11 +5798,11 @@ func (m *Response_Info) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x22
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.Info.Size()))
-		n19, err := m.Info.MarshalTo(dAtA[i:])
+		n21, err := m.Info.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n19
+		i += n21
 	}
 	return i, nil
 }
@@ -4588,11 +5812,11 @@ func (m *Response_SetOption) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x2a
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.SetOption.Size()))
-		n20, err := m.SetOption.MarshalTo(dAtA[i:])
+		n22, err := m.SetOption.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n20
+		i += n22
 	}
 	return i, nil
 }
@@ -4602,11 +5826,11 @@ func (m *Response_InitChain) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x32
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.InitChain.Size()))
-		n21, err := m.InitChain.MarshalTo(dAtA[i:])
+		n23, err := m.InitChain.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n21
+		i += n23
 	}
 	return i, nil
 }
@@ -4616,11 +5840,11 @@ func (m *Response_Query) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x3a
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.Query.Size()))
-		n22, err := m.Query.MarshalTo(dAtA[i:])
+		n24, err := m.Query.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n22
+		i += n24
 	}
 	return i, nil
 }
@@ -4630,11 +5854,11 @@ func (m *Response_BeginBlock) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x42
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.BeginBlock.Size()))
-		n23, err := m.BeginBlock.MarshalTo(dAtA[i:])
+		n25, err := m.BeginBlock.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n23
+		i += n25
 	}
 	return i, nil
 }
@@ -4644,11 +5868,11 @@ func (m *Response_CheckTx) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x4a
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.CheckTx.Size()))
-		n24, err := m.CheckTx.MarshalTo(dAtA[i:])
+		n26, err := m.CheckTx.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n24
+		i += n26
 	}
 	return i, nil
 }
@@ -4658,11 +5882,11 @@ func (m *Response_DeliverTx) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x52
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.DeliverTx.Size()))
-		n25, err := m.DeliverTx.MarshalTo(dAtA[i:])
+		n27, err := m.DeliverTx.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n25
+		i += n27
 	}
 	return i, nil
 }
@@ -4672,11 +5896,11 @@ func (m *Response_EndBlock) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x5a
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.EndBlock.Size()))
-		n26, err := m.EndBlock.MarshalTo(dAtA[i:])
+		n28, err := m.EndBlock.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n26
+		i += n28
 	}
 	return i, nil
 }
@@ -4686,11 +5910,11 @@ func (m *Response_Commit) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x62
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.Commit.Size()))
-		n27, err := m.Commit.MarshalTo(dAtA[i:])
+		n29, err := m.Commit.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n27
+		i += n29
 	}
 	return i, nil
 }
@@ -4715,6 +5939,9 @@ func (m *ResponseException) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintTypes(dAtA, i, uint64(len(m.Error)))
 		i += copy(dAtA[i:], m.Error)
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4739,6 +5966,9 @@ func (m *ResponseEcho) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintTypes(dAtA, i, uint64(len(m.Message)))
 		i += copy(dAtA[i:], m.Message)
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4757,6 +5987,9 @@ func (m *ResponseFlush) MarshalTo(dAtA []byte) (int, error) {
 	_ = i
 	var l int
 	_ = l
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4798,6 +6031,9 @@ func (m *ResponseInfo) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintTypes(dAtA, i, uint64(len(m.LastBlockAppHash)))
 		i += copy(dAtA[i:], m.LastBlockAppHash)
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4833,6 +6069,9 @@ func (m *ResponseSetOption) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintTypes(dAtA, i, uint64(len(m.Info)))
 		i += copy(dAtA[i:], m.Info)
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4855,11 +6094,11 @@ func (m *ResponseInitChain) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0xa
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.ConsensusParams.Size()))
-		n28, err := m.ConsensusParams.MarshalTo(dAtA[i:])
+		n30, err := m.ConsensusParams.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n28
+		i += n30
 	}
 	if len(m.Validators) > 0 {
 		for _, msg := range m.Validators {
@@ -4873,6 +6112,9 @@ func (m *ResponseInitChain) MarshalTo(dAtA []byte) (int, error) {
 			i += n
 		}
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4936,6 +6178,9 @@ func (m *ResponseQuery) MarshalTo(dAtA []byte) (int, error) {
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.Height))
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -4966,6 +6211,9 @@ func (m *ResponseBeginBlock) MarshalTo(dAtA []byte) (int, error) {
 			i += n
 		}
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -5029,14 +6277,9 @@ func (m *ResponseCheckTx) MarshalTo(dAtA []byte) (int, error) {
 			i += n
 		}
 	}
-	dAtA[i] = 0x42
-	i++
-	i = encodeVarintTypes(dAtA, i, uint64(m.Fee.Size()))
-	n29, err := m.Fee.MarshalTo(dAtA[i:])
-	if err != nil {
-		return 0, err
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
 	}
-	i += n29
 	return i, nil
 }
 
@@ -5100,14 +6343,9 @@ func (m *ResponseDeliverTx) MarshalTo(dAtA []byte) (int, error) {
 			i += n
 		}
 	}
-	dAtA[i] = 0x42
-	i++
-	i = encodeVarintTypes(dAtA, i, uint64(m.Fee.Size()))
-	n30, err := m.Fee.MarshalTo(dAtA[i:])
-	if err != nil {
-		return 0, err
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
 	}
-	i += n30
 	return i, nil
 }
 
@@ -5160,6 +6398,9 @@ func (m *ResponseEndBlock) MarshalTo(dAtA []byte) (int, error) {
 			i += n
 		}
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -5184,6 +6425,9 @@ func (m *ResponseCommit) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintTypes(dAtA, i, uint64(len(m.Data)))
 		i += copy(dAtA[i:], m.Data)
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -5232,6 +6476,9 @@ func (m *ConsensusParams) MarshalTo(dAtA []byte) (int, error) {
 		}
 		i += n34
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -5265,6 +6512,9 @@ func (m *BlockSize) MarshalTo(dAtA []byte) (int, error) {
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.MaxGas))
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -5293,6 +6543,9 @@ func (m *TxSize) MarshalTo(dAtA []byte) (int, error) {
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.MaxGas))
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -5316,6 +6569,47 @@ func (m *BlockGossip) MarshalTo(dAtA []byte) (int, error) {
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.BlockPartSizeBytes))
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	return i, nil
+}
+
+func (m *LastCommitInfo) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *LastCommitInfo) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if m.CommitRound != 0 {
+		dAtA[i] = 0x8
+		i++
+		i = encodeVarintTypes(dAtA, i, uint64(m.CommitRound))
+	}
+	if len(m.Validators) > 0 {
+		for _, msg := range m.Validators {
+			dAtA[i] = 0x12
+			i++
+			i = encodeVarintTypes(dAtA, i, uint64(msg.Size()))
+			n, err := msg.MarshalTo(dAtA[i:])
+			if err != nil {
+				return 0, err
+			}
+			i += n
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -5345,11 +6639,14 @@ func (m *Header) MarshalTo(dAtA []byte) (int, error) {
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.Height))
 	}
-	if m.Time != 0 {
-		dAtA[i] = 0x18
-		i++
-		i = encodeVarintTypes(dAtA, i, uint64(m.Time))
+	dAtA[i] = 0x1a
+	i++
+	i = encodeVarintTypes(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Time)))
+	n35, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i:])
+	if err != nil {
+		return 0, err
 	}
+	i += n35
 	if m.NumTxs != 0 {
 		dAtA[i] = 0x20
 		i++
@@ -5381,11 +6678,14 @@ func (m *Header) MarshalTo(dAtA []byte) (int, error) {
 	dAtA[i] = 0x4a
 	i++
 	i = encodeVarintTypes(dAtA, i, uint64(m.Proposer.Size()))
-	n35, err := m.Proposer.MarshalTo(dAtA[i:])
+	n36, err := m.Proposer.MarshalTo(dAtA[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n35
+	i += n36
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -5413,16 +6713,19 @@ func (m *Validator) MarshalTo(dAtA []byte) (int, error) {
 	dAtA[i] = 0x12
 	i++
 	i = encodeVarintTypes(dAtA, i, uint64(m.PubKey.Size()))
-	n36, err := m.PubKey.MarshalTo(dAtA[i:])
+	n37, err := m.PubKey.MarshalTo(dAtA[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n36
+	i += n37
 	if m.Power != 0 {
 		dAtA[i] = 0x18
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.Power))
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -5444,11 +6747,11 @@ func (m *SigningValidator) MarshalTo(dAtA []byte) (int, error) {
 	dAtA[i] = 0xa
 	i++
 	i = encodeVarintTypes(dAtA, i, uint64(m.Validator.Size()))
-	n37, err := m.Validator.MarshalTo(dAtA[i:])
+	n38, err := m.Validator.MarshalTo(dAtA[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n37
+	i += n38
 	if m.SignedLastBlock {
 		dAtA[i] = 0x10
 		i++
@@ -5459,6 +6762,9 @@ func (m *SigningValidator) MarshalTo(dAtA []byte) (int, error) {
 		}
 		i++
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -5489,6 +6795,9 @@ func (m *PubKey) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintTypes(dAtA, i, uint64(len(m.Data)))
 		i += copy(dAtA[i:], m.Data)
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -5516,26 +6825,32 @@ func (m *Evidence) MarshalTo(dAtA []byte) (int, error) {
 	dAtA[i] = 0x12
 	i++
 	i = encodeVarintTypes(dAtA, i, uint64(m.Validator.Size()))
-	n38, err := m.Validator.MarshalTo(dAtA[i:])
+	n39, err := m.Validator.MarshalTo(dAtA[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n38
+	i += n39
 	if m.Height != 0 {
 		dAtA[i] = 0x18
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.Height))
 	}
-	if m.Time != 0 {
-		dAtA[i] = 0x20
-		i++
-		i = encodeVarintTypes(dAtA, i, uint64(m.Time))
+	dAtA[i] = 0x22
+	i++
+	i = encodeVarintTypes(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Time)))
+	n40, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i:])
+	if err != nil {
+		return 0, err
 	}
+	i += n40
 	if m.TotalVotingPower != 0 {
 		dAtA[i] = 0x28
 		i++
 		i = encodeVarintTypes(dAtA, i, uint64(m.TotalVotingPower))
 	}
+	if m.XXX_unrecognized != nil {
+		i += copy(dAtA[i:], m.XXX_unrecognized)
+	}
 	return i, nil
 }
 
@@ -5576,6 +6891,7 @@ func NewPopulatedRequest(r randyTypes, easy bool) *Request {
 		this.Value = NewPopulatedRequest_DeliverTx(r, easy)
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 20)
 	}
 	return this
 }
@@ -5639,6 +6955,7 @@ func NewPopulatedRequestEcho(r randyTypes, easy bool) *RequestEcho {
 	this := &RequestEcho{}
 	this.Message = string(randStringTypes(r))
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 2)
 	}
 	return this
 }
@@ -5646,6 +6963,7 @@ func NewPopulatedRequestEcho(r randyTypes, easy bool) *RequestEcho {
 func NewPopulatedRequestFlush(r randyTypes, easy bool) *RequestFlush {
 	this := &RequestFlush{}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 1)
 	}
 	return this
 }
@@ -5654,6 +6972,7 @@ func NewPopulatedRequestInfo(r randyTypes, easy bool) *RequestInfo {
 	this := &RequestInfo{}
 	this.Version = string(randStringTypes(r))
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 2)
 	}
 	return this
 }
@@ -5663,43 +6982,43 @@ func NewPopulatedRequestSetOption(r randyTypes, easy bool) *RequestSetOption {
 	this.Key = string(randStringTypes(r))
 	this.Value = string(randStringTypes(r))
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 3)
 	}
 	return this
 }
 
 func NewPopulatedRequestInitChain(r randyTypes, easy bool) *RequestInitChain {
 	this := &RequestInitChain{}
-	this.Time = int64(r.Int63())
-	if r.Intn(2) == 0 {
-		this.Time *= -1
-	}
+	v1 := github_com_gogo_protobuf_types.NewPopulatedStdTime(r, easy)
+	this.Time = *v1
 	this.ChainId = string(randStringTypes(r))
 	if r.Intn(10) != 0 {
 		this.ConsensusParams = NewPopulatedConsensusParams(r, easy)
 	}
 	if r.Intn(10) != 0 {
-		v1 := r.Intn(5)
-		this.Validators = make([]Validator, v1)
-		for i := 0; i < v1; i++ {
-			v2 := NewPopulatedValidator(r, easy)
-			this.Validators[i] = *v2
+		v2 := r.Intn(5)
+		this.Validators = make([]Validator, v2)
+		for i := 0; i < v2; i++ {
+			v3 := NewPopulatedValidator(r, easy)
+			this.Validators[i] = *v3
 		}
 	}
-	v3 := r.Intn(100)
-	this.AppStateBytes = make([]byte, v3)
-	for i := 0; i < v3; i++ {
+	v4 := r.Intn(100)
+	this.AppStateBytes = make([]byte, v4)
+	for i := 0; i < v4; i++ {
 		this.AppStateBytes[i] = byte(r.Intn(256))
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 6)
 	}
 	return this
 }
 
 func NewPopulatedRequestQuery(r randyTypes, easy bool) *RequestQuery {
 	this := &RequestQuery{}
-	v4 := r.Intn(100)
-	this.Data = make([]byte, v4)
-	for i := 0; i < v4; i++ {
+	v5 := r.Intn(100)
+	this.Data = make([]byte, v5)
+	for i := 0; i < v5; i++ {
 		this.Data[i] = byte(r.Intn(256))
 	}
 	this.Path = string(randStringTypes(r))
@@ -5709,27 +7028,22 @@ func NewPopulatedRequestQuery(r randyTypes, easy bool) *RequestQuery {
 	}
 	this.Prove = bool(bool(r.Intn(2) == 0))
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 5)
 	}
 	return this
 }
 
 func NewPopulatedRequestBeginBlock(r randyTypes, easy bool) *RequestBeginBlock {
 	this := &RequestBeginBlock{}
-	v5 := r.Intn(100)
-	this.Hash = make([]byte, v5)
-	for i := 0; i < v5; i++ {
+	v6 := r.Intn(100)
+	this.Hash = make([]byte, v6)
+	for i := 0; i < v6; i++ {
 		this.Hash[i] = byte(r.Intn(256))
 	}
-	v6 := NewPopulatedHeader(r, easy)
-	this.Header = *v6
-	if r.Intn(10) != 0 {
-		v7 := r.Intn(5)
-		this.Validators = make([]SigningValidator, v7)
-		for i := 0; i < v7; i++ {
-			v8 := NewPopulatedSigningValidator(r, easy)
-			this.Validators[i] = *v8
-		}
-	}
+	v7 := NewPopulatedHeader(r, easy)
+	this.Header = *v7
+	v8 := NewPopulatedLastCommitInfo(r, easy)
+	this.LastCommitInfo = *v8
 	if r.Intn(10) != 0 {
 		v9 := r.Intn(5)
 		this.ByzantineValidators = make([]Evidence, v9)
@@ -5739,6 +7053,7 @@ func NewPopulatedRequestBeginBlock(r randyTypes, easy bool) *RequestBeginBlock {
 		}
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 5)
 	}
 	return this
 }
@@ -5751,6 +7066,7 @@ func NewPopulatedRequestCheckTx(r randyTypes, easy bool) *RequestCheckTx {
 		this.Tx[i] = byte(r.Intn(256))
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 2)
 	}
 	return this
 }
@@ -5763,6 +7079,7 @@ func NewPopulatedRequestDeliverTx(r randyTypes, easy bool) *RequestDeliverTx {
 		this.Tx[i] = byte(r.Intn(256))
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 2)
 	}
 	return this
 }
@@ -5774,6 +7091,7 @@ func NewPopulatedRequestEndBlock(r randyTypes, easy bool) *RequestEndBlock {
 		this.Height *= -1
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 2)
 	}
 	return this
 }
@@ -5781,6 +7099,7 @@ func NewPopulatedRequestEndBlock(r randyTypes, easy bool) *RequestEndBlock {
 func NewPopulatedRequestCommit(r randyTypes, easy bool) *RequestCommit {
 	this := &RequestCommit{}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 1)
 	}
 	return this
 }
@@ -5815,6 +7134,7 @@ func NewPopulatedResponse(r randyTypes, easy bool) *Response {
 		this.Value = NewPopulatedResponse_Commit(r, easy)
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 13)
 	}
 	return this
 }
@@ -5883,6 +7203,7 @@ func NewPopulatedResponseException(r randyTypes, easy bool) *ResponseException {
 	this := &ResponseException{}
 	this.Error = string(randStringTypes(r))
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 2)
 	}
 	return this
 }
@@ -5891,6 +7212,7 @@ func NewPopulatedResponseEcho(r randyTypes, easy bool) *ResponseEcho {
 	this := &ResponseEcho{}
 	this.Message = string(randStringTypes(r))
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 2)
 	}
 	return this
 }
@@ -5898,6 +7220,7 @@ func NewPopulatedResponseEcho(r randyTypes, easy bool) *ResponseEcho {
 func NewPopulatedResponseFlush(r randyTypes, easy bool) *ResponseFlush {
 	this := &ResponseFlush{}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 1)
 	}
 	return this
 }
@@ -5916,6 +7239,7 @@ func NewPopulatedResponseInfo(r randyTypes, easy bool) *ResponseInfo {
 		this.LastBlockAppHash[i] = byte(r.Intn(256))
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 5)
 	}
 	return this
 }
@@ -5926,6 +7250,7 @@ func NewPopulatedResponseSetOption(r randyTypes, easy bool) *ResponseSetOption {
 	this.Log = string(randStringTypes(r))
 	this.Info = string(randStringTypes(r))
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 5)
 	}
 	return this
 }
@@ -5944,6 +7269,7 @@ func NewPopulatedResponseInitChain(r randyTypes, easy bool) *ResponseInitChain {
 		}
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 3)
 	}
 	return this
 }
@@ -5977,6 +7303,7 @@ func NewPopulatedResponseQuery(r randyTypes, easy bool) *ResponseQuery {
 		this.Height *= -1
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 10)
 	}
 	return this
 }
@@ -5992,6 +7319,7 @@ func NewPopulatedResponseBeginBlock(r randyTypes, easy bool) *ResponseBeginBlock
 		}
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 2)
 	}
 	return this
 }
@@ -6022,9 +7350,8 @@ func NewPopulatedResponseCheckTx(r randyTypes, easy bool) *ResponseCheckTx {
 			this.Tags[i] = *v23
 		}
 	}
-	v24 := common.NewPopulatedKI64Pair(r, easy)
-	this.Fee = *v24
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 8)
 	}
 	return this
 }
@@ -6032,9 +7359,9 @@ func NewPopulatedResponseCheckTx(r randyTypes, easy bool) *ResponseCheckTx {
 func NewPopulatedResponseDeliverTx(r randyTypes, easy bool) *ResponseDeliverTx {
 	this := &ResponseDeliverTx{}
 	this.Code = uint32(r.Uint32())
-	v25 := r.Intn(100)
-	this.Data = make([]byte, v25)
-	for i := 0; i < v25; i++ {
+	v24 := r.Intn(100)
+	this.Data = make([]byte, v24)
+	for i := 0; i < v24; i++ {
 		this.Data[i] = byte(r.Intn(256))
 	}
 	this.Log = string(randStringTypes(r))
@@ -6048,16 +7375,15 @@ func NewPopulatedResponseDeliverTx(r randyTypes, easy bool) *ResponseDeliverTx {
 		this.GasUsed *= -1
 	}
 	if r.Intn(10) != 0 {
-		v26 := r.Intn(5)
-		this.Tags = make([]common.KVPair, v26)
-		for i := 0; i < v26; i++ {
-			v27 := common.NewPopulatedKVPair(r, easy)
-			this.Tags[i] = *v27
+		v25 := r.Intn(5)
+		this.Tags = make([]common.KVPair, v25)
+		for i := 0; i < v25; i++ {
+			v26 := common.NewPopulatedKVPair(r, easy)
+			this.Tags[i] = *v26
 		}
 	}
-	v28 := common.NewPopulatedKI64Pair(r, easy)
-	this.Fee = *v28
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 8)
 	}
 	return this
 }
@@ -6065,37 +7391,39 @@ func NewPopulatedResponseDeliverTx(r randyTypes, easy bool) *ResponseDeliverTx {
 func NewPopulatedResponseEndBlock(r randyTypes, easy bool) *ResponseEndBlock {
 	this := &ResponseEndBlock{}
 	if r.Intn(10) != 0 {
-		v29 := r.Intn(5)
-		this.ValidatorUpdates = make([]Validator, v29)
-		for i := 0; i < v29; i++ {
-			v30 := NewPopulatedValidator(r, easy)
-			this.ValidatorUpdates[i] = *v30
+		v27 := r.Intn(5)
+		this.ValidatorUpdates = make([]Validator, v27)
+		for i := 0; i < v27; i++ {
+			v28 := NewPopulatedValidator(r, easy)
+			this.ValidatorUpdates[i] = *v28
 		}
 	}
 	if r.Intn(10) != 0 {
 		this.ConsensusParamUpdates = NewPopulatedConsensusParams(r, easy)
 	}
 	if r.Intn(10) != 0 {
-		v31 := r.Intn(5)
-		this.Tags = make([]common.KVPair, v31)
-		for i := 0; i < v31; i++ {
-			v32 := common.NewPopulatedKVPair(r, easy)
-			this.Tags[i] = *v32
+		v29 := r.Intn(5)
+		this.Tags = make([]common.KVPair, v29)
+		for i := 0; i < v29; i++ {
+			v30 := common.NewPopulatedKVPair(r, easy)
+			this.Tags[i] = *v30
 		}
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 4)
 	}
 	return this
 }
 
 func NewPopulatedResponseCommit(r randyTypes, easy bool) *ResponseCommit {
 	this := &ResponseCommit{}
-	v33 := r.Intn(100)
-	this.Data = make([]byte, v33)
-	for i := 0; i < v33; i++ {
+	v31 := r.Intn(100)
+	this.Data = make([]byte, v31)
+	for i := 0; i < v31; i++ {
 		this.Data[i] = byte(r.Intn(256))
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 3)
 	}
 	return this
 }
@@ -6112,6 +7440,7 @@ func NewPopulatedConsensusParams(r randyTypes, easy bool) *ConsensusParams {
 		this.BlockGossip = NewPopulatedBlockGossip(r, easy)
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 4)
 	}
 	return this
 }
@@ -6131,6 +7460,7 @@ func NewPopulatedBlockSize(r randyTypes, easy bool) *BlockSize {
 		this.MaxGas *= -1
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 4)
 	}
 	return this
 }
@@ -6146,6 +7476,7 @@ func NewPopulatedTxSize(r randyTypes, easy bool) *TxSize {
 		this.MaxGas *= -1
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 3)
 	}
 	return this
 }
@@ -6157,6 +7488,27 @@ func NewPopulatedBlockGossip(r randyTypes, easy bool) *BlockGossip {
 		this.BlockPartSizeBytes *= -1
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 2)
+	}
+	return this
+}
+
+func NewPopulatedLastCommitInfo(r randyTypes, easy bool) *LastCommitInfo {
+	this := &LastCommitInfo{}
+	this.CommitRound = int32(r.Int31())
+	if r.Intn(2) == 0 {
+		this.CommitRound *= -1
+	}
+	if r.Intn(10) != 0 {
+		v32 := r.Intn(5)
+		this.Validators = make([]SigningValidator, v32)
+		for i := 0; i < v32; i++ {
+			v33 := NewPopulatedSigningValidator(r, easy)
+			this.Validators[i] = *v33
+		}
+	}
+	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 3)
 	}
 	return this
 }
@@ -6168,10 +7520,8 @@ func NewPopulatedHeader(r randyTypes, easy bool) *Header {
 	if r.Intn(2) == 0 {
 		this.Height *= -1
 	}
-	this.Time = int64(r.Int63())
-	if r.Intn(2) == 0 {
-		this.Time *= -1
-	}
+	v34 := github_com_gogo_protobuf_types.NewPopulatedStdTime(r, easy)
+	this.Time = *v34
 	this.NumTxs = int32(r.Int31())
 	if r.Intn(2) == 0 {
 		this.NumTxs *= -1
@@ -6180,52 +7530,55 @@ func NewPopulatedHeader(r randyTypes, easy bool) *Header {
 	if r.Intn(2) == 0 {
 		this.TotalTxs *= -1
 	}
-	v34 := r.Intn(100)
-	this.LastBlockHash = make([]byte, v34)
-	for i := 0; i < v34; i++ {
-		this.LastBlockHash[i] = byte(r.Intn(256))
-	}
 	v35 := r.Intn(100)
-	this.ValidatorsHash = make([]byte, v35)
+	this.LastBlockHash = make([]byte, v35)
 	for i := 0; i < v35; i++ {
-		this.ValidatorsHash[i] = byte(r.Intn(256))
+		this.LastBlockHash[i] = byte(r.Intn(256))
 	}
 	v36 := r.Intn(100)
-	this.AppHash = make([]byte, v36)
+	this.ValidatorsHash = make([]byte, v36)
 	for i := 0; i < v36; i++ {
+		this.ValidatorsHash[i] = byte(r.Intn(256))
+	}
+	v37 := r.Intn(100)
+	this.AppHash = make([]byte, v37)
+	for i := 0; i < v37; i++ {
 		this.AppHash[i] = byte(r.Intn(256))
 	}
-	v37 := NewPopulatedValidator(r, easy)
-	this.Proposer = *v37
+	v38 := NewPopulatedValidator(r, easy)
+	this.Proposer = *v38
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 10)
 	}
 	return this
 }
 
 func NewPopulatedValidator(r randyTypes, easy bool) *Validator {
 	this := &Validator{}
-	v38 := r.Intn(100)
-	this.Address = make([]byte, v38)
-	for i := 0; i < v38; i++ {
+	v39 := r.Intn(100)
+	this.Address = make([]byte, v39)
+	for i := 0; i < v39; i++ {
 		this.Address[i] = byte(r.Intn(256))
 	}
-	v39 := NewPopulatedPubKey(r, easy)
-	this.PubKey = *v39
+	v40 := NewPopulatedPubKey(r, easy)
+	this.PubKey = *v40
 	this.Power = int64(r.Int63())
 	if r.Intn(2) == 0 {
 		this.Power *= -1
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 4)
 	}
 	return this
 }
 
 func NewPopulatedSigningValidator(r randyTypes, easy bool) *SigningValidator {
 	this := &SigningValidator{}
-	v40 := NewPopulatedValidator(r, easy)
-	this.Validator = *v40
+	v41 := NewPopulatedValidator(r, easy)
+	this.Validator = *v41
 	this.SignedLastBlock = bool(bool(r.Intn(2) == 0))
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 3)
 	}
 	return this
 }
@@ -6233,12 +7586,13 @@ func NewPopulatedSigningValidator(r randyTypes, easy bool) *SigningValidator {
 func NewPopulatedPubKey(r randyTypes, easy bool) *PubKey {
 	this := &PubKey{}
 	this.Type = string(randStringTypes(r))
-	v41 := r.Intn(100)
-	this.Data = make([]byte, v41)
-	for i := 0; i < v41; i++ {
+	v42 := r.Intn(100)
+	this.Data = make([]byte, v42)
+	for i := 0; i < v42; i++ {
 		this.Data[i] = byte(r.Intn(256))
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 3)
 	}
 	return this
 }
@@ -6246,21 +7600,20 @@ func NewPopulatedPubKey(r randyTypes, easy bool) *PubKey {
 func NewPopulatedEvidence(r randyTypes, easy bool) *Evidence {
 	this := &Evidence{}
 	this.Type = string(randStringTypes(r))
-	v42 := NewPopulatedValidator(r, easy)
-	this.Validator = *v42
+	v43 := NewPopulatedValidator(r, easy)
+	this.Validator = *v43
 	this.Height = int64(r.Int63())
 	if r.Intn(2) == 0 {
 		this.Height *= -1
 	}
-	this.Time = int64(r.Int63())
-	if r.Intn(2) == 0 {
-		this.Time *= -1
-	}
+	v44 := github_com_gogo_protobuf_types.NewPopulatedStdTime(r, easy)
+	this.Time = *v44
 	this.TotalVotingPower = int64(r.Int63())
 	if r.Intn(2) == 0 {
 		this.TotalVotingPower *= -1
 	}
 	if !easy && r.Intn(10) != 0 {
+		this.XXX_unrecognized = randUnrecognizedTypes(r, 6)
 	}
 	return this
 }
@@ -6284,9 +7637,9 @@ func randUTF8RuneTypes(r randyTypes) rune {
 	return rune(ru + 61)
 }
 func randStringTypes(r randyTypes) string {
-	v43 := r.Intn(100)
-	tmps := make([]rune, v43)
-	for i := 0; i < v43; i++ {
+	v45 := r.Intn(100)
+	tmps := make([]rune, v45)
+	for i := 0; i < v45; i++ {
 		tmps[i] = randUTF8RuneTypes(r)
 	}
 	return string(tmps)
@@ -6308,11 +7661,11 @@ func randFieldTypes(dAtA []byte, r randyTypes, fieldNumber int, wire int) []byte
 	switch wire {
 	case 0:
 		dAtA = encodeVarintPopulateTypes(dAtA, uint64(key))
-		v44 := r.Int63()
+		v46 := r.Int63()
 		if r.Intn(2) == 0 {
-			v44 *= -1
+			v46 *= -1
 		}
-		dAtA = encodeVarintPopulateTypes(dAtA, uint64(v44))
+		dAtA = encodeVarintPopulateTypes(dAtA, uint64(v46))
 	case 1:
 		dAtA = encodeVarintPopulateTypes(dAtA, uint64(key))
 		dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
@@ -6343,6 +7696,9 @@ func (m *Request) Size() (n int) {
 	if m.Value != nil {
 		n += m.Value.Size()
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6452,12 +7808,18 @@ func (m *RequestEcho) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovTypes(uint64(l))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
 func (m *RequestFlush) Size() (n int) {
 	var l int
 	_ = l
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6468,6 +7830,9 @@ func (m *RequestInfo) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovTypes(uint64(l))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6482,15 +7847,17 @@ func (m *RequestSetOption) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovTypes(uint64(l))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
 func (m *RequestInitChain) Size() (n int) {
 	var l int
 	_ = l
-	if m.Time != 0 {
-		n += 1 + sovTypes(uint64(m.Time))
-	}
+	l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Time)
+	n += 1 + l + sovTypes(uint64(l))
 	l = len(m.ChainId)
 	if l > 0 {
 		n += 1 + l + sovTypes(uint64(l))
@@ -6509,6 +7876,9 @@ func (m *RequestInitChain) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovTypes(uint64(l))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6529,6 +7899,9 @@ func (m *RequestQuery) Size() (n int) {
 	if m.Prove {
 		n += 2
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6541,18 +7914,17 @@ func (m *RequestBeginBlock) Size() (n int) {
 	}
 	l = m.Header.Size()
 	n += 1 + l + sovTypes(uint64(l))
-	if len(m.Validators) > 0 {
-		for _, e := range m.Validators {
-			l = e.Size()
-			n += 1 + l + sovTypes(uint64(l))
-		}
-	}
+	l = m.LastCommitInfo.Size()
+	n += 1 + l + sovTypes(uint64(l))
 	if len(m.ByzantineValidators) > 0 {
 		for _, e := range m.ByzantineValidators {
 			l = e.Size()
 			n += 1 + l + sovTypes(uint64(l))
 		}
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6563,6 +7935,9 @@ func (m *RequestCheckTx) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovTypes(uint64(l))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6573,6 +7948,9 @@ func (m *RequestDeliverTx) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovTypes(uint64(l))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6582,12 +7960,18 @@ func (m *RequestEndBlock) Size() (n int) {
 	if m.Height != 0 {
 		n += 1 + sovTypes(uint64(m.Height))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
 func (m *RequestCommit) Size() (n int) {
 	var l int
 	_ = l
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6597,6 +7981,9 @@ func (m *Response) Size() (n int) {
 	if m.Value != nil {
 		n += m.Value.Size()
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6715,6 +8102,9 @@ func (m *ResponseException) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovTypes(uint64(l))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6725,12 +8115,18 @@ func (m *ResponseEcho) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovTypes(uint64(l))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
 func (m *ResponseFlush) Size() (n int) {
 	var l int
 	_ = l
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6752,6 +8148,9 @@ func (m *ResponseInfo) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovTypes(uint64(l))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6769,6 +8168,9 @@ func (m *ResponseSetOption) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovTypes(uint64(l))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6785,6 +8187,9 @@ func (m *ResponseInitChain) Size() (n int) {
 			n += 1 + l + sovTypes(uint64(l))
 		}
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6820,6 +8225,9 @@ func (m *ResponseQuery) Size() (n int) {
 	if m.Height != 0 {
 		n += 1 + sovTypes(uint64(m.Height))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6832,6 +8240,9 @@ func (m *ResponseBeginBlock) Size() (n int) {
 			n += 1 + l + sovTypes(uint64(l))
 		}
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6865,8 +8276,9 @@ func (m *ResponseCheckTx) Size() (n int) {
 			n += 1 + l + sovTypes(uint64(l))
 		}
 	}
-	l = m.Fee.Size()
-	n += 1 + l + sovTypes(uint64(l))
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6900,8 +8312,9 @@ func (m *ResponseDeliverTx) Size() (n int) {
 			n += 1 + l + sovTypes(uint64(l))
 		}
 	}
-	l = m.Fee.Size()
-	n += 1 + l + sovTypes(uint64(l))
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6924,6 +8337,9 @@ func (m *ResponseEndBlock) Size() (n int) {
 			n += 1 + l + sovTypes(uint64(l))
 		}
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6934,6 +8350,9 @@ func (m *ResponseCommit) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovTypes(uint64(l))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6952,6 +8371,9 @@ func (m *ConsensusParams) Size() (n int) {
 		l = m.BlockGossip.Size()
 		n += 1 + l + sovTypes(uint64(l))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6967,6 +8389,9 @@ func (m *BlockSize) Size() (n int) {
 	if m.MaxGas != 0 {
 		n += 1 + sovTypes(uint64(m.MaxGas))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6979,6 +8404,9 @@ func (m *TxSize) Size() (n int) {
 	if m.MaxGas != 0 {
 		n += 1 + sovTypes(uint64(m.MaxGas))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -6988,6 +8416,27 @@ func (m *BlockGossip) Size() (n int) {
 	if m.BlockPartSizeBytes != 0 {
 		n += 1 + sovTypes(uint64(m.BlockPartSizeBytes))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *LastCommitInfo) Size() (n int) {
+	var l int
+	_ = l
+	if m.CommitRound != 0 {
+		n += 1 + sovTypes(uint64(m.CommitRound))
+	}
+	if len(m.Validators) > 0 {
+		for _, e := range m.Validators {
+			l = e.Size()
+			n += 1 + l + sovTypes(uint64(l))
+		}
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -7001,9 +8450,8 @@ func (m *Header) Size() (n int) {
 	if m.Height != 0 {
 		n += 1 + sovTypes(uint64(m.Height))
 	}
-	if m.Time != 0 {
-		n += 1 + sovTypes(uint64(m.Time))
-	}
+	l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Time)
+	n += 1 + l + sovTypes(uint64(l))
 	if m.NumTxs != 0 {
 		n += 1 + sovTypes(uint64(m.NumTxs))
 	}
@@ -7024,6 +8472,9 @@ func (m *Header) Size() (n int) {
 	}
 	l = m.Proposer.Size()
 	n += 1 + l + sovTypes(uint64(l))
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -7039,6 +8490,9 @@ func (m *Validator) Size() (n int) {
 	if m.Power != 0 {
 		n += 1 + sovTypes(uint64(m.Power))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -7050,6 +8504,9 @@ func (m *SigningValidator) Size() (n int) {
 	if m.SignedLastBlock {
 		n += 2
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -7064,6 +8521,9 @@ func (m *PubKey) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovTypes(uint64(l))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -7079,12 +8539,14 @@ func (m *Evidence) Size() (n int) {
 	if m.Height != 0 {
 		n += 1 + sovTypes(uint64(m.Height))
 	}
-	if m.Time != 0 {
-		n += 1 + sovTypes(uint64(m.Time))
-	}
+	l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Time)
+	n += 1 + l + sovTypes(uint64(l))
 	if m.TotalVotingPower != 0 {
 		n += 1 + sovTypes(uint64(m.TotalVotingPower))
 	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
 	return n
 }
 
@@ -7494,6 +8956,7 @@ func (m *Request) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -7573,6 +9036,7 @@ func (m *RequestEcho) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -7623,6 +9087,7 @@ func (m *RequestFlush) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -7702,6 +9167,7 @@ func (m *RequestInfo) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -7810,6 +9276,7 @@ func (m *RequestSetOption) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -7849,10 +9316,10 @@ func (m *RequestInitChain) Unmarshal(dAtA []byte) error {
 		}
 		switch fieldNum {
 		case 1:
-			if wireType != 0 {
+			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType)
 			}
-			m.Time = 0
+			var msglen int
 			for shift := uint(0); ; shift += 7 {
 				if shift >= 64 {
 					return ErrIntOverflowTypes
@@ -7862,11 +9329,22 @@ func (m *RequestInitChain) Unmarshal(dAtA []byte) error {
 				}
 				b := dAtA[iNdEx]
 				iNdEx++
-				m.Time |= (int64(b) & 0x7F) << shift
+				msglen |= (int(b) & 0x7F) << shift
 				if b < 0x80 {
 					break
 				}
 			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
 		case 2:
 			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType)
@@ -8003,6 +9481,7 @@ func (m *RequestInitChain) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -8152,6 +9631,7 @@ func (m *RequestQuery) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -8253,7 +9733,7 @@ func (m *RequestBeginBlock) Unmarshal(dAtA []byte) error {
 			iNdEx = postIndex
 		case 3:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field LastCommitInfo", wireType)
 			}
 			var msglen int
 			for shift := uint(0); ; shift += 7 {
@@ -8277,8 +9757,7 @@ func (m *RequestBeginBlock) Unmarshal(dAtA []byte) error {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			m.Validators = append(m.Validators, SigningValidator{})
-			if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+			if err := m.LastCommitInfo.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 				return err
 			}
 			iNdEx = postIndex
@@ -8325,6 +9804,7 @@ func (m *RequestBeginBlock) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -8406,6 +9886,7 @@ func (m *RequestCheckTx) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -8487,6 +9968,7 @@ func (m *RequestDeliverTx) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -8556,6 +10038,7 @@ func (m *RequestEndBlock) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -8606,6 +10089,7 @@ func (m *RequestCommit) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -9040,6 +10524,7 @@ func (m *Response) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -9119,6 +10604,7 @@ func (m *ResponseException) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -9198,6 +10684,7 @@ func (m *ResponseEcho) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -9248,6 +10735,7 @@ func (m *ResponseFlush) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -9406,6 +10894,7 @@ func (m *ResponseInfo) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -9533,6 +11022,7 @@ func (m *ResponseSetOption) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -9647,6 +11137,7 @@ func (m *ResponseInitChain) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -9905,6 +11396,7 @@ func (m *ResponseQuery) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -9986,6 +11478,7 @@ func (m *ResponseBeginBlock) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -10201,36 +11694,6 @@ func (m *ResponseCheckTx) Unmarshal(dAtA []byte) error {
 				return err
 			}
 			iNdEx = postIndex
-		case 8:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Fee", wireType)
-			}
-			var msglen int
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowTypes
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				msglen |= (int(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			if msglen < 0 {
-				return ErrInvalidLengthTypes
-			}
-			postIndex := iNdEx + msglen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			if err := m.Fee.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
-				return err
-			}
-			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipTypes(dAtA[iNdEx:])
@@ -10243,6 +11706,7 @@ func (m *ResponseCheckTx) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -10458,36 +11922,6 @@ func (m *ResponseDeliverTx) Unmarshal(dAtA []byte) error {
 				return err
 			}
 			iNdEx = postIndex
-		case 8:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Fee", wireType)
-			}
-			var msglen int
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowTypes
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				msglen |= (int(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			if msglen < 0 {
-				return ErrInvalidLengthTypes
-			}
-			postIndex := iNdEx + msglen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			if err := m.Fee.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
-				return err
-			}
-			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipTypes(dAtA[iNdEx:])
@@ -10500,6 +11934,7 @@ func (m *ResponseDeliverTx) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -10645,6 +12080,7 @@ func (m *ResponseEndBlock) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -10726,6 +12162,7 @@ func (m *ResponseCommit) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -10875,6 +12312,7 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -10982,6 +12420,7 @@ func (m *BlockSize) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -11070,6 +12509,7 @@ func (m *TxSize) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -11139,6 +12579,108 @@ func (m *BlockGossip) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *LastCommitInfo) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: LastCommitInfo: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: LastCommitInfo: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field CommitRound", wireType)
+			}
+			m.CommitRound = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.CommitRound |= (int32(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Validators = append(m.Validators, SigningValidator{})
+			if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -11226,10 +12768,10 @@ func (m *Header) Unmarshal(dAtA []byte) error {
 				}
 			}
 		case 3:
-			if wireType != 0 {
+			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType)
 			}
-			m.Time = 0
+			var msglen int
 			for shift := uint(0); ; shift += 7 {
 				if shift >= 64 {
 					return ErrIntOverflowTypes
@@ -11239,11 +12781,22 @@ func (m *Header) Unmarshal(dAtA []byte) error {
 				}
 				b := dAtA[iNdEx]
 				iNdEx++
-				m.Time |= (int64(b) & 0x7F) << shift
+				msglen |= (int(b) & 0x7F) << shift
 				if b < 0x80 {
 					break
 				}
 			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
 		case 4:
 			if wireType != 0 {
 				return fmt.Errorf("proto: wrong wireType = %d for field NumTxs", wireType)
@@ -11417,6 +12970,7 @@ func (m *Header) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -11547,6 +13101,7 @@ func (m *Validator) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -11647,6 +13202,7 @@ func (m *SigningValidator) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -11757,6 +13313,7 @@ func (m *PubKey) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -11874,10 +13431,10 @@ func (m *Evidence) Unmarshal(dAtA []byte) error {
 				}
 			}
 		case 4:
-			if wireType != 0 {
+			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType)
 			}
-			m.Time = 0
+			var msglen int
 			for shift := uint(0); ; shift += 7 {
 				if shift >= 64 {
 					return ErrIntOverflowTypes
@@ -11887,11 +13444,22 @@ func (m *Evidence) Unmarshal(dAtA []byte) error {
 				}
 				b := dAtA[iNdEx]
 				iNdEx++
-				m.Time |= (int64(b) & 0x7F) << shift
+				msglen |= (int(b) & 0x7F) << shift
 				if b < 0x80 {
 					break
 				}
 			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
 		case 5:
 			if wireType != 0 {
 				return fmt.Errorf("proto: wrong wireType = %d for field TotalVotingPower", wireType)
@@ -11923,6 +13491,7 @@ func (m *Evidence) Unmarshal(dAtA []byte) error {
 			if (iNdEx + skippy) > l {
 				return io.ErrUnexpectedEOF
 			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
 			iNdEx += skippy
 		}
 	}
@@ -12037,128 +13606,134 @@ var (
 	ErrIntOverflowTypes   = fmt.Errorf("proto: integer overflow")
 )
 
-func init() { proto.RegisterFile("abci/types/types.proto", fileDescriptorTypes) }
-func init() { golang_proto.RegisterFile("abci/types/types.proto", fileDescriptorTypes) }
-
-var fileDescriptorTypes = []byte{
-	// 1892 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x58, 0x4b, 0x73, 0x1c, 0x49,
-	0x11, 0x56, 0xcf, 0xbb, 0x53, 0x8f, 0x19, 0x97, 0x6c, 0x69, 0x3c, 0x0b, 0xb2, 0xa3, 0x83, 0xf0,
-	0xca, 0xac, 0x56, 0x02, 0xed, 0xda, 0x61, 0xef, 0xc2, 0x06, 0x1a, 0xad, 0xd9, 0x51, 0x2c, 0x0f,
-	0xd1, 0xf6, 0x9a, 0x08, 0x2e, 0x13, 0x35, 0xd3, 0xa5, 0x9e, 0x0e, 0xcf, 0x74, 0xf7, 0x76, 0xd5,
-	0x68, 0x47, 0xbe, 0x71, 0xdf, 0xe0, 0xca, 0x99, 0x1b, 0x27, 0x0e, 0x44, 0x10, 0xc1, 0x91, 0x13,
-	0xb1, 0x47, 0xfe, 0x00, 0x0e, 0xd0, 0x72, 0xe2, 0x17, 0x70, 0x83, 0xa8, 0xac, 0xea, 0xa7, 0x7a,
-	0x1c, 0xc2, 0x1c, 0xb9, 0x48, 0x95, 0x9d, 0x99, 0x55, 0x95, 0x39, 0x99, 0x5f, 0x66, 0x16, 0x6c,
-	0xd1, 0xd1, 0xd8, 0x3b, 0x10, 0x17, 0x21, 0xe3, 0xea, 0xef, 0x7e, 0x18, 0x05, 0x22, 0x20, 0x75,
-	0x24, 0x7a, 0xef, 0xba, 0x9e, 0x98, 0xcc, 0x47, 0xfb, 0xe3, 0x60, 0x76, 0xe0, 0x06, 0x6e, 0x70,
-	0x80, 0xdc, 0xd1, 0xfc, 0x0c, 0x29, 0x24, 0x70, 0xa5, 0xb4, 0x7a, 0x8f, 0x32, 0xe2, 0x82, 0xf9,
-	0x0e, 0x8b, 0x66, 0x9e, 0x2f, 0xb2, 0xcb, 0xa9, 0x37, 0xe2, 0x07, 0xe3, 0x60, 0x36, 0x0b, 0xfc,
-	0xec, 0x79, 0xd6, 0x9f, 0x6b, 0xd0, 0xb4, 0xd9, 0xe7, 0x73, 0xc6, 0x05, 0xd9, 0x85, 0x1a, 0x1b,
-	0x4f, 0x82, 0x6e, 0xe5, 0xae, 0xb1, 0xbb, 0x7a, 0x48, 0xf6, 0x95, 0x9c, 0xe6, 0x3e, 0x19, 0x4f,
-	0x82, 0xc1, 0x8a, 0x8d, 0x12, 0xe4, 0x1d, 0xa8, 0x9f, 0x4d, 0xe7, 0x7c, 0xd2, 0xad, 0xa2, 0xe8,
-	0x66, 0x5e, 0xf4, 0x87, 0x92, 0x35, 0x58, 0xb1, 0x95, 0x8c, 0xdc, 0xd6, 0xf3, 0xcf, 0x82, 0x6e,
-	0xad, 0x6c, 0xdb, 0x13, 0xff, 0x0c, 0xb7, 0x95, 0x12, 0xe4, 0x11, 0x00, 0x67, 0x62, 0x18, 0x84,
-	0xc2, 0x0b, 0xfc, 0x6e, 0x1d, 0xe5, 0xb7, 0xf3, 0xf2, 0x4f, 0x99, 0xf8, 0x29, 0xb2, 0x07, 0x2b,
-	0xb6, 0xc9, 0x63, 0x42, 0x6a, 0x7a, 0xbe, 0x27, 0x86, 0xe3, 0x09, 0xf5, 0xfc, 0x6e, 0xa3, 0x4c,
-	0xf3, 0xc4, 0xf7, 0xc4, 0xb1, 0x64, 0x4b, 0x4d, 0x2f, 0x26, 0xa4, 0x29, 0x9f, 0xcf, 0x59, 0x74,
-	0xd1, 0x6d, 0x96, 0x99, 0xf2, 0x33, 0xc9, 0x92, 0xa6, 0xa0, 0x0c, 0xf9, 0x10, 0x56, 0x47, 0xcc,
-	0xf5, 0xfc, 0xe1, 0x68, 0x1a, 0x8c, 0x5f, 0x74, 0x5b, 0xa8, 0xd2, 0xcd, 0xab, 0xf4, 0xa5, 0x40,
-	0x5f, 0xf2, 0x07, 0x2b, 0x36, 0x8c, 0x12, 0x8a, 0x1c, 0x42, 0x6b, 0x3c, 0x61, 0xe3, 0x17, 0x43,
-	0xb1, 0xe8, 0x9a, 0xa8, 0x79, 0x2b, 0xaf, 0x79, 0x2c, 0xb9, 0xcf, 0x16, 0x83, 0x15, 0xbb, 0x39,
-	0x56, 0x4b, 0xf2, 0x00, 0x4c, 0xe6, 0x3b, 0xfa, 0xb8, 0x55, 0x54, 0xda, 0x2a, 0xfc, 0x2e, 0xbe,
-	0x13, 0x1f, 0xd6, 0x62, 0x7a, 0x4d, 0xf6, 0xa1, 0x21, 0x7f, 0x6b, 0x4f, 0x74, 0xd7, 0x50, 0xe7,
-	0x66, 0xe1, 0x20, 0xe4, 0x0d, 0x56, 0x6c, 0x2d, 0x25, 0xdd, 0xe7, 0xb0, 0xa9, 0x77, 0xce, 0x22,
-	0x79, 0xb9, 0xcd, 0x32, 0xf7, 0x7d, 0xac, 0xf8, 0x78, 0x3d, 0xd3, 0x89, 0x89, 0x7e, 0x13, 0xea,
-	0xe7, 0x74, 0x3a, 0x67, 0xd6, 0xdb, 0xb0, 0x9a, 0x89, 0x14, 0xd2, 0x85, 0xe6, 0x8c, 0x71, 0x4e,
-	0x5d, 0xd6, 0x35, 0xee, 0x1a, 0xbb, 0xa6, 0x1d, 0x93, 0xd6, 0x06, 0xac, 0x65, 0xe3, 0x24, 0xa3,
-	0x28, 0x63, 0x41, 0x2a, 0x9e, 0xb3, 0x88, 0xcb, 0x00, 0xd0, 0x8a, 0x9a, 0xb4, 0x3e, 0x80, 0x4e,
-	0x31, 0x08, 0x48, 0x07, 0xaa, 0x2f, 0xd8, 0x85, 0x96, 0x94, 0x4b, 0x72, 0x53, 0x5f, 0x08, 0xa3,
-	0xd8, 0xb4, 0xf5, 0xed, 0xfe, 0x61, 0x24, 0xca, 0x49, 0x1c, 0x10, 0x02, 0x35, 0xe1, 0xcd, 0xd4,
-	0x05, 0xab, 0x36, 0xae, 0xc9, 0x6d, 0xf9, 0x23, 0x51, 0xcf, 0x1f, 0x7a, 0x8e, 0xde, 0xa1, 0x89,
-	0xf4, 0x89, 0x43, 0x8e, 0xa0, 0x33, 0x0e, 0x7c, 0xce, 0x7c, 0x3e, 0xe7, 0xc3, 0x90, 0x46, 0x74,
-	0xc6, 0x75, 0xfc, 0xc7, 0x3f, 0xc9, 0x71, 0xcc, 0x3e, 0x45, 0xae, 0xdd, 0x1e, 0xe7, 0x3f, 0x90,
-	0x87, 0x00, 0xe7, 0x74, 0xea, 0x39, 0x54, 0x04, 0x11, 0xef, 0xd6, 0xee, 0x56, 0x77, 0x57, 0x0f,
-	0x3b, 0x5a, 0xf9, 0x79, 0xcc, 0xe8, 0xd7, 0xbe, 0x7a, 0x75, 0x67, 0xc5, 0xce, 0x48, 0x92, 0x7b,
-	0xd0, 0xa6, 0x61, 0x38, 0xe4, 0x82, 0x0a, 0x36, 0x1c, 0x5d, 0x08, 0xc6, 0x31, 0x3b, 0xd6, 0xec,
-	0x75, 0x1a, 0x86, 0x4f, 0xe5, 0xd7, 0xbe, 0xfc, 0x68, 0x39, 0x89, 0x6f, 0x31, 0x70, 0xa5, 0x85,
-	0x0e, 0x15, 0x14, 0x2d, 0x5c, 0xb3, 0x71, 0x2d, 0xbf, 0x85, 0x54, 0x4c, 0xb4, 0x75, 0xb8, 0x26,
-	0x5b, 0xd0, 0x98, 0x30, 0xcf, 0x9d, 0x08, 0x34, 0xa8, 0x6a, 0x6b, 0x4a, 0x3a, 0x33, 0x8c, 0x82,
-	0x73, 0x86, 0xb9, 0xdb, 0xb2, 0x15, 0x61, 0xfd, 0xd5, 0x80, 0x1b, 0x57, 0x82, 0x5d, 0xee, 0x3b,
-	0xa1, 0x7c, 0x12, 0x9f, 0x25, 0xd7, 0xe4, 0x1d, 0xb9, 0x2f, 0x75, 0x58, 0xa4, 0x31, 0x65, 0x5d,
-	0xdb, 0x3a, 0xc0, 0x8f, 0xda, 0x50, 0x2d, 0x42, 0xbe, 0x9f, 0x73, 0x4e, 0x15, 0x9d, 0x13, 0x07,
-	0xe1, 0x53, 0xcf, 0xf5, 0x3d, 0xdf, 0x7d, 0x9d, 0x8f, 0x06, 0x70, 0x73, 0x74, 0xf1, 0x92, 0xfa,
-	0xc2, 0xf3, 0xd9, 0xf0, 0x8a, 0x97, 0xdb, 0x7a, 0xa3, 0x27, 0xe7, 0x9e, 0xc3, 0xfc, 0x31, 0xd3,
-	0x1b, 0x6c, 0x26, 0x2a, 0xc9, 0xd6, 0xdc, 0xba, 0x0b, 0x1b, 0xf9, 0x8c, 0x24, 0x1b, 0x50, 0x11,
-	0x0b, 0x6d, 0x59, 0x45, 0x2c, 0x2c, 0x2b, 0x89, 0xa6, 0x24, 0x2d, 0xae, 0xc8, 0xdc, 0x87, 0x76,
-	0x21, 0x45, 0x33, 0x6e, 0x36, 0xb2, 0x6e, 0xb6, 0xda, 0xb0, 0x9e, 0xcb, 0x4c, 0xeb, 0xcb, 0x3a,
-	0xb4, 0x6c, 0xc6, 0x43, 0x19, 0x3e, 0xe4, 0x11, 0x98, 0x6c, 0x31, 0x66, 0x0a, 0x14, 0x8d, 0x02,
-	0xe4, 0x28, 0x99, 0x27, 0x31, 0x5f, 0x26, 0x67, 0x22, 0x4c, 0xee, 0xe7, 0x00, 0x7d, 0xb3, 0xa8,
-	0x94, 0x45, 0xf4, 0xbd, 0x3c, 0xa2, 0xdf, 0x2c, 0xc8, 0x16, 0x20, 0xfd, 0x7e, 0x0e, 0xd2, 0x8b,
-	0x1b, 0xe7, 0x30, 0xfd, 0x71, 0x09, 0xa6, 0x17, 0xaf, 0xbf, 0x04, 0xd4, 0x1f, 0x97, 0x80, 0x7a,
-	0xf7, 0xca, 0x59, 0xa5, 0xa8, 0xbe, 0x97, 0x47, 0xf5, 0xa2, 0x39, 0x05, 0x58, 0xff, 0x5e, 0x19,
-	0xac, 0xdf, 0x2e, 0xe8, 0x2c, 0xc5, 0xf5, 0xf7, 0xae, 0xe0, 0xfa, 0x56, 0x41, 0xb5, 0x04, 0xd8,
-	0x1f, 0xe7, 0x10, 0x17, 0x4a, 0x6d, 0x2b, 0x87, 0x5c, 0xf2, 0xf0, 0x6a, 0x4d, 0xd8, 0x2e, 0xfe,
-	0xb4, 0x65, 0x45, 0xe1, 0xa0, 0x50, 0x14, 0x6e, 0x15, 0x6f, 0x59, 0xa8, 0x0a, 0x29, 0xb6, 0xdf,
-	0x97, 0xf9, 0x5e, 0x88, 0x34, 0x89, 0x0d, 0x2c, 0x8a, 0x82, 0x48, 0x83, 0xaf, 0x22, 0xac, 0x5d,
-	0x89, 0x40, 0x69, 0x7c, 0xbd, 0xa6, 0x0e, 0x60, 0xd0, 0x67, 0xa2, 0xcb, 0xfa, 0xb5, 0x91, 0xea,
-	0x62, 0x29, 0xc8, 0xa2, 0x97, 0xa9, 0xd1, 0x2b, 0x53, 0x1e, 0x2a, 0xb9, 0xf2, 0x40, 0xbe, 0x0d,
-	0x37, 0xa6, 0x94, 0x0b, 0xe5, 0x97, 0x61, 0x0e, 0xce, 0xda, 0x92, 0xa1, 0x1c, 0xa2, 0x70, 0xed,
-	0x5d, 0xd8, 0xcc, 0xc8, 0x4a, 0x68, 0x45, 0xe8, 0xaa, 0x61, 0xf2, 0x76, 0x12, 0xe9, 0xa3, 0x30,
-	0x1c, 0x50, 0x3e, 0xb1, 0x7e, 0x9c, 0xda, 0x9f, 0x96, 0x1e, 0x02, 0xb5, 0x71, 0xe0, 0x28, 0xb3,
-	0xd6, 0x6d, 0x5c, 0xcb, 0x72, 0x34, 0x0d, 0x5c, 0x3c, 0xd5, 0xb4, 0xe5, 0x52, 0x4a, 0x25, 0x99,
-	0x62, 0xaa, 0x94, 0xb0, 0x7e, 0x65, 0xa4, 0xfb, 0xa5, 0xd5, 0xa8, 0xac, 0xbc, 0x18, 0xff, 0x4b,
-	0x79, 0xa9, 0x5c, 0xb7, 0xbc, 0x58, 0x7f, 0x30, 0xd2, 0xdf, 0x22, 0x29, 0x1c, 0x6f, 0x66, 0x9c,
-	0x0c, 0x0b, 0xcf, 0x77, 0xd8, 0x02, 0x53, 0xbd, 0x6a, 0x2b, 0x22, 0xae, 0xd3, 0x0d, 0x74, 0x70,
-	0xbe, 0x4e, 0x37, 0xf1, 0x9b, 0x22, 0x74, 0xc1, 0x09, 0xce, 0x30, 0x07, 0xd7, 0x6c, 0x45, 0x64,
-	0x70, 0xd3, 0xcc, 0xe1, 0xe6, 0x29, 0x90, 0xab, 0xd9, 0x49, 0x3e, 0x80, 0x9a, 0xa0, 0xae, 0x74,
-	0x9e, 0xb4, 0x7f, 0x63, 0x5f, 0x75, 0xbd, 0xfb, 0x9f, 0x3e, 0x3f, 0xa5, 0x5e, 0xd4, 0xdf, 0x92,
-	0xd6, 0xff, 0xf3, 0xd5, 0x9d, 0x0d, 0x29, 0xb3, 0x17, 0xcc, 0x3c, 0xc1, 0x66, 0xa1, 0xb8, 0xb0,
-	0x51, 0xc7, 0xfa, 0xb7, 0x21, 0x51, 0x3b, 0x97, 0xb5, 0xa5, 0xbe, 0x88, 0x43, 0xb3, 0x92, 0x29,
-	0xac, 0xd7, 0xf3, 0xcf, 0x37, 0x01, 0x5c, 0xca, 0x87, 0x5f, 0x50, 0x5f, 0x30, 0x47, 0x3b, 0xc9,
-	0x74, 0x29, 0xff, 0x39, 0x7e, 0x90, 0xfd, 0x87, 0x64, 0xcf, 0x39, 0x73, 0xd0, 0x5b, 0x55, 0xbb,
-	0xe9, 0x52, 0xfe, 0x19, 0x67, 0x4e, 0x62, 0x57, 0xf3, 0xbf, 0xb7, 0x8b, 0xec, 0x42, 0xf5, 0x8c,
-	0x31, 0x8d, 0x6c, 0x9d, 0x44, 0xf5, 0xe4, 0xe1, 0xfb, 0xa8, 0xac, 0x42, 0x42, 0x8a, 0x58, 0xbf,
-	0xac, 0xa4, 0xc1, 0x99, 0x16, 0xb7, 0xff, 0x2f, 0x1f, 0x7c, 0x8d, 0xdd, 0x62, 0x1e, 0x4a, 0xc9,
-	0x31, 0xdc, 0x48, 0x52, 0x66, 0x38, 0x0f, 0x1d, 0x2a, 0xbb, 0x30, 0xe3, 0xb5, 0x39, 0xd6, 0x49,
-	0x14, 0x3e, 0x53, 0xf2, 0xe4, 0x27, 0xb0, 0x5d, 0x48, 0xf2, 0x64, 0xab, 0xca, 0x6b, 0x73, 0xfd,
-	0x56, 0x3e, 0xd7, 0xe3, 0xfd, 0x62, 0x7f, 0x54, 0xdf, 0x20, 0xd6, 0xbf, 0x25, 0xdb, 0x9c, 0x2c,
-	0xf4, 0x97, 0xfd, 0xa2, 0xd6, 0x6f, 0x0c, 0x68, 0x17, 0x2e, 0x43, 0x0e, 0x00, 0x14, 0x72, 0x72,
-	0xef, 0x25, 0xd3, 0x20, 0x15, 0xfb, 0x00, 0x9d, 0xf5, 0xd4, 0x7b, 0xc9, 0x6c, 0x73, 0x14, 0x2f,
-	0xc9, 0x3d, 0x68, 0x8a, 0x85, 0x92, 0xce, 0x37, 0x82, 0xcf, 0x16, 0x28, 0xda, 0x10, 0xf8, 0x9f,
-	0x3c, 0x80, 0x35, 0xb5, 0xb1, 0x1b, 0x70, 0xee, 0x85, 0xba, 0x19, 0x21, 0xd9, 0xad, 0x3f, 0x41,
-	0x8e, 0xbd, 0x3a, 0x4a, 0x09, 0xeb, 0x17, 0x60, 0x26, 0xc7, 0x92, 0xb7, 0xc0, 0x9c, 0xd1, 0x85,
-	0xee, 0x92, 0xe5, 0xdd, 0xea, 0x76, 0x6b, 0x46, 0x17, 0xd8, 0x20, 0x93, 0x6d, 0x68, 0x4a, 0xa6,
-	0x58, 0x28, 0x7f, 0xd7, 0xed, 0xc6, 0x8c, 0x2e, 0x9e, 0x2d, 0x12, 0x86, 0x4b, 0x79, 0xdc, 0x02,
-	0xcf, 0xe8, 0xe2, 0x13, 0xca, 0xad, 0x8f, 0xa0, 0xa1, 0x2e, 0x79, 0xad, 0x8d, 0xa5, 0x7e, 0x25,
-	0xa7, 0xff, 0x03, 0x58, 0xcd, 0xdc, 0x9b, 0x7c, 0x17, 0x6e, 0x29, 0x0b, 0x43, 0x1a, 0x09, 0xf4,
-	0x48, 0x6e, 0x43, 0x82, 0xcc, 0x53, 0x1a, 0x09, 0x79, 0xa4, 0x6a, 0xea, 0x7f, 0x5f, 0x81, 0x86,
-	0x6a, 0x98, 0xc9, 0xbd, 0xcc, 0x74, 0x82, 0x55, 0xb1, 0xbf, 0x7a, 0xf9, 0xea, 0x4e, 0x13, 0x0b,
-	0xc8, 0xc9, 0xc7, 0xe9, 0xa8, 0x92, 0x02, 0x66, 0x25, 0xd7, 0xcf, 0xc7, 0x13, 0x4f, 0x35, 0x33,
-	0xf1, 0x6c, 0x43, 0xd3, 0x9f, 0xcf, 0xd0, 0x25, 0x35, 0xe5, 0x12, 0x7f, 0x3e, 0x93, 0x2e, 0x79,
-	0x0b, 0x4c, 0x11, 0x08, 0x3a, 0x45, 0x96, 0x4a, 0xd2, 0x16, 0x7e, 0x90, 0xcc, 0x7b, 0xd0, 0xce,
-	0x56, 0x5b, 0x59, 0x3d, 0x15, 0xb8, 0xaf, 0xa7, 0xb5, 0x56, 0x4e, 0x00, 0x6f, 0x43, 0x3b, 0x2d,
-	0x34, 0x4a, 0x4e, 0x01, 0xfe, 0x46, 0xfa, 0x19, 0x05, 0x6f, 0x43, 0x2b, 0xa9, 0xc3, 0x0a, 0xfc,
-	0x9b, 0x54, 0x95, 0x5f, 0x39, 0x38, 0x87, 0x51, 0x10, 0x06, 0x9c, 0x45, 0xba, 0xc1, 0x5a, 0x96,
-	0x70, 0x89, 0x9c, 0xe5, 0x81, 0x99, 0x30, 0x65, 0xd3, 0x40, 0x1d, 0x27, 0x62, 0x9c, 0xeb, 0xfe,
-	0x3c, 0x26, 0xc9, 0x1e, 0x34, 0xc3, 0xf9, 0x68, 0x28, 0x6b, 0x53, 0x3e, 0x30, 0x4f, 0xe7, 0xa3,
-	0x4f, 0xd9, 0x45, 0x3c, 0xa1, 0x84, 0x48, 0x61, 0x75, 0x0a, 0xbe, 0x60, 0x91, 0xf6, 0x9f, 0x22,
-	0x2c, 0x01, 0x9d, 0xe2, 0x78, 0x42, 0xde, 0x07, 0x33, 0xb1, 0xaf, 0x90, 0x20, 0xc5, 0x3b, 0xa7,
-	0x82, 0xb2, 0x85, 0xe1, 0x9e, 0xeb, 0x33, 0x67, 0x98, 0xfa, 0x16, 0xef, 0xd5, 0xb2, 0xdb, 0x8a,
-	0xf1, 0xa3, 0xd8, 0xb9, 0xd6, 0x77, 0xa0, 0xa1, 0xee, 0x88, 0x3f, 0xea, 0x45, 0x18, 0xf7, 0x57,
-	0xb8, 0x2e, 0xcd, 0xe4, 0xdf, 0x19, 0xd0, 0x8a, 0xc7, 0x9f, 0x52, 0xa5, 0xdc, 0xa5, 0x2b, 0xd7,
-	0xbd, 0xf4, 0xb2, 0xd9, 0x31, 0x8e, 0xb5, 0x5a, 0x26, 0xd6, 0xf6, 0x80, 0xa8, 0x90, 0x3a, 0x0f,
-	0x84, 0xe7, 0xbb, 0x43, 0xe5, 0x4d, 0x15, 0x5b, 0x1d, 0xe4, 0x3c, 0x47, 0xc6, 0xa9, 0xfc, 0x7e,
-	0xf8, 0x65, 0x1d, 0xda, 0x47, 0xfd, 0xe3, 0x93, 0xa3, 0x30, 0x9c, 0x7a, 0x63, 0x8a, 0x5d, 0xd7,
-	0x01, 0xd4, 0xb0, 0xaf, 0x2c, 0x79, 0x9d, 0xea, 0x95, 0x0d, 0x38, 0xe4, 0x10, 0xea, 0xd8, 0x5e,
-	0x92, 0xb2, 0x47, 0xaa, 0x5e, 0xe9, 0x9c, 0x23, 0x0f, 0x51, 0x0d, 0xe8, 0xd5, 0xb7, 0xaa, 0x5e,
-	0xd9, 0xb0, 0x43, 0x3e, 0x02, 0x33, 0x6d, 0x0c, 0x97, 0xbd, 0x58, 0xf5, 0x96, 0x8e, 0x3d, 0x52,
-	0x3f, 0xad, 0xb5, 0xcb, 0x1e, 0x5e, 0x7a, 0x4b, 0xe7, 0x03, 0xf2, 0x08, 0x9a, 0x71, 0xb7, 0x52,
-	0xfe, 0xa6, 0xd4, 0x5b, 0x32, 0x92, 0x48, 0xf7, 0xa8, 0x8e, 0xaf, 0xec, 0xe1, 0xab, 0x57, 0x3a,
-	0x37, 0x91, 0x07, 0xd0, 0xd0, 0x05, 0xa3, 0xf4, 0x5d, 0xa9, 0x57, 0x3e, 0x58, 0x48, 0x23, 0xd3,
-	0x6e, 0x77, 0xd9, 0xe3, 0x5c, 0x6f, 0xe9, 0x80, 0x47, 0x8e, 0x00, 0x32, 0x5d, 0xde, 0xd2, 0x57,
-	0xb7, 0xde, 0xf2, 0xc1, 0x8d, 0x7c, 0x08, 0xad, 0x74, 0x18, 0x2f, 0x7f, 0x47, 0xeb, 0x2d, 0x9b,
-	0xa5, 0xfa, 0xdf, 0xf8, 0xd7, 0xdf, 0x77, 0x8c, 0xdf, 0x5e, 0xee, 0x18, 0x7f, 0xbc, 0xdc, 0x31,
-	0xbe, 0xba, 0xdc, 0x31, 0xfe, 0x72, 0xb9, 0x63, 0xfc, 0xed, 0x72, 0xc7, 0xf8, 0xd3, 0xd7, 0x3b,
-	0xc6, 0xa8, 0x81, 0xef, 0xa9, 0xef, 0xfd, 0x27, 0x00, 0x00, 0xff, 0xff, 0xf4, 0x59, 0x8b, 0xa6,
-	0xd9, 0x15, 0x00, 0x00,
+func init() { proto.RegisterFile("abci/types/types.proto", fileDescriptor_types_d8da2202f45d32c0) }
+func init() {
+	golang_proto.RegisterFile("abci/types/types.proto", fileDescriptor_types_d8da2202f45d32c0)
+}
+
+var fileDescriptor_types_d8da2202f45d32c0 = []byte{
+	// 1959 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0x4f, 0x73, 0x1b, 0x49,
+	0x15, 0xf7, 0xc8, 0xb2, 0xa4, 0x79, 0xb2, 0x2d, 0xa7, 0x9d, 0xd8, 0x8a, 0x16, 0xec, 0x30, 0x45,
+	0x65, 0x1d, 0xd6, 0x2b, 0x83, 0x97, 0x6c, 0x39, 0xbb, 0xb0, 0x85, 0xe5, 0x0d, 0x2b, 0xd7, 0x2e,
+	0x60, 0x26, 0xd9, 0x50, 0xc5, 0x45, 0xd5, 0xd2, 0xb4, 0x47, 0x53, 0x91, 0x66, 0x66, 0xa7, 0x5b,
+	0x5e, 0x39, 0x1f, 0x81, 0xda, 0xa2, 0xb8, 0x71, 0xe6, 0xc6, 0x17, 0xa0, 0x8a, 0x23, 0x27, 0x6a,
+	0x8f, 0x1c, 0xa0, 0xe0, 0x14, 0xc0, 0x5b, 0x5c, 0xf8, 0x04, 0x1c, 0xa9, 0xd7, 0xdd, 0xf3, 0xd7,
+	0xa3, 0x54, 0x12, 0x6e, 0x5c, 0xa4, 0xee, 0x7e, 0xef, 0xf5, 0xf4, 0x7b, 0xfd, 0xde, 0xfb, 0xbd,
+	0xd7, 0xb0, 0x45, 0x87, 0x23, 0xef, 0x40, 0x5c, 0x86, 0x8c, 0xab, 0xdf, 0x6e, 0x18, 0x05, 0x22,
+	0x20, 0x2b, 0x72, 0xd2, 0x79, 0xdb, 0xf5, 0xc4, 0x78, 0x36, 0xec, 0x8e, 0x82, 0xe9, 0x81, 0x1b,
+	0xb8, 0xc1, 0x81, 0xa4, 0x0e, 0x67, 0xe7, 0x72, 0x26, 0x27, 0x72, 0xa4, 0xa4, 0x3a, 0xbb, 0x6e,
+	0x10, 0xb8, 0x13, 0x96, 0x72, 0x09, 0x6f, 0xca, 0xb8, 0xa0, 0xd3, 0x50, 0x33, 0x1c, 0x65, 0xf6,
+	0x13, 0xcc, 0x77, 0x58, 0x34, 0xf5, 0x7c, 0x91, 0x1d, 0x4e, 0xbc, 0x21, 0x3f, 0x18, 0x05, 0xd3,
+	0x69, 0xe0, 0x67, 0x0f, 0x64, 0xfd, 0xb1, 0x0a, 0x75, 0x9b, 0x7d, 0x36, 0x63, 0x5c, 0x90, 0x3d,
+	0xa8, 0xb2, 0xd1, 0x38, 0x68, 0x57, 0xee, 0x18, 0x7b, 0xcd, 0x43, 0xd2, 0x55, 0x7c, 0x9a, 0xfa,
+	0x70, 0x34, 0x0e, 0xfa, 0x4b, 0xb6, 0xe4, 0x20, 0x6f, 0xc1, 0xca, 0xf9, 0x64, 0xc6, 0xc7, 0xed,
+	0x65, 0xc9, 0xba, 0x99, 0x67, 0xfd, 0x21, 0x92, 0xfa, 0x4b, 0xb6, 0xe2, 0xc1, 0x6d, 0x3d, 0xff,
+	0x3c, 0x68, 0x57, 0xcb, 0xb6, 0x3d, 0xf5, 0xcf, 0xe5, 0xb6, 0xc8, 0x41, 0x8e, 0x00, 0x38, 0x13,
+	0x83, 0x20, 0x14, 0x5e, 0xe0, 0xb7, 0x57, 0x24, 0xff, 0x76, 0x9e, 0xff, 0x11, 0x13, 0x3f, 0x91,
+	0xe4, 0xfe, 0x92, 0x6d, 0xf2, 0x78, 0x82, 0x92, 0x9e, 0xef, 0x89, 0xc1, 0x68, 0x4c, 0x3d, 0xbf,
+	0x5d, 0x2b, 0x93, 0x3c, 0xf5, 0x3d, 0x71, 0x82, 0x64, 0x94, 0xf4, 0xe2, 0x09, 0xaa, 0xf2, 0xd9,
+	0x8c, 0x45, 0x97, 0xed, 0x7a, 0x99, 0x2a, 0x3f, 0x45, 0x12, 0xaa, 0x22, 0x79, 0xc8, 0xfb, 0xd0,
+	0x1c, 0x32, 0xd7, 0xf3, 0x07, 0xc3, 0x49, 0x30, 0x7a, 0xda, 0x6e, 0x48, 0x91, 0x76, 0x5e, 0xa4,
+	0x87, 0x0c, 0x3d, 0xa4, 0xf7, 0x97, 0x6c, 0x18, 0x26, 0x33, 0x72, 0x08, 0x8d, 0xd1, 0x98, 0x8d,
+	0x9e, 0x0e, 0xc4, 0xbc, 0x6d, 0x4a, 0xc9, 0x5b, 0x79, 0xc9, 0x13, 0xa4, 0x3e, 0x9e, 0xf7, 0x97,
+	0xec, 0xfa, 0x48, 0x0d, 0xc9, 0x7d, 0x30, 0x99, 0xef, 0xe8, 0xcf, 0x35, 0xa5, 0xd0, 0x56, 0xe1,
+	0x5e, 0x7c, 0x27, 0xfe, 0x58, 0x83, 0xe9, 0x31, 0xe9, 0x42, 0x0d, 0xef, 0xda, 0x13, 0xed, 0x55,
+	0x29, 0x73, 0xb3, 0xf0, 0x21, 0x49, 0xeb, 0x2f, 0xd9, 0x9a, 0x0b, 0xcd, 0xe7, 0xb0, 0x89, 0x77,
+	0xc1, 0x22, 0x3c, 0xdc, 0x66, 0x99, 0xf9, 0x3e, 0x54, 0x74, 0x79, 0x3c, 0xd3, 0x89, 0x27, 0xbd,
+	0x3a, 0xac, 0x5c, 0xd0, 0xc9, 0x8c, 0x59, 0x6f, 0x42, 0x33, 0xe3, 0x29, 0xa4, 0x0d, 0xf5, 0x29,
+	0xe3, 0x9c, 0xba, 0xac, 0x6d, 0xdc, 0x31, 0xf6, 0x4c, 0x3b, 0x9e, 0x5a, 0xeb, 0xb0, 0x9a, 0xf5,
+	0x93, 0x8c, 0x20, 0xfa, 0x02, 0x0a, 0x5e, 0xb0, 0x88, 0xa3, 0x03, 0x68, 0x41, 0x3d, 0xb5, 0xde,
+	0x83, 0x8d, 0xa2, 0x13, 0x90, 0x0d, 0x58, 0x7e, 0xca, 0x2e, 0x35, 0x27, 0x0e, 0xc9, 0x4d, 0x7d,
+	0x20, 0xe9, 0xc5, 0xa6, 0xad, 0x4f, 0xf7, 0x8b, 0x4a, 0x22, 0x9c, 0xf8, 0x01, 0x39, 0x82, 0x2a,
+	0x06, 0x92, 0x94, 0x6e, 0x1e, 0x76, 0xba, 0x2a, 0xca, 0xba, 0x71, 0x94, 0x75, 0x1f, 0xc7, 0x51,
+	0xd6, 0x6b, 0x7c, 0xf9, 0x7c, 0x77, 0xe9, 0x57, 0x7f, 0xdf, 0x35, 0x6c, 0x29, 0x41, 0x6e, 0xe3,
+	0x55, 0x52, 0xcf, 0x1f, 0x78, 0x8e, 0xfe, 0x4e, 0x5d, 0xce, 0x4f, 0x1d, 0x72, 0x0c, 0x1b, 0xa3,
+	0xc0, 0xe7, 0xcc, 0xe7, 0x33, 0x3e, 0x08, 0x69, 0x44, 0xa7, 0x5c, 0x47, 0x49, 0x7c, 0x71, 0x27,
+	0x31, 0xf9, 0x4c, 0x52, 0xed, 0xd6, 0x28, 0xbf, 0x40, 0xde, 0x05, 0xb8, 0xa0, 0x13, 0xcf, 0xa1,
+	0x22, 0x88, 0x78, 0xbb, 0x7a, 0x67, 0x79, 0xaf, 0x79, 0xb8, 0xa1, 0x85, 0x9f, 0xc4, 0x84, 0x5e,
+	0x15, 0xcf, 0x64, 0x67, 0x38, 0xc9, 0x5d, 0x68, 0xd1, 0x30, 0x1c, 0x70, 0x41, 0x05, 0x1b, 0x0c,
+	0x2f, 0x05, 0xe3, 0x32, 0x86, 0x56, 0xed, 0x35, 0x1a, 0x86, 0x8f, 0x70, 0xb5, 0x87, 0x8b, 0x96,
+	0x93, 0xdc, 0x80, 0x74, 0x6f, 0x42, 0xa0, 0xea, 0x50, 0x41, 0xa5, 0x1d, 0x56, 0x6d, 0x39, 0xc6,
+	0xb5, 0x90, 0x8a, 0xb1, 0xd6, 0x4e, 0x8e, 0xc9, 0x16, 0xd4, 0xc6, 0xcc, 0x73, 0xc7, 0x42, 0x2a,
+	0xb4, 0x6c, 0xeb, 0x19, 0x9a, 0x3c, 0x8c, 0x82, 0x0b, 0x26, 0x23, 0xbc, 0x61, 0xab, 0x89, 0xf5,
+	0x2f, 0x03, 0x6e, 0x5c, 0x0b, 0x09, 0xdc, 0x77, 0x4c, 0xf9, 0x38, 0xfe, 0x16, 0x8e, 0xc9, 0x5b,
+	0xb8, 0x2f, 0x75, 0x58, 0xa4, 0x33, 0xcf, 0x9a, 0xd6, 0xb5, 0x2f, 0x17, 0xb5, 0xa2, 0x9a, 0x85,
+	0x3c, 0x84, 0x8d, 0x09, 0xe5, 0x62, 0xa0, 0x3c, 0x77, 0x20, 0x33, 0xcb, 0x72, 0x2e, 0x9a, 0x3e,
+	0xa1, 0xb1, 0x87, 0xa3, 0x43, 0x69, 0xf1, 0xf5, 0x49, 0x6e, 0x95, 0xf4, 0xe1, 0xe6, 0xf0, 0xf2,
+	0x19, 0xf5, 0x85, 0xe7, 0xb3, 0xc1, 0x35, 0x6b, 0xb7, 0xf4, 0x56, 0x0f, 0x2f, 0x3c, 0x87, 0xf9,
+	0x23, 0xa6, 0x37, 0xd9, 0x4c, 0x44, 0x92, 0x6b, 0xe0, 0xd6, 0x1d, 0x58, 0xcf, 0xc7, 0x2f, 0x59,
+	0x87, 0x8a, 0x98, 0x6b, 0x0d, 0x2b, 0x62, 0x6e, 0x59, 0x89, 0xef, 0x25, 0x41, 0x74, 0x8d, 0xe7,
+	0x1e, 0xb4, 0x0a, 0x01, 0x9d, 0x31, 0xb7, 0x91, 0x35, 0xb7, 0xd5, 0x82, 0xb5, 0x5c, 0x1c, 0x5b,
+	0x5f, 0xac, 0x40, 0xc3, 0x66, 0x3c, 0x44, 0x37, 0x22, 0x47, 0x60, 0xb2, 0xf9, 0x88, 0xa9, 0x14,
+	0x6a, 0x14, 0x12, 0x94, 0xe2, 0x79, 0x18, 0xd3, 0x31, 0x94, 0x13, 0x66, 0x72, 0x2f, 0x97, 0xfe,
+	0x37, 0x8b, 0x42, 0xd9, 0xfc, 0xbf, 0x9f, 0xcf, 0xff, 0x37, 0x0b, 0xbc, 0x05, 0x00, 0xb8, 0x97,
+	0x03, 0x80, 0xe2, 0xc6, 0x39, 0x04, 0x78, 0x50, 0x82, 0x00, 0xc5, 0xe3, 0x2f, 0x80, 0x80, 0x07,
+	0x25, 0x10, 0xd0, 0xbe, 0xf6, 0xad, 0x52, 0x0c, 0xd8, 0xcf, 0x63, 0x40, 0x51, 0x9d, 0x02, 0x08,
+	0x7c, 0xaf, 0x0c, 0x04, 0x6e, 0x17, 0x64, 0x16, 0xa2, 0xc0, 0x3b, 0xd7, 0x50, 0x60, 0xab, 0x20,
+	0x5a, 0x02, 0x03, 0x0f, 0x72, 0xf9, 0x19, 0x4a, 0x75, 0x2b, 0x4f, 0xd0, 0xe4, 0xdd, 0xeb, 0x08,
+	0xb2, 0x5d, 0xbc, 0xda, 0x32, 0x08, 0x39, 0x28, 0x40, 0xc8, 0xad, 0xe2, 0x29, 0x0b, 0x18, 0x92,
+	0x22, 0xc1, 0x3d, 0x8c, 0xfb, 0x82, 0xa7, 0x61, 0x8e, 0x60, 0x51, 0x14, 0x44, 0x3a, 0x55, 0xab,
+	0x89, 0xb5, 0x87, 0x99, 0x28, 0xf5, 0xaf, 0x17, 0xa0, 0x86, 0x74, 0xfa, 0x8c, 0x77, 0x59, 0xbf,
+	0x36, 0x52, 0x59, 0x19, 0xd1, 0xd9, 0x2c, 0x66, 0xea, 0x2c, 0x96, 0x01, 0x93, 0x4a, 0x0e, 0x4c,
+	0xc8, 0xb7, 0xe0, 0x86, 0x4c, 0x23, 0xd2, 0x2e, 0x83, 0x5c, 0x5a, 0x6b, 0x21, 0x41, 0x19, 0x44,
+	0xe5, 0xb7, 0xb7, 0x61, 0x33, 0xc3, 0x8b, 0x29, 0x56, 0xa6, 0xb0, 0xaa, 0x0c, 0xde, 0x8d, 0x84,
+	0xfb, 0x38, 0x0c, 0xfb, 0x94, 0x8f, 0xad, 0x1f, 0xa5, 0xfa, 0xa7, 0x40, 0x45, 0xa0, 0x3a, 0x0a,
+	0x1c, 0xa5, 0xd6, 0x9a, 0x2d, 0xc7, 0x08, 0x5e, 0x93, 0xc0, 0x95, 0x5f, 0x35, 0x6d, 0x1c, 0x22,
+	0x57, 0x12, 0x29, 0xa6, 0x0a, 0x09, 0xeb, 0x97, 0x46, 0xba, 0x5f, 0x8a, 0x5d, 0x65, 0x30, 0x63,
+	0xfc, 0x2f, 0x30, 0x53, 0x79, 0x59, 0x98, 0xb1, 0x7e, 0x67, 0xa4, 0x77, 0x91, 0x00, 0xc8, 0xeb,
+	0x29, 0x87, 0x6e, 0xe1, 0xf9, 0x0e, 0x9b, 0xcb, 0x50, 0x5f, 0xb6, 0xd5, 0x24, 0x46, 0xf5, 0x9a,
+	0x34, 0x70, 0x1e, 0xd5, 0xeb, 0x72, 0x4d, 0x4d, 0x34, 0xf0, 0x04, 0xe7, 0x32, 0x06, 0x57, 0x6d,
+	0x35, 0xc9, 0xe4, 0x4d, 0x33, 0x97, 0x37, 0xcf, 0x80, 0x5c, 0x8f, 0x4e, 0xf2, 0x1e, 0x54, 0x05,
+	0x75, 0xd1, 0x78, 0xa8, 0xff, 0x7a, 0x57, 0xd5, 0xc8, 0xdd, 0x8f, 0x9f, 0x9c, 0x51, 0x2f, 0xea,
+	0x6d, 0xa1, 0xf6, 0xff, 0x7e, 0xbe, 0xbb, 0x8e, 0x3c, 0xfb, 0xc1, 0xd4, 0x13, 0x6c, 0x1a, 0x8a,
+	0x4b, 0x5b, 0xca, 0x58, 0x7f, 0x31, 0x30, 0x6b, 0xe7, 0xa2, 0xb6, 0xd4, 0x16, 0xb1, 0x6b, 0x56,
+	0x32, 0x00, 0xfb, 0x72, 0xf6, 0xf9, 0x3a, 0x80, 0x4b, 0xf9, 0xe0, 0x73, 0xea, 0x0b, 0xe6, 0x68,
+	0x23, 0x99, 0x2e, 0xe5, 0x3f, 0x93, 0x0b, 0x58, 0x87, 0x20, 0x79, 0xc6, 0x99, 0x23, 0xad, 0xb5,
+	0x6c, 0xd7, 0x5d, 0xca, 0x3f, 0xe5, 0xcc, 0x49, 0xf4, 0xaa, 0xbf, 0x86, 0x5e, 0x7f, 0xcd, 0xb8,
+	0x5c, 0x0a, 0x59, 0xff, 0x0f, 0x9a, 0x7d, 0x65, 0x20, 0x16, 0xe7, 0xd3, 0x1e, 0x39, 0x81, 0x1b,
+	0x89, 0x7b, 0x0f, 0x66, 0xa1, 0x43, 0xb1, 0x72, 0x32, 0x5e, 0x18, 0x0f, 0x1b, 0x89, 0xc0, 0xa7,
+	0x8a, 0x9f, 0xfc, 0x18, 0xb6, 0x0b, 0x01, 0x99, 0x6c, 0x55, 0x79, 0x61, 0x5c, 0xde, 0xca, 0xc7,
+	0x65, 0xbc, 0x5f, 0xac, 0xe5, 0xf2, 0x6b, 0x68, 0xf9, 0x4d, 0x2c, 0x49, 0xb2, 0x69, 0xba, 0xec,
+	0x9e, 0xac, 0xdf, 0x18, 0xd0, 0x2a, 0x1c, 0x86, 0x1c, 0x00, 0xa8, 0x2c, 0xc7, 0xbd, 0x67, 0x71,
+	0x61, 0x1c, 0xdb, 0x40, 0x1a, 0xeb, 0x91, 0xf7, 0x8c, 0xd9, 0xe6, 0x30, 0x1e, 0x92, 0xbb, 0x50,
+	0x17, 0x73, 0xc5, 0x9d, 0x2f, 0xde, 0x1e, 0xcf, 0x25, 0x6b, 0x4d, 0xc8, 0x7f, 0x72, 0x1f, 0x56,
+	0xd5, 0xc6, 0x6e, 0xc0, 0xb9, 0x17, 0xea, 0xc2, 0x81, 0x64, 0xb7, 0xfe, 0x48, 0x52, 0xec, 0xe6,
+	0x30, 0x9d, 0x58, 0x3f, 0x07, 0x33, 0xf9, 0x2c, 0x79, 0x03, 0xcc, 0x29, 0x9d, 0xeb, 0xca, 0x16,
+	0xcf, 0xb6, 0x62, 0x37, 0xa6, 0x74, 0x2e, 0x8b, 0x5a, 0xb2, 0x0d, 0x75, 0x24, 0x8a, 0xb9, 0xb2,
+	0xf7, 0x8a, 0x5d, 0x9b, 0xd2, 0xf9, 0xe3, 0x79, 0x42, 0x70, 0x29, 0x8f, 0xcb, 0xd6, 0x29, 0x9d,
+	0x7f, 0x44, 0xb9, 0xf5, 0x01, 0xd4, 0xd4, 0x21, 0x5f, 0x6a, 0x63, 0x94, 0xaf, 0xe4, 0xe4, 0x7f,
+	0x00, 0xcd, 0xcc, 0xb9, 0xc9, 0x77, 0xe0, 0x96, 0xd2, 0x30, 0xa4, 0x91, 0x90, 0x16, 0xc9, 0x6d,
+	0x48, 0x24, 0xf1, 0x8c, 0x46, 0x02, 0x3f, 0xa9, 0x0a, 0xf1, 0x08, 0xd6, 0xf3, 0xc5, 0x2a, 0xf9,
+	0x06, 0xac, 0xea, 0xc2, 0x36, 0x0a, 0x66, 0xbe, 0xa3, 0x65, 0x9b, 0x6a, 0xcd, 0xc6, 0x25, 0xf2,
+	0xfd, 0x92, 0xb4, 0x1d, 0x23, 0xfa, 0x23, 0xcf, 0xf5, 0x3d, 0xdf, 0x7d, 0x51, 0xf6, 0xfe, 0x5b,
+	0x05, 0x6a, 0xaa, 0xb0, 0x26, 0x77, 0x33, 0x5d, 0x8c, 0x44, 0xcd, 0x5e, 0xf3, 0xea, 0xf9, 0x6e,
+	0x5d, 0x02, 0xcc, 0xe9, 0x87, 0x69, 0x4b, 0x93, 0x26, 0xd4, 0x4a, 0xae, 0xee, 0x8f, 0xfb, 0xa7,
+	0xe5, 0x57, 0xee, 0x9f, 0xb6, 0xa1, 0xee, 0xcf, 0xa6, 0xf2, 0xb2, 0xaa, 0xea, 0xb2, 0xfc, 0xd9,
+	0x14, 0x2f, 0xeb, 0x0d, 0x30, 0x45, 0x20, 0xe8, 0x44, 0x92, 0x54, 0x52, 0x68, 0xc8, 0x05, 0x24,
+	0xde, 0x85, 0x56, 0x16, 0xb3, 0x11, 0x83, 0x15, 0x44, 0xac, 0xa5, 0x88, 0x8d, 0xfd, 0xc4, 0x9b,
+	0xd0, 0x4a, 0x15, 0x56, 0x7c, 0x0a, 0x36, 0xd6, 0xd3, 0x65, 0xc9, 0x78, 0x1b, 0x1a, 0x09, 0x9a,
+	0x2b, 0x08, 0xa9, 0x53, 0x05, 0xe2, 0xd8, 0xac, 0x87, 0x51, 0x10, 0x06, 0x9c, 0x45, 0xba, 0x4c,
+	0x5b, 0x94, 0x0a, 0x12, 0x3e, 0xcb, 0x03, 0x33, 0x21, 0x62, 0xe9, 0x41, 0x1d, 0x27, 0x62, 0x9c,
+	0xeb, 0x2a, 0x3f, 0x9e, 0x92, 0x7d, 0xa8, 0x87, 0xb3, 0xe1, 0x00, 0x11, 0x2e, 0x1f, 0x32, 0x67,
+	0xb3, 0xe1, 0xc7, 0xec, 0x32, 0xee, 0x77, 0x42, 0x39, 0x93, 0x18, 0x17, 0x7c, 0xce, 0x22, 0xed,
+	0xbc, 0x6a, 0x62, 0x09, 0xd8, 0x28, 0xde, 0x35, 0xf9, 0x2e, 0x98, 0x89, 0x7e, 0x85, 0xd0, 0x2d,
+	0x9e, 0x39, 0x65, 0xc4, 0x42, 0x88, 0x7b, 0xae, 0xcf, 0x9c, 0x41, 0x6a, 0x5b, 0x79, 0xae, 0x86,
+	0xdd, 0x52, 0x84, 0x4f, 0x62, 0xe3, 0x5a, 0xdf, 0x86, 0x9a, 0x3a, 0x23, 0xe6, 0x13, 0xdc, 0x39,
+	0x2e, 0xb6, 0x70, 0x5c, 0x9a, 0x63, 0xfe, 0x6c, 0x40, 0x23, 0x6e, 0xa2, 0x4a, 0x85, 0x72, 0x87,
+	0xae, 0xbc, 0xec, 0xa1, 0x17, 0x75, 0xa2, 0xb1, 0x47, 0x56, 0x5f, 0xd9, 0x23, 0xf7, 0x81, 0x28,
+	0xc7, 0xbb, 0x08, 0x84, 0xe7, 0xbb, 0x03, 0x65, 0x73, 0xe5, 0x81, 0x1b, 0x92, 0xf2, 0x44, 0x12,
+	0xce, 0x70, 0xfd, 0xf0, 0x8b, 0x15, 0x68, 0x1d, 0xf7, 0x4e, 0x4e, 0x8f, 0xc3, 0x70, 0xe2, 0x8d,
+	0xa8, 0xac, 0xf0, 0x0e, 0xa0, 0x2a, 0x6b, 0xd8, 0x92, 0x77, 0xb3, 0x4e, 0x59, 0x33, 0x45, 0x0e,
+	0x61, 0x45, 0x96, 0xb2, 0xa4, 0xec, 0xf9, 0xac, 0x53, 0xda, 0x53, 0xe1, 0x47, 0x54, 0xb1, 0x7b,
+	0xfd, 0x15, 0xad, 0x53, 0xd6, 0x58, 0x91, 0x0f, 0xc0, 0x4c, 0x8b, 0xd0, 0x45, 0x6f, 0x69, 0x9d,
+	0x85, 0x2d, 0x16, 0xca, 0xa7, 0x15, 0xc0, 0xa2, 0x27, 0xa1, 0xce, 0xc2, 0x5e, 0x84, 0x1c, 0x41,
+	0x3d, 0xae, 0x8c, 0xca, 0x5f, 0xbb, 0x3a, 0x0b, 0xda, 0x1f, 0x34, 0x8f, 0xaa, 0x2e, 0xcb, 0x9e,
+	0xe4, 0x3a, 0xa5, 0x3d, 0x1a, 0xb9, 0x0f, 0x35, 0x0d, 0x78, 0xa5, 0x2f, 0x5e, 0x9d, 0xf2, 0x26,
+	0x06, 0x95, 0x4c, 0x2b, 0xeb, 0x45, 0xcf, 0x86, 0x9d, 0x85, 0xcd, 0x24, 0x39, 0x06, 0xc8, 0x54,
+	0x94, 0x0b, 0xdf, 0x03, 0x3b, 0x8b, 0x9b, 0x44, 0xf2, 0x3e, 0x34, 0xd2, 0xc6, 0xbf, 0xfc, 0x85,
+	0xaf, 0xb3, 0xa8, 0x6f, 0xeb, 0x7d, 0xed, 0x3f, 0xff, 0xdc, 0x31, 0x7e, 0x7b, 0xb5, 0x63, 0xfc,
+	0xfe, 0x6a, 0xc7, 0xf8, 0xf2, 0x6a, 0xc7, 0xf8, 0xd3, 0xd5, 0x8e, 0xf1, 0x8f, 0xab, 0x1d, 0xe3,
+	0x0f, 0x5f, 0xed, 0x18, 0xc3, 0x9a, 0x74, 0xff, 0x77, 0xfe, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xc1,
+	0xc2, 0x93, 0xfb, 0x94, 0x16, 0x00, 0x00,
 }
diff --git a/vendor/github.com/tendermint/tendermint/abci/types/types.proto b/vendor/github.com/tendermint/tendermint/abci/types/types.proto
index 0e1c18430fde7c6e2e399c1025189e8bbe277201..6e6b1cd3671a542833b635755ba6cab361cd52ac 100644
--- a/vendor/github.com/tendermint/tendermint/abci/types/types.proto
+++ b/vendor/github.com/tendermint/tendermint/abci/types/types.proto
@@ -4,6 +4,7 @@ package types;
 // For more information on gogo.proto, see:
 // https://github.com/gogo/protobuf/blob/master/extensions.md
 import "github.com/gogo/protobuf/gogoproto/gogo.proto";
+import "google/protobuf/timestamp.proto";
 import "github.com/tendermint/tendermint/libs/common/types.proto";
 
 // This file is copied from http://github.com/tendermint/abci
@@ -56,7 +57,7 @@ message RequestSetOption {
 }
 
 message RequestInitChain {
-  int64 time = 1;
+  google.protobuf.Timestamp time = 1  [(gogoproto.nullable)=false, (gogoproto.stdtime)=true];
   string chain_id = 2;
   ConsensusParams consensus_params = 3;
   repeated Validator validators = 4  [(gogoproto.nullable)=false];
@@ -70,10 +71,11 @@ message RequestQuery {
   bool prove = 4;
 }
 
+// NOTE: validators here have empty pubkeys.
 message RequestBeginBlock {
   bytes hash = 1;
   Header header = 2 [(gogoproto.nullable)=false];
-  repeated SigningValidator validators = 3  [(gogoproto.nullable)=false];
+  LastCommitInfo last_commit_info = 3 [(gogoproto.nullable)=false];
   repeated Evidence byzantine_validators = 4 [(gogoproto.nullable)=false];
 }
 
@@ -168,7 +170,6 @@ message ResponseCheckTx {
   int64 gas_wanted  = 5;
   int64 gas_used = 6;
   repeated common.KVPair tags = 7 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"];
-  common.KI64Pair fee = 8 [(gogoproto.nullable)=false];
 }
 
 message ResponseDeliverTx {
@@ -179,7 +180,6 @@ message ResponseDeliverTx {
   int64 gas_wanted = 5;
   int64 gas_used = 6;
   repeated common.KVPair tags = 7 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"];
-  common.KI64Pair fee = 8 [(gogoproto.nullable)=false];
 }
 
 message ResponseEndBlock {
@@ -204,14 +204,14 @@ message ConsensusParams {
   BlockGossip block_gossip = 3;
 }
 
-// BlockSize contain limits on the block size.
+// BlockSize contains limits on the block size.
 message BlockSize {
   int32 max_bytes = 1;
   int32 max_txs = 2;
   int64 max_gas = 3;
 }
 
-// TxSize contain limits on the tx size.
+// TxSize contains limits on the tx size.
 message TxSize {
   int32 max_bytes = 1;
   int64 max_gas = 2;
@@ -224,6 +224,11 @@ message BlockGossip {
   int32 block_part_size_bytes = 1;
 }
 
+message LastCommitInfo {
+  int32 commit_round = 1;
+  repeated SigningValidator validators = 2 [(gogoproto.nullable)=false];
+}
+
 //----------------------------------------
 // Blockchain Types
 
@@ -232,7 +237,7 @@ message Header {
   // basics
   string chain_id = 1 [(gogoproto.customname)="ChainID"];
   int64 height = 2;
-  int64 time = 3;
+  google.protobuf.Timestamp time = 3 [(gogoproto.nullable)=false, (gogoproto.stdtime)=true];
 
   // txs
   int32 num_txs = 4;
@@ -269,7 +274,7 @@ message Evidence {
   string type = 1;
   Validator validator = 2 [(gogoproto.nullable)=false];
   int64 height = 3;
-  int64 time = 4;
+  google.protobuf.Timestamp time = 4 [(gogoproto.nullable)=false, (gogoproto.stdtime)=true];
   int64 total_voting_power = 5;
 }
 
diff --git a/vendor/github.com/tendermint/tendermint/blockchain/pool.go b/vendor/github.com/tendermint/tendermint/blockchain/pool.go
index e379d846a79508680e6665a56d9fc22980f65385..a881c7cb736a470b80955bf1784056695072539f 100644
--- a/vendor/github.com/tendermint/tendermint/blockchain/pool.go
+++ b/vendor/github.com/tendermint/tendermint/blockchain/pool.go
@@ -29,10 +29,10 @@ eg, L = latency = 0.1s
 */
 
 const (
-	requestIntervalMS         = 100
-	maxTotalRequesters        = 1000
+	requestIntervalMS         = 2
+	maxTotalRequesters        = 600
 	maxPendingRequests        = maxTotalRequesters
-	maxPendingRequestsPerPeer = 50
+	maxPendingRequestsPerPeer = 20
 
 	// Minimum recv rate to ensure we're receiving blocks from a peer fast
 	// enough. If a peer is not sending us data at at least that rate, we
@@ -219,14 +219,12 @@ func (pool *BlockPool) RedoRequest(height int64) p2p.ID {
 	defer pool.mtx.Unlock()
 
 	request := pool.requesters[height]
-
-	if request.block == nil {
-		panic("Expected block to be non-nil")
+	peerID := request.getPeerID()
+	if peerID != p2p.ID("") {
+		// RemovePeer will redo all requesters associated with this peer.
+		pool.removePeer(peerID)
 	}
-
-	// RemovePeer will redo all requesters associated with this peer.
-	pool.removePeer(request.peerID)
-	return request.peerID
+	return peerID
 }
 
 // TODO: ensure that blocks come in order for each peer.
diff --git a/vendor/github.com/tendermint/tendermint/blockchain/reactor.go b/vendor/github.com/tendermint/tendermint/blockchain/reactor.go
index 449a42ff09e6e17ab0a191d59373be6ec6cf0aff..f00df50c32879213186eed250dde5e6263d2dd28 100644
--- a/vendor/github.com/tendermint/tendermint/blockchain/reactor.go
+++ b/vendor/github.com/tendermint/tendermint/blockchain/reactor.go
@@ -18,7 +18,8 @@ const (
 	// BlockchainChannel is a channel for blocks and status updates (`BlockStore` height)
 	BlockchainChannel = byte(0x40)
 
-	trySyncIntervalMS = 50
+	trySyncIntervalMS = 10
+
 	// stop syncing when last block's time is
 	// within this much of the system time.
 	// stopSyncingDurationMinutes = 10
@@ -76,8 +77,9 @@ func NewBlockchainReactor(state sm.State, blockExec *sm.BlockExecutor, store *Bl
 			store.Height()))
 	}
 
-	const capacity = 1000 // must be bigger than peers count
-	requestsCh := make(chan BlockRequest, capacity)
+	requestsCh := make(chan BlockRequest, maxTotalRequesters)
+
+	const capacity = 1000                      // must be bigger than peers count
 	errorsCh := make(chan peerError, capacity) // so we don't block in #Receive#pool.AddBlock
 
 	pool := NewBlockPool(
@@ -107,9 +109,6 @@ func (bcR *BlockchainReactor) SetLogger(l log.Logger) {
 
 // OnStart implements cmn.Service.
 func (bcR *BlockchainReactor) OnStart() error {
-	if err := bcR.BaseReactor.OnStart(); err != nil {
-		return err
-	}
 	if bcR.fastSync {
 		err := bcR.pool.Start()
 		if err != nil {
@@ -122,7 +121,6 @@ func (bcR *BlockchainReactor) OnStart() error {
 
 // OnStop implements cmn.Service.
 func (bcR *BlockchainReactor) OnStop() {
-	bcR.BaseReactor.OnStop()
 	bcR.pool.Stop()
 }
 
@@ -209,7 +207,6 @@ func (bcR *BlockchainReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte)
 
 // Handle messages from the poolReactor telling the reactor what to do.
 // NOTE: Don't sleep in the FOR_LOOP or otherwise slow it down!
-// (Except for the SYNC_LOOP, which is the primary purpose and must be synchronous.)
 func (bcR *BlockchainReactor) poolRoutine() {
 
 	trySyncTicker := time.NewTicker(trySyncIntervalMS * time.Millisecond)
@@ -224,6 +221,8 @@ func (bcR *BlockchainReactor) poolRoutine() {
 	lastHundred := time.Now()
 	lastRate := 0.0
 
+	didProcessCh := make(chan struct{}, 1)
+
 FOR_LOOP:
 	for {
 		select {
@@ -239,14 +238,17 @@ FOR_LOOP:
 				// The pool handles timeouts, just let it go.
 				continue FOR_LOOP
 			}
+
 		case err := <-bcR.errorsCh:
 			peer := bcR.Switch.Peers().Get(err.peerID)
 			if peer != nil {
 				bcR.Switch.StopPeerForError(peer, err)
 			}
+
 		case <-statusUpdateTicker.C:
 			// ask for status updates
 			go bcR.BroadcastStatusRequest() // nolint: errcheck
+
 		case <-switchToConsensusTicker.C:
 			height, numPending, lenRequesters := bcR.pool.GetStatus()
 			outbound, inbound, _ := bcR.Switch.NumPeers()
@@ -261,60 +263,78 @@ FOR_LOOP:
 
 				break FOR_LOOP
 			}
+
 		case <-trySyncTicker.C: // chan time
-			// This loop can be slow as long as it's doing syncing work.
-		SYNC_LOOP:
-			for i := 0; i < 10; i++ {
-				// See if there are any blocks to sync.
-				first, second := bcR.pool.PeekTwoBlocks()
-				//bcR.Logger.Info("TrySync peeked", "first", first, "second", second)
-				if first == nil || second == nil {
-					// We need both to sync the first block.
-					break SYNC_LOOP
+			select {
+			case didProcessCh <- struct{}{}:
+			default:
+			}
+
+		case <-didProcessCh:
+			// NOTE: It is a subtle mistake to process more than a single block
+			// at a time (e.g. 10) here, because we only TrySend 1 request per
+			// loop.  The ratio mismatch can result in starving of blocks, a
+			// sudden burst of requests and responses, and repeat.
+			// Consequently, it is better to split these routines rather than
+			// coupling them as it's written here.  TODO uncouple from request
+			// routine.
+
+			// See if there are any blocks to sync.
+			first, second := bcR.pool.PeekTwoBlocks()
+			//bcR.Logger.Info("TrySync peeked", "first", first, "second", second)
+			if first == nil || second == nil {
+				// We need both to sync the first block.
+				continue FOR_LOOP
+			} else {
+				// Try again quickly next loop.
+				didProcessCh <- struct{}{}
+			}
+
+			firstParts := first.MakePartSet(state.ConsensusParams.BlockPartSizeBytes)
+			firstPartsHeader := firstParts.Header()
+			firstID := types.BlockID{first.Hash(), firstPartsHeader}
+			// Finally, verify the first block using the second's commit
+			// NOTE: we can probably make this more efficient, but note that calling
+			// first.Hash() doesn't verify the tx contents, so MakePartSet() is
+			// currently necessary.
+			err := state.Validators.VerifyCommit(
+				chainID, firstID, first.Height, second.LastCommit)
+			if err != nil {
+				bcR.Logger.Error("Error in validation", "err", err)
+				peerID := bcR.pool.RedoRequest(first.Height)
+				peer := bcR.Switch.Peers().Get(peerID)
+				if peer != nil {
+					// NOTE: we've already removed the peer's request, but we
+					// still need to clean up the rest.
+					bcR.Switch.StopPeerForError(peer, fmt.Errorf("BlockchainReactor validation error: %v", err))
 				}
-				firstParts := first.MakePartSet(state.ConsensusParams.BlockPartSizeBytes)
-				firstPartsHeader := firstParts.Header()
-				firstID := types.BlockID{first.Hash(), firstPartsHeader}
-				// Finally, verify the first block using the second's commit
-				// NOTE: we can probably make this more efficient, but note that calling
-				// first.Hash() doesn't verify the tx contents, so MakePartSet() is
-				// currently necessary.
-				err := state.Validators.VerifyCommit(
-					chainID, firstID, first.Height, second.LastCommit)
+				continue FOR_LOOP
+			} else {
+				bcR.pool.PopRequest()
+
+				// TODO: batch saves so we dont persist to disk every block
+				bcR.store.SaveBlock(first, firstParts, second.LastCommit)
+
+				// TODO: same thing for app - but we would need a way to
+				// get the hash without persisting the state
+				var err error
+				state, err = bcR.blockExec.ApplyBlock(state, firstID, first)
 				if err != nil {
-					bcR.Logger.Error("Error in validation", "err", err)
-					peerID := bcR.pool.RedoRequest(first.Height)
-					peer := bcR.Switch.Peers().Get(peerID)
-					if peer != nil {
-						bcR.Switch.StopPeerForError(peer, fmt.Errorf("BlockchainReactor validation error: %v", err))
-					}
-					break SYNC_LOOP
-				} else {
-					bcR.pool.PopRequest()
-
-					// TODO: batch saves so we dont persist to disk every block
-					bcR.store.SaveBlock(first, firstParts, second.LastCommit)
-
-					// TODO: same thing for app - but we would need a way to
-					// get the hash without persisting the state
-					var err error
-					state, err = bcR.blockExec.ApplyBlock(state, firstID, first)
-					if err != nil {
-						// TODO This is bad, are we zombie?
-						cmn.PanicQ(cmn.Fmt("Failed to process committed block (%d:%X): %v",
-							first.Height, first.Hash(), err))
-					}
-					blocksSynced++
-
-					if blocksSynced%100 == 0 {
-						lastRate = 0.9*lastRate + 0.1*(100/time.Since(lastHundred).Seconds())
-						bcR.Logger.Info("Fast Sync Rate", "height", bcR.pool.height,
-							"max_peer_height", bcR.pool.MaxPeerHeight(), "blocks/s", lastRate)
-						lastHundred = time.Now()
-					}
+					// TODO This is bad, are we zombie?
+					cmn.PanicQ(cmn.Fmt("Failed to process committed block (%d:%X): %v",
+						first.Height, first.Hash(), err))
+				}
+				blocksSynced++
+
+				if blocksSynced%100 == 0 {
+					lastRate = 0.9*lastRate + 0.1*(100/time.Since(lastHundred).Seconds())
+					bcR.Logger.Info("Fast Sync Rate", "height", bcR.pool.height,
+						"max_peer_height", bcR.pool.MaxPeerHeight(), "blocks/s", lastRate)
+					lastHundred = time.Now()
 				}
 			}
 			continue FOR_LOOP
+
 		case <-bcR.Quit():
 			break FOR_LOOP
 		}
diff --git a/vendor/github.com/tendermint/tendermint/consensus/reactor.go b/vendor/github.com/tendermint/tendermint/consensus/reactor.go
index 3eb1d73aa639e4393e2fc1b730740a8669682c48..58ff42ae2b75928c1f580b0798d8d3229371e52a 100644
--- a/vendor/github.com/tendermint/tendermint/consensus/reactor.go
+++ b/vendor/github.com/tendermint/tendermint/consensus/reactor.go
@@ -58,9 +58,6 @@ func NewConsensusReactor(consensusState *ConsensusState, fastSync bool) *Consens
 // broadcasted to other peers and starting state if we're not in fast sync.
 func (conR *ConsensusReactor) OnStart() error {
 	conR.Logger.Info("ConsensusReactor ", "fastSync", conR.FastSync())
-	if err := conR.BaseReactor.OnStart(); err != nil {
-		return err
-	}
 
 	conR.subscribeToBroadcastEvents()
 
@@ -77,7 +74,6 @@ func (conR *ConsensusReactor) OnStart() error {
 // OnStop implements BaseService by unsubscribing from events and stopping
 // state.
 func (conR *ConsensusReactor) OnStop() {
-	conR.BaseReactor.OnStop()
 	conR.unsubscribeFromBroadcastEvents()
 	conR.conS.Stop()
 	if !conR.FastSync() {
diff --git a/vendor/github.com/tendermint/tendermint/consensus/replay.go b/vendor/github.com/tendermint/tendermint/consensus/replay.go
index dd940998fabdf4753c637650e52e5187f7ee5702..bb1f2e46db9f6c4d33103d4c1bbe1c13a76009e8 100644
--- a/vendor/github.com/tendermint/tendermint/consensus/replay.go
+++ b/vendor/github.com/tendermint/tendermint/consensus/replay.go
@@ -227,7 +227,7 @@ func (h *Handshaker) NBlocks() int {
 func (h *Handshaker) Handshake(proxyApp proxy.AppConns) error {
 
 	// Handshake is done via ABCI Info on the query conn.
-	res, err := proxyApp.Query().InfoSync(abci.RequestInfo{version.Version})
+	res, err := proxyApp.Query().InfoSync(abci.RequestInfo{Version: version.Version})
 	if err != nil {
 		return fmt.Errorf("Error calling Info: %v", err)
 	}
@@ -269,7 +269,7 @@ func (h *Handshaker) ReplayBlocks(state sm.State, appHash []byte, appBlockHeight
 		validators := types.TM2PB.Validators(state.Validators)
 		csParams := types.TM2PB.ConsensusParams(h.genDoc.ConsensusParams)
 		req := abci.RequestInitChain{
-			Time:            h.genDoc.GenesisTime.Unix(), // TODO
+			Time:            h.genDoc.GenesisTime,
 			ChainId:         h.genDoc.ChainID,
 			ConsensusParams: csParams,
 			Validators:      validators,
diff --git a/vendor/github.com/tendermint/tendermint/consensus/state.go b/vendor/github.com/tendermint/tendermint/consensus/state.go
index f66a872eb641133a4a922dc0da56b07a184162a1..6ffe6ef643196e6bac6a49fa24eeb8acbf2f07b4 100644
--- a/vendor/github.com/tendermint/tendermint/consensus/state.go
+++ b/vendor/github.com/tendermint/tendermint/consensus/state.go
@@ -553,9 +553,30 @@ func (cs *ConsensusState) newStep() {
 // Updates (state transitions) happen on timeouts, complete proposals, and 2/3 majorities.
 // ConsensusState must be locked before any internal state is updated.
 func (cs *ConsensusState) receiveRoutine(maxSteps int) {
+	onExit := func(cs *ConsensusState) {
+		// NOTE: the internalMsgQueue may have signed messages from our
+		// priv_val that haven't hit the WAL, but its ok because
+		// priv_val tracks LastSig
+
+		// close wal now that we're done writing to it
+		cs.wal.Stop()
+		cs.wal.Wait()
+
+		close(cs.done)
+	}
+
 	defer func() {
 		if r := recover(); r != nil {
 			cs.Logger.Error("CONSENSUS FAILURE!!!", "err", r, "stack", string(debug.Stack()))
+			// stop gracefully
+			//
+			// NOTE: We most probably shouldn't be running any further when there is
+			// some unexpected panic. Some unknown error happened, and so we don't
+			// know if that will result in the validator signing an invalid thing. It
+			// might be worthwhile to explore a mechanism for manual resuming via
+			// some console or secure RPC system, but for now, halting the chain upon
+			// unexpected consensus bugs sounds like the better option.
+			onExit(cs)
 		}
 	}()
 
@@ -588,16 +609,7 @@ func (cs *ConsensusState) receiveRoutine(maxSteps int) {
 			// go to the next step
 			cs.handleTimeout(ti, rs)
 		case <-cs.Quit():
-
-			// NOTE: the internalMsgQueue may have signed messages from our
-			// priv_val that haven't hit the WAL, but its ok because
-			// priv_val tracks LastSig
-
-			// close wal now that we're done writing to it
-			cs.wal.Stop()
-			cs.wal.Wait()
-
-			close(cs.done)
+			onExit(cs)
 			return
 		}
 	}
diff --git a/vendor/github.com/tendermint/tendermint/crypto/README.md b/vendor/github.com/tendermint/tendermint/crypto/README.md
index 5fac67338cb4caca65d610256d8c6e9376ec5b9a..bb663122733c118fd515d614464acc3c6a97c769 100644
--- a/vendor/github.com/tendermint/tendermint/crypto/README.md
+++ b/vendor/github.com/tendermint/tendermint/crypto/README.md
@@ -24,9 +24,7 @@ crypto `.Bytes()` uses Amino:binary encoding, but Amino:JSON is also supported.
 Example Amino:JSON encodings:
 
 ed25519.PrivKeyEd25519     - {"type":"954568A3288910","value":"EVkqJO/jIXp3rkASXfh9YnyToYXRXhBr6g9cQVxPFnQBP/5povV4HTjvsy530kybxKHwEi85iU8YL0qQhSYVoQ=="}
-crypto.SignatureEd25519   - {"type":"6BF5903DA1DB28","value":"77sQNZOrf7ltExpf7AV1WaYPCHbyRLgjBsoWVzcduuLk+jIGmYk+s5R6Emm29p12HeiNAuhUJgdFGmwkpeGJCA=="}
 ed25519.PubKeyEd25519      - {"type":"AC26791624DE60","value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE="}
 crypto.PrivKeySecp256k1   - {"type":"019E82E1B0F798","value":"zx4Pnh67N+g2V+5vZbQzEyRerX9c4ccNZOVzM9RvJ0Y="}
-crypto.SignatureSecp256k1 - {"type":"6D1EA416E1FEE8","value":"MEUCIQCIg5TqS1l7I+MKTrSPIuUN2+4m5tA29dcauqn3NhEJ2wIgICaZ+lgRc5aOTVahU/XoLopXKn8BZcl0bnuYWLvohR8="}
 crypto.PubKeySecp256k1    - {"type":"F8CCEAEB5AE980","value":"A8lPKJXcNl5VHt1FK8a244K9EJuS4WX1hFBnwisi0IJx"}
 ```
diff --git a/vendor/github.com/tendermint/tendermint/crypto/crypto.go b/vendor/github.com/tendermint/tendermint/crypto/crypto.go
index 4c097b3517934c445d958c15fb19c071ef61b322..09c12ff7660b672af338cceac6222305b5a5bf9d 100644
--- a/vendor/github.com/tendermint/tendermint/crypto/crypto.go
+++ b/vendor/github.com/tendermint/tendermint/crypto/crypto.go
@@ -6,7 +6,7 @@ import (
 
 type PrivKey interface {
 	Bytes() []byte
-	Sign(msg []byte) (Signature, error)
+	Sign(msg []byte) ([]byte, error)
 	PubKey() PubKey
 	Equals(PrivKey) bool
 }
@@ -19,16 +19,10 @@ type Address = cmn.HexBytes
 type PubKey interface {
 	Address() Address
 	Bytes() []byte
-	VerifyBytes(msg []byte, sig Signature) bool
+	VerifyBytes(msg []byte, sig []byte) bool
 	Equals(PubKey) bool
 }
 
-type Signature interface {
-	Bytes() []byte
-	IsZero() bool
-	Equals(Signature) bool
-}
-
 type Symmetric interface {
 	Keygen() []byte
 	Encrypt(plaintext []byte, secret []byte) (ciphertext []byte)
diff --git a/vendor/github.com/tendermint/tendermint/crypto/ed25519/ed25519.go b/vendor/github.com/tendermint/tendermint/crypto/ed25519/ed25519.go
index 8b7bd42bd955c15118dc672705453981bd970878..fa7526f3fcf716d8ab185a1279e1ef6f9a2c74fe 100644
--- a/vendor/github.com/tendermint/tendermint/crypto/ed25519/ed25519.go
+++ b/vendor/github.com/tendermint/tendermint/crypto/ed25519/ed25519.go
@@ -4,13 +4,13 @@ import (
 	"bytes"
 	"crypto/subtle"
 	"fmt"
+	"io"
 
 	"github.com/tendermint/ed25519"
 	"github.com/tendermint/ed25519/extra25519"
 	amino "github.com/tendermint/go-amino"
 	"github.com/tendermint/tendermint/crypto"
 	"github.com/tendermint/tendermint/crypto/tmhash"
-	cmn "github.com/tendermint/tendermint/libs/common"
 )
 
 //-------------------------------------
@@ -18,9 +18,11 @@ import (
 var _ crypto.PrivKey = PrivKeyEd25519{}
 
 const (
-	Ed25519PrivKeyAminoRoute   = "tendermint/PrivKeyEd25519"
-	Ed25519PubKeyAminoRoute    = "tendermint/PubKeyEd25519"
-	Ed25519SignatureAminoRoute = "tendermint/SignatureEd25519"
+	Ed25519PrivKeyAminoRoute = "tendermint/PrivKeyEd25519"
+	Ed25519PubKeyAminoRoute  = "tendermint/PubKeyEd25519"
+	// Size of an Edwards25519 signature. Namely the size of a compressed
+	// Edwards25519 point, and a field element. Both of which are 32 bytes.
+	SignatureEd25519Size = 64
 )
 
 var cdc = amino.NewCodec()
@@ -33,10 +35,6 @@ func init() {
 	cdc.RegisterInterface((*crypto.PrivKey)(nil), nil)
 	cdc.RegisterConcrete(PrivKeyEd25519{},
 		Ed25519PrivKeyAminoRoute, nil)
-
-	cdc.RegisterInterface((*crypto.Signature)(nil), nil)
-	cdc.RegisterConcrete(SignatureEd25519{},
-		Ed25519SignatureAminoRoute, nil)
 }
 
 // PrivKeyEd25519 implements crypto.PrivKey.
@@ -48,10 +46,10 @@ func (privKey PrivKeyEd25519) Bytes() []byte {
 }
 
 // Sign produces a signature on the provided message.
-func (privKey PrivKeyEd25519) Sign(msg []byte) (crypto.Signature, error) {
+func (privKey PrivKeyEd25519) Sign(msg []byte) ([]byte, error) {
 	privKeyBytes := [64]byte(privKey)
 	signatureBytes := ed25519.Sign(&privKeyBytes, msg)
-	return SignatureEd25519(*signatureBytes), nil
+	return signatureBytes[:], nil
 }
 
 // PubKey gets the corresponding public key from the private key.
@@ -102,8 +100,16 @@ func (privKey PrivKeyEd25519) ToCurve25519() *[PubKeyEd25519Size]byte {
 // It uses OS randomness in conjunction with the current global random seed
 // in tendermint/libs/common to generate the private key.
 func GenPrivKey() PrivKeyEd25519 {
+	return genPrivKey(crypto.CReader())
+}
+
+// genPrivKey generates a new ed25519 private key using the provided reader.
+func genPrivKey(rand io.Reader) PrivKeyEd25519 {
 	privKey := new([64]byte)
-	copy(privKey[:32], crypto.CRandBytes(32))
+	_, err := io.ReadFull(rand, privKey[:32])
+	if err != nil {
+		panic(err)
+	}
 	// ed25519.MakePublicKey(privKey) alters the last 32 bytes of privKey.
 	// It places the pubkey in the last 32 bytes of privKey, and returns the
 	// public key.
@@ -150,15 +156,15 @@ func (pubKey PubKeyEd25519) Bytes() []byte {
 	return bz
 }
 
-func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ crypto.Signature) bool {
+func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ []byte) bool {
 	// make sure we use the same algorithm to sign
-	sig, ok := sig_.(SignatureEd25519)
-	if !ok {
+	if len(sig_) != SignatureEd25519Size {
 		return false
 	}
+	sig := new([SignatureEd25519Size]byte)
+	copy(sig[:], sig_)
 	pubKeyBytes := [PubKeyEd25519Size]byte(pubKey)
-	sigBytes := [SignatureEd25519Size]byte(sig)
-	return ed25519.Verify(&pubKeyBytes, msg, &sigBytes)
+	return ed25519.Verify(&pubKeyBytes, msg, sig)
 }
 
 // ToCurve25519 takes a public key and returns its representation on
@@ -188,40 +194,3 @@ func (pubKey PubKeyEd25519) Equals(other crypto.PubKey) bool {
 		return false
 	}
 }
-
-//-------------------------------------
-
-var _ crypto.Signature = SignatureEd25519{}
-
-// Size of an Edwards25519 signature. Namely the size of a compressed
-// Edwards25519 point, and a field element. Both of which are 32 bytes.
-const SignatureEd25519Size = 64
-
-// SignatureEd25519 implements crypto.Signature
-type SignatureEd25519 [SignatureEd25519Size]byte
-
-func (sig SignatureEd25519) Bytes() []byte {
-	bz, err := cdc.MarshalBinaryBare(sig)
-	if err != nil {
-		panic(err)
-	}
-	return bz
-}
-
-func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 }
-
-func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", cmn.Fingerprint(sig[:])) }
-
-func (sig SignatureEd25519) Equals(other crypto.Signature) bool {
-	if otherEd, ok := other.(SignatureEd25519); ok {
-		return subtle.ConstantTimeCompare(sig[:], otherEd[:]) == 1
-	} else {
-		return false
-	}
-}
-
-func SignatureEd25519FromBytes(data []byte) crypto.Signature {
-	var sig SignatureEd25519
-	copy(sig[:], data)
-	return sig
-}
diff --git a/vendor/github.com/tendermint/tendermint/crypto/encoding/amino/amino.go b/vendor/github.com/tendermint/tendermint/crypto/encoding/amino/amino.go
index 2b5e15b4fd171591bd77166f537d1ca6e695fe18..fd9a08442e839c2cd675550fdc14b5e0c9385f68 100644
--- a/vendor/github.com/tendermint/tendermint/crypto/encoding/amino/amino.go
+++ b/vendor/github.com/tendermint/tendermint/crypto/encoding/amino/amino.go
@@ -33,12 +33,6 @@ func RegisterAmino(cdc *amino.Codec) {
 		"tendermint/PrivKeyEd25519", nil)
 	cdc.RegisterConcrete(secp256k1.PrivKeySecp256k1{},
 		"tendermint/PrivKeySecp256k1", nil)
-
-	cdc.RegisterInterface((*crypto.Signature)(nil), nil)
-	cdc.RegisterConcrete(ed25519.SignatureEd25519{},
-		"tendermint/SignatureEd25519", nil)
-	cdc.RegisterConcrete(secp256k1.SignatureSecp256k1{},
-		"tendermint/SignatureSecp256k1", nil)
 }
 
 func PrivKeyFromBytes(privKeyBytes []byte) (privKey crypto.PrivKey, err error) {
@@ -50,8 +44,3 @@ func PubKeyFromBytes(pubKeyBytes []byte) (pubKey crypto.PubKey, err error) {
 	err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey)
 	return
 }
-
-func SignatureFromBytes(pubKeyBytes []byte) (pubKey crypto.Signature, err error) {
-	err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey)
-	return
-}
diff --git a/vendor/github.com/tendermint/tendermint/crypto/secp256k1/secp256k1.go b/vendor/github.com/tendermint/tendermint/crypto/secp256k1/secp256k1.go
index 4b210dc7fe9c3889419837bb88570915ed7c5bc5..aee5dafe7a2154258bd7149742ae81bc212995e3 100644
--- a/vendor/github.com/tendermint/tendermint/crypto/secp256k1/secp256k1.go
+++ b/vendor/github.com/tendermint/tendermint/crypto/secp256k1/secp256k1.go
@@ -5,19 +5,18 @@ import (
 	"crypto/sha256"
 	"crypto/subtle"
 	"fmt"
+	"io"
 
 	secp256k1 "github.com/btcsuite/btcd/btcec"
 	amino "github.com/tendermint/go-amino"
 	"github.com/tendermint/tendermint/crypto"
-	"github.com/tendermint/tendermint/libs/common"
 	"golang.org/x/crypto/ripemd160"
 )
 
 //-------------------------------------
 const (
-	Secp256k1PrivKeyAminoRoute   = "tendermint/PrivKeySecp256k1"
-	Secp256k1PubKeyAminoRoute    = "tendermint/PubKeySecp256k1"
-	Secp256k1SignatureAminoRoute = "tendermint/SignatureSecp256k1"
+	Secp256k1PrivKeyAminoRoute = "tendermint/PrivKeySecp256k1"
+	Secp256k1PubKeyAminoRoute  = "tendermint/PubKeySecp256k1"
 )
 
 var cdc = amino.NewCodec()
@@ -30,10 +29,6 @@ func init() {
 	cdc.RegisterInterface((*crypto.PrivKey)(nil), nil)
 	cdc.RegisterConcrete(PrivKeySecp256k1{},
 		Secp256k1PrivKeyAminoRoute, nil)
-
-	cdc.RegisterInterface((*crypto.Signature)(nil), nil)
-	cdc.RegisterConcrete(SignatureSecp256k1{},
-		Secp256k1SignatureAminoRoute, nil)
 }
 
 //-------------------------------------
@@ -49,13 +44,13 @@ func (privKey PrivKeySecp256k1) Bytes() []byte {
 }
 
 // Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg.
-func (privKey PrivKeySecp256k1) Sign(msg []byte) (crypto.Signature, error) {
+func (privKey PrivKeySecp256k1) Sign(msg []byte) ([]byte, error) {
 	priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:])
 	sig, err := priv.Sign(crypto.Sha256(msg))
 	if err != nil {
 		return nil, err
 	}
-	return SignatureSecp256k1(sig.Serialize()), nil
+	return sig.Serialize(), nil
 }
 
 // PubKey performs the point-scalar multiplication from the privKey on the
@@ -80,8 +75,16 @@ func (privKey PrivKeySecp256k1) Equals(other crypto.PrivKey) bool {
 // It uses OS randomness in conjunction with the current global random seed
 // in tendermint/libs/common to generate the private key.
 func GenPrivKey() PrivKeySecp256k1 {
+	return genPrivKey(crypto.CReader())
+}
+
+// genPrivKey generates a new secp256k1 private key using the provided reader.
+func genPrivKey(rand io.Reader) PrivKeySecp256k1 {
 	privKeyBytes := [32]byte{}
-	copy(privKeyBytes[:], crypto.CRandBytes(32))
+	_, err := io.ReadFull(rand, privKeyBytes[:])
+	if err != nil {
+		panic(err)
+	}
 	// crypto.CRandBytes is guaranteed to be 32 bytes long, so it can be
 	// casted to PrivKeySecp256k1.
 	return PrivKeySecp256k1(privKeyBytes)
@@ -133,13 +136,7 @@ func (pubKey PubKeySecp256k1) Bytes() []byte {
 	return bz
 }
 
-func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, interfaceSig crypto.Signature) bool {
-	// and assert same algorithm to sign and verify
-	sig, ok := interfaceSig.(SignatureSecp256k1)
-	if !ok {
-		return false
-	}
-
+func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig []byte) bool {
 	pub, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256())
 	if err != nil {
 		return false
@@ -161,38 +158,3 @@ func (pubKey PubKeySecp256k1) Equals(other crypto.PubKey) bool {
 	}
 	return false
 }
-
-//-------------------------------------
-
-var _ crypto.Signature = SignatureSecp256k1{}
-
-// SignatureSecp256k1 implements crypto.Signature
-type SignatureSecp256k1 []byte
-
-func (sig SignatureSecp256k1) Bytes() []byte {
-	bz, err := cdc.MarshalBinaryBare(sig)
-	if err != nil {
-		panic(err)
-	}
-	return bz
-}
-
-func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 }
-
-func (sig SignatureSecp256k1) String() string {
-	return fmt.Sprintf("/%X.../", common.Fingerprint(sig[:]))
-}
-
-func (sig SignatureSecp256k1) Equals(other crypto.Signature) bool {
-	if otherSecp, ok := other.(SignatureSecp256k1); ok {
-		return subtle.ConstantTimeCompare(sig[:], otherSecp[:]) == 1
-	} else {
-		return false
-	}
-}
-
-func SignatureSecp256k1FromBytes(data []byte) crypto.Signature {
-	sig := make(SignatureSecp256k1, len(data))
-	copy(sig[:], data)
-	return sig
-}
diff --git a/vendor/github.com/tendermint/tendermint/evidence/reactor.go b/vendor/github.com/tendermint/tendermint/evidence/reactor.go
index bf11ac105572f0174e7d1a9da4d51f455acfda93..cfe47364c03a0aed82ce918fbcbbd086715ad2bf 100644
--- a/vendor/github.com/tendermint/tendermint/evidence/reactor.go
+++ b/vendor/github.com/tendermint/tendermint/evidence/reactor.go
@@ -44,11 +44,6 @@ func (evR *EvidenceReactor) SetLogger(l log.Logger) {
 	evR.evpool.SetLogger(l)
 }
 
-// OnStart implements cmn.Service
-func (evR *EvidenceReactor) OnStart() error {
-	return evR.BaseReactor.OnStart()
-}
-
 // GetChannels implements Reactor.
 // It returns the list of channels for this reactor.
 func (evR *EvidenceReactor) GetChannels() []*p2p.ChannelDescriptor {
diff --git a/vendor/github.com/tendermint/tendermint/libs/autofile/autofile.go b/vendor/github.com/tendermint/tendermint/libs/autofile/autofile.go
index 313da67890d826b785ff30c6c94847818f2fc32d..2f1bb4fd527a7aba72b82f5b8c18ddb8364f3a7d 100644
--- a/vendor/github.com/tendermint/tendermint/libs/autofile/autofile.go
+++ b/vendor/github.com/tendermint/tendermint/libs/autofile/autofile.go
@@ -35,18 +35,20 @@ const autoFileOpenDuration = 1000 * time.Millisecond
 // Automatically closes and re-opens file for writing.
 // This is useful for using a log file with the logrotate tool.
 type AutoFile struct {
-	ID     string
-	Path   string
-	ticker *time.Ticker
-	mtx    sync.Mutex
-	file   *os.File
+	ID            string
+	Path          string
+	ticker        *time.Ticker
+	tickerStopped chan struct{} // closed when ticker is stopped
+	mtx           sync.Mutex
+	file          *os.File
 }
 
 func OpenAutoFile(path string) (af *AutoFile, err error) {
 	af = &AutoFile{
-		ID:     cmn.RandStr(12) + ":" + path,
-		Path:   path,
-		ticker: time.NewTicker(autoFileOpenDuration),
+		ID:            cmn.RandStr(12) + ":" + path,
+		Path:          path,
+		ticker:        time.NewTicker(autoFileOpenDuration),
+		tickerStopped: make(chan struct{}),
 	}
 	if err = af.openFile(); err != nil {
 		return
@@ -58,18 +60,18 @@ func OpenAutoFile(path string) (af *AutoFile, err error) {
 
 func (af *AutoFile) Close() error {
 	af.ticker.Stop()
+	close(af.tickerStopped)
 	err := af.closeFile()
 	sighupWatchers.removeAutoFile(af)
 	return err
 }
 
 func (af *AutoFile) processTicks() {
-	for {
-		_, ok := <-af.ticker.C
-		if !ok {
-			return // Done.
-		}
+	select {
+	case <-af.ticker.C:
 		af.closeFile()
+	case <-af.tickerStopped:
+		return
 	}
 }
 
diff --git a/vendor/github.com/tendermint/tendermint/libs/autofile/group.go b/vendor/github.com/tendermint/tendermint/libs/autofile/group.go
index b4368ed9e0acafb3612bdd618dbdc5c8d5defc05..e747f04dd9ead3aec643e2d87fa7ec1f528c9bab 100644
--- a/vendor/github.com/tendermint/tendermint/libs/autofile/group.go
+++ b/vendor/github.com/tendermint/tendermint/libs/autofile/group.go
@@ -85,7 +85,6 @@ func OpenGroup(headPath string) (g *Group, err error) {
 		Head:           head,
 		headBuf:        bufio.NewWriterSize(head, 4096*10),
 		Dir:            dir,
-		ticker:         time.NewTicker(groupCheckDuration),
 		headSizeLimit:  defaultHeadSizeLimit,
 		totalSizeLimit: defaultTotalSizeLimit,
 		minIndex:       0,
@@ -102,6 +101,7 @@ func OpenGroup(headPath string) (g *Group, err error) {
 // OnStart implements Service by starting the goroutine that checks file and
 // group limits.
 func (g *Group) OnStart() error {
+	g.ticker = time.NewTicker(groupCheckDuration)
 	go g.processTicks()
 	return nil
 }
@@ -199,21 +199,15 @@ func (g *Group) Flush() error {
 }
 
 func (g *Group) processTicks() {
-	for {
-		_, ok := <-g.ticker.C
-		if !ok {
-			return // Done.
-		}
+	select {
+	case <-g.ticker.C:
 		g.checkHeadSizeLimit()
 		g.checkTotalSizeLimit()
+	case <-g.Quit():
+		return
 	}
 }
 
-// NOTE: for testing
-func (g *Group) stopTicker() {
-	g.ticker.Stop()
-}
-
 // NOTE: this function is called manually in tests.
 func (g *Group) checkHeadSizeLimit() {
 	limit := g.HeadSizeLimit()
diff --git a/vendor/github.com/tendermint/tendermint/libs/autofile/sighup_watcher.go b/vendor/github.com/tendermint/tendermint/libs/autofile/sighup_watcher.go
index 56fbd4d8693aae702a355049c9c55032fe1af470..f72f12fcdd17768a0dfa1a2c937c3b2a93e2a82a 100644
--- a/vendor/github.com/tendermint/tendermint/libs/autofile/sighup_watcher.go
+++ b/vendor/github.com/tendermint/tendermint/libs/autofile/sighup_watcher.go
@@ -18,13 +18,19 @@ var sighupCounter int32 // For testing
 func initSighupWatcher() {
 	sighupWatchers = newSighupWatcher()
 
-	c := make(chan os.Signal, 1)
-	signal.Notify(c, syscall.SIGHUP)
+	hup := make(chan os.Signal, 1)
+	signal.Notify(hup, syscall.SIGHUP)
+
+	quit := make(chan os.Signal, 1)
+	signal.Notify(quit, os.Interrupt, syscall.SIGTERM)
 
 	go func() {
-		for range c {
+		select {
+		case <-hup:
 			sighupWatchers.closeAll()
 			atomic.AddInt32(&sighupCounter, 1)
+		case <-quit:
+			return
 		}
 	}()
 }
diff --git a/vendor/github.com/tendermint/tendermint/libs/common/bit_array.go b/vendor/github.com/tendermint/tendermint/libs/common/bit_array.go
index 0290921a6c178b9d0d174b934b76b70ece394e35..abf6110d80d810dac6ba120a094265ea7ddc9e38 100644
--- a/vendor/github.com/tendermint/tendermint/libs/common/bit_array.go
+++ b/vendor/github.com/tendermint/tendermint/libs/common/bit_array.go
@@ -8,13 +8,15 @@ import (
 	"sync"
 )
 
+// BitArray is a thread-safe implementation of a bit array.
 type BitArray struct {
 	mtx   sync.Mutex
 	Bits  int      `json:"bits"`  // NOTE: persisted via reflect, must be exported
 	Elems []uint64 `json:"elems"` // NOTE: persisted via reflect, must be exported
 }
 
-// There is no BitArray whose Size is 0.  Use nil instead.
+// NewBitArray returns a new bit array.
+// It returns nil if the number of bits is zero.
 func NewBitArray(bits int) *BitArray {
 	if bits <= 0 {
 		return nil
@@ -25,6 +27,7 @@ func NewBitArray(bits int) *BitArray {
 	}
 }
 
+// Size returns the number of bits in the bitarray
 func (bA *BitArray) Size() int {
 	if bA == nil {
 		return 0
@@ -32,7 +35,8 @@ func (bA *BitArray) Size() int {
 	return bA.Bits
 }
 
-// NOTE: behavior is undefined if i >= bA.Bits
+// GetIndex returns the bit at index i within the bit array.
+// The behavior is undefined if i >= bA.Bits
 func (bA *BitArray) GetIndex(i int) bool {
 	if bA == nil {
 		return false
@@ -49,7 +53,8 @@ func (bA *BitArray) getIndex(i int) bool {
 	return bA.Elems[i/64]&(uint64(1)<<uint(i%64)) > 0
 }
 
-// NOTE: behavior is undefined if i >= bA.Bits
+// SetIndex sets the bit at index i within the bit array.
+// The behavior is undefined if i >= bA.Bits
 func (bA *BitArray) SetIndex(i int, v bool) bool {
 	if bA == nil {
 		return false
@@ -71,6 +76,7 @@ func (bA *BitArray) setIndex(i int, v bool) bool {
 	return true
 }
 
+// Copy returns a copy of the provided bit array.
 func (bA *BitArray) Copy() *BitArray {
 	if bA == nil {
 		return nil
@@ -98,7 +104,9 @@ func (bA *BitArray) copyBits(bits int) *BitArray {
 	}
 }
 
-// Returns a BitArray of larger bits size.
+// Or returns a bit array resulting from a bitwise OR of the two bit arrays.
+// If the two bit-arrys have different lengths, Or right-pads the smaller of the two bit-arrays with zeroes.
+// Thus the size of the return value is the maximum of the two provided bit arrays.
 func (bA *BitArray) Or(o *BitArray) *BitArray {
 	if bA == nil && o == nil {
 		return nil
@@ -110,7 +118,11 @@ func (bA *BitArray) Or(o *BitArray) *BitArray {
 		return bA.Copy()
 	}
 	bA.mtx.Lock()
-	defer bA.mtx.Unlock()
+	o.mtx.Lock()
+	defer func() {
+		bA.mtx.Unlock()
+		o.mtx.Unlock()
+	}()
 	c := bA.copyBits(MaxInt(bA.Bits, o.Bits))
 	for i := 0; i < len(c.Elems); i++ {
 		c.Elems[i] |= o.Elems[i]
@@ -118,13 +130,19 @@ func (bA *BitArray) Or(o *BitArray) *BitArray {
 	return c
 }
 
-// Returns a BitArray of smaller bit size.
+// And returns a bit array resulting from a bitwise AND of the two bit arrays.
+// If the two bit-arrys have different lengths, this truncates the larger of the two bit-arrays from the right.
+// Thus the size of the return value is the minimum of the two provided bit arrays.
 func (bA *BitArray) And(o *BitArray) *BitArray {
 	if bA == nil || o == nil {
 		return nil
 	}
 	bA.mtx.Lock()
-	defer bA.mtx.Unlock()
+	o.mtx.Lock()
+	defer func() {
+		bA.mtx.Unlock()
+		o.mtx.Unlock()
+	}()
 	return bA.and(o)
 }
 
@@ -136,12 +154,17 @@ func (bA *BitArray) and(o *BitArray) *BitArray {
 	return c
 }
 
+// Not returns a bit array resulting from a bitwise Not of the provided bit array.
 func (bA *BitArray) Not() *BitArray {
 	if bA == nil {
 		return nil // Degenerate
 	}
 	bA.mtx.Lock()
 	defer bA.mtx.Unlock()
+	return bA.not()
+}
+
+func (bA *BitArray) not() *BitArray {
 	c := bA.copy()
 	for i := 0; i < len(c.Elems); i++ {
 		c.Elems[i] = ^c.Elems[i]
@@ -149,13 +172,20 @@ func (bA *BitArray) Not() *BitArray {
 	return c
 }
 
+// Sub subtracts the two bit-arrays bitwise, without carrying the bits.
+// This is essentially bA.And(o.Not()).
+// If bA is longer than o, o is right padded with zeroes.
 func (bA *BitArray) Sub(o *BitArray) *BitArray {
 	if bA == nil || o == nil {
 		// TODO: Decide if we should do 1's complement here?
 		return nil
 	}
 	bA.mtx.Lock()
-	defer bA.mtx.Unlock()
+	o.mtx.Lock()
+	defer func() {
+		bA.mtx.Unlock()
+		o.mtx.Unlock()
+	}()
 	if bA.Bits > o.Bits {
 		c := bA.copy()
 		for i := 0; i < len(o.Elems)-1; i++ {
@@ -164,15 +194,15 @@ func (bA *BitArray) Sub(o *BitArray) *BitArray {
 		i := len(o.Elems) - 1
 		if i >= 0 {
 			for idx := i * 64; idx < o.Bits; idx++ {
-				// NOTE: each individual GetIndex() call to o is safe.
-				c.setIndex(idx, c.getIndex(idx) && !o.GetIndex(idx))
+				c.setIndex(idx, c.getIndex(idx) && !o.getIndex(idx))
 			}
 		}
 		return c
 	}
-	return bA.and(o.Not()) // Note degenerate case where o == nil
+	return bA.and(o.not()) // Note degenerate case where o == nil
 }
 
+// IsEmpty returns true iff all bits in the bit array are 0
 func (bA *BitArray) IsEmpty() bool {
 	if bA == nil {
 		return true // should this be opposite?
@@ -187,6 +217,7 @@ func (bA *BitArray) IsEmpty() bool {
 	return true
 }
 
+// IsFull returns true iff all bits in the bit array are 1.
 func (bA *BitArray) IsFull() bool {
 	if bA == nil {
 		return true
@@ -207,6 +238,8 @@ func (bA *BitArray) IsFull() bool {
 	return (lastElem+1)&((uint64(1)<<uint(lastElemBits))-1) == 0
 }
 
+// PickRandom returns a random index in the bit array, and its value.
+// It uses the global randomness in `random.go` to get this index.
 func (bA *BitArray) PickRandom() (int, bool) {
 	if bA == nil {
 		return 0, false
@@ -260,6 +293,8 @@ func (bA *BitArray) String() string {
 	return bA.StringIndented("")
 }
 
+// StringIndented returns the same thing as String(), but applies the indent
+// at every 10th bit, and twice at every 50th bit.
 func (bA *BitArray) StringIndented(indent string) string {
 	if bA == nil {
 		return "nil-BitArray"
@@ -295,6 +330,7 @@ func (bA *BitArray) stringIndented(indent string) string {
 	return fmt.Sprintf("BA{%v:%v}", bA.Bits, strings.Join(lines, indent))
 }
 
+// Bytes returns the byte representation of the bits within the bitarray.
 func (bA *BitArray) Bytes() []byte {
 	bA.mtx.Lock()
 	defer bA.mtx.Unlock()
@@ -309,15 +345,18 @@ func (bA *BitArray) Bytes() []byte {
 	return bytes
 }
 
-// NOTE: other bitarray o is not locked when reading,
-// so if necessary, caller must copy or lock o prior to calling Update.
-// If bA is nil, does nothing.
+// Update sets the bA's bits to be that of the other bit array.
+// The copying begins from the begin of both bit arrays.
 func (bA *BitArray) Update(o *BitArray) {
 	if bA == nil || o == nil {
 		return
 	}
 	bA.mtx.Lock()
-	defer bA.mtx.Unlock()
+	o.mtx.Lock()
+	defer func() {
+		bA.mtx.Unlock()
+		o.mtx.Unlock()
+	}()
 
 	copy(bA.Elems, o.Elems)
 }
diff --git a/vendor/github.com/tendermint/tendermint/libs/common/os.go b/vendor/github.com/tendermint/tendermint/libs/common/os.go
index 00f4da57b0dd81e759520af9179a4d7b7d89f552..b8419764e9f82eef958fc99d903afeea8ecd68a9 100644
--- a/vendor/github.com/tendermint/tendermint/libs/common/os.go
+++ b/vendor/github.com/tendermint/tendermint/libs/common/os.go
@@ -8,7 +8,6 @@ import (
 	"os"
 	"os/exec"
 	"os/signal"
-	"path/filepath"
 	"strings"
 	"syscall"
 )
@@ -124,60 +123,6 @@ func MustWriteFile(filePath string, contents []byte, mode os.FileMode) {
 	}
 }
 
-// WriteFileAtomic creates a temporary file with data and the perm given and
-// swaps it atomically with filename if successful.
-func WriteFileAtomic(filename string, data []byte, perm os.FileMode) error {
-	var (
-		dir      = filepath.Dir(filename)
-		tempFile = filepath.Join(dir, "write-file-atomic-"+RandStr(32))
-		// Override in case it does exist, create in case it doesn't and force kernel
-		// flush, which still leaves the potential of lingering disk cache.
-		flag = os.O_WRONLY | os.O_CREATE | os.O_SYNC | os.O_TRUNC
-	)
-
-	f, err := os.OpenFile(tempFile, flag, perm)
-	if err != nil {
-		return err
-	}
-	// Clean up in any case. Defer stacking order is last-in-first-out.
-	defer os.Remove(f.Name())
-	defer f.Close()
-
-	if n, err := f.Write(data); err != nil {
-		return err
-	} else if n < len(data) {
-		return io.ErrShortWrite
-	}
-	// Close the file before renaming it, otherwise it will cause "The process 
-	// cannot access the file because it is being used by another process." on windows.
-	f.Close()
-
-	return os.Rename(f.Name(), filename)
-}
-
-//--------------------------------------------------------------------------------
-
-func Tempfile(prefix string) (*os.File, string) {
-	file, err := ioutil.TempFile("", prefix)
-	if err != nil {
-		PanicCrisis(err)
-	}
-	return file, file.Name()
-}
-
-func Tempdir(prefix string) (*os.File, string) {
-	tempDir := os.TempDir() + "/" + prefix + RandStr(12)
-	err := EnsureDir(tempDir, 0700)
-	if err != nil {
-		panic(Fmt("Error creating temp dir: %v", err))
-	}
-	dir, err := os.Open(tempDir)
-	if err != nil {
-		panic(Fmt("Error opening temp dir: %v", err))
-	}
-	return dir, tempDir
-}
-
 //--------------------------------------------------------------------------------
 
 func Prompt(prompt string, defaultValue string) (string, error) {
diff --git a/vendor/github.com/tendermint/tendermint/libs/common/random.go b/vendor/github.com/tendermint/tendermint/libs/common/random.go
index 51bfd15c48cda7b635c99c0fef77949daf1ace39..4b0594d0e58daf5a9d9edb4e859c4d5911596cd6 100644
--- a/vendor/github.com/tendermint/tendermint/libs/common/random.go
+++ b/vendor/github.com/tendermint/tendermint/libs/common/random.go
@@ -109,6 +109,10 @@ func RandInt63n(n int64) int64 {
 	return grand.Int63n(n)
 }
 
+func RandBool() bool {
+	return grand.Bool()
+}
+
 func RandFloat32() float32 {
 	return grand.Float32()
 }
@@ -274,6 +278,13 @@ func (r *Rand) Intn(n int) int {
 	return i
 }
 
+// Bool returns a uniformly random boolean
+func (r *Rand) Bool() bool {
+	// See https://github.com/golang/go/issues/23804#issuecomment-365370418
+	// for reasoning behind computing like this
+	return r.Int63()%2 == 0
+}
+
 // Perm returns a pseudo-random permutation of n integers in [0, n).
 func (r *Rand) Perm(n int) []int {
 	r.Lock()
diff --git a/vendor/github.com/tendermint/tendermint/libs/common/tempfile.go b/vendor/github.com/tendermint/tendermint/libs/common/tempfile.go
new file mode 100644
index 0000000000000000000000000000000000000000..a5bb7a5b56cae478bb45ccfafd212afcb3f8f7f0
--- /dev/null
+++ b/vendor/github.com/tendermint/tendermint/libs/common/tempfile.go
@@ -0,0 +1,128 @@
+package common
+
+import (
+	fmt "fmt"
+	"io"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+)
+
+const (
+	atomicWriteFilePrefix = "write-file-atomic-"
+	// Maximum number of atomic write file conflicts before we start reseeding
+	// (reduced from golang's default 10 due to using an increased randomness space)
+	atomicWriteFileMaxNumConflicts = 5
+	// Maximum number of attempts to make at writing the write file before giving up
+	// (reduced from golang's default 10000 due to using an increased randomness space)
+	atomicWriteFileMaxNumWriteAttempts = 1000
+	// LCG constants from Donald Knuth MMIX
+	// This LCG's has a period equal to 2**64
+	lcgA = 6364136223846793005
+	lcgC = 1442695040888963407
+	// Create in case it doesn't exist and force kernel
+	// flush, which still leaves the potential of lingering disk cache.
+	// Never overwrites files
+	atomicWriteFileFlag = os.O_WRONLY | os.O_CREATE | os.O_SYNC | os.O_TRUNC | os.O_EXCL
+)
+
+var (
+	atomicWriteFileRand   uint64
+	atomicWriteFileRandMu sync.Mutex
+)
+
+func writeFileRandReseed() uint64 {
+	// Scale the PID, to minimize the chance that two processes seeded at similar times
+	// don't get the same seed. Note that PID typically ranges in [0, 2**15), but can be
+	// up to 2**22 under certain configurations. We left bit-shift the PID by 20, so that
+	// a PID difference of one corresponds to a time difference of 2048 seconds.
+	// The important thing here is that now for a seed conflict, they would both have to be on
+	// the correct nanosecond offset, and second-based offset, which is much less likely than
+	// just a conflict with the correct nanosecond offset.
+	return uint64(time.Now().UnixNano() + int64(os.Getpid()<<20))
+}
+
+// Use a fast thread safe LCG for atomic write file names.
+// Returns a string corresponding to a 64 bit int.
+// If it was a negative int, the leading number is a 0.
+func randWriteFileSuffix() string {
+	atomicWriteFileRandMu.Lock()
+	r := atomicWriteFileRand
+	if r == 0 {
+		r = writeFileRandReseed()
+	}
+
+	// Update randomness according to lcg
+	r = r*lcgA + lcgC
+
+	atomicWriteFileRand = r
+	atomicWriteFileRandMu.Unlock()
+	// Can have a negative name, replace this in the following
+	suffix := strconv.Itoa(int(r))
+	if string(suffix[0]) == "-" {
+		// Replace first "-" with "0". This is purely for UI clarity,
+		// as otherwhise there would be two `-` in a row.
+		suffix = strings.Replace(suffix, "-", "0", 1)
+	}
+	return suffix
+}
+
+// WriteFileAtomic creates a temporary file with data and provided perm and
+// swaps it atomically with filename if successful.
+func WriteFileAtomic(filename string, data []byte, perm os.FileMode) (err error) {
+	// This implementation is inspired by the golang stdlibs method of creating
+	// tempfiles. Notable differences are that we use different flags, a 64 bit LCG
+	// and handle negatives differently.
+	// The core reason we can't use golang's TempFile is that we must write
+	// to the file synchronously, as we need this to persist to disk.
+	// We also open it in write-only mode, to avoid concerns that arise with read.
+	var (
+		dir = filepath.Dir(filename)
+		f   *os.File
+	)
+
+	nconflict := 0
+	// Limit the number of attempts to create a file. Something is seriously
+	// wrong if it didn't get created after 1000 attempts, and we don't want
+	// an infinite loop
+	i := 0
+	for ; i < atomicWriteFileMaxNumWriteAttempts; i++ {
+		name := filepath.Join(dir, atomicWriteFilePrefix+randWriteFileSuffix())
+		f, err = os.OpenFile(name, atomicWriteFileFlag, perm)
+		// If the file already exists, try a new file
+		if os.IsExist(err) {
+			// If the files exists too many times, start reseeding as we've
+			// likely hit another instances seed.
+			if nconflict++; nconflict > atomicWriteFileMaxNumConflicts {
+				atomicWriteFileRandMu.Lock()
+				atomicWriteFileRand = writeFileRandReseed()
+				atomicWriteFileRandMu.Unlock()
+			}
+			continue
+		} else if err != nil {
+			return err
+		}
+		break
+	}
+	if i == atomicWriteFileMaxNumWriteAttempts {
+		return fmt.Errorf("Could not create atomic write file after %d attempts", i)
+	}
+
+	// Clean up in any case. Defer stacking order is last-in-first-out.
+	defer os.Remove(f.Name())
+	defer f.Close()
+
+	if n, err := f.Write(data); err != nil {
+		return err
+	} else if n < len(data) {
+		return io.ErrShortWrite
+	}
+	// Close the file before renaming it, otherwise it will cause "The process
+	// cannot access the file because it is being used by another process." on windows.
+	f.Close()
+
+	return os.Rename(f.Name(), filename)
+}
diff --git a/vendor/github.com/tendermint/tendermint/node/id.go b/vendor/github.com/tendermint/tendermint/node/id.go
index 5100597c6233ffe30aead79f6a37548992d60efe..d8e41eca7028039fcbf408aa4c6f82e97c5b6d2e 100644
--- a/vendor/github.com/tendermint/tendermint/node/id.go
+++ b/vendor/github.com/tendermint/tendermint/node/id.go
@@ -26,7 +26,7 @@ type NodeGreeting struct {
 
 type SignedNodeGreeting struct {
 	NodeGreeting
-	Signature crypto.Signature
+	Signature []byte
 }
 
 func (pnid *PrivNodeID) SignGreeting() *SignedNodeGreeting {
diff --git a/vendor/github.com/tendermint/tendermint/node/node.go b/vendor/github.com/tendermint/tendermint/node/node.go
index e333c667a8991c39da89680431c8d8f33417053c..0c3396dc6860e7d2f63da394d63f8c6b6bc94fad 100644
--- a/vendor/github.com/tendermint/tendermint/node/node.go
+++ b/vendor/github.com/tendermint/tendermint/node/node.go
@@ -85,7 +85,7 @@ func DefaultNewNode(config *cfg.Config, logger log.Logger) (*Node, error) {
 		proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()),
 		DefaultGenesisDocProviderFunc(config),
 		DefaultDBProvider,
-		DefaultMetricsProvider,
+		DefaultMetricsProvider(config.Instrumentation),
 		logger,
 	)
 }
@@ -93,15 +93,15 @@ func DefaultNewNode(config *cfg.Config, logger log.Logger) (*Node, error) {
 // MetricsProvider returns a consensus, p2p and mempool Metrics.
 type MetricsProvider func() (*cs.Metrics, *p2p.Metrics, *mempl.Metrics)
 
-// DefaultMetricsProvider returns consensus, p2p and mempool Metrics build
-// using Prometheus client library.
-func DefaultMetricsProvider() (*cs.Metrics, *p2p.Metrics, *mempl.Metrics) {
-	return cs.PrometheusMetrics(), p2p.PrometheusMetrics(), mempl.PrometheusMetrics()
-}
-
-// NopMetricsProvider returns consensus, p2p and mempool Metrics as no-op.
-func NopMetricsProvider() (*cs.Metrics, *p2p.Metrics, *mempl.Metrics) {
-	return cs.NopMetrics(), p2p.NopMetrics(), mempl.NopMetrics()
+// DefaultMetricsProvider returns Metrics build using Prometheus client library
+// if Prometheus is enabled. Otherwise, it returns no-op Metrics.
+func DefaultMetricsProvider(config *cfg.InstrumentationConfig) MetricsProvider {
+	return func() (*cs.Metrics, *p2p.Metrics, *mempl.Metrics) {
+		if config.Prometheus {
+			return cs.PrometheusMetrics(), p2p.PrometheusMetrics(), mempl.PrometheusMetrics()
+		}
+		return cs.NopMetrics(), p2p.NopMetrics(), mempl.NopMetrics()
+	}
 }
 
 //------------------------------------------------------------------------------
@@ -229,17 +229,7 @@ func NewNode(config *cfg.Config,
 		consensusLogger.Info("This node is not a validator", "addr", privValidator.GetAddress(), "pubKey", privValidator.GetPubKey())
 	}
 
-	// metrics
-	var (
-		csMetrics    *cs.Metrics
-		p2pMetrics   *p2p.Metrics
-		memplMetrics *mempl.Metrics
-	)
-	if config.Instrumentation.Prometheus {
-		csMetrics, p2pMetrics, memplMetrics = metricsProvider()
-	} else {
-		csMetrics, p2pMetrics, memplMetrics = NopMetricsProvider()
-	}
+	csMetrics, p2pMetrics, memplMetrics := metricsProvider()
 
 	// Make MempoolReactor
 	mempoolLogger := logger.With("module", "mempool")
@@ -462,7 +452,8 @@ func (n *Node) OnStart() error {
 		n.rpcListeners = listeners
 	}
 
-	if n.config.Instrumentation.Prometheus {
+	if n.config.Instrumentation.Prometheus &&
+		n.config.Instrumentation.PrometheusListenAddr != "" {
 		n.prometheusSrv = n.startPrometheusServer(n.config.Instrumentation.PrometheusListenAddr)
 	}
 
diff --git a/vendor/github.com/tendermint/tendermint/p2p/conn/secret_connection.go b/vendor/github.com/tendermint/tendermint/p2p/conn/secret_connection.go
index a2cbe008d6bb1626cc1a43b588246750c055c436..75199ee6ba3273dd9add491338ea1996f09527f2 100644
--- a/vendor/github.com/tendermint/tendermint/p2p/conn/secret_connection.go
+++ b/vendor/github.com/tendermint/tendermint/p2p/conn/secret_connection.go
@@ -1,9 +1,3 @@
-// Uses nacl's secret_box to encrypt a net.Conn.
-// It is (meant to be) an implementation of the STS protocol.
-// Note we do not (yet) assume that a remote peer's pubkey
-// is known ahead of time, and thus we are technically
-// still vulnerable to MITM. (TODO!)
-// See docs/sts-final.pdf for more info
 package conn
 
 import (
@@ -16,36 +10,45 @@ import (
 	"net"
 	"time"
 
+	"golang.org/x/crypto/chacha20poly1305"
+	"golang.org/x/crypto/curve25519"
 	"golang.org/x/crypto/nacl/box"
-	"golang.org/x/crypto/nacl/secretbox"
-	"golang.org/x/crypto/ripemd160"
 
 	"github.com/tendermint/tendermint/crypto"
 	cmn "github.com/tendermint/tendermint/libs/common"
+	"golang.org/x/crypto/hkdf"
 )
 
 // 4 + 1024 == 1028 total frame size
 const dataLenSize = 4
 const dataMaxSize = 1024
 const totalFrameSize = dataMaxSize + dataLenSize
-const sealedFrameSize = totalFrameSize + secretbox.Overhead
+const aeadSizeOverhead = 16 // overhead of poly 1305 authentication tag
+const aeadKeySize = chacha20poly1305.KeySize
+const aeadNonceSize = chacha20poly1305.NonceSize
 
-// Implements net.Conn
+// SecretConnection implements net.conn.
+// It is an implementation of the STS protocol.
+// Note we do not (yet) assume that a remote peer's pubkey
+// is known ahead of time, and thus we are technically
+// still vulnerable to MITM. (TODO!)
+// See docs/sts-final.pdf for more info
 type SecretConnection struct {
 	conn       io.ReadWriteCloser
 	recvBuffer []byte
-	recvNonce  *[24]byte
-	sendNonce  *[24]byte
+	recvNonce  *[aeadNonceSize]byte
+	sendNonce  *[aeadNonceSize]byte
+	recvSecret *[aeadKeySize]byte
+	sendSecret *[aeadKeySize]byte
 	remPubKey  crypto.PubKey
-	shrSecret  *[32]byte // shared secret
 }
 
-// Performs handshake and returns a new authenticated SecretConnection.
-// Returns nil if error in handshake.
+// MakeSecretConnection performs handshake and returns a new authenticated
+// SecretConnection.
+// Returns nil if there is an error in handshake.
 // Caller should call conn.Close()
 // See docs/sts-final.pdf for more information.
 func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*SecretConnection, error) {
-
 	locPubKey := locPrivKey.PubKey()
 
 	// Generate ephemeral keys for perfect forward secrecy.
@@ -59,29 +62,27 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*
 		return nil, err
 	}
 
-	// Compute common shared secret.
-	shrSecret := computeSharedSecret(remEphPub, locEphPriv)
-
 	// Sort by lexical order.
-	loEphPub, hiEphPub := sort32(locEphPub, remEphPub)
+	loEphPub, _ := sort32(locEphPub, remEphPub)
 
 	// Check if the local ephemeral public key
 	// was the least, lexicographically sorted.
 	locIsLeast := bytes.Equal(locEphPub[:], loEphPub[:])
 
-	// Generate nonces to use for secretbox.
-	recvNonce, sendNonce := genNonces(loEphPub, hiEphPub, locIsLeast)
+	// Compute common diffie hellman secret using X25519.
+	dhSecret := computeDHSecret(remEphPub, locEphPriv)
 
-	// Generate common challenge to sign.
-	challenge := genChallenge(loEphPub, hiEphPub)
+	// generate the secret used for receiving, sending, challenge via hkdf-sha2 on dhSecret
+	recvSecret, sendSecret, challenge := deriveSecretAndChallenge(dhSecret, locIsLeast)
 
 	// Construct SecretConnection.
 	sc := &SecretConnection{
 		conn:       conn,
 		recvBuffer: nil,
-		recvNonce:  recvNonce,
-		sendNonce:  sendNonce,
-		shrSecret:  shrSecret,
+		recvNonce:  new([aeadNonceSize]byte),
+		sendNonce:  new([aeadNonceSize]byte),
+		recvSecret: recvSecret,
+		sendSecret: sendSecret,
 	}
 
 	// Sign the challenge bytes for authentication.
@@ -92,6 +93,7 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*
 	if err != nil {
 		return nil, err
 	}
+
 	remPubKey, remSignature := authSigMsg.Key, authSigMsg.Sig
 	if !remPubKey.VerifyBytes(challenge[:], remSignature) {
 		return nil, errors.New("Challenge verification failed")
@@ -102,7 +104,7 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*
 	return sc, nil
 }
 
-// Returns authenticated remote pubkey
+// RemotePubKey returns authenticated remote pubkey
 func (sc *SecretConnection) RemotePubKey() crypto.PubKey {
 	return sc.remPubKey
 }
@@ -124,14 +126,17 @@ func (sc *SecretConnection) Write(data []byte) (n int, err error) {
 		binary.BigEndian.PutUint32(frame, uint32(chunkLength))
 		copy(frame[dataLenSize:], chunk)
 
+		aead, err := chacha20poly1305.New(sc.sendSecret[:])
+		if err != nil {
+			return n, errors.New("Invalid SecretConnection Key")
+		}
 		// encrypt the frame
-		var sealedFrame = make([]byte, sealedFrameSize)
-		secretbox.Seal(sealedFrame[:0], frame, sc.sendNonce, sc.shrSecret)
-		// fmt.Printf("secretbox.Seal(sealed:%X,sendNonce:%X,shrSecret:%X\n", sealedFrame, sc.sendNonce, sc.shrSecret)
-		incr2Nonce(sc.sendNonce)
+		var sealedFrame = make([]byte, aeadSizeOverhead+totalFrameSize)
+		aead.Seal(sealedFrame[:0], sc.sendNonce[:], frame, nil)
+		incrNonce(sc.sendNonce)
 		// end encryption
 
-		_, err := sc.conn.Write(sealedFrame)
+		_, err = sc.conn.Write(sealedFrame)
 		if err != nil {
 			return n, err
 		}
@@ -148,7 +153,11 @@ func (sc *SecretConnection) Read(data []byte) (n int, err error) {
 		return
 	}
 
-	sealedFrame := make([]byte, sealedFrameSize)
+	aead, err := chacha20poly1305.New(sc.recvSecret[:])
+	if err != nil {
+		return n, errors.New("Invalid SecretConnection Key")
+	}
+	sealedFrame := make([]byte, totalFrameSize+aeadSizeOverhead)
 	_, err = io.ReadFull(sc.conn, sealedFrame)
 	if err != nil {
 		return
@@ -156,12 +165,11 @@ func (sc *SecretConnection) Read(data []byte) (n int, err error) {
 
 	// decrypt the frame
 	var frame = make([]byte, totalFrameSize)
-	// fmt.Printf("secretbox.Open(sealed:%X,recvNonce:%X,shrSecret:%X\n", sealedFrame, sc.recvNonce, sc.shrSecret)
-	_, ok := secretbox.Open(frame[:0], sealedFrame, sc.recvNonce, sc.shrSecret)
-	if !ok {
+	_, err = aead.Open(frame[:0], sc.recvNonce[:], sealedFrame, nil)
+	if err != nil {
 		return n, errors.New("Failed to decrypt SecretConnection")
 	}
-	incr2Nonce(sc.recvNonce)
+	incrNonce(sc.recvNonce)
 	// end decryption
 
 	var chunkLength = binary.BigEndian.Uint32(frame) // read the first two bytes
@@ -176,6 +184,7 @@ func (sc *SecretConnection) Read(data []byte) (n int, err error) {
 }
 
 // Implements net.Conn
+// nolint
 func (sc *SecretConnection) Close() error                  { return sc.conn.Close() }
 func (sc *SecretConnection) LocalAddr() net.Addr           { return sc.conn.(net.Conn).LocalAddr() }
 func (sc *SecretConnection) RemoteAddr() net.Addr          { return sc.conn.(net.Conn).RemoteAddr() }
@@ -204,18 +213,16 @@ func shareEphPubKey(conn io.ReadWriteCloser, locEphPub *[32]byte) (remEphPub *[3
 			var _, err1 = cdc.MarshalBinaryWriter(conn, locEphPub)
 			if err1 != nil {
 				return nil, err1, true // abort
-			} else {
-				return nil, nil, false
 			}
+			return nil, nil, false
 		},
 		func(_ int) (val interface{}, err error, abort bool) {
 			var _remEphPub [32]byte
 			var _, err2 = cdc.UnmarshalBinaryReader(conn, &_remEphPub, 1024*1024) // TODO
 			if err2 != nil {
 				return nil, err2, true // abort
-			} else {
-				return _remEphPub, nil, false
 			}
+			return _remEphPub, nil, false
 		},
 	)
 
@@ -230,9 +237,40 @@ func shareEphPubKey(conn io.ReadWriteCloser, locEphPub *[32]byte) (remEphPub *[3
 	return &_remEphPub, nil
 }
 
-func computeSharedSecret(remPubKey, locPrivKey *[32]byte) (shrSecret *[32]byte) {
-	shrSecret = new([32]byte)
-	box.Precompute(shrSecret, remPubKey, locPrivKey)
+func deriveSecretAndChallenge(dhSecret *[32]byte, locIsLeast bool) (recvSecret, sendSecret *[aeadKeySize]byte, challenge *[32]byte) {
+	hash := sha256.New
+	hkdf := hkdf.New(hash, dhSecret[:], nil, []byte("TENDERMINT_SECRET_CONNECTION_KEY_AND_CHALLENGE_GEN"))
+	// get enough data for 2 aead keys, and a 32 byte challenge
+	res := new([2*aeadKeySize + 32]byte)
+	_, err := io.ReadFull(hkdf, res[:])
+	if err != nil {
+		panic(err)
+	}
+
+	challenge = new([32]byte)
+	recvSecret = new([aeadKeySize]byte)
+	sendSecret = new([aeadKeySize]byte)
+	// Use the last 32 bytes as the challenge
+	copy(challenge[:], res[2*aeadKeySize:2*aeadKeySize+32])
+
+	// bytes 0 through aeadKeySize - 1 are one aead key.
+	// bytes aeadKeySize through 2*aeadKeySize -1 are another aead key.
+	// which key corresponds to sending and receiving key depends on whether
+	// the local key is less than the remote key.
+	if locIsLeast {
+		copy(recvSecret[:], res[0:aeadKeySize])
+		copy(sendSecret[:], res[aeadKeySize:aeadKeySize*2])
+	} else {
+		copy(sendSecret[:], res[0:aeadKeySize])
+		copy(recvSecret[:], res[aeadKeySize:aeadKeySize*2])
+	}
+
+	return
+}
+
+func computeDHSecret(remPubKey, locPrivKey *[32]byte) (shrKey *[32]byte) {
+	shrKey = new([32]byte)
+	curve25519.ScalarMult(shrKey, locPrivKey, remPubKey)
 	return
 }
 
@@ -247,26 +285,7 @@ func sort32(foo, bar *[32]byte) (lo, hi *[32]byte) {
 	return
 }
 
-func genNonces(loPubKey, hiPubKey *[32]byte, locIsLo bool) (recvNonce, sendNonce *[24]byte) {
-	nonce1 := hash24(append(loPubKey[:], hiPubKey[:]...))
-	nonce2 := new([24]byte)
-	copy(nonce2[:], nonce1[:])
-	nonce2[len(nonce2)-1] ^= 0x01
-	if locIsLo {
-		recvNonce = nonce1
-		sendNonce = nonce2
-	} else {
-		recvNonce = nonce2
-		sendNonce = nonce1
-	}
-	return
-}
-
-func genChallenge(loPubKey, hiPubKey *[32]byte) (challenge *[32]byte) {
-	return hash32(append(loPubKey[:], hiPubKey[:]...))
-}
-
-func signChallenge(challenge *[32]byte, locPrivKey crypto.PrivKey) (signature crypto.Signature) {
+func signChallenge(challenge *[32]byte, locPrivKey crypto.PrivKey) (signature []byte) {
 	signature, err := locPrivKey.Sign(challenge[:])
 	// TODO(ismail): let signChallenge return an error instead
 	if err != nil {
@@ -277,10 +296,10 @@ func signChallenge(challenge *[32]byte, locPrivKey crypto.PrivKey) (signature cr
 
 type authSigMessage struct {
 	Key crypto.PubKey
-	Sig crypto.Signature
+	Sig []byte
 }
 
-func shareAuthSignature(sc *SecretConnection, pubKey crypto.PubKey, signature crypto.Signature) (recvMsg authSigMessage, err error) {
+func shareAuthSignature(sc *SecretConnection, pubKey crypto.PubKey, signature []byte) (recvMsg authSigMessage, err error) {
 
 	// Send our info and receive theirs in tandem.
 	var trs, _ = cmn.Parallel(
@@ -288,18 +307,16 @@ func shareAuthSignature(sc *SecretConnection, pubKey crypto.PubKey, signature cr
 			var _, err1 = cdc.MarshalBinaryWriter(sc, authSigMessage{pubKey, signature})
 			if err1 != nil {
 				return nil, err1, true // abort
-			} else {
-				return nil, nil, false
 			}
+			return nil, nil, false
 		},
 		func(_ int) (val interface{}, err error, abort bool) {
 			var _recvMsg authSigMessage
 			var _, err2 = cdc.UnmarshalBinaryReader(sc, &_recvMsg, 1024*1024) // TODO
 			if err2 != nil {
 				return nil, err2, true // abort
-			} else {
-				return _recvMsg, nil, false
 			}
+			return _recvMsg, nil, false
 		},
 	)
 
@@ -315,36 +332,11 @@ func shareAuthSignature(sc *SecretConnection, pubKey crypto.PubKey, signature cr
 
 //--------------------------------------------------------------------------------
 
-// sha256
-func hash32(input []byte) (res *[32]byte) {
-	hasher := sha256.New()
-	hasher.Write(input) // nolint: errcheck, gas
-	resSlice := hasher.Sum(nil)
-	res = new([32]byte)
-	copy(res[:], resSlice)
-	return
-}
-
-// We only fill in the first 20 bytes with ripemd160
-func hash24(input []byte) (res *[24]byte) {
-	hasher := ripemd160.New()
-	hasher.Write(input) // nolint: errcheck, gas
-	resSlice := hasher.Sum(nil)
-	res = new([24]byte)
-	copy(res[:], resSlice)
-	return
-}
-
-// increment nonce big-endian by 2 with wraparound.
-func incr2Nonce(nonce *[24]byte) {
-	incrNonce(nonce)
-	incrNonce(nonce)
-}
-
 // increment nonce big-endian by 1 with wraparound.
-func incrNonce(nonce *[24]byte) {
-	for i := 23; 0 <= i; i-- {
+func incrNonce(nonce *[aeadNonceSize]byte) {
+	for i := aeadNonceSize - 1; 0 <= i; i-- {
 		nonce[i]++
+		// if this byte wrapped around to zero, we need to increment the next byte
 		if nonce[i] != 0 {
 			return
 		}
diff --git a/vendor/github.com/tendermint/tendermint/p2p/pex/addrbook.go b/vendor/github.com/tendermint/tendermint/p2p/pex/addrbook.go
index c630d14c370c0d467240b99f159f9a12390e8902..ad6e0c00be2d2603ecd8bb20e2321a719968717e 100644
--- a/vendor/github.com/tendermint/tendermint/p2p/pex/addrbook.go
+++ b/vendor/github.com/tendermint/tendermint/p2p/pex/addrbook.go
@@ -45,6 +45,9 @@ type AddrBook interface {
 
 	// Do we need more peers?
 	NeedMoreAddrs() bool
+	// Is Address Book Empty? Answer should not depend on being in your own
+	// address book, or private peers
+	Empty() bool
 
 	// Pick an address to dial
 	PickAddress(biasTowardsNewAddrs int) *p2p.NetAddress
@@ -223,6 +226,12 @@ func (a *addrBook) NeedMoreAddrs() bool {
 	return a.Size() < needAddressThreshold
 }
 
+// Empty implements AddrBook - returns true if there are no addresses in the address book.
+// Does not count the peer appearing in its own address book, or private peers.
+func (a *addrBook) Empty() bool {
+	return a.Size() == 0
+}
+
 // PickAddress implements AddrBook. It picks an address to connect to.
 // The address is picked randomly from an old or new bucket according
 // to the biasTowardsNewAddrs argument, which must be between [0, 100] (or else is truncated to that range)
@@ -496,7 +505,6 @@ out:
 	}
 	saveFileTicker.Stop()
 	a.saveToFile(a.filePath)
-	a.Logger.Info("Address handler done")
 }
 
 //----------------------------------------------------------
@@ -638,6 +646,7 @@ func (a *addrBook) addAddress(addr, src *p2p.NetAddress) error {
 	if a.routabilityStrict && !addr.Routable() {
 		return ErrAddrBookNonRoutable{addr}
 	}
+
 	// TODO: we should track ourAddrs by ID and by IP:PORT and refuse both.
 	if _, ok := a.ourAddrs[addr.String()]; ok {
 		return ErrAddrBookSelf{addr}
@@ -647,6 +656,10 @@ func (a *addrBook) addAddress(addr, src *p2p.NetAddress) error {
 		return ErrAddrBookPrivate{addr}
 	}
 
+	if _, ok := a.privateIDs[src.ID]; ok {
+		return ErrAddrBookPrivateSrc{src}
+	}
+
 	ka := a.addrLookup[addr.ID]
 	if ka != nil {
 		// If its already old and the addr is the same, ignore it.
diff --git a/vendor/github.com/tendermint/tendermint/p2p/pex/errors.go b/vendor/github.com/tendermint/tendermint/p2p/pex/errors.go
index 34bfb5ab165746bdb1137b76641d67ea9edfcc03..7f660bdc5a7d860b3be6a2e74d3716be81579166 100644
--- a/vendor/github.com/tendermint/tendermint/p2p/pex/errors.go
+++ b/vendor/github.com/tendermint/tendermint/p2p/pex/errors.go
@@ -30,6 +30,14 @@ func (err ErrAddrBookPrivate) Error() string {
 	return fmt.Sprintf("Cannot add private peer with address %v", err.Addr)
 }
 
+type ErrAddrBookPrivateSrc struct {
+	Src *p2p.NetAddress
+}
+
+func (err ErrAddrBookPrivateSrc) Error() string {
+	return fmt.Sprintf("Cannot add peer coming from private peer with address %v", err.Src)
+}
+
 type ErrAddrBookNilAddr struct {
 	Addr *p2p.NetAddress
 	Src  *p2p.NetAddress
diff --git a/vendor/github.com/tendermint/tendermint/p2p/pex/pex_reactor.go b/vendor/github.com/tendermint/tendermint/p2p/pex/pex_reactor.go
index 5c4894ce481f2aff852f532996bd1a5398ee6f27..288cb0d150e0fd5bde094130e4a7b27ddb1fb3c8 100644
--- a/vendor/github.com/tendermint/tendermint/p2p/pex/pex_reactor.go
+++ b/vendor/github.com/tendermint/tendermint/p2p/pex/pex_reactor.go
@@ -7,9 +7,10 @@ import (
 	"sync"
 	"time"
 
+	"github.com/pkg/errors"
+
 	amino "github.com/tendermint/go-amino"
 	cmn "github.com/tendermint/tendermint/libs/common"
-
 	"github.com/tendermint/tendermint/p2p"
 	"github.com/tendermint/tendermint/p2p/conn"
 )
@@ -74,6 +75,8 @@ type PEXReactor struct {
 	requestsSent         *cmn.CMap // ID->struct{}: unanswered send requests
 	lastReceivedRequests *cmn.CMap // ID->time.Time: last time peer requested from us
 
+	seedAddrs []*p2p.NetAddress
+
 	attemptsToDial sync.Map // address (string) -> {number of attempts (int), last time dialed (time.Time)}
 }
 
@@ -113,20 +116,20 @@ func NewPEXReactor(b AddrBook, config *PEXReactorConfig) *PEXReactor {
 
 // OnStart implements BaseService
 func (r *PEXReactor) OnStart() error {
-	if err := r.BaseReactor.OnStart(); err != nil {
-		return err
-	}
 	err := r.book.Start()
 	if err != nil && err != cmn.ErrAlreadyStarted {
 		return err
 	}
 
-	// return err if user provided a bad seed address
-	// or a host name that we cant resolve
-	if err := r.checkSeeds(); err != nil {
+	numOnline, seedAddrs, err := r.checkSeeds()
+	if err != nil {
 		return err
+	} else if numOnline == 0 && r.book.Empty() {
+		return errors.New("Address book is empty, and could not connect to any seed nodes")
 	}
 
+	r.seedAddrs = seedAddrs
+
 	// Check if this node should run
 	// in seed/crawler mode
 	if r.config.SeedMode {
@@ -139,7 +142,6 @@ func (r *PEXReactor) OnStart() error {
 
 // OnStop implements BaseService
 func (r *PEXReactor) OnStop() {
-	r.BaseReactor.OnStop()
 	r.book.Stop()
 }
 
@@ -285,7 +287,6 @@ func (r *PEXReactor) RequestAddrs(p Peer) {
 // request for this peer and deletes the open request.
 // If there's no open request for the src peer, it returns an error.
 func (r *PEXReactor) ReceiveAddrs(addrs []*p2p.NetAddress, src Peer) error {
-
 	id := string(src.ID())
 	if !r.requestsSent.Has(id) {
 		return cmn.NewError("Received unsolicited pexAddrsMessage")
@@ -301,6 +302,13 @@ func (r *PEXReactor) ReceiveAddrs(addrs []*p2p.NetAddress, src Peer) error {
 
 		err := r.book.AddAddress(netAddr, srcAddr)
 		r.logErrAddrBook(err)
+
+		// If this address came from a seed node, try to connect to it without waiting.
+		for _, seedAddr := range r.seedAddrs {
+			if seedAddr.Equals(srcAddr) {
+				r.ensurePeers()
+			}
+		}
 	}
 	return nil
 }
@@ -471,34 +479,36 @@ func (r *PEXReactor) dialPeer(addr *p2p.NetAddress) {
 	}
 }
 
-// check seed addresses are well formed
-func (r *PEXReactor) checkSeeds() error {
+// checkSeeds checks that addresses are well formed.
+// Returns number of seeds we can connect to, along with all seeds addrs.
+// return err if user provided any badly formatted seed addresses.
+// Doesn't error if the seed node can't be reached.
+// numOnline returns -1 if no seed nodes were in the initial configuration.
+func (r *PEXReactor) checkSeeds() (numOnline int, netAddrs []*p2p.NetAddress, err error) {
 	lSeeds := len(r.config.Seeds)
 	if lSeeds == 0 {
-		return nil
+		return -1, nil, nil
 	}
-	_, errs := p2p.NewNetAddressStrings(r.config.Seeds)
+	netAddrs, errs := p2p.NewNetAddressStrings(r.config.Seeds)
+	numOnline = lSeeds - len(errs)
 	for _, err := range errs {
-		if err != nil {
-			return err
+		switch e := err.(type) {
+		case p2p.ErrNetAddressLookup:
+			r.Logger.Error("Connecting to seed failed", "err", e)
+		default:
+			return 0, nil, errors.Wrap(e, "seed node configuration has error")
 		}
 	}
-	return nil
+	return
 }
 
 // randomly dial seeds until we connect to one or exhaust them
 func (r *PEXReactor) dialSeeds() {
-	lSeeds := len(r.config.Seeds)
-	if lSeeds == 0 {
-		return
-	}
-	seedAddrs, _ := p2p.NewNetAddressStrings(r.config.Seeds)
-
-	perm := cmn.RandPerm(lSeeds)
+	perm := cmn.RandPerm(len(r.seedAddrs))
 	// perm := r.Switch.rng.Perm(lSeeds)
 	for _, i := range perm {
 		// dial a random seed
-		seedAddr := seedAddrs[i]
+		seedAddr := r.seedAddrs[i]
 		err := r.Switch.DialPeerWithAddress(seedAddr, false)
 		if err == nil {
 			return
diff --git a/vendor/github.com/tendermint/tendermint/privval/priv_validator.go b/vendor/github.com/tendermint/tendermint/privval/priv_validator.go
index 5b056d8a0b5b3d8b7dce82e7b2099c3465f5387c..a81751a9147f9d79faf0d2f50289e954c951e2cf 100644
--- a/vendor/github.com/tendermint/tendermint/privval/priv_validator.go
+++ b/vendor/github.com/tendermint/tendermint/privval/priv_validator.go
@@ -38,14 +38,14 @@ func voteToStep(vote *types.Vote) int8 {
 // to prevent double signing.
 // NOTE: the directory containing the pv.filePath must already exist.
 type FilePV struct {
-	Address       types.Address    `json:"address"`
-	PubKey        crypto.PubKey    `json:"pub_key"`
-	LastHeight    int64            `json:"last_height"`
-	LastRound     int              `json:"last_round"`
-	LastStep      int8             `json:"last_step"`
-	LastSignature crypto.Signature `json:"last_signature,omitempty"` // so we dont lose signatures XXX Why would we lose signatures?
-	LastSignBytes cmn.HexBytes     `json:"last_signbytes,omitempty"` // so we dont lose signatures XXX Why would we lose signatures?
-	PrivKey       crypto.PrivKey   `json:"priv_key"`
+	Address       types.Address  `json:"address"`
+	PubKey        crypto.PubKey  `json:"pub_key"`
+	LastHeight    int64          `json:"last_height"`
+	LastRound     int            `json:"last_round"`
+	LastStep      int8           `json:"last_step"`
+	LastSignature []byte         `json:"last_signature,omitempty"` // so we dont lose signatures XXX Why would we lose signatures?
+	LastSignBytes cmn.HexBytes   `json:"last_signbytes,omitempty"` // so we dont lose signatures XXX Why would we lose signatures?
+	PrivKey       crypto.PrivKey `json:"priv_key"`
 
 	// For persistence.
 	// Overloaded for testing.
@@ -138,7 +138,7 @@ func (pv *FilePV) save() {
 // Reset resets all fields in the FilePV.
 // NOTE: Unsafe!
 func (pv *FilePV) Reset() {
-	var sig crypto.Signature
+	var sig []byte
 	pv.LastHeight = 0
 	pv.LastRound = 0
 	pv.LastStep = 0
@@ -277,7 +277,7 @@ func (pv *FilePV) signProposal(chainID string, proposal *types.Proposal) error {
 
 // Persist height/round/step and signature
 func (pv *FilePV) saveSigned(height int64, round int, step int8,
-	signBytes []byte, sig crypto.Signature) {
+	signBytes []byte, sig []byte) {
 
 	pv.LastHeight = height
 	pv.LastRound = round
diff --git a/vendor/github.com/tendermint/tendermint/privval/socket.go b/vendor/github.com/tendermint/tendermint/privval/socket.go
index c33443edad01f81a01b461c2764252a82e7d07eb..d5ede471c2eb83722992ae9f477e8f74063b4c5b 100644
--- a/vendor/github.com/tendermint/tendermint/privval/socket.go
+++ b/vendor/github.com/tendermint/tendermint/privval/socket.go
@@ -7,12 +7,12 @@ import (
 	"net"
 	"time"
 
-	"github.com/tendermint/go-amino"
+	amino "github.com/tendermint/go-amino"
+
 	"github.com/tendermint/tendermint/crypto"
 	"github.com/tendermint/tendermint/crypto/ed25519"
 	cmn "github.com/tendermint/tendermint/libs/common"
 	"github.com/tendermint/tendermint/libs/log"
-
 	p2pconn "github.com/tendermint/tendermint/p2p/conn"
 	"github.com/tendermint/tendermint/types"
 )
@@ -33,7 +33,7 @@ var (
 )
 
 var (
-	acceptDeadline = time.Second + defaultAcceptDeadlineSeconds
+	acceptDeadline = time.Second * defaultAcceptDeadlineSeconds
 	connDeadline   = time.Second * defaultConnDeadlineSeconds
 	connHeartbeat  = time.Second * defaultConnHeartBeatSeconds
 )
diff --git a/vendor/github.com/tendermint/tendermint/rpc/core/README.md b/vendor/github.com/tendermint/tendermint/rpc/core/README.md
index 9547079b2975e9b6c28c521380d9d914cfd756ee..32c3051e336c37b16115a5ee8f585ec23c5437af 100644
--- a/vendor/github.com/tendermint/tendermint/rpc/core/README.md
+++ b/vendor/github.com/tendermint/tendermint/rpc/core/README.md
@@ -1,18 +1,15 @@
 # Tendermint RPC
 
-## Generate markdown for [Slate](https://github.com/tendermint/slate)
-
-We are using [Slate](https://github.com/tendermint/slate) to power our RPC
+We are using [Slate](https://github.com/lord/slate) to power our RPC
 documentation. For generating markdown use:
 
 ```shell
 go get github.com/davecheney/godoc2md
 
-godoc2md -template rpc/core/doc_template.txt github.com/tendermint/tendermint/rpc/core | grep -v -e "pipe.go" -e "routes.go" -e "dev.go" | sed 's$/src/target$https://github.com/tendermint/tendermint/tree/master/rpc/core$'
+# from root of this repo
+make rpc-docs
 ```
 
-For more information see the [CI script for building the Slate docs](/scripts/slate.sh)
-
 ## Pagination
 
 Requests that return multiple items will be paginated to 30 items by default.
diff --git a/vendor/github.com/tendermint/tendermint/rpc/core/abci.go b/vendor/github.com/tendermint/tendermint/rpc/core/abci.go
index 100176195771a5e88d7740d34d7b544901c9a97c..3f399be80fdf0254327c8a5a776f656f6727f44a 100644
--- a/vendor/github.com/tendermint/tendermint/rpc/core/abci.go
+++ b/vendor/github.com/tendermint/tendermint/rpc/core/abci.go
@@ -93,7 +93,7 @@ func ABCIQuery(path string, data cmn.HexBytes, height int64, trusted bool) (*cty
 // }
 // ```
 func ABCIInfo() (*ctypes.ResultABCIInfo, error) {
-	resInfo, err := proxyAppQuery.InfoSync(abci.RequestInfo{version.Version})
+	resInfo, err := proxyAppQuery.InfoSync(abci.RequestInfo{Version: version.Version})
 	if err != nil {
 		return nil, err
 	}
diff --git a/vendor/github.com/tendermint/tendermint/rpc/core/slate_header.txt b/vendor/github.com/tendermint/tendermint/rpc/core/slate_header.txt
new file mode 100644
index 0000000000000000000000000000000000000000..bb4ca6e03c40aa77c03374599031664f68692b4e
--- /dev/null
+++ b/vendor/github.com/tendermint/tendermint/rpc/core/slate_header.txt
@@ -0,0 +1,13 @@
+---
+title: RPC Reference
+
+language_tabs: # must be one of https://git.io/vQNgJ
+  - shell
+  - go
+
+toc_footers:
+  - <a href='https://tendermint.com/'>Tendermint</a>
+  - <a href='https://github.com/lord/slate'>Documentation Powered by Slate</a>
+
+search: true
+---
diff --git a/vendor/github.com/tendermint/tendermint/rpc/core/status.go b/vendor/github.com/tendermint/tendermint/rpc/core/status.go
index 739e67b8607cba0b504d4b624786becf655453f6..4cb7667b7568bde550258a2885c61325f90a91e4 100644
--- a/vendor/github.com/tendermint/tendermint/rpc/core/status.go
+++ b/vendor/github.com/tendermint/tendermint/rpc/core/status.go
@@ -104,20 +104,11 @@ func Status() (*ctypes.ResultStatus, error) {
 	return result, nil
 }
 
-const consensusTimeout = time.Second
-
 func validatorAtHeight(h int64) *types.Validator {
-	lastBlockHeight, vals := getValidatorsWithTimeout(
-		consensusState,
-		consensusTimeout,
-	)
-
-	if lastBlockHeight == -1 {
-		return nil
-	}
-
 	privValAddress := pubKey.Address()
 
+	lastBlockHeight, vals := consensusState.GetValidators()
+
 	// if we're still at height h, search in the current validator set
 	if lastBlockHeight == h {
 		for _, val := range vals {
@@ -140,32 +131,3 @@ func validatorAtHeight(h int64) *types.Validator {
 
 	return nil
 }
-
-type validatorRetriever interface {
-	GetValidators() (int64, []*types.Validator)
-}
-
-// NOTE: Consensus might halt, but we still need to process RPC requests (at
-// least for endpoints whole output does not depend on consensus state).
-func getValidatorsWithTimeout(
-	vr validatorRetriever,
-	t time.Duration,
-) (int64, []*types.Validator) {
-	resultCh := make(chan struct {
-		lastBlockHeight int64
-		vals            []*types.Validator
-	})
-	go func() {
-		h, v := vr.GetValidators()
-		resultCh <- struct {
-			lastBlockHeight int64
-			vals            []*types.Validator
-		}{h, v}
-	}()
-	select {
-	case res := <-resultCh:
-		return res.lastBlockHeight, res.vals
-	case <-time.After(t):
-		return -1, []*types.Validator{}
-	}
-}
diff --git a/vendor/github.com/tendermint/tendermint/state/execution.go b/vendor/github.com/tendermint/tendermint/state/execution.go
index f38f5e0bb9ace4986238b41409855d725abb01fd..54e1ec73ae04de0cad695bb74625e33ab2e1acf9 100644
--- a/vendor/github.com/tendermint/tendermint/state/execution.go
+++ b/vendor/github.com/tendermint/tendermint/state/execution.go
@@ -188,9 +188,12 @@ func execBlockOnProxyApp(logger log.Logger, proxyAppConn proxy.AppConnConsensus,
 
 	// Begin block
 	_, err := proxyAppConn.BeginBlockSync(abci.RequestBeginBlock{
-		Hash:                block.Hash(),
-		Header:              types.TM2PB.Header(&block.Header),
-		Validators:          signVals,
+		Hash:   block.Hash(),
+		Header: types.TM2PB.Header(&block.Header),
+		LastCommitInfo: abci.LastCommitInfo{
+			CommitRound: int32(block.LastCommit.Round()),
+			Validators:  signVals,
+		},
 		ByzantineValidators: byzVals,
 	})
 	if err != nil {
@@ -207,7 +210,7 @@ func execBlockOnProxyApp(logger log.Logger, proxyAppConn proxy.AppConnConsensus,
 	}
 
 	// End block
-	abciResponses.EndBlock, err = proxyAppConn.EndBlockSync(abci.RequestEndBlock{block.Height})
+	abciResponses.EndBlock, err = proxyAppConn.EndBlockSync(abci.RequestEndBlock{Height: block.Height})
 	if err != nil {
 		logger.Error("Error in proxyAppConn.EndBlock", "err", err)
 		return nil, err
@@ -245,7 +248,7 @@ func getBeginBlockValidatorInfo(block *types.Block, lastValSet *types.ValidatorS
 			vote = block.LastCommit.Precommits[i]
 		}
 		val := abci.SigningValidator{
-			Validator:       types.TM2PB.Validator(val),
+			Validator:       types.TM2PB.ValidatorWithoutPubKey(val),
 			SignedLastBlock: vote != nil,
 		}
 		signVals[i] = val
diff --git a/vendor/github.com/tendermint/tendermint/state/store.go b/vendor/github.com/tendermint/tendermint/state/store.go
index 9e94e36faab74a8e1ac2642749f3db82327f65a3..3a1a6231b73decd9e3f61c690cb114496133c724 100644
--- a/vendor/github.com/tendermint/tendermint/state/store.go
+++ b/vendor/github.com/tendermint/tendermint/state/store.go
@@ -80,6 +80,7 @@ func loadState(db dbm.DB, key []byte) (state State) {
 }
 
 // SaveState persists the State, the ValidatorsInfo, and the ConsensusParamsInfo to the database.
+// This flushes the writes (e.g. calls SetSync).
 func SaveState(db dbm.DB, state State) {
 	saveState(db, state, stateKey)
 }
@@ -218,7 +219,7 @@ func saveValidatorsInfo(db dbm.DB, nextHeight, changeHeight int64, valSet *types
 	if changeHeight == nextHeight {
 		valInfo.ValidatorSet = valSet
 	}
-	db.SetSync(calcValidatorsKey(nextHeight), valInfo.Bytes())
+	db.Set(calcValidatorsKey(nextHeight), valInfo.Bytes())
 }
 
 //-----------------------------------------------------------------------------
@@ -289,5 +290,5 @@ func saveConsensusParamsInfo(db dbm.DB, nextHeight, changeHeight int64, params t
 	if changeHeight == nextHeight {
 		paramsInfo.ConsensusParams = params
 	}
-	db.SetSync(calcConsensusParamsKey(nextHeight), paramsInfo.Bytes())
+	db.Set(calcConsensusParamsKey(nextHeight), paramsInfo.Bytes())
 }
diff --git a/vendor/github.com/tendermint/tendermint/tools/build/LICENSE b/vendor/github.com/tendermint/tendermint/tools/build/LICENSE
deleted file mode 100644
index bb66bb3507e96f784d5f0e8d3d824fede11dcb5e..0000000000000000000000000000000000000000
--- a/vendor/github.com/tendermint/tendermint/tools/build/LICENSE
+++ /dev/null
@@ -1,204 +0,0 @@
-Tendermint Core
-License: Apache2.0
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "{}"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright 2016 All in Bits, Inc
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/vendor/github.com/tendermint/tendermint/tools/mintnet-kubernetes/LICENSE b/vendor/github.com/tendermint/tendermint/tools/mintnet-kubernetes/LICENSE
deleted file mode 100644
index 64a33ddf1a4455dceb070463508e23b500bc8936..0000000000000000000000000000000000000000
--- a/vendor/github.com/tendermint/tendermint/tools/mintnet-kubernetes/LICENSE
+++ /dev/null
@@ -1,192 +0,0 @@
-Copyright (C) 2017 Tendermint
-
-
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        https://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       https://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/vendor/github.com/tendermint/tendermint/tools/tm-bench/LICENSE b/vendor/github.com/tendermint/tendermint/tools/tm-bench/LICENSE
deleted file mode 100644
index f489139675ee621b374d23e48f555adc5c0b64d4..0000000000000000000000000000000000000000
--- a/vendor/github.com/tendermint/tendermint/tools/tm-bench/LICENSE
+++ /dev/null
@@ -1,204 +0,0 @@
-Tendermint Bench
-Copyright 2017 Tendermint
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/vendor/github.com/tendermint/tendermint/tools/tm-monitor/LICENSE b/vendor/github.com/tendermint/tendermint/tools/tm-monitor/LICENSE
deleted file mode 100644
index 20728d3180c4374e819e969750015e7588a15a21..0000000000000000000000000000000000000000
--- a/vendor/github.com/tendermint/tendermint/tools/tm-monitor/LICENSE
+++ /dev/null
@@ -1,204 +0,0 @@
-Tendermint Monitor
-Copyright 2017 Tendermint
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/vendor/github.com/tendermint/tendermint/types/canonical_json.go b/vendor/github.com/tendermint/tendermint/types/canonical_json.go
index 189a8a7a2fec6f93455e5b8e23aa636659d94001..aca9e9b799cc10d9aeaadc304d35af841e53cd8c 100644
--- a/vendor/github.com/tendermint/tendermint/types/canonical_json.go
+++ b/vendor/github.com/tendermint/tendermint/types/canonical_json.go
@@ -9,7 +9,7 @@ import (
 // Canonical json is amino's json for structs with fields in alphabetical order
 
 // TimeFormat is used for generating the sigs
-const TimeFormat = "2006-01-02T15:04:05.000Z"
+const TimeFormat = time.RFC3339Nano
 
 type CanonicalJSONBlockID struct {
 	Hash        cmn.HexBytes               `json:"hash,omitempty"`
diff --git a/vendor/github.com/tendermint/tendermint/types/heartbeat.go b/vendor/github.com/tendermint/tendermint/types/heartbeat.go
index cebe2864cf430211f5cf86043485cc9a492bf5bd..151f1b0b21705c55b20385b7bb8cc817011cc03c 100644
--- a/vendor/github.com/tendermint/tendermint/types/heartbeat.go
+++ b/vendor/github.com/tendermint/tendermint/types/heartbeat.go
@@ -3,7 +3,6 @@ package types
 import (
 	"fmt"
 
-	"github.com/tendermint/tendermint/crypto"
 	cmn "github.com/tendermint/tendermint/libs/common"
 )
 
@@ -13,12 +12,12 @@ import (
 // json field tags because we always want the JSON
 // representation to be in its canonical form.
 type Heartbeat struct {
-	ValidatorAddress Address          `json:"validator_address"`
-	ValidatorIndex   int              `json:"validator_index"`
-	Height           int64            `json:"height"`
-	Round            int              `json:"round"`
-	Sequence         int              `json:"sequence"`
-	Signature        crypto.Signature `json:"signature"`
+	ValidatorAddress Address `json:"validator_address"`
+	ValidatorIndex   int     `json:"validator_index"`
+	Height           int64   `json:"height"`
+	Round            int     `json:"round"`
+	Sequence         int     `json:"sequence"`
+	Signature        []byte  `json:"signature"`
 }
 
 // SignBytes returns the Heartbeat bytes for signing.
@@ -48,5 +47,6 @@ func (heartbeat *Heartbeat) String() string {
 
 	return fmt.Sprintf("Heartbeat{%v:%X %v/%02d (%v) %v}",
 		heartbeat.ValidatorIndex, cmn.Fingerprint(heartbeat.ValidatorAddress),
-		heartbeat.Height, heartbeat.Round, heartbeat.Sequence, heartbeat.Signature)
+		heartbeat.Height, heartbeat.Round, heartbeat.Sequence,
+		fmt.Sprintf("/%X.../", cmn.Fingerprint(heartbeat.Signature[:])))
 }
diff --git a/vendor/github.com/tendermint/tendermint/types/proposal.go b/vendor/github.com/tendermint/tendermint/types/proposal.go
index 52ce8756e8f591fb474e5c46dc4c8727191df4f0..81a5e2c33f5143e90f9009f93d79f209f88713bc 100644
--- a/vendor/github.com/tendermint/tendermint/types/proposal.go
+++ b/vendor/github.com/tendermint/tendermint/types/proposal.go
@@ -5,7 +5,7 @@ import (
 	"fmt"
 	"time"
 
-	"github.com/tendermint/tendermint/crypto"
+	cmn "github.com/tendermint/tendermint/libs/common"
 )
 
 var (
@@ -19,13 +19,13 @@ var (
 // to be considered valid. It may depend on votes from a previous round,
 // a so-called Proof-of-Lock (POL) round, as noted in the POLRound and POLBlockID.
 type Proposal struct {
-	Height           int64            `json:"height"`
-	Round            int              `json:"round"`
-	Timestamp        time.Time        `json:"timestamp"`
-	BlockPartsHeader PartSetHeader    `json:"block_parts_header"`
-	POLRound         int              `json:"pol_round"`    // -1 if null.
-	POLBlockID       BlockID          `json:"pol_block_id"` // zero if null.
-	Signature        crypto.Signature `json:"signature"`
+	Height           int64         `json:"height"`
+	Round            int           `json:"round"`
+	Timestamp        time.Time     `json:"timestamp"`
+	BlockPartsHeader PartSetHeader `json:"block_parts_header"`
+	POLRound         int           `json:"pol_round"`    // -1 if null.
+	POLBlockID       BlockID       `json:"pol_block_id"` // zero if null.
+	Signature        []byte        `json:"signature"`
 }
 
 // NewProposal returns a new Proposal.
@@ -43,9 +43,10 @@ func NewProposal(height int64, round int, blockPartsHeader PartSetHeader, polRou
 
 // String returns a string representation of the Proposal.
 func (p *Proposal) String() string {
-	return fmt.Sprintf("Proposal{%v/%v %v (%v,%v) %v @ %s}",
+	return fmt.Sprintf("Proposal{%v/%v %v (%v,%v) %X @ %s}",
 		p.Height, p.Round, p.BlockPartsHeader, p.POLRound,
-		p.POLBlockID, p.Signature, CanonicalTime(p.Timestamp))
+		p.POLBlockID,
+		cmn.Fingerprint(p.Signature), CanonicalTime(p.Timestamp))
 }
 
 // SignBytes returns the Proposal bytes for signing
diff --git a/vendor/github.com/tendermint/tendermint/types/protobuf.go b/vendor/github.com/tendermint/tendermint/types/protobuf.go
index 0e1e446dba4af2eb6b19e6748f03056425ebb990..01d4ebf0cbb3012dbd088aacdcd638ab5af47bd3 100644
--- a/vendor/github.com/tendermint/tendermint/types/protobuf.go
+++ b/vendor/github.com/tendermint/tendermint/types/protobuf.go
@@ -38,7 +38,7 @@ func (tm2pb) Header(header *Header) abci.Header {
 		ChainID: header.ChainID,
 		Height:  header.Height,
 
-		Time:     header.Time.Unix(),
+		Time:     header.Time,
 		NumTxs:   int32(header.NumTxs), // XXX: overflow
 		TotalTxs: header.TotalTxs,
 
@@ -50,6 +50,13 @@ func (tm2pb) Header(header *Header) abci.Header {
 	}
 }
 
+func (tm2pb) ValidatorWithoutPubKey(val *Validator) abci.Validator {
+	return abci.Validator{
+		Address: val.PubKey.Address(),
+		Power:   val.VotingPower,
+	}
+}
+
 // XXX: panics on unknown pubkey type
 func (tm2pb) Validator(val *Validator) abci.Validator {
 	return abci.Validator{
@@ -129,9 +136,9 @@ func (tm2pb) Evidence(ev Evidence, valSet *ValidatorSet, evTime time.Time) abci.
 
 	return abci.Evidence{
 		Type:             evType,
-		Validator:        TM2PB.Validator(val),
+		Validator:        TM2PB.ValidatorWithoutPubKey(val),
 		Height:           ev.Height(),
-		Time:             evTime.Unix(),
+		Time:             evTime,
 		TotalVotingPower: valSet.TotalVotingPower(),
 	}
 }
diff --git a/vendor/github.com/tendermint/tendermint/types/vote.go b/vendor/github.com/tendermint/tendermint/types/vote.go
index ed4ebd73e51c85f3d1806c27ce2e3d7e871681fa..9a6180d75567975f92959b814a3024e8ff51659f 100644
--- a/vendor/github.com/tendermint/tendermint/types/vote.go
+++ b/vendor/github.com/tendermint/tendermint/types/vote.go
@@ -61,14 +61,14 @@ type Address = cmn.HexBytes
 
 // Represents a prevote, precommit, or commit vote from validators for consensus.
 type Vote struct {
-	ValidatorAddress Address          `json:"validator_address"`
-	ValidatorIndex   int              `json:"validator_index"`
-	Height           int64            `json:"height"`
-	Round            int              `json:"round"`
-	Timestamp        time.Time        `json:"timestamp"`
-	Type             byte             `json:"type"`
-	BlockID          BlockID          `json:"block_id"` // zero if vote is nil.
-	Signature        crypto.Signature `json:"signature"`
+	ValidatorAddress Address   `json:"validator_address"`
+	ValidatorIndex   int       `json:"validator_index"`
+	Height           int64     `json:"height"`
+	Round            int       `json:"round"`
+	Timestamp        time.Time `json:"timestamp"`
+	Type             byte      `json:"type"`
+	BlockID          BlockID   `json:"block_id"` // zero if vote is nil.
+	Signature        []byte    `json:"signature"`
 }
 
 func (vote *Vote) SignBytes(chainID string) []byte {
@@ -98,10 +98,11 @@ func (vote *Vote) String() string {
 		cmn.PanicSanity("Unknown vote type")
 	}
 
-	return fmt.Sprintf("Vote{%v:%X %v/%02d/%v(%v) %X %v @ %s}",
+	return fmt.Sprintf("Vote{%v:%X %v/%02d/%v(%v) %X %X @ %s}",
 		vote.ValidatorIndex, cmn.Fingerprint(vote.ValidatorAddress),
 		vote.Height, vote.Round, vote.Type, typeString,
-		cmn.Fingerprint(vote.BlockID.Hash), vote.Signature,
+		cmn.Fingerprint(vote.BlockID.Hash),
+		cmn.Fingerprint(vote.Signature),
 		CanonicalTime(vote.Timestamp))
 }
 
diff --git a/vendor/github.com/tendermint/tendermint/types/vote_set.go b/vendor/github.com/tendermint/tendermint/types/vote_set.go
index c516810534863522cc01d4a9751f4e28d65d9930..36bf5ef7e3293a4963ab5bbcebb83cf19dc3bfd8 100644
--- a/vendor/github.com/tendermint/tendermint/types/vote_set.go
+++ b/vendor/github.com/tendermint/tendermint/types/vote_set.go
@@ -179,7 +179,7 @@ func (voteSet *VoteSet) addVote(vote *Vote) (added bool, err error) {
 
 	// If we already know of this vote, return false.
 	if existing, ok := voteSet.getVote(valIndex, blockKey); ok {
-		if existing.Signature.Equals(vote.Signature) {
+		if bytes.Equal(existing.Signature, vote.Signature) {
 			return false, nil // duplicate
 		}
 		return false, errors.Wrapf(ErrVoteNonDeterministicSignature, "Existing vote: %v; New vote: %v", existing, vote)
diff --git a/vendor/github.com/tendermint/tendermint/version/version.go b/vendor/github.com/tendermint/tendermint/version/version.go
index 85b1f19185a9eb66a1a0d700838ef7afd68ca82f..04880cfe0de35b5a548a9fb034cb14ae6ab9623e 100644
--- a/vendor/github.com/tendermint/tendermint/version/version.go
+++ b/vendor/github.com/tendermint/tendermint/version/version.go
@@ -3,14 +3,14 @@ package version
 // Version components
 const (
 	Maj = "0"
-	Min = "22"
-	Fix = "8"
+	Min = "23"
+	Fix = "0"
 )
 
 var (
 	// Version is the current version of Tendermint
 	// Must be a string because scripts like dist.sh read this file.
-	Version = "0.22.8"
+	Version = "0.23.0"
 
 	// GitCommit is the current HEAD set using ldflags.
 	GitCommit string
diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go
new file mode 100644
index 0000000000000000000000000000000000000000..bbb86efef55d97e1f21185a87c3140c0134ceef3
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go
@@ -0,0 +1,101 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD as specified in RFC 7539,
+// and its extended nonce variant XChaCha20-Poly1305.
+package chacha20poly1305 // import "golang.org/x/crypto/chacha20poly1305"
+
+import (
+	"crypto/cipher"
+	"encoding/binary"
+	"errors"
+)
+
+const (
+	// KeySize is the size of the key used by this AEAD, in bytes.
+	KeySize = 32
+
+	// NonceSize is the size of the nonce used with the standard variant of this
+	// AEAD, in bytes.
+	//
+	// Note that this is too short to be safely generated at random if the same
+	// key is reused more than 2³² times.
+	NonceSize = 12
+
+	// NonceSizeX is the size of the nonce used with the XChaCha20-Poly1305
+	// variant of this AEAD, in bytes.
+	NonceSizeX = 24
+)
+
+type chacha20poly1305 struct {
+	key [8]uint32
+}
+
+// New returns a ChaCha20-Poly1305 AEAD that uses the given 256-bit key.
+func New(key []byte) (cipher.AEAD, error) {
+	if len(key) != KeySize {
+		return nil, errors.New("chacha20poly1305: bad key length")
+	}
+	ret := new(chacha20poly1305)
+	ret.key[0] = binary.LittleEndian.Uint32(key[0:4])
+	ret.key[1] = binary.LittleEndian.Uint32(key[4:8])
+	ret.key[2] = binary.LittleEndian.Uint32(key[8:12])
+	ret.key[3] = binary.LittleEndian.Uint32(key[12:16])
+	ret.key[4] = binary.LittleEndian.Uint32(key[16:20])
+	ret.key[5] = binary.LittleEndian.Uint32(key[20:24])
+	ret.key[6] = binary.LittleEndian.Uint32(key[24:28])
+	ret.key[7] = binary.LittleEndian.Uint32(key[28:32])
+	return ret, nil
+}
+
+func (c *chacha20poly1305) NonceSize() int {
+	return NonceSize
+}
+
+func (c *chacha20poly1305) Overhead() int {
+	return 16
+}
+
+func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
+	if len(nonce) != NonceSize {
+		panic("chacha20poly1305: bad nonce length passed to Seal")
+	}
+
+	if uint64(len(plaintext)) > (1<<38)-64 {
+		panic("chacha20poly1305: plaintext too large")
+	}
+
+	return c.seal(dst, nonce, plaintext, additionalData)
+}
+
+var errOpen = errors.New("chacha20poly1305: message authentication failed")
+
+func (c *chacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+	if len(nonce) != NonceSize {
+		panic("chacha20poly1305: bad nonce length passed to Open")
+	}
+	if len(ciphertext) < 16 {
+		return nil, errOpen
+	}
+	if uint64(len(ciphertext)) > (1<<38)-48 {
+		panic("chacha20poly1305: ciphertext too large")
+	}
+
+	return c.open(dst, nonce, ciphertext, additionalData)
+}
+
+// sliceForAppend takes a slice and a requested number of bytes. It returns a
+// slice with the contents of the given slice followed by that many bytes and a
+// second slice that aliases into it and contains only the extra bytes. If the
+// original slice has sufficient capacity then no allocation is performed.
+func sliceForAppend(in []byte, n int) (head, tail []byte) {
+	if total := len(in) + n; cap(in) >= total {
+		head = in[:total]
+	} else {
+		head = make([]byte, total)
+		copy(head, in)
+	}
+	tail = head[len(in):]
+	return
+}
diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
new file mode 100644
index 0000000000000000000000000000000000000000..ec13d138806546eb2fdc74abbc8dc5c35f3977d5
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
@@ -0,0 +1,87 @@
+// Copyright 2016 The Go Authors. 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.7,amd64,!gccgo,!appengine
+
+package chacha20poly1305
+
+import (
+	"encoding/binary"
+
+	"golang.org/x/crypto/internal/subtle"
+	"golang.org/x/sys/cpu"
+)
+
+//go:noescape
+func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool
+
+//go:noescape
+func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)
+
+var (
+	useASM  = cpu.X86.HasSSSE3
+	useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2
+)
+
+// setupState writes a ChaCha20 input matrix to state. See
+// https://tools.ietf.org/html/rfc7539#section-2.3.
+func setupState(state *[16]uint32, key *[8]uint32, nonce []byte) {
+	state[0] = 0x61707865
+	state[1] = 0x3320646e
+	state[2] = 0x79622d32
+	state[3] = 0x6b206574
+
+	state[4] = key[0]
+	state[5] = key[1]
+	state[6] = key[2]
+	state[7] = key[3]
+	state[8] = key[4]
+	state[9] = key[5]
+	state[10] = key[6]
+	state[11] = key[7]
+
+	state[12] = 0
+	state[13] = binary.LittleEndian.Uint32(nonce[:4])
+	state[14] = binary.LittleEndian.Uint32(nonce[4:8])
+	state[15] = binary.LittleEndian.Uint32(nonce[8:12])
+}
+
+func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
+	if !useASM {
+		return c.sealGeneric(dst, nonce, plaintext, additionalData)
+	}
+
+	var state [16]uint32
+	setupState(&state, &c.key, nonce)
+
+	ret, out := sliceForAppend(dst, len(plaintext)+16)
+	if subtle.InexactOverlap(out, plaintext) {
+		panic("chacha20poly1305: invalid buffer overlap")
+	}
+	chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData)
+	return ret
+}
+
+func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+	if !useASM {
+		return c.openGeneric(dst, nonce, ciphertext, additionalData)
+	}
+
+	var state [16]uint32
+	setupState(&state, &c.key, nonce)
+
+	ciphertext = ciphertext[:len(ciphertext)-16]
+	ret, out := sliceForAppend(dst, len(ciphertext))
+	if subtle.InexactOverlap(out, ciphertext) {
+		panic("chacha20poly1305: invalid buffer overlap")
+	}
+	if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) {
+		for i := range out {
+			out[i] = 0
+		}
+		return nil, errOpen
+	}
+
+	return ret, nil
+}
diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s
new file mode 100644
index 0000000000000000000000000000000000000000..af76bbcc93f8c7608b3ce3e9c7fa3e76724b413a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s
@@ -0,0 +1,2695 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file was originally from https://golang.org/cl/24717 by Vlad Krasnov of CloudFlare.
+
+// +build go1.7,amd64,!gccgo,!appengine
+
+#include "textflag.h"
+// General register allocation
+#define oup DI
+#define inp SI
+#define inl BX
+#define adp CX // free to reuse, after we hash the additional data
+#define keyp R8 // free to reuse, when we copy the key to stack
+#define itr2 R9 // general iterator
+#define itr1 CX // general iterator
+#define acc0 R10
+#define acc1 R11
+#define acc2 R12
+#define t0 R13
+#define t1 R14
+#define t2 R15
+#define t3 R8
+// Register and stack allocation for the SSE code
+#define rStore (0*16)(BP)
+#define sStore (1*16)(BP)
+#define state1Store (2*16)(BP)
+#define state2Store (3*16)(BP)
+#define tmpStore (4*16)(BP)
+#define ctr0Store (5*16)(BP)
+#define ctr1Store (6*16)(BP)
+#define ctr2Store (7*16)(BP)
+#define ctr3Store (8*16)(BP)
+#define A0 X0
+#define A1 X1
+#define A2 X2
+#define B0 X3
+#define B1 X4
+#define B2 X5
+#define C0 X6
+#define C1 X7
+#define C2 X8
+#define D0 X9
+#define D1 X10
+#define D2 X11
+#define T0 X12
+#define T1 X13
+#define T2 X14
+#define T3 X15
+#define A3 T0
+#define B3 T1
+#define C3 T2
+#define D3 T3
+// Register and stack allocation for the AVX2 code
+#define rsStoreAVX2 (0*32)(BP)
+#define state1StoreAVX2 (1*32)(BP)
+#define state2StoreAVX2 (2*32)(BP)
+#define ctr0StoreAVX2 (3*32)(BP)
+#define ctr1StoreAVX2 (4*32)(BP)
+#define ctr2StoreAVX2 (5*32)(BP)
+#define ctr3StoreAVX2 (6*32)(BP)
+#define tmpStoreAVX2 (7*32)(BP) // 256 bytes on stack
+#define AA0 Y0
+#define AA1 Y5
+#define AA2 Y6
+#define AA3 Y7
+#define BB0 Y14
+#define BB1 Y9
+#define BB2 Y10
+#define BB3 Y11
+#define CC0 Y12
+#define CC1 Y13
+#define CC2 Y8
+#define CC3 Y15
+#define DD0 Y4
+#define DD1 Y1
+#define DD2 Y2
+#define DD3 Y3
+#define TT0 DD3
+#define TT1 AA3
+#define TT2 BB3
+#define TT3 CC3
+// ChaCha20 constants
+DATA ·chacha20Constants<>+0x00(SB)/4, $0x61707865
+DATA ·chacha20Constants<>+0x04(SB)/4, $0x3320646e
+DATA ·chacha20Constants<>+0x08(SB)/4, $0x79622d32
+DATA ·chacha20Constants<>+0x0c(SB)/4, $0x6b206574
+DATA ·chacha20Constants<>+0x10(SB)/4, $0x61707865
+DATA ·chacha20Constants<>+0x14(SB)/4, $0x3320646e
+DATA ·chacha20Constants<>+0x18(SB)/4, $0x79622d32
+DATA ·chacha20Constants<>+0x1c(SB)/4, $0x6b206574
+// <<< 16 with PSHUFB
+DATA ·rol16<>+0x00(SB)/8, $0x0504070601000302
+DATA ·rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A
+DATA ·rol16<>+0x10(SB)/8, $0x0504070601000302
+DATA ·rol16<>+0x18(SB)/8, $0x0D0C0F0E09080B0A
+// <<< 8 with PSHUFB
+DATA ·rol8<>+0x00(SB)/8, $0x0605040702010003
+DATA ·rol8<>+0x08(SB)/8, $0x0E0D0C0F0A09080B
+DATA ·rol8<>+0x10(SB)/8, $0x0605040702010003
+DATA ·rol8<>+0x18(SB)/8, $0x0E0D0C0F0A09080B
+
+DATA ·avx2InitMask<>+0x00(SB)/8, $0x0
+DATA ·avx2InitMask<>+0x08(SB)/8, $0x0
+DATA ·avx2InitMask<>+0x10(SB)/8, $0x1
+DATA ·avx2InitMask<>+0x18(SB)/8, $0x0
+
+DATA ·avx2IncMask<>+0x00(SB)/8, $0x2
+DATA ·avx2IncMask<>+0x08(SB)/8, $0x0
+DATA ·avx2IncMask<>+0x10(SB)/8, $0x2
+DATA ·avx2IncMask<>+0x18(SB)/8, $0x0
+// Poly1305 key clamp
+DATA ·polyClampMask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
+DATA ·polyClampMask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
+DATA ·polyClampMask<>+0x10(SB)/8, $0xFFFFFFFFFFFFFFFF
+DATA ·polyClampMask<>+0x18(SB)/8, $0xFFFFFFFFFFFFFFFF
+
+DATA ·sseIncMask<>+0x00(SB)/8, $0x1
+DATA ·sseIncMask<>+0x08(SB)/8, $0x0
+// To load/store the last < 16 bytes in a buffer
+DATA ·andMask<>+0x00(SB)/8, $0x00000000000000ff
+DATA ·andMask<>+0x08(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x10(SB)/8, $0x000000000000ffff
+DATA ·andMask<>+0x18(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x20(SB)/8, $0x0000000000ffffff
+DATA ·andMask<>+0x28(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x30(SB)/8, $0x00000000ffffffff
+DATA ·andMask<>+0x38(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x40(SB)/8, $0x000000ffffffffff
+DATA ·andMask<>+0x48(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x50(SB)/8, $0x0000ffffffffffff
+DATA ·andMask<>+0x58(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x60(SB)/8, $0x00ffffffffffffff
+DATA ·andMask<>+0x68(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x70(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0x78(SB)/8, $0x0000000000000000
+DATA ·andMask<>+0x80(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0x88(SB)/8, $0x00000000000000ff
+DATA ·andMask<>+0x90(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0x98(SB)/8, $0x000000000000ffff
+DATA ·andMask<>+0xa0(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0xa8(SB)/8, $0x0000000000ffffff
+DATA ·andMask<>+0xb0(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0xb8(SB)/8, $0x00000000ffffffff
+DATA ·andMask<>+0xc0(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0xc8(SB)/8, $0x000000ffffffffff
+DATA ·andMask<>+0xd0(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0xd8(SB)/8, $0x0000ffffffffffff
+DATA ·andMask<>+0xe0(SB)/8, $0xffffffffffffffff
+DATA ·andMask<>+0xe8(SB)/8, $0x00ffffffffffffff
+
+GLOBL ·chacha20Constants<>(SB), (NOPTR+RODATA), $32
+GLOBL ·rol16<>(SB), (NOPTR+RODATA), $32
+GLOBL ·rol8<>(SB), (NOPTR+RODATA), $32
+GLOBL ·sseIncMask<>(SB), (NOPTR+RODATA), $16
+GLOBL ·avx2IncMask<>(SB), (NOPTR+RODATA), $32
+GLOBL ·avx2InitMask<>(SB), (NOPTR+RODATA), $32
+GLOBL ·polyClampMask<>(SB), (NOPTR+RODATA), $32
+GLOBL ·andMask<>(SB), (NOPTR+RODATA), $240
+// No PALIGNR in Go ASM yet (but VPALIGNR is present).
+#define shiftB0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X3, X3
+#define shiftB1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x04 // PALIGNR $4, X4, X4
+#define shiftB2Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X5, X5
+#define shiftB3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X13, X13
+#define shiftC0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X6, X6
+#define shiftC1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x08 // PALIGNR $8, X7, X7
+#define shiftC2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc0; BYTE $0x08 // PALIGNR $8, X8, X8
+#define shiftC3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X14, X14
+#define shiftD0Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x0c // PALIGNR $12, X9, X9
+#define shiftD1Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x0c // PALIGNR $12, X10, X10
+#define shiftD2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X11, X11
+#define shiftD3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x0c // PALIGNR $12, X15, X15
+#define shiftB0Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X3, X3
+#define shiftB1Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x0c // PALIGNR $12, X4, X4
+#define shiftB2Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X5, X5
+#define shiftB3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X13, X13
+#define shiftC0Right shiftC0Left
+#define shiftC1Right shiftC1Left
+#define shiftC2Right shiftC2Left
+#define shiftC3Right shiftC3Left
+#define shiftD0Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x04 // PALIGNR $4, X9, X9
+#define shiftD1Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x04 // PALIGNR $4, X10, X10
+#define shiftD2Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X11, X11
+#define shiftD3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x04 // PALIGNR $4, X15, X15
+// Some macros
+#define chachaQR(A, B, C, D, T) \
+	PADDD B, A; PXOR A, D; PSHUFB ·rol16<>(SB), D                            \
+	PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $12, T; PSRLL $20, B; PXOR T, B \
+	PADDD B, A; PXOR A, D; PSHUFB ·rol8<>(SB), D                             \
+	PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $7, T; PSRLL $25, B; PXOR T, B
+
+#define chachaQR_AVX2(A, B, C, D, T) \
+	VPADDD B, A, A; VPXOR A, D, D; VPSHUFB ·rol16<>(SB), D, D                         \
+	VPADDD D, C, C; VPXOR C, B, B; VPSLLD $12, B, T; VPSRLD $20, B, B; VPXOR T, B, B \
+	VPADDD B, A, A; VPXOR A, D, D; VPSHUFB ·rol8<>(SB), D, D                          \
+	VPADDD D, C, C; VPXOR C, B, B; VPSLLD $7, B, T; VPSRLD $25, B, B; VPXOR T, B, B
+
+#define polyAdd(S) ADDQ S, acc0; ADCQ 8+S, acc1; ADCQ $1, acc2
+#define polyMulStage1 MOVQ (0*8)(BP), AX; MOVQ AX, t2; MULQ acc0; MOVQ AX, t0; MOVQ DX, t1; MOVQ (0*8)(BP), AX; MULQ acc1; IMULQ acc2, t2; ADDQ AX, t1; ADCQ DX, t2
+#define polyMulStage2 MOVQ (1*8)(BP), AX; MOVQ AX, t3; MULQ acc0; ADDQ AX, t1; ADCQ $0, DX; MOVQ DX, acc0; MOVQ (1*8)(BP), AX; MULQ acc1; ADDQ AX, t2; ADCQ $0, DX
+#define polyMulStage3 IMULQ acc2, t3; ADDQ acc0, t2; ADCQ DX, t3
+#define polyMulReduceStage MOVQ t0, acc0; MOVQ t1, acc1; MOVQ t2, acc2; ANDQ $3, acc2; MOVQ t2, t0; ANDQ $-4, t0; MOVQ t3, t1; SHRQ $2, t2:t3; SHRQ $2, t3; ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $0, acc2; ADDQ t2, acc0; ADCQ t3, acc1; ADCQ $0, acc2
+
+#define polyMulStage1_AVX2 MOVQ (0*8)(BP), DX; MOVQ DX, t2; MULXQ acc0, t0, t1; IMULQ acc2, t2; MULXQ acc1, AX, DX; ADDQ AX, t1; ADCQ DX, t2
+#define polyMulStage2_AVX2 MOVQ (1*8)(BP), DX; MULXQ acc0, acc0, AX; ADDQ acc0, t1; MULXQ acc1, acc1, t3; ADCQ acc1, t2; ADCQ $0, t3
+#define polyMulStage3_AVX2 IMULQ acc2, DX; ADDQ AX, t2; ADCQ DX, t3
+
+#define polyMul polyMulStage1; polyMulStage2; polyMulStage3; polyMulReduceStage
+#define polyMulAVX2 polyMulStage1_AVX2; polyMulStage2_AVX2; polyMulStage3_AVX2; polyMulReduceStage
+// ----------------------------------------------------------------------------
+TEXT polyHashADInternal<>(SB), NOSPLIT, $0
+	// adp points to beginning of additional data
+	// itr2 holds ad length
+	XORQ acc0, acc0
+	XORQ acc1, acc1
+	XORQ acc2, acc2
+	CMPQ itr2, $13
+	JNE  hashADLoop
+
+openFastTLSAD:
+	// Special treatment for the TLS case of 13 bytes
+	MOVQ (adp), acc0
+	MOVQ 5(adp), acc1
+	SHRQ $24, acc1
+	MOVQ $1, acc2
+	polyMul
+	RET
+
+hashADLoop:
+	// Hash in 16 byte chunks
+	CMPQ itr2, $16
+	JB   hashADTail
+	polyAdd(0(adp))
+	LEAQ (1*16)(adp), adp
+	SUBQ $16, itr2
+	polyMul
+	JMP  hashADLoop
+
+hashADTail:
+	CMPQ itr2, $0
+	JE   hashADDone
+
+	// Hash last < 16 byte tail
+	XORQ t0, t0
+	XORQ t1, t1
+	XORQ t2, t2
+	ADDQ itr2, adp
+
+hashADTailLoop:
+	SHLQ $8, t1:t0
+	SHLQ $8, t0
+	MOVB -1(adp), t2
+	XORQ t2, t0
+	DECQ adp
+	DECQ itr2
+	JNE  hashADTailLoop
+
+hashADTailFinish:
+	ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2
+	polyMul
+
+	// Finished AD
+hashADDone:
+	RET
+
+// ----------------------------------------------------------------------------
+// func chacha20Poly1305Open(dst, key, src, ad []byte) bool
+TEXT ·chacha20Poly1305Open(SB), 0, $288-97
+	// For aligned stack access
+	MOVQ SP, BP
+	ADDQ $32, BP
+	ANDQ $-32, BP
+	MOVQ dst+0(FP), oup
+	MOVQ key+24(FP), keyp
+	MOVQ src+48(FP), inp
+	MOVQ src_len+56(FP), inl
+	MOVQ ad+72(FP), adp
+
+	// Check for AVX2 support
+	CMPB ·useAVX2(SB), $1
+	JE   chacha20Poly1305Open_AVX2
+
+	// Special optimization, for very short buffers
+	CMPQ inl, $128
+	JBE  openSSE128 // About 16% faster
+
+	// For long buffers, prepare the poly key first
+	MOVOU ·chacha20Constants<>(SB), A0
+	MOVOU (1*16)(keyp), B0
+	MOVOU (2*16)(keyp), C0
+	MOVOU (3*16)(keyp), D0
+	MOVO  D0, T1
+
+	// Store state on stack for future use
+	MOVO B0, state1Store
+	MOVO C0, state2Store
+	MOVO D0, ctr3Store
+	MOVQ $10, itr2
+
+openSSEPreparePolyKey:
+	chachaQR(A0, B0, C0, D0, T0)
+	shiftB0Left;  shiftC0Left; shiftD0Left
+	chachaQR(A0, B0, C0, D0, T0)
+	shiftB0Right; shiftC0Right; shiftD0Right
+	DECQ          itr2
+	JNE           openSSEPreparePolyKey
+
+	// A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded
+	PADDL ·chacha20Constants<>(SB), A0; PADDL state1Store, B0
+
+	// Clamp and store the key
+	PAND ·polyClampMask<>(SB), A0
+	MOVO A0, rStore; MOVO B0, sStore
+
+	// Hash AAD
+	MOVQ ad_len+80(FP), itr2
+	CALL polyHashADInternal<>(SB)
+
+openSSEMainLoop:
+	CMPQ inl, $256
+	JB   openSSEMainLoopDone
+
+	// Load state, increment counter blocks
+	MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0
+	MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1
+	MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2
+	MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3
+
+	// Store counters
+	MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store
+
+	// There are 10 ChaCha20 iterations of 2QR each, so for 6 iterations we hash 2 blocks, and for the remaining 4 only 1 block - for a total of 16
+	MOVQ $4, itr1
+	MOVQ inp, itr2
+
+openSSEInternalLoop:
+	MOVO          C3, tmpStore
+	chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+	MOVO          tmpStore, C3
+	MOVO          C1, tmpStore
+	chachaQR(A3, B3, C3, D3, C1)
+	MOVO          tmpStore, C1
+	polyAdd(0(itr2))
+	shiftB0Left;  shiftB1Left; shiftB2Left; shiftB3Left
+	shiftC0Left;  shiftC1Left; shiftC2Left; shiftC3Left
+	shiftD0Left;  shiftD1Left; shiftD2Left; shiftD3Left
+	polyMulStage1
+	polyMulStage2
+	LEAQ          (2*8)(itr2), itr2
+	MOVO          C3, tmpStore
+	chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+	MOVO          tmpStore, C3
+	MOVO          C1, tmpStore
+	polyMulStage3
+	chachaQR(A3, B3, C3, D3, C1)
+	MOVO          tmpStore, C1
+	polyMulReduceStage
+	shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right
+	shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right
+	shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right
+	DECQ          itr1
+	JGE           openSSEInternalLoop
+
+	polyAdd(0(itr2))
+	polyMul
+	LEAQ (2*8)(itr2), itr2
+
+	CMPQ itr1, $-6
+	JG   openSSEInternalLoop
+
+	// Add in the state
+	PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3
+	PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3
+	PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3
+	PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3
+
+	// Load - xor - store
+	MOVO  D3, tmpStore
+	MOVOU (0*16)(inp), D3; PXOR D3, A0; MOVOU A0, (0*16)(oup)
+	MOVOU (1*16)(inp), D3; PXOR D3, B0; MOVOU B0, (1*16)(oup)
+	MOVOU (2*16)(inp), D3; PXOR D3, C0; MOVOU C0, (2*16)(oup)
+	MOVOU (3*16)(inp), D3; PXOR D3, D0; MOVOU D0, (3*16)(oup)
+	MOVOU (4*16)(inp), D0; PXOR D0, A1; MOVOU A1, (4*16)(oup)
+	MOVOU (5*16)(inp), D0; PXOR D0, B1; MOVOU B1, (5*16)(oup)
+	MOVOU (6*16)(inp), D0; PXOR D0, C1; MOVOU C1, (6*16)(oup)
+	MOVOU (7*16)(inp), D0; PXOR D0, D1; MOVOU D1, (7*16)(oup)
+	MOVOU (8*16)(inp), D0; PXOR D0, A2; MOVOU A2, (8*16)(oup)
+	MOVOU (9*16)(inp), D0; PXOR D0, B2; MOVOU B2, (9*16)(oup)
+	MOVOU (10*16)(inp), D0; PXOR D0, C2; MOVOU C2, (10*16)(oup)
+	MOVOU (11*16)(inp), D0; PXOR D0, D2; MOVOU D2, (11*16)(oup)
+	MOVOU (12*16)(inp), D0; PXOR D0, A3; MOVOU A3, (12*16)(oup)
+	MOVOU (13*16)(inp), D0; PXOR D0, B3; MOVOU B3, (13*16)(oup)
+	MOVOU (14*16)(inp), D0; PXOR D0, C3; MOVOU C3, (14*16)(oup)
+	MOVOU (15*16)(inp), D0; PXOR tmpStore, D0; MOVOU D0, (15*16)(oup)
+	LEAQ  256(inp), inp
+	LEAQ  256(oup), oup
+	SUBQ  $256, inl
+	JMP   openSSEMainLoop
+
+openSSEMainLoopDone:
+	// Handle the various tail sizes efficiently
+	TESTQ inl, inl
+	JE    openSSEFinalize
+	CMPQ  inl, $64
+	JBE   openSSETail64
+	CMPQ  inl, $128
+	JBE   openSSETail128
+	CMPQ  inl, $192
+	JBE   openSSETail192
+	JMP   openSSETail256
+
+openSSEFinalize:
+	// Hash in the PT, AAD lengths
+	ADDQ ad_len+80(FP), acc0; ADCQ src_len+56(FP), acc1; ADCQ $1, acc2
+	polyMul
+
+	// Final reduce
+	MOVQ    acc0, t0
+	MOVQ    acc1, t1
+	MOVQ    acc2, t2
+	SUBQ    $-5, acc0
+	SBBQ    $-1, acc1
+	SBBQ    $3, acc2
+	CMOVQCS t0, acc0
+	CMOVQCS t1, acc1
+	CMOVQCS t2, acc2
+
+	// Add in the "s" part of the key
+	ADDQ 0+sStore, acc0
+	ADCQ 8+sStore, acc1
+
+	// Finally, constant time compare to the tag at the end of the message
+	XORQ    AX, AX
+	MOVQ    $1, DX
+	XORQ    (0*8)(inp), acc0
+	XORQ    (1*8)(inp), acc1
+	ORQ     acc1, acc0
+	CMOVQEQ DX, AX
+
+	// Return true iff tags are equal
+	MOVB AX, ret+96(FP)
+	RET
+
+// ----------------------------------------------------------------------------
+// Special optimization for buffers smaller than 129 bytes
+openSSE128:
+	// For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks
+	MOVOU ·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0
+	MOVO  A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1
+	MOVO  A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2
+	MOVO  B0, T1; MOVO C0, T2; MOVO D1, T3
+	MOVQ  $10, itr2
+
+openSSE128InnerCipherLoop:
+	chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+	shiftB0Left;  shiftB1Left; shiftB2Left
+	shiftC0Left;  shiftC1Left; shiftC2Left
+	shiftD0Left;  shiftD1Left; shiftD2Left
+	chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+	shiftB0Right; shiftB1Right; shiftB2Right
+	shiftC0Right; shiftC1Right; shiftC2Right
+	shiftD0Right; shiftD1Right; shiftD2Right
+	DECQ          itr2
+	JNE           openSSE128InnerCipherLoop
+
+	// A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded
+	PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2
+	PADDL T1, B0; PADDL T1, B1; PADDL T1, B2
+	PADDL T2, C1; PADDL T2, C2
+	PADDL T3, D1; PADDL ·sseIncMask<>(SB), T3; PADDL T3, D2
+
+	// Clamp and store the key
+	PAND  ·polyClampMask<>(SB), A0
+	MOVOU A0, rStore; MOVOU B0, sStore
+
+	// Hash
+	MOVQ ad_len+80(FP), itr2
+	CALL polyHashADInternal<>(SB)
+
+openSSE128Open:
+	CMPQ inl, $16
+	JB   openSSETail16
+	SUBQ $16, inl
+
+	// Load for hashing
+	polyAdd(0(inp))
+
+	// Load for decryption
+	MOVOU (inp), T0; PXOR T0, A1; MOVOU A1, (oup)
+	LEAQ  (1*16)(inp), inp
+	LEAQ  (1*16)(oup), oup
+	polyMul
+
+	// Shift the stream "left"
+	MOVO B1, A1
+	MOVO C1, B1
+	MOVO D1, C1
+	MOVO A2, D1
+	MOVO B2, A2
+	MOVO C2, B2
+	MOVO D2, C2
+	JMP  openSSE128Open
+
+openSSETail16:
+	TESTQ inl, inl
+	JE    openSSEFinalize
+
+	// We can safely load the CT from the end, because it is padded with the MAC
+	MOVQ   inl, itr2
+	SHLQ   $4, itr2
+	LEAQ   ·andMask<>(SB), t0
+	MOVOU  (inp), T0
+	ADDQ   inl, inp
+	PAND   -16(t0)(itr2*1), T0
+	MOVO   T0, 0+tmpStore
+	MOVQ   T0, t0
+	MOVQ   8+tmpStore, t1
+	PXOR   A1, T0
+
+	// We can only store one byte at a time, since plaintext can be shorter than 16 bytes
+openSSETail16Store:
+	MOVQ T0, t3
+	MOVB t3, (oup)
+	PSRLDQ $1, T0
+	INCQ   oup
+	DECQ   inl
+	JNE    openSSETail16Store
+	ADDQ   t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2
+	polyMul
+	JMP    openSSEFinalize
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 64 bytes of ciphertext
+openSSETail64:
+	// Need to decrypt up to 64 bytes - prepare single block
+	MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store
+	XORQ itr2, itr2
+	MOVQ inl, itr1
+	CMPQ itr1, $16
+	JB   openSSETail64LoopB
+
+openSSETail64LoopA:
+	// Perform ChaCha rounds, while hashing the remaining input
+	polyAdd(0(inp)(itr2*1))
+	polyMul
+	SUBQ $16, itr1
+
+openSSETail64LoopB:
+	ADDQ          $16, itr2
+	chachaQR(A0, B0, C0, D0, T0)
+	shiftB0Left;  shiftC0Left; shiftD0Left
+	chachaQR(A0, B0, C0, D0, T0)
+	shiftB0Right; shiftC0Right; shiftD0Right
+
+	CMPQ itr1, $16
+	JAE  openSSETail64LoopA
+
+	CMPQ itr2, $160
+	JNE  openSSETail64LoopB
+
+	PADDL ·chacha20Constants<>(SB), A0; PADDL state1Store, B0; PADDL state2Store, C0; PADDL ctr0Store, D0
+
+openSSETail64DecLoop:
+	CMPQ  inl, $16
+	JB    openSSETail64DecLoopDone
+	SUBQ  $16, inl
+	MOVOU (inp), T0
+	PXOR  T0, A0
+	MOVOU A0, (oup)
+	LEAQ  16(inp), inp
+	LEAQ  16(oup), oup
+	MOVO  B0, A0
+	MOVO  C0, B0
+	MOVO  D0, C0
+	JMP   openSSETail64DecLoop
+
+openSSETail64DecLoopDone:
+	MOVO A0, A1
+	JMP  openSSETail16
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 128 bytes of ciphertext
+openSSETail128:
+	// Need to decrypt up to 128 bytes - prepare two blocks
+	MOVO ·chacha20Constants<>(SB), A1; MOVO state1Store, B1; MOVO state2Store, C1; MOVO ctr3Store, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr0Store
+	MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr1Store
+	XORQ itr2, itr2
+	MOVQ inl, itr1
+	ANDQ $-16, itr1
+
+openSSETail128LoopA:
+	// Perform ChaCha rounds, while hashing the remaining input
+	polyAdd(0(inp)(itr2*1))
+	polyMul
+
+openSSETail128LoopB:
+	ADDQ          $16, itr2
+	chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0)
+	shiftB0Left;  shiftC0Left; shiftD0Left
+	shiftB1Left;  shiftC1Left; shiftD1Left
+	chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0)
+	shiftB0Right; shiftC0Right; shiftD0Right
+	shiftB1Right; shiftC1Right; shiftD1Right
+
+	CMPQ itr2, itr1
+	JB   openSSETail128LoopA
+
+	CMPQ itr2, $160
+	JNE  openSSETail128LoopB
+
+	PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1
+	PADDL state1Store, B0; PADDL state1Store, B1
+	PADDL state2Store, C0; PADDL state2Store, C1
+	PADDL ctr1Store, D0; PADDL ctr0Store, D1
+
+	MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3
+	PXOR  T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1
+	MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup)
+
+	SUBQ $64, inl
+	LEAQ 64(inp), inp
+	LEAQ 64(oup), oup
+	JMP  openSSETail64DecLoop
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 192 bytes of ciphertext
+openSSETail192:
+	// Need to decrypt up to 192 bytes - prepare three blocks
+	MOVO ·chacha20Constants<>(SB), A2; MOVO state1Store, B2; MOVO state2Store, C2; MOVO ctr3Store, D2; PADDL ·sseIncMask<>(SB), D2; MOVO D2, ctr0Store
+	MOVO A2, A1; MOVO B2, B1; MOVO C2, C1; MOVO D2, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store
+	MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr2Store
+
+	MOVQ    inl, itr1
+	MOVQ    $160, itr2
+	CMPQ    itr1, $160
+	CMOVQGT itr2, itr1
+	ANDQ    $-16, itr1
+	XORQ    itr2, itr2
+
+openSSLTail192LoopA:
+	// Perform ChaCha rounds, while hashing the remaining input
+	polyAdd(0(inp)(itr2*1))
+	polyMul
+
+openSSLTail192LoopB:
+	ADDQ         $16, itr2
+	chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+	shiftB0Left; shiftC0Left; shiftD0Left
+	shiftB1Left; shiftC1Left; shiftD1Left
+	shiftB2Left; shiftC2Left; shiftD2Left
+
+	chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+	shiftB0Right; shiftC0Right; shiftD0Right
+	shiftB1Right; shiftC1Right; shiftD1Right
+	shiftB2Right; shiftC2Right; shiftD2Right
+
+	CMPQ itr2, itr1
+	JB   openSSLTail192LoopA
+
+	CMPQ itr2, $160
+	JNE  openSSLTail192LoopB
+
+	CMPQ inl, $176
+	JB   openSSLTail192Store
+
+	polyAdd(160(inp))
+	polyMul
+
+	CMPQ inl, $192
+	JB   openSSLTail192Store
+
+	polyAdd(176(inp))
+	polyMul
+
+openSSLTail192Store:
+	PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2
+	PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2
+	PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2
+	PADDL ctr2Store, D0; PADDL ctr1Store, D1; PADDL ctr0Store, D2
+
+	MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3
+	PXOR  T0, A2; PXOR T1, B2; PXOR T2, C2; PXOR T3, D2
+	MOVOU A2, (0*16)(oup); MOVOU B2, (1*16)(oup); MOVOU C2, (2*16)(oup); MOVOU D2, (3*16)(oup)
+
+	MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3
+	PXOR  T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1
+	MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup)
+
+	SUBQ $128, inl
+	LEAQ 128(inp), inp
+	LEAQ 128(oup), oup
+	JMP  openSSETail64DecLoop
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 256 bytes of ciphertext
+openSSETail256:
+	// Need to decrypt up to 256 bytes - prepare four blocks
+	MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0
+	MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1
+	MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2
+	MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3
+
+	// Store counters
+	MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store
+	XORQ itr2, itr2
+
+openSSETail256Loop:
+	// This loop inteleaves 8 ChaCha quarter rounds with 1 poly multiplication
+	polyAdd(0(inp)(itr2*1))
+	MOVO          C3, tmpStore
+	chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+	MOVO          tmpStore, C3
+	MOVO          C1, tmpStore
+	chachaQR(A3, B3, C3, D3, C1)
+	MOVO          tmpStore, C1
+	shiftB0Left;  shiftB1Left; shiftB2Left; shiftB3Left
+	shiftC0Left;  shiftC1Left; shiftC2Left; shiftC3Left
+	shiftD0Left;  shiftD1Left; shiftD2Left; shiftD3Left
+	polyMulStage1
+	polyMulStage2
+	MOVO          C3, tmpStore
+	chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+	MOVO          tmpStore, C3
+	MOVO          C1, tmpStore
+	chachaQR(A3, B3, C3, D3, C1)
+	MOVO          tmpStore, C1
+	polyMulStage3
+	polyMulReduceStage
+	shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right
+	shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right
+	shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right
+	ADDQ          $2*8, itr2
+	CMPQ          itr2, $160
+	JB            openSSETail256Loop
+	MOVQ          inl, itr1
+	ANDQ          $-16, itr1
+
+openSSETail256HashLoop:
+	polyAdd(0(inp)(itr2*1))
+	polyMul
+	ADDQ $2*8, itr2
+	CMPQ itr2, itr1
+	JB   openSSETail256HashLoop
+
+	// Add in the state
+	PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3
+	PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3
+	PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3
+	PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3
+	MOVO  D3, tmpStore
+
+	// Load - xor - store
+	MOVOU (0*16)(inp), D3; PXOR D3, A0
+	MOVOU (1*16)(inp), D3; PXOR D3, B0
+	MOVOU (2*16)(inp), D3; PXOR D3, C0
+	MOVOU (3*16)(inp), D3; PXOR D3, D0
+	MOVOU A0, (0*16)(oup)
+	MOVOU B0, (1*16)(oup)
+	MOVOU C0, (2*16)(oup)
+	MOVOU D0, (3*16)(oup)
+	MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0
+	PXOR  A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1
+	MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup)
+	MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0
+	PXOR  A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2
+	MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup)
+	LEAQ  192(inp), inp
+	LEAQ  192(oup), oup
+	SUBQ  $192, inl
+	MOVO  A3, A0
+	MOVO  B3, B0
+	MOVO  C3, C0
+	MOVO  tmpStore, D0
+
+	JMP openSSETail64DecLoop
+
+// ----------------------------------------------------------------------------
+// ------------------------- AVX2 Code ----------------------------------------
+chacha20Poly1305Open_AVX2:
+	VZEROUPPER
+	VMOVDQU ·chacha20Constants<>(SB), AA0
+	BYTE    $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14
+	BYTE    $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12
+	BYTE    $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4
+	VPADDD  ·avx2InitMask<>(SB), DD0, DD0
+
+	// Special optimization, for very short buffers
+	CMPQ inl, $192
+	JBE  openAVX2192
+	CMPQ inl, $320
+	JBE  openAVX2320
+
+	// For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream
+	VMOVDQA BB0, state1StoreAVX2
+	VMOVDQA CC0, state2StoreAVX2
+	VMOVDQA DD0, ctr3StoreAVX2
+	MOVQ    $10, itr2
+
+openAVX2PreparePolyKey:
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0)
+	VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0)
+	VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0
+	DECQ     itr2
+	JNE      openAVX2PreparePolyKey
+
+	VPADDD ·chacha20Constants<>(SB), AA0, AA0
+	VPADDD state1StoreAVX2, BB0, BB0
+	VPADDD state2StoreAVX2, CC0, CC0
+	VPADDD ctr3StoreAVX2, DD0, DD0
+
+	VPERM2I128 $0x02, AA0, BB0, TT0
+
+	// Clamp and store poly key
+	VPAND   ·polyClampMask<>(SB), TT0, TT0
+	VMOVDQA TT0, rsStoreAVX2
+
+	// Stream for the first 64 bytes
+	VPERM2I128 $0x13, AA0, BB0, AA0
+	VPERM2I128 $0x13, CC0, DD0, BB0
+
+	// Hash AD + first 64 bytes
+	MOVQ ad_len+80(FP), itr2
+	CALL polyHashADInternal<>(SB)
+	XORQ itr1, itr1
+
+openAVX2InitialHash64:
+	polyAdd(0(inp)(itr1*1))
+	polyMulAVX2
+	ADDQ $16, itr1
+	CMPQ itr1, $64
+	JNE  openAVX2InitialHash64
+
+	// Decrypt the first 64 bytes
+	VPXOR   (0*32)(inp), AA0, AA0
+	VPXOR   (1*32)(inp), BB0, BB0
+	VMOVDQU AA0, (0*32)(oup)
+	VMOVDQU BB0, (1*32)(oup)
+	LEAQ    (2*32)(inp), inp
+	LEAQ    (2*32)(oup), oup
+	SUBQ    $64, inl
+
+openAVX2MainLoop:
+	CMPQ inl, $512
+	JB   openAVX2MainLoopDone
+
+	// Load state, increment counter blocks, store the incremented counters
+	VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3
+	VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3
+	VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3
+	VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3
+	VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2
+	XORQ    itr1, itr1
+
+openAVX2InternalLoop:
+	// Lets just say this spaghetti loop interleaves 2 quarter rounds with 3 poly multiplications
+	// Effectively per 512 bytes of stream we hash 480 bytes of ciphertext
+	polyAdd(0*8(inp)(itr1*1))
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	polyMulStage1_AVX2
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	VPSHUFB  ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+	polyMulStage2_AVX2
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	polyMulStage3_AVX2
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+	polyMulReduceStage
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	VPSHUFB  ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+	polyAdd(2*8(inp)(itr1*1))
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	polyMulStage1_AVX2
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+	polyMulStage2_AVX2
+	VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+	VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	polyMulStage3_AVX2
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	VPSHUFB  ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+	polyMulReduceStage
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	polyAdd(4*8(inp)(itr1*1))
+	LEAQ     (6*8)(itr1), itr1
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+	polyMulStage1_AVX2
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	polyMulStage2_AVX2
+	VPSHUFB  ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	polyMulStage3_AVX2
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+	polyMulReduceStage
+	VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+	VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3
+	CMPQ     itr1, $480
+	JNE      openAVX2InternalLoop
+
+	VPADDD  ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3
+	VPADDD  state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3
+	VPADDD  state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3
+	VPADDD  ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3
+	VMOVDQA CC3, tmpStoreAVX2
+
+	// We only hashed 480 of the 512 bytes available - hash the remaining 32 here
+	polyAdd(480(inp))
+	polyMulAVX2
+	VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0
+	VPXOR      (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0
+	VMOVDQU    CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup)
+	VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0
+	VPXOR      (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0
+	VMOVDQU    AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup)
+
+	// and here
+	polyAdd(496(inp))
+	polyMulAVX2
+	VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0
+	VPXOR      (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0
+	VMOVDQU    AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup)
+	VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0
+	VPXOR      (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0
+	VMOVDQU    AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup)
+	LEAQ       (32*16)(inp), inp
+	LEAQ       (32*16)(oup), oup
+	SUBQ       $(32*16), inl
+	JMP        openAVX2MainLoop
+
+openAVX2MainLoopDone:
+	// Handle the various tail sizes efficiently
+	TESTQ inl, inl
+	JE    openSSEFinalize
+	CMPQ  inl, $128
+	JBE   openAVX2Tail128
+	CMPQ  inl, $256
+	JBE   openAVX2Tail256
+	CMPQ  inl, $384
+	JBE   openAVX2Tail384
+	JMP   openAVX2Tail512
+
+// ----------------------------------------------------------------------------
+// Special optimization for buffers smaller than 193 bytes
+openAVX2192:
+	// For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks
+	VMOVDQA AA0, AA1
+	VMOVDQA BB0, BB1
+	VMOVDQA CC0, CC1
+	VPADDD  ·avx2IncMask<>(SB), DD0, DD1
+	VMOVDQA AA0, AA2
+	VMOVDQA BB0, BB2
+	VMOVDQA CC0, CC2
+	VMOVDQA DD0, DD2
+	VMOVDQA DD1, TT3
+	MOVQ    $10, itr2
+
+openAVX2192InnerCipherLoop:
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+	VPALIGNR   $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1
+	VPALIGNR   $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+	VPALIGNR   $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+	VPALIGNR   $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1
+	VPALIGNR   $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+	VPALIGNR   $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1
+	DECQ       itr2
+	JNE        openAVX2192InnerCipherLoop
+	VPADDD     AA2, AA0, AA0; VPADDD AA2, AA1, AA1
+	VPADDD     BB2, BB0, BB0; VPADDD BB2, BB1, BB1
+	VPADDD     CC2, CC0, CC0; VPADDD CC2, CC1, CC1
+	VPADDD     DD2, DD0, DD0; VPADDD TT3, DD1, DD1
+	VPERM2I128 $0x02, AA0, BB0, TT0
+
+	// Clamp and store poly key
+	VPAND   ·polyClampMask<>(SB), TT0, TT0
+	VMOVDQA TT0, rsStoreAVX2
+
+	// Stream for up to 192 bytes
+	VPERM2I128 $0x13, AA0, BB0, AA0
+	VPERM2I128 $0x13, CC0, DD0, BB0
+	VPERM2I128 $0x02, AA1, BB1, CC0
+	VPERM2I128 $0x02, CC1, DD1, DD0
+	VPERM2I128 $0x13, AA1, BB1, AA1
+	VPERM2I128 $0x13, CC1, DD1, BB1
+
+openAVX2ShortOpen:
+	// Hash
+	MOVQ ad_len+80(FP), itr2
+	CALL polyHashADInternal<>(SB)
+
+openAVX2ShortOpenLoop:
+	CMPQ inl, $32
+	JB   openAVX2ShortTail32
+	SUBQ $32, inl
+
+	// Load for hashing
+	polyAdd(0*8(inp))
+	polyMulAVX2
+	polyAdd(2*8(inp))
+	polyMulAVX2
+
+	// Load for decryption
+	VPXOR   (inp), AA0, AA0
+	VMOVDQU AA0, (oup)
+	LEAQ    (1*32)(inp), inp
+	LEAQ    (1*32)(oup), oup
+
+	// Shift stream left
+	VMOVDQA BB0, AA0
+	VMOVDQA CC0, BB0
+	VMOVDQA DD0, CC0
+	VMOVDQA AA1, DD0
+	VMOVDQA BB1, AA1
+	VMOVDQA CC1, BB1
+	VMOVDQA DD1, CC1
+	VMOVDQA AA2, DD1
+	VMOVDQA BB2, AA2
+	JMP     openAVX2ShortOpenLoop
+
+openAVX2ShortTail32:
+	CMPQ    inl, $16
+	VMOVDQA A0, A1
+	JB      openAVX2ShortDone
+
+	SUBQ $16, inl
+
+	// Load for hashing
+	polyAdd(0*8(inp))
+	polyMulAVX2
+
+	// Load for decryption
+	VPXOR      (inp), A0, T0
+	VMOVDQU    T0, (oup)
+	LEAQ       (1*16)(inp), inp
+	LEAQ       (1*16)(oup), oup
+	VPERM2I128 $0x11, AA0, AA0, AA0
+	VMOVDQA    A0, A1
+
+openAVX2ShortDone:
+	VZEROUPPER
+	JMP openSSETail16
+
+// ----------------------------------------------------------------------------
+// Special optimization for buffers smaller than 321 bytes
+openAVX2320:
+	// For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks
+	VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD ·avx2IncMask<>(SB), DD0, DD1
+	VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD ·avx2IncMask<>(SB), DD1, DD2
+	VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3
+	MOVQ    $10, itr2
+
+openAVX2320InnerCipherLoop:
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+	VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+	VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+	VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+	VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2
+	DECQ     itr2
+	JNE      openAVX2320InnerCipherLoop
+
+	VMOVDQA ·chacha20Constants<>(SB), TT0
+	VPADDD  TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2
+	VPADDD  TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2
+	VPADDD  TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2
+	VMOVDQA ·avx2IncMask<>(SB), TT0
+	VPADDD  TT3, DD0, DD0; VPADDD TT0, TT3, TT3
+	VPADDD  TT3, DD1, DD1; VPADDD TT0, TT3, TT3
+	VPADDD  TT3, DD2, DD2
+
+	// Clamp and store poly key
+	VPERM2I128 $0x02, AA0, BB0, TT0
+	VPAND      ·polyClampMask<>(SB), TT0, TT0
+	VMOVDQA    TT0, rsStoreAVX2
+
+	// Stream for up to 320 bytes
+	VPERM2I128 $0x13, AA0, BB0, AA0
+	VPERM2I128 $0x13, CC0, DD0, BB0
+	VPERM2I128 $0x02, AA1, BB1, CC0
+	VPERM2I128 $0x02, CC1, DD1, DD0
+	VPERM2I128 $0x13, AA1, BB1, AA1
+	VPERM2I128 $0x13, CC1, DD1, BB1
+	VPERM2I128 $0x02, AA2, BB2, CC1
+	VPERM2I128 $0x02, CC2, DD2, DD1
+	VPERM2I128 $0x13, AA2, BB2, AA2
+	VPERM2I128 $0x13, CC2, DD2, BB2
+	JMP        openAVX2ShortOpen
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 128 bytes of ciphertext
+openAVX2Tail128:
+	// Need to decrypt up to 128 bytes - prepare two blocks
+	VMOVDQA ·chacha20Constants<>(SB), AA1
+	VMOVDQA state1StoreAVX2, BB1
+	VMOVDQA state2StoreAVX2, CC1
+	VMOVDQA ctr3StoreAVX2, DD1
+	VPADDD  ·avx2IncMask<>(SB), DD1, DD1
+	VMOVDQA DD1, DD0
+
+	XORQ  itr2, itr2
+	MOVQ  inl, itr1
+	ANDQ  $-16, itr1
+	TESTQ itr1, itr1
+	JE    openAVX2Tail128LoopB
+
+openAVX2Tail128LoopA:
+	// Perform ChaCha rounds, while hashing the remaining input
+	polyAdd(0(inp)(itr2*1))
+	polyMulAVX2
+
+openAVX2Tail128LoopB:
+	ADDQ     $16, itr2
+	chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+	VPALIGNR $4, BB1, BB1, BB1
+	VPALIGNR $8, CC1, CC1, CC1
+	VPALIGNR $12, DD1, DD1, DD1
+	chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+	VPALIGNR $12, BB1, BB1, BB1
+	VPALIGNR $8, CC1, CC1, CC1
+	VPALIGNR $4, DD1, DD1, DD1
+	CMPQ     itr2, itr1
+	JB       openAVX2Tail128LoopA
+	CMPQ     itr2, $160
+	JNE      openAVX2Tail128LoopB
+
+	VPADDD     ·chacha20Constants<>(SB), AA1, AA1
+	VPADDD     state1StoreAVX2, BB1, BB1
+	VPADDD     state2StoreAVX2, CC1, CC1
+	VPADDD     DD0, DD1, DD1
+	VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0
+
+openAVX2TailLoop:
+	CMPQ inl, $32
+	JB   openAVX2Tail
+	SUBQ $32, inl
+
+	// Load for decryption
+	VPXOR   (inp), AA0, AA0
+	VMOVDQU AA0, (oup)
+	LEAQ    (1*32)(inp), inp
+	LEAQ    (1*32)(oup), oup
+	VMOVDQA BB0, AA0
+	VMOVDQA CC0, BB0
+	VMOVDQA DD0, CC0
+	JMP     openAVX2TailLoop
+
+openAVX2Tail:
+	CMPQ    inl, $16
+	VMOVDQA A0, A1
+	JB      openAVX2TailDone
+	SUBQ    $16, inl
+
+	// Load for decryption
+	VPXOR      (inp), A0, T0
+	VMOVDQU    T0, (oup)
+	LEAQ       (1*16)(inp), inp
+	LEAQ       (1*16)(oup), oup
+	VPERM2I128 $0x11, AA0, AA0, AA0
+	VMOVDQA    A0, A1
+
+openAVX2TailDone:
+	VZEROUPPER
+	JMP openSSETail16
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 256 bytes of ciphertext
+openAVX2Tail256:
+	// Need to decrypt up to 256 bytes - prepare four blocks
+	VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1
+	VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1
+	VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1
+	VMOVDQA ctr3StoreAVX2, DD0
+	VPADDD  ·avx2IncMask<>(SB), DD0, DD0
+	VPADDD  ·avx2IncMask<>(SB), DD0, DD1
+	VMOVDQA DD0, TT1
+	VMOVDQA DD1, TT2
+
+	// Compute the number of iterations that will hash data
+	MOVQ    inl, tmpStoreAVX2
+	MOVQ    inl, itr1
+	SUBQ    $128, itr1
+	SHRQ    $4, itr1
+	MOVQ    $10, itr2
+	CMPQ    itr1, $10
+	CMOVQGT itr2, itr1
+	MOVQ    inp, inl
+	XORQ    itr2, itr2
+
+openAVX2Tail256LoopA:
+	polyAdd(0(inl))
+	polyMulAVX2
+	LEAQ 16(inl), inl
+
+	// Perform ChaCha rounds, while hashing the remaining input
+openAVX2Tail256LoopB:
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+	VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+	VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1
+	INCQ     itr2
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+	VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+	VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1
+	CMPQ     itr2, itr1
+	JB       openAVX2Tail256LoopA
+
+	CMPQ itr2, $10
+	JNE  openAVX2Tail256LoopB
+
+	MOVQ inl, itr2
+	SUBQ inp, inl
+	MOVQ inl, itr1
+	MOVQ tmpStoreAVX2, inl
+
+	// Hash the remainder of data (if any)
+openAVX2Tail256Hash:
+	ADDQ $16, itr1
+	CMPQ itr1, inl
+	JGT  openAVX2Tail256HashEnd
+	polyAdd (0(itr2))
+	polyMulAVX2
+	LEAQ 16(itr2), itr2
+	JMP  openAVX2Tail256Hash
+
+// Store 128 bytes safely, then go to store loop
+openAVX2Tail256HashEnd:
+	VPADDD     ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1
+	VPADDD     state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1
+	VPADDD     state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1
+	VPADDD     TT1, DD0, DD0; VPADDD TT2, DD1, DD1
+	VPERM2I128 $0x02, AA0, BB0, AA2; VPERM2I128 $0x02, CC0, DD0, BB2; VPERM2I128 $0x13, AA0, BB0, CC2; VPERM2I128 $0x13, CC0, DD0, DD2
+	VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0
+
+	VPXOR   (0*32)(inp), AA2, AA2; VPXOR (1*32)(inp), BB2, BB2; VPXOR (2*32)(inp), CC2, CC2; VPXOR (3*32)(inp), DD2, DD2
+	VMOVDQU AA2, (0*32)(oup); VMOVDQU BB2, (1*32)(oup); VMOVDQU CC2, (2*32)(oup); VMOVDQU DD2, (3*32)(oup)
+	LEAQ    (4*32)(inp), inp
+	LEAQ    (4*32)(oup), oup
+	SUBQ    $4*32, inl
+
+	JMP openAVX2TailLoop
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 384 bytes of ciphertext
+openAVX2Tail384:
+	// Need to decrypt up to 384 bytes - prepare six blocks
+	VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2
+	VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2
+	VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2
+	VMOVDQA ctr3StoreAVX2, DD0
+	VPADDD  ·avx2IncMask<>(SB), DD0, DD0
+	VPADDD  ·avx2IncMask<>(SB), DD0, DD1
+	VPADDD  ·avx2IncMask<>(SB), DD1, DD2
+	VMOVDQA DD0, ctr0StoreAVX2
+	VMOVDQA DD1, ctr1StoreAVX2
+	VMOVDQA DD2, ctr2StoreAVX2
+
+	// Compute the number of iterations that will hash two blocks of data
+	MOVQ    inl, tmpStoreAVX2
+	MOVQ    inl, itr1
+	SUBQ    $256, itr1
+	SHRQ    $4, itr1
+	ADDQ    $6, itr1
+	MOVQ    $10, itr2
+	CMPQ    itr1, $10
+	CMOVQGT itr2, itr1
+	MOVQ    inp, inl
+	XORQ    itr2, itr2
+
+	// Perform ChaCha rounds, while hashing the remaining input
+openAVX2Tail384LoopB:
+	polyAdd(0(inl))
+	polyMulAVX2
+	LEAQ 16(inl), inl
+
+openAVX2Tail384LoopA:
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+	VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+	VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2
+	polyAdd(0(inl))
+	polyMulAVX2
+	LEAQ     16(inl), inl
+	INCQ     itr2
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+	VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+	VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2
+
+	CMPQ itr2, itr1
+	JB   openAVX2Tail384LoopB
+
+	CMPQ itr2, $10
+	JNE  openAVX2Tail384LoopA
+
+	MOVQ inl, itr2
+	SUBQ inp, inl
+	MOVQ inl, itr1
+	MOVQ tmpStoreAVX2, inl
+
+openAVX2Tail384Hash:
+	ADDQ $16, itr1
+	CMPQ itr1, inl
+	JGT  openAVX2Tail384HashEnd
+	polyAdd(0(itr2))
+	polyMulAVX2
+	LEAQ 16(itr2), itr2
+	JMP  openAVX2Tail384Hash
+
+// Store 256 bytes safely, then go to store loop
+openAVX2Tail384HashEnd:
+	VPADDD     ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2
+	VPADDD     state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2
+	VPADDD     state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2
+	VPADDD     ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2
+	VPERM2I128 $0x02, AA0, BB0, TT0; VPERM2I128 $0x02, CC0, DD0, TT1; VPERM2I128 $0x13, AA0, BB0, TT2; VPERM2I128 $0x13, CC0, DD0, TT3
+	VPXOR      (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3
+	VMOVDQU    TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup)
+	VPERM2I128 $0x02, AA1, BB1, TT0; VPERM2I128 $0x02, CC1, DD1, TT1; VPERM2I128 $0x13, AA1, BB1, TT2; VPERM2I128 $0x13, CC1, DD1, TT3
+	VPXOR      (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3
+	VMOVDQU    TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup)
+	VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0
+	LEAQ       (8*32)(inp), inp
+	LEAQ       (8*32)(oup), oup
+	SUBQ       $8*32, inl
+	JMP        openAVX2TailLoop
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 512 bytes of ciphertext
+openAVX2Tail512:
+	VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3
+	VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3
+	VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3
+	VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3
+	VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2
+	XORQ    itr1, itr1
+	MOVQ    inp, itr2
+
+openAVX2Tail512LoopB:
+	polyAdd(0(itr2))
+	polyMulAVX2
+	LEAQ (2*8)(itr2), itr2
+
+openAVX2Tail512LoopA:
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	VPSHUFB  ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+	polyAdd(0*8(itr2))
+	polyMulAVX2
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	VPSHUFB  ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+	VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+	VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	VPSHUFB  ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	polyAdd(2*8(itr2))
+	polyMulAVX2
+	LEAQ     (4*8)(itr2), itr2
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	VPSHUFB  ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+	VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+	VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3
+	INCQ     itr1
+	CMPQ     itr1, $4
+	JLT      openAVX2Tail512LoopB
+
+	CMPQ itr1, $10
+	JNE  openAVX2Tail512LoopA
+
+	MOVQ inl, itr1
+	SUBQ $384, itr1
+	ANDQ $-16, itr1
+
+openAVX2Tail512HashLoop:
+	TESTQ itr1, itr1
+	JE    openAVX2Tail512HashEnd
+	polyAdd(0(itr2))
+	polyMulAVX2
+	LEAQ  16(itr2), itr2
+	SUBQ  $16, itr1
+	JMP   openAVX2Tail512HashLoop
+
+openAVX2Tail512HashEnd:
+	VPADDD     ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3
+	VPADDD     state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3
+	VPADDD     state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3
+	VPADDD     ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3
+	VMOVDQA    CC3, tmpStoreAVX2
+	VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0
+	VPXOR      (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0
+	VMOVDQU    CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup)
+	VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0
+	VPXOR      (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0
+	VMOVDQU    AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup)
+	VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0
+	VPXOR      (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0
+	VMOVDQU    AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup)
+	VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0
+
+	LEAQ (12*32)(inp), inp
+	LEAQ (12*32)(oup), oup
+	SUBQ $12*32, inl
+
+	JMP openAVX2TailLoop
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+// func chacha20Poly1305Seal(dst, key, src, ad []byte)
+TEXT ·chacha20Poly1305Seal(SB), 0, $288-96
+	// For aligned stack access
+	MOVQ SP, BP
+	ADDQ $32, BP
+	ANDQ $-32, BP
+	MOVQ dst+0(FP), oup
+	MOVQ key+24(FP), keyp
+	MOVQ src+48(FP), inp
+	MOVQ src_len+56(FP), inl
+	MOVQ ad+72(FP), adp
+
+	CMPB ·useAVX2(SB), $1
+	JE   chacha20Poly1305Seal_AVX2
+
+	// Special optimization, for very short buffers
+	CMPQ inl, $128
+	JBE  sealSSE128 // About 15% faster
+
+	// In the seal case - prepare the poly key + 3 blocks of stream in the first iteration
+	MOVOU ·chacha20Constants<>(SB), A0
+	MOVOU (1*16)(keyp), B0
+	MOVOU (2*16)(keyp), C0
+	MOVOU (3*16)(keyp), D0
+
+	// Store state on stack for future use
+	MOVO B0, state1Store
+	MOVO C0, state2Store
+
+	// Load state, increment counter blocks
+	MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1
+	MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2
+	MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3
+
+	// Store counters
+	MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store
+	MOVQ $10, itr2
+
+sealSSEIntroLoop:
+	MOVO         C3, tmpStore
+	chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+	MOVO         tmpStore, C3
+	MOVO         C1, tmpStore
+	chachaQR(A3, B3, C3, D3, C1)
+	MOVO         tmpStore, C1
+	shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left
+	shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left
+	shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left
+
+	MOVO          C3, tmpStore
+	chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+	MOVO          tmpStore, C3
+	MOVO          C1, tmpStore
+	chachaQR(A3, B3, C3, D3, C1)
+	MOVO          tmpStore, C1
+	shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right
+	shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right
+	shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right
+	DECQ          itr2
+	JNE           sealSSEIntroLoop
+
+	// Add in the state
+	PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3
+	PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3
+	PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3
+	PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3
+
+	// Clamp and store the key
+	PAND ·polyClampMask<>(SB), A0
+	MOVO A0, rStore
+	MOVO B0, sStore
+
+	// Hash AAD
+	MOVQ ad_len+80(FP), itr2
+	CALL polyHashADInternal<>(SB)
+
+	MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0
+	PXOR  A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1
+	MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup)
+	MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0
+	PXOR  A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2
+	MOVOU A2, (4*16)(oup); MOVOU B2, (5*16)(oup); MOVOU C2, (6*16)(oup); MOVOU D2, (7*16)(oup)
+
+	MOVQ $128, itr1
+	SUBQ $128, inl
+	LEAQ 128(inp), inp
+
+	MOVO A3, A1; MOVO B3, B1; MOVO C3, C1; MOVO D3, D1
+
+	CMPQ inl, $64
+	JBE  sealSSE128SealHash
+
+	MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0
+	PXOR  A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3
+	MOVOU A3, (8*16)(oup); MOVOU B3, (9*16)(oup); MOVOU C3, (10*16)(oup); MOVOU D3, (11*16)(oup)
+
+	ADDQ $64, itr1
+	SUBQ $64, inl
+	LEAQ 64(inp), inp
+
+	MOVQ $2, itr1
+	MOVQ $8, itr2
+
+	CMPQ inl, $64
+	JBE  sealSSETail64
+	CMPQ inl, $128
+	JBE  sealSSETail128
+	CMPQ inl, $192
+	JBE  sealSSETail192
+
+sealSSEMainLoop:
+	// Load state, increment counter blocks
+	MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0
+	MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1
+	MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2
+	MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3
+
+	// Store counters
+	MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store
+
+sealSSEInnerLoop:
+	MOVO          C3, tmpStore
+	chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+	MOVO          tmpStore, C3
+	MOVO          C1, tmpStore
+	chachaQR(A3, B3, C3, D3, C1)
+	MOVO          tmpStore, C1
+	polyAdd(0(oup))
+	shiftB0Left;  shiftB1Left; shiftB2Left; shiftB3Left
+	shiftC0Left;  shiftC1Left; shiftC2Left; shiftC3Left
+	shiftD0Left;  shiftD1Left; shiftD2Left; shiftD3Left
+	polyMulStage1
+	polyMulStage2
+	LEAQ          (2*8)(oup), oup
+	MOVO          C3, tmpStore
+	chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3)
+	MOVO          tmpStore, C3
+	MOVO          C1, tmpStore
+	polyMulStage3
+	chachaQR(A3, B3, C3, D3, C1)
+	MOVO          tmpStore, C1
+	polyMulReduceStage
+	shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right
+	shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right
+	shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right
+	DECQ          itr2
+	JGE           sealSSEInnerLoop
+	polyAdd(0(oup))
+	polyMul
+	LEAQ          (2*8)(oup), oup
+	DECQ          itr1
+	JG            sealSSEInnerLoop
+
+	// Add in the state
+	PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3
+	PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3
+	PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3
+	PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3
+	MOVO  D3, tmpStore
+
+	// Load - xor - store
+	MOVOU (0*16)(inp), D3; PXOR D3, A0
+	MOVOU (1*16)(inp), D3; PXOR D3, B0
+	MOVOU (2*16)(inp), D3; PXOR D3, C0
+	MOVOU (3*16)(inp), D3; PXOR D3, D0
+	MOVOU A0, (0*16)(oup)
+	MOVOU B0, (1*16)(oup)
+	MOVOU C0, (2*16)(oup)
+	MOVOU D0, (3*16)(oup)
+	MOVO  tmpStore, D3
+
+	MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0
+	PXOR  A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1
+	MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup)
+	MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0
+	PXOR  A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2
+	MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup)
+	ADDQ  $192, inp
+	MOVQ  $192, itr1
+	SUBQ  $192, inl
+	MOVO  A3, A1
+	MOVO  B3, B1
+	MOVO  C3, C1
+	MOVO  D3, D1
+	CMPQ  inl, $64
+	JBE   sealSSE128SealHash
+	MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0
+	PXOR  A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3
+	MOVOU A3, (12*16)(oup); MOVOU B3, (13*16)(oup); MOVOU C3, (14*16)(oup); MOVOU D3, (15*16)(oup)
+	LEAQ  64(inp), inp
+	SUBQ  $64, inl
+	MOVQ  $6, itr1
+	MOVQ  $4, itr2
+	CMPQ  inl, $192
+	JG    sealSSEMainLoop
+
+	MOVQ  inl, itr1
+	TESTQ inl, inl
+	JE    sealSSE128SealHash
+	MOVQ  $6, itr1
+	CMPQ  inl, $64
+	JBE   sealSSETail64
+	CMPQ  inl, $128
+	JBE   sealSSETail128
+	JMP   sealSSETail192
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 64 bytes of plaintext
+sealSSETail64:
+	// Need to encrypt up to 64 bytes - prepare single block, hash 192 or 256 bytes
+	MOVO  ·chacha20Constants<>(SB), A1
+	MOVO  state1Store, B1
+	MOVO  state2Store, C1
+	MOVO  ctr3Store, D1
+	PADDL ·sseIncMask<>(SB), D1
+	MOVO  D1, ctr0Store
+
+sealSSETail64LoopA:
+	// Perform ChaCha rounds, while hashing the previously encrypted ciphertext
+	polyAdd(0(oup))
+	polyMul
+	LEAQ 16(oup), oup
+
+sealSSETail64LoopB:
+	chachaQR(A1, B1, C1, D1, T1)
+	shiftB1Left;  shiftC1Left; shiftD1Left
+	chachaQR(A1, B1, C1, D1, T1)
+	shiftB1Right; shiftC1Right; shiftD1Right
+	polyAdd(0(oup))
+	polyMul
+	LEAQ          16(oup), oup
+
+	DECQ itr1
+	JG   sealSSETail64LoopA
+
+	DECQ  itr2
+	JGE   sealSSETail64LoopB
+	PADDL ·chacha20Constants<>(SB), A1
+	PADDL state1Store, B1
+	PADDL state2Store, C1
+	PADDL ctr0Store, D1
+
+	JMP sealSSE128Seal
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 128 bytes of plaintext
+sealSSETail128:
+	// Need to encrypt up to 128 bytes - prepare two blocks, hash 192 or 256 bytes
+	MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store
+	MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store
+
+sealSSETail128LoopA:
+	// Perform ChaCha rounds, while hashing the previously encrypted ciphertext
+	polyAdd(0(oup))
+	polyMul
+	LEAQ 16(oup), oup
+
+sealSSETail128LoopB:
+	chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0)
+	shiftB0Left;  shiftC0Left; shiftD0Left
+	shiftB1Left;  shiftC1Left; shiftD1Left
+	polyAdd(0(oup))
+	polyMul
+	LEAQ          16(oup), oup
+	chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0)
+	shiftB0Right; shiftC0Right; shiftD0Right
+	shiftB1Right; shiftC1Right; shiftD1Right
+
+	DECQ itr1
+	JG   sealSSETail128LoopA
+
+	DECQ itr2
+	JGE  sealSSETail128LoopB
+
+	PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1
+	PADDL state1Store, B0; PADDL state1Store, B1
+	PADDL state2Store, C0; PADDL state2Store, C1
+	PADDL ctr0Store, D0; PADDL ctr1Store, D1
+
+	MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3
+	PXOR  T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0
+	MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup)
+
+	MOVQ $64, itr1
+	LEAQ 64(inp), inp
+	SUBQ $64, inl
+
+	JMP sealSSE128SealHash
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 192 bytes of plaintext
+sealSSETail192:
+	// Need to encrypt up to 192 bytes - prepare three blocks, hash 192 or 256 bytes
+	MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store
+	MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store
+	MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2; MOVO D2, ctr2Store
+
+sealSSETail192LoopA:
+	// Perform ChaCha rounds, while hashing the previously encrypted ciphertext
+	polyAdd(0(oup))
+	polyMul
+	LEAQ 16(oup), oup
+
+sealSSETail192LoopB:
+	chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+	shiftB0Left; shiftC0Left; shiftD0Left
+	shiftB1Left; shiftC1Left; shiftD1Left
+	shiftB2Left; shiftC2Left; shiftD2Left
+
+	polyAdd(0(oup))
+	polyMul
+	LEAQ 16(oup), oup
+
+	chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+	shiftB0Right; shiftC0Right; shiftD0Right
+	shiftB1Right; shiftC1Right; shiftD1Right
+	shiftB2Right; shiftC2Right; shiftD2Right
+
+	DECQ itr1
+	JG   sealSSETail192LoopA
+
+	DECQ itr2
+	JGE  sealSSETail192LoopB
+
+	PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2
+	PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2
+	PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2
+	PADDL ctr0Store, D0; PADDL ctr1Store, D1; PADDL ctr2Store, D2
+
+	MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3
+	PXOR  T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0
+	MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup)
+	MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3
+	PXOR  T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1
+	MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup)
+
+	MOVO A2, A1
+	MOVO B2, B1
+	MOVO C2, C1
+	MOVO D2, D1
+	MOVQ $128, itr1
+	LEAQ 128(inp), inp
+	SUBQ $128, inl
+
+	JMP sealSSE128SealHash
+
+// ----------------------------------------------------------------------------
+// Special seal optimization for buffers smaller than 129 bytes
+sealSSE128:
+	// For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks
+	MOVOU ·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0
+	MOVO  A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1
+	MOVO  A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2
+	MOVO  B0, T1; MOVO C0, T2; MOVO D1, T3
+	MOVQ  $10, itr2
+
+sealSSE128InnerCipherLoop:
+	chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+	shiftB0Left;  shiftB1Left; shiftB2Left
+	shiftC0Left;  shiftC1Left; shiftC2Left
+	shiftD0Left;  shiftD1Left; shiftD2Left
+	chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0)
+	shiftB0Right; shiftB1Right; shiftB2Right
+	shiftC0Right; shiftC1Right; shiftC2Right
+	shiftD0Right; shiftD1Right; shiftD2Right
+	DECQ          itr2
+	JNE           sealSSE128InnerCipherLoop
+
+	// A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded
+	PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2
+	PADDL T1, B0; PADDL T1, B1; PADDL T1, B2
+	PADDL T2, C1; PADDL T2, C2
+	PADDL T3, D1; PADDL ·sseIncMask<>(SB), T3; PADDL T3, D2
+	PAND  ·polyClampMask<>(SB), A0
+	MOVOU A0, rStore
+	MOVOU B0, sStore
+
+	// Hash
+	MOVQ ad_len+80(FP), itr2
+	CALL polyHashADInternal<>(SB)
+	XORQ itr1, itr1
+
+sealSSE128SealHash:
+	// itr1 holds the number of bytes encrypted but not yet hashed
+	CMPQ itr1, $16
+	JB   sealSSE128Seal
+	polyAdd(0(oup))
+	polyMul
+
+	SUBQ $16, itr1
+	ADDQ $16, oup
+
+	JMP sealSSE128SealHash
+
+sealSSE128Seal:
+	CMPQ inl, $16
+	JB   sealSSETail
+	SUBQ $16, inl
+
+	// Load for decryption
+	MOVOU (inp), T0
+	PXOR  T0, A1
+	MOVOU A1, (oup)
+	LEAQ  (1*16)(inp), inp
+	LEAQ  (1*16)(oup), oup
+
+	// Extract for hashing
+	MOVQ   A1, t0
+	PSRLDQ $8, A1
+	MOVQ A1, t1
+	ADDQ   t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2
+	polyMul
+
+	// Shift the stream "left"
+	MOVO B1, A1
+	MOVO C1, B1
+	MOVO D1, C1
+	MOVO A2, D1
+	MOVO B2, A2
+	MOVO C2, B2
+	MOVO D2, C2
+	JMP  sealSSE128Seal
+
+sealSSETail:
+	TESTQ inl, inl
+	JE    sealSSEFinalize
+
+	// We can only load the PT one byte at a time to avoid read after end of buffer
+	MOVQ inl, itr2
+	SHLQ $4, itr2
+	LEAQ ·andMask<>(SB), t0
+	MOVQ inl, itr1
+	LEAQ -1(inp)(inl*1), inp
+	XORQ t2, t2
+	XORQ t3, t3
+	XORQ AX, AX
+
+sealSSETailLoadLoop:
+	SHLQ $8, t2, t3
+	SHLQ $8, t2
+	MOVB (inp), AX
+	XORQ AX, t2
+	LEAQ   -1(inp), inp
+	DECQ   itr1
+	JNE    sealSSETailLoadLoop
+	MOVQ t2, 0+tmpStore
+	MOVQ t3, 8+tmpStore
+	PXOR 0+tmpStore, A1
+	MOVOU  A1, (oup)
+	MOVOU  -16(t0)(itr2*1), T0
+	PAND   T0, A1
+	MOVQ   A1, t0
+	PSRLDQ $8, A1
+	MOVQ   A1, t1
+	ADDQ   t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2
+	polyMul
+
+	ADDQ inl, oup
+
+sealSSEFinalize:
+	// Hash in the buffer lengths
+	ADDQ ad_len+80(FP), acc0
+	ADCQ src_len+56(FP), acc1
+	ADCQ $1, acc2
+	polyMul
+
+	// Final reduce
+	MOVQ    acc0, t0
+	MOVQ    acc1, t1
+	MOVQ    acc2, t2
+	SUBQ    $-5, acc0
+	SBBQ    $-1, acc1
+	SBBQ    $3, acc2
+	CMOVQCS t0, acc0
+	CMOVQCS t1, acc1
+	CMOVQCS t2, acc2
+
+	// Add in the "s" part of the key
+	ADDQ 0+sStore, acc0
+	ADCQ 8+sStore, acc1
+
+	// Finally store the tag at the end of the message
+	MOVQ acc0, (0*8)(oup)
+	MOVQ acc1, (1*8)(oup)
+	RET
+
+// ----------------------------------------------------------------------------
+// ------------------------- AVX2 Code ----------------------------------------
+chacha20Poly1305Seal_AVX2:
+	VZEROUPPER
+	VMOVDQU ·chacha20Constants<>(SB), AA0
+	BYTE    $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14
+	BYTE    $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12
+	BYTE    $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4
+	VPADDD  ·avx2InitMask<>(SB), DD0, DD0
+
+	// Special optimizations, for very short buffers
+	CMPQ inl, $192
+	JBE  seal192AVX2 // 33% faster
+	CMPQ inl, $320
+	JBE  seal320AVX2 // 17% faster
+
+	// For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream
+	VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3
+	VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3; VMOVDQA BB0, state1StoreAVX2
+	VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3; VMOVDQA CC0, state2StoreAVX2
+	VPADDD  ·avx2IncMask<>(SB), DD0, DD1; VMOVDQA DD0, ctr0StoreAVX2
+	VPADDD  ·avx2IncMask<>(SB), DD1, DD2; VMOVDQA DD1, ctr1StoreAVX2
+	VPADDD  ·avx2IncMask<>(SB), DD2, DD3; VMOVDQA DD2, ctr2StoreAVX2
+	VMOVDQA DD3, ctr3StoreAVX2
+	MOVQ    $10, itr2
+
+sealAVX2IntroLoop:
+	VMOVDQA CC3, tmpStoreAVX2
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3)
+	VMOVDQA tmpStoreAVX2, CC3
+	VMOVDQA CC1, tmpStoreAVX2
+	chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1)
+	VMOVDQA tmpStoreAVX2, CC1
+
+	VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0
+	VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1
+	VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2
+	VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3
+
+	VMOVDQA CC3, tmpStoreAVX2
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3)
+	VMOVDQA tmpStoreAVX2, CC3
+	VMOVDQA CC1, tmpStoreAVX2
+	chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1)
+	VMOVDQA tmpStoreAVX2, CC1
+
+	VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0
+	VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1
+	VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2
+	VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3
+	DECQ     itr2
+	JNE      sealAVX2IntroLoop
+
+	VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3
+	VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3
+	VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3
+	VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3
+
+	VPERM2I128 $0x13, CC0, DD0, CC0 // Stream bytes 96 - 127
+	VPERM2I128 $0x02, AA0, BB0, DD0 // The Poly1305 key
+	VPERM2I128 $0x13, AA0, BB0, AA0 // Stream bytes 64 - 95
+
+	// Clamp and store poly key
+	VPAND   ·polyClampMask<>(SB), DD0, DD0
+	VMOVDQA DD0, rsStoreAVX2
+
+	// Hash AD
+	MOVQ ad_len+80(FP), itr2
+	CALL polyHashADInternal<>(SB)
+
+	// Can store at least 320 bytes
+	VPXOR   (0*32)(inp), AA0, AA0
+	VPXOR   (1*32)(inp), CC0, CC0
+	VMOVDQU AA0, (0*32)(oup)
+	VMOVDQU CC0, (1*32)(oup)
+
+	VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0
+	VPXOR      (2*32)(inp), AA0, AA0; VPXOR (3*32)(inp), BB0, BB0; VPXOR (4*32)(inp), CC0, CC0; VPXOR (5*32)(inp), DD0, DD0
+	VMOVDQU    AA0, (2*32)(oup); VMOVDQU BB0, (3*32)(oup); VMOVDQU CC0, (4*32)(oup); VMOVDQU DD0, (5*32)(oup)
+	VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0
+	VPXOR      (6*32)(inp), AA0, AA0; VPXOR (7*32)(inp), BB0, BB0; VPXOR (8*32)(inp), CC0, CC0; VPXOR (9*32)(inp), DD0, DD0
+	VMOVDQU    AA0, (6*32)(oup); VMOVDQU BB0, (7*32)(oup); VMOVDQU CC0, (8*32)(oup); VMOVDQU DD0, (9*32)(oup)
+
+	MOVQ $320, itr1
+	SUBQ $320, inl
+	LEAQ 320(inp), inp
+
+	VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, CC3, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, CC3, DD3, DD0
+	CMPQ       inl, $128
+	JBE        sealAVX2SealHash
+
+	VPXOR   (0*32)(inp), AA0, AA0; VPXOR (1*32)(inp), BB0, BB0; VPXOR (2*32)(inp), CC0, CC0; VPXOR (3*32)(inp), DD0, DD0
+	VMOVDQU AA0, (10*32)(oup); VMOVDQU BB0, (11*32)(oup); VMOVDQU CC0, (12*32)(oup); VMOVDQU DD0, (13*32)(oup)
+	SUBQ    $128, inl
+	LEAQ    128(inp), inp
+
+	MOVQ $8, itr1
+	MOVQ $2, itr2
+
+	CMPQ inl, $128
+	JBE  sealAVX2Tail128
+	CMPQ inl, $256
+	JBE  sealAVX2Tail256
+	CMPQ inl, $384
+	JBE  sealAVX2Tail384
+	CMPQ inl, $512
+	JBE  sealAVX2Tail512
+
+	// We have 448 bytes to hash, but main loop hashes 512 bytes at a time - perform some rounds, before the main loop
+	VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3
+	VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3
+	VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3
+	VMOVDQA ctr3StoreAVX2, DD0
+	VPADDD  ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3
+	VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2
+
+	VMOVDQA CC3, tmpStoreAVX2
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3)
+	VMOVDQA tmpStoreAVX2, CC3
+	VMOVDQA CC1, tmpStoreAVX2
+	chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1)
+	VMOVDQA tmpStoreAVX2, CC1
+
+	VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0
+	VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1
+	VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2
+	VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3
+
+	VMOVDQA CC3, tmpStoreAVX2
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3)
+	VMOVDQA tmpStoreAVX2, CC3
+	VMOVDQA CC1, tmpStoreAVX2
+	chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1)
+	VMOVDQA tmpStoreAVX2, CC1
+
+	VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0
+	VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1
+	VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2
+	VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	VPSHUFB  ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+
+	SUBQ $16, oup                  // Adjust the pointer
+	MOVQ $9, itr1
+	JMP  sealAVX2InternalLoopStart
+
+sealAVX2MainLoop:
+	// Load state, increment counter blocks, store the incremented counters
+	VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3
+	VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3
+	VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3
+	VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3
+	VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2
+	MOVQ    $10, itr1
+
+sealAVX2InternalLoop:
+	polyAdd(0*8(oup))
+	VPADDD  BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	polyMulStage1_AVX2
+	VPXOR   AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+	polyMulStage2_AVX2
+	VPADDD  DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	VPXOR   CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	polyMulStage3_AVX2
+	VMOVDQA CC3, tmpStoreAVX2
+	VPSLLD  $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD  $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD  $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD  $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA tmpStoreAVX2, CC3
+	polyMulReduceStage
+
+sealAVX2InternalLoopStart:
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	VPSHUFB  ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+	polyAdd(2*8(oup))
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	polyMulStage1_AVX2
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+	polyMulStage2_AVX2
+	VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+	VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	polyMulStage3_AVX2
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	VPSHUFB  ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+	polyMulReduceStage
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	polyAdd(4*8(oup))
+	LEAQ     (6*8)(oup), oup
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+	polyMulStage1_AVX2
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	polyMulStage2_AVX2
+	VPSHUFB  ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	polyMulStage3_AVX2
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+	polyMulReduceStage
+	VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+	VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3
+	DECQ     itr1
+	JNE      sealAVX2InternalLoop
+
+	VPADDD  ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3
+	VPADDD  state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3
+	VPADDD  state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3
+	VPADDD  ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3
+	VMOVDQA CC3, tmpStoreAVX2
+
+	// We only hashed 480 of the 512 bytes available - hash the remaining 32 here
+	polyAdd(0*8(oup))
+	polyMulAVX2
+	LEAQ       (4*8)(oup), oup
+	VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0
+	VPXOR      (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0
+	VMOVDQU    CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup)
+	VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0
+	VPXOR      (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0
+	VMOVDQU    AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup)
+
+	// and here
+	polyAdd(-2*8(oup))
+	polyMulAVX2
+	VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0
+	VPXOR      (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0
+	VMOVDQU    AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup)
+	VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0
+	VPXOR      (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0
+	VMOVDQU    AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup)
+	LEAQ       (32*16)(inp), inp
+	SUBQ       $(32*16), inl
+	CMPQ       inl, $512
+	JG         sealAVX2MainLoop
+
+	// Tail can only hash 480 bytes
+	polyAdd(0*8(oup))
+	polyMulAVX2
+	polyAdd(2*8(oup))
+	polyMulAVX2
+	LEAQ 32(oup), oup
+
+	MOVQ $10, itr1
+	MOVQ $0, itr2
+	CMPQ inl, $128
+	JBE  sealAVX2Tail128
+	CMPQ inl, $256
+	JBE  sealAVX2Tail256
+	CMPQ inl, $384
+	JBE  sealAVX2Tail384
+	JMP  sealAVX2Tail512
+
+// ----------------------------------------------------------------------------
+// Special optimization for buffers smaller than 193 bytes
+seal192AVX2:
+	// For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks
+	VMOVDQA AA0, AA1
+	VMOVDQA BB0, BB1
+	VMOVDQA CC0, CC1
+	VPADDD  ·avx2IncMask<>(SB), DD0, DD1
+	VMOVDQA AA0, AA2
+	VMOVDQA BB0, BB2
+	VMOVDQA CC0, CC2
+	VMOVDQA DD0, DD2
+	VMOVDQA DD1, TT3
+	MOVQ    $10, itr2
+
+sealAVX2192InnerCipherLoop:
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+	VPALIGNR   $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1
+	VPALIGNR   $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+	VPALIGNR   $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+	VPALIGNR   $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1
+	VPALIGNR   $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+	VPALIGNR   $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1
+	DECQ       itr2
+	JNE        sealAVX2192InnerCipherLoop
+	VPADDD     AA2, AA0, AA0; VPADDD AA2, AA1, AA1
+	VPADDD     BB2, BB0, BB0; VPADDD BB2, BB1, BB1
+	VPADDD     CC2, CC0, CC0; VPADDD CC2, CC1, CC1
+	VPADDD     DD2, DD0, DD0; VPADDD TT3, DD1, DD1
+	VPERM2I128 $0x02, AA0, BB0, TT0
+
+	// Clamp and store poly key
+	VPAND   ·polyClampMask<>(SB), TT0, TT0
+	VMOVDQA TT0, rsStoreAVX2
+
+	// Stream for up to 192 bytes
+	VPERM2I128 $0x13, AA0, BB0, AA0
+	VPERM2I128 $0x13, CC0, DD0, BB0
+	VPERM2I128 $0x02, AA1, BB1, CC0
+	VPERM2I128 $0x02, CC1, DD1, DD0
+	VPERM2I128 $0x13, AA1, BB1, AA1
+	VPERM2I128 $0x13, CC1, DD1, BB1
+
+sealAVX2ShortSeal:
+	// Hash aad
+	MOVQ ad_len+80(FP), itr2
+	CALL polyHashADInternal<>(SB)
+	XORQ itr1, itr1
+
+sealAVX2SealHash:
+	// itr1 holds the number of bytes encrypted but not yet hashed
+	CMPQ itr1, $16
+	JB   sealAVX2ShortSealLoop
+	polyAdd(0(oup))
+	polyMul
+	SUBQ $16, itr1
+	ADDQ $16, oup
+	JMP  sealAVX2SealHash
+
+sealAVX2ShortSealLoop:
+	CMPQ inl, $32
+	JB   sealAVX2ShortTail32
+	SUBQ $32, inl
+
+	// Load for encryption
+	VPXOR   (inp), AA0, AA0
+	VMOVDQU AA0, (oup)
+	LEAQ    (1*32)(inp), inp
+
+	// Now can hash
+	polyAdd(0*8(oup))
+	polyMulAVX2
+	polyAdd(2*8(oup))
+	polyMulAVX2
+	LEAQ (1*32)(oup), oup
+
+	// Shift stream left
+	VMOVDQA BB0, AA0
+	VMOVDQA CC0, BB0
+	VMOVDQA DD0, CC0
+	VMOVDQA AA1, DD0
+	VMOVDQA BB1, AA1
+	VMOVDQA CC1, BB1
+	VMOVDQA DD1, CC1
+	VMOVDQA AA2, DD1
+	VMOVDQA BB2, AA2
+	JMP     sealAVX2ShortSealLoop
+
+sealAVX2ShortTail32:
+	CMPQ    inl, $16
+	VMOVDQA A0, A1
+	JB      sealAVX2ShortDone
+
+	SUBQ $16, inl
+
+	// Load for encryption
+	VPXOR   (inp), A0, T0
+	VMOVDQU T0, (oup)
+	LEAQ    (1*16)(inp), inp
+
+	// Hash
+	polyAdd(0*8(oup))
+	polyMulAVX2
+	LEAQ       (1*16)(oup), oup
+	VPERM2I128 $0x11, AA0, AA0, AA0
+	VMOVDQA    A0, A1
+
+sealAVX2ShortDone:
+	VZEROUPPER
+	JMP sealSSETail
+
+// ----------------------------------------------------------------------------
+// Special optimization for buffers smaller than 321 bytes
+seal320AVX2:
+	// For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks
+	VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD ·avx2IncMask<>(SB), DD0, DD1
+	VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD ·avx2IncMask<>(SB), DD1, DD2
+	VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3
+	MOVQ    $10, itr2
+
+sealAVX2320InnerCipherLoop:
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+	VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+	VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+	VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+	VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2
+	DECQ     itr2
+	JNE      sealAVX2320InnerCipherLoop
+
+	VMOVDQA ·chacha20Constants<>(SB), TT0
+	VPADDD  TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2
+	VPADDD  TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2
+	VPADDD  TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2
+	VMOVDQA ·avx2IncMask<>(SB), TT0
+	VPADDD  TT3, DD0, DD0; VPADDD TT0, TT3, TT3
+	VPADDD  TT3, DD1, DD1; VPADDD TT0, TT3, TT3
+	VPADDD  TT3, DD2, DD2
+
+	// Clamp and store poly key
+	VPERM2I128 $0x02, AA0, BB0, TT0
+	VPAND      ·polyClampMask<>(SB), TT0, TT0
+	VMOVDQA    TT0, rsStoreAVX2
+
+	// Stream for up to 320 bytes
+	VPERM2I128 $0x13, AA0, BB0, AA0
+	VPERM2I128 $0x13, CC0, DD0, BB0
+	VPERM2I128 $0x02, AA1, BB1, CC0
+	VPERM2I128 $0x02, CC1, DD1, DD0
+	VPERM2I128 $0x13, AA1, BB1, AA1
+	VPERM2I128 $0x13, CC1, DD1, BB1
+	VPERM2I128 $0x02, AA2, BB2, CC1
+	VPERM2I128 $0x02, CC2, DD2, DD1
+	VPERM2I128 $0x13, AA2, BB2, AA2
+	VPERM2I128 $0x13, CC2, DD2, BB2
+	JMP        sealAVX2ShortSeal
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 128 bytes of ciphertext
+sealAVX2Tail128:
+	// Need to decrypt up to 128 bytes - prepare two blocks
+	// If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed
+	// If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed
+	VMOVDQA ·chacha20Constants<>(SB), AA0
+	VMOVDQA state1StoreAVX2, BB0
+	VMOVDQA state2StoreAVX2, CC0
+	VMOVDQA ctr3StoreAVX2, DD0
+	VPADDD  ·avx2IncMask<>(SB), DD0, DD0
+	VMOVDQA DD0, DD1
+
+sealAVX2Tail128LoopA:
+	polyAdd(0(oup))
+	polyMul
+	LEAQ 16(oup), oup
+
+sealAVX2Tail128LoopB:
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0)
+	polyAdd(0(oup))
+	polyMul
+	VPALIGNR $4, BB0, BB0, BB0
+	VPALIGNR $8, CC0, CC0, CC0
+	VPALIGNR $12, DD0, DD0, DD0
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0)
+	polyAdd(16(oup))
+	polyMul
+	LEAQ     32(oup), oup
+	VPALIGNR $12, BB0, BB0, BB0
+	VPALIGNR $8, CC0, CC0, CC0
+	VPALIGNR $4, DD0, DD0, DD0
+	DECQ     itr1
+	JG       sealAVX2Tail128LoopA
+	DECQ     itr2
+	JGE      sealAVX2Tail128LoopB
+
+	VPADDD ·chacha20Constants<>(SB), AA0, AA1
+	VPADDD state1StoreAVX2, BB0, BB1
+	VPADDD state2StoreAVX2, CC0, CC1
+	VPADDD DD1, DD0, DD1
+
+	VPERM2I128 $0x02, AA1, BB1, AA0
+	VPERM2I128 $0x02, CC1, DD1, BB0
+	VPERM2I128 $0x13, AA1, BB1, CC0
+	VPERM2I128 $0x13, CC1, DD1, DD0
+	JMP        sealAVX2ShortSealLoop
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 256 bytes of ciphertext
+sealAVX2Tail256:
+	// Need to decrypt up to 256 bytes - prepare two blocks
+	// If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed
+	// If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed
+	VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA ·chacha20Constants<>(SB), AA1
+	VMOVDQA state1StoreAVX2, BB0; VMOVDQA state1StoreAVX2, BB1
+	VMOVDQA state2StoreAVX2, CC0; VMOVDQA state2StoreAVX2, CC1
+	VMOVDQA ctr3StoreAVX2, DD0
+	VPADDD  ·avx2IncMask<>(SB), DD0, DD0
+	VPADDD  ·avx2IncMask<>(SB), DD0, DD1
+	VMOVDQA DD0, TT1
+	VMOVDQA DD1, TT2
+
+sealAVX2Tail256LoopA:
+	polyAdd(0(oup))
+	polyMul
+	LEAQ 16(oup), oup
+
+sealAVX2Tail256LoopB:
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+	polyAdd(0(oup))
+	polyMul
+	VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+	VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0)
+	polyAdd(16(oup))
+	polyMul
+	LEAQ     32(oup), oup
+	VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1
+	VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1
+	DECQ     itr1
+	JG       sealAVX2Tail256LoopA
+	DECQ     itr2
+	JGE      sealAVX2Tail256LoopB
+
+	VPADDD     ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1
+	VPADDD     state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1
+	VPADDD     state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1
+	VPADDD     TT1, DD0, DD0; VPADDD TT2, DD1, DD1
+	VPERM2I128 $0x02, AA0, BB0, TT0
+	VPERM2I128 $0x02, CC0, DD0, TT1
+	VPERM2I128 $0x13, AA0, BB0, TT2
+	VPERM2I128 $0x13, CC0, DD0, TT3
+	VPXOR      (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3
+	VMOVDQU    TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup)
+	MOVQ       $128, itr1
+	LEAQ       128(inp), inp
+	SUBQ       $128, inl
+	VPERM2I128 $0x02, AA1, BB1, AA0
+	VPERM2I128 $0x02, CC1, DD1, BB0
+	VPERM2I128 $0x13, AA1, BB1, CC0
+	VPERM2I128 $0x13, CC1, DD1, DD0
+
+	JMP sealAVX2SealHash
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 384 bytes of ciphertext
+sealAVX2Tail384:
+	// Need to decrypt up to 384 bytes - prepare two blocks
+	// If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed
+	// If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed
+	VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2
+	VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2
+	VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2
+	VMOVDQA ctr3StoreAVX2, DD0
+	VPADDD  ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2
+	VMOVDQA DD0, TT1; VMOVDQA DD1, TT2; VMOVDQA DD2, TT3
+
+sealAVX2Tail384LoopA:
+	polyAdd(0(oup))
+	polyMul
+	LEAQ 16(oup), oup
+
+sealAVX2Tail384LoopB:
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+	polyAdd(0(oup))
+	polyMul
+	VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+	VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2
+	chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0)
+	polyAdd(16(oup))
+	polyMul
+	LEAQ     32(oup), oup
+	VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2
+	VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2
+	DECQ     itr1
+	JG       sealAVX2Tail384LoopA
+	DECQ     itr2
+	JGE      sealAVX2Tail384LoopB
+
+	VPADDD     ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2
+	VPADDD     state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2
+	VPADDD     state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2
+	VPADDD     TT1, DD0, DD0; VPADDD TT2, DD1, DD1; VPADDD TT3, DD2, DD2
+	VPERM2I128 $0x02, AA0, BB0, TT0
+	VPERM2I128 $0x02, CC0, DD0, TT1
+	VPERM2I128 $0x13, AA0, BB0, TT2
+	VPERM2I128 $0x13, CC0, DD0, TT3
+	VPXOR      (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3
+	VMOVDQU    TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup)
+	VPERM2I128 $0x02, AA1, BB1, TT0
+	VPERM2I128 $0x02, CC1, DD1, TT1
+	VPERM2I128 $0x13, AA1, BB1, TT2
+	VPERM2I128 $0x13, CC1, DD1, TT3
+	VPXOR      (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3
+	VMOVDQU    TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup)
+	MOVQ       $256, itr1
+	LEAQ       256(inp), inp
+	SUBQ       $256, inl
+	VPERM2I128 $0x02, AA2, BB2, AA0
+	VPERM2I128 $0x02, CC2, DD2, BB0
+	VPERM2I128 $0x13, AA2, BB2, CC0
+	VPERM2I128 $0x13, CC2, DD2, DD0
+
+	JMP sealAVX2SealHash
+
+// ----------------------------------------------------------------------------
+// Special optimization for the last 512 bytes of ciphertext
+sealAVX2Tail512:
+	// Need to decrypt up to 512 bytes - prepare two blocks
+	// If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed
+	// If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed
+	VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3
+	VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3
+	VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3
+	VMOVDQA ctr3StoreAVX2, DD0
+	VPADDD  ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3
+	VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2
+
+sealAVX2Tail512LoopA:
+	polyAdd(0(oup))
+	polyMul
+	LEAQ 16(oup), oup
+
+sealAVX2Tail512LoopB:
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	VPSHUFB  ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+	polyAdd(0*8(oup))
+	polyMulAVX2
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	VPSHUFB  ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+	VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+	VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	VPSHUFB  ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	polyAdd(2*8(oup))
+	polyMulAVX2
+	LEAQ     (4*8)(oup), oup
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+	VPADDD   BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3
+	VPXOR    AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3
+	VPSHUFB  ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3
+	VPADDD   DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3
+	VPXOR    CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3
+	VMOVDQA  CC3, tmpStoreAVX2
+	VPSLLD   $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0
+	VPSLLD   $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1
+	VPSLLD   $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2
+	VPSLLD   $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3
+	VMOVDQA  tmpStoreAVX2, CC3
+	VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3
+	VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3
+	VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3
+
+	DECQ itr1
+	JG   sealAVX2Tail512LoopA
+	DECQ itr2
+	JGE  sealAVX2Tail512LoopB
+
+	VPADDD     ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3
+	VPADDD     state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3
+	VPADDD     state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3
+	VPADDD     ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3
+	VMOVDQA    CC3, tmpStoreAVX2
+	VPERM2I128 $0x02, AA0, BB0, CC3
+	VPXOR      (0*32)(inp), CC3, CC3
+	VMOVDQU    CC3, (0*32)(oup)
+	VPERM2I128 $0x02, CC0, DD0, CC3
+	VPXOR      (1*32)(inp), CC3, CC3
+	VMOVDQU    CC3, (1*32)(oup)
+	VPERM2I128 $0x13, AA0, BB0, CC3
+	VPXOR      (2*32)(inp), CC3, CC3
+	VMOVDQU    CC3, (2*32)(oup)
+	VPERM2I128 $0x13, CC0, DD0, CC3
+	VPXOR      (3*32)(inp), CC3, CC3
+	VMOVDQU    CC3, (3*32)(oup)
+
+	VPERM2I128 $0x02, AA1, BB1, AA0
+	VPERM2I128 $0x02, CC1, DD1, BB0
+	VPERM2I128 $0x13, AA1, BB1, CC0
+	VPERM2I128 $0x13, CC1, DD1, DD0
+	VPXOR      (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0
+	VMOVDQU    AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup)
+
+	VPERM2I128 $0x02, AA2, BB2, AA0
+	VPERM2I128 $0x02, CC2, DD2, BB0
+	VPERM2I128 $0x13, AA2, BB2, CC0
+	VPERM2I128 $0x13, CC2, DD2, DD0
+	VPXOR      (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0
+	VMOVDQU    AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup)
+
+	MOVQ       $384, itr1
+	LEAQ       384(inp), inp
+	SUBQ       $384, inl
+	VPERM2I128 $0x02, AA3, BB3, AA0
+	VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0
+	VPERM2I128 $0x13, AA3, BB3, CC0
+	VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0
+
+	JMP sealAVX2SealHash
diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
new file mode 100644
index 0000000000000000000000000000000000000000..c27971216c9bfe8642bfccb543865cb923daffc8
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
@@ -0,0 +1,81 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package chacha20poly1305
+
+import (
+	"encoding/binary"
+
+	"golang.org/x/crypto/internal/chacha20"
+	"golang.org/x/crypto/internal/subtle"
+	"golang.org/x/crypto/poly1305"
+)
+
+func roundTo16(n int) int {
+	return 16 * ((n + 15) / 16)
+}
+
+func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte {
+	ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize)
+	if subtle.InexactOverlap(out, plaintext) {
+		panic("chacha20poly1305: invalid buffer overlap")
+	}
+
+	var polyKey [32]byte
+	s := chacha20.New(c.key, [3]uint32{
+		binary.LittleEndian.Uint32(nonce[0:4]),
+		binary.LittleEndian.Uint32(nonce[4:8]),
+		binary.LittleEndian.Uint32(nonce[8:12]),
+	})
+	s.XORKeyStream(polyKey[:], polyKey[:])
+	s.Advance() // skip the next 32 bytes
+	s.XORKeyStream(out, plaintext)
+
+	polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(plaintext))+8+8)
+	copy(polyInput, additionalData)
+	copy(polyInput[roundTo16(len(additionalData)):], out[:len(plaintext)])
+	binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData)))
+	binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(plaintext)))
+
+	var tag [poly1305.TagSize]byte
+	poly1305.Sum(&tag, polyInput, &polyKey)
+	copy(out[len(plaintext):], tag[:])
+
+	return ret
+}
+
+func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+	var tag [poly1305.TagSize]byte
+	copy(tag[:], ciphertext[len(ciphertext)-16:])
+	ciphertext = ciphertext[:len(ciphertext)-16]
+
+	var polyKey [32]byte
+	s := chacha20.New(c.key, [3]uint32{
+		binary.LittleEndian.Uint32(nonce[0:4]),
+		binary.LittleEndian.Uint32(nonce[4:8]),
+		binary.LittleEndian.Uint32(nonce[8:12]),
+	})
+	s.XORKeyStream(polyKey[:], polyKey[:])
+	s.Advance() // skip the next 32 bytes
+
+	polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(ciphertext))+8+8)
+	copy(polyInput, additionalData)
+	copy(polyInput[roundTo16(len(additionalData)):], ciphertext)
+	binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData)))
+	binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(ciphertext)))
+
+	ret, out := sliceForAppend(dst, len(ciphertext))
+	if subtle.InexactOverlap(out, ciphertext) {
+		panic("chacha20poly1305: invalid buffer overlap")
+	}
+	if !poly1305.Verify(&tag, polyInput, &polyKey) {
+		for i := range out {
+			out[i] = 0
+		}
+		return nil, errOpen
+	}
+
+	s.XORKeyStream(out, ciphertext)
+	return ret, nil
+}
diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go
new file mode 100644
index 0000000000000000000000000000000000000000..4c2eb703c327cddc1a3caea33cfc85e9b8dd59c1
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go
@@ -0,0 +1,15 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !amd64 !go1.7 gccgo appengine
+
+package chacha20poly1305
+
+func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
+	return c.sealGeneric(dst, nonce, plaintext, additionalData)
+}
+
+func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+	return c.openGeneric(dst, nonce, ciphertext, additionalData)
+}
diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go b/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go
new file mode 100644
index 0000000000000000000000000000000000000000..a02fa5719247380db85914ecae472bcffea9da17
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go
@@ -0,0 +1,104 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package chacha20poly1305
+
+import (
+	"crypto/cipher"
+	"encoding/binary"
+	"errors"
+
+	"golang.org/x/crypto/internal/chacha20"
+)
+
+type xchacha20poly1305 struct {
+	key [8]uint32
+}
+
+// NewX returns a XChaCha20-Poly1305 AEAD that uses the given 256-bit key.
+//
+// XChaCha20-Poly1305 is a ChaCha20-Poly1305 variant that takes a longer nonce,
+// suitable to be generated randomly without risk of collisions. It should be
+// preferred when nonce uniqueness cannot be trivially ensured, or whenever
+// nonces are randomly generated.
+func NewX(key []byte) (cipher.AEAD, error) {
+	if len(key) != KeySize {
+		return nil, errors.New("chacha20poly1305: bad key length")
+	}
+	ret := new(xchacha20poly1305)
+	ret.key[0] = binary.LittleEndian.Uint32(key[0:4])
+	ret.key[1] = binary.LittleEndian.Uint32(key[4:8])
+	ret.key[2] = binary.LittleEndian.Uint32(key[8:12])
+	ret.key[3] = binary.LittleEndian.Uint32(key[12:16])
+	ret.key[4] = binary.LittleEndian.Uint32(key[16:20])
+	ret.key[5] = binary.LittleEndian.Uint32(key[20:24])
+	ret.key[6] = binary.LittleEndian.Uint32(key[24:28])
+	ret.key[7] = binary.LittleEndian.Uint32(key[28:32])
+	return ret, nil
+}
+
+func (*xchacha20poly1305) NonceSize() int {
+	return NonceSizeX
+}
+
+func (*xchacha20poly1305) Overhead() int {
+	return 16
+}
+
+func (x *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
+	if len(nonce) != NonceSizeX {
+		panic("chacha20poly1305: bad nonce length passed to Seal")
+	}
+
+	// XChaCha20-Poly1305 technically supports a 64-bit counter, so there is no
+	// size limit. However, since we reuse the ChaCha20-Poly1305 implementation,
+	// the second half of the counter is not available. This is unlikely to be
+	// an issue because the cipher.AEAD API requires the entire message to be in
+	// memory, and the counter overflows at 256 GB.
+	if uint64(len(plaintext)) > (1<<38)-64 {
+		panic("chacha20poly1305: plaintext too large")
+	}
+
+	hNonce := [4]uint32{
+		binary.LittleEndian.Uint32(nonce[0:4]),
+		binary.LittleEndian.Uint32(nonce[4:8]),
+		binary.LittleEndian.Uint32(nonce[8:12]),
+		binary.LittleEndian.Uint32(nonce[12:16]),
+	}
+	c := &chacha20poly1305{
+		key: chacha20.HChaCha20(&x.key, &hNonce),
+	}
+	// The first 4 bytes of the final nonce are unused counter space.
+	cNonce := make([]byte, NonceSize)
+	copy(cNonce[4:12], nonce[16:24])
+
+	return c.seal(dst, cNonce[:], plaintext, additionalData)
+}
+
+func (x *xchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+	if len(nonce) != NonceSizeX {
+		panic("chacha20poly1305: bad nonce length passed to Open")
+	}
+	if len(ciphertext) < 16 {
+		return nil, errOpen
+	}
+	if uint64(len(ciphertext)) > (1<<38)-48 {
+		panic("chacha20poly1305: ciphertext too large")
+	}
+
+	hNonce := [4]uint32{
+		binary.LittleEndian.Uint32(nonce[0:4]),
+		binary.LittleEndian.Uint32(nonce[4:8]),
+		binary.LittleEndian.Uint32(nonce[8:12]),
+		binary.LittleEndian.Uint32(nonce[12:16]),
+	}
+	c := &chacha20poly1305{
+		key: chacha20.HChaCha20(&x.key, &hNonce),
+	}
+	// The first 4 bytes of the final nonce are unused counter space.
+	cNonce := make([]byte, NonceSize)
+	copy(cNonce[4:12], nonce[16:24])
+
+	return c.open(dst, cNonce[:], ciphertext, additionalData)
+}
diff --git a/vendor/golang.org/x/crypto/hkdf/hkdf.go b/vendor/golang.org/x/crypto/hkdf/hkdf.go
new file mode 100644
index 0000000000000000000000000000000000000000..5bc246355a265a3359b491152779b0c35fa180a4
--- /dev/null
+++ b/vendor/golang.org/x/crypto/hkdf/hkdf.go
@@ -0,0 +1,75 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package hkdf implements the HMAC-based Extract-and-Expand Key Derivation
+// Function (HKDF) as defined in RFC 5869.
+//
+// HKDF is a cryptographic key derivation function (KDF) with the goal of
+// expanding limited input keying material into one or more cryptographically
+// strong secret keys.
+//
+// RFC 5869: https://tools.ietf.org/html/rfc5869
+package hkdf // import "golang.org/x/crypto/hkdf"
+
+import (
+	"crypto/hmac"
+	"errors"
+	"hash"
+	"io"
+)
+
+type hkdf struct {
+	expander hash.Hash
+	size     int
+
+	info    []byte
+	counter byte
+
+	prev  []byte
+	cache []byte
+}
+
+func (f *hkdf) Read(p []byte) (int, error) {
+	// Check whether enough data can be generated
+	need := len(p)
+	remains := len(f.cache) + int(255-f.counter+1)*f.size
+	if remains < need {
+		return 0, errors.New("hkdf: entropy limit reached")
+	}
+	// Read from the cache, if enough data is present
+	n := copy(p, f.cache)
+	p = p[n:]
+
+	// Fill the buffer
+	for len(p) > 0 {
+		f.expander.Reset()
+		f.expander.Write(f.prev)
+		f.expander.Write(f.info)
+		f.expander.Write([]byte{f.counter})
+		f.prev = f.expander.Sum(f.prev[:0])
+		f.counter++
+
+		// Copy the new batch into p
+		f.cache = f.prev
+		n = copy(p, f.cache)
+		p = p[n:]
+	}
+	// Save leftovers for next run
+	f.cache = f.cache[n:]
+
+	return need, nil
+}
+
+// New returns a new HKDF using the given hash, the secret keying material to expand
+// and optional salt and info fields.
+func New(hash func() hash.Hash, secret, salt, info []byte) io.Reader {
+	if salt == nil {
+		salt = make([]byte, hash().Size())
+	}
+	extractor := hmac.New(hash, salt)
+	extractor.Write(secret)
+	prk := extractor.Sum(nil)
+
+	return &hkdf{hmac.New(hash, prk), extractor.Size(), info, 1, nil, nil}
+}
diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go b/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go
new file mode 100644
index 0000000000000000000000000000000000000000..6570847f5e07ae83da7cc84acb4c3048ce785ca9
--- /dev/null
+++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go
@@ -0,0 +1,264 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package ChaCha20 implements the core ChaCha20 function as specified
+// in https://tools.ietf.org/html/rfc7539#section-2.3.
+package chacha20
+
+import (
+	"crypto/cipher"
+	"encoding/binary"
+
+	"golang.org/x/crypto/internal/subtle"
+)
+
+// assert that *Cipher implements cipher.Stream
+var _ cipher.Stream = (*Cipher)(nil)
+
+// Cipher is a stateful instance of ChaCha20 using a particular key
+// and nonce. A *Cipher implements the cipher.Stream interface.
+type Cipher struct {
+	key     [8]uint32
+	counter uint32 // incremented after each block
+	nonce   [3]uint32
+	buf     [bufSize]byte // buffer for unused keystream bytes
+	len     int           // number of unused keystream bytes at end of buf
+}
+
+// New creates a new ChaCha20 stream cipher with the given key and nonce.
+// The initial counter value is set to 0.
+func New(key [8]uint32, nonce [3]uint32) *Cipher {
+	return &Cipher{key: key, nonce: nonce}
+}
+
+// ChaCha20 constants spelling "expand 32-byte k"
+const (
+	j0 uint32 = 0x61707865
+	j1 uint32 = 0x3320646e
+	j2 uint32 = 0x79622d32
+	j3 uint32 = 0x6b206574
+)
+
+func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
+	a += b
+	d ^= a
+	d = (d << 16) | (d >> 16)
+	c += d
+	b ^= c
+	b = (b << 12) | (b >> 20)
+	a += b
+	d ^= a
+	d = (d << 8) | (d >> 24)
+	c += d
+	b ^= c
+	b = (b << 7) | (b >> 25)
+	return a, b, c, d
+}
+
+// XORKeyStream XORs each byte in the given slice with a byte from the
+// cipher's key stream. Dst and src must overlap entirely or not at all.
+//
+// If len(dst) < len(src), XORKeyStream will panic. It is acceptable
+// to pass a dst bigger than src, and in that case, XORKeyStream will
+// only update dst[:len(src)] and will not touch the rest of dst.
+//
+// Multiple calls to XORKeyStream behave as if the concatenation of
+// the src buffers was passed in a single run. That is, Cipher
+// maintains state and does not reset at each XORKeyStream call.
+func (s *Cipher) XORKeyStream(dst, src []byte) {
+	if len(dst) < len(src) {
+		panic("chacha20: output smaller than input")
+	}
+	if subtle.InexactOverlap(dst[:len(src)], src) {
+		panic("chacha20: invalid buffer overlap")
+	}
+
+	// xor src with buffered keystream first
+	if s.len != 0 {
+		buf := s.buf[len(s.buf)-s.len:]
+		if len(src) < len(buf) {
+			buf = buf[:len(src)]
+		}
+		td, ts := dst[:len(buf)], src[:len(buf)] // BCE hint
+		for i, b := range buf {
+			td[i] = ts[i] ^ b
+		}
+		s.len -= len(buf)
+		if s.len != 0 {
+			return
+		}
+		s.buf = [len(s.buf)]byte{} // zero the empty buffer
+		src = src[len(buf):]
+		dst = dst[len(buf):]
+	}
+
+	if len(src) == 0 {
+		return
+	}
+	if haveAsm {
+		if uint64(len(src))+uint64(s.counter)*64 > (1<<38)-64 {
+			panic("chacha20: counter overflow")
+		}
+		s.xorKeyStreamAsm(dst, src)
+		return
+	}
+
+	// set up a 64-byte buffer to pad out the final block if needed
+	// (hoisted out of the main loop to avoid spills)
+	rem := len(src) % 64  // length of final block
+	fin := len(src) - rem // index of final block
+	if rem > 0 {
+		copy(s.buf[len(s.buf)-64:], src[fin:])
+	}
+
+	// pre-calculate most of the first round
+	s1, s5, s9, s13 := quarterRound(j1, s.key[1], s.key[5], s.nonce[0])
+	s2, s6, s10, s14 := quarterRound(j2, s.key[2], s.key[6], s.nonce[1])
+	s3, s7, s11, s15 := quarterRound(j3, s.key[3], s.key[7], s.nonce[2])
+
+	n := len(src)
+	src, dst = src[:n:n], dst[:n:n] // BCE hint
+	for i := 0; i < n; i += 64 {
+		// calculate the remainder of the first round
+		s0, s4, s8, s12 := quarterRound(j0, s.key[0], s.key[4], s.counter)
+
+		// execute the second round
+		x0, x5, x10, x15 := quarterRound(s0, s5, s10, s15)
+		x1, x6, x11, x12 := quarterRound(s1, s6, s11, s12)
+		x2, x7, x8, x13 := quarterRound(s2, s7, s8, s13)
+		x3, x4, x9, x14 := quarterRound(s3, s4, s9, s14)
+
+		// execute the remaining 18 rounds
+		for i := 0; i < 9; i++ {
+			x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
+			x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
+			x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
+			x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
+
+			x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
+			x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
+			x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
+			x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
+		}
+
+		x0 += j0
+		x1 += j1
+		x2 += j2
+		x3 += j3
+
+		x4 += s.key[0]
+		x5 += s.key[1]
+		x6 += s.key[2]
+		x7 += s.key[3]
+		x8 += s.key[4]
+		x9 += s.key[5]
+		x10 += s.key[6]
+		x11 += s.key[7]
+
+		x12 += s.counter
+		x13 += s.nonce[0]
+		x14 += s.nonce[1]
+		x15 += s.nonce[2]
+
+		// increment the counter
+		s.counter += 1
+		if s.counter == 0 {
+			panic("chacha20: counter overflow")
+		}
+
+		// pad to 64 bytes if needed
+		in, out := src[i:], dst[i:]
+		if i == fin {
+			// src[fin:] has already been copied into s.buf before
+			// the main loop
+			in, out = s.buf[len(s.buf)-64:], s.buf[len(s.buf)-64:]
+		}
+		in, out = in[:64], out[:64] // BCE hint
+
+		// XOR the key stream with the source and write out the result
+		xor(out[0:], in[0:], x0)
+		xor(out[4:], in[4:], x1)
+		xor(out[8:], in[8:], x2)
+		xor(out[12:], in[12:], x3)
+		xor(out[16:], in[16:], x4)
+		xor(out[20:], in[20:], x5)
+		xor(out[24:], in[24:], x6)
+		xor(out[28:], in[28:], x7)
+		xor(out[32:], in[32:], x8)
+		xor(out[36:], in[36:], x9)
+		xor(out[40:], in[40:], x10)
+		xor(out[44:], in[44:], x11)
+		xor(out[48:], in[48:], x12)
+		xor(out[52:], in[52:], x13)
+		xor(out[56:], in[56:], x14)
+		xor(out[60:], in[60:], x15)
+	}
+	// copy any trailing bytes out of the buffer and into dst
+	if rem != 0 {
+		s.len = 64 - rem
+		copy(dst[fin:], s.buf[len(s.buf)-64:])
+	}
+}
+
+// Advance discards bytes in the key stream until the next 64 byte block
+// boundary is reached and updates the counter accordingly. If the key
+// stream is already at a block boundary no bytes will be discarded and
+// the counter will be unchanged.
+func (s *Cipher) Advance() {
+	s.len -= s.len % 64
+	if s.len == 0 {
+		s.buf = [len(s.buf)]byte{}
+	}
+}
+
+// XORKeyStream crypts bytes from in to out using the given key and counters.
+// In and out must overlap entirely or not at all. Counter contains the raw
+// ChaCha20 counter bytes (i.e. block counter followed by nonce).
+func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
+	s := Cipher{
+		key: [8]uint32{
+			binary.LittleEndian.Uint32(key[0:4]),
+			binary.LittleEndian.Uint32(key[4:8]),
+			binary.LittleEndian.Uint32(key[8:12]),
+			binary.LittleEndian.Uint32(key[12:16]),
+			binary.LittleEndian.Uint32(key[16:20]),
+			binary.LittleEndian.Uint32(key[20:24]),
+			binary.LittleEndian.Uint32(key[24:28]),
+			binary.LittleEndian.Uint32(key[28:32]),
+		},
+		nonce: [3]uint32{
+			binary.LittleEndian.Uint32(counter[4:8]),
+			binary.LittleEndian.Uint32(counter[8:12]),
+			binary.LittleEndian.Uint32(counter[12:16]),
+		},
+		counter: binary.LittleEndian.Uint32(counter[0:4]),
+	}
+	s.XORKeyStream(out, in)
+}
+
+// HChaCha20 uses the ChaCha20 core to generate a derived key from a key and a
+// nonce. It should only be used as part of the XChaCha20 construction.
+func HChaCha20(key *[8]uint32, nonce *[4]uint32) [8]uint32 {
+	x0, x1, x2, x3 := j0, j1, j2, j3
+	x4, x5, x6, x7 := key[0], key[1], key[2], key[3]
+	x8, x9, x10, x11 := key[4], key[5], key[6], key[7]
+	x12, x13, x14, x15 := nonce[0], nonce[1], nonce[2], nonce[3]
+
+	for i := 0; i < 10; i++ {
+		x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
+		x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
+		x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
+		x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
+
+		x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
+		x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
+		x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
+		x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
+	}
+
+	var out [8]uint32
+	out[0], out[1], out[2], out[3] = x0, x1, x2, x3
+	out[4], out[5], out[6], out[7] = x12, x13, x14, x15
+	return out
+}
diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go b/vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go
new file mode 100644
index 0000000000000000000000000000000000000000..91520d1de079f2958f132a50dbdfba24c3bb4814
--- /dev/null
+++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go
@@ -0,0 +1,16 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !s390x gccgo appengine
+
+package chacha20
+
+const (
+	bufSize = 64
+	haveAsm = false
+)
+
+func (*Cipher) xorKeyStreamAsm(dst, src []byte) {
+	panic("not implemented")
+}
diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.go b/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.go
new file mode 100644
index 0000000000000000000000000000000000000000..0c1c671c40b77f6bdce6ecf16c4fc69ce57efb55
--- /dev/null
+++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.go
@@ -0,0 +1,30 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build s390x,!gccgo,!appengine
+
+package chacha20
+
+var haveAsm = hasVectorFacility()
+
+const bufSize = 256
+
+// hasVectorFacility reports whether the machine supports the vector
+// facility (vx).
+// Implementation in asm_s390x.s.
+func hasVectorFacility() bool
+
+// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only
+// be called when the vector facility is available.
+// Implementation in asm_s390x.s.
+//go:noescape
+func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32, buf *[256]byte, len *int)
+
+func (c *Cipher) xorKeyStreamAsm(dst, src []byte) {
+	xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter, &c.buf, &c.len)
+}
+
+// EXRL targets, DO NOT CALL!
+func mvcSrcToBuf()
+func mvcBufToDst()
diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.s b/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.s
new file mode 100644
index 0000000000000000000000000000000000000000..98427c5e222afb50882af5fc9a8846aa90aa3dde
--- /dev/null
+++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.s
@@ -0,0 +1,283 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build s390x,!gccgo,!appengine
+
+#include "go_asm.h"
+#include "textflag.h"
+
+// This is an implementation of the ChaCha20 encryption algorithm as
+// specified in RFC 7539. It uses vector instructions to compute
+// 4 keystream blocks in parallel (256 bytes) which are then XORed
+// with the bytes in the input slice.
+
+GLOBL ·constants<>(SB), RODATA|NOPTR, $32
+// BSWAP: swap bytes in each 4-byte element
+DATA ·constants<>+0x00(SB)/4, $0x03020100
+DATA ·constants<>+0x04(SB)/4, $0x07060504
+DATA ·constants<>+0x08(SB)/4, $0x0b0a0908
+DATA ·constants<>+0x0c(SB)/4, $0x0f0e0d0c
+// J0: [j0, j1, j2, j3]
+DATA ·constants<>+0x10(SB)/4, $0x61707865
+DATA ·constants<>+0x14(SB)/4, $0x3320646e
+DATA ·constants<>+0x18(SB)/4, $0x79622d32
+DATA ·constants<>+0x1c(SB)/4, $0x6b206574
+
+// EXRL targets:
+TEXT ·mvcSrcToBuf(SB), NOFRAME|NOSPLIT, $0
+	MVC $1, (R1), (R8)
+	RET
+
+TEXT ·mvcBufToDst(SB), NOFRAME|NOSPLIT, $0
+	MVC $1, (R8), (R9)
+	RET
+
+#define BSWAP V5
+#define J0    V6
+#define KEY0  V7
+#define KEY1  V8
+#define NONCE V9
+#define CTR   V10
+#define M0    V11
+#define M1    V12
+#define M2    V13
+#define M3    V14
+#define INC   V15
+#define X0    V16
+#define X1    V17
+#define X2    V18
+#define X3    V19
+#define X4    V20
+#define X5    V21
+#define X6    V22
+#define X7    V23
+#define X8    V24
+#define X9    V25
+#define X10   V26
+#define X11   V27
+#define X12   V28
+#define X13   V29
+#define X14   V30
+#define X15   V31
+
+#define NUM_ROUNDS 20
+
+#define ROUND4(a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3, d0, d1, d2, d3) \
+	VAF    a1, a0, a0  \
+	VAF    b1, b0, b0  \
+	VAF    c1, c0, c0  \
+	VAF    d1, d0, d0  \
+	VX     a0, a2, a2  \
+	VX     b0, b2, b2  \
+	VX     c0, c2, c2  \
+	VX     d0, d2, d2  \
+	VERLLF $16, a2, a2 \
+	VERLLF $16, b2, b2 \
+	VERLLF $16, c2, c2 \
+	VERLLF $16, d2, d2 \
+	VAF    a2, a3, a3  \
+	VAF    b2, b3, b3  \
+	VAF    c2, c3, c3  \
+	VAF    d2, d3, d3  \
+	VX     a3, a1, a1  \
+	VX     b3, b1, b1  \
+	VX     c3, c1, c1  \
+	VX     d3, d1, d1  \
+	VERLLF $12, a1, a1 \
+	VERLLF $12, b1, b1 \
+	VERLLF $12, c1, c1 \
+	VERLLF $12, d1, d1 \
+	VAF    a1, a0, a0  \
+	VAF    b1, b0, b0  \
+	VAF    c1, c0, c0  \
+	VAF    d1, d0, d0  \
+	VX     a0, a2, a2  \
+	VX     b0, b2, b2  \
+	VX     c0, c2, c2  \
+	VX     d0, d2, d2  \
+	VERLLF $8, a2, a2  \
+	VERLLF $8, b2, b2  \
+	VERLLF $8, c2, c2  \
+	VERLLF $8, d2, d2  \
+	VAF    a2, a3, a3  \
+	VAF    b2, b3, b3  \
+	VAF    c2, c3, c3  \
+	VAF    d2, d3, d3  \
+	VX     a3, a1, a1  \
+	VX     b3, b1, b1  \
+	VX     c3, c1, c1  \
+	VX     d3, d1, d1  \
+	VERLLF $7, a1, a1  \
+	VERLLF $7, b1, b1  \
+	VERLLF $7, c1, c1  \
+	VERLLF $7, d1, d1
+
+#define PERMUTE(mask, v0, v1, v2, v3) \
+	VPERM v0, v0, mask, v0 \
+	VPERM v1, v1, mask, v1 \
+	VPERM v2, v2, mask, v2 \
+	VPERM v3, v3, mask, v3
+
+#define ADDV(x, v0, v1, v2, v3) \
+	VAF x, v0, v0 \
+	VAF x, v1, v1 \
+	VAF x, v2, v2 \
+	VAF x, v3, v3
+
+#define XORV(off, dst, src, v0, v1, v2, v3) \
+	VLM  off(src), M0, M3          \
+	PERMUTE(BSWAP, v0, v1, v2, v3) \
+	VX   v0, M0, M0                \
+	VX   v1, M1, M1                \
+	VX   v2, M2, M2                \
+	VX   v3, M3, M3                \
+	VSTM M0, M3, off(dst)
+
+#define SHUFFLE(a, b, c, d, t, u, v, w) \
+	VMRHF a, c, t \ // t = {a[0], c[0], a[1], c[1]}
+	VMRHF b, d, u \ // u = {b[0], d[0], b[1], d[1]}
+	VMRLF a, c, v \ // v = {a[2], c[2], a[3], c[3]}
+	VMRLF b, d, w \ // w = {b[2], d[2], b[3], d[3]}
+	VMRHF t, u, a \ // a = {a[0], b[0], c[0], d[0]}
+	VMRLF t, u, b \ // b = {a[1], b[1], c[1], d[1]}
+	VMRHF v, w, c \ // c = {a[2], b[2], c[2], d[2]}
+	VMRLF v, w, d // d = {a[3], b[3], c[3], d[3]}
+
+// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32, buf *[256]byte, len *int)
+TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
+	MOVD $·constants<>(SB), R1
+	MOVD dst+0(FP), R2         // R2=&dst[0]
+	LMG  src+24(FP), R3, R4    // R3=&src[0] R4=len(src)
+	MOVD key+48(FP), R5        // R5=key
+	MOVD nonce+56(FP), R6      // R6=nonce
+	MOVD counter+64(FP), R7    // R7=counter
+	MOVD buf+72(FP), R8        // R8=buf
+	MOVD len+80(FP), R9        // R9=len
+
+	// load BSWAP and J0
+	VLM (R1), BSWAP, J0
+
+	// set up tail buffer
+	ADD     $-1, R4, R12
+	MOVBZ   R12, R12
+	CMPUBEQ R12, $255, aligned
+	MOVD    R4, R1
+	AND     $~255, R1
+	MOVD    $(R3)(R1*1), R1
+	EXRL    $·mvcSrcToBuf(SB), R12
+	MOVD    $255, R0
+	SUB     R12, R0
+	MOVD    R0, (R9)               // update len
+
+aligned:
+	// setup
+	MOVD  $95, R0
+	VLM   (R5), KEY0, KEY1
+	VLL   R0, (R6), NONCE
+	VZERO M0
+	VLEIB $7, $32, M0
+	VSRLB M0, NONCE, NONCE
+
+	// initialize counter values
+	VLREPF (R7), CTR
+	VZERO  INC
+	VLEIF  $1, $1, INC
+	VLEIF  $2, $2, INC
+	VLEIF  $3, $3, INC
+	VAF    INC, CTR, CTR
+	VREPIF $4, INC
+
+chacha:
+	VREPF $0, J0, X0
+	VREPF $1, J0, X1
+	VREPF $2, J0, X2
+	VREPF $3, J0, X3
+	VREPF $0, KEY0, X4
+	VREPF $1, KEY0, X5
+	VREPF $2, KEY0, X6
+	VREPF $3, KEY0, X7
+	VREPF $0, KEY1, X8
+	VREPF $1, KEY1, X9
+	VREPF $2, KEY1, X10
+	VREPF $3, KEY1, X11
+	VLR   CTR, X12
+	VREPF $1, NONCE, X13
+	VREPF $2, NONCE, X14
+	VREPF $3, NONCE, X15
+
+	MOVD $(NUM_ROUNDS/2), R1
+
+loop:
+	ROUND4(X0, X4, X12,  X8, X1, X5, X13,  X9, X2, X6, X14, X10, X3, X7, X15, X11)
+	ROUND4(X0, X5, X15, X10, X1, X6, X12, X11, X2, X7, X13, X8,  X3, X4, X14, X9)
+
+	ADD $-1, R1
+	BNE loop
+
+	// decrement length
+	ADD $-256, R4
+	BLT tail
+
+continue:
+	// rearrange vectors
+	SHUFFLE(X0, X1, X2, X3, M0, M1, M2, M3)
+	ADDV(J0, X0, X1, X2, X3)
+	SHUFFLE(X4, X5, X6, X7, M0, M1, M2, M3)
+	ADDV(KEY0, X4, X5, X6, X7)
+	SHUFFLE(X8, X9, X10, X11, M0, M1, M2, M3)
+	ADDV(KEY1, X8, X9, X10, X11)
+	VAF CTR, X12, X12
+	SHUFFLE(X12, X13, X14, X15, M0, M1, M2, M3)
+	ADDV(NONCE, X12, X13, X14, X15)
+
+	// increment counters
+	VAF INC, CTR, CTR
+
+	// xor keystream with plaintext
+	XORV(0*64, R2, R3, X0, X4,  X8, X12)
+	XORV(1*64, R2, R3, X1, X5,  X9, X13)
+	XORV(2*64, R2, R3, X2, X6, X10, X14)
+	XORV(3*64, R2, R3, X3, X7, X11, X15)
+
+	// increment pointers
+	MOVD $256(R2), R2
+	MOVD $256(R3), R3
+
+	CMPBNE  R4, $0, chacha
+	CMPUBEQ R12, $255, return
+	EXRL    $·mvcBufToDst(SB), R12 // len was updated during setup
+
+return:
+	VSTEF $0, CTR, (R7)
+	RET
+
+tail:
+	MOVD R2, R9
+	MOVD R8, R2
+	MOVD R8, R3
+	MOVD $0, R4
+	JMP  continue
+
+// func hasVectorFacility() bool
+TEXT ·hasVectorFacility(SB), NOSPLIT, $24-1
+	MOVD  $x-24(SP), R1
+	XC    $24, 0(R1), 0(R1) // clear the storage
+	MOVD  $2, R0            // R0 is the number of double words stored -1
+	WORD  $0xB2B01000       // STFLE 0(R1)
+	XOR   R0, R0            // reset the value of R0
+	MOVBZ z-8(SP), R1
+	AND   $0x40, R1
+	BEQ   novector
+
+vectorinstalled:
+	// check if the vector instruction has been enabled
+	VLEIB  $0, $0xF, V16
+	VLGVB  $0, V16, R1
+	CMPBNE R1, $0xF, novector
+	MOVB   $1, ret+0(FP)      // have vx
+	RET
+
+novector:
+	MOVB $0, ret+0(FP) // no vx
+	RET
diff --git a/vendor/golang.org/x/crypto/internal/chacha20/xor.go b/vendor/golang.org/x/crypto/internal/chacha20/xor.go
new file mode 100644
index 0000000000000000000000000000000000000000..9c5ba0b33ae3a873c3c8f1aa7d0c9f303d65b74d
--- /dev/null
+++ b/vendor/golang.org/x/crypto/internal/chacha20/xor.go
@@ -0,0 +1,43 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found src the LICENSE file.
+
+package chacha20
+
+import (
+	"runtime"
+)
+
+// Platforms that have fast unaligned 32-bit little endian accesses.
+const unaligned = runtime.GOARCH == "386" ||
+	runtime.GOARCH == "amd64" ||
+	runtime.GOARCH == "arm64" ||
+	runtime.GOARCH == "ppc64le" ||
+	runtime.GOARCH == "s390x"
+
+// xor reads a little endian uint32 from src, XORs it with u and
+// places the result in little endian byte order in dst.
+func xor(dst, src []byte, u uint32) {
+	_, _ = src[3], dst[3] // eliminate bounds checks
+	if unaligned {
+		// The compiler should optimize this code into
+		// 32-bit unaligned little endian loads and stores.
+		// TODO: delete once the compiler does a reliably
+		// good job with the generic code below.
+		// See issue #25111 for more details.
+		v := uint32(src[0])
+		v |= uint32(src[1]) << 8
+		v |= uint32(src[2]) << 16
+		v |= uint32(src[3]) << 24
+		v ^= u
+		dst[0] = byte(v)
+		dst[1] = byte(v >> 8)
+		dst[2] = byte(v >> 16)
+		dst[3] = byte(v >> 24)
+	} else {
+		dst[0] = src[0] ^ byte(u)
+		dst[1] = src[1] ^ byte(u>>8)
+		dst[2] = src[2] ^ byte(u>>16)
+		dst[3] = src[3] ^ byte(u>>24)
+	}
+}