From 88ac31f8755b3182629205608fe3c886359e0925 Mon Sep 17 00:00:00 2001 From: Marko Date: Fri, 17 Jan 2020 11:31:44 +0100 Subject: [PATCH 01/45] docs: update theme version (#4315) Signed-off-by: Marko Baricevic --- docs/package-lock.json | 2 +- docs/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index e96344500..78267219c 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -9624,4 +9624,4 @@ "integrity": "sha1-4Se9nmb9hGvl6rSME5SIL3wOT5g=" } } -} \ No newline at end of file +} diff --git a/docs/package.json b/docs/package.json index 0358a91a3..15a4f5482 100644 --- a/docs/package.json +++ b/docs/package.json @@ -4,7 +4,7 @@ "description": "Welcome to the Tendermint Core documentation!", "main": "index.js", "dependencies": { - "vuepress-theme-cosmos": "^1.0.73" + "vuepress-theme-cosmos": "^1.0.135" }, "devDependencies": { "@vuepress/plugin-google-analytics": "^1.2.0" From a3dc82b10fcb87414fd2ae8b270f4e16eb2840eb Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 17 Jan 2020 16:12:14 +0400 Subject: [PATCH 02/45] deps: bump github.com/spf13/viper from 1.6.1 to 1.6.2 (#4318) Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.6.1 to 1.6.2. - [Release notes](https://github.com/spf13/viper/releases) - [Commits](https://github.com/spf13/viper/compare/v1.6.1...v1.6.2) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 9fe06e48e..3d1dc21c3 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/rs/cors v1.7.0 github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa github.com/spf13/cobra v0.0.1 - github.com/spf13/viper v1.6.1 + github.com/spf13/viper v1.6.2 github.com/stretchr/testify v1.4.0 github.com/tendermint/go-amino v0.14.1 github.com/tendermint/tm-db v0.4.0 diff --git a/go.sum b/go.sum index fbbeb485e..31930911c 100644 --- a/go.sum +++ b/go.sum @@ -199,6 +199,8 @@ github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.6.1 h1:VPZzIkznI1YhVMRi6vNFLHSwhnhReBfgTxIPccpfdZk= github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= +github.com/spf13/viper v1.6.2 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E= +github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From b50cb26664ccd6c32a4499a86dee9e8eccf3d5ce Mon Sep 17 00:00:00 2001 From: Marko Date: Fri, 17 Jan 2020 18:32:31 +0100 Subject: [PATCH 03/45] rpc: check nil blockmeta (#4320) * rpc: check nil blockmeta - fixes #4319 - check if block meta is nil Signed-off-by: Marko Baricevic * add changelog entry --- CHANGELOG_PENDING.md | 2 ++ rpc/core/blocks.go | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index be210ae52..aac1e6542 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -21,4 +21,6 @@ program](https://hackerone.com/tendermint). ### BUG FIXES: +- [rpc] [#\4319] Check BlockMeta is not nil in Blocks & BlockByHash + diff --git a/rpc/core/blocks.go b/rpc/core/blocks.go index ed3c4257b..777981b06 100644 --- a/rpc/core/blocks.go +++ b/rpc/core/blocks.go @@ -76,8 +76,11 @@ func Block(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultBlock, error) return nil, err } - blockMeta := blockStore.LoadBlockMeta(height) block := blockStore.LoadBlock(height) + blockMeta := blockStore.LoadBlockMeta(height) + if blockMeta == nil { + return &ctypes.ResultBlock{BlockID: types.BlockID{}, Block: block}, nil + } return &ctypes.ResultBlock{BlockID: blockMeta.BlockID, Block: block}, nil } @@ -88,6 +91,9 @@ func BlockByHash(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultBlock, error height := block.Height blockMeta := blockStore.LoadBlockMeta(height) + if blockMeta == nil { + return &ctypes.ResultBlock{BlockID: types.BlockID{}, Block: block}, nil + } return &ctypes.ResultBlock{BlockID: blockMeta.BlockID, Block: block}, nil } From 9cbfe7950d3f0dd10855984defbc3955e3a386d0 Mon Sep 17 00:00:00 2001 From: Erik Grinaker Date: Sat, 18 Jan 2020 19:01:18 +0100 Subject: [PATCH 04/45] tests: bind test servers to 127.0.0.1 (#4322) --- config/config.go | 6 +++--- consensus/wal_generator.go | 6 +++--- p2p/netaddress.go | 2 +- rpc/lib/rpc_test.go | 2 +- rpc/lib/test/main.go | 2 +- rpc/test/helpers.go | 6 +++--- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/config/config.go b/config/config.go index 38ea4ba0f..dc3eff7d1 100644 --- a/config/config.go +++ b/config/config.go @@ -415,8 +415,8 @@ func DefaultRPCConfig() *RPCConfig { // TestRPCConfig returns a configuration for testing the RPC server func TestRPCConfig() *RPCConfig { cfg := DefaultRPCConfig() - cfg.ListenAddress = "tcp://0.0.0.0:36657" - cfg.GRPCListenAddress = "tcp://0.0.0.0:36658" + cfg.ListenAddress = "tcp://127.0.0.1:36657" + cfg.GRPCListenAddress = "tcp://127.0.0.1:36658" cfg.Unsafe = true return cfg } @@ -584,7 +584,7 @@ func DefaultP2PConfig() *P2PConfig { // TestP2PConfig returns a configuration for testing the peer-to-peer layer func TestP2PConfig() *P2PConfig { cfg := DefaultP2PConfig() - cfg.ListenAddress = "tcp://0.0.0.0:36656" + cfg.ListenAddress = "tcp://127.0.0.1:36656" cfg.FlushThrottleTimeout = 10 * time.Millisecond cfg.AllowDuplicateIP = true return cfg diff --git a/consensus/wal_generator.go b/consensus/wal_generator.go index 64ac95210..244edd536 100644 --- a/consensus/wal_generator.go +++ b/consensus/wal_generator.go @@ -125,9 +125,9 @@ func randPort() int { func makeAddrs() (string, string, string) { start := randPort() - return fmt.Sprintf("tcp://0.0.0.0:%d", start), - fmt.Sprintf("tcp://0.0.0.0:%d", start+1), - fmt.Sprintf("tcp://0.0.0.0:%d", start+2) + return fmt.Sprintf("tcp://127.0.0.1:%d", start), + fmt.Sprintf("tcp://127.0.0.1:%d", start+1), + fmt.Sprintf("tcp://127.0.0.1:%d", start+2) } // getConfig returns a config for test cases diff --git a/p2p/netaddress.go b/p2p/netaddress.go index ed5b703e7..c71f3ce7f 100644 --- a/p2p/netaddress.go +++ b/p2p/netaddress.go @@ -48,7 +48,7 @@ func NewNetAddress(id ID, addr net.Addr) *NetAddress { if flag.Lookup("test.v") == nil { // normal run panic(fmt.Sprintf("Only TCPAddrs are supported. Got: %v", addr)) } else { // in testing - netAddr := NewNetAddressIPPort(net.IP("0.0.0.0"), 0) + netAddr := NewNetAddressIPPort(net.IP("127.0.0.1"), 0) netAddr.ID = id return netAddr } diff --git a/rpc/lib/rpc_test.go b/rpc/lib/rpc_test.go index fbf041f57..5b95666a7 100644 --- a/rpc/lib/rpc_test.go +++ b/rpc/lib/rpc_test.go @@ -28,7 +28,7 @@ import ( // Client and Server should work over tcp or unix sockets const ( - tcpAddr = "tcp://0.0.0.0:47768" + tcpAddr = "tcp://127.0.0.1:47768" unixSocket = "/tmp/rpc_test.sock" unixAddr = "unix://" + unixSocket diff --git a/rpc/lib/test/main.go b/rpc/lib/test/main.go index 891f9388d..a7141048c 100644 --- a/rpc/lib/test/main.go +++ b/rpc/lib/test/main.go @@ -37,7 +37,7 @@ func main() { rpcserver.RegisterRPCFuncs(mux, routes, cdc, logger) config := rpcserver.DefaultConfig() - listener, err := rpcserver.Listen("0.0.0.0:8008", config) + listener, err := rpcserver.Listen("tcp://127.0.0.1:8008", config) if err != nil { tmos.Exit(err.Error()) } diff --git a/rpc/test/helpers.go b/rpc/test/helpers.go index 0b25b2e5f..46aea59e1 100644 --- a/rpc/test/helpers.go +++ b/rpc/test/helpers.go @@ -85,9 +85,9 @@ func randPort() int { } func makeAddrs() (string, string, string) { - return fmt.Sprintf("tcp://0.0.0.0:%d", randPort()), - fmt.Sprintf("tcp://0.0.0.0:%d", randPort()), - fmt.Sprintf("tcp://0.0.0.0:%d", randPort()) + return fmt.Sprintf("tcp://127.0.0.1:%d", randPort()), + fmt.Sprintf("tcp://127.0.0.1:%d", randPort()), + fmt.Sprintf("tcp://127.0.0.1:%d", randPort()) } func createConfig() *cfg.Config { From 2d510d2f272c7b96926477987ef7b7e9e3f5667c Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 20 Jan 2020 14:41:26 +0400 Subject: [PATCH 05/45] rpc: PR#4320 follow up (#4323) * rpc: update urls to rpc website * rpc: check blockMeta is not nil in Commit Refs #4319 --- rpc/core/abci.go | 4 ++-- rpc/core/blocks.go | 26 ++++++++++++++------------ rpc/core/consensus.go | 6 +++--- rpc/core/events.go | 6 +++--- rpc/core/evidence.go | 2 +- rpc/core/health.go | 2 +- rpc/core/mempool.go | 10 +++++----- rpc/core/net.go | 4 ++-- rpc/core/status.go | 3 ++- rpc/core/tx.go | 5 ++--- 10 files changed, 35 insertions(+), 33 deletions(-) diff --git a/rpc/core/abci.go b/rpc/core/abci.go index a9955d1a5..8f135ba26 100644 --- a/rpc/core/abci.go +++ b/rpc/core/abci.go @@ -9,7 +9,7 @@ import ( ) // ABCIQuery queries the application for some information. -// More: https://tendermint.com/rpc/#/ABCI/abci_query +// More: https://docs.tendermint.com/master/rpc/#/ABCI/abci_query func ABCIQuery( ctx *rpctypes.Context, path string, @@ -31,7 +31,7 @@ func ABCIQuery( } // ABCIInfo gets some info about the application. -// More: https://tendermint.com/rpc/#/ABCI/abci_info +// More: https://docs.tendermint.com/master/rpc/#/ABCI/abci_info func ABCIInfo(ctx *rpctypes.Context) (*ctypes.ResultABCIInfo, error) { resInfo, err := proxyAppQuery.InfoSync(proxy.RequestInfo) if err != nil { diff --git a/rpc/core/blocks.go b/rpc/core/blocks.go index 777981b06..e340d4dfb 100644 --- a/rpc/core/blocks.go +++ b/rpc/core/blocks.go @@ -12,9 +12,8 @@ import ( // BlockchainInfo gets block headers for minHeight <= height <= maxHeight. // Block headers are returned in descending order (highest first). -// More: https://tendermint.com/rpc/#/Info/blockchain +// More: https://docs.tendermint.com/master/rpc/#/Info/blockchain func BlockchainInfo(ctx *rpctypes.Context, minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) { - // maximum 20 block metas const limit int64 = 20 var err error @@ -68,7 +67,7 @@ func filterMinMax(height, min, max, limit int64) (int64, int64, error) { // Block gets block at a given height. // If no height is provided, it will fetch the latest block. -// More: https://tendermint.com/rpc/#/Info/block +// More: https://docs.tendermint.com/master/rpc/#/Info/block func Block(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultBlock, error) { storeHeight := blockStore.Height() height, err := getHeight(storeHeight, heightPtr) @@ -85,21 +84,20 @@ func Block(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultBlock, error) } // BlockByHash gets block by hash. -// More: https://tendermint.com/rpc/#/Info/block_by_hash +// More: https://docs.tendermint.com/master/rpc/#/Info/block_by_hash func BlockByHash(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultBlock, error) { block := blockStore.LoadBlockByHash(hash) - height := block.Height - - blockMeta := blockStore.LoadBlockMeta(height) - if blockMeta == nil { - return &ctypes.ResultBlock{BlockID: types.BlockID{}, Block: block}, nil + if block == nil { + return &ctypes.ResultBlock{BlockID: types.BlockID{}, Block: nil}, nil } + // If block is not nil, then blockMeta can't be nil. + blockMeta := blockStore.LoadBlockMeta(block.Height) return &ctypes.ResultBlock{BlockID: blockMeta.BlockID, Block: block}, nil } // Commit gets block commit at a given height. // If no height is provided, it will fetch the commit for the latest block. -// More: https://tendermint.com/rpc/#/Info/commit +// More: https://docs.tendermint.com/master/rpc/#/Info/commit func Commit(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultCommit, error) { storeHeight := blockStore.Height() height, err := getHeight(storeHeight, heightPtr) @@ -107,7 +105,11 @@ func Commit(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultCommit, erro return nil, err } - header := blockStore.LoadBlockMeta(height).Header + blockMeta := blockStore.LoadBlockMeta(height) + if blockMeta == nil { + return nil, nil + } + header := blockMeta.Header // If the next block has not been committed yet, // use a non-canonical commit @@ -127,7 +129,7 @@ func Commit(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultCommit, erro // Results are for the height of the block containing the txs. // Thus response.results.deliver_tx[5] is the results of executing // getBlock(h).Txs[5] -// More: https://tendermint.com/rpc/#/Info/block_results +// More: https://docs.tendermint.com/master/rpc/#/Info/block_results func BlockResults(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultBlockResults, error) { storeHeight := blockStore.Height() height, err := getHeight(storeHeight, heightPtr) diff --git a/rpc/core/consensus.go b/rpc/core/consensus.go index 6a5a49e03..d88a6ba6a 100644 --- a/rpc/core/consensus.go +++ b/rpc/core/consensus.go @@ -13,7 +13,7 @@ import ( // If no height is provided, it will fetch the current validator set. // Note the validators are sorted by their address - this is the canonical // order for the validators in the set as used in computing their Merkle root. -// More: https://tendermint.com/rpc/#/Info/validators +// More: https://docs.tendermint.com/master/rpc/#/Info/validators func Validators(ctx *rpctypes.Context, heightPtr *int64, page, perPage int) (*ctypes.ResultValidators, error) { // The latest validator that we know is the // NextValidator of the last block. @@ -46,7 +46,7 @@ func Validators(ctx *rpctypes.Context, heightPtr *int64, page, perPage int) (*ct // DumpConsensusState dumps consensus state. // UNSTABLE -// More: https://tendermint.com/rpc/#/Info/dump_consensus_state +// More: https://docs.tendermint.com/master/rpc/#/Info/dump_consensus_state func DumpConsensusState(ctx *rpctypes.Context) (*ctypes.ResultDumpConsensusState, error) { // Get Peer consensus states. peers := p2pPeers.Peers().List() @@ -88,7 +88,7 @@ func ConsensusState(ctx *rpctypes.Context) (*ctypes.ResultConsensusState, error) // ConsensusParams gets the consensus parameters at the given block height. // If no height is provided, it will fetch the current consensus params. -// More: https://tendermint.com/rpc/#/Info/consensus_params +// More: https://docs.tendermint.com/master/rpc/#/Info/consensus_params func ConsensusParams(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultConsensusParams, error) { height := consensusState.GetState().LastBlockHeight + 1 height, err := getHeight(height, heightPtr) diff --git a/rpc/core/events.go b/rpc/core/events.go index 49bf7be5d..2a4d042fc 100644 --- a/rpc/core/events.go +++ b/rpc/core/events.go @@ -13,7 +13,7 @@ import ( ) // Subscribe for events via WebSocket. -// More: https://tendermint.com/rpc/#/Websocket/subscribe +// More: https://docs.tendermint.com/master/rpc/#/Websocket/subscribe func Subscribe(ctx *rpctypes.Context, query string) (*ctypes.ResultSubscribe, error) { addr := ctx.RemoteAddr() @@ -72,7 +72,7 @@ func Subscribe(ctx *rpctypes.Context, query string) (*ctypes.ResultSubscribe, er } // Unsubscribe from events via WebSocket. -// More: https://tendermint.com/rpc/#/Websocket/unsubscribe +// More: https://docs.tendermint.com/master/rpc/#/Websocket/unsubscribe func Unsubscribe(ctx *rpctypes.Context, query string) (*ctypes.ResultUnsubscribe, error) { addr := ctx.RemoteAddr() logger.Info("Unsubscribe from query", "remote", addr, "query", query) @@ -88,7 +88,7 @@ func Unsubscribe(ctx *rpctypes.Context, query string) (*ctypes.ResultUnsubscribe } // UnsubscribeAll from all events via WebSocket. -// More: https://tendermint.com/rpc/#/Websocket/unsubscribe_all +// More: https://docs.tendermint.com/master/rpc/#/Websocket/unsubscribe_all func UnsubscribeAll(ctx *rpctypes.Context) (*ctypes.ResultUnsubscribe, error) { addr := ctx.RemoteAddr() logger.Info("Unsubscribe from all", "remote", addr) diff --git a/rpc/core/evidence.go b/rpc/core/evidence.go index 7edda8b57..4ae138e7e 100644 --- a/rpc/core/evidence.go +++ b/rpc/core/evidence.go @@ -7,7 +7,7 @@ import ( ) // BroadcastEvidence broadcasts evidence of the misbehavior. -// More: https://tendermint.com/rpc/#/Info/broadcast_evidence +// More: https://docs.tendermint.com/master/rpc/#/Info/broadcast_evidence func BroadcastEvidence(ctx *rpctypes.Context, ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) { err := evidencePool.AddEvidence(ev) if err != nil { diff --git a/rpc/core/health.go b/rpc/core/health.go index 3d4f70dd1..eb715bea0 100644 --- a/rpc/core/health.go +++ b/rpc/core/health.go @@ -7,7 +7,7 @@ import ( // Health gets node health. Returns empty result (200 OK) on success, no // response - in case of an error. -// More: https://tendermint.com/rpc/#/Info/health +// More: https://docs.tendermint.com/master/rpc/#/Info/health func Health(ctx *rpctypes.Context) (*ctypes.ResultHealth, error) { return &ctypes.ResultHealth{}, nil } diff --git a/rpc/core/mempool.go b/rpc/core/mempool.go index 03123d057..28b73ab33 100644 --- a/rpc/core/mempool.go +++ b/rpc/core/mempool.go @@ -19,7 +19,7 @@ import ( // BroadcastTxAsync returns right away, with no response. Does not wait for // CheckTx nor DeliverTx results. -// More: https://tendermint.com/rpc/#/Tx/broadcast_tx_async +// More: https://docs.tendermint.com/master/rpc/#/Tx/broadcast_tx_async func BroadcastTxAsync(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { err := mempool.CheckTx(tx, nil, mempl.TxInfo{}) @@ -31,7 +31,7 @@ func BroadcastTxAsync(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadca // BroadcastTxSync returns with the response from CheckTx. Does not wait for // DeliverTx result. -// More: https://tendermint.com/rpc/#/Tx/broadcast_tx_sync +// More: https://docs.tendermint.com/master/rpc/#/Tx/broadcast_tx_sync func BroadcastTxSync(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { resCh := make(chan *abci.Response, 1) err := mempool.CheckTx(tx, func(res *abci.Response) { @@ -51,7 +51,7 @@ func BroadcastTxSync(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcas } // BroadcastTxCommit returns with the responses from CheckTx and DeliverTx. -// More: https://tendermint.com/rpc/#/Tx/broadcast_tx_commit +// More: https://docs.tendermint.com/master/rpc/#/Tx/broadcast_tx_commit func BroadcastTxCommit(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) { subscriber := ctx.RemoteAddr() @@ -129,7 +129,7 @@ func BroadcastTxCommit(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadc // UnconfirmedTxs gets unconfirmed transactions (maximum ?limit entries) // including their number. -// More: https://tendermint.com/rpc/#/Info/unconfirmed_txs +// More: https://docs.tendermint.com/master/rpc/#/Info/unconfirmed_txs func UnconfirmedTxs(ctx *rpctypes.Context, limit int) (*ctypes.ResultUnconfirmedTxs, error) { // reuse per_page validator limit = validatePerPage(limit) @@ -143,7 +143,7 @@ func UnconfirmedTxs(ctx *rpctypes.Context, limit int) (*ctypes.ResultUnconfirmed } // NumUnconfirmedTxs gets number of unconfirmed transactions. -// More: https://tendermint.com/rpc/#/Info/num_unconfirmed_txs +// More: https://docs.tendermint.com/master/rpc/#/Info/num_unconfirmed_txs func NumUnconfirmedTxs(ctx *rpctypes.Context) (*ctypes.ResultUnconfirmedTxs, error) { return &ctypes.ResultUnconfirmedTxs{ Count: mempool.Size(), diff --git a/rpc/core/net.go b/rpc/core/net.go index 6f3e4bb7f..4a3d67d4f 100644 --- a/rpc/core/net.go +++ b/rpc/core/net.go @@ -11,7 +11,7 @@ import ( ) // NetInfo returns network info. -// More: https://tendermint.com/rpc/#/Info/net_info +// More: https://docs.tendermint.com/master/rpc/#/Info/net_info func NetInfo(ctx *rpctypes.Context) (*ctypes.ResultNetInfo, error) { peersList := p2pPeers.Peers().List() peers := make([]ctypes.Peer, 0, len(peersList)) @@ -69,7 +69,7 @@ func UnsafeDialPeers(ctx *rpctypes.Context, peers []string, persistent bool) (*c } // Genesis returns genesis file. -// More: https://tendermint.com/rpc/#/Info/genesis +// More: https://docs.tendermint.com/master/rpc/#/Info/genesis func Genesis(ctx *rpctypes.Context) (*ctypes.ResultGenesis, error) { return &ctypes.ResultGenesis{Genesis: genDoc}, nil } diff --git a/rpc/core/status.go b/rpc/core/status.go index 36c521f30..e6438009a 100644 --- a/rpc/core/status.go +++ b/rpc/core/status.go @@ -14,7 +14,7 @@ import ( // Status returns Tendermint status including node info, pubkey, latest block // hash, app hash, block height and time. -// More: https://tendermint.com/rpc/#/Info/status +// More: https://docs.tendermint.com/master/rpc/#/Info/status func Status(ctx *rpctypes.Context) (*ctypes.ResultStatus, error) { var latestHeight int64 if consensusReactor.FastSync() { @@ -22,6 +22,7 @@ func Status(ctx *rpctypes.Context) (*ctypes.ResultStatus, error) { } else { latestHeight = consensusState.GetLastHeight() } + var ( latestBlockMeta *types.BlockMeta latestBlockHash tmbytes.HexBytes diff --git a/rpc/core/tx.go b/rpc/core/tx.go index 26d5364f4..f3cd54e4f 100644 --- a/rpc/core/tx.go +++ b/rpc/core/tx.go @@ -15,9 +15,8 @@ import ( // Tx allows you to query the transaction results. `nil` could mean the // transaction is in the mempool, invalidated, or was not sent in the first // place. -// More: https://tendermint.com/rpc/#/Info/tx +// More: https://docs.tendermint.com/master/rpc/#/Info/tx func Tx(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) { - // if index is disabled, return error if _, ok := txIndexer.(*null.TxIndex); ok { return nil, fmt.Errorf("transaction indexing is disabled") @@ -53,7 +52,7 @@ func Tx(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error // TxSearch allows you to query for multiple transactions results. It returns a // list of transactions (maximum ?per_page entries) and the total count. -// More: https://tendermint.com/rpc/#/Info/tx_search +// More: https://docs.tendermint.com/master/rpc/#/Info/tx_search func TxSearch(ctx *rpctypes.Context, query string, prove bool, page, perPage int) (*ctypes.ResultTxSearch, error) { // if index is disabled, return error if _, ok := txIndexer.(*null.TxIndex); ok { From 5f2f97548f8714e05f5dae877ea2972d3e074187 Mon Sep 17 00:00:00 2001 From: dongsamb Date: Wed, 22 Jan 2020 16:03:05 +0900 Subject: [PATCH 06/45] adr: ADR-052: Tendermint Mode (#4302) * Separate ADR Tendermint Mode from ADR-051 * Update docs/architecture/adr-052-tendermint-mode.md Co-Authored-By: Anton Kaliaev * Apply suggestions from code review Co-Authored-By: Marko * Apply suggestions from code review Co-Authored-By: Marko * remove line of mode info of rpc * Add link to ADR table of contents Co-authored-by: Anton Kaliaev Co-authored-by: Marko Fullnode mode : fullnode mode does not have any capability to participate on consensus Validator mode : this mode is exactly same as existing state machine behavior. sync without voting on consensus, and participate consensus when fully synced Seed mode : lightweight seed mode only for maintain an address book, p2p like TenderSeed Separate ADR Tendermint Mode from ADR-051 #4262 --- docs/architecture/README.md | 1 + docs/architecture/adr-052-tendermint-mode.md | 81 ++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 docs/architecture/adr-052-tendermint-mode.md diff --git a/docs/architecture/README.md b/docs/architecture/README.md index cc507ae78..d29a49c81 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -64,3 +64,4 @@ Note the context/background should be written in the present tense. - [ADR-039-Peer-Behaviour](./adr-039-peer-behaviour.md) - [ADR-041-Proposer-Selection-via-ABCI](./adr-041-proposer-selection-via-abci.md) - [ADR-043-Blockchain-RiRi-Org](./adr-043-blockchain-riri-org.md) +- [ADR-052-Tendermint-Mode](./adr-052-tendermint-mode.md) diff --git a/docs/architecture/adr-052-tendermint-mode.md b/docs/architecture/adr-052-tendermint-mode.md new file mode 100644 index 000000000..edf217a06 --- /dev/null +++ b/docs/architecture/adr-052-tendermint-mode.md @@ -0,0 +1,81 @@ +# ADR 052: Tendermint Mode + +## Changelog + +* 27-11-2019: Initial draft from ADR-051 +* 13-01-2020: Separate ADR Tendermint Mode from ADR-051 + +## Context + +- Fullnode mode: fullnode mode does not have the capability to become a validator. +- Validator mode : this mode is exactly same as existing state machine behavior. sync without voting on consensus, and participate consensus when fully synced +- Seed mode : lightweight seed mode maintaining an address book, p2p like [TenderSeed](https://gitlab.com/polychainlabs/tenderseed) + +## Decision + +We would like to suggest a simple Tendermint mode abstraction. These modes will live under one binary, and when initializing a node the user will be able to specify which node they would like to create. + +- Which reactor, component to include for each node + - fullnode *(default)* + - switch, transport + - reactors + - mempool + - consensus + - evidence + - blockchain + - p2p/pex + - rpc (safe connections only) + - *~~no privValidator(priv_validator_key.json, priv_validator_state.json)~~* + - validator + - switch, transport + - reactors + - mempool + - consensus + - evidence + - blockchain +  - p2p/pex + - rpc (safe connections only) + - with privValidator(priv_validator_key.json, priv_validator_state.json) + - seed + - switch, transport + - reactor + - p2p/pex +- Configuration, cli command + - We would like to suggest by introducing `mode` parameter in `config.toml` and cli + - `mode = "{{ .BaseConfig.Mode }}"` in `config.toml` + - `tendermint node --mode validator` in cli + - fullnode | validator | seed (default: "fullnode") +- RPC modification + - `host:26657/status` + - return empty `validator_info` when fullnode mode + - no rpc server in seed mode +- Where to modify in codebase + - Add switch for `config.Mode` on `node/node.go:DefaultNewNode` + - If `config.Mode==validator`, call default `NewNode` (current logic) + - If `config.Mode==fullnode`, call `NewNode` with `nil` `privValidator` (do not load or generation) + - Need to add exception routine for `nil` `privValidator` to related functions + - If `config.Mode==seed`, call `NewSeedNode` (seed version of `node/node.go:NewNode`) + - Need to add exception routine for `nil` `reactor`, `component` to related functions + +## Status + +Proposed + +## Consequences + +### Positive + +- Node operators can choose mode when they run state machine according to the purpose of the node. +- Mode can prevent mistakes because users have to specify which mode they want to run via flag. (eg. If a user want to run a validator node, she/he should explicitly write down validator as mode) +- Different mode needs different reactors, resulting in efficient resource usage. + +### Negative + +- Users need to study how each mode operate and which capability it has. + +### Neutral + +## References + +- Issue [#2237](https://github.com/tendermint/tendermint/issues/2237) : Tendermint "mode" +- [TenderSeed](https://gitlab.com/polychainlabs/tenderseed) : A lightweight Tendermint Seed Node. From f95409e07091686df30e055b8456cd886583e847 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 22 Jan 2020 15:19:03 +0400 Subject: [PATCH 07/45] lite2: move AutoClient into Client (#4326) * lite2: move AutoClient into Client Most of the users will want auto update feature, so it makes sense to move it into the Client itself, rather than having a separate abstraction (it makes the code cleaner, but introduces an extra thing the user will need to learn). Also, add `FirstTrustedHeight` func to Client to get first trusted height. * fix db store tests * separate examples for auto and manual clients * AutoUpdate tries to update to latest state NOT 1 header at a time * fix errors * lite2: make Logger an option remove SetLogger func * fix lite cmd * lite2: make concurrency assumptions explicit * fixes after my own review * no need for nextHeightFn sequence func will download intermediate headers * correct comment --- cmd/tendermint/commands/lite.go | 2 +- lite2/auto_client.go | 76 --------------- lite2/auto_client_test.go | 76 --------------- lite2/client.go | 114 ++++++++++++++++++++--- lite2/client_test.go | 159 +++++++++++++++++++++++++++++--- lite2/example_test.go | 48 +++++----- lite2/provider/errors.go | 12 +++ lite2/provider/http/http.go | 9 ++ lite2/provider/mock/mock.go | 6 +- lite2/provider/provider.go | 4 +- lite2/store/db/db.go | 5 +- lite2/store/db/db_test.go | 8 +- lite2/store/store.go | 6 +- 13 files changed, 303 insertions(+), 222 deletions(-) delete mode 100644 lite2/auto_client.go delete mode 100644 lite2/auto_client_test.go create mode 100644 lite2/provider/errors.go diff --git a/cmd/tendermint/commands/lite.go b/cmd/tendermint/commands/lite.go index b86714419..52d253d77 100644 --- a/cmd/tendermint/commands/lite.go +++ b/cmd/tendermint/commands/lite.go @@ -86,11 +86,11 @@ func runProxy(cmd *cobra.Command, args []string) error { }, httpp.NewWithClient(chainID, node), dbs.New(db, chainID), + lite.Logger(liteLogger), ) if err != nil { return err } - c.SetLogger(liteLogger) p := lproxy.Proxy{ Addr: listenAddr, diff --git a/lite2/auto_client.go b/lite2/auto_client.go deleted file mode 100644 index a5b2489c0..000000000 --- a/lite2/auto_client.go +++ /dev/null @@ -1,76 +0,0 @@ -package lite - -import ( - "time" - - "github.com/tendermint/tendermint/types" -) - -// AutoClient can auto update itself by fetching headers every N seconds. -type AutoClient struct { - base *Client - updatePeriod time.Duration - quit chan struct{} - - trustedHeaders chan *types.SignedHeader - errs chan error -} - -// NewAutoClient creates a new client and starts a polling goroutine. -func NewAutoClient(base *Client, updatePeriod time.Duration) *AutoClient { - c := &AutoClient{ - base: base, - updatePeriod: updatePeriod, - quit: make(chan struct{}), - trustedHeaders: make(chan *types.SignedHeader), - errs: make(chan error), - } - go c.autoUpdate() - return c -} - -// TrustedHeaders returns a channel onto which new trusted headers are posted. -func (c *AutoClient) TrustedHeaders() <-chan *types.SignedHeader { - return c.trustedHeaders -} - -// Err returns a channel onto which errors are posted. -func (c *AutoClient) Errs() <-chan error { - return c.errs -} - -// Stop stops the client. -func (c *AutoClient) Stop() { - close(c.quit) -} - -func (c *AutoClient) autoUpdate() { - ticker := time.NewTicker(c.updatePeriod) - defer ticker.Stop() - - for { - select { - case <-ticker.C: - lastTrustedHeight, err := c.base.LastTrustedHeight() - if err != nil { - c.errs <- err - continue - } - - if lastTrustedHeight == -1 { - // no headers yet => wait - continue - } - - h, err := c.base.VerifyHeaderAtHeight(lastTrustedHeight+1, time.Now()) - if err != nil { - // no header yet or verification error => try again after updatePeriod - c.errs <- err - continue - } - c.trustedHeaders <- h - case <-c.quit: - return - } - } -} diff --git a/lite2/auto_client_test.go b/lite2/auto_client_test.go deleted file mode 100644 index d80c60a9a..000000000 --- a/lite2/auto_client_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package lite - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - dbm "github.com/tendermint/tm-db" - - "github.com/tendermint/tendermint/libs/log" - mockp "github.com/tendermint/tendermint/lite2/provider/mock" - dbs "github.com/tendermint/tendermint/lite2/store/db" - "github.com/tendermint/tendermint/types" -) - -func TestAutoClient(t *testing.T) { - const ( - chainID = "TestAutoClient" - ) - - var ( - keys = genPrivKeys(4) - // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! - vals = keys.ToValidators(20, 10) - bTime = time.Now().Add(-1 * time.Hour) - header = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - ) - - base, err := NewClient( - chainID, - TrustOptions{ - Period: 4 * time.Hour, - Height: 1, - Hash: header.Hash(), - }, - mockp.New( - chainID, - map[int64]*types.SignedHeader{ - // trusted header - 1: header, - // interim header (3/3 signed) - 2: keys.GenSignedHeader(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - // last header (3/3 signed) - 3: keys.GenSignedHeader(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - 3: vals, - 4: vals, - }, - ), - dbs.New(dbm.NewMemDB(), chainID), - ) - require.NoError(t, err) - base.SetLogger(log.TestingLogger()) - - c := NewAutoClient(base, 1*time.Second) - defer c.Stop() - - for i := 2; i <= 3; i++ { - select { - case h := <-c.TrustedHeaders(): - assert.EqualValues(t, i, h.Height) - case err := <-c.Errs(): - require.NoError(t, err) - case <-time.After(2 * time.Second): - t.Fatal("no headers/errors received in 2 sec") - } - } -} diff --git a/lite2/client.go b/lite2/client.go index b705a932b..9d95817f0 100644 --- a/lite2/client.go +++ b/lite2/client.go @@ -48,6 +48,7 @@ const ( sequential mode = iota + 1 skipping + defaultUpdatePeriod = 5 * time.Second defaultRemoveNoLongerTrustedHeadersPeriod = 24 * time.Hour ) @@ -90,6 +91,13 @@ func AlternativeSources(providers []provider.Provider) Option { } } +// UpdatePeriod option can be used to change default polling period (5s). +func UpdatePeriod(d time.Duration) Option { + return func(c *Client) { + c.updatePeriod = d + } +} + // RemoveNoLongerTrustedHeadersPeriod option can be used to define how often // the routine, which cleans up no longer trusted headers (outside of trusting // period), is run. Default: once a day. When set to zero, the routine won't be @@ -109,10 +117,20 @@ func ConfirmationFunction(fn func(action string) bool) Option { } } +// Logger option can be used to set a logger for the client. +func Logger(l log.Logger) Option { + return func(c *Client) { + c.logger = l + } +} + // Client represents a light client, connected to a single chain, which gets // headers from a primary provider, verifies them either sequentially or by // skipping some and stores them in a trusted store (usually, a local FS). // +// By default, the client will poll the primary provider for new headers every +// 5s (UpdatePeriod). If there are any, it will try to advance the state. +// // Default verification: SkippingVerification(DefaultTrustLevel) type Client struct { chainID string @@ -134,6 +152,7 @@ type Client struct { // Highest next validator set from the store (height=H+1). trustedNextVals *types.ValidatorSet + updatePeriod time.Duration removeNoLongerTrustedHeadersPeriod time.Duration confirmationFn func(action string) bool @@ -162,6 +181,7 @@ func NewClient( trustLevel: DefaultTrustLevel, primary: primary, trustedStore: trustedStore, + updatePeriod: defaultUpdatePeriod, removeNoLongerTrustedHeadersPeriod: defaultRemoveNoLongerTrustedHeadersPeriod, confirmationFn: func(action string) bool { return true }, quit: make(chan struct{}), @@ -191,6 +211,10 @@ func NewClient( go c.removeNoLongerTrustedHeadersRoutine() } + if c.updatePeriod > 0 { + go c.autoUpdate() + } + return c, nil } @@ -339,16 +363,12 @@ func (c *Client) initializeWithTrustOptions(options TrustOptions) error { return c.updateTrustedHeaderAndVals(h, nextVals) } -// Stop stops the light client. +// Stop stops all the goroutines. If you wish to remove all the data, call +// Cleanup. func (c *Client) Stop() { close(c.quit) } -// SetLogger sets a logger. -func (c *Client) SetLogger(l log.Logger) { - c.logger = l -} - // TrustedHeader returns a trusted header at the given height (0 - the latest) // or nil if no such header exist. // @@ -361,7 +381,10 @@ func (c *Client) SetLogger(l log.Logger) { // - header expired, therefore can't be trusted (ErrOldHeaderExpired); // - there are some issues with the trusted store, although that should not // happen normally; -// - negative height is passed. +// - negative height is passed; +// - header is not found. +// +// Safe for concurrent use by multiple goroutines. func (c *Client) TrustedHeader(height int64, now time.Time) (*types.SignedHeader, error) { if height < 0 { return nil, errors.New("negative height") @@ -379,9 +402,6 @@ func (c *Client) TrustedHeader(height int64, now time.Time) (*types.SignedHeader if err != nil { return nil, err } - if h == nil { - return nil, nil - } // Ensure header can still be trusted. if HeaderExpired(h, c.trustingPeriod, now) { @@ -393,11 +413,23 @@ func (c *Client) TrustedHeader(height int64, now time.Time) (*types.SignedHeader // LastTrustedHeight returns a last trusted height. -1 and nil are returned if // there are no trusted headers. +// +// Safe for concurrent use by multiple goroutines. func (c *Client) LastTrustedHeight() (int64, error) { return c.trustedStore.LastSignedHeaderHeight() } +// FirstTrustedHeight returns a first trusted height. -1 and nil are returned if +// there are no trusted headers. +// +// Safe for concurrent use by multiple goroutines. +func (c *Client) FirstTrustedHeight() (int64, error) { + return c.trustedStore.FirstSignedHeaderHeight() +} + // ChainID returns the chain ID the light client was configured with. +// +// Safe for concurrent use by multiple goroutines. func (c *Client) ChainID() string { return c.chainID } @@ -406,6 +438,8 @@ func (c *Client) ChainID() string { // and calls VerifyHeader. // // If the trusted header is more recent than one here, an error is returned. +// If the header is not found by the primary provider, +// provider.ErrSignedHeaderNotFound error is returned. func (c *Client) VerifyHeaderAtHeight(height int64, now time.Time) (*types.SignedHeader, error) { c.logger.Info("VerifyHeaderAtHeight", "height", height) @@ -435,6 +469,10 @@ func (c *Client) VerifyHeaderAtHeight(height int64, now time.Time) (*types.Signe // https://github.com/tendermint/spec/blob/master/spec/consensus/light-client.md // // If the trusted header is more recent than one here, an error is returned. +// +// If, at any moment, SignedHeader or ValidatorSet are not found by the primary +// provider, provider.ErrSignedHeaderNotFound / +// provider.ErrValidatorSetNotFound error is returned. func (c *Client) VerifyHeader(newHeader *types.SignedHeader, newVals *types.ValidatorSet, now time.Time) error { c.logger.Info("VerifyHeader", "height", newHeader.Hash(), "newVals", newVals.Hash()) @@ -708,10 +746,6 @@ func (c *Client) RemoveNoLongerTrustedHeaders(now time.Time) { c.logger.Error("can't get a trusted header", "err", err, "height", height) continue } - if h == nil { - c.logger.Debug("attempted to remove non-existing header", "height", height) - continue - } // Stop if the header is within the trusting period. if !HeaderExpired(h, c.trustingPeriod, now) { @@ -725,3 +759,55 @@ func (c *Client) RemoveNoLongerTrustedHeaders(now time.Time) { } } } + +func (c *Client) autoUpdate() { + ticker := time.NewTicker(c.updatePeriod) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + err := c.AutoUpdate(time.Now()) + if err != nil { + c.logger.Error("Error during auto update", "err", err) + } + case <-c.quit: + return + } + } +} + +// AutoUpdate attempts to advance the state making exponential steps (note: +// when SequentialVerification is being used, the client will still be +// downloading all intermediate headers). +// +// Exposed for testing. +func (c *Client) AutoUpdate(now time.Time) error { + lastTrustedHeight, err := c.LastTrustedHeight() + if err != nil { + return errors.Wrap(err, "can't get last trusted height") + } + + if lastTrustedHeight == -1 { + // no headers yet => wait + return nil + } + + var i int64 + for err == nil { + // exponential increment: 1, 2, 4, 8, 16, ... + height := lastTrustedHeight + int64(1< 0. // - // If the store is empty and the latest SignedHeader is requested, an error - // is returned. + // If SignedHeader is not found, an error is returned. SignedHeader(height int64) (*types.SignedHeader, error) // ValidatorSet returns the ValidatorSet that corresponds to height. // // height must be > 0. // - // If the store is empty and the latest ValidatorSet is requested, an error - // is returned. + // If ValidatorSet is not found, an error is returned. ValidatorSet(height int64) (*types.ValidatorSet, error) // LastSignedHeaderHeight returns the last (newest) SignedHeader height. From 1905ef7ca8ab4a8a8bfc1bba9b020f6be6061d2f Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 22 Jan 2020 20:26:47 +0400 Subject: [PATCH 08/45] lite2: improve auto update (#4334) * lite2: advance to latest header without any exponential steps rename autoUpdate to autoUpdateRoutine * lite2: wait in Cleanup until goroutines finished running --- lite2/client.go | 47 ++++++++++++++++++++++--------------- lite2/client_test.go | 16 +++++-------- lite2/example_test.go | 12 +++++++--- lite2/provider/mock/mock.go | 6 +++++ 4 files changed, 49 insertions(+), 32 deletions(-) diff --git a/lite2/client.go b/lite2/client.go index 9d95817f0..ad7f8415f 100644 --- a/lite2/client.go +++ b/lite2/client.go @@ -3,6 +3,7 @@ package lite import ( "bytes" "fmt" + "sync" "time" "github.com/pkg/errors" @@ -154,6 +155,7 @@ type Client struct { updatePeriod time.Duration removeNoLongerTrustedHeadersPeriod time.Duration + routinesWaitGroup sync.WaitGroup confirmationFn func(action string) bool @@ -208,11 +210,13 @@ func NewClient( } if c.removeNoLongerTrustedHeadersPeriod > 0 { + c.routinesWaitGroup.Add(1) go c.removeNoLongerTrustedHeadersRoutine() } if c.updatePeriod > 0 { - go c.autoUpdate() + c.routinesWaitGroup.Add(1) + go c.autoUpdateRoutine() } return c, nil @@ -474,7 +478,7 @@ func (c *Client) VerifyHeaderAtHeight(height int64, now time.Time) (*types.Signe // provider, provider.ErrSignedHeaderNotFound / // provider.ErrValidatorSetNotFound error is returned. func (c *Client) VerifyHeader(newHeader *types.SignedHeader, newVals *types.ValidatorSet, now time.Time) error { - c.logger.Info("VerifyHeader", "height", newHeader.Hash(), "newVals", newVals.Hash()) + c.logger.Info("VerifyHeader", "height", newHeader.Hash(), "newVals", fmt.Sprintf("%X", newVals.Hash())) if c.trustedHeader.Height >= newHeader.Height { return errors.Errorf("header at more recent height #%d exists", c.trustedHeader.Height) @@ -507,8 +511,11 @@ func (c *Client) VerifyHeader(newHeader *types.SignedHeader, newVals *types.Vali return c.updateTrustedHeaderAndVals(newHeader, nextVals) } -// Cleanup removes all the data (headers and validator sets) stored. +// Cleanup removes all the data (headers and validator sets) stored. It blocks +// until internal routines are finished. Note: the client must be stopped at +// this point. func (c *Client) Cleanup() error { + c.routinesWaitGroup.Wait() c.logger.Info("Cleanup everything") return c.cleanup(0) } @@ -707,6 +714,8 @@ func (c *Client) compareNewHeaderWithRandomAlternative(h *types.SignedHeader) er } func (c *Client) removeNoLongerTrustedHeadersRoutine() { + defer c.routinesWaitGroup.Done() + ticker := time.NewTicker(c.removeNoLongerTrustedHeadersPeriod) defer ticker.Stop() @@ -760,14 +769,16 @@ func (c *Client) RemoveNoLongerTrustedHeaders(now time.Time) { } } -func (c *Client) autoUpdate() { +func (c *Client) autoUpdateRoutine() { + defer c.routinesWaitGroup.Done() + ticker := time.NewTicker(c.updatePeriod) defer ticker.Stop() for { select { case <-ticker.C: - err := c.AutoUpdate(time.Now()) + err := c.Update(time.Now()) if err != nil { c.logger.Error("Error during auto update", "err", err) } @@ -777,12 +788,12 @@ func (c *Client) autoUpdate() { } } -// AutoUpdate attempts to advance the state making exponential steps (note: +// Update attempts to advance the state making exponential steps (note: // when SequentialVerification is being used, the client will still be // downloading all intermediate headers). // // Exposed for testing. -func (c *Client) AutoUpdate(now time.Time) error { +func (c *Client) Update(now time.Time) error { lastTrustedHeight, err := c.LastTrustedHeight() if err != nil { return errors.Wrap(err, "can't get last trusted height") @@ -793,20 +804,18 @@ func (c *Client) AutoUpdate(now time.Time) error { return nil } - var i int64 - for err == nil { - // exponential increment: 1, 2, 4, 8, 16, ... - height := lastTrustedHeight + int64(1< lastTrustedHeight { + err = c.VerifyHeader(latestHeader, latestVals, now) if err != nil { - if errors.Is(err, provider.ErrSignedHeaderNotFound) { - c.logger.Debug("No header yet", "at", height) - return nil - } - return errors.Wrapf(err, "failed to verify the header #%d", height) + return err } - c.logger.Info("Advanced to new state", "height", h.Height, "hash", h.Hash()) - i++ + + c.logger.Info("Advanced to new state", "height", latestHeader.Height, "hash", latestHeader.Hash()) } return nil diff --git a/lite2/client_test.go b/lite2/client_test.go index eea533208..3065b76c0 100644 --- a/lite2/client_test.go +++ b/lite2/client_test.go @@ -350,6 +350,7 @@ func TestClient_Cleanup(t *testing.T) { ) require.NoError(t, err) + c.Stop() c.Cleanup() // Check no headers exist after Cleanup. @@ -661,9 +662,9 @@ func TestClientRestoreTrustedHeaderAfterStartup3(t *testing.T) { } } -func TestClient_AutoUpdate(t *testing.T) { +func TestClient_Update(t *testing.T) { const ( - chainID = "TestClient_AutoUpdate" + chainID = "TestClient_Update" ) var ( @@ -707,16 +708,11 @@ func TestClient_AutoUpdate(t *testing.T) { require.NoError(t, err) defer c.Stop() - // should result in downloading & verifying headers #2 and #3 - err = c.AutoUpdate(bTime.Add(2 * time.Hour)) + // should result in downloading & verifying header #3 + err = c.Update(bTime.Add(2 * time.Hour)) require.NoError(t, err) - h, err := c.TrustedHeader(2, bTime.Add(2*time.Hour)) - assert.NoError(t, err) - require.NotNil(t, h) - assert.EqualValues(t, 2, h.Height) - - h, err = c.TrustedHeader(3, bTime.Add(2*time.Hour)) + h, err := c.TrustedHeader(3, bTime.Add(2*time.Hour)) assert.NoError(t, err) require.NotNil(t, h) assert.EqualValues(t, 3, h.Height) diff --git a/lite2/example_test.go b/lite2/example_test.go index 772012a96..48804c77d 100644 --- a/lite2/example_test.go +++ b/lite2/example_test.go @@ -63,11 +63,14 @@ func TestExample_Client_AutoUpdate(t *testing.T) { if err != nil { stdlog.Fatal(err) } - defer c.Stop() + defer func() { + c.Stop() + c.Cleanup() + }() time.Sleep(2 * time.Second) - h, err := c.TrustedHeader(3, time.Now()) + h, err := c.TrustedHeader(0, time.Now()) if err != nil { stdlog.Fatal(err) } @@ -122,7 +125,10 @@ func TestExample_Client_ManualUpdate(t *testing.T) { if err != nil { stdlog.Fatal(err) } - defer c.Stop() + defer func() { + c.Stop() + c.Cleanup() + }() _, err = c.VerifyHeaderAtHeight(3, time.Now()) if err != nil { diff --git a/lite2/provider/mock/mock.go b/lite2/provider/mock/mock.go index 3d8cd6876..f895420e5 100644 --- a/lite2/provider/mock/mock.go +++ b/lite2/provider/mock/mock.go @@ -27,6 +27,9 @@ func (p *mock) ChainID() string { } func (p *mock) SignedHeader(height int64) (*types.SignedHeader, error) { + if height == 0 && len(p.headers) > 0 { + return p.headers[int64(len(p.headers))], nil + } if _, ok := p.headers[height]; ok { return p.headers[height], nil } @@ -34,6 +37,9 @@ func (p *mock) SignedHeader(height int64) (*types.SignedHeader, error) { } func (p *mock) ValidatorSet(height int64) (*types.ValidatorSet, error) { + if height == 0 && len(p.vals) > 0 { + return p.vals[int64(len(p.vals))], nil + } if _, ok := p.vals[height]; ok { return p.vals[height], nil } From 082e211ef976b9357d733bc01bb27755f32ee3d9 Mon Sep 17 00:00:00 2001 From: Marko Date: Thu, 23 Jan 2020 08:57:42 +0100 Subject: [PATCH 09/45] docs: minor doc fixes (#4335) * docs: minor doc fixes - minor doc fixes that i ran into while reading things - test if we have github actions Signed-off-by: Marko Baricevic * no github actions yet * add with * revert and change wording --- docs/architecture/adr-015-crypto-encoding.md | 8 +++---- docs/tendermint-core/block-structure.md | 2 +- docs/tendermint-core/light-client-protocol.md | 2 +- docs/tendermint-core/metrics.md | 24 +++++++++---------- docs/tendermint-core/validators.md | 6 ++--- docs/tools/README.md | 16 ++++++++++--- docs/tools/benchmarking.md | 4 ---- 7 files changed, 34 insertions(+), 28 deletions(-) delete mode 100644 docs/tools/benchmarking.md diff --git a/docs/architecture/adr-015-crypto-encoding.md b/docs/architecture/adr-015-crypto-encoding.md index 665129f12..bb0a8cd80 100644 --- a/docs/architecture/adr-015-crypto-encoding.md +++ b/docs/architecture/adr-015-crypto-encoding.md @@ -21,12 +21,12 @@ representation of the pubkey. This has two significant drawbacks. Amino encoding is less space-efficient, due to requiring support for upgradability. Amino encoding support requires forking protobuf and adding this new interface support -option in the langauge of choice. +option in the language of choice. The reason for continuing to use amino however is that people can create code more easily in languages that already have an up to date amino library. It is possible that this will change in the future, if it is deemed that -requiring amino for interacting with tendermint cryptography is unneccessary. +requiring amino for interacting with Tendermint cryptography is unnecessary. The arguments for space efficiency here are refuted on the basis that there are far more egregious wastages of space in the SDK. @@ -35,9 +35,9 @@ increasing the space attached to each validator / account. The alternative to using amino here would be for us to create an enum type. Switching to just an enum type is worthy of investigation post-launch. -For referrence, part of amino encoding interfaces is basically a 4 byte enum +For reference, part of amino encoding interfaces is basically a 4 byte enum type definition. -Enum types would just change that 4 bytes to be a varuint, and it would remove +Enum types would just change that 4 bytes to be a variant, and it would remove the protobuf overhead, but it would be hard to integrate into the existing API. ### Signatures diff --git a/docs/tendermint-core/block-structure.md b/docs/tendermint-core/block-structure.md index a87589115..95a81e588 100644 --- a/docs/tendermint-core/block-structure.md +++ b/docs/tendermint-core/block-structure.md @@ -11,6 +11,6 @@ nodes. This blockchain is accessible via various rpc endpoints, mainly `/blockchain?minHeight=_&maxHeight=_` to get a list of headers. But what exactly is stored in these blocks? -The [specification](../spec/blockchain/blockchain.md) contains a detailed description of each component - that's the best place to get started. +The [specification](https://github.com/tendermint/spec/blob/953523c3cb99fdb8c8f7a2d21e3a99094279e9de/spec/blockchain/blockchain.md) contains a detailed description of each component - that's the best place to get started. To dig deeper, check out the [types package documentation](https://godoc.org/github.com/tendermint/tendermint/types). diff --git a/docs/tendermint-core/light-client-protocol.md b/docs/tendermint-core/light-client-protocol.md index d64ca1084..1296fa471 100644 --- a/docs/tendermint-core/light-client-protocol.md +++ b/docs/tendermint-core/light-client-protocol.md @@ -18,7 +18,7 @@ commit for a recent block hash where the commit includes a majority of signatures from the last known validator set. From there, all the application state is verifiable with [merkle -proofs](../spec/blockchain/encoding.md#iavl-tree). +proofs](https://github.com/tendermint/spec/blob/953523c3cb99fdb8c8f7a2d21e3a99094279e9de/spec/blockchain/encoding.md#iavl-tree). ## Properties diff --git a/docs/tendermint-core/metrics.md b/docs/tendermint-core/metrics.md index c6ac6c3a7..57a6cea50 100644 --- a/docs/tendermint-core/metrics.md +++ b/docs/tendermint-core/metrics.md @@ -34,21 +34,21 @@ The following metrics are available: | consensus_rounds | Gauge | 0.21.0 | | Number of rounds | | consensus_num_txs | Gauge | 0.21.0 | | Number of transactions | | consensus_total_txs | Gauge | 0.21.0 | | Total number of transactions committed | -| consensus_block_parts | counter | on dev | peer_id | number of blockparts transmitted by peer | -| consensus_latest_block_height | gauge | on dev | | /status sync_info number | -| consensus_fast_syncing | gauge | on dev | | either 0 (not fast syncing) or 1 (syncing) | +| consensus_block_parts | counter | 0.25.0 | peer_id | number of blockparts transmitted by peer | +| consensus_latest_block_height | gauge | 0.25.0 | | /status sync_info number | +| consensus_fast_syncing | gauge | 0.25.0 | | either 0 (not fast syncing) or 1 (syncing) | | consensus_block_size_bytes | Gauge | 0.21.0 | | Block size in bytes | | p2p_peers | Gauge | 0.21.0 | | Number of peers node's connected to | -| p2p_peer_receive_bytes_total | counter | on dev | peer_id, chID | number of bytes per channel received from a given peer | -| p2p_peer_send_bytes_total | counter | on dev | peer_id, chID | number of bytes per channel sent to a given peer | -| p2p_peer_pending_send_bytes | gauge | on dev | peer_id | number of pending bytes to be sent to a given peer | -| p2p_num_txs | gauge | on dev | peer_id | number of transactions submitted by each peer_id | -| p2p_pending_send_bytes | gauge | on dev | peer_id | amount of data pending to be sent to peer | +| p2p_peer_receive_bytes_total | counter | 0.25.0 | peer_id, chID | number of bytes per channel received from a given peer | +| p2p_peer_send_bytes_total | counter | 0.25.0 | peer_id, chID | number of bytes per channel sent to a given peer | +| p2p_peer_pending_send_bytes | gauge | 0.25.0 | peer_id | number of pending bytes to be sent to a given peer | +| p2p_num_txs | gauge | 0.25.0 | peer_id | number of transactions submitted by each peer_id | +| p2p_pending_send_bytes | gauge | 0.25.0 | peer_id | amount of data pending to be sent to peer | | mempool_size | Gauge | 0.21.0 | | Number of uncommitted transactions | -| mempool_tx_size_bytes | histogram | on dev | | transaction sizes in bytes | -| mempool_failed_txs | counter | on dev | | number of failed transactions | -| mempool_recheck_times | counter | on dev | | number of transactions rechecked in the mempool | -| state_block_processing_time | histogram | on dev | | time between BeginBlock and EndBlock in ms | +| mempool_tx_size_bytes | histogram | 0.25.0 | | transaction sizes in bytes | +| mempool_failed_txs | counter | 0.25.0 | | number of failed transactions | +| mempool_recheck_times | counter | 0.25.0 | | number of transactions rechecked in the mempool | +| state_block_processing_time | histogram | 0.25.0 | | time between BeginBlock and EndBlock in ms | ## Useful queries diff --git a/docs/tendermint-core/validators.md b/docs/tendermint-core/validators.md index 307d267c6..97a5da8ca 100644 --- a/docs/tendermint-core/validators.md +++ b/docs/tendermint-core/validators.md @@ -31,9 +31,9 @@ There are two ways to become validator. _+2/3 is short for "more than 2/3"_ A block is committed when +2/3 of the validator set sign [precommit -votes](../spec/blockchain/blockchain.md#vote) for that block at the same `round`. +votes](https://github.com/tendermint/spec/blob/953523c3cb99fdb8c8f7a2d21e3a99094279e9de/spec/blockchain/blockchain.md#vote) for that block at the same `round`. The +2/3 set of precommit votes is called a -[_commit_](../spec/blockchain/blockchain.md#commit). While any +2/3 set of +[_commit_](https://github.com/tendermint/spec/blob/953523c3cb99fdb8c8f7a2d21e3a99094279e9de/spec/blockchain/blockchain.md#commit). While any +2/3 set of precommits for the same block at the same height&round can serve as validation, the canonical commit is included in the next block (see -[LastCommit](../spec/blockchain/blockchain.md#lastcommit)). +[LastCommit](https://github.com/tendermint/spec/blob/953523c3cb99fdb8c8f7a2d21e3a99094279e9de/spec/blockchain/blockchain.md#lastcommit)). diff --git a/docs/tools/README.md b/docs/tools/README.md index fbde42db0..c326cde5b 100644 --- a/docs/tools/README.md +++ b/docs/tools/README.md @@ -7,8 +7,18 @@ parent: # Overview -Tendermint comes with some tools for: +Tendermint has some tools that are associated with it for: -- [Benchmarking](./benchmarking.md) -- [Monitoring](./monitoring.md) +- [Benchmarking](#benchmarking) - [Validation of remote signers](./remote-signer-validation.md) +- [Testnets](#testnets) + + +## Benchmarking + +Benchmarking is done with tm-load-test, for information on how to use the tool please visit the docs: https://github.com/interchainio/tm-load-test + + +## Testnets + +The testnets tool is aimed at testing Tendermint with different configurations. For more information please visit: https://github.com/interchainio/testnets. diff --git a/docs/tools/benchmarking.md b/docs/tools/benchmarking.md deleted file mode 100644 index ca6f7ea35..000000000 --- a/docs/tools/benchmarking.md +++ /dev/null @@ -1,4 +0,0 @@ -# tm-load-test - -Tm-bench has been removed in favor of [tm-load-test](https://github.com/interchainio/tm-load-test). -for information on how to use tm-load-test please visit the docs: https://github.com/interchainio/tm-load-test From 696e13e1ff4c0be2052d2a4f4e36ef3031b11598 Mon Sep 17 00:00:00 2001 From: dongsamb Date: Fri, 24 Jan 2020 16:02:35 +0900 Subject: [PATCH 10/45] adr: ADR-051: Double Signing Risk Reduction (#4262) * Add adr-051 to docs * add details * Update docs/architecture/adr-051-double-signing-protection-with-tendermint-mode.md Co-Authored-By: Anton Kaliaev * rename adr-051 for only double singing protection * remove contents about tendermint mode * change title to Double Signing Rist Reduction * rename adr md file * add a adr link to ToC Co-authored-by: b-harvest <38277329+dlguddus@users.noreply.github.com> Co-authored-by: Anton Kaliaev --- docs/architecture/README.md | 1 + .../adr-051-double-signing-risk-reduction.md | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 docs/architecture/adr-051-double-signing-risk-reduction.md diff --git a/docs/architecture/README.md b/docs/architecture/README.md index d29a49c81..7055a3676 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -64,4 +64,5 @@ Note the context/background should be written in the present tense. - [ADR-039-Peer-Behaviour](./adr-039-peer-behaviour.md) - [ADR-041-Proposer-Selection-via-ABCI](./adr-041-proposer-selection-via-abci.md) - [ADR-043-Blockchain-RiRi-Org](./adr-043-blockchain-riri-org.md) +- [ADR-051-Double-Signing-Risk-Reduction](./adr-051-double-signing-risk-reduction.md) - [ADR-052-Tendermint-Mode](./adr-052-tendermint-mode.md) diff --git a/docs/architecture/adr-051-double-signing-risk-reduction.md b/docs/architecture/adr-051-double-signing-risk-reduction.md new file mode 100644 index 000000000..04ee41a67 --- /dev/null +++ b/docs/architecture/adr-051-double-signing-risk-reduction.md @@ -0,0 +1,53 @@ +# ADR 051: Double Signing Risk Reduction + +## Changelog + +* 27-11-2019: Initial draft +* 13-01-2020: Separate into 2 ADR, This ADR will only cover Double signing Protection and ADR-052 handle Tendermint Mode +* 22-01-2020: change the title from "Double signing Protection" to "Double Signing Risk Reduction" + +## Context + +To provide a risk reduction method for double signing incidents mistakenly executed by validators +- Validators often mistakenly run duplicated validators to cause double-signing incident +- This proposed feature is to reduce the risk of mistaken double-signing incident by checking recent N blocks before voting begins +- When we think of such serious impact on double-signing incident, it is very reasonable to have multiple risk reduction algorithm built in node daemon + +## Decision + +We would like to suggest a double signing risk reduction method. + +- Methodology : query recent consensus results to find out whether node's consensus key is used on consensus recently or not +- When to check + - When the state machine starts `ConsensusReactor` after fully synced + - When the node is validator ( with privValidator ) + - When `cs.config.DoubleSignCheckHeight > 0` +- How to check + 1. When a validator is transformed from syncing status to fully synced status, the state machine check recent N blocks (`latest_height - double_sign_check_height`) to find out whether there exists consensus votes using the validator's consensus key + 2. If there exists votes from the validator's consensus key, exit state machine program +- Configuration + - We would like to suggest by introducing `double_sign_check_height` parameter in `config.toml` and cli, how many blocks state machine looks back to check votes + - `double_sign_check_height = {{ .Consensus.DoubleSignCheckHeight }}` in `config.toml` + - `tendermint node --double_sign_check_height` in cli + - State machine ignore checking procedure when `vote-check-height == 0` + +## Status + +Proposed + +## Consequences + +### Positive + +- Validators can avoid double signing incident by mistakes. (eg. If another validator node is voting on consensus, starting new validator node with same consensus key will cause panic stop of the state machine because consensus votes with the consensus key are found in recent blocks) +- We expect this method will prevent majority of double signing incident by mistakes. + +### Negative + +- When the risk reduction method is on, restarting a validator node will panic because the node itself voted on consensus with the same consensus key. So, validators should stop the state machine, wait for some blocks, and then restart the state machine to avoid panic stop. + +### Neutral + +## References + +- Issue [#4059](https://github.com/tendermint/tendermint/issues/4059) : double-signing protection From 48be9bcb0929fdeaea5135344e36cf647251aede Mon Sep 17 00:00:00 2001 From: Erik Grinaker Date: Mon, 27 Jan 2020 10:40:54 +0100 Subject: [PATCH 11/45] Add IPv6 support for P2P integration tests (#4340) --- test/app/counter_test.sh | 8 ++++---- test/app/test.sh | 12 +++++------- test/p2p/README.md | 17 ++++++++++++++++- test/p2p/address.sh | 28 ++++++++++++++++++++++++++++ test/p2p/atomic_broadcast/test.sh | 9 +++++---- test/p2p/basic/test.sh | 7 ++++--- test/p2p/circleci.sh | 15 +++++++++++++++ test/p2p/client.sh | 15 +++++++++++---- test/p2p/fast_sync/check_peer.sh | 7 ++++--- test/p2p/fast_sync/test.sh | 9 ++++----- test/p2p/fast_sync/test_peer.sh | 15 ++++++++------- test/p2p/ip.sh | 5 ----- test/p2p/ip_plus_id.sh | 7 ------- test/p2p/kill_all/check_peers.sh | 9 +++++---- test/p2p/kill_all/test.sh | 9 ++++----- test/p2p/local_testnet_start.sh | 17 ++++++++++------- test/p2p/peer.sh | 17 ++++++++++++----- test/p2p/persistent_peers.sh | 11 +++++------ test/p2p/pex/check_peer.sh | 7 ++++--- test/p2p/pex/dial_peers.sh | 13 ++++++------- test/p2p/pex/test.sh | 11 +++++------ test/p2p/pex/test_addrbook.sh | 13 +++++++------ test/p2p/pex/test_dial_peers.sh | 17 ++++++++--------- test/p2p/test.sh | 20 ++++++++++++-------- tests.mk | 27 ++++++++++++++++++++++----- 25 files changed, 204 insertions(+), 121 deletions(-) create mode 100755 test/p2p/address.sh delete mode 100755 test/p2p/ip.sh delete mode 100755 test/p2p/ip_plus_id.sh diff --git a/test/app/counter_test.sh b/test/app/counter_test.sh index a4f7c83b9..3af2b885f 100755 --- a/test/app/counter_test.sh +++ b/test/app/counter_test.sh @@ -36,11 +36,11 @@ function getCode() { # build grpc client if needed if [[ "$GRPC_BROADCAST_TX" != "" ]]; then - if [ -f grpc_client ]; then - rm grpc_client + if [ -f test/app/grpc_client ]; then + rm test/app/grpc_client fi echo "... building grpc_client" - go build -mod=readonly -o grpc_client grpc_client.go + go build -mod=readonly -o test/app/grpc_client test/app/grpc_client.go fi function sendTx() { @@ -59,7 +59,7 @@ function sendTx() { RESPONSE=$(echo "$RESPONSE" | jq '.result') else - RESPONSE=$(./grpc_client "$TX") + RESPONSE=$(./test/app/grpc_client "$TX") IS_ERR=false ERROR="" fi diff --git a/test/app/test.sh b/test/app/test.sh index 0f77da04e..dc60bfc1f 100755 --- a/test/app/test.sh +++ b/test/app/test.sh @@ -22,7 +22,7 @@ function kvstore_over_socket(){ sleep 5 echo "running test" - bash kvstore_test.sh "KVStore over Socket" + bash test/app/kvstore_test.sh "KVStore over Socket" kill -9 $pid_kvstore $pid_tendermint } @@ -40,7 +40,7 @@ function kvstore_over_socket_reorder(){ sleep 5 echo "running test" - bash kvstore_test.sh "KVStore over Socket" + bash test/app/kvstore_test.sh "KVStore over Socket" kill -9 $pid_kvstore $pid_tendermint } @@ -57,7 +57,7 @@ function counter_over_socket() { sleep 5 echo "running test" - bash counter_test.sh "Counter over Socket" + bash test/app/counter_test.sh "Counter over Socket" kill -9 $pid_counter $pid_tendermint } @@ -73,7 +73,7 @@ function counter_over_grpc() { sleep 5 echo "running test" - bash counter_test.sh "Counter over GRPC" + bash test/app/counter_test.sh "Counter over GRPC" kill -9 $pid_counter $pid_tendermint } @@ -91,13 +91,11 @@ function counter_over_grpc_grpc() { sleep 5 echo "running test" - GRPC_BROADCAST_TX=true bash counter_test.sh "Counter over GRPC via GRPC BroadcastTx" + GRPC_BROADCAST_TX=true bash test/app/counter_test.sh "Counter over GRPC via GRPC BroadcastTx" kill -9 $pid_counter $pid_tendermint } -cd $GOPATH/src/github.com/tendermint/tendermint/test/app - case "$1" in "kvstore_over_socket") kvstore_over_socket diff --git a/test/p2p/README.md b/test/p2p/README.md index 956ce906c..1ebf4c17f 100644 --- a/test/p2p/README.md +++ b/test/p2p/README.md @@ -4,7 +4,7 @@ These scripts facilitate setting up and testing a local testnet using docker con Setup your own local testnet as follows. -For consistency, we assume all commands are run from the Tendermint repository root (ie. $GOPATH/src/github.com/tendermint/tendermint). +For consistency, we assume all commands are run from the Tendermint repository root. First, build the docker image: @@ -49,3 +49,18 @@ We can confirm they are making blocks by checking the `/status` message using `c ``` curl 172.57.0.101:26657/status | jq . ``` + +## IPv6 tests + +IPv6 tests require a Docker daemon with IPv6 enabled, by setting the following in `daemon.json`: + +```json +{ + "ipv6": true, + "fixed-cidr-v6": "2001:db8:1::/64" +} +``` + +In Docker for Mac, this is done via Preferences → Docker Engine. + +Once set, run IPv6 tests via `make test_p2p_ipv6`. \ No newline at end of file diff --git a/test/p2p/address.sh b/test/p2p/address.sh new file mode 100755 index 000000000..0b0248db2 --- /dev/null +++ b/test/p2p/address.sh @@ -0,0 +1,28 @@ +#! /bin/bash +set -eu + +IPV=$1 +ID=$2 +PORT=${3:-} +DOCKER_IMAGE=${4:-} + +if [[ "$IPV" == 6 ]]; then + ADDRESS="fd80:b10c::" +else + ADDRESS="172.57.0." +fi +ADDRESS="$ADDRESS$((100+$ID))" + +if [[ -n "$PORT" ]]; then + if [[ "$IPV" == 6 ]]; then + ADDRESS="[$ADDRESS]" + fi + ADDRESS="$ADDRESS:$PORT" +fi + +if [[ -n "$DOCKER_IMAGE" ]]; then + NODEID="$(docker run --rm -e TMHOME=/go/src/github.com/tendermint/tendermint/test/p2p/data/mach$((ID-1)) $DOCKER_IMAGE tendermint show_node_id)" + ADDRESS="$NODEID@$ADDRESS" +fi + +echo $ADDRESS \ No newline at end of file diff --git a/test/p2p/atomic_broadcast/test.sh b/test/p2p/atomic_broadcast/test.sh index f066707d3..a93067c3d 100644 --- a/test/p2p/atomic_broadcast/test.sh +++ b/test/p2p/atomic_broadcast/test.sh @@ -1,7 +1,8 @@ #! /bin/bash set -u -N=$1 +IPV=$1 +N=$2 ################################################################### # assumes peers are already synced up @@ -14,7 +15,7 @@ N=$1 echo "" # run the test on each of them for i in $(seq 1 "$N"); do - addr=$(test/p2p/ip.sh "$i"):26657 + addr=$(test/p2p/address.sh $IPV $i 26657) # current state HASH1=$(curl -s "$addr/status" | jq .result.sync_info.latest_app_hash) @@ -37,7 +38,7 @@ for i in $(seq 1 "$N"); do minHeight=$h2 for j in $(seq 1 "$N"); do if [[ "$i" != "$j" ]]; then - addrJ=$(test/p2p/ip.sh "$j"):26657 + addrJ=$(test/p2p/address.sh $IPV $j 26657) h=$(curl -s "$addrJ/status" | jq .result.sync_info.latest_block_height | jq fromjson) while [ "$h" -lt "$minHeight" ]; do @@ -57,7 +58,7 @@ for i in $(seq 1 "$N"); do # check we get the same new hash on all other nodes for j in $(seq 1 "$N"); do if [[ "$i" != "$j" ]]; then - addrJ=$(test/p2p/ip.sh "$j"):26657 + addrJ=$(test/p2p/address.sh $IPV $j 26657) HASH3=$(curl -s "$addrJ/status" | jq .result.sync_info.latest_app_hash) if [[ "$HASH2" != "$HASH3" ]]; then diff --git a/test/p2p/basic/test.sh b/test/p2p/basic/test.sh index 423b5b017..676b5cbe6 100755 --- a/test/p2p/basic/test.sh +++ b/test/p2p/basic/test.sh @@ -1,7 +1,8 @@ #! /bin/bash set -u -N=$1 +IPV=$1 +N=$2 ################################################################### # wait for all peers to come online @@ -16,7 +17,7 @@ MAX_SLEEP=60 # wait for everyone to come online echo "Waiting for nodes to come online" for i in `seq 1 $N`; do - addr=$(test/p2p/ip.sh $i):26657 + addr=$(test/p2p/address.sh $IPV $i 26657) curl -s $addr/status > /dev/null ERR=$? COUNT=0 @@ -36,7 +37,7 @@ done echo "" # wait for each of them to sync up for i in `seq 1 $N`; do - addr=$(test/p2p/ip.sh $i):26657 + addr=$(test/p2p/address.sh $IPV $i 26657) N_1=$(($N - 1)) # - assert everyone has N-1 other peers diff --git a/test/p2p/circleci.sh b/test/p2p/circleci.sh index c548d5752..92869ff45 100644 --- a/test/p2p/circleci.sh +++ b/test/p2p/circleci.sh @@ -6,6 +6,17 @@ SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" +# Enable IPv6 support in Docker daemon +echo +echo "* [$(date +"%T")] enabling IPv6 stack in Docker daemon" +cat <<'EOF' | sudo tee /etc/docker/daemon.json +{ + "ipv6": true, + "fixed-cidr-v6": "2001:db8:1::/64" +} +EOF +sudo service docker restart + LOGS_DIR="$DIR/logs" echo echo "* [$(date +"%T")] cleaning up $LOGS_DIR" @@ -34,6 +45,10 @@ echo echo "* [$(date +"%T")] running p2p tests on a local docker network" bash "$DIR/../p2p/test.sh" tester +echo +echo "* [$(date +"%T")] running IPv6 p2p tests on a local docker network" +bash "$DIR/../p2p/test.sh" tester 6 + echo echo "* [$(date +"%T")] copying log files out of docker container into $LOGS_DIR" docker cp rsyslog:/var/log $LOGS_DIR diff --git a/test/p2p/client.sh b/test/p2p/client.sh index fa11ce870..b3c907fba 100644 --- a/test/p2p/client.sh +++ b/test/p2p/client.sh @@ -3,17 +3,24 @@ set -eu DOCKER_IMAGE=$1 NETWORK_NAME=$2 -ID=$3 -CMD=$4 +IPV=$3 +ID=$4 +CMD=$5 NAME=test_container_$ID +if [[ "$IPV" == 6 ]]; then + IP_SWITCH="--ip6" +else + IP_SWITCH="--ip" +fi + echo "starting test client container with CMD=$CMD" # run the test container on the local network docker run -t --rm \ - -v "$GOPATH/src/github.com/tendermint/tendermint/test/p2p/:/go/src/github.com/tendermint/tendermint/test/p2p" \ + -v "$PWD/test/p2p/:/go/src/github.com/tendermint/tendermint/test/p2p" \ --net="$NETWORK_NAME" \ - --ip=$(test/p2p/ip.sh "-1") \ + $IP_SWITCH=$(test/p2p/address.sh $IPV -1) \ --name "$NAME" \ --entrypoint bash \ "$DOCKER_IMAGE" $CMD diff --git a/test/p2p/fast_sync/check_peer.sh b/test/p2p/fast_sync/check_peer.sh index d5d3fc2b5..798b508fa 100644 --- a/test/p2p/fast_sync/check_peer.sh +++ b/test/p2p/fast_sync/check_peer.sh @@ -2,7 +2,8 @@ set -eu set -o pipefail -ID=$1 +IPV=$1 +ID=$2 ########################################### # @@ -10,9 +11,9 @@ ID=$1 # ########################################### -addr=$(test/p2p/ip.sh $ID):26657 +addr=$(test/p2p/address.sh $IPV $ID 26657) peerID=$(( $(($ID % 4)) + 1 )) # 1->2 ... 3->4 ... 4->1 -peer_addr=$(test/p2p/ip.sh $peerID):26657 +peer_addr=$(test/p2p/address.sh $IPV $peerID 26657) # get another peer's height h1=`curl -s $peer_addr/status | jq .result.sync_info.latest_block_height | jq fromjson` diff --git a/test/p2p/fast_sync/test.sh b/test/p2p/fast_sync/test.sh index 8820d199c..79655232f 100644 --- a/test/p2p/fast_sync/test.sh +++ b/test/p2p/fast_sync/test.sh @@ -3,14 +3,13 @@ set -eu DOCKER_IMAGE=$1 NETWORK_NAME=$2 -N=$3 -PROXY_APP=$4 - -cd $GOPATH/src/github.com/tendermint/tendermint +IPV=$3 +N=$4 +PROXY_APP=$5 # run it on each of them for i in `seq 1 $N`; do - bash test/p2p/fast_sync/test_peer.sh $DOCKER_IMAGE $NETWORK_NAME $i $N $PROXY_APP + bash test/p2p/fast_sync/test_peer.sh $DOCKER_IMAGE $NETWORK_NAME $IPV $i $N $PROXY_APP done diff --git a/test/p2p/fast_sync/test_peer.sh b/test/p2p/fast_sync/test_peer.sh index 08ea9deb1..b4c34336f 100644 --- a/test/p2p/fast_sync/test_peer.sh +++ b/test/p2p/fast_sync/test_peer.sh @@ -3,9 +3,10 @@ set -eu DOCKER_IMAGE=$1 NETWORK_NAME=$2 -ID=$3 -N=$4 -PROXY_APP=$5 +IPV=$3 +ID=$4 +N=$5 +PROXY_APP=$6 ############################################################### # this runs on each peer: @@ -23,14 +24,14 @@ set +e # circle sigh :( set -e # restart peer - should have an empty blockchain - PERSISTENT_PEERS="$(test/p2p/ip_plus_id.sh 1 $DOCKER_IMAGE):26656" + PERSISTENT_PEERS="$(test/p2p/address.sh $IPV 1 26656 $DOCKER_IMAGE)" for j in `seq 2 $N`; do - PERSISTENT_PEERS="$PERSISTENT_PEERS,$(test/p2p/ip_plus_id.sh $j $DOCKER_IMAGE):26656" + PERSISTENT_PEERS="$PERSISTENT_PEERS,$(test/p2p/address.sh $IPV $j 26656 $DOCKER_IMAGE)" done - bash test/p2p/peer.sh $DOCKER_IMAGE $NETWORK_NAME $ID $PROXY_APP "--p2p.persistent_peers $PERSISTENT_PEERS --p2p.pex --rpc.unsafe" + bash test/p2p/peer.sh $DOCKER_IMAGE $NETWORK_NAME $IPV $ID $PROXY_APP "--p2p.persistent_peers $PERSISTENT_PEERS --p2p.pex --rpc.unsafe" # wait for peer to sync and check the app hash - bash test/p2p/client.sh $DOCKER_IMAGE $NETWORK_NAME fs_$ID "test/p2p/fast_sync/check_peer.sh $ID" + bash test/p2p/client.sh $DOCKER_IMAGE $NETWORK_NAME $IPV fs_$ID "test/p2p/fast_sync/check_peer.sh $IPV $ID" echo "" echo "PASS" diff --git a/test/p2p/ip.sh b/test/p2p/ip.sh deleted file mode 100755 index 77753f541..000000000 --- a/test/p2p/ip.sh +++ /dev/null @@ -1,5 +0,0 @@ -#! /bin/bash -set -eu - -ID=$1 -echo "172.57.0.$((100+$ID))" diff --git a/test/p2p/ip_plus_id.sh b/test/p2p/ip_plus_id.sh deleted file mode 100755 index 95871d3f1..000000000 --- a/test/p2p/ip_plus_id.sh +++ /dev/null @@ -1,7 +0,0 @@ -#! /bin/bash -set -eu - -ID=$1 -DOCKER_IMAGE=$2 -NODEID="$(docker run --rm -e TMHOME=/go/src/github.com/tendermint/tendermint/test/p2p/data/mach$((ID-1)) $DOCKER_IMAGE tendermint show_node_id)" -echo "$NODEID@172.57.0.$((100+$ID))" diff --git a/test/p2p/kill_all/check_peers.sh b/test/p2p/kill_all/check_peers.sh index 95da7484e..504cdeddd 100644 --- a/test/p2p/kill_all/check_peers.sh +++ b/test/p2p/kill_all/check_peers.sh @@ -1,7 +1,8 @@ #! /bin/bash set -eu -NUM_OF_PEERS=$1 +IPV=$1 +NUM_OF_PEERS=$2 # how many attempts for each peer to catch up by height MAX_ATTEMPTS_TO_CATCH_UP=120 @@ -9,7 +10,7 @@ MAX_ATTEMPTS_TO_CATCH_UP=120 echo "Waiting for nodes to come online" set +e for i in $(seq 1 "$NUM_OF_PEERS"); do - addr=$(test/p2p/ip.sh "$i"):26657 + addr=$(test/p2p/address.sh $IPV $i 26657) curl -s "$addr/status" > /dev/null ERR=$? while [ "$ERR" != 0 ]; do @@ -22,7 +23,7 @@ done set -e # get the first peer's height -addr=$(test/p2p/ip.sh 1):26657 +addr=$(test/p2p/address.sh $IPV 1 26657) h1=$(curl -s "$addr/status" | jq .result.sync_info.latest_block_height | sed -e "s/^\"\(.*\)\"$/\1/g") echo "1st peer is on height $h1" @@ -32,7 +33,7 @@ for i in $(seq 2 "$NUM_OF_PEERS"); do hi=0 while [[ $hi -le $h1 ]] ; do - addr=$(test/p2p/ip.sh "$i"):26657 + addr=$(test/p2p/address.sh $IPV $i 26657) hi=$(curl -s "$addr/status" | jq .result.sync_info.latest_block_height | sed -e "s/^\"\(.*\)\"$/\1/g") echo "... peer $i is on height $hi" diff --git a/test/p2p/kill_all/test.sh b/test/p2p/kill_all/test.sh index 318a1fe47..755612130 100644 --- a/test/p2p/kill_all/test.sh +++ b/test/p2p/kill_all/test.sh @@ -3,10 +3,9 @@ set -eu DOCKER_IMAGE=$1 NETWORK_NAME=$2 -NUM_OF_PEERS=$3 -NUM_OF_CRASHES=$4 - -cd "$GOPATH/src/github.com/tendermint/tendermint" +IPV=$3 +NUM_OF_PEERS=$4 +NUM_OF_CRASHES=$5 ############################################################### # NUM_OF_CRASHES times: @@ -24,7 +23,7 @@ for i in $(seq 1 "$NUM_OF_CRASHES"); do docker start "local_testnet_$j" done - bash test/p2p/client.sh "$DOCKER_IMAGE" "$NETWORK_NAME" kill_all_$i "test/p2p/kill_all/check_peers.sh $NUM_OF_PEERS" + bash test/p2p/client.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$IPV" kill_all_$i "test/p2p/kill_all/check_peers.sh $IPV $NUM_OF_PEERS" done echo "" diff --git a/test/p2p/local_testnet_start.sh b/test/p2p/local_testnet_start.sh index 25b3c6d3e..8da6be4bb 100644 --- a/test/p2p/local_testnet_start.sh +++ b/test/p2p/local_testnet_start.sh @@ -3,22 +3,25 @@ set -eu DOCKER_IMAGE=$1 NETWORK_NAME=$2 -N=$3 -APP_PROXY=$4 +IPV=$3 +N=$4 +APP_PROXY=$5 set +u -PERSISTENT_PEERS=$5 +PERSISTENT_PEERS=$6 if [[ "$PERSISTENT_PEERS" != "" ]]; then echo "PersistentPeers: $PERSISTENT_PEERS" PERSISTENT_PEERS="--p2p.persistent_peers $PERSISTENT_PEERS" fi set -u -cd "$GOPATH/src/github.com/tendermint/tendermint" - # create docker network -docker network create --driver bridge --subnet 172.57.0.0/16 "$NETWORK_NAME" +if [[ $IPV == 6 ]]; then + docker network create --driver bridge --ipv6 --subnet fd80:b10c::/48 "$NETWORK_NAME" +else + docker network create --driver bridge --subnet 172.57.0.0/16 "$NETWORK_NAME" +fi for i in $(seq 1 "$N"); do - bash test/p2p/peer.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$i" "$APP_PROXY" "$PERSISTENT_PEERS --p2p.pex --rpc.unsafe" + bash test/p2p/peer.sh "$DOCKER_IMAGE" "$NETWORK_NAME" $IPV "$i" "$APP_PROXY" "$PERSISTENT_PEERS --p2p.pex --rpc.unsafe" done diff --git a/test/p2p/peer.sh b/test/p2p/peer.sh index 63d46f8d5..bf146ca1b 100644 --- a/test/p2p/peer.sh +++ b/test/p2p/peer.sh @@ -3,13 +3,20 @@ set -eu DOCKER_IMAGE=$1 NETWORK_NAME=$2 -ID=$3 -APP_PROXY=$4 +IPV=$3 +ID=$4 +APP_PROXY=$5 set +u -NODE_FLAGS=$5 +NODE_FLAGS=$6 set -u +if [[ "$IPV" == 6 ]]; then + IP_SWITCH="--ip6" +else + IP_SWITCH="--ip" +fi + echo "starting tendermint peer ID=$ID" # start tendermint container on the network # NOTE: $NODE_FLAGS should be unescaped (no quotes). otherwise it will be @@ -20,7 +27,7 @@ echo "starting tendermint peer ID=$ID" if [[ "$ID" == "x" ]]; then # Set "x" to "1" to print to console. docker run \ --net="$NETWORK_NAME" \ - --ip=$(test/p2p/ip.sh "$ID") \ + $IP_SWITCH=$(test/p2p/address.sh $IPV $ID) \ --name "local_testnet_$ID" \ --entrypoint tendermint \ -e TMHOME="/go/src/github.com/tendermint/tendermint/test/p2p/data/mach$((ID-1))" \ @@ -33,7 +40,7 @@ if [[ "$ID" == "x" ]]; then # Set "x" to "1" to print to console. else docker run -d \ --net="$NETWORK_NAME" \ - --ip=$(test/p2p/ip.sh "$ID") \ + $IP_SWITCH=$(test/p2p/address.sh $IPV $ID) \ --name "local_testnet_$ID" \ --entrypoint tendermint \ -e TMHOME="/go/src/github.com/tendermint/tendermint/test/p2p/data/mach$((ID-1))" \ diff --git a/test/p2p/persistent_peers.sh b/test/p2p/persistent_peers.sh index 6d3e1ed66..a1e76991a 100644 --- a/test/p2p/persistent_peers.sh +++ b/test/p2p/persistent_peers.sh @@ -1,13 +1,12 @@ #! /bin/bash set -eu -N=$1 -DOCKER_IMAGE=$2 +IPV=$1 +N=$2 +DOCKER_IMAGE=$3 -cd "$GOPATH/src/github.com/tendermint/tendermint" - -persistent_peers="$(test/p2p/ip_plus_id.sh 1 $DOCKER_IMAGE):26656" +persistent_peers="$(test/p2p/address.sh $IPV 1 26656 $DOCKER_IMAGE)" for i in $(seq 2 $N); do - persistent_peers="$persistent_peers,$(test/p2p/ip_plus_id.sh $i $DOCKER_IMAGE):26656" + persistent_peers="$persistent_peers,$(test/p2p/address.sh $IPV $i 26656 $DOCKER_IMAGE)" done echo "$persistent_peers" diff --git a/test/p2p/pex/check_peer.sh b/test/p2p/pex/check_peer.sh index 7ae42e9b6..93499d9f9 100644 --- a/test/p2p/pex/check_peer.sh +++ b/test/p2p/pex/check_peer.sh @@ -1,10 +1,11 @@ #! /bin/bash set -u -ID=$1 -N=$2 +IPV=$1 +ID=$2 +N=$3 -addr=$(test/p2p/ip.sh "$ID"):26657 +addr=$(test/p2p/address.sh $IPV "$ID" 26657) echo "2. wait until peer $ID connects to other nodes using pex reactor" peers_count="0" diff --git a/test/p2p/pex/dial_peers.sh b/test/p2p/pex/dial_peers.sh index 43bde48b5..8c4d40f44 100644 --- a/test/p2p/pex/dial_peers.sh +++ b/test/p2p/pex/dial_peers.sh @@ -1,14 +1,13 @@ #! /bin/bash set -u -N=$1 -PEERS=$2 - -cd "$GOPATH/src/github.com/tendermint/tendermint" +IPV=$1 +N=$2 +PEERS=$3 echo "Waiting for nodes to come online" for i in $(seq 1 "$N"); do - addr=$(test/p2p/ip.sh "$i"):26657 + addr=$(test/p2p/address.sh $IPV $i 26657) curl -s "$addr/status" > /dev/null ERR=$? while [ "$ERR" != 0 ]; do @@ -19,5 +18,5 @@ for i in $(seq 1 "$N"); do echo "... node $i is up" done -IP=$(test/p2p/ip.sh 1) -curl "$IP:26657/dial_peers?persistent=true&peers=\\[$PEERS\\]" +ADDR=$(test/p2p/address.sh $IPV 1 26657) +curl "$ADDR/dial_peers?persistent=true&peers=\\[$PEERS\\]" diff --git a/test/p2p/pex/test.sh b/test/p2p/pex/test.sh index ffecd6510..1e87a9fa5 100644 --- a/test/p2p/pex/test.sh +++ b/test/p2p/pex/test.sh @@ -3,13 +3,12 @@ set -eu DOCKER_IMAGE=$1 NETWORK_NAME=$2 -N=$3 -PROXY_APP=$4 - -cd "$GOPATH/src/github.com/tendermint/tendermint" +IPV=$3 +N=$4 +PROXY_APP=$5 echo "Test reconnecting from the address book" -bash test/p2p/pex/test_addrbook.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$N" "$PROXY_APP" +bash test/p2p/pex/test_addrbook.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$IPV" "$N" "$PROXY_APP" echo "Test connecting via /dial_peers" -bash test/p2p/pex/test_dial_peers.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$N" "$PROXY_APP" +bash test/p2p/pex/test_dial_peers.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$IPV" "$N" "$PROXY_APP" diff --git a/test/p2p/pex/test_addrbook.sh b/test/p2p/pex/test_addrbook.sh index 06f9212fd..06fc4215f 100644 --- a/test/p2p/pex/test_addrbook.sh +++ b/test/p2p/pex/test_addrbook.sh @@ -3,8 +3,9 @@ set -eu DOCKER_IMAGE=$1 NETWORK_NAME=$2 -N=$3 -PROXY_APP=$4 +IPV=$3 +N=$4 +PROXY_APP=$5 ID=1 @@ -24,11 +25,11 @@ docker rm -vf "local_testnet_$ID" set -e # NOTE that we do not provide persistent_peers -bash test/p2p/peer.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$ID" "$PROXY_APP" "--p2p.pex --rpc.unsafe" +bash test/p2p/peer.sh "$DOCKER_IMAGE" "$NETWORK_NAME" $IPV "$ID" "$PROXY_APP" "--p2p.pex --rpc.unsafe" echo "started local_testnet_$ID" # if the client runs forever, it means addrbook wasn't saved or was empty -bash test/p2p/client.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$CLIENT_NAME" "test/p2p/pex/check_peer.sh $ID $N" +bash test/p2p/client.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$IPV" "$CLIENT_NAME" "test/p2p/pex/check_peer.sh $IPV $ID $N" # Now we know that the node is up. @@ -53,11 +54,11 @@ docker rm -vf "local_testnet_$ID" set -e # NOTE that we do not provide persistent_peers -bash test/p2p/peer.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$ID" "$PROXY_APP" "--p2p.pex --rpc.unsafe" +bash test/p2p/peer.sh "$DOCKER_IMAGE" "$NETWORK_NAME" $IPV "$ID" "$PROXY_APP" "--p2p.pex --rpc.unsafe" echo "started local_testnet_$ID" # if the client runs forever, it means other peers have removed us from their books (which should not happen) -bash test/p2p/client.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$CLIENT_NAME" "test/p2p/pex/check_peer.sh $ID $N" +bash test/p2p/client.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$IPV" "$CLIENT_NAME" "test/p2p/pex/check_peer.sh $IPV $ID $N" # Now we know that the node is up. diff --git a/test/p2p/pex/test_dial_peers.sh b/test/p2p/pex/test_dial_peers.sh index cb6e7e182..af76a5699 100644 --- a/test/p2p/pex/test_dial_peers.sh +++ b/test/p2p/pex/test_dial_peers.sh @@ -3,13 +3,12 @@ set -eu DOCKER_IMAGE=$1 NETWORK_NAME=$2 -N=$3 -PROXY_APP=$4 +IPV=$3 +N=$4 +PROXY_APP=$5 ID=1 -cd $GOPATH/src/github.com/tendermint/tendermint - echo "----------------------------------------------------------------------" echo "Testing full network connection using one /dial_peers call" echo "(assuming peers are started with pex enabled)" @@ -21,19 +20,19 @@ set -e # start the testnet on a local network # NOTE we re-use the same network for all tests -bash test/p2p/local_testnet_start.sh $DOCKER_IMAGE $NETWORK_NAME $N $PROXY_APP "" +bash test/p2p/local_testnet_start.sh $DOCKER_IMAGE $NETWORK_NAME $IPV $N $PROXY_APP "" -PERSISTENT_PEERS="\"$(test/p2p/ip_plus_id.sh 1 $DOCKER_IMAGE):26656\"" +PERSISTENT_PEERS="\"$(test/p2p/address.sh $IPV 1 26656 $DOCKER_IMAGE)\"" for i in $(seq 2 $N); do - PERSISTENT_PEERS="$PERSISTENT_PEERS,\"$(test/p2p/ip_plus_id.sh $i $DOCKER_IMAGE):26656\"" + PERSISTENT_PEERS="$PERSISTENT_PEERS,\"$(test/p2p/address.sh $IPV $i 26656 $DOCKER_IMAGE)\"" done echo "$PERSISTENT_PEERS" # dial peers from one node CLIENT_NAME="dial_peers" -bash test/p2p/client.sh $DOCKER_IMAGE $NETWORK_NAME $CLIENT_NAME "test/p2p/pex/dial_peers.sh $N $PERSISTENT_PEERS" +bash test/p2p/client.sh $DOCKER_IMAGE $NETWORK_NAME $IPV $CLIENT_NAME "test/p2p/pex/dial_peers.sh $IPV $N $PERSISTENT_PEERS" # test basic connectivity and consensus # start client container and check the num peers and height for all nodes CLIENT_NAME="dial_peers_basic" -bash test/p2p/client.sh $DOCKER_IMAGE $NETWORK_NAME $CLIENT_NAME "test/p2p/basic/test.sh $N" +bash test/p2p/client.sh $DOCKER_IMAGE $NETWORK_NAME $IPV $CLIENT_NAME "test/p2p/basic/test.sh $IPV $N" diff --git a/test/p2p/test.sh b/test/p2p/test.sh index abcf2ca07..fe28f02a9 100644 --- a/test/p2p/test.sh +++ b/test/p2p/test.sh @@ -5,34 +5,38 @@ DOCKER_IMAGE=$1 NETWORK_NAME=local_testnet N=4 PROXY_APP=persistent_kvstore +IPV=${2:-4} # Default to IPv4 -cd "$GOPATH/src/github.com/tendermint/tendermint" +if [[ "$IPV" != "4" && "$IPV" != "6" ]]; then + echo "IP version must be 4 or 6" >&2 + exit 1 +fi # stop the existing testnet and remove local network set +e bash test/p2p/local_testnet_stop.sh "$NETWORK_NAME" "$N" set -e -PERSISTENT_PEERS=$(bash test/p2p/persistent_peers.sh $N $DOCKER_IMAGE) +PERSISTENT_PEERS=$(bash test/p2p/persistent_peers.sh $IPV $N $DOCKER_IMAGE) # start the testnet on a local network # NOTE we re-use the same network for all tests -bash test/p2p/local_testnet_start.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$N" "$PROXY_APP" "$PERSISTENT_PEERS" +bash test/p2p/local_testnet_start.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$IPV" "$N" "$PROXY_APP" "$PERSISTENT_PEERS" # test basic connectivity and consensus # start client container and check the num peers and height for all nodes -bash test/p2p/client.sh "$DOCKER_IMAGE" "$NETWORK_NAME" basic "test/p2p/basic/test.sh $N" +bash test/p2p/client.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$IPV" basic "test/p2p/basic/test.sh $IPV $N" # test atomic broadcast: # start client container and test sending a tx to each node -bash test/p2p/client.sh "$DOCKER_IMAGE" "$NETWORK_NAME" ab "test/p2p/atomic_broadcast/test.sh $N" +bash test/p2p/client.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$IPV" ab "test/p2p/atomic_broadcast/test.sh $IPV $N" # test fast sync (from current state of network): # for each node, kill it and readd via fast sync -bash test/p2p/fast_sync/test.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$N" "$PROXY_APP" +bash test/p2p/fast_sync/test.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$IPV" "$N" "$PROXY_APP" # test killing all peers 3 times -bash test/p2p/kill_all/test.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$N" 3 +bash test/p2p/kill_all/test.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$IPV" "$N" 3 # test pex -bash test/p2p/pex/test.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$N" "$PROXY_APP" +bash test/p2p/pex/test.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$IPV" "$N" "$PROXY_APP" diff --git a/tests.mk b/tests.mk index 18caef496..72bba47e4 100644 --- a/tests.mk +++ b/tests.mk @@ -38,17 +38,32 @@ test_persistence: test_p2p: docker rm -f rsyslog || true - rm -rf test/logs || true - mkdir test/logs - cd test/ - docker run -d -v "logs:/var/log/" -p 127.0.0.1:5514:514/udp --name rsyslog voxxit/rsyslog - cd .. + rm -rf test/logs && mkdir -p test/logs + docker run -d -v "$(CURDIR)/test/logs:/var/log/" -p 127.0.0.1:5514:514/udp --name rsyslog voxxit/rsyslog # requires 'tester' the image from above bash test/p2p/test.sh tester # the `docker cp` takes a really long time; uncomment for debugging # # mkdir -p test/p2p/logs && docker cp rsyslog:/var/log test/p2p/logs +test_p2p_ipv6: + # IPv6 tests require Docker daemon with IPv6 enabled, e.g. in daemon.json: + # + # { + # "ipv6": true, + # "fixed-cidr-v6": "2001:db8:1::/64" + # } + # + # Docker for Mac can set this via Preferences -> Docker Engine. + docker rm -f rsyslog || true + rm -rf test/logs && mkdir -p test/logs + docker run -d -v "$(CURDIR)/test/logs:/var/log/" -p 127.0.0.1:5514:514/udp --name rsyslog voxxit/rsyslog + # requires 'tester' the image from above + bash test/p2p/test.sh tester 6 + # the `docker cp` takes a really long time; uncomment for debugging + # + # mkdir -p test/p2p/logs && docker cp rsyslog:/var/log test/p2p/logs + test_integrations: make build_docker_test_image make tools @@ -60,6 +75,8 @@ test_integrations: make test_libs make test_persistence make test_p2p + # Disabled by default since it requires Docker daemon with IPv6 enabled + #make test_p2p_ipv6 test_release: @go test -tags release $(PACKAGES) From 59a922d38ab9889935b4f2aac6eb8aa85c047de2 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 27 Jan 2020 19:49:04 +0400 Subject: [PATCH 12/45] lite2: add Start, TrustedValidatorSet funcs (#4337) * lite2: add Start method There are few reasons to do that: 1) separation of state and dynamics (some users will want to delay starting the light client; does not matter we should not allow them to create a light client object) 2) less important, but some users might not need autoUpdateRoutine and removeNoLongerTrustedHeadersRoutine routines * lite2: wait till routines are finished in Stop because they are started in Start, it feels more natural to wait for them to finish in Stop. * lite2: add TrustedValidatorSet func --- lite2/client.go | 66 ++++++++++++++++++++++++++++++++----------- lite2/client_test.go | 39 +++++++++++++++++++++++++ lite2/example_test.go | 8 ++++++ 3 files changed, 96 insertions(+), 17 deletions(-) diff --git a/lite2/client.go b/lite2/client.go index ad7f8415f..b8ef6e807 100644 --- a/lite2/client.go +++ b/lite2/client.go @@ -209,16 +209,6 @@ func NewClient( } } - if c.removeNoLongerTrustedHeadersPeriod > 0 { - c.routinesWaitGroup.Add(1) - go c.removeNoLongerTrustedHeadersRoutine() - } - - if c.updatePeriod > 0 { - c.routinesWaitGroup.Add(1) - go c.autoUpdateRoutine() - } - return c, nil } @@ -367,10 +357,30 @@ func (c *Client) initializeWithTrustOptions(options TrustOptions) error { return c.updateTrustedHeaderAndVals(h, nextVals) } -// Stop stops all the goroutines. If you wish to remove all the data, call -// Cleanup. +// Start starts two processes: 1) auto updating 2) removing outdated headers. +func (c *Client) Start() error { + c.logger.Info("Starting light client") + + if c.removeNoLongerTrustedHeadersPeriod > 0 { + c.routinesWaitGroup.Add(1) + go c.removeNoLongerTrustedHeadersRoutine() + } + + if c.updatePeriod > 0 { + c.routinesWaitGroup.Add(1) + go c.autoUpdateRoutine() + } + + return nil +} + +// Stop stops two processes: 1) auto updating 2) removing outdated headers. +// Stop only returns after both of them are finished running. If you wish to +// remove all the data, call Cleanup. func (c *Client) Stop() { + c.logger.Info("Stopping light client") close(c.quit) + c.routinesWaitGroup.Wait() } // TrustedHeader returns a trusted header at the given height (0 - the latest) @@ -415,6 +425,30 @@ func (c *Client) TrustedHeader(height int64, now time.Time) (*types.SignedHeader return h, nil } +// TrustedValidatorSet returns a trusted validator set at the given height (0 - +// the latest) or nil if no such validator set exist. The second return +// parameter is height validator set corresponds to (useful when you pass 0). +// +// height must be >= 0. +// +// It returns an error if: +// - header signed by that validator set expired (ErrOldHeaderExpired) +// - there are some issues with the trusted store, although that should not +// happen normally; +// - negative height is passed; +// - validator set is not found. +// +// Safe for concurrent use by multiple goroutines. +func (c *Client) TrustedValidatorSet(height int64, now time.Time) (*types.ValidatorSet, error) { + // Checks height is positive and header is not expired. + _, err := c.TrustedHeader(height, now) + if err != nil { + return nil, err + } + + return c.trustedStore.ValidatorSet(height) +} + // LastTrustedHeight returns a last trusted height. -1 and nil are returned if // there are no trusted headers. // @@ -511,12 +545,10 @@ func (c *Client) VerifyHeader(newHeader *types.SignedHeader, newVals *types.Vali return c.updateTrustedHeaderAndVals(newHeader, nextVals) } -// Cleanup removes all the data (headers and validator sets) stored. It blocks -// until internal routines are finished. Note: the client must be stopped at -// this point. +// Cleanup removes all the data (headers and validator sets) stored. Note: the +// client must be stopped at this point. func (c *Client) Cleanup() error { - c.routinesWaitGroup.Wait() - c.logger.Info("Cleanup everything") + c.logger.Info("Removing all the data") return c.cleanup(0) } diff --git a/lite2/client_test.go b/lite2/client_test.go index 3065b76c0..d9f58347c 100644 --- a/lite2/client_test.go +++ b/lite2/client_test.go @@ -137,6 +137,8 @@ func TestClient_SequentialVerification(t *testing.T) { } else { require.NoError(t, err) } + err = c.Start() + require.NoError(t, err) defer c.Stop() _, err = c.VerifyHeaderAtHeight(3, bTime.Add(3*time.Hour)) @@ -235,6 +237,8 @@ func TestClient_SkippingVerification(t *testing.T) { } else { require.NoError(t, err) } + err = c.Start() + require.NoError(t, err) defer c.Stop() _, err = c.VerifyHeaderAtHeight(3, bTime.Add(3*time.Hour)) @@ -290,6 +294,8 @@ func TestClientRemovesNoLongerTrustedHeaders(t *testing.T) { Logger(log.TestingLogger()), ) require.NoError(t, err) + err = c.Start() + require.NoError(t, err) defer c.Stop() // Verify new headers. @@ -349,6 +355,8 @@ func TestClient_Cleanup(t *testing.T) { Logger(log.TestingLogger()), ) require.NoError(t, err) + err = c.Start() + require.NoError(t, err) c.Stop() c.Cleanup() @@ -402,6 +410,9 @@ func TestClientRestoreTrustedHeaderAfterStartup1(t *testing.T) { Logger(log.TestingLogger()), ) require.NoError(t, err) + err = c.Start() + require.NoError(t, err) + defer c.Stop() h, err := c.TrustedHeader(1, bTime.Add(1*time.Second)) assert.NoError(t, err) @@ -441,6 +452,9 @@ func TestClientRestoreTrustedHeaderAfterStartup1(t *testing.T) { Logger(log.TestingLogger()), ) require.NoError(t, err) + err = c.Start() + require.NoError(t, err) + defer c.Stop() h, err := c.TrustedHeader(1, bTime.Add(1*time.Second)) assert.NoError(t, err) @@ -496,6 +510,9 @@ func TestClientRestoreTrustedHeaderAfterStartup2(t *testing.T) { Logger(log.TestingLogger()), ) require.NoError(t, err) + err = c.Start() + require.NoError(t, err) + defer c.Stop() // Check we still have the 1st header (+header+). h, err := c.TrustedHeader(1, bTime.Add(2*time.Hour).Add(1*time.Second)) @@ -541,6 +558,9 @@ func TestClientRestoreTrustedHeaderAfterStartup2(t *testing.T) { Logger(log.TestingLogger()), ) require.NoError(t, err) + err = c.Start() + require.NoError(t, err) + defer c.Stop() // Check we no longer have the invalid 1st header (+header+). h, err := c.TrustedHeader(1, bTime.Add(2*time.Hour).Add(1*time.Second)) @@ -598,6 +618,9 @@ func TestClientRestoreTrustedHeaderAfterStartup3(t *testing.T) { Logger(log.TestingLogger()), ) require.NoError(t, err) + err = c.Start() + require.NoError(t, err) + defer c.Stop() // Check we still have the 1st header (+header+). h, err := c.TrustedHeader(1, bTime.Add(2*time.Hour).Add(1*time.Second)) @@ -648,6 +671,9 @@ func TestClientRestoreTrustedHeaderAfterStartup3(t *testing.T) { Logger(log.TestingLogger()), ) require.NoError(t, err) + err = c.Start() + require.NoError(t, err) + defer c.Stop() // Check we have swapped invalid 1st header (+header+) with correct one (+header1+). h, err := c.TrustedHeader(1, bTime.Add(2*time.Hour).Add(1*time.Second)) @@ -706,6 +732,8 @@ func TestClient_Update(t *testing.T) { Logger(log.TestingLogger()), ) require.NoError(t, err) + err = c.Start() + require.NoError(t, err) defer c.Stop() // should result in downloading & verifying header #3 @@ -763,6 +791,13 @@ func TestClient_Concurrency(t *testing.T) { Logger(log.TestingLogger()), ) require.NoError(t, err) + err = c.Start() + require.NoError(t, err) + defer c.Stop() + + _, err = c.VerifyHeaderAtHeight(2, bTime.Add(2*time.Hour)) + require.NoError(t, err) + var wg sync.WaitGroup for i := 0; i < 100; i++ { wg.Add(1) @@ -783,6 +818,10 @@ func TestClient_Concurrency(t *testing.T) { h, err := c.TrustedHeader(1, bTime.Add(2*time.Hour)) assert.NoError(t, err) assert.NotNil(t, h) + + vals, err := c.TrustedValidatorSet(2, bTime.Add(2*time.Hour)) + assert.NoError(t, err) + assert.NotNil(t, vals) }() } diff --git a/lite2/example_test.go b/lite2/example_test.go index 48804c77d..4a291236b 100644 --- a/lite2/example_test.go +++ b/lite2/example_test.go @@ -63,6 +63,10 @@ func TestExample_Client_AutoUpdate(t *testing.T) { if err != nil { stdlog.Fatal(err) } + err = c.Start() + if err != nil { + stdlog.Fatal(err) + } defer func() { c.Stop() c.Cleanup() @@ -125,6 +129,10 @@ func TestExample_Client_ManualUpdate(t *testing.T) { if err != nil { stdlog.Fatal(err) } + err = c.Start() + if err != nil { + stdlog.Fatal(err) + } defer func() { c.Stop() c.Cleanup() From d90dc9db260d6d37d8a6be201d0515ab7862cf6e Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 27 Jan 2020 21:20:56 +0400 Subject: [PATCH 13/45] rpc: add sort_order option to tx_search (#4342) I have added order_by which can be "asc" or "desc" (should be in string format) in the tx_search RPC method. Fixes: #3333 Author: @princesinha19 --- CHANGELOG_PENDING.md | 3 +++ lite2/proxy/routes.go | 9 ++++---- lite2/rpc/client.go | 5 ++-- rpc/client/httpclient.go | 4 +++- rpc/client/interface.go | 2 +- rpc/client/localclient.go | 5 ++-- rpc/client/rpc_test.go | 46 ++++++++++++++++++++++++++----------- rpc/core/routes.go | 2 +- rpc/core/tx.go | 30 +++++++++++++++++++++--- rpc/swagger/swagger.yaml | 8 +++++++ state/txindex/kv/kv.go | 23 +++++++------------ state/txindex/kv/kv_test.go | 23 ------------------- 12 files changed, 95 insertions(+), 65 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index aac1e6542..c100f12bc 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -3,6 +3,7 @@ \*\* Special thanks to external contributors on this release: +@princesinha19 Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint). @@ -17,6 +18,8 @@ program](https://hackerone.com/tendermint). ### FEATURES: +- [rpc] [\#3333] Add `order_by` to `/tx_search` endpoint, allowing to change default ordering from asc to desc (more in the future) (@princesinha19) + ### IMPROVEMENTS: ### BUG FIXES: diff --git a/lite2/proxy/routes.go b/lite2/proxy/routes.go index 110cfe88f..f7d5cd25b 100644 --- a/lite2/proxy/routes.go +++ b/lite2/proxy/routes.go @@ -26,7 +26,7 @@ func RPCRoutes(c *lrpc.Client) map[string]*rpcserver.RPCFunc { "block_results": rpcserver.NewRPCFunc(makeBlockResultsFunc(c), "height"), "commit": rpcserver.NewRPCFunc(makeCommitFunc(c), "height"), "tx": rpcserver.NewRPCFunc(makeTxFunc(c), "hash,prove"), - "tx_search": rpcserver.NewRPCFunc(makeTxSearchFunc(c), "query,prove,page,per_page"), + "tx_search": rpcserver.NewRPCFunc(makeTxSearchFunc(c), "query,prove,page,per_page,order_by"), "validators": rpcserver.NewRPCFunc(makeValidatorsFunc(c), "height,page,per_page"), "dump_consensus_state": rpcserver.NewRPCFunc(makeDumpConsensusStateFunc(c), ""), "consensus_state": rpcserver.NewRPCFunc(makeConsensusStateFunc(c), ""), @@ -122,11 +122,12 @@ func makeTxFunc(c *lrpc.Client) rpcTxFunc { } type rpcTxSearchFunc func(ctx *rpctypes.Context, query string, prove bool, - page, perPage int) (*ctypes.ResultTxSearch, error) + page, perPage int, orderBy string) (*ctypes.ResultTxSearch, error) func makeTxSearchFunc(c *lrpc.Client) rpcTxSearchFunc { - return func(ctx *rpctypes.Context, query string, prove bool, page, perPage int) (*ctypes.ResultTxSearch, error) { - return c.TxSearch(query, prove, page, perPage) + return func(ctx *rpctypes.Context, query string, prove bool, page, perPage int, orderBy string) ( + *ctypes.ResultTxSearch, error) { + return c.TxSearch(query, prove, page, perPage, orderBy) } } diff --git a/lite2/rpc/client.go b/lite2/rpc/client.go index 458e871ad..9778878ac 100644 --- a/lite2/rpc/client.go +++ b/lite2/rpc/client.go @@ -295,8 +295,9 @@ func (c *Client) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) { return res, res.Proof.Validate(h.DataHash) } -func (c *Client) TxSearch(query string, prove bool, page, perPage int) (*ctypes.ResultTxSearch, error) { - return c.next.TxSearch(query, prove, page, perPage) +func (c *Client) TxSearch(query string, prove bool, page, perPage int, orderBy string) ( + *ctypes.ResultTxSearch, error) { + return c.next.TxSearch(query, prove, page, perPage, orderBy) } func (c *Client) Validators(height *int64, page, perPage int) (*ctypes.ResultValidators, error) { diff --git a/rpc/client/httpclient.go b/rpc/client/httpclient.go index 29175fe19..021df82e6 100644 --- a/rpc/client/httpclient.go +++ b/rpc/client/httpclient.go @@ -348,13 +348,15 @@ func (c *baseRPCClient) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) { return result, nil } -func (c *baseRPCClient) TxSearch(query string, prove bool, page, perPage int) (*ctypes.ResultTxSearch, error) { +func (c *baseRPCClient) TxSearch(query string, prove bool, page, perPage int, orderBy string) ( + *ctypes.ResultTxSearch, error) { result := new(ctypes.ResultTxSearch) params := map[string]interface{}{ "query": query, "prove": prove, "page": page, "per_page": perPage, + "order_by": orderBy, } _, err := c.caller.Call("tx_search", params, result) if err != nil { diff --git a/rpc/client/interface.go b/rpc/client/interface.go index 72e899551..408d803c8 100644 --- a/rpc/client/interface.go +++ b/rpc/client/interface.go @@ -69,7 +69,7 @@ type SignClient interface { Commit(height *int64) (*ctypes.ResultCommit, error) Validators(height *int64, page, perPage int) (*ctypes.ResultValidators, error) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) - TxSearch(query string, prove bool, page, perPage int) (*ctypes.ResultTxSearch, error) + TxSearch(query string, prove bool, page, perPage int, orderBy string) (*ctypes.ResultTxSearch, error) } // HistoryClient provides access to data from genesis to now in large chunks. diff --git a/rpc/client/localclient.go b/rpc/client/localclient.go index c1d0809a6..e6b0eb937 100644 --- a/rpc/client/localclient.go +++ b/rpc/client/localclient.go @@ -160,8 +160,9 @@ func (c *Local) Tx(hash []byte, prove bool) (*ctypes.ResultTx, error) { return core.Tx(c.ctx, hash, prove) } -func (c *Local) TxSearch(query string, prove bool, page, perPage int) (*ctypes.ResultTxSearch, error) { - return core.TxSearch(c.ctx, query, prove, page, perPage) +func (c *Local) TxSearch(query string, prove bool, page, perPage int, orderBy string) ( + *ctypes.ResultTxSearch, error) { + return core.TxSearch(c.ctx, query, prove, page, perPage, orderBy) } func (c *Local) BroadcastEvidence(ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) { diff --git a/rpc/client/rpc_test.go b/rpc/client/rpc_test.go index 52f0961b9..55c7755ac 100644 --- a/rpc/client/rpc_test.go +++ b/rpc/client/rpc_test.go @@ -418,7 +418,7 @@ func TestTxSearch(t *testing.T) { c := getHTTPClient() _, _, tx := MakeTxKV() bres, err := c.BroadcastTxCommit(tx) - require.Nil(t, err, "%+v", err) + require.Nil(t, err) txHeight := bres.Height txHash := bres.Hash @@ -430,8 +430,8 @@ func TestTxSearch(t *testing.T) { // now we query for the tx. // since there's only one tx, we know index=0. - result, err := c.TxSearch(fmt.Sprintf("tx.hash='%v'", txHash), true, 1, 30) - require.Nil(t, err, "%+v", err) + result, err := c.TxSearch(fmt.Sprintf("tx.hash='%v'", txHash), true, 1, 30, "asc") + require.Nil(t, err) require.Len(t, result.Txs, 1) ptx := result.Txs[0] @@ -448,33 +448,53 @@ func TestTxSearch(t *testing.T) { } // query by height - result, err = c.TxSearch(fmt.Sprintf("tx.height=%d", txHeight), true, 1, 30) - require.Nil(t, err, "%+v", err) + result, err = c.TxSearch(fmt.Sprintf("tx.height=%d", txHeight), true, 1, 30, "asc") + require.Nil(t, err) require.Len(t, result.Txs, 1) // query for non existing tx - result, err = c.TxSearch(fmt.Sprintf("tx.hash='%X'", anotherTxHash), false, 1, 30) - require.Nil(t, err, "%+v", err) + result, err = c.TxSearch(fmt.Sprintf("tx.hash='%X'", anotherTxHash), false, 1, 30, "asc") + require.Nil(t, err) require.Len(t, result.Txs, 0) // query using a compositeKey (see kvstore application) - result, err = c.TxSearch("app.creator='Cosmoshi Netowoko'", false, 1, 30) - require.Nil(t, err, "%+v", err) + result, err = c.TxSearch("app.creator='Cosmoshi Netowoko'", false, 1, 30, "asc") + require.Nil(t, err) if len(result.Txs) == 0 { t.Fatal("expected a lot of transactions") } // query using a compositeKey (see kvstore application) and height - result, err = c.TxSearch("app.creator='Cosmoshi Netowoko' AND tx.height<10000", true, 1, 30) - require.Nil(t, err, "%+v", err) + result, err = c.TxSearch("app.creator='Cosmoshi Netowoko' AND tx.height<10000", true, 1, 30, "asc") + require.Nil(t, err) if len(result.Txs) == 0 { t.Fatal("expected a lot of transactions") } // query a non existing tx with page 1 and txsPerPage 1 - result, err = c.TxSearch("app.creator='Cosmoshi Neetowoko'", true, 1, 1) - require.Nil(t, err, "%+v", err) + result, err = c.TxSearch("app.creator='Cosmoshi Neetowoko'", true, 1, 1, "asc") + require.Nil(t, err) require.Len(t, result.Txs, 0) + + // broadcast another transaction to make sure we have at least two. + _, _, tx2 := MakeTxKV() + _, err = c.BroadcastTxCommit(tx2) + require.Nil(t, err) + + // chech sorting + result, err = c.TxSearch(fmt.Sprintf("tx.height >= 1"), false, 1, 30, "asc") + require.Nil(t, err) + for k := 0; k < len(result.Txs)-1; k++ { + require.LessOrEqual(t, result.Txs[k].Height, result.Txs[k+1].Height) + require.LessOrEqual(t, result.Txs[k].Index, result.Txs[k+1].Index) + } + + result, err = c.TxSearch(fmt.Sprintf("tx.height >= 1"), false, 1, 30, "desc") + require.Nil(t, err) + for k := 0; k < len(result.Txs)-1; k++ { + require.GreaterOrEqual(t, result.Txs[k].Height, result.Txs[k+1].Height) + require.GreaterOrEqual(t, result.Txs[k].Index, result.Txs[k+1].Index) + } } } diff --git a/rpc/core/routes.go b/rpc/core/routes.go index 0e959d6d4..42a57456a 100644 --- a/rpc/core/routes.go +++ b/rpc/core/routes.go @@ -23,7 +23,7 @@ var Routes = map[string]*rpc.RPCFunc{ "block_results": rpc.NewRPCFunc(BlockResults, "height"), "commit": rpc.NewRPCFunc(Commit, "height"), "tx": rpc.NewRPCFunc(Tx, "hash,prove"), - "tx_search": rpc.NewRPCFunc(TxSearch, "query,prove,page,per_page"), + "tx_search": rpc.NewRPCFunc(TxSearch, "query,prove,page,per_page,order_by"), "validators": rpc.NewRPCFunc(Validators, "height,page,per_page"), "dump_consensus_state": rpc.NewRPCFunc(DumpConsensusState, ""), "consensus_state": rpc.NewRPCFunc(ConsensusState, ""), diff --git a/rpc/core/tx.go b/rpc/core/tx.go index f3cd54e4f..cd6306060 100644 --- a/rpc/core/tx.go +++ b/rpc/core/tx.go @@ -2,9 +2,11 @@ package core import ( "fmt" + "sort" + + "github.com/pkg/errors" tmmath "github.com/tendermint/tendermint/libs/math" - tmquery "github.com/tendermint/tendermint/libs/pubsub/query" ctypes "github.com/tendermint/tendermint/rpc/core/types" rpctypes "github.com/tendermint/tendermint/rpc/lib/types" @@ -53,10 +55,11 @@ func Tx(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error // TxSearch allows you to query for multiple transactions results. It returns a // list of transactions (maximum ?per_page entries) and the total count. // More: https://docs.tendermint.com/master/rpc/#/Info/tx_search -func TxSearch(ctx *rpctypes.Context, query string, prove bool, page, perPage int) (*ctypes.ResultTxSearch, error) { +func TxSearch(ctx *rpctypes.Context, query string, prove bool, page, perPage int, orderBy string) ( + *ctypes.ResultTxSearch, error) { // if index is disabled, return error if _, ok := txIndexer.(*null.TxIndex); ok { - return nil, fmt.Errorf("transaction indexing is disabled") + return nil, errors.New("transaction indexing is disabled") } q, err := tmquery.New(query) @@ -100,5 +103,26 @@ func TxSearch(ctx *rpctypes.Context, query string, prove bool, page, perPage int } } + if len(apiResults) > 1 { + switch orderBy { + case "desc": + sort.Slice(apiResults, func(i, j int) bool { + if apiResults[i].Height == apiResults[j].Height { + return apiResults[i].Index > apiResults[j].Index + } + return apiResults[i].Height > apiResults[j].Height + }) + case "asc", "": + sort.Slice(apiResults, func(i, j int) bool { + if apiResults[i].Height == apiResults[j].Height { + return apiResults[i].Index < apiResults[j].Index + } + return apiResults[i].Height < apiResults[j].Height + }) + default: + return nil, errors.New("expected order_by to be either `asc` or `desc` or empty") + } + } + return &ctypes.ResultTxSearch{Txs: apiResults, TotalCount: totalCount}, nil } diff --git a/rpc/swagger/swagger.yaml b/rpc/swagger/swagger.yaml index f56380450..aa4d837ba 100644 --- a/rpc/swagger/swagger.yaml +++ b/rpc/swagger/swagger.yaml @@ -859,6 +859,14 @@ paths: type: number default: 30 example: 30 + - in: query + name: order_by + description: Order in which transactions are sorted ("asc" or "desc"), by height & index. If empty, default sorting will be still applied. + required: false + schema: + type: string + default: "asc" + example: "asc" tags: - Info description: | diff --git a/state/txindex/kv/kv.go b/state/txindex/kv/kv.go index ce894f25b..5fcd5ab73 100644 --- a/state/txindex/kv/kv.go +++ b/state/txindex/kv/kv.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/hex" "fmt" - "sort" "strconv" "strings" "time" @@ -160,12 +159,14 @@ func (txi *TxIndex) indexEvents(result *types.TxResult, hash []byte, store dbm.S } } -// Search performs a search using the given query. It breaks the query into -// conditions (like "tx.height > 5"). For each condition, it queries the DB -// index. One special use cases here: (1) if "tx.hash" is found, it returns tx -// result for it (2) for range queries it is better for the client to provide -// both lower and upper bounds, so we are not performing a full scan. Results -// from querying indexes are then intersected and returned to the caller. +// Search performs a search using the given query. +// +// It breaks the query into conditions (like "tx.height > 5"). For each +// condition, it queries the DB index. One special use cases here: (1) if +// "tx.hash" is found, it returns tx result for it (2) for range queries it is +// better for the client to provide both lower and upper bounds, so we are not +// performing a full scan. Results from querying indexes are then intersected +// and returned to the caller, in no particular order. func (txi *TxIndex) Search(q *query.Query) ([]*types.TxResult, error) { var hashesInitialized bool filteredHashes := make(map[string][]byte) @@ -250,14 +251,6 @@ func (txi *TxIndex) Search(q *query.Query) ([]*types.TxResult, error) { results = append(results, res) } - // sort by height & index by default - sort.Slice(results, func(i, j int) bool { - if results[i].Height == results[j].Height { - return results[i].Index < results[j].Index - } - return results[i].Height < results[j].Height - }) - return results, nil } diff --git a/state/txindex/kv/kv_test.go b/state/txindex/kv/kv_test.go index e6c077917..efb767f21 100644 --- a/state/txindex/kv/kv_test.go +++ b/state/txindex/kv/kv_test.go @@ -272,29 +272,6 @@ func TestTxSearchMultipleTxs(t *testing.T) { assert.NoError(t, err) require.Len(t, results, 3) - assert.Equal(t, []*types.TxResult{txResult3, txResult2, txResult}, results) -} - -func TestIndexAllTags(t *testing.T) { - indexer := NewTxIndex(db.NewMemDB(), IndexAllEvents()) - - txResult := txResultWithEvents([]abci.Event{ - {Type: "account", Attributes: []kv.Pair{{Key: []byte("owner"), Value: []byte("Ivan")}}}, - {Type: "account", Attributes: []kv.Pair{{Key: []byte("number"), Value: []byte("1")}}}, - }) - - err := indexer.Index(txResult) - require.NoError(t, err) - - results, err := indexer.Search(query.MustParse("account.number >= 1")) - assert.NoError(t, err) - assert.Len(t, results, 1) - assert.Equal(t, []*types.TxResult{txResult}, results) - - results, err = indexer.Search(query.MustParse("account.owner = 'Ivan'")) - assert.NoError(t, err) - assert.Len(t, results, 1) - assert.Equal(t, []*types.TxResult{txResult}, results) } func txResultWithEvents(events []abci.Event) *types.TxResult { From 6f93cfa54850144199b17475857e7fc66c20378e Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 28 Jan 2020 14:30:14 +0400 Subject: [PATCH 14/45] lite2: rename alternative providers to witnesses (#4344) Closes #4341 --- lite2/client.go | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/lite2/client.go b/lite2/client.go index b8ef6e807..1c8aca2b4 100644 --- a/lite2/client.go +++ b/lite2/client.go @@ -84,11 +84,12 @@ func SkippingVerification(trustLevel tmmath.Fraction) Option { } } -// AlternativeSources option can be used to supply alternative providers, which -// will be used for cross-checking the primary provider. -func AlternativeSources(providers []provider.Provider) Option { +// Witnesses option can be used to supply providers, which will be used for +// cross-checking the primary provider. A witness can become a primary iff the +// current primary is unavailable. +func Witnesses(providers []provider.Provider) Option { return func(c *Client) { - c.alternatives = providers + c.witnesses = providers } } @@ -142,9 +143,8 @@ type Client struct { // Primary provider of new headers. primary provider.Provider - // Alternative providers for checking the primary for misbehavior by - // comparing data. - alternatives []provider.Provider + // See Witnesses option + witnesses []provider.Provider // Where trusted headers are stored. trustedStore store.Store @@ -153,13 +153,15 @@ type Client struct { // Highest next validator set from the store (height=H+1). trustedNextVals *types.ValidatorSet - updatePeriod time.Duration + // See UpdatePeriod option + updatePeriod time.Duration + // See RemoveNoLongerTrustedHeadersPeriod option removeNoLongerTrustedHeadersPeriod time.Duration - routinesWaitGroup sync.WaitGroup - + // See ConfirmationFunction option confirmationFn func(action string) bool - quit chan struct{} + routinesWaitGroup sync.WaitGroup + quit chan struct{} logger log.Logger } @@ -518,8 +520,9 @@ func (c *Client) VerifyHeader(newHeader *types.SignedHeader, newVals *types.Vali return errors.Errorf("header at more recent height #%d exists", c.trustedHeader.Height) } - if len(c.alternatives) > 0 { - if err := c.compareNewHeaderWithRandomAlternative(newHeader); err != nil { + if len(c.witnesses) > 0 { + if err := c.compareNewHeaderWithRandomWitness(newHeader); err != nil { + c.logger.Error("Error when comparing new header with one from a witness", "err", err) return err } } @@ -721,25 +724,25 @@ func (c *Client) fetchHeaderAndValsAtHeight(height int64) (*types.SignedHeader, return h, vals, nil } -// compare header with one from a random alternative provider. -func (c *Client) compareNewHeaderWithRandomAlternative(h *types.SignedHeader) error { - // 1. Pick an alternative provider. - p := c.alternatives[tmrand.Intn(len(c.alternatives))] +// compare header with one from a random witness. +func (c *Client) compareNewHeaderWithRandomWitness(h *types.SignedHeader) error { + // 1. Pick a witness. + witness := c.witnesses[tmrand.Intn(len(c.witnesses))] // 2. Fetch the header. - altHeader, err := p.SignedHeader(h.Height) + altH, err := witness.SignedHeader(h.Height) if err != nil { return errors.Wrapf(err, - "failed to obtain header #%d from alternative provider %v", h.Height, p) + "failed to obtain header #%d from the witness %v", h.Height, witness) } // 3. Compare hashes. - if !bytes.Equal(h.Hash(), altHeader.Hash()) { + if !bytes.Equal(h.Hash(), altH.Hash()) { // TODO: One of the providers is lying. Send the evidence to fork // accountability server. return errors.Errorf( - "new header hash %X does not match one from alternative provider %X", - h.Hash(), altHeader.Hash()) + "header hash %X does not match one %X from the witness %v", + h.Hash(), altH.Hash(), witness) } return nil From c5ecd802a22f82b0a4787c68d749fbc1da682306 Mon Sep 17 00:00:00 2001 From: Marko Date: Tue, 28 Jan 2020 12:33:28 +0100 Subject: [PATCH 15/45] docs: update links to rpc (#4348) * docs: update links to rpc - links to rpc have not been updated. thank you @okwme Signed-off-by: Marko Baricevic * Update docs/app-dev/indexing-transactions.md --- docs/app-dev/app-architecture.md | 2 +- docs/app-dev/indexing-transactions.md | 4 ++-- docs/app-dev/subscribing-to-events-via-websocket.md | 2 +- docs/tendermint-core/running-in-production.md | 2 +- docs/tendermint-core/using-tendermint.md | 2 +- rpc/core/consensus.go | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/app-dev/app-architecture.md b/docs/app-dev/app-architecture.md index 074f4ad13..d98e279dc 100644 --- a/docs/app-dev/app-architecture.md +++ b/docs/app-dev/app-architecture.md @@ -56,6 +56,6 @@ Tendermint. See the following for more extensive documentation: - [Interchain Standard for the Light-Client REST API](https://github.com/cosmos/cosmos-sdk/pull/1028) -- [Tendermint RPC Docs](https://tendermint.com/rpc/) +- [Tendermint RPC Docs](https://docs.tendermint.com/master/rpc/) - [Tendermint in Production](../tendermint-core/running-in-production.md) - [ABCI spec](https://github.com/tendermint/spec/tree/95cf253b6df623066ff7cd4074a94e7a3f147c7a/spec/abci) diff --git a/docs/app-dev/indexing-transactions.md b/docs/app-dev/indexing-transactions.md index b3a4789b0..4afca5775 100644 --- a/docs/app-dev/indexing-transactions.md +++ b/docs/app-dev/indexing-transactions.md @@ -106,7 +106,7 @@ You can query the transaction results by calling `/tx_search` RPC endpoint: curl "localhost:26657/tx_search?query=\"account.name='igor'\"&prove=true" ``` -Check out [API docs](https://tendermint.com/rpc/#txsearch) for more information +Check out [API docs](https://docs.tendermint.com/master/rpc/#/Info/tx_search) for more information on query syntax and other options. ## Subscribing to Transactions @@ -125,5 +125,5 @@ a query to `/subscribe` RPC endpoint. } ``` -Check out [API docs](https://tendermint.com/rpc/#subscribe) for more information +Check out [API docs](https://docs.tendermint.com/master/rpc/#subscribe) for more information on query syntax and other options. diff --git a/docs/app-dev/subscribing-to-events-via-websocket.md b/docs/app-dev/subscribing-to-events-via-websocket.md index afedc1d59..5f5cc8921 100644 --- a/docs/app-dev/subscribing-to-events-via-websocket.md +++ b/docs/app-dev/subscribing-to-events-via-websocket.md @@ -24,7 +24,7 @@ method via Websocket. } ``` -Check out [API docs](https://tendermint.com/rpc/) for +Check out [API docs](https://docs.tendermint.com/master/rpc/) for more information on query syntax and other options. You can also use tags, given you had included them into DeliverTx diff --git a/docs/tendermint-core/running-in-production.md b/docs/tendermint-core/running-in-production.md index 1df370893..7a436ec95 100644 --- a/docs/tendermint-core/running-in-production.md +++ b/docs/tendermint-core/running-in-production.md @@ -99,7 +99,7 @@ send & receive rate per connection (`SendRate`, `RecvRate`). ### RPC Endpoints returning multiple entries are limited by default to return 30 -elements (100 max). See the [RPC Documentation](https://tendermint.com/rpc/) +elements (100 max). See the [RPC Documentation](https://docs.tendermint.com/master/rpc/) for more information. Rate-limiting and authentication are another key aspects to help protect diff --git a/docs/tendermint-core/using-tendermint.md b/docs/tendermint-core/using-tendermint.md index 46b6cc1b5..2c6370e84 100644 --- a/docs/tendermint-core/using-tendermint.md +++ b/docs/tendermint-core/using-tendermint.md @@ -160,7 +160,7 @@ endpoints. Some take no arguments (like `/status`), while others specify the argument name and use `_` as a placeholder. ::: tip -Find the RPC Documentation [here](https://tendermint.com/rpc/) +Find the RPC Documentation [here](https://docs.tendermint.com/master/rpc/) ::: ### Formatting diff --git a/rpc/core/consensus.go b/rpc/core/consensus.go index d88a6ba6a..a2a619ea5 100644 --- a/rpc/core/consensus.go +++ b/rpc/core/consensus.go @@ -79,7 +79,7 @@ func DumpConsensusState(ctx *rpctypes.Context) (*ctypes.ResultDumpConsensusState // ConsensusState returns a concise summary of the consensus state. // UNSTABLE -// More: https://tendermint.com/rpc/#/Info/consensus_state +// More: https://docs.tendermint.com/master/rpc/#/Info/consensus_state func ConsensusState(ctx *rpctypes.Context) (*ctypes.ResultConsensusState, error) { // Get self round state. bz, err := consensusState.GetRoundStateSimpleJSON() From 85244a42ea306dafef90a73405202825076e7173 Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Tue, 28 Jan 2020 17:16:16 +0100 Subject: [PATCH 16/45] lite2: refactor cleanup() (#4343) * lite2: add Start method There are few reasons to do that: 1) separation of state and dynamics (some users will want to delay starting the light client; does not matter we should not allow them to create a light client object) 2) less important, but some users might not need autoUpdateRoutine and removeNoLongerTrustedHeadersRoutine routines * lite2: wait till routines are finished in Stop because they are started in Start, it feels more natural to wait for them to finish in Stop. * lite2: add TrustedValidatorSet func * refactor cleanup code * changed restore header and val function to handle negative height * reverted restoreTrustedHeaderAndNextVals() functionality Co-authored-by: Anton Kaliaev --- lite2/client.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lite2/client.go b/lite2/client.go index 1c8aca2b4..446e272f7 100644 --- a/lite2/client.go +++ b/lite2/client.go @@ -282,8 +282,6 @@ func (c *Client) checkTrustedHeaderUsingOptions(options TrustOptions) error { if c.confirmationFn(action) { // remove all the headers ( options.Height, trustedHeader.Height ] c.cleanup(options.Height + 1) - // set c.trustedHeader to one at options.Height - c.restoreTrustedHeaderAndNextVals() c.logger.Info("Rolled back to older header (newer headers were removed)", "old", options.Height) @@ -555,7 +553,7 @@ func (c *Client) Cleanup() error { return c.cleanup(0) } -// stopHeight=0 -> remove all data +// cleanup deletes all headers & validator sets between +stopHeight+ and latest height included func (c *Client) cleanup(stopHeight int64) error { // 1) Get the oldest height. oldestHeight, err := c.trustedStore.FirstSignedHeaderHeight() @@ -570,7 +568,7 @@ func (c *Client) cleanup(stopHeight int64) error { } // 3) Remove all headers and validator sets. - if stopHeight == 0 { + if stopHeight < oldestHeight { stopHeight = oldestHeight } for height := stopHeight; height <= latestHeight; height++ { @@ -583,6 +581,10 @@ func (c *Client) cleanup(stopHeight int64) error { c.trustedHeader = nil c.trustedNextVals = nil + err = c.restoreTrustedHeaderAndNextVals() + if err != nil { + return err + } return nil } From 587ac3a5635829802bcfe5b4976c52210fefe233 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 29 Jan 2020 10:04:42 +0400 Subject: [PATCH 17/45] node: use GRPCMaxOpenConnections when creating the gRPC server (#4349) not MaxOpenConnections Fixes #4311 Also, set MaxBodyBytes, MaxHeaderBytes and WriteTimeout similar to HTTP server. --- CHANGELOG_PENDING.md | 5 ++--- node/node.go | 11 ++++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index c100f12bc..fa7624986 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -24,6 +24,5 @@ program](https://hackerone.com/tendermint). ### BUG FIXES: -- [rpc] [#\4319] Check BlockMeta is not nil in Blocks & BlockByHash - - +- [node] [#\4311] Use `GRPCMaxOpenConnections` when creating the gRPC server, not `MaxOpenConnections` +- [rpc] [#\4319] Check `BlockMeta` is not nil in `/block` & `/block_by_hash` diff --git a/node/node.go b/node/node.go index ffca39ee0..104e572fb 100644 --- a/node/node.go +++ b/node/node.go @@ -948,7 +948,16 @@ func (n *Node) startRPC() ([]net.Listener, error) { grpcListenAddr := n.config.RPC.GRPCListenAddress if grpcListenAddr != "" { config := rpcserver.DefaultConfig() - config.MaxOpenConnections = n.config.RPC.MaxOpenConnections + config.MaxBodyBytes = n.config.RPC.MaxBodyBytes + config.MaxHeaderBytes = n.config.RPC.MaxHeaderBytes + // NOTE: GRPCMaxOpenConnections is used, not MaxOpenConnections + config.MaxOpenConnections = n.config.RPC.GRPCMaxOpenConnections + // If necessary adjust global WriteTimeout to ensure it's greater than + // TimeoutBroadcastTxCommit. + // See https://github.com/tendermint/tendermint/issues/3435 + if config.WriteTimeout <= n.config.RPC.TimeoutBroadcastTxCommit { + config.WriteTimeout = n.config.RPC.TimeoutBroadcastTxCommit + 1*time.Second + } listener, err := rpcserver.Listen(grpcListenAddr, config) if err != nil { return nil, err From 79b99f052bef09046f90b1f853f482cd7721269e Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 29 Jan 2020 10:14:32 +0400 Subject: [PATCH 18/45] lite2: batch save & delete operations in DB store (#4345) Closes #4330 --- lite2/store/db/db.go | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/lite2/store/db/db.go b/lite2/store/db/db.go index 4f534cd11..32c5a4d50 100644 --- a/lite2/store/db/db.go +++ b/lite2/store/db/db.go @@ -1,11 +1,11 @@ package db import ( - "errors" "fmt" "regexp" "strconv" + "github.com/pkg/errors" "github.com/tendermint/go-amino" dbm "github.com/tendermint/tm-db" @@ -38,20 +38,21 @@ func (s *dbs) SaveSignedHeaderAndNextValidatorSet(sh *types.SignedHeader, valSet panic("negative or zero height") } - // TODO: batch - bz, err := s.cdc.MarshalBinaryLengthPrefixed(sh) + shBz, err := s.cdc.MarshalBinaryLengthPrefixed(sh) if err != nil { - return err + return errors.Wrap(err, "marshalling header") } - s.db.Set(s.shKey(sh.Height), bz) - - bz, err = s.cdc.MarshalBinaryLengthPrefixed(valSet) + valSetBz, err := s.cdc.MarshalBinaryLengthPrefixed(valSet) if err != nil { - return err + return errors.Wrap(err, "marshalling validator set") } - s.db.Set(s.vsKey(sh.Height+1), bz) - return nil + b := s.db.NewBatch() + b.Set(s.shKey(sh.Height), shBz) + b.Set(s.vsKey(sh.Height+1), valSetBz) + err = b.WriteSync() + b.Close() + return err } // DeleteSignedHeaderAndNextValidatorSet deletes SignedHeader and ValidatorSet @@ -61,11 +62,12 @@ func (s *dbs) DeleteSignedHeaderAndNextValidatorSet(height int64) error { panic("negative or zero height") } - // TODO: batch - s.db.Delete(s.shKey(height)) - s.db.Delete(s.vsKey(height + 1)) - - return nil + b := s.db.NewBatch() + b.Delete(s.shKey(height)) + b.Delete(s.vsKey(height + 1)) + err := b.WriteSync() + b.Close() + return err } // SignedHeader loads SignedHeader at the given height. From 8b80de830f4c88eb345e51e0af0b3dc171db6578 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 29 Jan 2020 12:41:44 +0100 Subject: [PATCH 19/45] build(deps): bump google.golang.org/grpc from 1.26.0 to 1.27.0 (#4355) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.26.0 to 1.27.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.26.0...v1.27.0) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 3d1dc21c3..4a2c8d1fa 100644 --- a/go.mod +++ b/go.mod @@ -32,5 +32,5 @@ require ( golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 golang.org/x/net v0.0.0-20190628185345-da137c7871d7 golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a // indirect - google.golang.org/grpc v1.26.0 + google.golang.org/grpc v1.27.0 ) diff --git a/go.sum b/go.sum index 31930911c..a718c9bfe 100644 --- a/go.sum +++ b/go.sum @@ -286,6 +286,8 @@ google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 71d50f7ab5c27beb1a8d36d89343ce66ec57ac3d Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Thu, 30 Jan 2020 08:21:17 +0100 Subject: [PATCH 20/45] lite2: panic if witness is on another chain (#4356) Closes #4350 Checks that the chain ID of the witness and that of the lite client are the same before updating the witness list. --- lite2/client.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lite2/client.go b/lite2/client.go index 446e272f7..4d49c9cac 100644 --- a/lite2/client.go +++ b/lite2/client.go @@ -89,6 +89,11 @@ func SkippingVerification(trustLevel tmmath.Fraction) Option { // current primary is unavailable. func Witnesses(providers []provider.Provider) Option { return func(c *Client) { + for _, witness := range providers { + if witness.ChainID() != c.ChainID() { + panic("Witness chainID is not equal to the Lite Client chainID") + } + } c.witnesses = providers } } From b04b752e5bc929658db5ef14b56b78acd89740ae Mon Sep 17 00:00:00 2001 From: Erik Grinaker Date: Thu, 30 Jan 2020 11:57:24 +0100 Subject: [PATCH 21/45] Add ADR-053: State Sync Prototype (#4352) --- .../adr-053-state-sync-prototype.md | 209 ++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 docs/architecture/adr-053-state-sync-prototype.md diff --git a/docs/architecture/adr-053-state-sync-prototype.md b/docs/architecture/adr-053-state-sync-prototype.md new file mode 100644 index 000000000..95615325d --- /dev/null +++ b/docs/architecture/adr-053-state-sync-prototype.md @@ -0,0 +1,209 @@ +# ADR 053: State Sync Prototype + +This ADR outlines the plan for an initial state sync prototype, and is subject to change as we gain feedback and experience. It builds on discussions and findings in [ADR-042](./adr-042-state-sync.md), see that for background information. + +## Changelog + +* 2020-01-28: Initial draft (Erik Grinaker) + +## Context + +State sync will allow a new node to receive a snapshot of the application state without downloading blocks or going through consensus. This bootstraps the node significantly faster than the current fast sync system, which replays all historical blocks. + +Background discussions and justifications are detailed in [ADR-042](./adr-042-state-sync.md). Its recommendations can be summarized as: + +* The application periodically takes full state snapshots (i.e. eager snapshots). + +* The application splits snapshots into smaller chunks that can be individually verified against a chain app hash. + +* Tendermint uses the light client to obtain a trusted chain app hash for verification. + +* Tendermint discovers and downloads snapshot chunks in parallel from multiple peers, and passes them to the application via ABCI to be applied and verified against the chain app hash. + +* Historical blocks are not backfilled, so state synced nodes will have a truncated block history. + +## Tendermint Proposal + +This describes the snapshot/restore process seen from Tendermint. The interface is kept as small and general as possible to give applications maximum flexibility. + +### Snapshot Data Structure + +A node can have multiple snapshots taken at various heights. Snapshots can be taken in different application-specified formats (e.g. MessagePack as format `1` and Protobuf as format `2`, or similarly for schema versioning). Each snapshot consists of multiple chunks containing the actual state data, allowing parallel downloads and reduced memory usage. + +```proto +message Snapshot { + uint64 height = 1; // The height at which the snapshot was taken + uint32 format = 2; // The application-specific snapshot format + uint64 chunks = 3; // The number of chunks in the snapshot + bytes metadata = 4; // Arbitrary application metadata +} + +message SnapshotChunk { + uint64 height = 1; // The height of the corresponding snapshot + uint32 format = 2; // The application-specific snapshot format + uint64 chunk = 3; // The chunk index (zero-based) + bytes data = 4; // Serialized application state in an arbitrary format + bytes checksum = 5; // SHA-1 checksum of data +} +``` + +Chunk verification data must be encoded along with the state data in the `data` field. + +Chunk `data` cannot be larger than 64 MB, and snapshot `metadata` cannot be larger than 64 KB. + +### ABCI Interface + +```proto +// Lists available snapshots +message RequestListSnapshots {} + +message ResponseListSnapshots { + repeated Snapshot snapshots = 1; +} + +// Offers a snapshot to the application +message RequestOfferSnapshot { + Snapshot snapshot = 1; +} + +message ResponseOfferSnapshot { + bool accepted = 1; + enum reason { // Reason why snapshot was rejected + unknown = 0; // Unknown or generic reason + invalid_height = 1; // Height is rejected: avoid this height + invalid_format = 2; // Format is rejected: avoid this format + } +} + +// Fetches a snapshot chunk +message RequestGetSnapshotChunk { + uint64 height = 1; + uint32 format = 2; + uint64 chunk = 3; +} + +message ResponseGetSnapshotChunk { + SnapshotChunk chunk = 1; +} + +// Applies a snapshot chunk +message RequestApplySnapshotChunk { + SnapshotChunk chunk = 1; + bytes chain_hash = 2; +} + +message ResponseApplySnapshotChunk { + bool applied = 1; + enum reason { // Reason why chunk failed + unknown = 0; // Unknown or generic reason + verify_failed = 1; // Chunk verification failed + } +} +``` + +### Taking Snapshots + +Tendermint is not aware of the snapshotting process at all, it is entirely an application concern. The following guarantees must be provided: + +* **Periodic:** snapshots must be taken periodically, not on-demand, for faster restores, lower load, and less DoS risk. + +* **Deterministic:** snapshots must be deterministic, and identical across all nodes - typically by taking a snapshot at given height intervals. + +* **Consistent:** snapshots must be consistent, i.e. not affected by concurrent writes - typically by using a data store that supports versioning and/or snapshot isolation. + +* **Asynchronous:** snapshots must be asynchronous, i.e. not halt block processing and state transitions. + +* **Chunked:** snapshots must be split into chunks of reasonable size (on the order of megabytes), and each chunk must be verifiable against the chain app hash. + +* **Garbage collected:** snapshots must be garbage collected periodically. + +### Restoring Snapshots + +Nodes should have options for enabling state sync and/or fast sync, and be provided a trusted header hash for the light client. + +When starting an empty node with state sync and fast sync enabled, snapshots are restored as follows: + +1. The node checks that it is empty, i.e. that it has no state nor blocks. + +2. The node contacts the given seeds to discover peers. + +3. The node contacts a set of full nodes, and verifies the trusted block header using the given hash via the light client. + +4. The node requests available snapshots via `RequestListSnapshots`. Snapshots with `metadata` greater than 64 KB are rejected. + +5. The node iterates over all snapshots in reverse order by height and format until it finds one that satisfies all of the following conditions: + + * The snapshot height's block is considered trustworthy by the light client (i.e. snapshot height is greater than trusted header and within unbonding period of the latest trustworthy block). + + * The snapshot's height or format hasn't been explicitly rejected by an earlier `RequestOffsetSnapshot` call (via `invalid_height` or `invalid_format`). + + * The application accepts the `RequestOfferSnapshot` call. + +6. The node downloads chunks in parallel from multiple peers via `RequestGetSnapshotChunk`, and both the sender and receiver verifies their checksums. Chunks with `data` greater than 64 MB are rejected. + +7. The node passes chunks sequentially to the app via `RequestApplySnapshotChunk`, along with the chain's app hash at the snapshot height for verification. If the chunk is rejected the node should retry it. If it was rejected with `verify_failed`, it should be refetched from a different source. If an internal error occurred, `ResponseException` should be returned and state sync should be aborted. + +8. Once all chunks have been applied, the node compares the app hash to the chain app hash, and if they do not match it either errors or discards the state and starts over. + +9. The node switches to fast sync to catch up blocks that were committed while restoring the snapshot. + +10. The node switches to normal consensus mode. + +## Gaia Proposal + +This describes the snapshot process seen from Gaia, using format version `1`. The serialization format is unspecified, but likely to be compressed Amino or Protobuf. + +### Snapshot Metadata + +In the initial version there is no snapshot metadata, so it is set to an empty byte buffer. + +Once all chunks have been successfully built, snapshot metadata should be serialized and stored in the file system as e.g. `snapshots///metadata`, and served via `RequestListSnapshots`. + +### Snapshot Chunk Format + +The Gaia data structure consists of a set of named IAVL trees. A root hash is constructed by taking the root hashes of each of the IAVL trees, then constructing a Merkle tree of the sorted name/hash map. + +IAVL trees are versioned, but a snapshot only contains the version relevant for the snapshot height. All historical versions are ignored. + +IAVL trees are insertion-order dependent, so key/value pairs must be stored in an appropriate insertion order to produce the same tree branching structure and thus the same Merkle hashes. + +A chunk corresponds to a subtree key range within an IAVL tree, in insertion order, along with the Merkle proof from the root of the subtree all the way up to the root of the multistore (including the Merkle proof for the surrounding multistore. + +```go +struct SnapshotChunk { + Store string // Name (key) of IAVL store in outer MultiStore + Keys [][]byte // Snapshotted keys in insertion order + Values [][]byte // Snapshotted values corresponding to Keys + Proof []merkle.ProofOp // Merkle proof from subtree root to MultiStore root +} +``` + +This chunk structure is believed to be sufficient to reconstruct an identical IAVL tree by applying separate chunks, but this may require the chunks to be ordered in a certain way; further research is needed. + +We do not use IAVL RangeProofs, since these include redundant data such as proofs for intermediate and leaf nodes that can be derived from the above data. + +Chunks should be built greedily by collecting key/value pairs constituting a complete subtree up to some size limit (e.g. 32 MB), then serialized. Chunk data is stored in the file system as `snapshots////data`, along with a SHA-1 checksum in `snapshots////checksum`, and served via `RequestGetSnapshotChunk`. + +### Snapshot Scheduling + +Snapshots should be taken at some configurable height interval, e.g. every 1000 blocks. All nodes should preferably have the same snapshot schedule, such that all nodes can serve chunks for a given snapshot. + +Taking consistent snapshots of IAVL trees is greatly simplified by them being versioned: simply snapshot the version that corresponds to the snapshot height, while concurrent writes create new versions. IAVL pruning must not prune a version that is being snapshotted. + +Snapshots must also be garbage collected after some configurable time, e.g. by keeping the latest `n` snapshots. + +## Open Questions + +* Is it possible to reconstruct an identical IAVL tree given separate subtrees in an appropriate order, or is more data needed about the branch structure? + +* Should we punish nodes that provide invalid snapshots? + +* Is it OK for state-synced nodes to not have historical blocks nor historical IAVL versions? + +## Status + +Proposed + +## References + +* [ADR-042](./adr-042-state-sync.md) and its references From ca03e43d931bf64e455b182164b302234dbd030a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 30 Jan 2020 15:34:07 +0400 Subject: [PATCH 22/45] deps: bump github.com/golang/protobuf from 1.3.2 to 1.3.3 (#4359) Bumps [github.com/golang/protobuf](https://github.com/golang/protobuf) from 1.3.2 to 1.3.3. - [Release notes](https://github.com/golang/protobuf/releases) - [Commits](https://github.com/golang/protobuf/compare/v1.3.2...v1.3.3) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 4a2c8d1fa..93f65f57d 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/go-kit/kit v0.9.0 github.com/go-logfmt/logfmt v0.5.0 github.com/gogo/protobuf v1.3.1 - github.com/golang/protobuf v1.3.2 + github.com/golang/protobuf v1.3.3 github.com/google/gofuzz v1.0.0 // indirect github.com/gorilla/websocket v1.4.1 github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f diff --git a/go.sum b/go.sum index a718c9bfe..ce0ff1081 100644 --- a/go.sum +++ b/go.sum @@ -82,6 +82,8 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= From 81e3cca340796fd186c3b12ca6c1c46750d01925 Mon Sep 17 00:00:00 2001 From: Tess Rinearson Date: Mon, 3 Feb 2020 12:56:34 +0100 Subject: [PATCH 23/45] docs: update npm dependencies (#4364) --- docs/package-lock.json | 3446 ++++++++++++++++++++++++++-------------- docs/package.json | 2 +- 2 files changed, 2241 insertions(+), 1207 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 78267219c..e5e653713 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -5,27 +5,28 @@ "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", "requires": { - "@babel/highlight": "^7.0.0" + "@babel/highlight": "^7.8.3" } }, "@babel/core": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.2.tgz", - "integrity": "sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.4.tgz", + "integrity": "sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==", "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.7.2", - "@babel/helpers": "^7.7.0", - "@babel/parser": "^7.7.2", - "@babel/template": "^7.7.0", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.7.2", + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helpers": "^7.8.4", + "@babel/parser": "^7.8.4", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.4", + "@babel/types": "^7.8.3", "convert-source-map": "^1.7.0", "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", "json5": "^2.1.0", "lodash": "^4.17.13", "resolve": "^1.3.2", @@ -54,6 +55,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -62,11 +68,11 @@ } }, "@babel/generator": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.2.tgz", - "integrity": "sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", + "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", "requires": { - "@babel/types": "^7.7.2", + "@babel/types": "^7.8.3", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0" @@ -80,214 +86,214 @@ } }, "@babel/helper-annotate-as-pure": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.0.tgz", - "integrity": "sha512-k50CQxMlYTYo+GGyUGFwpxKVtxVJi9yh61sXZji3zYHccK9RYliZGSTOgci85T+r+0VFN2nWbGM04PIqwfrpMg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz", + "integrity": "sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw==", "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.8.3" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.0.tgz", - "integrity": "sha512-Cd8r8zs4RKDwMG/92lpZcnn5WPQ3LAMQbCw42oqUh4s7vsSN5ANUZjMel0OOnxDLq57hoDDbai+ryygYfCTOsw==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz", + "integrity": "sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw==", "requires": { - "@babel/helper-explode-assignable-expression": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-explode-assignable-expression": "^7.8.3", + "@babel/types": "^7.8.3" } }, "@babel/helper-call-delegate": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.7.0.tgz", - "integrity": "sha512-Su0Mdq7uSSWGZayGMMQ+z6lnL00mMCnGAbO/R0ZO9odIdB/WNU/VfQKqMQU0fdIsxQYbRjDM4BixIa93SQIpvw==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz", + "integrity": "sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A==", "requires": { - "@babel/helper-hoist-variables": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-hoist-variables": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" } }, "@babel/helper-create-class-features-plugin": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.7.0.tgz", - "integrity": "sha512-MZiB5qvTWoyiFOgootmRSDV1udjIqJW/8lmxgzKq6oDqxdmHUjeP2ZUOmgHdYjmUVNABqRrHjYAYRvj8Eox/UA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz", + "integrity": "sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA==", "requires": { - "@babel/helper-function-name": "^7.7.0", - "@babel/helper-member-expression-to-functions": "^7.7.0", - "@babel/helper-optimise-call-expression": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.7.0", - "@babel/helper-split-export-declaration": "^7.7.0" + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3" } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.2.tgz", - "integrity": "sha512-pAil/ZixjTlrzNpjx+l/C/wJk002Wo7XbbZ8oujH/AoJ3Juv0iN/UTcPUHXKMFLqsfS0Hy6Aow8M31brUYBlQQ==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz", + "integrity": "sha512-Gcsm1OHCUr9o9TcJln57xhWHtdXbA2pgQ58S0Lxlks0WMGNXuki4+GLfX0p+L2ZkINUGZvfkz8rzoqJQSthI+Q==", "requires": { - "@babel/helper-regex": "^7.4.4", + "@babel/helper-regex": "^7.8.3", "regexpu-core": "^4.6.0" } }, "@babel/helper-define-map": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.7.0.tgz", - "integrity": "sha512-kPKWPb0dMpZi+ov1hJiwse9dWweZsz3V9rP4KdytnX1E7z3cTNmFGglwklzFPuqIcHLIY3bgKSs4vkwXXdflQA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz", + "integrity": "sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g==", "requires": { - "@babel/helper-function-name": "^7.7.0", - "@babel/types": "^7.7.0", + "@babel/helper-function-name": "^7.8.3", + "@babel/types": "^7.8.3", "lodash": "^4.17.13" } }, "@babel/helper-explode-assignable-expression": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.0.tgz", - "integrity": "sha512-CDs26w2shdD1urNUAji2RJXyBFCaR+iBEGnFz3l7maizMkQe3saVw9WtjG1tz8CwbjvlFnaSLVhgnu1SWaherg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz", + "integrity": "sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw==", "requires": { - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" } }, "@babel/helper-function-name": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz", - "integrity": "sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", "requires": { - "@babel/helper-get-function-arity": "^7.7.0", - "@babel/template": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" } }, "@babel/helper-get-function-arity": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz", - "integrity": "sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.8.3" } }, "@babel/helper-hoist-variables": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.0.tgz", - "integrity": "sha512-LUe/92NqsDAkJjjCEWkNe+/PcpnisvnqdlRe19FahVapa4jndeuJ+FBiTX1rcAKWKcJGE+C3Q3tuEuxkSmCEiQ==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz", + "integrity": "sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg==", "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.8.3" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.0.tgz", - "integrity": "sha512-QaCZLO2RtBcmvO/ekOLp8p7R5X2JriKRizeDpm5ChATAFWrrYDcDxPuCIBXKyBjY+i1vYSdcUTMIb8psfxHDPA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", + "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.8.3" } }, "@babel/helper-module-imports": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.0.tgz", - "integrity": "sha512-Dv3hLKIC1jyfTkClvyEkYP2OlkzNvWs5+Q8WgPbxM5LMeorons7iPP91JM+DU7tRbhqA1ZeooPaMFvQrn23RHw==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", + "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==", "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.8.3" } }, "@babel/helper-module-transforms": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.7.0.tgz", - "integrity": "sha512-rXEefBuheUYQyX4WjV19tuknrJFwyKw0HgzRwbkyTbB+Dshlq7eqkWbyjzToLrMZk/5wKVKdWFluiAsVkHXvuQ==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz", + "integrity": "sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q==", "requires": { - "@babel/helper-module-imports": "^7.7.0", - "@babel/helper-simple-access": "^7.7.0", - "@babel/helper-split-export-declaration": "^7.7.0", - "@babel/template": "^7.7.0", - "@babel/types": "^7.7.0", + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-simple-access": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3", "lodash": "^4.17.13" } }, "@babel/helper-optimise-call-expression": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.0.tgz", - "integrity": "sha512-48TeqmbazjNU/65niiiJIJRc5JozB8acui1OS7bSd6PgxfuovWsvjfWSzlgx+gPFdVveNzUdpdIg5l56Pl5jqg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", + "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.8.3" } }, "@babel/helper-plugin-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==" + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==" }, "@babel/helper-regex": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", - "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.8.3.tgz", + "integrity": "sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ==", "requires": { "lodash": "^4.17.13" } }, "@babel/helper-remap-async-to-generator": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.0.tgz", - "integrity": "sha512-pHx7RN8X0UNHPB/fnuDnRXVZ316ZigkO8y8D835JlZ2SSdFKb6yH9MIYRU4fy/KPe5sPHDFOPvf8QLdbAGGiyw==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz", + "integrity": "sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA==", "requires": { - "@babel/helper-annotate-as-pure": "^7.7.0", - "@babel/helper-wrap-function": "^7.7.0", - "@babel/template": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-wrap-function": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" } }, "@babel/helper-replace-supers": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.7.0.tgz", - "integrity": "sha512-5ALYEul5V8xNdxEeWvRsBzLMxQksT7MaStpxjJf9KsnLxpAKBtfw5NeMKZJSYDa0lKdOcy0g+JT/f5mPSulUgg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz", + "integrity": "sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA==", "requires": { - "@babel/helper-member-expression-to-functions": "^7.7.0", - "@babel/helper-optimise-call-expression": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" } }, "@babel/helper-simple-access": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.7.0.tgz", - "integrity": "sha512-AJ7IZD7Eem3zZRuj5JtzFAptBw7pMlS3y8Qv09vaBWoFsle0d1kAn5Wq6Q9MyBXITPOKnxwkZKoAm4bopmv26g==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", + "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==", "requires": { - "@babel/template": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" } }, "@babel/helper-split-export-declaration": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz", - "integrity": "sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.8.3" } }, "@babel/helper-wrap-function": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.7.0.tgz", - "integrity": "sha512-sd4QjeMgQqzshSjecZjOp8uKfUtnpmCyQhKQrVJBBgeHAB/0FPi33h3AbVlVp07qQtMD4QgYSzaMI7VwncNK/w==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz", + "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==", "requires": { - "@babel/helper-function-name": "^7.7.0", - "@babel/template": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-function-name": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" } }, "@babel/helpers": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.0.tgz", - "integrity": "sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz", + "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==", "requires": { - "@babel/template": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.4", + "@babel/types": "^7.8.3" } }, "@babel/highlight": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", - "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", "requires": { "chalk": "^2.0.0", "esutils": "^2.0.2", @@ -295,391 +301,399 @@ } }, "@babel/parser": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.3.tgz", - "integrity": "sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A==" + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==" }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.0.tgz", - "integrity": "sha512-ot/EZVvf3mXtZq0Pd0+tSOfGWMizqmOohXmNZg6LNFjHOV+wOPv7BvVYh8oPR8LhpIP3ye8nNooKL50YRWxpYA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz", + "integrity": "sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.7.0", - "@babel/plugin-syntax-async-generators": "^7.2.0" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-remap-async-to-generator": "^7.8.3", + "@babel/plugin-syntax-async-generators": "^7.8.0" } }, "@babel/plugin-proposal-class-properties": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.7.0.tgz", - "integrity": "sha512-tufDcFA1Vj+eWvwHN+jvMN6QsV5o+vUlytNKrbMiCeDL0F2j92RURzUsUMWE5EJkLyWxjdUslCsMQa9FWth16A==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz", + "integrity": "sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-proposal-decorators": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.7.0.tgz", - "integrity": "sha512-dMCDKmbYFQQTn1+VJjl5hbqlweuHl5oDeMU9B1Q7oAWi0mHxjQQDHdJIK6iW76NE1KJT3zA6dDU3weR1WT5D4A==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.8.3.tgz", + "integrity": "sha512-e3RvdvS4qPJVTe288DlXjwKflpfy1hr0j5dz5WpIYYeP7vQZg2WfAEIp8k5/Lwis/m5REXEteIz6rrcDtXXG7w==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-decorators": "^7.2.0" + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-decorators": "^7.8.3" } }, "@babel/plugin-proposal-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", - "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz", + "integrity": "sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-json-strings": "^7.2.0" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0" } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz", - "integrity": "sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0" } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", - "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.0.tgz", - "integrity": "sha512-mk34H+hp7kRBWJOOAR0ZMGCydgKMD4iN9TpDRp3IIcbunltxEY89XSimc6WbtSLCDrwcdy/EEw7h5CFCzxTchw==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.3.tgz", + "integrity": "sha512-1/1/rEZv2XGweRwwSkLpY+s60za9OZ1hJs4YDqFHCw0kYWYwL5IFljVY1MYBL+weT1l9pokDO2uhSTLVxzoHkQ==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-syntax-async-generators": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", - "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-decorators": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.2.0.tgz", - "integrity": "sha512-38QdqVoXdHUQfTpZo3rQwqQdWtCn5tMv4uV6r2RMfTqNBuv4ZBhz79SfaQWKTVmxHjeFv/DnXVC/+agHCklYWA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.8.3.tgz", + "integrity": "sha512-8Hg4dNNT9/LcA1zQlfwuKR8BUc/if7Q7NkTam9sGTcJphLwpf2g4S42uhspQrIrR+dpzE0dtTqBVFoHl8GtnnQ==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-syntax-dynamic-import": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", - "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", - "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-jsx": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz", - "integrity": "sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz", + "integrity": "sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-syntax-object-rest-spread": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", - "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", - "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", - "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz", + "integrity": "sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.0.tgz", - "integrity": "sha512-vLI2EFLVvRBL3d8roAMqtVY0Bm9C1QzLkdS57hiKrjUBSqsQYrBsMCeOg/0KK7B0eK9V71J5mWcha9yyoI2tZw==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz", + "integrity": "sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ==", "requires": { - "@babel/helper-module-imports": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.7.0" + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-remap-async-to-generator": "^7.8.3" } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", - "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz", + "integrity": "sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz", - "integrity": "sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz", + "integrity": "sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-plugin-utils": "^7.8.3", "lodash": "^4.17.13" } }, "@babel/plugin-transform-classes": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.0.tgz", - "integrity": "sha512-/b3cKIZwGeUesZheU9jNYcwrEA7f/Bo4IdPmvp7oHgvks2majB5BoT5byAql44fiNQYOPzhk2w8DbgfuafkMoA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz", + "integrity": "sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w==", "requires": { - "@babel/helper-annotate-as-pure": "^7.7.0", - "@babel/helper-define-map": "^7.7.0", - "@babel/helper-function-name": "^7.7.0", - "@babel/helper-optimise-call-expression": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.7.0", - "@babel/helper-split-export-declaration": "^7.7.0", + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-define-map": "^7.8.3", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", "globals": "^11.1.0" } }, "@babel/plugin-transform-computed-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", - "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz", + "integrity": "sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-destructuring": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz", - "integrity": "sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.3.tgz", + "integrity": "sha512-H4X646nCkiEcHZUZaRkhE2XVsoz0J/1x3VVujnn96pSoGCtKPA99ZZA+va+gK+92Zycd6OBKCD8tDb/731bhgQ==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.0.tgz", - "integrity": "sha512-3QQlF7hSBnSuM1hQ0pS3pmAbWLax/uGNCbPBND9y+oJ4Y776jsyujG2k0Sn2Aj2a0QwVOiOFL5QVPA7spjvzSA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz", + "integrity": "sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", - "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz", + "integrity": "sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", - "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz", + "integrity": "sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ==", "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-for-of": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", - "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz", + "integrity": "sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-function-name": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.0.tgz", - "integrity": "sha512-P5HKu0d9+CzZxP5jcrWdpe7ZlFDe24bmqP6a6X8BHEBl/eizAsY8K6LX8LASZL0Jxdjm5eEfzp+FIrxCm/p8bA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz", + "integrity": "sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ==", "requires": { - "@babel/helper-function-name": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", - "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz", + "integrity": "sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", - "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz", + "integrity": "sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ==", "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.0.tgz", - "integrity": "sha512-KEMyWNNWnjOom8vR/1+d+Ocz/mILZG/eyHHO06OuBQ2aNhxT62fr4y6fGOplRx+CxCSp3IFwesL8WdINfY/3kg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz", + "integrity": "sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg==", "requires": { - "@babel/helper-module-transforms": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.7.0", + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-simple-access": "^7.8.3", "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.0.tgz", - "integrity": "sha512-ZAuFgYjJzDNv77AjXRqzQGlQl4HdUM6j296ee4fwKVZfhDR9LAGxfvXjBkb06gNETPnN0sLqRm9Gxg4wZH6dXg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz", + "integrity": "sha512-8cESMCJjmArMYqa9AO5YuMEkE4ds28tMpZcGZB/jl3n0ZzlsxOAi3mC+SKypTfT8gjMupCnd3YiXCkMjj2jfOg==", "requires": { - "@babel/helper-hoist-variables": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-hoist-variables": "^7.8.3", + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.0.tgz", - "integrity": "sha512-u7eBA03zmUswQ9LQ7Qw0/ieC1pcAkbp5OQatbWUzY1PaBccvuJXUkYzoN1g7cqp7dbTu6Dp9bXyalBvD04AANA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz", + "integrity": "sha512-evhTyWhbwbI3/U6dZAnx/ePoV7H6OUG+OjiJFHmhr9FPn0VShjwC2kdxqIuQ/+1P50TMrneGzMeyMTFOjKSnAw==", "requires": { - "@babel/helper-module-transforms": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.0.tgz", - "integrity": "sha512-+SicSJoKouPctL+j1pqktRVCgy+xAch1hWWTMy13j0IflnyNjaoskj+DwRQFimHbLqO3sq2oN2CXMvXq3Bgapg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz", + "integrity": "sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.7.0" + "@babel/helper-create-regexp-features-plugin": "^7.8.3" } }, "@babel/plugin-transform-new-target": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", - "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz", + "integrity": "sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-object-super": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", - "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz", + "integrity": "sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.5.5" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3" } }, "@babel/plugin-transform-parameters": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", - "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz", + "integrity": "sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA==", "requires": { - "@babel/helper-call-delegate": "^7.4.4", - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-call-delegate": "^7.8.3", + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-regenerator": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.0.tgz", - "integrity": "sha512-AXmvnC+0wuj/cFkkS/HFHIojxH3ffSXE+ttulrqWjZZRaUOonfJc60e1wSNT4rV8tIunvu/R3wCp71/tLAa9xg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz", + "integrity": "sha512-qt/kcur/FxrQrzFR432FGZznkVAjiyFtCOANjkAKwCbt465L6ZCiUQh2oMYGU3Wo8LRFJxNDFwWn106S5wVUNA==", "requires": { "regenerator-transform": "^0.14.0" } }, "@babel/plugin-transform-runtime": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.6.2.tgz", - "integrity": "sha512-cqULw/QB4yl73cS5Y0TZlQSjDvNkzDbu0FurTZyHlJpWE5T3PCMdnyV+xXoH1opr1ldyHODe3QAX3OMAii5NxA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.8.3.tgz", + "integrity": "sha512-/vqUt5Yh+cgPZXXjmaG9NT8aVfThKk7G4OqkVhrXqwsC5soMn/qTCxs36rZ2QFhpfTJcjw4SNDIZ4RUb8OL4jQ==", "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", "resolve": "^1.8.1", "semver": "^5.5.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", - "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz", + "integrity": "sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-spread": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz", - "integrity": "sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz", + "integrity": "sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", - "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz", + "integrity": "sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-regex": "^7.8.3" } }, "@babel/plugin-transform-template-literals": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", - "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz", + "integrity": "sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ==", "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", - "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz", + "integrity": "sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.0.tgz", - "integrity": "sha512-RrThb0gdrNwFAqEAAx9OWgtx6ICK69x7i9tCnMdVrxQwSDp/Abu9DXFU5Hh16VP33Rmxh04+NGW28NsIkFvFKA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz", + "integrity": "sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/preset-env": { @@ -730,12 +744,19 @@ "invariant": "^2.2.2", "js-levenshtein": "^1.1.3", "semver": "^5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } } }, "@babel/runtime": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.2.tgz", - "integrity": "sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.4.tgz", + "integrity": "sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ==", "requires": { "regenerator-runtime": "^0.13.2" }, @@ -748,9 +769,9 @@ } }, "@babel/runtime-corejs2": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.7.2.tgz", - "integrity": "sha512-GfVnHchOBvIMsweQ13l4jd9lT4brkevnavnVOej5g2y7PpTRY+R4pcQlCjWMZoUla5rMLFzaS/Ll2s59cB1TqQ==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.8.4.tgz", + "integrity": "sha512-7jU2FgNqNHX6yTuU/Dr/vH5/O8eVL9U85MG5aDw1LzGfCvvhXC1shdXfVzCQDsoY967yrAKeLujRv7l8BU+dZA==", "requires": { "core-js": "^2.6.5", "regenerator-runtime": "^0.13.2" @@ -764,26 +785,26 @@ } }, "@babel/template": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.0.tgz", - "integrity": "sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" } }, "@babel/traverse": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.2.tgz", - "integrity": "sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", + "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.7.2", - "@babel/helper-function-name": "^7.7.0", - "@babel/helper-split-export-declaration": "^7.7.0", - "@babel/parser": "^7.7.2", - "@babel/types": "^7.7.2", + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.4", + "@babel/types": "^7.8.3", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" @@ -805,9 +826,9 @@ } }, "@babel/types": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.2.tgz", - "integrity": "sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", "requires": { "esutils": "^2.0.2", "lodash": "^4.17.13", @@ -822,10 +843,11 @@ } }, "@cosmos-ui/vue": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/@cosmos-ui/vue/-/vue-0.5.16.tgz", - "integrity": "sha512-Z4byEoZLkIbumm3SlnrzwuyvDi6vzWv2GfT36QuaPFWusCShGgc47ehXp2S55tKrNajOIiF9bfgasHRL6mfHFA==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/@cosmos-ui/vue/-/vue-0.5.21.tgz", + "integrity": "sha512-Y60AMxFKgHrgE/EHxnGKaTcYUN1nJa5m3SylhsCe/d0AvzF9RSYGSPwVgDxmW4KiufBKXkv4PmiNG9WDNWwdxw==", "requires": { + "tiny-cookie": "^2.3.1", "vue": "^2.6.10" } }, @@ -843,6 +865,19 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==" }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "requires": { + "defer-to-connect": "^1.0.1" + } + }, "@types/babel-types": { "version": "7.0.7", "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.7.tgz", @@ -856,6 +891,11 @@ "@types/babel-types": "*" } }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + }, "@types/events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", @@ -877,9 +917,9 @@ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" }, "@types/node": { - "version": "12.12.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.11.tgz", - "integrity": "sha512-O+x6uIpa6oMNTkPuHDa9MhMMehlxLAd5QcOvKRjAFsBVpeFWTOPnXbDvILvFgFFZfQ1xh1EZi1FbXxUix+zpsQ==" + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.7.0.tgz", + "integrity": "sha512-GnZbirvmqZUzMgkFn70c74OQpTTUcCzlhQliTzYjQMqg+hVKcDnxdL19Ne3UdYzdMA/+W3eb646FWn/ZaT1NfQ==" }, "@types/q": { "version": "1.5.2", @@ -991,26 +1031,21 @@ } }, "@vue/component-compiler-utils": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.0.2.tgz", - "integrity": "sha512-BSnY2PmW4QwU1AOcGSNYAmEPLjdQ9itl1YpLCWtpwMA5Jy/aqWNuzZ9+ZZ8h6yZJ53W95tVkEP6yrXJ/zUHdEA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.1.1.tgz", + "integrity": "sha512-+lN3nsfJJDGMNz7fCpcoYIORrXo0K3OTsdr8jCM7FuqdI4+70TY6gxY6viJ2Xi1clqyPg7LpeOWwjF31vSMmUw==", "requires": { "consolidate": "^0.15.1", "hash-sum": "^1.0.2", "lru-cache": "^4.1.2", "merge-source-map": "^1.1.0", "postcss": "^7.0.14", - "postcss-selector-parser": "^5.0.0", + "postcss-selector-parser": "^6.0.2", "prettier": "^1.18.2", "source-map": "~0.6.1", "vue-template-es2015-compiler": "^1.9.0" }, "dependencies": { - "cssesc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", - "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==" - }, "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", @@ -1020,16 +1055,6 @@ "yallist": "^2.1.2" } }, - "postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", - "requires": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", @@ -1038,17 +1063,17 @@ } }, "@vuepress/core": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@vuepress/core/-/core-1.2.0.tgz", - "integrity": "sha512-ZIsUkQIF+h4Yk6q4okoRnRwRhcYePu/kNiL0WWPDGycjai8cFqFjLDP/tJjfTKXmn9A62j2ETjSwaiMxCtDkyw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@vuepress/core/-/core-1.3.0.tgz", + "integrity": "sha512-/KaH10ggZeEnwh/i8A02VtGHfuIfTEf/pIPV9BBVjK5M6ToPhF2pkcXlPk5PbCWam2dKm7ZDQddJzev1dY5TNA==", "requires": { "@babel/core": "^7.0.0", "@vue/babel-preset-app": "^3.1.1", - "@vuepress/markdown": "^1.2.0", - "@vuepress/markdown-loader": "^1.2.0", - "@vuepress/plugin-last-updated": "^1.2.0", - "@vuepress/plugin-register-components": "^1.2.0", - "@vuepress/shared-utils": "^1.2.0", + "@vuepress/markdown": "^1.3.0", + "@vuepress/markdown-loader": "^1.3.0", + "@vuepress/plugin-last-updated": "^1.3.0", + "@vuepress/plugin-register-components": "^1.3.0", + "@vuepress/shared-utils": "^1.3.0", "autoprefixer": "^9.5.1", "babel-loader": "^8.0.4", "cache-loader": "^3.0.0", @@ -1075,18 +1100,18 @@ "vuepress-html-webpack-plugin": "^3.2.0", "vuepress-plugin-container": "^2.0.2", "webpack": "^4.8.1", - "webpack-chain": "^4.6.0", + "webpack-chain": "^6.0.0", "webpack-dev-server": "^3.5.1", "webpack-merge": "^4.1.2", "webpackbar": "3.2.0" } }, "@vuepress/markdown": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@vuepress/markdown/-/markdown-1.2.0.tgz", - "integrity": "sha512-RLRQmTu5wJbCO4Qv+J0K53o5Ew7nAGItLwWyzCbIUB6pRsya3kqSCViWQVlKlS53zFTmRHuAC9tJMRdzly3mCA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@vuepress/markdown/-/markdown-1.3.0.tgz", + "integrity": "sha512-h4FCAxcYLSGuoftbumsesqquRuQksb98sygiP/EV1J7z3qVj8r/1YdRRoUoE0Yd9hw0izN52KJRYZC7tlUmBnw==", "requires": { - "@vuepress/shared-utils": "^1.2.0", + "@vuepress/shared-utils": "^1.3.0", "markdown-it": "^8.4.1", "markdown-it-anchor": "^5.0.2", "markdown-it-chain": "^1.3.0", @@ -1115,19 +1140,19 @@ } }, "@vuepress/markdown-loader": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@vuepress/markdown-loader/-/markdown-loader-1.2.0.tgz", - "integrity": "sha512-gOZzoHjfp/W6t+qKBRdbHS/9TwRnNuhY7V+yFzxofNONFHQULofIN/arG+ptYc2SuqJ541jqudNQW+ldHNMC2w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@vuepress/markdown-loader/-/markdown-loader-1.3.0.tgz", + "integrity": "sha512-20J9+wuyCxhwOWfb7aDY0F/+j2oQYaoDE1VbH3zaqI9XesPl42DsEwA1Nw1asEm3yXdh+uC2scBCiNcv94tsHg==", "requires": { - "@vuepress/markdown": "^1.2.0", + "@vuepress/markdown": "^1.3.0", "loader-utils": "^1.1.0", "lru-cache": "^5.1.1" } }, "@vuepress/plugin-active-header-links": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@vuepress/plugin-active-header-links/-/plugin-active-header-links-1.2.0.tgz", - "integrity": "sha512-vdi7l96pElJvEmcx6t9DWJNH25TIurS8acjN3+b7o4NzdaszFn5j6klN6WtI4Z+5BVDrxHP5W1F3Ebw8SZyupA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-active-header-links/-/plugin-active-header-links-1.3.0.tgz", + "integrity": "sha512-C+EhZefAOxN83jVZebRWqFUBUklTsTtWRiDFczxcxqH995ZZumi1UFKj9TurOjrZppUDr4ftfxIqGkj4QSUeWw==", "requires": { "lodash.debounce": "^4.0.8" } @@ -1139,38 +1164,38 @@ "dev": true }, "@vuepress/plugin-last-updated": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@vuepress/plugin-last-updated/-/plugin-last-updated-1.2.0.tgz", - "integrity": "sha512-j4uZb/MXDyG+v9QCG3T/rkiaOhC/ib7NKCt1cjn3GOwvWTDmB5UZm9EBhUpbDNrBgxW+SaHOe3kMVNO8bGOTGw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-last-updated/-/plugin-last-updated-1.3.0.tgz", + "integrity": "sha512-zCg98YiCFzBo7hHh5CE4H7lO13QaexeNXKC8SC7aNopjhg1/+rzFKEWt5frARnYqhMrkhEqcegSuB4xWxNV+zQ==", "requires": { "cross-spawn": "^6.0.5" } }, "@vuepress/plugin-nprogress": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@vuepress/plugin-nprogress/-/plugin-nprogress-1.2.0.tgz", - "integrity": "sha512-0apt3Dp6XVCOkLViX6seKSEJgARihi+pX3/r8j8ndFp9Y+vmgLFZnQnGE5iKNi1ty+A6PZOK0RQcBjwTAU4pAw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-nprogress/-/plugin-nprogress-1.3.0.tgz", + "integrity": "sha512-PuBDAhaYLvwG63LamIc1fMk+s4kUqPuvNYKfZjQlF3LtXjlCMvd6YEQyogfB9cZnFOg1nryeHJwWoAdFvzw29Q==", "requires": { "nprogress": "^0.2.0" } }, "@vuepress/plugin-register-components": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@vuepress/plugin-register-components/-/plugin-register-components-1.2.0.tgz", - "integrity": "sha512-C32b8sbGtDEX8I3SUUKS/w2rThiRFiKxmzNcJD996me7VY/4rgmZ8CxGtb6G9wByVoK0UdG1SOkrgOPdSCm80A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-register-components/-/plugin-register-components-1.3.0.tgz", + "integrity": "sha512-IkBacuTDHSHhI3qWXPQtVWTEAL+wprrbaYrD+g2n9xV3dzMkhHJxbpRpw7eAbvsP85a03rVouwRukZ+YlhYPPQ==", "requires": { - "@vuepress/shared-utils": "^1.2.0" + "@vuepress/shared-utils": "^1.3.0" } }, "@vuepress/plugin-search": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@vuepress/plugin-search/-/plugin-search-1.2.0.tgz", - "integrity": "sha512-QU3JfnMfImDAArbJOVH1q1iCDE5QrT99GLpNGo6KQYZWqY1TWAbgyf8C2hQdaI03co1lkU2Wn/iqzHJ5WHlueg==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-search/-/plugin-search-1.3.0.tgz", + "integrity": "sha512-buoQ6gQ2MLbLQ7Nhg5KJWPzKo7NtvdK/e6Fo1ig/kbOG5HyYKHCyqLjbQ/ZqT+fGbaSeEjH3DaVYTNx55GRX5A==" }, "@vuepress/shared-utils": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@vuepress/shared-utils/-/shared-utils-1.2.0.tgz", - "integrity": "sha512-wo5Ng2/xzsmIYCzvWxgLFlDBp7FkmJp2shAkbSurLNAh1vixhs0+LyDxsk01+m34ktJSp9rTUUsm6khw/Fvo0w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@vuepress/shared-utils/-/shared-utils-1.3.0.tgz", + "integrity": "sha512-n1AFgt8SiMDdc5aIj5yOqS3E6+dAZ+9tPw6qf1mBiqvdZzwaUtlydvXqVkskrwUo18znLrUr55VYwubMOaxFnQ==", "requires": { "chalk": "^2.3.2", "diacritics": "^1.3.0", @@ -1181,23 +1206,16 @@ "hash-sum": "^1.0.2", "semver": "^6.0.0", "upath": "^1.1.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } } }, "@vuepress/theme-default": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@vuepress/theme-default/-/theme-default-1.2.0.tgz", - "integrity": "sha512-mJxAMYQQv4OrGFsArMlONu8RpCzPUVx81dumkyTT4ay5PXAWTj+WDeFQLOT3j0g9QrDJGnHhbiw2aS+R/0WUyQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@vuepress/theme-default/-/theme-default-1.3.0.tgz", + "integrity": "sha512-0KKTIQQAyO3xE9Gn5vdQYWY+B1onzMm2i3Td610FiLsCRqeHsWs/stl6tlP3nV75OUHwBRH/w0ITrIF4kMR7GQ==", "requires": { - "@vuepress/plugin-active-header-links": "^1.2.0", - "@vuepress/plugin-nprogress": "^1.2.0", - "@vuepress/plugin-search": "^1.2.0", + "@vuepress/plugin-active-header-links": "^1.3.0", + "@vuepress/plugin-nprogress": "^1.3.0", + "@vuepress/plugin-search": "^1.3.0", "docsearch.js": "^2.5.2", "lodash": "^4.17.15", "stylus": "^0.54.5", @@ -1414,11 +1432,11 @@ "integrity": "sha1-xdG9SxKQCPEWPyNvhuX66iAm4u8=" }, "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" @@ -1454,6 +1472,31 @@ "reduce": "^1.0.1", "semver": "^5.1.0", "tunnel-agent": "^0.6.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } } }, "align-text": { @@ -1464,6 +1507,16 @@ "kind-of": "^3.0.2", "longest": "^1.0.1", "repeat-string": "^1.5.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "alphanum-sort": { @@ -1471,6 +1524,39 @@ "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=" }, + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "requires": { + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "ansi-colors": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", @@ -1666,16 +1752,16 @@ } }, "autoprefixer": { - "version": "9.7.2", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.2.tgz", - "integrity": "sha512-LCAfcdej1182uVvPOZnytbq61AhnOZ/4JelDaJGDeNwewyU1AMaNthcHsyz1NRjTmd2FkurMckLWfkHg3Z//KA==", + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.4.tgz", + "integrity": "sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g==", "requires": { - "browserslist": "^4.7.3", - "caniuse-lite": "^1.0.30001010", + "browserslist": "^4.8.3", + "caniuse-lite": "^1.0.30001020", "chalk": "^2.4.2", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", - "postcss": "^7.0.23", + "postcss": "^7.0.26", "postcss-value-parser": "^4.0.2" } }, @@ -1685,17 +1771,16 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" }, "axios": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz", - "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", + "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", "requires": { - "follow-redirects": "1.5.10", - "is-buffer": "^2.0.2" + "follow-redirects": "1.5.10" } }, "babel-loader": { @@ -1707,21 +1792,6 @@ "loader-utils": "^1.0.2", "mkdirp": "^0.5.1", "pify": "^4.0.1" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } - } } }, "babel-plugin-dynamic-import-node": { @@ -1821,11 +1891,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, @@ -1857,10 +1922,19 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "bluebird": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", - "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==" + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "bn.js": { "version": "4.11.8", @@ -1889,10 +1963,13 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } } } }, @@ -1914,6 +1991,105 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, + "boxen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1938,16 +2114,6 @@ "snapdragon-node": "^2.0.1", "split-string": "^3.0.2", "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } } }, "brorand": { @@ -2021,13 +2187,13 @@ } }, "browserslist": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.3.tgz", - "integrity": "sha512-jWvmhqYpx+9EZm/FxcZSbUZyDEvDTLDi3nSAKbzEkyWvtI0mNSmUosey+5awDW1RUlrgXbQb5A6qY1xQH9U6MQ==", + "version": "4.8.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.6.tgz", + "integrity": "sha512-ZHao85gf0eZ0ESxLfCp73GG9O/VTytYDIkIiZDlURppLTI9wErSM/5yAKEq6rcUdxBLjMELmrYUJGg5sxGKMHg==", "requires": { - "caniuse-lite": "^1.0.30001010", - "electron-to-chromium": "^1.3.306", - "node-releases": "^1.1.40" + "caniuse-lite": "^1.0.30001023", + "electron-to-chromium": "^1.3.341", + "node-releases": "^1.1.47" } }, "buffer": { @@ -2038,13 +2204,6 @@ "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - } } }, "buffer-from": { @@ -2078,9 +2237,9 @@ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, "cac": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.5.3.tgz", - "integrity": "sha512-wZfzSWVXuue1H3J7TDNjbzg4KTqPXCmh7F3QIzEYXfnhMCcOUrx99M7rpO2UDVJA9dqv3butGj2nHvCV47CmPg==" + "version": "6.5.6", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.5.6.tgz", + "integrity": "sha512-8jsGLeBiYEVYTDExaj/rDPG4tyra4yjjacIL10TQ+MobPcg9/IST+dkKLu6sOzq0GcIC6fQqX1nkH9HoskQLAw==" }, "cacache": { "version": "12.0.3", @@ -2102,21 +2261,6 @@ "ssri": "^6.0.1", "unique-filename": "^1.1.1", "y18n": "^4.0.0" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } - } } }, "cache-base": { @@ -2146,20 +2290,39 @@ "mkdirp": "^0.5.1", "neo-async": "^2.6.1", "schema-utils": "^1.0.0" + } + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" }, "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", "requires": { - "minimist": "0.0.8" + "pump": "^3.0.0" } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + }, + "normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" } } }, @@ -2215,9 +2378,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001011", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001011.tgz", - "integrity": "sha512-h+Eqyn/YA6o6ZTqpS86PyRmNWOs1r54EBDcd2NTwwfsXQ8re1B38SnB+p2RKF8OUsyEIjeDU8XGec1RGO/wYCg==" + "version": "1.0.30001023", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001023.tgz", + "integrity": "sha512-C5TDMiYG11EOhVOA62W1p3UsJ2z4DsHtMBQtjzp3ZsUglcQn62WOUgW0y795c7A5uZ+GCEIvzkMatLIlAsbNTA==" }, "caseless": { "version": "0.12.0", @@ -2251,6 +2414,26 @@ "is-regex": "^1.0.3" } }, + "cheerio": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.1", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash": "^4.15.0", + "parse5": "^3.0.1" + }, + "dependencies": { + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + } + } + }, "chokidar": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", @@ -2319,13 +2502,18 @@ } }, "clean-css": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", - "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", "requires": { "source-map": "~0.6.0" } }, + "cli-boxes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", + "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==" + }, "clipboard": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz", @@ -2337,6 +2525,11 @@ "tiny-emitter": "^2.0.0" } }, + "clipboard-copy": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/clipboard-copy/-/clipboard-copy-3.1.0.tgz", + "integrity": "sha512-Xsu1NddBXB89IUauda5BIq3Zq73UWkjkaQlPQbLNvNsd5WBMnTWPNKYR6HGaySOxGYZ+BKxP2E9X4ElnI3yiPA==" + }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", @@ -2347,6 +2540,14 @@ "wordwrap": "0.0.2" } }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "^1.0.0" + } + }, "coa": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", @@ -2426,11 +2627,11 @@ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" }, "compressible": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz", - "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "requires": { - "mime-db": ">= 1.40.0 < 2" + "mime-db": ">= 1.43.0 < 2" } }, "compression": { @@ -2447,6 +2648,14 @@ "vary": "~1.1.2" }, "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -2468,6 +2677,71 @@ "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "configstore": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.0.tgz", + "integrity": "sha512-eE/hvMs7qw7DlcB5JPRnthmrITuHMmACUJAp89v6PT6iOqzoLS7HRWhBtuHMlhNHo2AhUSA/3Dh1bKNJHcublQ==", + "requires": { + "dot-prop": "^5.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "dot-prop": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", + "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", + "requires": { + "is-obj": "^2.0.0" + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" + }, + "make-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", + "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", + "requires": { + "semver": "^6.0.0" + } + } } }, "connect-history-api-fallback": { @@ -2476,9 +2750,9 @@ "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" }, "consola": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.11.0.tgz", - "integrity": "sha512-2bcAqHastlPSCvZ+ur8bgHInGAWvUnysWz3h3xRX+/XZoCY7avolJJnVXOPGoVoyCcg1b231XixonoArmgxaoA==" + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.11.3.tgz", + "integrity": "sha512-aoW0YIIAmeftGR8GSpw6CGQluNdkWMWh3yEFjH/hmynTYnMtibXszii3lxCXmk8YxJtI3FAK5aTiquA5VH68Gw==" }, "console-browserify": { "version": "1.2.0", @@ -2565,21 +2839,6 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.0" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } - } } }, "copy-descriptor": { @@ -2588,9 +2847,9 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, "copy-webpack-plugin": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.0.5.tgz", - "integrity": "sha512-7N68eIoQTyudAuxkfPT7HzGoQ+TsmArN/I3HFwG+lVE3FNzqvZKIiaxtYh4o3BIznioxUvx9j26+Rtsc9htQUQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz", + "integrity": "sha512-P15M5ZC8dyCjQHWwd4Ia/dm0SgVvZJMYeykVIVYXbGyqO4dWB5oyPHp9i7wjwo5LhtlhKbiBCdS2NvM07Wlybg==", "requires": { "cacache": "^12.0.3", "find-cache-dir": "^2.1.0", @@ -2602,7 +2861,7 @@ "normalize-path": "^3.0.0", "p-limit": "^2.2.1", "schema-utils": "^1.0.0", - "serialize-javascript": "^2.1.0", + "serialize-javascript": "^2.1.2", "webpack-log": "^2.0.0" }, "dependencies": { @@ -2625,9 +2884,9 @@ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" }, "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", "requires": { "p-try": "^2.0.0" } @@ -2650,9 +2909,9 @@ } }, "core-js": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", - "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" }, "core-util-is": { "version": "1.0.2", @@ -2714,6 +2973,13 @@ "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } } }, "crypto-browserify": { @@ -2734,6 +3000,11 @@ "randomfill": "^1.0.3" } }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + }, "css": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", @@ -2798,14 +3069,14 @@ } }, "css-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", - "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", "requires": { - "boolbase": "^1.0.0", - "css-what": "^3.2.1", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" } }, "css-select-base-adapter": { @@ -2828,9 +3099,9 @@ "integrity": "sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY=" }, "css-what": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.2.1.tgz", - "integrity": "sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" }, "cssesc": { "version": "3.0.0", @@ -2935,9 +3206,9 @@ "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=" }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "requires": { "ms": "2.0.0" } @@ -2952,6 +3223,14 @@ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, "deep-equal": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", @@ -2965,6 +3244,11 @@ "regexp.prototype.flags": "^1.2.0" } }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, "deepmerge": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", @@ -2979,6 +3263,11 @@ "ip-regex": "^2.1.0" } }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -3021,11 +3310,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, @@ -3172,18 +3456,18 @@ } }, "dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", "requires": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" + "domelementtype": "^1.3.0", + "entities": "^1.1.1" }, "dependencies": { - "domelementtype": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", - "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==" + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" } } }, @@ -3211,9 +3495,9 @@ } }, "domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", "requires": { "dom-serializer": "0", "domelementtype": "1" @@ -3227,6 +3511,11 @@ "is-obj": "^1.0.0" } }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -3236,6 +3525,35 @@ "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "ecc-jsbn": { @@ -3253,14 +3571,14 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.3.310", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.310.tgz", - "integrity": "sha512-ixvxy46JrDv5c8k1+th66Z+xDZD8zShNs6oh7hgyMpNZUgaoRBisXgFZKAyyhQTAj7oU2Y/uZ0AAsj/TY4N0tA==" + "version": "1.3.344", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.344.tgz", + "integrity": "sha512-tvbx2Wl8WBR+ym3u492D0L6/jH+8NoQXqe46+QhbWH3voVPauGuZYeb1QAXYoOAWuiP2dbSvlBx0kQ1F3hu/Mw==" }, "elliptic": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz", - "integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", + "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", "requires": { "bn.js": "^4.4.0", "brorand": "^1.0.1", @@ -3312,6 +3630,33 @@ "errno": "^0.1.3", "readable-stream": "^2.0.1" } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } } } }, @@ -3351,20 +3696,21 @@ } }, "es-abstract": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", - "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", "requires": { - "es-to-primitive": "^1.2.0", + "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.0", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-inspect": "^1.6.0", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", "object-keys": "^1.1.1", - "string.prototype.trimleft": "^2.1.0", - "string.prototype.trimright": "^2.1.0" + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" } }, "es-to-primitive": { @@ -3435,9 +3781,9 @@ "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==" }, "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", + "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==" }, "eventsource": { "version": "1.0.7", @@ -3484,6 +3830,14 @@ "to-regex": "^3.0.1" }, "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", @@ -3491,14 +3845,6 @@ "requires": { "is-descriptor": "^0.1.0" } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } } } }, @@ -3544,10 +3890,13 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } }, "safe-buffer": { "version": "5.1.2", @@ -3562,22 +3911,11 @@ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } + "is-extendable": "^0.1.0" } }, "extglob": { @@ -3603,14 +3941,6 @@ "is-descriptor": "^1.0.0" } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", @@ -3636,11 +3966,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, @@ -3650,9 +3975,9 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" }, "fast-glob": { "version": "2.2.7", @@ -3668,9 +3993,9 @@ } }, "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "faye-websocket": { "version": "0.10.0", @@ -3702,6 +4027,12 @@ "schema-utils": "^1.0.0" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -3711,16 +4042,6 @@ "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } } }, "finalhandler": { @@ -3735,6 +4056,16 @@ "parseurl": "~1.3.3", "statuses": "~1.5.0", "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } } }, "find-babel-config": { @@ -3778,6 +4109,35 @@ "requires": { "inherits": "^2.0.3", "readable-stream": "^2.3.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "follow-redirects": { @@ -3786,16 +4146,6 @@ "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", "requires": { "debug": "=3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - } } }, "for-in": { @@ -3848,6 +4198,35 @@ "requires": { "inherits": "^2.0.1", "readable-stream": "^2.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "fs-extra": { @@ -3869,6 +4248,35 @@ "iferr": "^0.1.5", "imurmurhash": "^0.1.4", "readable-stream": "1 || 2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "fs.realpath": { @@ -3877,13 +4285,14 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", + "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", "optional": true, "requires": { + "bindings": "^1.5.0", "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" + "node-pre-gyp": "*" }, "dependencies": { "abbrev": { @@ -3925,7 +4334,7 @@ } }, "chownr": { - "version": "1.1.1", + "version": "1.1.3", "bundled": true, "optional": true }, @@ -3950,7 +4359,7 @@ "optional": true }, "debug": { - "version": "4.1.1", + "version": "3.2.6", "bundled": true, "optional": true, "requires": { @@ -3973,11 +4382,11 @@ "optional": true }, "fs-minipass": { - "version": "1.2.5", + "version": "1.2.7", "bundled": true, "optional": true, "requires": { - "minipass": "^2.2.1" + "minipass": "^2.6.0" } }, "fs.realpath": { @@ -4001,7 +4410,7 @@ } }, "glob": { - "version": "7.1.3", + "version": "7.1.6", "bundled": true, "optional": true, "requires": { @@ -4027,7 +4436,7 @@ } }, "ignore-walk": { - "version": "3.0.1", + "version": "3.0.3", "bundled": true, "optional": true, "requires": { @@ -4044,7 +4453,7 @@ } }, "inherits": { - "version": "2.0.3", + "version": "2.0.4", "bundled": true, "optional": true }, @@ -4080,7 +4489,7 @@ "optional": true }, "minipass": { - "version": "2.3.5", + "version": "2.9.0", "bundled": true, "optional": true, "requires": { @@ -4089,11 +4498,11 @@ } }, "minizlib": { - "version": "1.2.1", + "version": "1.3.3", "bundled": true, "optional": true, "requires": { - "minipass": "^2.2.1" + "minipass": "^2.9.0" } }, "mkdirp": { @@ -4105,22 +4514,22 @@ } }, "ms": { - "version": "2.1.1", + "version": "2.1.2", "bundled": true, "optional": true }, "needle": { - "version": "2.3.0", + "version": "2.4.0", "bundled": true, "optional": true, "requires": { - "debug": "^4.1.0", + "debug": "^3.2.6", "iconv-lite": "^0.4.4", "sax": "^1.2.4" } }, "node-pre-gyp": { - "version": "0.12.0", + "version": "0.14.0", "bundled": true, "optional": true, "requires": { @@ -4133,7 +4542,7 @@ "rc": "^1.2.7", "rimraf": "^2.6.1", "semver": "^5.3.0", - "tar": "^4" + "tar": "^4.4.2" } }, "nopt": { @@ -4146,12 +4555,20 @@ } }, "npm-bundled": { - "version": "1.0.6", + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", "bundled": true, "optional": true }, "npm-packlist": { - "version": "1.4.1", + "version": "1.4.7", "bundled": true, "optional": true, "requires": { @@ -4213,7 +4630,7 @@ "optional": true }, "process-nextick-args": { - "version": "2.0.0", + "version": "2.0.1", "bundled": true, "optional": true }, @@ -4250,7 +4667,7 @@ } }, "rimraf": { - "version": "2.6.3", + "version": "2.7.1", "bundled": true, "optional": true, "requires": { @@ -4273,7 +4690,7 @@ "optional": true }, "semver": { - "version": "5.7.0", + "version": "5.7.1", "bundled": true, "optional": true }, @@ -4319,17 +4736,17 @@ "optional": true }, "tar": { - "version": "4.4.8", + "version": "4.4.13", "bundled": true, "optional": true, "requires": { "chownr": "^1.1.1", "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", "mkdirp": "^0.5.0", "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" + "yallist": "^3.0.3" } }, "util-deprecate": { @@ -4351,7 +4768,7 @@ "optional": true }, "yallist": { - "version": "3.0.3", + "version": "3.1.1", "bundled": true, "optional": true } @@ -4362,6 +4779,16 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "fuse.js": { + "version": "3.4.6", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.4.6.tgz", + "integrity": "sha512-H6aJY4UpLFwxj1+5nAvufom5b2BT2v45P1MkPvdGIK8fWjQx/7o6tTT1+ALV0yawQvbmvCF0ufl2et8eJ7v7Cg==" + }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==" + }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", @@ -4434,6 +4861,14 @@ "process": "^0.11.10" } }, + "global-dirs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", + "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", + "requires": { + "ini": "^1.3.5" + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -4463,6 +4898,24 @@ "delegate": "^3.1.2" } }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, "graceful-fs": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", @@ -4477,13 +4930,6 @@ "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" - }, - "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - } } }, "handle-thing": { @@ -4550,11 +4996,6 @@ "kind-of": "^4.0.0" }, "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", @@ -4565,6 +5006,11 @@ } } }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==" + }, "hash-base": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", @@ -4615,8 +5061,20 @@ "requires": { "mkdirp": "0.3.0", "nopt": "1.0.10" + }, + "dependencies": { + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=" + } } }, + "hotkeys-js": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/hotkeys-js/-/hotkeys-js-3.7.3.tgz", + "integrity": "sha512-CSaeVPAKEEYNexYR35znMJnCqoofk7oqG/AOOqWow1qDT0Yxy+g+Y8Hs/LhGlsZaSJ7973YN6/N41LAr3t30QQ==" + }, "hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", @@ -4626,6 +5084,35 @@ "obuf": "^1.0.0", "readable-stream": "^2.0.1", "wbuf": "^1.1.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "hsl-regex": { @@ -4702,19 +5189,14 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - }, - "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } } } }, + "http-cache-semantics": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", + "integrity": "sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==" + }, "http-deceiver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", @@ -4846,6 +5328,11 @@ "resolve-from": "^3.0.0" } }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + }, "import-local": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", @@ -4884,6 +5371,11 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, "internal-ip": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", @@ -4893,11 +5385,6 @@ "ipaddr.js": "^1.9.0" } }, - "intersection-observer": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.7.0.tgz", - "integrity": "sha512-Id0Fij0HsB/vKWGeBe9PxeY45ttRiBmhFyyt/geBdDHBYNctMRTE3dC1U3ujzz3lap+hVXlEcVaB56kZP/eEUg==" - }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -4937,6 +5424,16 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-arguments": { @@ -4958,14 +5455,29 @@ } }, "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==" + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "requires": { + "ci-info": "^2.0.0" + }, + "dependencies": { + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + } + } }, "is-color-stop": { "version": "1.1.0", @@ -4986,12 +5498,22 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" }, "is-descriptor": { "version": "0.1.6", @@ -5054,12 +5576,43 @@ "is-extglob": "^2.1.1" } }, + "is-installed-globally": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.1.tgz", + "integrity": "sha512-oiEcGoQbGc+3/iijAijrK2qFpkNoNjsHOm/5V5iaeydyrS/hnwaRCEgH5cpW0P3T1lSjV5piB7S5b5lEugNLhg==", + "requires": { + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + }, + "dependencies": { + "is-path-inside": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", + "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==" + } + } + }, + "is-npm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", + "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==" + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-obj": { @@ -5107,11 +5660,11 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" }, "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", "requires": { - "has": "^1.0.1" + "has": "^1.0.3" } }, "is-resolvable": { @@ -5155,10 +5708,15 @@ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + }, "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", @@ -5214,6 +5772,11 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -5275,25 +5838,23 @@ "promise": "^7.0.1" } }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "requires": { + "json-buffer": "3.0.0" + } + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==" }, "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - } - } + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, "last-call-webpack-plugin": { "version": "3.0.0", @@ -5304,6 +5865,14 @@ "webpack-sources": "^1.1.0" } }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "requires": { + "package-json": "^6.3.0" + } + }, "lazy-cache": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", @@ -5364,6 +5933,11 @@ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" }, + "lodash.chunk": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz", + "integrity": "sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw=" + }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -5384,6 +5958,16 @@ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" }, + "lodash.padstart": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", + "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=" + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, "lodash.template": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", @@ -5429,6 +6013,11 @@ "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=" }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -5437,11 +6026,6 @@ "yallist": "^3.0.2" } }, - "lunr": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.8.tgz", - "integrity": "sha512-oxMeX/Y35PNFuZoHp+jUj5OSEmLCaIH4KTFJh7a93cHBoFmpw2IoPs22VIz7vyO2YUnx2Tn9dzIwO2P/4quIRg==" - }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -5449,6 +6033,13 @@ "requires": { "pify": "^4.0.1", "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } } }, "mamacro": { @@ -5505,6 +6096,17 @@ "integrity": "sha512-XClV8I1TKy8L2qsT9iX3qiV+50ZtcInGXI80CA+DP62sMs7hXlyV/RM3hfwy5O3Ad0sJm9xIwQELgANfESo8mQ==", "requires": { "webpack-chain": "^4.9.0" + }, + "dependencies": { + "webpack-chain": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-4.12.1.tgz", + "integrity": "sha512-BCfKo2YkDe2ByqkEWe1Rw+zko4LsyS75LVr29C6xIrxAg9JHJ4pl8kaIZ396SUSNp6b4815dRZPSTAS8LlURRQ==", + "requires": { + "deepmerge": "^1.5.2", + "javascript-stringify": "^1.6.0" + } + } } }, "markdown-it-container": { @@ -5517,11 +6119,6 @@ "resolved": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-1.4.0.tgz", "integrity": "sha1-m+4OmpkKljupbfaYDE/dsF37Tcw=" }, - "markdown-it-ins": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/markdown-it-ins/-/markdown-it-ins-3.0.0.tgz", - "integrity": "sha512-+vyAdBuMGwmT2yMlAFJSx2VR/0QZ1onQ/Mkkmr4l9tDFOh5sVoAgRbkgbuSsk+sxJ9vaMH/IQ323ydfvQrPO/Q==" - }, "markdown-it-table-of-contents": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.4.4.tgz", @@ -5569,6 +6166,35 @@ "requires": { "errno": "^0.1.3", "readable-stream": "^2.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "merge-descriptors": { @@ -5614,10 +6240,22 @@ "to-regex": "^3.0.2" }, "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } } } }, @@ -5636,16 +6274,16 @@ "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==" }, "mime-db": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", - "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==" + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" }, "mime-types": { - "version": "2.1.25", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", - "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", "requires": { - "mime-db": "1.42.0" + "mime-db": "1.43.0" } }, "mimic-fn": { @@ -5653,6 +6291,11 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, "min-document": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", @@ -5732,9 +6375,19 @@ } }, "mkdirp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=" + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } + } }, "move-concurrently": { "version": "1.0.1", @@ -5747,21 +6400,6 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.3" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } - } } }, "ms": { @@ -5807,10 +6445,22 @@ "to-regex": "^3.0.1" }, "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } } } }, @@ -5872,31 +6522,48 @@ "vm-browserify": "^1.0.1" }, "dependencies": { - "events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", - "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==" - }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, "node-releases": { - "version": "1.1.41", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.41.tgz", - "integrity": "sha512-+IctMa7wIs8Cfsa8iYzeaLTFwv5Y4r5jZud+4AnfymzeEXKBCavFX0KBgzVaPVqf0ywa6PrO8/b+bPqdwjGBSg==", + "version": "1.1.47", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.47.tgz", + "integrity": "sha512-k4xjVPx5FpwBUj0Gw7uvFOTF4Ep8Hok1I6qjwL3pLfwe7Y0REQSAqOwwv9TWBCUtMHxcXfY4PgRLRozcChvTcA==", "requires": { "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } } }, "nopt": { @@ -5985,6 +6652,14 @@ "requires": { "is-descriptor": "^0.1.0" } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5994,9 +6669,9 @@ "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" }, "object-is": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", - "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz", + "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==" }, "object-keys": { "version": "1.1.1", @@ -6023,12 +6698,12 @@ } }, "object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" } }, "object.pick": { @@ -6040,12 +6715,12 @@ } }, "object.values": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", - "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", + "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" } @@ -6121,6 +6796,11 @@ "mem": "^4.0.0" } }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" + }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", @@ -6170,10 +6850,21 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + } + }, "pako": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", - "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==" + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "parallel-transform": { "version": "1.2.0", @@ -6183,6 +6874,35 @@ "cyclist": "^1.0.1", "inherits": "^2.0.3", "readable-stream": "^2.1.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "param-case": { @@ -6215,6 +6935,14 @@ "json-parse-better-errors": "^1.0.1" } }, + "parse5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "requires": { + "@types/node": "*" + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -6341,9 +7069,9 @@ } }, "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", "requires": { "p-try": "^2.0.0" } @@ -6389,19 +7117,6 @@ "ms": "^2.1.1" } }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -6415,9 +7130,9 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "postcss": { - "version": "7.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.23.tgz", - "integrity": "sha512-hOlMf3ouRIFXD+j2VJecwssTwbvsPGJVMzupptg+85WA+i7MwyrydmQAgY3R+m0Bc0exunhbJmijy8u8+vufuQ==", + "version": "7.0.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.26.tgz", + "integrity": "sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -6700,9 +7415,9 @@ } }, "postcss-modules-scope": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz", - "integrity": "sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.1.tgz", + "integrity": "sha512-OXRUPecnHCg8b9xWvldG/jUpRIGPNRka0r4D4j0ESUU2/5IOnpsjfPPmDprM3Ih8CgZ8FXjWqaniK5v4rWt3oQ==", "requires": { "postcss": "^7.0.6", "postcss-selector-parser": "^6.0.0" @@ -6990,9 +7705,9 @@ "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==" }, "prismjs": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.17.1.tgz", - "integrity": "sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.19.0.tgz", + "integrity": "sha512-IVFtbW9mCWm9eOIaEkNyo2Vl4NnEifis2GQ7/MLRG5TQe6t+4Sj9J5QWI9i3v+SS43uZBlCAOn+zYTVYQcPXJw==", "requires": { "clipboard": "^2.0.0" } @@ -7045,9 +7760,9 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "psl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", - "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==" + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", + "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==" }, "public-encrypt": { "version": "4.0.3", @@ -7225,9 +7940,9 @@ "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" }, "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, "query-string": { "version": "5.1.1", @@ -7294,30 +8009,25 @@ } } }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.5.0.tgz", + "integrity": "sha512-gSz026xs2LfxBPudDuI41V1lka8cxg64E66SGe78zJlsUofOg/yqwezdIcdfwik6B4h8LFmWPA9ef9X3FiNFLA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, "readdirp": { @@ -7328,6 +8038,35 @@ "graceful-fs": "^4.1.11", "micromatch": "^3.1.10", "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "reduce": { @@ -7371,14 +8110,34 @@ "requires": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } } }, "regexp.prototype.flags": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", - "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", "requires": { - "define-properties": "^1.1.2" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" } }, "regexpu-core": { @@ -7394,15 +8153,31 @@ "unicode-match-property-value-ecmascript": "^1.1.0" } }, + "registry-auth-token": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz", + "integrity": "sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==", + "requires": { + "rc": "^1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "requires": { + "rc": "^1.2.8" + } + }, "regjsgen": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==" }, "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.2.tgz", + "integrity": "sha512-E9ghzUtoLwDekPT0DYCp+c4h+bvuUpe6rRHCTYn6eGoqj1LgKXxT6I0Il4WbjhQkOghzi/V+y03bPKvbllL93Q==", "requires": { "jsesc": "~0.5.0" }, @@ -7434,33 +8209,6 @@ "htmlparser2": "^3.3.0", "strip-ansi": "^3.0.0", "utila": "^0.4.0" - }, - "dependencies": { - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - } } }, "repeat-element": { @@ -7498,6 +8246,13 @@ "tough-cookie": "~2.4.3", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + } } }, "require-directory": { @@ -7521,9 +8276,9 @@ "integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc=" }, "resolve": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.2.tgz", - "integrity": "sha512-cAVTI2VLHWYsGOirfeYVVQ7ZDejtQ9fp4YhYckWDEkFfqbVjaT11iM8k6xSAfGFMM+gDpZjMnFssPu8we+mqFw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", + "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", "requires": { "path-parse": "^1.0.6" } @@ -7546,6 +8301,14 @@ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "requires": { + "lowercase-keys": "^1.0.0" + } + }, "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", @@ -7639,21 +8402,6 @@ "requires": { "extend-shallow": "^2.0.1", "kind-of": "^6.0.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - } } }, "select": { @@ -7676,9 +8424,17 @@ } }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "requires": { + "semver": "^6.3.0" + } }, "send": { "version": "0.17.1", @@ -7700,6 +8456,21 @@ "statuses": "~1.5.0" }, "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -7713,9 +8484,9 @@ } }, "serialize-javascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.0.tgz", - "integrity": "sha512-a/mxFfU00QT88umAJQsNWOnUKckhNCqOl028N48e7wFmo2/EHpTo9Wso+iJJCMrQnmFvcjto5RJdAHEvVhcyUQ==" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==" }, "serve-index": { "version": "1.9.1", @@ -7731,6 +8502,14 @@ "parseurl": "~1.3.2" }, "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, "http-errors": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", @@ -7779,16 +8558,6 @@ "is-extendable": "^0.1.1", "is-plain-object": "^2.0.3", "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } } }, "setimmediate": { @@ -7843,6 +8612,17 @@ } } }, + "sitemap": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-3.2.2.tgz", + "integrity": "sha512-TModL/WU4m2q/mQcrDgNANn0P4LwprM9MMvG4hu5zP4c6IIKs2YLTu6nXXnNr8ODW/WFtxKggiJ1EGn2W0GNmg==", + "requires": { + "lodash.chunk": "^4.2.0", + "lodash.padstart": "^4.6.1", + "whatwg-url": "^7.0.0", + "xmlbuilder": "^13.0.0" + } + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -7868,6 +8648,14 @@ "use": "^3.1.0" }, "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", @@ -7876,14 +8664,6 @@ "is-descriptor": "^0.1.0" } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -7934,11 +8714,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, @@ -7948,6 +8723,16 @@ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "requires": { "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "sockjs": { @@ -8014,11 +8799,11 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", "requires": { - "atob": "^2.1.1", + "atob": "^2.1.2", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", "source-map-url": "^0.4.0", @@ -8091,16 +8876,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } } } }, @@ -8110,6 +8885,25 @@ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "requires": { "extend-shallow": "^3.0.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } } }, "sprintf-js": { @@ -8190,6 +8984,35 @@ "requires": { "inherits": "~2.0.1", "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "stream-each": { @@ -8211,12 +9034,41 @@ "readable-stream": "^2.3.6", "to-arraybuffer": "^1.0.0", "xtend": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" }, "strict-uri-encode": { "version": "1.1.0", @@ -8248,36 +9100,29 @@ } }, "string.prototype.trimleft": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", - "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", "requires": { "define-properties": "^1.1.3", "function-bind": "^1.1.1" } }, "string.prototype.trimright": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", - "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", "requires": { "define-properties": "^1.1.3", "function-bind": "^1.1.1" } }, "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } + "safe-buffer": "~5.2.0" } }, "strip-ansi": { @@ -8298,6 +9143,11 @@ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, "stylehacks": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", @@ -8335,32 +9185,6 @@ "source-map": "^0.7.3" }, "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, "source-map": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", @@ -8411,17 +9235,29 @@ "util.promisify": "~1.0.0" }, "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", "requires": { - "minimist": "0.0.8" + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-what": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.2.1.tgz", + "integrity": "sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw==" + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" } } } @@ -8431,10 +9267,15 @@ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" }, + "term-size": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz", + "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==" + }, "terser": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.4.0.tgz", - "integrity": "sha512-oDG16n2WKm27JO8h4y/w3iqBGAOSCtq7k8dRmrn4Wf9NouL0b2WpMHGChFGZq4nFAQy1FsNJrVQHfurXOSTmOA==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.3.tgz", + "integrity": "sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==", "requires": { "commander": "^2.20.0", "source-map": "~0.6.1", @@ -8449,26 +9290,19 @@ } }, "terser-webpack-plugin": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz", - "integrity": "sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz", + "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==", "requires": { "cacache": "^12.0.2", "find-cache-dir": "^2.1.0", "is-wsl": "^1.1.0", "schema-utils": "^1.0.0", - "serialize-javascript": "^1.7.0", + "serialize-javascript": "^2.1.2", "source-map": "^0.6.1", "terser": "^4.1.2", "webpack-sources": "^1.4.0", "worker-farm": "^1.7.0" - }, - "dependencies": { - "serialize-javascript": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", - "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==" - } } }, "text-table": { @@ -8488,6 +9322,35 @@ "requires": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "thunky": { @@ -8508,39 +9371,17 @@ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" }, + "tiny-cookie": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tiny-cookie/-/tiny-cookie-2.3.1.tgz", + "integrity": "sha512-C4x1e8dHfKf03ewuN9aIZzzOfN2a6QKhYlnHdzJxmmjMTLqcskI20F+EplszjODQ4SHmIGFJrvUUnBMS/bJbOA==" + }, "tiny-emitter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", "optional": true }, - "tm-tooltip": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/tm-tooltip/-/tm-tooltip-0.0.10.tgz", - "integrity": "sha512-ud+LicFlyhwLwO/nfGvtASg3TyUCjaEQC5GCZaE/JzXQmwK0ndb+4F0/ek8xr07rOENFUIT9N+1tmUDqCAtv1g==", - "requires": { - "markdown-it": "^9.1.0" - }, - "dependencies": { - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - }, - "markdown-it": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-9.1.0.tgz", - "integrity": "sha512-xHKG4C8iPriyfu/jc2hsCC045fKrMQ0VexX2F1FGYiRxDxqMB2aAhF8WauJ3fltn2kb90moGBkiiEdooGIg55w==", - "requires": { - "argparse": "^1.0.7", - "entities": "~1.1.1", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - } - } - } - }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", @@ -8562,8 +9403,23 @@ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" + }, "to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", @@ -8573,6 +9429,25 @@ "extend-shallow": "^3.0.2", "regex-not": "^1.0.2", "safe-regex": "^1.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } } }, "to-regex-range": { @@ -8620,6 +9495,14 @@ } } }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "requires": { + "punycode": "^2.1.0" + } + }, "tslib": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", @@ -8662,6 +9545,14 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, "uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", @@ -8751,6 +9642,14 @@ "imurmurhash": "^0.1.4" } }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "requires": { + "crypto-random-string": "^2.0.0" + } + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -8799,11 +9698,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" } } }, @@ -8812,6 +9706,71 @@ "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" }, + "update-notifier": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.0.0.tgz", + "integrity": "sha512-p9zf71hWt5GVXM4iEBujpUgx8mK9AWiCCapEJm/O1z5ntCim83Z1ATqzZFBHFYqx03laMqv8LiDgs/7ikXjf/g==", + "requires": { + "boxen": "^4.2.0", + "chalk": "^3.0.0", + "configstore": "^5.0.0", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.1", + "is-npm": "^4.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "upper-case": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", @@ -8865,6 +9824,14 @@ "requires-port": "^1.0.0" } }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "requires": { + "prepend-http": "^2.0.0" + } + }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -8891,12 +9858,14 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "util.promisify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", "requires": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" } }, "utila": { @@ -8910,9 +9879,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, "v-runtime-template": { "version": "1.10.0", @@ -8925,9 +9894,9 @@ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, "vendors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.3.tgz", - "integrity": "sha512-fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==" }, "verror": { "version": "1.10.0", @@ -8950,9 +9919,9 @@ "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" }, "vue": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.10.tgz", - "integrity": "sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==" + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.11.tgz", + "integrity": "sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ==" }, "vue-hot-reload-api": { "version": "2.3.4", @@ -8960,11 +9929,11 @@ "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==" }, "vue-loader": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.7.2.tgz", - "integrity": "sha512-H/P9xt/nkocyu4hZKg5TzPqyCT1oKOaCSk9zs0JCbJuy0Q8KtR0bjJpnT/5R5x/Ckd1GFkkLQnQ1C4x6xXeLZg==", + "version": "15.8.3", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.8.3.tgz", + "integrity": "sha512-yFksTFbhp+lxlm92DrKdpVIWMpranXnTEuGSc0oW+Gk43M9LWaAmBTnfj5+FCdve715mTHvo78IdaXf5TbiTJg==", "requires": { - "@vue/component-compiler-utils": "^3.0.0", + "@vue/component-compiler-utils": "^3.1.0", "hash-sum": "^1.0.2", "loader-utils": "^1.1.0", "vue-hot-reload-api": "^2.3.0", @@ -8972,22 +9941,22 @@ } }, "vue-router": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.1.3.tgz", - "integrity": "sha512-8iSa4mGNXBjyuSZFCCO4fiKfvzqk+mhL0lnKuGcQtO1eoj8nq3CmbEG8FwK5QqoqwDgsjsf1GDuisDX4cdb/aQ==" + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.1.5.tgz", + "integrity": "sha512-BszkPvhl7I9h334GjckCh7sVFyjTPMMJFJ4Bsrem/Ik+B/9gt5tgrk8k4gGLO4ZpdvciVdg7O41gW4DisQWurg==" }, "vue-server-renderer": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/vue-server-renderer/-/vue-server-renderer-2.6.10.tgz", - "integrity": "sha512-UYoCEutBpKzL2fKCwx8zlRtRtwxbPZXKTqbl2iIF4yRZUNO/ovrHyDAJDljft0kd+K0tZhN53XRHkgvCZoIhug==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/vue-server-renderer/-/vue-server-renderer-2.6.11.tgz", + "integrity": "sha512-V3faFJHr2KYfdSIalL+JjinZSHYUhlrvJ9pzCIjjwSh77+pkrsXpK4PucdPcng57+N77pd1LrKqwbqjQdktU1A==", "requires": { "chalk": "^1.1.3", "hash-sum": "^1.0.2", "he": "^1.1.0", - "lodash.template": "^4.4.0", + "lodash.template": "^4.5.0", "lodash.uniq": "^4.5.0", "resolve": "^1.2.0", - "serialize-javascript": "^1.3.0", + "serialize-javascript": "^2.1.2", "source-map": "0.5.6" }, "dependencies": { @@ -9008,11 +9977,6 @@ "supports-color": "^2.0.0" } }, - "serialize-javascript": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", - "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==" - }, "source-map": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", @@ -9035,9 +9999,9 @@ } }, "vue-template-compiler": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.10.tgz", - "integrity": "sha512-jVZkw4/I/HT5ZMvRnhv78okGusqe0+qH2A0Em0Cp8aq78+NK9TII263CDVz2QXZsIT+yyV/gZc/j/vlwa+Epyg==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz", + "integrity": "sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA==", "requires": { "de-indent": "^1.0.2", "he": "^1.1.0" @@ -9049,15 +10013,16 @@ "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==" }, "vuepress": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vuepress/-/vuepress-1.2.0.tgz", - "integrity": "sha512-EfHo8Cc73qo+1Pm18hM0qOGynmDr8q5fu2664obynsdCJ1zpvoShVnA0Msraw4SI2xDc0iAoIb3dTwxUIM8DAw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/vuepress/-/vuepress-1.3.0.tgz", + "integrity": "sha512-TmPmHiT70aq4xqy4XczUJmUdpGlMSheOGGVwA2nhYSIS9IEd4ngPbfT9oEcAFTsGHXsr5KH8EgEU7G+3wWzY/A==", "requires": { - "@vuepress/core": "^1.2.0", - "@vuepress/theme-default": "^1.2.0", - "cac": "^6.3.9", + "@vuepress/core": "^1.3.0", + "@vuepress/theme-default": "^1.3.0", + "cac": "^6.5.5", "envinfo": "^7.2.0", - "opencollective-postinstall": "^2.0.2" + "opencollective-postinstall": "^2.0.2", + "update-notifier": "^4.0.0" } }, "vuepress-html-webpack-plugin": { @@ -9094,17 +10059,34 @@ "json5": "^0.5.0", "object-assign": "^4.0.1" } + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } } } }, "vuepress-plugin-container": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/vuepress-plugin-container/-/vuepress-plugin-container-2.1.1.tgz", - "integrity": "sha512-1hKZZ9DzVvgNZiSZfiTGiAzbq9bYww64kFz5yv3BRLKdEYX7rSIxKW6lFrbyaTCPQkT1qWgr95sM+GVetpcQFw==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/vuepress-plugin-container/-/vuepress-plugin-container-2.1.2.tgz", + "integrity": "sha512-Df5KoIDMYiFg45GTfFw2hIiLGSsjhms4f3ppl2UIBf5nWMxi2lfifcoo8MooMSfxboxRZjoDccqQfu0fypaKrQ==", "requires": { "markdown-it-container": "^2.0.0" } }, + "vuepress-plugin-sitemap": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/vuepress-plugin-sitemap/-/vuepress-plugin-sitemap-2.3.1.tgz", + "integrity": "sha512-n+8lbukhrKrsI9H/EX0EBgkE1pn85LAQFvQ5dIvrZP4Kz6JxPOPPNTQmZMhahQV1tXbLZQCEN7A1WZH4x+arJQ==", + "requires": { + "sitemap": "^3.0.0" + } + }, "vuepress-plugin-smooth-scroll": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/vuepress-plugin-smooth-scroll/-/vuepress-plugin-smooth-scroll-0.0.3.tgz", @@ -9114,29 +10096,28 @@ } }, "vuepress-theme-cosmos": { - "version": "1.0.73", - "resolved": "https://registry.npmjs.org/vuepress-theme-cosmos/-/vuepress-theme-cosmos-1.0.73.tgz", - "integrity": "sha512-WXuld8UBxRG89WpKtmfjOdilARxF6jgcpYdwy7nWe6kv3PA1MNT0S7hDL9nztCwRk/6GAs6rtkhKyAn5WGfvxQ==", + "version": "1.0.148", + "resolved": "https://registry.npmjs.org/vuepress-theme-cosmos/-/vuepress-theme-cosmos-1.0.148.tgz", + "integrity": "sha512-IVzX339e9k25YNC62UZPfkLg50IGCctvlI/TQF6s63eCdh+ayHOPLTFq5zAiYTpP09Dbz4tSC74cQyO3fUyPOQ==", "requires": { - "@cosmos-ui/vue": "^0.5.16", - "@vuepress/plugin-last-updated": "^1.2.0", - "@vuepress/plugin-search": "^1.1.0", - "algoliasearch": "^3.35.1", + "@cosmos-ui/vue": "^0.5.20", "axios": "^0.19.0", - "docsearch.js": "^2.6.3", - "intersection-observer": "^0.7.0", - "lunr": "^2.3.8", + "cheerio": "^1.0.0-rc.3", + "clipboard-copy": "^3.1.0", + "entities": "^2.0.0", + "fuse.js": "^3.4.6", + "gray-matter": "^4.0.2", + "hotkeys-js": "^3.7.3", "markdown-it": "^10.0.0", "markdown-it-attrs": "^3.0.1", - "markdown-it-ins": "^3.0.0", "prismjs": "^1.17.1", "pug": "^2.0.4", "pug-plain-loader": "^1.0.0", "stylus": "^0.54.7", "stylus-loader": "^3.0.2", - "tm-tooltip": "0.0.10", "v-runtime-template": "^1.10.0", - "vuepress": "^1.2.0" + "vuepress": "^1.2.0", + "vuepress-plugin-sitemap": "^2.3.1" } }, "watchpack": { @@ -9157,10 +10138,15 @@ "minimalistic-assert": "^1.0.0" } }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, "webpack": { - "version": "4.41.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.2.tgz", - "integrity": "sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A==", + "version": "4.41.5", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.5.tgz", + "integrity": "sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw==", "requires": { "@webassemblyjs/ast": "1.8.5", "@webassemblyjs/helper-module-context": "1.8.5", @@ -9182,38 +10168,32 @@ "node-libs-browser": "^2.2.1", "schema-utils": "^1.0.0", "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.1", + "terser-webpack-plugin": "^1.4.3", "watchpack": "^1.6.0", "webpack-sources": "^1.4.1" }, "dependencies": { "acorn": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", - "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==" - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==" } } }, "webpack-chain": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-4.12.1.tgz", - "integrity": "sha512-BCfKo2YkDe2ByqkEWe1Rw+zko4LsyS75LVr29C6xIrxAg9JHJ4pl8kaIZ396SUSNp6b4815dRZPSTAS8LlURRQ==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.3.1.tgz", + "integrity": "sha512-PLWPY92p5Vj0hOylUGjRoRY7Kgrns5vmPFAQ9BpSHnBbVbh2akRQVUlbRb2mmGYRSY1FklTULtyVChNmcQjIVg==", "requires": { "deepmerge": "^1.5.2", - "javascript-stringify": "^1.6.0" + "javascript-stringify": "^2.0.1" + }, + "dependencies": { + "javascript-stringify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.0.1.tgz", + "integrity": "sha512-yV+gqbd5vaOYjqlbk16EG89xB5udgjqQF3C5FAORDg4f/IS1Yc5ERCv5e/57yBcfJYw05V5JyIXabhwb75Xxow==" + } } }, "webpack-dev-middleware": { @@ -9226,27 +10206,12 @@ "mkdirp": "^0.5.1", "range-parser": "^1.2.1", "webpack-log": "^2.0.0" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } - } } }, "webpack-dev-server": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.9.0.tgz", - "integrity": "sha512-E6uQ4kRrTX9URN9s/lIbqTAztwEPdvzVrcmHE8EQ9YnuT9J8Es5Wrd8n9BKg1a0oZ5EgEke/EQFgUsp18dSTBw==", + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.10.2.tgz", + "integrity": "sha512-pxZKPYb+n77UN8u9YxXT4IaIrGcNtijh/mi8TXbErHmczw0DtPnMTTjHj+eNjkqLOaAZM/qD7V59j/qJsEiaZA==", "requires": { "ansi-html": "0.0.7", "bonjour": "^3.5.0", @@ -9263,7 +10228,7 @@ "ip": "^1.1.5", "is-absolute-url": "^3.0.3", "killable": "^1.0.1", - "loglevel": "^1.6.4", + "loglevel": "^1.6.6", "opn": "^5.5.0", "p-retry": "^3.0.1", "portfinder": "^1.0.25", @@ -9344,9 +10309,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", "requires": { "p-try": "^2.0.0" } @@ -9364,11 +10329,6 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, "supports-color": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", @@ -9489,6 +10449,16 @@ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "when": { "version": "3.6.4", "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz", @@ -9507,6 +10477,49 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "requires": { + "string-width": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", @@ -9568,6 +10581,17 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "write-file-atomic": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.1.tgz", + "integrity": "sha512-JPStrIyyVJ6oCSz/691fAjFtefZ6q+fP6tm+OS4Qw6o+TGQxNp1ziY2PgS+X/m0V8OWhZiO/m4xSj+Pr4RrZvw==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, "ws": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", @@ -9576,6 +10600,16 @@ "async-limiter": "~1.0.0" } }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" + }, + "xmlbuilder": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", + "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==" + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/docs/package.json b/docs/package.json index 15a4f5482..962531efd 100644 --- a/docs/package.json +++ b/docs/package.json @@ -4,7 +4,7 @@ "description": "Welcome to the Tendermint Core documentation!", "main": "index.js", "dependencies": { - "vuepress-theme-cosmos": "^1.0.135" + "vuepress-theme-cosmos": "^1.0.148" }, "devDependencies": { "@vuepress/plugin-google-analytics": "^1.2.0" From 1edb542f99941153a4e9558abd7f3b8e46710d52 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 3 Feb 2020 13:59:16 +0100 Subject: [PATCH 24/45] lite2: make witnesses mandatory (#4358) * lite2: make witnesses mandatory at least one witness is required * lite2: return an error if there are no witnesses https://github.com/tendermint/tendermint/pull/4358#pullrequestreview-350635444 * cmd/lite: add witnesses flag * fix linter errors --- cmd/tendermint/commands/lite.go | 46 ++++- lite2/client.go | 53 +++--- lite2/client_test.go | 312 ++++++++++++++++++-------------- lite2/example_test.go | 15 +- 4 files changed, 252 insertions(+), 174 deletions(-) diff --git a/cmd/tendermint/commands/lite.go b/cmd/tendermint/commands/lite.go index 52d253d77..f27c34cf1 100644 --- a/cmd/tendermint/commands/lite.go +++ b/cmd/tendermint/commands/lite.go @@ -2,6 +2,7 @@ package commands import ( "net/http" + "strings" "time" "github.com/pkg/errors" @@ -12,6 +13,7 @@ import ( tmos "github.com/tendermint/tendermint/libs/os" lite "github.com/tendermint/tendermint/lite2" + "github.com/tendermint/tendermint/lite2/provider" httpp "github.com/tendermint/tendermint/lite2/provider/http" lproxy "github.com/tendermint/tendermint/lite2/proxy" lrpc "github.com/tendermint/tendermint/lite2/rpc" @@ -36,9 +38,10 @@ just with added trust and running locally.`, var ( listenAddr string - nodeAddr string + primaryAddr string chainID string home string + witnessesAddrs string maxOpenConnections int trustingPeriod time.Duration @@ -47,9 +50,17 @@ var ( ) func init() { - LiteCmd.Flags().StringVar(&listenAddr, "laddr", "tcp://localhost:8888", "Serve the proxy on the given address") - LiteCmd.Flags().StringVar(&nodeAddr, "node", "tcp://localhost:26657", "Connect to a Tendermint node at this address") + LiteCmd.Flags().StringVar(&listenAddr, "laddr", "tcp://localhost:8888", + "Serve the proxy on the given address") + + LiteCmd.Flags().StringVar(&primaryAddr, "primary", "tcp://localhost:26657", + "Connect to a Tendermint node at this address") + + LiteCmd.Flags().StringVar(&witnessesAddrs, "witnesses", "", + "Tendermint nodes to cross-check the primary node, comma-separated") + LiteCmd.Flags().StringVar(&chainID, "chain-id", "tendermint", "Specify the Tendermint chain ID") + LiteCmd.Flags().StringVar(&home, "home-dir", ".tendermint-lite", "Specify the home directory") LiteCmd.Flags().IntVar( &maxOpenConnections, @@ -57,19 +68,33 @@ func init() { 900, "Maximum number of simultaneous connections (including WebSocket).") - LiteCmd.Flags().DurationVar(&trustingPeriod, "trusting-period", 168*time.Hour, "Trusting period. Should be significantly less than the unbonding period") + LiteCmd.Flags().DurationVar(&trustingPeriod, "trusting-period", 168*time.Hour, + "Trusting period. Should be significantly less than the unbonding period") + LiteCmd.Flags().Int64Var(&trustedHeight, "trusted-height", 1, "Trusted header's height") + LiteCmd.Flags().BytesHexVar(&trustedHash, "trusted-hash", []byte{}, "Trusted header's hash") } func runProxy(cmd *cobra.Command, args []string) error { liteLogger := logger.With("module", "lite") - logger.Info("Connecting to Tendermint node...") - // First, connect a client - node, err := rpcclient.NewHTTP(nodeAddr, "/websocket") + logger.Info("Connecting to the primary node...") + rpcClient, err := rpcclient.NewHTTP(chainID, primaryAddr) if err != nil { - return errors.Wrap(err, "new HTTP client") + return errors.Wrapf(err, "http client for %s", primaryAddr) + } + primary := httpp.NewWithClient(chainID, rpcClient) + + logger.Info("Connecting to the witness nodes...") + addrs := strings.Split(witnessesAddrs, ",") + witnesses := make([]provider.Provider, len(addrs)) + for i, addr := range addrs { + p, err := httpp.New(chainID, addr) + if err != nil { + return errors.Wrapf(err, "http provider for %s", addr) + } + witnesses[i] = p } logger.Info("Creating client...") @@ -84,7 +109,8 @@ func runProxy(cmd *cobra.Command, args []string) error { Height: trustedHeight, Hash: trustedHash, }, - httpp.NewWithClient(chainID, node), + primary, + witnesses, dbs.New(db, chainID), lite.Logger(liteLogger), ) @@ -96,7 +122,7 @@ func runProxy(cmd *cobra.Command, args []string) error { Addr: listenAddr, Config: &rpcserver.Config{MaxOpenConnections: maxOpenConnections}, Codec: amino.NewCodec(), - Client: lrpc.NewClient(node, c), + Client: lrpc.NewClient(rpcClient, c), Logger: liteLogger, } // Stop upon receiving SIGTERM or CTRL-C. diff --git a/lite2/client.go b/lite2/client.go index 4d49c9cac..4248d5eb8 100644 --- a/lite2/client.go +++ b/lite2/client.go @@ -75,29 +75,12 @@ func SequentialVerification() Option { // applies to non-adjacent headers. For adjacent headers, sequential // verification is used. func SkippingVerification(trustLevel tmmath.Fraction) Option { - if err := ValidateTrustLevel(trustLevel); err != nil { - panic(err) - } return func(c *Client) { c.verificationMode = skipping c.trustLevel = trustLevel } } -// Witnesses option can be used to supply providers, which will be used for -// cross-checking the primary provider. A witness can become a primary iff the -// current primary is unavailable. -func Witnesses(providers []provider.Provider) Option { - return func(c *Client) { - for _, witness := range providers { - if witness.ChainID() != c.ChainID() { - panic("Witness chainID is not equal to the Lite Client chainID") - } - } - c.witnesses = providers - } -} - // UpdatePeriod option can be used to change default polling period (5s). func UpdatePeriod(d time.Duration) Option { return func(c *Client) { @@ -175,11 +158,16 @@ type Client struct { // obtain the header & vals from the primary or they are invalid (e.g. trust // hash does not match with the one from the header). // +// Witnesses are providers, which will be used for cross-checking the primary +// provider. At least one witness must be given. A witness can become a primary +// iff the current primary is unavailable. +// // See all Option(s) for the additional configuration. func NewClient( chainID string, trustOptions TrustOptions, primary provider.Provider, + witnesses []provider.Provider, trustedStore store.Store, options ...Option) (*Client, error) { @@ -189,6 +177,7 @@ func NewClient( verificationMode: skipping, trustLevel: DefaultTrustLevel, primary: primary, + witnesses: witnesses, trustedStore: trustedStore, updatePeriod: defaultUpdatePeriod, removeNoLongerTrustedHeadersPeriod: defaultRemoveNoLongerTrustedHeadersPeriod, @@ -201,6 +190,24 @@ func NewClient( o(c) } + // Validate the number of witnesses. + if len(c.witnesses) < 1 { + return nil, errors.New("expected at least one witness") + } + + // Verify witnesses are all on the same chain. + for i, w := range witnesses { + if w.ChainID() != chainID { + return nil, errors.Errorf("witness #%d: %v is on another chain %s, expected %s", + i, w, w.ChainID(), chainID) + } + } + + // Validate trust level. + if err := ValidateTrustLevel(c.trustLevel); err != nil { + return nil, err + } + if err := c.restoreTrustedHeaderAndNextVals(); err != nil { return nil, err } @@ -523,11 +530,9 @@ func (c *Client) VerifyHeader(newHeader *types.SignedHeader, newVals *types.Vali return errors.Errorf("header at more recent height #%d exists", c.trustedHeader.Height) } - if len(c.witnesses) > 0 { - if err := c.compareNewHeaderWithRandomWitness(newHeader); err != nil { - c.logger.Error("Error when comparing new header with one from a witness", "err", err) - return err - } + if err := c.compareNewHeaderWithRandomWitness(newHeader); err != nil { + c.logger.Error("Error when comparing new header with one from a witness", "err", err) + return err } var err error @@ -733,6 +738,10 @@ func (c *Client) fetchHeaderAndValsAtHeight(height int64) (*types.SignedHeader, // compare header with one from a random witness. func (c *Client) compareNewHeaderWithRandomWitness(h *types.SignedHeader) error { + if len(c.witnesses) == 0 { + return errors.New("could not find any witnesses") + } + // 1. Pick a witness. witness := c.witnesses[tmrand.Intn(len(c.witnesses))] diff --git a/lite2/client_test.go b/lite2/client_test.go index d9f58347c..9ddab1ead 100644 --- a/lite2/client_test.go +++ b/lite2/client_test.go @@ -11,6 +11,7 @@ import ( dbm "github.com/tendermint/tm-db" "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/lite2/provider" mockp "github.com/tendermint/tendermint/lite2/provider/mock" dbs "github.com/tendermint/tendermint/lite2/store/db" "github.com/tendermint/tendermint/types" @@ -127,6 +128,11 @@ func TestClient_SequentialVerification(t *testing.T) { tc.otherHeaders, tc.vals, ), + []provider.Provider{mockp.New( + chainID, + tc.otherHeaders, + tc.vals, + )}, dbs.New(dbm.NewMemDB(), chainID), SequentialVerification(), ) @@ -228,6 +234,11 @@ func TestClient_SkippingVerification(t *testing.T) { tc.otherHeaders, tc.vals, ), + []provider.Provider{mockp.New( + chainID, + tc.otherHeaders, + tc.vals, + )}, dbs.New(dbm.NewMemDB(), chainID), SkippingVerification(DefaultTrustLevel), ) @@ -264,6 +275,26 @@ func TestClientRemovesNoLongerTrustedHeaders(t *testing.T) { []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) ) + primary := mockp.New( + chainID, + map[int64]*types.SignedHeader{ + // trusted header + 1: header, + // interim header (3/3 signed) + 2: keys.GenSignedHeader(chainID, 2, bTime.Add(2*time.Hour), nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), + // last header (3/3 signed) + 3: keys.GenSignedHeader(chainID, 3, bTime.Add(4*time.Hour), nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), + }, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: vals, + 3: vals, + 4: vals, + }, + ) + c, err := NewClient( chainID, TrustOptions{ @@ -271,25 +302,8 @@ func TestClientRemovesNoLongerTrustedHeaders(t *testing.T) { Height: 1, Hash: header.Hash(), }, - mockp.New( - chainID, - map[int64]*types.SignedHeader{ - // trusted header - 1: header, - // interim header (3/3 signed) - 2: keys.GenSignedHeader(chainID, 2, bTime.Add(2*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - // last header (3/3 signed) - 3: keys.GenSignedHeader(chainID, 3, bTime.Add(4*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - 3: vals, - 4: vals, - }, - ), + primary, + []provider.Provider{primary}, dbs.New(dbm.NewMemDB(), chainID), Logger(log.TestingLogger()), ) @@ -333,6 +347,18 @@ func TestClient_Cleanup(t *testing.T) { []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) ) + primary := mockp.New( + chainID, + map[int64]*types.SignedHeader{ + // trusted header + 1: header, + }, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: vals, + }, + ) + c, err := NewClient( chainID, TrustOptions{ @@ -340,17 +366,8 @@ func TestClient_Cleanup(t *testing.T) { Height: 1, Hash: header.Hash(), }, - mockp.New( - chainID, - map[int64]*types.SignedHeader{ - // trusted header - 1: header, - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - }, - ), + primary, + []provider.Provider{primary}, dbs.New(dbm.NewMemDB(), chainID), Logger(log.TestingLogger()), ) @@ -388,6 +405,18 @@ func TestClientRestoreTrustedHeaderAfterStartup1(t *testing.T) { err := trustedStore.SaveSignedHeaderAndNextValidatorSet(header, vals) require.NoError(t, err) + primary := mockp.New( + chainID, + map[int64]*types.SignedHeader{ + // trusted header + 1: header, + }, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: vals, + }, + ) + c, err := NewClient( chainID, TrustOptions{ @@ -395,17 +424,8 @@ func TestClientRestoreTrustedHeaderAfterStartup1(t *testing.T) { Height: 1, Hash: header.Hash(), }, - mockp.New( - chainID, - map[int64]*types.SignedHeader{ - // trusted header - 1: header, - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - }, - ), + primary, + []provider.Provider{primary}, trustedStore, Logger(log.TestingLogger()), ) @@ -430,6 +450,18 @@ func TestClientRestoreTrustedHeaderAfterStartup1(t *testing.T) { header1 := keys.GenSignedHeader(chainID, 1, bTime.Add(1*time.Hour), nil, vals, vals, []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) + primary := mockp.New( + chainID, + map[int64]*types.SignedHeader{ + // trusted header + 1: header1, + }, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: vals, + }, + ) + c, err := NewClient( chainID, TrustOptions{ @@ -437,17 +469,8 @@ func TestClientRestoreTrustedHeaderAfterStartup1(t *testing.T) { Height: 1, Hash: header1.Hash(), }, - mockp.New( - chainID, - map[int64]*types.SignedHeader{ - // trusted header - 1: header1, - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - }, - ), + primary, + []provider.Provider{primary}, trustedStore, Logger(log.TestingLogger()), ) @@ -487,6 +510,18 @@ func TestClientRestoreTrustedHeaderAfterStartup2(t *testing.T) { header2 := keys.GenSignedHeader(chainID, 2, bTime.Add(2*time.Hour), nil, vals, vals, []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) + primary := mockp.New( + chainID, + map[int64]*types.SignedHeader{ + 1: header, + 2: header2, + }, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: vals, + 3: vals, + }, + ) c, err := NewClient( chainID, TrustOptions{ @@ -494,18 +529,8 @@ func TestClientRestoreTrustedHeaderAfterStartup2(t *testing.T) { Height: 2, Hash: header2.Hash(), }, - mockp.New( - chainID, - map[int64]*types.SignedHeader{ - 1: header, - 2: header2, - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - 3: vals, - }, - ), + primary, + []provider.Provider{primary}, trustedStore, Logger(log.TestingLogger()), ) @@ -535,6 +560,19 @@ func TestClientRestoreTrustedHeaderAfterStartup2(t *testing.T) { header2 := keys.GenSignedHeader(chainID, 2, bTime.Add(2*time.Hour), nil, vals, vals, []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) + primary := mockp.New( + chainID, + map[int64]*types.SignedHeader{ + 1: header1, + 2: header2, + }, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: vals, + 3: vals, + }, + ) + c, err := NewClient( chainID, TrustOptions{ @@ -542,18 +580,8 @@ func TestClientRestoreTrustedHeaderAfterStartup2(t *testing.T) { Height: 2, Hash: header2.Hash(), }, - mockp.New( - chainID, - map[int64]*types.SignedHeader{ - 1: header1, - 2: header2, - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - 3: vals, - }, - ), + primary, + []provider.Provider{primary}, trustedStore, Logger(log.TestingLogger()), ) @@ -595,6 +623,19 @@ func TestClientRestoreTrustedHeaderAfterStartup3(t *testing.T) { err = trustedStore.SaveSignedHeaderAndNextValidatorSet(header2, vals) require.NoError(t, err) + primary := mockp.New( + chainID, + map[int64]*types.SignedHeader{ + 1: header, + 2: header2, + }, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: vals, + 3: vals, + }, + ) + c, err := NewClient( chainID, TrustOptions{ @@ -602,18 +643,8 @@ func TestClientRestoreTrustedHeaderAfterStartup3(t *testing.T) { Height: 1, Hash: header.Hash(), }, - mockp.New( - chainID, - map[int64]*types.SignedHeader{ - 1: header, - 2: header2, - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - 3: vals, - }, - ), + primary, + []provider.Provider{primary}, trustedStore, Logger(log.TestingLogger()), ) @@ -650,6 +681,17 @@ func TestClientRestoreTrustedHeaderAfterStartup3(t *testing.T) { err = trustedStore.SaveSignedHeaderAndNextValidatorSet(header2, vals) require.NoError(t, err) + primary := mockp.New( + chainID, + map[int64]*types.SignedHeader{ + 1: header1, + }, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: vals, + }, + ) + c, err := NewClient( chainID, TrustOptions{ @@ -657,16 +699,8 @@ func TestClientRestoreTrustedHeaderAfterStartup3(t *testing.T) { Height: 1, Hash: header1.Hash(), }, - mockp.New( - chainID, - map[int64]*types.SignedHeader{ - 1: header1, - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - }, - ), + primary, + []provider.Provider{primary}, trustedStore, Logger(log.TestingLogger()), ) @@ -702,6 +736,26 @@ func TestClient_Update(t *testing.T) { []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) ) + primary := mockp.New( + chainID, + map[int64]*types.SignedHeader{ + // trusted header + 1: header, + // interim header (3/3 signed) + 2: keys.GenSignedHeader(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), + // last header (3/3 signed) + 3: keys.GenSignedHeader(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), + }, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: vals, + 3: vals, + 4: vals, + }, + ) + c, err := NewClient( chainID, TrustOptions{ @@ -709,25 +763,8 @@ func TestClient_Update(t *testing.T) { Height: 1, Hash: header.Hash(), }, - mockp.New( - chainID, - map[int64]*types.SignedHeader{ - // trusted header - 1: header, - // interim header (3/3 signed) - 2: keys.GenSignedHeader(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - // last header (3/3 signed) - 3: keys.GenSignedHeader(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - 3: vals, - 4: vals, - }, - ), + primary, + []provider.Provider{primary}, dbs.New(dbm.NewMemDB(), chainID), Logger(log.TestingLogger()), ) @@ -760,6 +797,26 @@ func TestClient_Concurrency(t *testing.T) { []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) ) + primary := mockp.New( + chainID, + map[int64]*types.SignedHeader{ + // trusted header + 1: header, + // interim header (3/3 signed) + 2: keys.GenSignedHeader(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), + // last header (3/3 signed) + 3: keys.GenSignedHeader(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), + }, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: vals, + 3: vals, + 4: vals, + }, + ) + c, err := NewClient( chainID, TrustOptions{ @@ -767,25 +824,8 @@ func TestClient_Concurrency(t *testing.T) { Height: 1, Hash: header.Hash(), }, - mockp.New( - chainID, - map[int64]*types.SignedHeader{ - // trusted header - 1: header, - // interim header (3/3 signed) - 2: keys.GenSignedHeader(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - // last header (3/3 signed) - 3: keys.GenSignedHeader(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - 3: vals, - 4: vals, - }, - ), + primary, + []provider.Provider{primary}, dbs.New(dbm.NewMemDB(), chainID), UpdatePeriod(0), Logger(log.TestingLogger()), diff --git a/lite2/example_test.go b/lite2/example_test.go index 4a291236b..87e839d9b 100644 --- a/lite2/example_test.go +++ b/lite2/example_test.go @@ -12,6 +12,7 @@ import ( "github.com/tendermint/tendermint/abci/example/kvstore" "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/lite2/provider" httpp "github.com/tendermint/tendermint/lite2/provider/http" dbs "github.com/tendermint/tendermint/lite2/store/db" rpctest "github.com/tendermint/tendermint/rpc/test" @@ -33,12 +34,12 @@ func TestExample_Client_AutoUpdate(t *testing.T) { chainID = config.ChainID() ) - provider, err := httpp.New(chainID, config.RPC.ListenAddress) + primary, err := httpp.New(chainID, config.RPC.ListenAddress) if err != nil { stdlog.Fatal(err) } - header, err := provider.SignedHeader(2) + header, err := primary.SignedHeader(2) if err != nil { stdlog.Fatal(err) } @@ -55,7 +56,8 @@ func TestExample_Client_AutoUpdate(t *testing.T) { Height: 2, Hash: header.Hash(), }, - provider, + primary, + []provider.Provider{primary}, // TODO: primary should not be used here dbs.New(db, chainID), UpdatePeriod(1*time.Second), Logger(log.TestingLogger()), @@ -99,12 +101,12 @@ func TestExample_Client_ManualUpdate(t *testing.T) { chainID = config.ChainID() ) - provider, err := httpp.New(chainID, config.RPC.ListenAddress) + primary, err := httpp.New(chainID, config.RPC.ListenAddress) if err != nil { stdlog.Fatal(err) } - header, err := provider.SignedHeader(2) + header, err := primary.SignedHeader(2) if err != nil { stdlog.Fatal(err) } @@ -121,7 +123,8 @@ func TestExample_Client_ManualUpdate(t *testing.T) { Height: 2, Hash: header.Hash(), }, - provider, + primary, + []provider.Provider{primary}, // TODO: primary should not be used here dbs.New(db, chainID), UpdatePeriod(0), Logger(log.TestingLogger()), From fa34ff96b879de9299fadcbeed32d36d33044a41 Mon Sep 17 00:00:00 2001 From: Tess Rinearson Date: Mon, 3 Feb 2020 15:00:31 +0100 Subject: [PATCH 25/45] abci: fix broken spec link (#4366) --- abci/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/abci/README.md b/abci/README.md index ad84eb77c..cd0e9bbd9 100644 --- a/abci/README.md +++ b/abci/README.md @@ -19,7 +19,7 @@ To get up and running quickly, see the [getting started guide](../docs/app-dev/g A detailed description of the ABCI methods and message types is contained in: -- [The main spec](../docs/spec/abci/abci.md) +- [The main spec](https://github.com/tendermint/spec/blob/master/spec/abci/abci.md) - [A protobuf file](./types/types.proto) - [A Go interface](./types/application.go) From 9b9f1beef3cfc5e501fc494afeb4862bd86482f3 Mon Sep 17 00:00:00 2001 From: Marko Date: Mon, 3 Feb 2020 18:15:27 +0100 Subject: [PATCH 26/45] docs: update guides proto paths (#4365) * update guides with correct path to libs/kv proto files * Apply suggestions from code review Co-Authored-By: Anton Kaliaev * format something to rerun ci Co-authored-by: Anton Kaliaev --- Makefile | 12 ------------ README.md | 6 +++--- docs/guides/go-built-in.md | 12 +++++------- docs/guides/go.md | 15 +++++++-------- docs/guides/java.md | 10 +++++----- docs/guides/kotlin.md | 11 ++++++----- 6 files changed, 26 insertions(+), 40 deletions(-) diff --git a/Makefile b/Makefile index a6c1df45c..f6ca17d18 100644 --- a/Makefile +++ b/Makefile @@ -94,10 +94,6 @@ protoc_libs: libs/kv/types.pb.go # generates certificates for TLS testing in remotedb and RPC server gen_certs: clean_certs certstrap init --common-name "tendermint.com" --passphrase "" - certstrap request-cert --common-name "remotedb" -ip "127.0.0.1" --passphrase "" - certstrap sign "remotedb" --CA "tendermint.com" --passphrase "" - mv out/remotedb.crt libs/db/remotedb/test.crt - mv out/remotedb.key libs/db/remotedb/test.key certstrap request-cert --common-name "server" -ip "127.0.0.1" --passphrase "" certstrap sign "server" --CA "tendermint.com" --passphrase "" mv out/server.crt rpc/lib/server/test.crt @@ -106,17 +102,9 @@ gen_certs: clean_certs # deletes generated certificates clean_certs: - rm -f libs/db/remotedb/test.crt - rm -f libs/db/remotedb/test.key rm -f rpc/lib/server/test.crt rm -f rpc/lib/server/test.key -test_libs: - go test -tags clevedb boltdb $(PACKAGES) - -grpc_dbserver: - protoc -I libs/db/remotedb/proto/ libs/db/remotedb/proto/defs.proto --go_out=plugins=grpc:libs/db/remotedb/proto - protoc_grpc: rpc/grpc/types.pb.go protoc_merkle: crypto/merkle/merkle.pb.go diff --git a/README.md b/README.md index 6d25546e1..9e87b4962 100644 --- a/README.md +++ b/README.md @@ -47,9 +47,9 @@ For examples of the kinds of bugs we're looking for, see [SECURITY.md](SECURITY. ## Minimum requirements -| Requirement | Notes | -| ----------- | ------------------ | -| Go version | Go1.13 or higher | +| Requirement | Notes | +| ----------- | ---------------- | +| Go version | Go1.13 or higher | ## Documentation diff --git a/docs/guides/go-built-in.md b/docs/guides/go-built-in.md index 56f910331..5ab71b829 100644 --- a/docs/guides/go-built-in.md +++ b/docs/guides/go-built-in.md @@ -1,6 +1,6 @@ ---- + # Creating a built-in application in Go @@ -55,8 +55,8 @@ $ echo $GOPATH We'll start by creating a new Go project. ```sh -$ mkdir -p $GOPATH/src/github.com/me/kvstore -$ cd $GOPATH/src/github.com/me/kvstore +$ mkdir kvstore +$ cd kvstore ``` Inside the example directory create a `main.go` file with the following content: @@ -569,7 +569,6 @@ We are going to use [Go modules](https://github.com/golang/go/wiki/Modules) for dependency management. ```sh -$ export GO111MODULE=on $ go mod init github.com/me/example $ go build ``` @@ -580,8 +579,7 @@ To create a default configuration, nodeKey and private validator files, let's execute `tendermint init`. But before we do that, we will need to install Tendermint Core. Please refer to [the official guide](https://docs.tendermint.com/master/introduction/install.html). If you're -installing from source, don't forget to checkout the latest release (`git -checkout vX.Y.Z`). +installing from source, don't forget to checkout the latest release (`git checkout vX.Y.Z`). ```sh $ rm -rf /tmp/example diff --git a/docs/guides/go.md b/docs/guides/go.md index 6559a0005..f688d0e4e 100644 --- a/docs/guides/go.md +++ b/docs/guides/go.md @@ -1,6 +1,6 @@ ---- + # Creating an application in Go @@ -58,8 +58,8 @@ $ echo $GOPATH We'll start by creating a new Go project. ```sh -$ mkdir -p $GOPATH/src/github.com/me/kvstore -$ cd $GOPATH/src/github.com/me/kvstore +$ mkdir kvstore +$ cd kvstore ``` Inside the example directory create a `main.go` file with the following content: @@ -228,9 +228,9 @@ func NewKVStoreApplication(db *badger.DB) *KVStoreApplication { ### 1.3.2 BeginBlock -> DeliverTx -> EndBlock -> Commit -When Tendermint Core has decided on the block, it's transfered to the +When Tendermint Core has decided on the block, it's transferred to the application in 3 parts: `BeginBlock`, one `DeliverTx` per transaction and -`EndBlock` in the end. DeliverTx are being transfered asynchronously, but the +`EndBlock` in the end. DeliverTx are being transferred asynchronously, but the responses are expected to come in order. ``` @@ -437,8 +437,7 @@ To create a default configuration, nodeKey and private validator files, let's execute `tendermint init`. But before we do that, we will need to install Tendermint Core. Please refer to [the official guide](https://docs.tendermint.com/master/introduction/install.html). If you're -installing from source, don't forget to checkout the latest release (`git -checkout vX.Y.Z`). +installing from source, don't forget to checkout the latest release (`git checkout vX.Y.Z`). ```sh $ rm -rf /tmp/example diff --git a/docs/guides/java.md b/docs/guides/java.md index 4109f042f..12bbc4565 100644 --- a/docs/guides/java.md +++ b/docs/guides/java.md @@ -1,6 +1,6 @@ ---- + # Creating an application in Java @@ -170,15 +170,15 @@ Copy the necessary `.proto` files to your project: mkdir -p \ $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/abci/types \ $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/crypto/merkle \ - $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/libs/common \ + $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/libs/kv \ $KVSTORE_HOME/src/main/proto/github.com/gogo/protobuf/gogoproto cp $GOPATH/src/github.com/tendermint/tendermint/abci/types/types.proto \ $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/abci/types/types.proto cp $GOPATH/src/github.com/tendermint/tendermint/crypto/merkle/merkle.proto \ $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/crypto/merkle/merkle.proto -cp $GOPATH/src/github.com/tendermint/tendermint/libs/common/types.proto \ - $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/libs/common/types.proto +cp $GOPATH/src/github.com/tendermint/tendermint/libs/kv/types.proto \ + $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/libs/kv/types.proto cp $GOPATH/src/github.com/gogo/protobuf/gogoproto/gogo.proto \ $KVSTORE_HOME/src/main/proto/github.com/gogo/protobuf/gogoproto/gogo.proto ``` diff --git a/docs/guides/kotlin.md b/docs/guides/kotlin.md index 1829e1074..0c15098a4 100644 --- a/docs/guides/kotlin.md +++ b/docs/guides/kotlin.md @@ -1,6 +1,7 @@ ---- + + # Creating an application in Kotlin ## Guide Assumptions @@ -169,15 +170,15 @@ Copy the necessary `.proto` files to your project: mkdir -p \ $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/abci/types \ $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/crypto/merkle \ - $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/libs/common \ + $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/libs/kv \ $KVSTORE_HOME/src/main/proto/github.com/gogo/protobuf/gogoproto cp $GOPATH/src/github.com/tendermint/tendermint/abci/types/types.proto \ $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/abci/types/types.proto cp $GOPATH/src/github.com/tendermint/tendermint/crypto/merkle/merkle.proto \ $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/crypto/merkle/merkle.proto -cp $GOPATH/src/github.com/tendermint/tendermint/libs/common/types.proto \ - $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/libs/common/types.proto +cp $GOPATH/src/github.com/tendermint/tendermint/libs/kv/types.proto \ + $KVSTORE_HOME/src/main/proto/github.com/tendermint/tendermint/libs/kv/types.proto cp $GOPATH/src/github.com/gogo/protobuf/gogoproto/gogo.proto \ $KVSTORE_HOME/src/main/proto/github.com/gogo/protobuf/gogoproto/gogo.proto ``` From df3eee455c9d2a4a9698a35aa0dfe6d5d2efd53d Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Tue, 4 Feb 2020 13:02:20 +0100 Subject: [PATCH 27/45] lite2: replace primary provider with alternative when unavailable (#4354) Closes issue #4338 Uses a wrapper function around both the signedHeader and validatorSet calls to the primary provider which attempts to retrieve the information 5 times before deeming the provider unavailable and replacing the primary provider with the first alternative before trying recursively again (until all alternatives are depleted) Employs a mutex lock for any operations involving the providers of the light client to ensure no operations occurs whilst the new primary is chosen. Commits: * created swapProvider function * eliminates old primary provider after replacement. Uses a mutex when changing providers * renamed to replaceProvider * created wrapped functions for signed header and val set * created test for primary provider replacement * implemented suggested revisions * created Witnesses() and Primary() * modified backoffAndJitterTime * modified backoffAndJitterTime * changed backoff base and jitter to functional arguments * implemented suggested changes * removed backoff function * changed exp function to match go version * halved the backoff time * removed seeding and added comments * fixed incorrect test * extract backoff timeout calc into a function Co-authored-by: Anton Kaliaev --- lite2/client.go | 109 ++++++++++++++++++++++++++++++++---- lite2/client_test.go | 56 ++++++++++++++++++ lite2/provider/mock/mock.go | 28 ++++++++- 3 files changed, 179 insertions(+), 14 deletions(-) diff --git a/lite2/client.go b/lite2/client.go index 4248d5eb8..c1dc88b1a 100644 --- a/lite2/client.go +++ b/lite2/client.go @@ -3,6 +3,7 @@ package lite import ( "bytes" "fmt" + "math/rand" "sync" "time" @@ -51,6 +52,7 @@ const ( defaultUpdatePeriod = 5 * time.Second defaultRemoveNoLongerTrustedHeadersPeriod = 24 * time.Hour + maxRetryAttempts = 10 ) // Option sets a parameter for the light client. @@ -128,9 +130,10 @@ type Client struct { verificationMode mode trustLevel tmmath.Fraction + // Mutex for locking during changes of the lite clients providers + providerMutex sync.Mutex // Primary provider of new headers. primary provider.Provider - // See Witnesses option witnesses []provider.Provider @@ -275,7 +278,7 @@ func (c *Client) checkTrustedHeaderUsingOptions(options TrustOptions) error { var primaryHash []byte switch { case options.Height > c.trustedHeader.Height: - h, err := c.primary.SignedHeader(c.trustedHeader.Height) + h, err := c.signedHeaderFromPrimary(c.trustedHeader.Height) if err != nil { return err } @@ -327,7 +330,7 @@ func (c *Client) checkTrustedHeaderUsingOptions(options TrustOptions) error { // Fetch trustedHeader and trustedNextVals from primary provider. func (c *Client) initializeWithTrustOptions(options TrustOptions) error { // 1) Fetch and verify the header. - h, err := c.primary.SignedHeader(options.Height) + h, err := c.signedHeaderFromPrimary(options.Height) if err != nil { return err } @@ -342,7 +345,7 @@ func (c *Client) initializeWithTrustOptions(options TrustOptions) error { } // 2) Fetch and verify the vals. - vals, err := c.primary.ValidatorSet(options.Height) + vals, err := c.validatorSetFromPrimary(options.Height) if err != nil { return err } @@ -360,7 +363,7 @@ func (c *Client) initializeWithTrustOptions(options TrustOptions) error { // 3) Fetch and verify the next vals (verification happens in // updateTrustedHeaderAndVals). - nextVals, err := c.primary.ValidatorSet(options.Height + 1) + nextVals, err := c.validatorSetFromPrimary(options.Height + 1) if err != nil { return err } @@ -549,13 +552,31 @@ func (c *Client) VerifyHeader(newHeader *types.SignedHeader, newVals *types.Vali } // Update trusted header and vals. - nextVals, err := c.primary.ValidatorSet(newHeader.Height + 1) + nextVals, err := c.validatorSetFromPrimary(newHeader.Height + 1) if err != nil { return err } return c.updateTrustedHeaderAndVals(newHeader, nextVals) } +// Primary returns the primary provider. +// +// NOTE: provider may be not safe for concurrent access. +func (c *Client) Primary() provider.Provider { + c.providerMutex.Lock() + defer c.providerMutex.Unlock() + return c.primary +} + +// Witnesses returns the witness providers. +// +// NOTE: providers may be not safe for concurrent access. +func (c *Client) Witnesses() []provider.Provider { + c.providerMutex.Lock() + defer c.providerMutex.Unlock() + return c.witnesses +} + // Cleanup removes all the data (headers and validator sets) stored. Note: the // client must be stopped at this point. func (c *Client) Cleanup() error { @@ -608,7 +629,7 @@ func (c *Client) sequence(newHeader *types.SignedHeader, newVals *types.Validato err error ) for height := c.trustedHeader.Height + 1; height < newHeader.Height; height++ { - interimHeader, err = c.primary.SignedHeader(height) + interimHeader, err = c.signedHeaderFromPrimary(height) if err != nil { return errors.Wrapf(err, "failed to obtain the header #%d", height) } @@ -628,7 +649,7 @@ func (c *Client) sequence(newHeader *types.SignedHeader, newVals *types.Validato if height == newHeader.Height-1 { nextVals = newVals } else { - nextVals, err = c.primary.ValidatorSet(height + 1) + nextVals, err = c.validatorSetFromPrimary(height + 1) if err != nil { return errors.Wrapf(err, "failed to obtain the vals #%d", height+1) } @@ -682,7 +703,7 @@ func (c *Client) bisection( // right branch { - nextVals, err := c.primary.ValidatorSet(pivot + 1) + nextVals, err := c.validatorSetFromPrimary(pivot + 1) if err != nil { return errors.Wrapf(err, "failed to obtain the vals #%d", pivot+1) } @@ -725,11 +746,11 @@ func (c *Client) updateTrustedHeaderAndVals(h *types.SignedHeader, nextVals *typ // fetch header and validators for the given height from primary provider. func (c *Client) fetchHeaderAndValsAtHeight(height int64) (*types.SignedHeader, *types.ValidatorSet, error) { - h, err := c.primary.SignedHeader(height) + h, err := c.signedHeaderFromPrimary(height) if err != nil { return nil, nil, errors.Wrapf(err, "failed to obtain the header #%d", height) } - vals, err := c.primary.ValidatorSet(height) + vals, err := c.validatorSetFromPrimary(height) if err != nil { return nil, nil, errors.Wrapf(err, "failed to obtain the vals #%d", height) } @@ -738,12 +759,15 @@ func (c *Client) fetchHeaderAndValsAtHeight(height int64) (*types.SignedHeader, // compare header with one from a random witness. func (c *Client) compareNewHeaderWithRandomWitness(h *types.SignedHeader) error { + c.providerMutex.Lock() + // 0. Check witnesses exist if len(c.witnesses) == 0 { return errors.New("could not find any witnesses") } // 1. Pick a witness. witness := c.witnesses[tmrand.Intn(len(c.witnesses))] + c.providerMutex.Unlock() // 2. Fetch the header. altH, err := witness.SignedHeader(h.Height) @@ -871,3 +895,66 @@ func (c *Client) Update(now time.Time) error { return nil } + +// replaceProvider takes the first alternative provider and promotes it as the primary provider +func (c *Client) replacePrimaryProvider() error { + c.providerMutex.Lock() + defer c.providerMutex.Unlock() + if len(c.witnesses) == 0 { + return errors.Errorf("no witnesses left") + } + c.primary = c.witnesses[0] + c.witnesses = c.witnesses[1:] + c.logger.Info("New primary", "p", c.primary) + return nil +} + +// signedHeaderFromPrimary retrieves the SignedHeader from the primary provider at the specified height. +// Handles dropout by the primary provider by swapping with an alternative provider +func (c *Client) signedHeaderFromPrimary(height int64) (*types.SignedHeader, error) { + for attempt := 1; attempt <= maxRetryAttempts; attempt++ { + c.providerMutex.Lock() + h, err := c.primary.SignedHeader(height) + c.providerMutex.Unlock() + if err == nil || err == provider.ErrSignedHeaderNotFound { + return h, err + } + time.Sleep(backoffTimeout(attempt)) + } + + c.logger.Info("Primary is unavailable. Replacing with the first witness") + err := c.replacePrimaryProvider() + if err != nil { + return nil, err + } + + return c.signedHeaderFromPrimary(height) +} + +// validatorSetFromPrimary retrieves the ValidatorSet from the primary provider at the specified height. +// Handles dropout by the primary provider after 5 attempts by replacing it with an alternative provider +func (c *Client) validatorSetFromPrimary(height int64) (*types.ValidatorSet, error) { + for attempt := 1; attempt <= maxRetryAttempts; attempt++ { + c.providerMutex.Lock() + h, err := c.primary.ValidatorSet(height) + c.providerMutex.Unlock() + if err == nil || err == provider.ErrValidatorSetNotFound { + return h, err + } + time.Sleep(backoffTimeout(attempt)) + } + + c.logger.Info("Primary is unavailable. Replacing with the first witness") + err := c.replacePrimaryProvider() + if err != nil { + return nil, err + } + + return c.validatorSetFromPrimary(height) +} + +// exponential backoff (with jitter) +// 0.5s -> 2s -> 4.5s -> 8s -> 12.5 with 1s variation +func backoffTimeout(attempt int) time.Duration { + return time.Duration(500*attempt*attempt)*time.Millisecond + time.Duration(rand.Intn(1000))*time.Millisecond +} diff --git a/lite2/client_test.go b/lite2/client_test.go index 9ddab1ead..d7145feb7 100644 --- a/lite2/client_test.go +++ b/lite2/client_test.go @@ -867,3 +867,59 @@ func TestClient_Concurrency(t *testing.T) { wg.Wait() } + +func TestProvider_Replacement(t *testing.T) { + const ( + chainID = "TestProvider_Replacement" + ) + + var ( + keys = genPrivKeys(4) + // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! + vals = keys.ToValidators(20, 10) + bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") + header = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) + primary = mockp.NewDeadMock(chainID) + witness = mockp.New( + chainID, + map[int64]*types.SignedHeader{ + // trusted header + 1: header, + // interim header (3/3 signed) + 2: keys.GenSignedHeader(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), + // last header (3/3 signed) + 3: keys.GenSignedHeader(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), + }, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: vals, + 3: vals, + 4: vals, + }, + ) + ) + + c, err := NewClient( + chainID, + TrustOptions{ + Period: 4 * time.Hour, + Height: 1, + Hash: header.Hash(), + }, + primary, + []provider.Provider{witness}, + dbs.New(dbm.NewMemDB(), chainID), + UpdatePeriod(0), + Logger(log.TestingLogger()), + ) + require.NoError(t, err) + err = c.Start() + require.NoError(t, err) + defer c.Stop() + assert.NotEqual(t, c.Primary(), primary) + assert.Equal(t, 0, len(c.Witnesses())) + +} diff --git a/lite2/provider/mock/mock.go b/lite2/provider/mock/mock.go index f895420e5..f41358345 100644 --- a/lite2/provider/mock/mock.go +++ b/lite2/provider/mock/mock.go @@ -1,19 +1,20 @@ package mock import ( + "github.com/pkg/errors" + "github.com/tendermint/tendermint/lite2/provider" "github.com/tendermint/tendermint/types" ) -// mock provider allows to directly set headers & vals, which can be handy when -// testing. type mock struct { chainID string headers map[int64]*types.SignedHeader vals map[int64]*types.ValidatorSet } -// New creates a mock provider. +// New creates a mock provider with the given set of headers and validator +// sets. func New(chainID string, headers map[int64]*types.SignedHeader, vals map[int64]*types.ValidatorSet) provider.Provider { return &mock{ chainID: chainID, @@ -45,3 +46,24 @@ func (p *mock) ValidatorSet(height int64) (*types.ValidatorSet, error) { } return nil, provider.ErrValidatorSetNotFound } + +type deadMock struct { + chainID string +} + +// NewDeadMock creates a mock provider that always errors. +func NewDeadMock(chainID string) provider.Provider { + return &deadMock{chainID: chainID} +} + +func (p *deadMock) ChainID() string { + return p.chainID +} + +func (p *deadMock) SignedHeader(height int64) (*types.SignedHeader, error) { + return nil, errors.New("no response from provider") +} + +func (p *deadMock) ValidatorSet(height int64) (*types.ValidatorSet, error) { + return nil, errors.New("no response from provider") +} From bb7a80ec7ecdf464702485493c05fea7d2a37f0e Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Thu, 6 Feb 2020 12:30:37 +0100 Subject: [PATCH 28/45] lite2: fetch missing headers (#4362) Closes #4328 When TrustedHeader(height) is called, if the height is less than the trusted height but the header is not in the trusted store then a function finds the previous lowest height with a trusted header and performs a forwards sequential verification to the header of the height that was given. If no error is found it updates the trusted store with the header and validator set for that height and can then return them to the user. Commits: * drafted trusted header * created function to find previous trusted height * updates missing headers less than the trusted height * minor cosmetic tweaks * incorporated suggestions * lite2: implement Backwards verification and add SignedHeaderAfter func to Store interface Refs https://github.com/tendermint/tendermint/issues/4328#issuecomment-581878549 * remove unused method * write tests * start with next height in SignedHeaderAfter func * fix linter errors * address Callum's comments Co-authored-by: Anton Kaliaev --- lite2/client.go | 155 ++++++++++++++++++++++++++++++++------ lite2/client_test.go | 63 ++++++++++++++++ lite2/store/db/db.go | 30 +++++++- lite2/store/db/db_test.go | 19 +++++ lite2/store/errors.go | 12 +++ lite2/store/store.go | 9 ++- lite2/test_helpers.go | 13 ++++ 7 files changed, 272 insertions(+), 29 deletions(-) create mode 100644 lite2/store/errors.go diff --git a/lite2/client.go b/lite2/client.go index c1dc88b1a..c46160712 100644 --- a/lite2/client.go +++ b/lite2/client.go @@ -398,11 +398,13 @@ func (c *Client) Stop() { c.routinesWaitGroup.Wait() } -// TrustedHeader returns a trusted header at the given height (0 - the latest) -// or nil if no such header exist. +// TrustedHeader returns a trusted header at the given height (0 - the latest). +// If a header is missing in trustedStore (e.g. it was skipped during +// bisection), it will be downloaded from primary. // -// Headers, which can't be trusted anymore, are removed once a day (can be -// changed with RemoveNoLongerTrustedHeadersPeriod option). +// Headers along with validator sets, which can't be trusted anymore, are +// removed once a day (can be changed with RemoveNoLongerTrustedHeadersPeriod +// option). // . // height must be >= 0. // @@ -411,7 +413,7 @@ func (c *Client) Stop() { // - there are some issues with the trusted store, although that should not // happen normally; // - negative height is passed; -// - header is not found. +// - header has not been verified yet // // Safe for concurrent use by multiple goroutines. func (c *Client) TrustedHeader(height int64, now time.Time) (*types.SignedHeader, error) { @@ -419,20 +421,35 @@ func (c *Client) TrustedHeader(height int64, now time.Time) (*types.SignedHeader return nil, errors.New("negative height") } - if height == 0 { - var err error - height, err = c.LastTrustedHeight() - if err != nil { - return nil, err - } - } - - h, err := c.trustedStore.SignedHeader(height) + // 1) Get latest height. + latestHeight, err := c.LastTrustedHeight() if err != nil { return nil, err } + if latestHeight == -1 { + return nil, errors.New("no headers exist") + } + if height > latestHeight { + return nil, errors.Errorf("unverified header requested (latest: %d)", latestHeight) + } + if height == 0 { + height = latestHeight + } - // Ensure header can still be trusted. + // 2) Get header from store. + h, err := c.trustedStore.SignedHeader(height) + switch { + case errors.Is(err, store.ErrSignedHeaderNotFound): + // 2.1) If not found, try to fetch header from primary. + h, err = c.fetchMissingTrustedHeader(height, now) + if err != nil { + return nil, err + } + case err != nil: + return nil, err + } + + // 3) Ensure header can still be trusted. if HeaderExpired(h, c.trustingPeriod, now) { return nil, ErrOldHeaderExpired{h.Time.Add(c.trustingPeriod), now} } @@ -440,23 +457,31 @@ func (c *Client) TrustedHeader(height int64, now time.Time) (*types.SignedHeader return h, nil } -// TrustedValidatorSet returns a trusted validator set at the given height (0 - -// the latest) or nil if no such validator set exist. The second return -// parameter is height validator set corresponds to (useful when you pass 0). +// TrustedValidatorSet returns a trusted validator set at the given height. If +// a validator set is missing in trustedStore (e.g. the associated header was +// skipped during bisection), it will be downloaded from primary. The second +// return parameter is height validator set corresponds to (useful when you +// pass 0). // // height must be >= 0. // +// Headers along with validator sets, which can't be trusted anymore, are +// removed once a day (can be changed with RemoveNoLongerTrustedHeadersPeriod +// option). +// // It returns an error if: // - header signed by that validator set expired (ErrOldHeaderExpired) // - there are some issues with the trusted store, although that should not // happen normally; // - negative height is passed; -// - validator set is not found. +// - header signed by that validator set has not been verified yet // // Safe for concurrent use by multiple goroutines. func (c *Client) TrustedValidatorSet(height int64, now time.Time) (*types.ValidatorSet, error) { - // Checks height is positive and header is not expired. - _, err := c.TrustedHeader(height, now) + // Checks height is positive and header (note: height - 1) is not expired. + // Additionally, it fetches validator set from primary if it's missing in + // store. + _, err := c.TrustedHeader(height-1, now) if err != nil { return nil, err } @@ -757,6 +782,79 @@ func (c *Client) fetchHeaderAndValsAtHeight(height int64) (*types.SignedHeader, return h, vals, nil } +// fetchMissingTrustedHeader finds the closest height after the +// requested height and does backwards verification. +func (c *Client) fetchMissingTrustedHeader(height int64, now time.Time) (*types.SignedHeader, error) { + c.logger.Info("Fetching missing header", "height", height) + + closestHeader, err := c.trustedStore.SignedHeaderAfter(height) + if err != nil { + return nil, errors.Wrapf(err, "can't get signed header after %d", height) + } + + // Perform backwards verification from closestHeader to header at the given + // height. + h, err := c.backwards(height, closestHeader, now) + if err != nil { + return nil, err + } + + // Fetch next validator set from primary and persist it. + nextVals, err := c.validatorSetFromPrimary(height + 1) + if err != nil { + return nil, errors.Wrapf(err, "failed to obtain the vals #%d", height) + } + if !bytes.Equal(h.NextValidatorsHash, nextVals.Hash()) { + return nil, errors.Errorf("expected next validator's hash %X, but got %X", + h.NextValidatorsHash, nextVals.Hash()) + } + if err := c.trustedStore.SaveSignedHeaderAndNextValidatorSet(h, nextVals); err != nil { + return nil, errors.Wrap(err, "failed to save trusted header") + } + + return h, nil +} + +// Backwards verification (see VerifyHeaderBackwards func in the spec) +func (c *Client) backwards(toHeight int64, fromHeader *types.SignedHeader, now time.Time) (*types.SignedHeader, error) { + var ( + trustedHeader = fromHeader + untrustedHeader *types.SignedHeader + err error + ) + + for i := trustedHeader.Height - 1; i >= toHeight; i-- { + untrustedHeader, err = c.signedHeaderFromPrimary(i) + if err != nil { + return nil, errors.Wrapf(err, "failed to obtain the header #%d", i) + } + + if err := untrustedHeader.ValidateBasic(c.chainID); err != nil { + return nil, errors.Wrap(err, "untrustedHeader.ValidateBasic failed") + } + + if !untrustedHeader.Time.Before(trustedHeader.Time) { + return nil, errors.Errorf("expected older header time %v to be before newer header time %v", + untrustedHeader.Time, + trustedHeader.Time) + } + + if HeaderExpired(untrustedHeader, c.trustingPeriod, now) { + return nil, ErrOldHeaderExpired{untrustedHeader.Time.Add(c.trustingPeriod), now} + } + + if !bytes.Equal(untrustedHeader.Hash(), trustedHeader.LastBlockID.Hash) { + return nil, errors.Errorf("older header hash %X does not match trusted header's last block %X", + untrustedHeader.Hash(), + trustedHeader.LastBlockID.Hash) + } + + trustedHeader = untrustedHeader + } + + return trustedHeader, nil +} + // compare header with one from a random witness. func (c *Client) compareNewHeaderWithRandomWitness(h *types.SignedHeader) error { c.providerMutex.Lock() @@ -916,8 +1014,15 @@ func (c *Client) signedHeaderFromPrimary(height int64) (*types.SignedHeader, err c.providerMutex.Lock() h, err := c.primary.SignedHeader(height) c.providerMutex.Unlock() - if err == nil || err == provider.ErrSignedHeaderNotFound { - return h, err + if err == nil { + // sanity check + if height > 0 && h.Height != height { + return nil, errors.Errorf("expected %d height, got %d", height, h.Height) + } + return h, nil + } + if err == provider.ErrSignedHeaderNotFound { + return nil, err } time.Sleep(backoffTimeout(attempt)) } @@ -936,10 +1041,10 @@ func (c *Client) signedHeaderFromPrimary(height int64) (*types.SignedHeader, err func (c *Client) validatorSetFromPrimary(height int64) (*types.ValidatorSet, error) { for attempt := 1; attempt <= maxRetryAttempts; attempt++ { c.providerMutex.Lock() - h, err := c.primary.ValidatorSet(height) + vals, err := c.primary.ValidatorSet(height) c.providerMutex.Unlock() if err == nil || err == provider.ErrValidatorSetNotFound { - return h, err + return vals, err } time.Sleep(backoffTimeout(attempt)) } diff --git a/lite2/client_test.go b/lite2/client_test.go index d7145feb7..702473715 100644 --- a/lite2/client_test.go +++ b/lite2/client_test.go @@ -919,7 +919,70 @@ func TestProvider_Replacement(t *testing.T) { err = c.Start() require.NoError(t, err) defer c.Stop() + assert.NotEqual(t, c.Primary(), primary) assert.Equal(t, 0, len(c.Witnesses())) +} +func TestProvider_TrustedHeaderFetchesMissingHeader(t *testing.T) { + const ( + chainID = "TestProvider_TrustedHeaderFetchesMissingHeader" + ) + + var ( + keys = genPrivKeys(4) + // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! + vals = keys.ToValidators(20, 10) + bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") + h1 = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) + h2 = keys.GenSignedHeaderLastBlockID(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys), types.BlockID{Hash: h1.Hash()}) + h3 = keys.GenSignedHeaderLastBlockID(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys), types.BlockID{Hash: h2.Hash()}) + primary = mockp.New( + chainID, + map[int64]*types.SignedHeader{ + 1: h1, + 2: h2, + 3: h3, + }, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: vals, + 3: vals, + 4: vals, + }, + ) + ) + + c, err := NewClient( + chainID, + TrustOptions{ + Period: 1 * time.Hour, + Height: 3, + Hash: h3.Hash(), + }, + primary, + []provider.Provider{primary}, + dbs.New(dbm.NewMemDB(), chainID), + UpdatePeriod(0), + Logger(log.TestingLogger()), + ) + require.NoError(t, err) + err = c.Start() + require.NoError(t, err) + defer c.Stop() + + // 1) header is missing => expect no error + h, err := c.TrustedHeader(2, bTime.Add(1*time.Hour).Add(1*time.Second)) + require.NoError(t, err) + if assert.NotNil(t, h) { + assert.EqualValues(t, 2, h.Height) + } + + // 2) header is missing, but it's expired => expect error + h, err = c.TrustedHeader(1, bTime.Add(1*time.Hour).Add(1*time.Second)) + assert.Error(t, err) + assert.Nil(t, h) } diff --git a/lite2/store/db/db.go b/lite2/store/db/db.go index 32c5a4d50..89897ed7f 100644 --- a/lite2/store/db/db.go +++ b/lite2/store/db/db.go @@ -81,7 +81,7 @@ func (s *dbs) SignedHeader(height int64) (*types.SignedHeader, error) { panic(err) } if len(bz) == 0 { - return nil, errors.New("signed header not found") + return nil, store.ErrSignedHeaderNotFound } var signedHeader *types.SignedHeader @@ -100,7 +100,7 @@ func (s *dbs) ValidatorSet(height int64) (*types.ValidatorSet, error) { panic(err) } if len(bz) == 0 { - return nil, errors.New("validator set not found") + return nil, store.ErrValidatorSetNotFound } var valSet *types.ValidatorSet @@ -154,6 +154,32 @@ func (s *dbs) FirstSignedHeaderHeight() (int64, error) { return -1, nil } +func (s *dbs) SignedHeaderAfter(height int64) (*types.SignedHeader, error) { + if height <= 0 { + panic("negative or zero height") + } + + itr, err := s.db.ReverseIterator( + s.shKey(height+1), + append(s.shKey(1<<63-1), byte(0x00)), + ) + if err != nil { + panic(err) + } + defer itr.Close() + + for itr.Valid() { + key := itr.Key() + _, existingHeight, ok := parseShKey(key) + if ok { + return s.SignedHeader(existingHeight) + } + itr.Next() + } + + panic(fmt.Sprintf("no header after height %d. make sure height is not greater than latest existing height", height)) +} + func (s *dbs) shKey(height int64) []byte { return []byte(fmt.Sprintf("sh/%s/%020d", s.prefix, height)) } diff --git a/lite2/store/db/db_test.go b/lite2/store/db/db_test.go index ba8dfd223..a1dc3000e 100644 --- a/lite2/store/db/db_test.go +++ b/lite2/store/db/db_test.go @@ -74,3 +74,22 @@ func Test_SaveSignedHeaderAndNextValidatorSet(t *testing.T) { require.Error(t, err) assert.Nil(t, valSet) } + +func Test_SignedHeaderAfter(t *testing.T) { + dbStore := New(dbm.NewMemDB(), "Test_SignedHeaderAfter") + + assert.Panics(t, func() { + dbStore.SignedHeaderAfter(0) + dbStore.SignedHeaderAfter(100) + }) + + err := dbStore.SaveSignedHeaderAndNextValidatorSet( + &types.SignedHeader{Header: &types.Header{Height: 2}}, &types.ValidatorSet{}) + require.NoError(t, err) + + h, err := dbStore.SignedHeaderAfter(1) + require.NoError(t, err) + if assert.NotNil(t, h) { + assert.EqualValues(t, 2, h.Height) + } +} diff --git a/lite2/store/errors.go b/lite2/store/errors.go new file mode 100644 index 000000000..8a587047b --- /dev/null +++ b/lite2/store/errors.go @@ -0,0 +1,12 @@ +package store + +import "errors" + +var ( + // ErrSignedHeaderNotFound is returned when a store does not have the + // requested header. + ErrSignedHeaderNotFound = errors.New("signed header not found") + // ErrValidatorSetNotFound is returned when a store does not have the + // requested validator set. + ErrValidatorSetNotFound = errors.New("validator set not found") +) diff --git a/lite2/store/store.go b/lite2/store/store.go index b95534fc1..33b94821d 100644 --- a/lite2/store/store.go +++ b/lite2/store/store.go @@ -21,14 +21,14 @@ type Store interface { // // height must be > 0. // - // If SignedHeader is not found, an error is returned. + // If SignedHeader is not found, ErrSignedHeaderNotFound is returned. SignedHeader(height int64) (*types.SignedHeader, error) // ValidatorSet returns the ValidatorSet that corresponds to height. // // height must be > 0. // - // If ValidatorSet is not found, an error is returned. + // If ValidatorSet is not found, ErrValidatorSetNotFound is returned. ValidatorSet(height int64) (*types.ValidatorSet, error) // LastSignedHeaderHeight returns the last (newest) SignedHeader height. @@ -40,4 +40,9 @@ type Store interface { // // If the store is empty, -1 and nil error are returned. FirstSignedHeaderHeight() (int64, error) + + // SignedHeaderAfter returns the SignedHeader after the certain height. + // + // height must be > 0 && <= LastSignedHeaderHeight. + SignedHeaderAfter(height int64) (*types.SignedHeader, error) } diff --git a/lite2/test_helpers.go b/lite2/test_helpers.go index 872704294..11074f8c0 100644 --- a/lite2/test_helpers.go +++ b/lite2/test_helpers.go @@ -147,3 +147,16 @@ func (pkz privKeys) GenSignedHeader(chainID string, height int64, bTime time.Tim Commit: pkz.signHeader(header, first, last), } } + +// GenSignedHeaderLastBlockID calls genHeader and signHeader and combines them into a SignedHeader. +func (pkz privKeys) GenSignedHeaderLastBlockID(chainID string, height int64, bTime time.Time, txs types.Txs, + valset, nextValset *types.ValidatorSet, appHash, consHash, resHash []byte, first, last int, + lastBlockID types.BlockID) *types.SignedHeader { + + header := genHeader(chainID, height, bTime, txs, valset, nextValset, appHash, consHash, resHash) + header.LastBlockID = lastBlockID + return &types.SignedHeader{ + Header: header, + Commit: pkz.signHeader(header, first, last), + } +} From af37db39b0c68ec7e070333ee6b57cc778ac7d71 Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Thu, 6 Feb 2020 15:36:13 +0100 Subject: [PATCH 29/45] lite2: cross-check new header with all witnesses (#4373) As opposed to checking a random witness, all witnesses provided should be used as a reference against the header provided by the primary node. This increases security (at the tradeoff of speed) but also gives control to the user. The more witnesses provided, the more secure the lite client can be. --- lite2/client.go | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/lite2/client.go b/lite2/client.go index c46160712..c6e2077dd 100644 --- a/lite2/client.go +++ b/lite2/client.go @@ -11,7 +11,6 @@ import ( "github.com/tendermint/tendermint/libs/log" tmmath "github.com/tendermint/tendermint/libs/math" - tmrand "github.com/tendermint/tendermint/libs/rand" "github.com/tendermint/tendermint/lite2/provider" "github.com/tendermint/tendermint/lite2/store" "github.com/tendermint/tendermint/types" @@ -558,7 +557,7 @@ func (c *Client) VerifyHeader(newHeader *types.SignedHeader, newVals *types.Vali return errors.Errorf("header at more recent height #%d exists", c.trustedHeader.Height) } - if err := c.compareNewHeaderWithRandomWitness(newHeader); err != nil { + if err := c.compareNewHeaderWithWitnesses(newHeader); err != nil { c.logger.Error("Error when comparing new header with one from a witness", "err", err) return err } @@ -855,32 +854,33 @@ func (c *Client) backwards(toHeight int64, fromHeader *types.SignedHeader, now t return trustedHeader, nil } -// compare header with one from a random witness. -func (c *Client) compareNewHeaderWithRandomWitness(h *types.SignedHeader) error { +// compare header with all witnesses provided. +func (c *Client) compareNewHeaderWithWitnesses(h *types.SignedHeader) error { c.providerMutex.Lock() + defer c.providerMutex.Unlock() // 0. Check witnesses exist if len(c.witnesses) == 0 { return errors.New("could not find any witnesses") } - // 1. Pick a witness. - witness := c.witnesses[tmrand.Intn(len(c.witnesses))] - c.providerMutex.Unlock() + // 1. Loop through all witnesses. + for _, witness := range c.witnesses { - // 2. Fetch the header. - altH, err := witness.SignedHeader(h.Height) - if err != nil { - return errors.Wrapf(err, - "failed to obtain header #%d from the witness %v", h.Height, witness) - } + // 2. Fetch the header. + altH, err := witness.SignedHeader(h.Height) + if err != nil { + return errors.Wrapf(err, + "failed to obtain header #%d from the witness %v", h.Height, witness) + } - // 3. Compare hashes. - if !bytes.Equal(h.Hash(), altH.Hash()) { - // TODO: One of the providers is lying. Send the evidence to fork - // accountability server. - return errors.Errorf( - "header hash %X does not match one %X from the witness %v", - h.Hash(), altH.Hash(), witness) + // 3. Compare hashes. + if !bytes.Equal(h.Hash(), altH.Hash()) { + // TODO: One of the providers is lying. Send the evidence to fork + // accountability server. + return errors.Errorf( + "header hash %X does not match one %X from the witness %v", + h.Hash(), altH.Hash(), witness) + } } return nil From 3e2f29988586ab78449fd96120ef6fe7b2114ffa Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 6 Feb 2020 16:51:30 +0100 Subject: [PATCH 30/45] deps: bump google.golang.org/grpc from 1.27.0 to 1.27.1 (#4372) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.27.0 to 1.27.1. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.27.0...v1.27.1) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 93f65f57d..b52f7ca4b 100644 --- a/go.mod +++ b/go.mod @@ -32,5 +32,5 @@ require ( golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 golang.org/x/net v0.0.0-20190628185345-da137c7871d7 golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a // indirect - google.golang.org/grpc v1.27.0 + google.golang.org/grpc v1.27.1 ) diff --git a/go.sum b/go.sum index ce0ff1081..19cfd4cb8 100644 --- a/go.sum +++ b/go.sum @@ -290,6 +290,8 @@ google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 66a544a640b191f45b8a2433b1d2748e5f891d8e Mon Sep 17 00:00:00 2001 From: Erik Grinaker Date: Fri, 7 Feb 2020 12:53:28 +0100 Subject: [PATCH 31/45] Fix broken /docs/spec links (#4376) --- README.md | 2 +- consensus/state.go | 4 ++-- crypto/README.md | 2 +- .../adr-044-lite-client-with-weak-subjectivity.md | 4 ++-- docs/architecture/adr-045-abci-evidence.md | 2 +- docs/interviews/tendermint-bft.md | 2 +- docs/tendermint-core/secure-p2p.md | 2 +- p2p/README.md | 10 +++++----- types/block.go | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 9e87b4962..bd3cc866e 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ For more information on upgrading, see [UPGRADING.md](./UPGRADING.md) ### Tendermint Core For details about the blockchain data structures and the p2p protocols, see the -[Tendermint specification](/docs/spec). +[Tendermint specification](https://docs.tendermint.com/master/spec/). For details on using the software, see the [documentation](/docs/) which is also hosted at: https://docs.tendermint.com/master/ diff --git a/consensus/state.go b/consensus/state.go index 5055fdd68..05c70b652 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -1864,10 +1864,10 @@ func (cs *State) voteTime() time.Time { now := tmtime.Now() minVoteTime := now // TODO: We should remove next line in case we don't vote for v in case cs.ProposalBlock == nil, - // even if cs.LockedBlock != nil. See https://github.com/tendermint/spec. + // even if cs.LockedBlock != nil. See https://docs.tendermint.com/master/spec/. timeIotaMs := time.Duration(cs.state.ConsensusParams.Block.TimeIotaMs) * time.Millisecond if cs.LockedBlock != nil { - // See the BFT time spec https://tendermint.com/docs/spec/consensus/bft-time.html + // See the BFT time spec https://docs.tendermint.com/master/spec/consensus/bft-time.html minVoteTime = cs.LockedBlock.Time.Add(timeIotaMs) } else if cs.ProposalBlock != nil { minVoteTime = cs.ProposalBlock.Time.Add(timeIotaMs) diff --git a/crypto/README.md b/crypto/README.md index 18a400a0f..cfbceb449 100644 --- a/crypto/README.md +++ b/crypto/README.md @@ -14,7 +14,7 @@ If you want to decode bytes into one of the types, but don't care about the spec ## Binary encoding -For Binary encoding, please refer to the [Tendermint encoding specification](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/encoding.md). +For Binary encoding, please refer to the [Tendermint encoding specification](https://docs.tendermint.com/master/spec/blockchain/encoding.html). ## JSON Encoding diff --git a/docs/architecture/adr-044-lite-client-with-weak-subjectivity.md b/docs/architecture/adr-044-lite-client-with-weak-subjectivity.md index 066f68f7f..2109e2952 100644 --- a/docs/architecture/adr-044-lite-client-with-weak-subjectivity.md +++ b/docs/architecture/adr-044-lite-client-with-weak-subjectivity.md @@ -84,7 +84,7 @@ The linear verification algorithm requires downloading all headers between the `TrustHeight` and the `LatestHeight`. The lite client downloads the full header for the provided `TrustHeight` and then proceeds to download `N+1` headers and applies the [Tendermint validation -rules](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/blockchain.md#validation) +rules](https://docs.tendermint.com/master/spec/blockchain/blockchain.html#validation) to each block. ### Bisecting Verification @@ -119,7 +119,7 @@ network usage. --- Check out the formal specification -[here](https://github.com/tendermint/tendermint/blob/master/docs/spec/consensus/light-client.md). +[here](https://docs.tendermint.com/master/spec/consensus/light-client.html). ## Status diff --git a/docs/architecture/adr-045-abci-evidence.md b/docs/architecture/adr-045-abci-evidence.md index 12f55986a..3cb91be75 100644 --- a/docs/architecture/adr-045-abci-evidence.md +++ b/docs/architecture/adr-045-abci-evidence.md @@ -18,7 +18,7 @@ graceful here, but that's for another day. It's possible to fool lite clients without there being a fork on the main chain - so called Fork-Lite. See the -[fork accountability](https://github.com/tendermint/tendermint/blob/master/docs/spec/consensus/fork-accountability.md) +[fork accountability](https://docs.tendermint.com/master/spec/consensus/fork-accountability.html) document for more details. For a sequential lite client, this can happen via equivocation or amnesia attacks. For a skipping lite client this can also happen via lunatic validator attacks. There must be some way for applications to punish diff --git a/docs/interviews/tendermint-bft.md b/docs/interviews/tendermint-bft.md index 8b3ad5743..6d3a940cc 100644 --- a/docs/interviews/tendermint-bft.md +++ b/docs/interviews/tendermint-bft.md @@ -247,4 +247,4 @@ keep the list of new nodes it discovers, and when you need to establish connection to a peer, you'll look to address book and get some addresses from there. There's categorization/ranking of nodes there. -[1]: https://github.com/tendermint/tendermint/blob/master/docs/spec/reactors/consensus/proposer-selection.md +[1]: https://docs.tendermint.com/master/spec/reactors/consensus/proposer-selection.html diff --git a/docs/tendermint-core/secure-p2p.md b/docs/tendermint-core/secure-p2p.md index 07dba46d0..96df41bc6 100644 --- a/docs/tendermint-core/secure-p2p.md +++ b/docs/tendermint-core/secure-p2p.md @@ -67,7 +67,7 @@ Authenticated encryption is enabled by default. ## Specification -The full p2p specification can be found [here](https://github.com/tendermint/tendermint/tree/master/docs/spec/p2p). +The full p2p specification can be found [here](https://docs.tendermint.com/master/spec/p2p/). ## Additional Reading diff --git a/p2p/README.md b/p2p/README.md index df4c2ae01..9ba7303fa 100644 --- a/p2p/README.md +++ b/p2p/README.md @@ -4,8 +4,8 @@ The p2p package provides an abstraction around peer-to-peer communication. Docs: -- [Connection](https://github.com/tendermint/tendermint/blob/master/docs/spec/p2p/connection.md) for details on how connections and multiplexing work -- [Peer](https://github.com/tendermint/tendermint/blob/master/docs/spec/p2p/peer.md) for details on peer ID, handshakes, and peer exchange -- [Node](https://github.com/tendermint/tendermint/blob/master/docs/spec/p2p/node.md) for details about different types of nodes and how they should work -- [Pex](https://github.com/tendermint/tendermint/blob/master/docs/spec/reactors/pex/pex.md) for details on peer discovery and exchange -- [Config](https://github.com/tendermint/tendermint/blob/master/docs/spec/p2p/config.md) for details on some config option +- [Connection](https://docs.tendermint.com/master/spec/p2p/connection.html) for details on how connections and multiplexing work +- [Peer](https://docs.tendermint.com/master/spec/p2p/node.html) for details on peer ID, handshakes, and peer exchange +- [Node](https://docs.tendermint.com/master/spec/p2p/node.html) for details about different types of nodes and how they should work +- [Pex](https://docs.tendermint.com/master/spec/reactors/pex/pex.html) for details on peer discovery and exchange +- [Config](https://docs.tendermint.com/master/spec/p2p/config.html) for details on some config option diff --git a/types/block.go b/types/block.go index 206ea4414..40a6e5472 100644 --- a/types/block.go +++ b/types/block.go @@ -319,7 +319,7 @@ func MaxDataBytesUnknownEvidence(maxBytes int64, valsCount int) int64 { // NOTE: changes to the Header should be duplicated in: // - header.Hash() // - abci.Header -// - /docs/spec/blockchain/blockchain.md +// - https://github.com/tendermint/spec/spec/blockchain/blockchain.md type Header struct { // basic block info Version version.Consensus `json:"version"` From b2832c66afa2324cb38e288d7789469c0b7d6249 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Fri, 7 Feb 2020 14:37:20 +0100 Subject: [PATCH 32/45] lite2: validate TrustOptions, add NewClientFromTrustedStore (#4374) * validate trust options * add NewClientFromTrustedStore func * make maxRetryAttempts an option Closes #4370 * hash size should be equal to tmhash.Size * make maxRetryAttempts uint * make maxRetryAttempts uint16 maxRetryAttempts possible - 68 years * we do not store trustingPeriod * added test to create client from trusted store * remove header and vals from primary to make sure we're restoring them from the DB --- lite2/client.go | 84 +++++++++++++++++++++++++++++++++++--------- lite2/client_test.go | 41 +++++++++++++++++++++ 2 files changed, 109 insertions(+), 16 deletions(-) diff --git a/lite2/client.go b/lite2/client.go index c6e2077dd..509f50534 100644 --- a/lite2/client.go +++ b/lite2/client.go @@ -9,6 +9,7 @@ import ( "github.com/pkg/errors" + "github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/libs/log" tmmath "github.com/tendermint/tendermint/libs/math" "github.com/tendermint/tendermint/lite2/provider" @@ -43,6 +44,23 @@ type TrustOptions struct { Hash []byte } +// ValidateBasic performs basic validation. +func (opts TrustOptions) ValidateBasic() error { + if opts.Period <= 0 { + return errors.New("negative or zero period") + } + if opts.Height <= 0 { + return errors.New("negative or zero height") + } + if len(opts.Hash) != tmhash.Size { + return errors.Errorf("expected hash size to be %d bytes, got %d bytes", + tmhash.Size, + len(opts.Hash), + ) + } + return nil +} + type mode byte const ( @@ -51,7 +69,7 @@ const ( defaultUpdatePeriod = 5 * time.Second defaultRemoveNoLongerTrustedHeadersPeriod = 24 * time.Hour - maxRetryAttempts = 10 + defaultMaxRetryAttempts = 10 ) // Option sets a parameter for the light client. @@ -115,6 +133,14 @@ func Logger(l log.Logger) Option { } } +// MaxRetryAttempts option can be used to set max attempts before replacing +// primary with a witness. +func MaxRetryAttempts(max uint16) Option { + return func(c *Client) { + c.maxRetryAttempts = max + } +} + // Client represents a light client, connected to a single chain, which gets // headers from a primary provider, verifies them either sequentially or by // skipping some and stores them in a trusted store (usually, a local FS). @@ -128,6 +154,7 @@ type Client struct { trustingPeriod time.Duration // see TrustOptions.Period verificationMode mode trustLevel tmmath.Fraction + maxRetryAttempts uint16 // see MaxRetryAttempts option // Mutex for locking during changes of the lite clients providers providerMutex sync.Mutex @@ -173,11 +200,47 @@ func NewClient( trustedStore store.Store, options ...Option) (*Client, error) { + if err := trustOptions.ValidateBasic(); err != nil { + return nil, errors.Wrap(err, "invalid TrustOptions") + } + + c, err := NewClientFromTrustedStore(chainID, trustOptions.Period, primary, witnesses, trustedStore, options...) + if err != nil { + return nil, err + } + + if c.trustedHeader != nil { + if err := c.checkTrustedHeaderUsingOptions(trustOptions); err != nil { + return nil, err + } + } + + if c.trustedHeader == nil || c.trustedHeader.Height != trustOptions.Height { + if err := c.initializeWithTrustOptions(trustOptions); err != nil { + return nil, err + } + } + + return c, err +} + +// NewClientFromTrustedStore initializes existing client from the trusted store. +// +// See NewClient +func NewClientFromTrustedStore( + chainID string, + trustingPeriod time.Duration, + primary provider.Provider, + witnesses []provider.Provider, + trustedStore store.Store, + options ...Option) (*Client, error) { + c := &Client{ chainID: chainID, - trustingPeriod: trustOptions.Period, + trustingPeriod: trustingPeriod, verificationMode: skipping, trustLevel: DefaultTrustLevel, + maxRetryAttempts: defaultMaxRetryAttempts, primary: primary, witnesses: witnesses, trustedStore: trustedStore, @@ -213,17 +276,6 @@ func NewClient( if err := c.restoreTrustedHeaderAndNextVals(); err != nil { return nil, err } - if c.trustedHeader != nil { - if err := c.checkTrustedHeaderUsingOptions(trustOptions); err != nil { - return nil, err - } - } - - if c.trustedHeader == nil || c.trustedHeader.Height != trustOptions.Height { - if err := c.initializeWithTrustOptions(trustOptions); err != nil { - return nil, err - } - } return c, nil } @@ -1010,7 +1062,7 @@ func (c *Client) replacePrimaryProvider() error { // signedHeaderFromPrimary retrieves the SignedHeader from the primary provider at the specified height. // Handles dropout by the primary provider by swapping with an alternative provider func (c *Client) signedHeaderFromPrimary(height int64) (*types.SignedHeader, error) { - for attempt := 1; attempt <= maxRetryAttempts; attempt++ { + for attempt := uint16(1); attempt <= c.maxRetryAttempts; attempt++ { c.providerMutex.Lock() h, err := c.primary.SignedHeader(height) c.providerMutex.Unlock() @@ -1039,7 +1091,7 @@ func (c *Client) signedHeaderFromPrimary(height int64) (*types.SignedHeader, err // validatorSetFromPrimary retrieves the ValidatorSet from the primary provider at the specified height. // Handles dropout by the primary provider after 5 attempts by replacing it with an alternative provider func (c *Client) validatorSetFromPrimary(height int64) (*types.ValidatorSet, error) { - for attempt := 1; attempt <= maxRetryAttempts; attempt++ { + for attempt := uint16(1); attempt <= c.maxRetryAttempts; attempt++ { c.providerMutex.Lock() vals, err := c.primary.ValidatorSet(height) c.providerMutex.Unlock() @@ -1060,6 +1112,6 @@ func (c *Client) validatorSetFromPrimary(height int64) (*types.ValidatorSet, err // exponential backoff (with jitter) // 0.5s -> 2s -> 4.5s -> 8s -> 12.5 with 1s variation -func backoffTimeout(attempt int) time.Duration { +func backoffTimeout(attempt uint16) time.Duration { return time.Duration(500*attempt*attempt)*time.Millisecond + time.Duration(rand.Intn(1000))*time.Millisecond } diff --git a/lite2/client_test.go b/lite2/client_test.go index 702473715..c5cfcd957 100644 --- a/lite2/client_test.go +++ b/lite2/client_test.go @@ -914,6 +914,7 @@ func TestProvider_Replacement(t *testing.T) { dbs.New(dbm.NewMemDB(), chainID), UpdatePeriod(0), Logger(log.TestingLogger()), + MaxRetryAttempts(1), ) require.NoError(t, err) err = c.Start() @@ -986,3 +987,43 @@ func TestProvider_TrustedHeaderFetchesMissingHeader(t *testing.T) { assert.Error(t, err) assert.Nil(t, h) } + +func Test_NewClientFromTrustedStore(t *testing.T) { + const ( + chainID = "Test_NewClientFromTrustedStore" + ) + + var ( + keys = genPrivKeys(4) + // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! + vals = keys.ToValidators(20, 10) + bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") + header = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) + primary = mockp.New( + chainID, + map[int64]*types.SignedHeader{}, + map[int64]*types.ValidatorSet{}, + ) + ) + + // 1) Initiate DB and fill with a "trusted" header + db := dbs.New(dbm.NewMemDB(), chainID) + err := db.SaveSignedHeaderAndNextValidatorSet(header, vals) + require.NoError(t, err) + + // 2) Initialize Lite Client from Trusted Store + c, err := NewClientFromTrustedStore( + chainID, + 1*time.Hour, + primary, + []provider.Provider{primary}, + db, + ) + require.NoError(t, err) + + // 3) Check header exists through the lite clients eyes + h, err := c.TrustedHeader(1, bTime.Add(1*time.Second)) + assert.NoError(t, err) + assert.EqualValues(t, 1, h.Height) +} From 5ac81eb1986623d91decbdf3c9bc692fe4f5349b Mon Sep 17 00:00:00 2001 From: Erik Grinaker Date: Fri, 7 Feb 2020 15:00:19 +0100 Subject: [PATCH 33/45] docs: fix incorrect link (#4377) --- types/block.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/block.go b/types/block.go index 40a6e5472..4f61a2bc9 100644 --- a/types/block.go +++ b/types/block.go @@ -319,7 +319,7 @@ func MaxDataBytesUnknownEvidence(maxBytes int64, valsCount int) int64 { // NOTE: changes to the Header should be duplicated in: // - header.Hash() // - abci.Header -// - https://github.com/tendermint/spec/spec/blockchain/blockchain.md +// - https://github.com/tendermint/spec/blob/master/spec/blockchain/blockchain.md type Header struct { // basic block info Version version.Consensus `json:"version"` From aeb6cc475e14c9b4c4455111f6dfb54672507006 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Fri, 7 Feb 2020 16:31:46 +0100 Subject: [PATCH 34/45] lite2: return if there are no headers in RemoveNoLongerTrustedHeaders (#4378) --- lite2/client.go | 8 +++++++- lite2/client_test.go | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lite2/client.go b/lite2/client.go index 509f50534..5dc1878eb 100644 --- a/lite2/client.go +++ b/lite2/client.go @@ -960,11 +960,14 @@ func (c *Client) removeNoLongerTrustedHeadersRoutine() { // Exposed for testing. func (c *Client) RemoveNoLongerTrustedHeaders(now time.Time) { // 1) Get the oldest height. - oldestHeight, err := c.trustedStore.FirstSignedHeaderHeight() + oldestHeight, err := c.FirstTrustedHeight() if err != nil { c.logger.Error("can't get first trusted height", "err", err) return } + if oldestHeight == -1 { // no headers yet => wait + return + } // 2) Get the latest height. latestHeight, err := c.LastTrustedHeight() @@ -972,6 +975,9 @@ func (c *Client) RemoveNoLongerTrustedHeaders(now time.Time) { c.logger.Error("can't get last trusted height", "err", err) return } + if latestHeight == -1 { // no headers yet => wait + return + } // 3) Remove all headers that are outside of the trusting period. for height := oldestHeight; height <= latestHeight; height++ { diff --git a/lite2/client_test.go b/lite2/client_test.go index c5cfcd957..3f7038e89 100644 --- a/lite2/client_test.go +++ b/lite2/client_test.go @@ -307,6 +307,12 @@ func TestClientRemovesNoLongerTrustedHeaders(t *testing.T) { dbs.New(dbm.NewMemDB(), chainID), Logger(log.TestingLogger()), ) + + assert.NotPanics(t, func() { + now := bTime.Add(4 * time.Hour).Add(1 * time.Second) + c.RemoveNoLongerTrustedHeaders(now) + }) + require.NoError(t, err) err = c.Start() require.NoError(t, err) From 31fd99a91a3732e7a9ddbfedee5ad6fc68091062 Mon Sep 17 00:00:00 2001 From: Marko Date: Tue, 11 Feb 2020 10:31:15 +0100 Subject: [PATCH 35/45] proto: add buf and protogen script (#4369) * proto: add buf and protogen script - add buf with minimal changes - add protogen script to easier generate proto files Signed-off-by: Marko Baricevic * add protoc needs * add some needed shell cmds * remove buf from tools as it is not needed everytime * add proto lint and breakage to ci * add section in changelog and upgrading files * address pr comments * remove space in circle config * remove spaces in makefile comment * add section on contributing on how to work with proto * bump buf to 0.7 * test bufbuild image * test install make in bufbuild image * revert to tendermintdev image * Update Makefile Co-Authored-By: Anton Kaliaev Co-authored-by: Anton Kaliaev --- .circleci/config.yml | 18 ++ CHANGELOG_PENDING.md | 4 + CONTRIBUTING.md | 4 + Makefile | 77 ++++--- UPGRADING.md | 8 + abci/types/types.pb.go | 298 ++++++++++++------------- abci/types/types.proto | 6 +- buf.yaml | 16 ++ crypto/merkle/merkle.pb.go | 84 +++---- crypto/merkle/merkle.proto | 2 +- libs/kv/types.pb.go | 22 +- libs/kv/types.proto | 2 +- rpc/grpc/types.pb.go | 104 ++++----- rpc/grpc/types.proto | 6 +- scripts/protocgen.sh | 11 + third_party/proto/gogoproto/gogo.proto | 147 ++++++++++++ tools.mk | 27 +++ 17 files changed, 512 insertions(+), 324 deletions(-) create mode 100644 buf.yaml create mode 100644 scripts/protocgen.sh create mode 100644 third_party/proto/gogoproto/gogo.proto diff --git a/.circleci/config.yml b/.circleci/config.yml index 239043d40..e0d8129a9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,6 +14,9 @@ executors: - image: tendermintdev/docker-website-deployment environment: AWS_REGION: us-east-1 + protoc: + docker: + - image: tendermintdev/docker-protoc commands: run_test: @@ -72,6 +75,19 @@ jobs: root: "/tmp/bin" paths: - "." + proto-lint: + executor: protoc + steps: + - checkout + - run: + command: make proto-lint + + proto-breakage: + executor: protoc + steps: + - checkout + - run: + command: make proto-check-breaking test_abci_apps: executor: golang @@ -391,6 +407,8 @@ workflows: - test_abci_apps: requires: - setup_dependencies + - proto-breakage + - proto-lint - test_abci_cli: requires: - setup_dependencies diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index fa7624986..50ce5d8d6 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -22,6 +22,10 @@ program](https://hackerone.com/tendermint). ### IMPROVEMENTS: +- [proto] [\#4369] Add [buf](https://buf.build/) for usage with linting and checking if there are breaking changes with the master branch. +- [proto] [\#4369] Add `make proto-gen` cmd to generate proto stubs outside of GOPATH. + + ### BUG FIXES: - [node] [#\4311] Use `GRPCMaxOpenConnections` when creating the gRPC server, not `MaxOpenConnections` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 52d5532f5..7b348ad76 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -98,6 +98,10 @@ need. Instead of running `go get -u=patch`, which will update anything, specify exactly the dependency you want to update, eg. `GO111MODULE=on go get -u github.com/tendermint/go-amino@master`. +## Protobuf + +When working with [protobuf](https://developers.google.com/protocol-buffers) there are a few things you should know. We use [buf](https://buf.build/) for our linting and breaking changes checking. If you would like to run linting and check if the changes you have made are breaking then you will have to install the needed dependencies with `make buf`. Then the linting cmd will be `make proto-lint` and the breaking changes check will be `make proto-check-breaking`. To generate new stubs based off of your changes you can run `make proto-gen` (you can do this outside of GOPATH). + ## Vagrant If you are a [Vagrant](https://www.vagrantup.com/) user, you can get started diff --git a/Makefile b/Makefile index f6ca17d18..540d157b8 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,6 @@ PACKAGES=$(shell go list ./...) OUTPUT?=build/tendermint -INCLUDE = -I=${GOPATH}/src/github.com/tendermint/tendermint -I=${GOPATH}/src -I=${GOPATH}/src/github.com/gogo/protobuf/protobuf BUILD_TAGS?='tendermint' LD_FLAGS = -X github.com/tendermint/tendermint/version.GitCommit=`git rev-parse --short=8 HEAD` -s -w BUILD_FLAGS = -mod=readonly -ldflags "$(LD_FLAGS)" @@ -12,8 +11,9 @@ all: check build test install include tools.mk include tests.mk -######################################## -### Build Tendermint +############################################################################### +### Build Tendermint ### +############################################################################### build: CGO_ENABLED=0 go build $(BUILD_FLAGS) -tags $(BUILD_TAGS) -o $(OUTPUT) ./cmd/tendermint/ @@ -30,26 +30,31 @@ install: install_c: CGO_ENABLED=1 go install $(BUILD_FLAGS) -tags "$(BUILD_TAGS) cleveldb" ./cmd/tendermint -######################################## -### Protobuf +############################################################################### +### Protobuf ### +############################################################################### -protoc_all: protoc_libs protoc_merkle protoc_abci protoc_grpc protoc_proto3types +proto-all: proto-gen proto-lint proto-check-breaking -%.pb.go: %.proto +proto-gen: ## If you get the following error, ## "error while loading shared libraries: libprotobuf.so.14: cannot open shared object file: No such file or directory" ## See https://stackoverflow.com/a/25518702 ## Note the $< here is substituted for the %.proto ## Note the $@ here is substituted for the %.pb.go - protoc $(INCLUDE) $< --gogo_out=Mgoogle/protobuf/timestamp.proto=github.com/golang/protobuf/ptypes/timestamp,Mgoogle/protobuf/duration.proto=github.com/golang/protobuf/ptypes/duration,plugins=grpc:../../.. + @sh scripts/protocgen.sh -######################################## -### Build ABCI +proto-lint: + @buf check lint --error-format=json -# see protobuf section above -protoc_abci: abci/types/types.pb.go +proto-check-breaking: + @buf check breaking --against-input '.git#branch=master' -protoc_proto3types: types/proto3/block.pb.go +.PHONY: proto-all proto-gen proto-lint proto-check-breaking + +############################################################################### +### Build ABCI ### +############################################################################### build_abci: @go build -mod=readonly -i ./abci/cmd/... @@ -57,8 +62,9 @@ build_abci: install_abci: @go install -mod=readonly ./abci/cmd/... -######################################## -### Distribution +############################################################################### +### Distribution ### +############################################################################### # dist builds binaries for all platforms and packages them for distribution # TODO add abci to these scripts @@ -86,10 +92,9 @@ get_deps_bin_size: @find $(WORK) -type f -name "*.a" | xargs -I{} du -hxs "{}" | sort -rh | sed -e s:${WORK}/::g > deps_bin_size.log @echo "Results can be found here: $(CURDIR)/deps_bin_size.log" -######################################## -### Libs - -protoc_libs: libs/kv/types.pb.go +############################################################################### +### Libs ### +############################################################################### # generates certificates for TLS testing in remotedb and RPC server gen_certs: clean_certs @@ -105,13 +110,9 @@ clean_certs: rm -f rpc/lib/server/test.crt rm -f rpc/lib/server/test.key -protoc_grpc: rpc/grpc/types.pb.go - -protoc_merkle: crypto/merkle/merkle.pb.go - - -######################################## -### Formatting, linting, and vetting +############################################################################### +### Formatting, linting, and vetting ### +############################################################################### fmt: @go fmt ./... @@ -122,8 +123,9 @@ lint: DESTINATION = ./index.html.md -########################################################### -### Documentation +############################################################################### +### Documentation ### +############################################################################### build-docs: cd docs && \ @@ -142,16 +144,18 @@ sync-docs: aws cloudfront create-invalidation --distribution-id ${CF_DISTRIBUTION_ID} --profile terraform --path "/*" ; .PHONY: sync-docs -########################################################### -### Docker image +############################################################################### +### Docker image ### +############################################################################### build-docker: cp $(OUTPUT) DOCKER/tendermint docker build --label=tendermint --tag="tendermint/tendermint" DOCKER rm -rf DOCKER/tendermint -########################################################### -### Local testnet using docker +############################################################################### +### Local testnet using docker ### +############################################################################### # Build linux binary on other platforms build-linux: tools @@ -176,8 +180,9 @@ localnet-start: localnet-stop build-docker-localnode localnet-stop: docker-compose down -########################################################### -### Remote full-nodes (sentry) using terraform and ansible +############################################################################### +### Remote full-nodes (sentry) using terraform and ansible ### +############################################################################### # Server management sentry-start: @@ -216,7 +221,7 @@ contract-tests: # unless there is a reason not to. # https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html .PHONY: check build build_race build_abci dist install install_abci check_tools tools update_tools draw_deps \ - protoc_abci protoc_libs gen_certs clean_certs grpc_dbserver fmt build-linux localnet-start \ - localnet-stop build-docker build-docker-localnode sentry-start sentry-config sentry-stop protoc_grpc protoc_all \ + gen_certs clean_certs grpc_dbserver fmt build-linux localnet-start \ + localnet-stop build-docker build-docker-localnode sentry-start sentry-config sentry-stop \ build_c install_c test_with_deadlock cleanup_after_test_with_deadlock lint build-contract-tests-hooks contract-tests \ build_c-amazonlinux diff --git a/UPGRADING.md b/UPGRADING.md index bb531d32f..ab2251ea7 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -3,6 +3,14 @@ This guide provides steps to be followed when you upgrade your applications to a newer version of Tendermint Core. +## Unreleased + + + +### Protobuf Changes + +When upgrading to version you will have to fetch the `third_party` directory along with the updated proto files. + ## v0.33.0 This release is not compatible with previous blockchains due to commit becoming signatures only and fields in the header have been removed. diff --git a/abci/types/types.pb.go b/abci/types/types.pb.go index d1a10eb9f..d8445f469 100644 --- a/abci/types/types.pb.go +++ b/abci/types/types.pb.go @@ -2960,156 +2960,156 @@ func init() { proto.RegisterFile("abci/types/types.proto", fileDescriptor_9f1eaa func init() { golang_proto.RegisterFile("abci/types/types.proto", fileDescriptor_9f1eaa49c51fa1ac) } var fileDescriptor_9f1eaa49c51fa1ac = []byte{ - // 2371 bytes of a gzipped FileDescriptorProto + // 2370 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x59, 0x4d, 0x90, 0x1b, 0x47, - 0x15, 0xde, 0xd1, 0x6a, 0xf5, 0xf3, 0xb4, 0xbb, 0x52, 0x3a, 0x4e, 0x22, 0x0b, 0x67, 0xd7, 0x35, - 0xfe, 0x5b, 0xe7, 0x47, 0x0e, 0x0b, 0xa1, 0x62, 0xec, 0x0a, 0xb5, 0x5a, 0x3b, 0x48, 0x15, 0xdb, - 0xd9, 0x8c, 0xed, 0xc5, 0x40, 0x55, 0xa6, 0x5a, 0x9a, 0xb6, 0x34, 0xb5, 0xd2, 0xcc, 0x64, 0xa6, - 0x25, 0x6b, 0x29, 0xee, 0x14, 0x55, 0x1c, 0xb8, 0x50, 0xc5, 0x85, 0x3b, 0x47, 0x0e, 0x1c, 0x72, - 0xe4, 0x98, 0x03, 0x07, 0x0e, 0x9c, 0x0d, 0x2c, 0x9c, 0xa8, 0x1c, 0x29, 0x8a, 0x23, 0xd5, 0xaf, - 0x7b, 0xfe, 0xb4, 0xd2, 0x6a, 0x1c, 0x7c, 0xe3, 0x22, 0x4d, 0x77, 0xbf, 0xf7, 0xba, 0xfb, 0xf5, - 0xeb, 0xf7, 0xbd, 0xf7, 0x1a, 0x5e, 0xa7, 0xdd, 0x9e, 0x7d, 0x83, 0x1f, 0x7b, 0x2c, 0x90, 0xbf, - 0x4d, 0xcf, 0x77, 0xb9, 0x4b, 0x5e, 0xe3, 0xcc, 0xb1, 0x98, 0x3f, 0xb2, 0x1d, 0xde, 0x14, 0x24, - 0x4d, 0x1c, 0x6c, 0xbc, 0xdb, 0xb7, 0xf9, 0x60, 0xdc, 0x6d, 0xf6, 0xdc, 0xd1, 0x8d, 0xbe, 0xdb, - 0x77, 0x6f, 0x20, 0x75, 0x77, 0xfc, 0x14, 0x5b, 0xd8, 0xc0, 0x2f, 0x29, 0xa5, 0x71, 0x2b, 0x41, - 0x1e, 0x0b, 0x4c, 0x7e, 0xf6, 0xfc, 0x63, 0x8f, 0xbb, 0x37, 0x46, 0xcc, 0x3f, 0x1a, 0x32, 0xf5, - 0xa7, 0x98, 0xbf, 0xbd, 0x94, 0x79, 0x68, 0x77, 0x83, 0x1b, 0x47, 0x93, 0xe4, 0xc2, 0x1b, 0xdb, - 0x7d, 0xd7, 0xed, 0x0f, 0x59, 0xbc, 0x30, 0x6e, 0x8f, 0x58, 0xc0, 0xe9, 0xc8, 0x53, 0x04, 0x5b, - 0xb3, 0x04, 0xd6, 0xd8, 0xa7, 0xdc, 0x76, 0x1d, 0x39, 0xae, 0xff, 0x7b, 0x0d, 0x8a, 0x06, 0xfb, - 0x7c, 0xcc, 0x02, 0x4e, 0x3e, 0x80, 0x3c, 0xeb, 0x0d, 0xdc, 0x7a, 0xee, 0xa2, 0xb6, 0x53, 0xd9, - 0xd5, 0x9b, 0x73, 0x95, 0xd2, 0x54, 0xd4, 0x77, 0x7b, 0x03, 0xb7, 0xbd, 0x62, 0x20, 0x07, 0xb9, - 0x05, 0x6b, 0x4f, 0x87, 0xe3, 0x60, 0x50, 0x5f, 0x45, 0xd6, 0x4b, 0x67, 0xb3, 0x7e, 0x24, 0x48, - 0xdb, 0x2b, 0x86, 0xe4, 0x11, 0xd3, 0xda, 0xce, 0x53, 0xb7, 0x9e, 0xcf, 0x32, 0x6d, 0xc7, 0x79, - 0x8a, 0xd3, 0x0a, 0x0e, 0xd2, 0x06, 0x08, 0x18, 0x37, 0x5d, 0x4f, 0x6c, 0xa8, 0xbe, 0x86, 0xfc, - 0xd7, 0xce, 0xe6, 0x7f, 0xc8, 0xf8, 0x27, 0x48, 0xde, 0x5e, 0x31, 0xca, 0x41, 0xd8, 0x10, 0x92, - 0x6c, 0xc7, 0xe6, 0x66, 0x6f, 0x40, 0x6d, 0xa7, 0x5e, 0xc8, 0x22, 0xa9, 0xe3, 0xd8, 0x7c, 0x5f, - 0x90, 0x0b, 0x49, 0x76, 0xd8, 0x10, 0xaa, 0xf8, 0x7c, 0xcc, 0xfc, 0xe3, 0x7a, 0x31, 0x8b, 0x2a, - 0x3e, 0x15, 0xa4, 0x42, 0x15, 0xc8, 0x43, 0x3e, 0x86, 0x4a, 0x97, 0xf5, 0x6d, 0xc7, 0xec, 0x0e, - 0xdd, 0xde, 0x51, 0xbd, 0x84, 0x22, 0x76, 0xce, 0x16, 0xd1, 0x12, 0x0c, 0x2d, 0x41, 0xdf, 0x5e, - 0x31, 0xa0, 0x1b, 0xb5, 0x48, 0x0b, 0x4a, 0xbd, 0x01, 0xeb, 0x1d, 0x99, 0x7c, 0x5a, 0x2f, 0xa3, - 0xa4, 0x2b, 0x67, 0x4b, 0xda, 0x17, 0xd4, 0x8f, 0xa6, 0xed, 0x15, 0xa3, 0xd8, 0x93, 0x9f, 0x42, - 0x2f, 0x16, 0x1b, 0xda, 0x13, 0xe6, 0x0b, 0x29, 0xaf, 0x66, 0xd1, 0xcb, 0x1d, 0x49, 0x8f, 0x72, - 0xca, 0x56, 0xd8, 0x20, 0x77, 0xa1, 0xcc, 0x1c, 0x4b, 0x6d, 0xac, 0x82, 0x82, 0xae, 0x2e, 0xb1, - 0x30, 0xc7, 0x0a, 0xb7, 0x55, 0x62, 0xea, 0x9b, 0x7c, 0x08, 0x85, 0x9e, 0x3b, 0x1a, 0xd9, 0xbc, - 0xbe, 0x8e, 0x32, 0x2e, 0x2f, 0xd9, 0x12, 0xd2, 0xb6, 0x57, 0x0c, 0xc5, 0xd5, 0x2a, 0xc2, 0xda, - 0x84, 0x0e, 0xc7, 0x4c, 0xbf, 0x06, 0x95, 0x84, 0x25, 0x93, 0x3a, 0x14, 0x47, 0x2c, 0x08, 0x68, - 0x9f, 0xd5, 0xb5, 0x8b, 0xda, 0x4e, 0xd9, 0x08, 0x9b, 0xfa, 0x26, 0xac, 0x27, 0xed, 0x56, 0x1f, - 0x45, 0x8c, 0xc2, 0x16, 0x05, 0xe3, 0x84, 0xf9, 0x81, 0x30, 0x40, 0xc5, 0xa8, 0x9a, 0xe4, 0x12, - 0x6c, 0xe0, 0x6e, 0xcd, 0x70, 0x5c, 0xdc, 0xab, 0xbc, 0xb1, 0x8e, 0x9d, 0x87, 0x8a, 0x68, 0x1b, - 0x2a, 0xde, 0xae, 0x17, 0x91, 0xac, 0x22, 0x09, 0x78, 0xbb, 0x9e, 0x22, 0xd0, 0xbf, 0x0b, 0xb5, - 0x59, 0xd3, 0x25, 0x35, 0x58, 0x3d, 0x62, 0xc7, 0x6a, 0x3e, 0xf1, 0x49, 0xce, 0xa9, 0x6d, 0xe1, - 0x1c, 0x65, 0x43, 0xed, 0xf1, 0x77, 0xb9, 0x88, 0x39, 0xb2, 0x56, 0x71, 0xdd, 0x84, 0x93, 0x40, - 0xee, 0xca, 0x6e, 0xa3, 0x29, 0x1d, 0x44, 0x33, 0x74, 0x10, 0xcd, 0x47, 0xa1, 0x07, 0x69, 0x95, - 0xbe, 0x7c, 0xbe, 0xbd, 0xf2, 0xcb, 0xbf, 0x6c, 0x6b, 0x06, 0x72, 0x90, 0xf3, 0xc2, 0xa0, 0xa8, - 0xed, 0x98, 0xb6, 0xa5, 0xe6, 0x29, 0x62, 0xbb, 0x63, 0x91, 0x4f, 0xa1, 0xd6, 0x73, 0x9d, 0x80, - 0x39, 0xc1, 0x38, 0x30, 0x3d, 0xea, 0xd3, 0x51, 0xa0, 0x7c, 0xc1, 0xa2, 0x43, 0xde, 0x0f, 0xc9, - 0x0f, 0x90, 0xda, 0xa8, 0xf6, 0xd2, 0x1d, 0xe4, 0x1e, 0xc0, 0x84, 0x0e, 0x6d, 0x8b, 0x72, 0xd7, - 0x0f, 0xea, 0xf9, 0x8b, 0xab, 0x67, 0x08, 0x3b, 0x0c, 0x09, 0x1f, 0x7b, 0x16, 0xe5, 0xac, 0x95, - 0x17, 0x2b, 0x37, 0x12, 0xfc, 0xe4, 0x2a, 0x54, 0xa9, 0xe7, 0x99, 0x01, 0xa7, 0x9c, 0x99, 0xdd, - 0x63, 0xce, 0x02, 0xf4, 0x17, 0xeb, 0xc6, 0x06, 0xf5, 0xbc, 0x87, 0xa2, 0xb7, 0x25, 0x3a, 0x75, - 0x2b, 0x3a, 0x6d, 0xbc, 0x9a, 0x84, 0x40, 0xde, 0xa2, 0x9c, 0xa2, 0xb6, 0xd6, 0x0d, 0xfc, 0x16, - 0x7d, 0x1e, 0xe5, 0x03, 0xa5, 0x03, 0xfc, 0x26, 0xaf, 0x43, 0x61, 0xc0, 0xec, 0xfe, 0x80, 0xe3, - 0xb6, 0x57, 0x0d, 0xd5, 0x12, 0x07, 0xe3, 0xf9, 0xee, 0x84, 0xa1, 0x77, 0x2b, 0x19, 0xb2, 0xa1, - 0xff, 0x2a, 0x07, 0xaf, 0x9c, 0xba, 0xbe, 0x42, 0xee, 0x80, 0x06, 0x83, 0x70, 0x2e, 0xf1, 0x4d, - 0x6e, 0x09, 0xb9, 0xd4, 0x62, 0xbe, 0xf2, 0xca, 0x6f, 0x2e, 0xd0, 0x40, 0x1b, 0x89, 0xd4, 0xc6, - 0x15, 0x0b, 0x79, 0x0c, 0xb5, 0x21, 0x0d, 0xb8, 0x29, 0x6d, 0xdf, 0x44, 0x2f, 0xbb, 0x7a, 0xa6, - 0x27, 0xb8, 0x47, 0xc3, 0x3b, 0x23, 0x8c, 0x5b, 0x89, 0xdb, 0x1c, 0xa6, 0x7a, 0xc9, 0x13, 0x38, - 0xd7, 0x3d, 0xfe, 0x09, 0x75, 0xb8, 0xed, 0x30, 0xf3, 0xd4, 0x19, 0x6d, 0x2f, 0x10, 0x7d, 0x77, - 0x62, 0x5b, 0xcc, 0xe9, 0x85, 0x87, 0xf3, 0x6a, 0x24, 0x22, 0x3a, 0xbc, 0x40, 0x7f, 0x02, 0x9b, - 0x69, 0x5f, 0x44, 0x36, 0x21, 0xc7, 0xa7, 0x4a, 0x23, 0x39, 0x3e, 0x25, 0xdf, 0x81, 0xbc, 0x10, - 0x87, 0xda, 0xd8, 0x5c, 0x08, 0x16, 0x8a, 0xfb, 0xd1, 0xb1, 0xc7, 0x0c, 0xa4, 0xd7, 0xf5, 0xe8, - 0x26, 0x44, 0xfe, 0x69, 0x56, 0xb6, 0x7e, 0x1d, 0xaa, 0x33, 0xae, 0x27, 0x71, 0xac, 0x5a, 0xf2, - 0x58, 0xf5, 0x2a, 0x6c, 0xa4, 0x3c, 0x8c, 0xfe, 0xc7, 0x02, 0x94, 0x0c, 0x16, 0x78, 0xc2, 0x88, - 0x49, 0x1b, 0xca, 0x6c, 0xda, 0x63, 0x12, 0x96, 0xb4, 0x25, 0x4e, 0x5c, 0xf2, 0xdc, 0x0d, 0xe9, - 0x85, 0xd7, 0x8c, 0x98, 0xc9, 0xcd, 0x14, 0x24, 0x5f, 0x5a, 0x26, 0x24, 0x89, 0xc9, 0xb7, 0xd3, - 0x98, 0x7c, 0x79, 0x09, 0xef, 0x0c, 0x28, 0xdf, 0x4c, 0x81, 0xf2, 0xb2, 0x89, 0x53, 0xa8, 0xdc, - 0x99, 0x83, 0xca, 0xcb, 0xb6, 0xbf, 0x00, 0x96, 0x3b, 0x73, 0x60, 0x79, 0x67, 0xe9, 0x5a, 0xe6, - 0xe2, 0xf2, 0xed, 0x34, 0x2e, 0x2f, 0x53, 0xc7, 0x0c, 0x30, 0xdf, 0x9b, 0x07, 0xcc, 0xd7, 0x97, - 0xc8, 0x58, 0x88, 0xcc, 0xfb, 0xa7, 0x90, 0xf9, 0xea, 0x12, 0x51, 0x73, 0xa0, 0xb9, 0x93, 0x82, - 0x66, 0xc8, 0xa4, 0x9b, 0x05, 0xd8, 0xfc, 0xd1, 0x69, 0x6c, 0xbe, 0xb6, 0xcc, 0xd4, 0xe6, 0x81, - 0xf3, 0xf7, 0x66, 0xc0, 0xf9, 0xca, 0xb2, 0x5d, 0x2d, 0x44, 0xe7, 0xeb, 0xc2, 0x3f, 0xce, 0xdc, - 0x0c, 0xe1, 0x4b, 0x99, 0xef, 0xbb, 0xbe, 0x02, 0x3e, 0xd9, 0xd0, 0x77, 0x84, 0xc7, 0x8e, 0xed, - 0xff, 0x0c, 0x24, 0xc7, 0x4b, 0x9b, 0xb0, 0x76, 0xfd, 0x0b, 0x2d, 0xe6, 0x45, 0xcf, 0x96, 0xf4, - 0xf6, 0x65, 0xe5, 0xed, 0x13, 0x00, 0x9f, 0x4b, 0x03, 0xfc, 0x36, 0x54, 0x04, 0xa6, 0xcc, 0x60, - 0x37, 0xf5, 0x42, 0xec, 0x26, 0x6f, 0xc1, 0x2b, 0xe8, 0x7f, 0x65, 0x18, 0xa0, 0x1c, 0x49, 0x1e, - 0x1d, 0x49, 0x55, 0x0c, 0x48, 0x0d, 0x4a, 0xa0, 0x78, 0x17, 0x5e, 0x4d, 0xd0, 0x0a, 0xb9, 0x88, - 0x05, 0x12, 0xa4, 0x6a, 0x11, 0xf5, 0x9e, 0xe7, 0xb5, 0x69, 0x30, 0xd0, 0xef, 0xc7, 0x0a, 0x8a, - 0xe3, 0x02, 0x02, 0xf9, 0x9e, 0x6b, 0xc9, 0x7d, 0x6f, 0x18, 0xf8, 0x2d, 0x62, 0x85, 0xa1, 0xdb, - 0xc7, 0xc5, 0x95, 0x0d, 0xf1, 0x29, 0xa8, 0xa2, 0xab, 0x5d, 0x96, 0x77, 0x56, 0xff, 0xbd, 0x16, - 0xcb, 0x8b, 0x43, 0x85, 0x79, 0xa8, 0xae, 0xbd, 0x4c, 0x54, 0xcf, 0xfd, 0x6f, 0xa8, 0xae, 0xff, - 0x4b, 0x8b, 0x8f, 0x34, 0xc2, 0xeb, 0xaf, 0xa7, 0x02, 0x61, 0x5d, 0xb6, 0x63, 0xb1, 0x29, 0xaa, - 0x7c, 0xd5, 0x90, 0x8d, 0x30, 0xd4, 0x2a, 0xe0, 0x31, 0xa4, 0x43, 0xad, 0x22, 0xf6, 0xc9, 0x06, - 0x79, 0x1f, 0x71, 0xde, 0x7d, 0xaa, 0x5c, 0x43, 0x0a, 0x04, 0x65, 0xd6, 0xd7, 0x54, 0xe9, 0xde, - 0x81, 0x20, 0x33, 0x24, 0x75, 0x02, 0x5f, 0xca, 0xa9, 0xb0, 0xe1, 0x02, 0x94, 0xc5, 0xd2, 0x03, - 0x8f, 0xf6, 0x18, 0xde, 0xed, 0xb2, 0x11, 0x77, 0xe8, 0x16, 0x90, 0xd3, 0x3e, 0x86, 0x3c, 0x80, - 0x02, 0x9b, 0x30, 0x87, 0x8b, 0x33, 0x12, 0x6a, 0xbd, 0xb0, 0x10, 0x88, 0x99, 0xc3, 0x5b, 0x75, - 0xa1, 0xcc, 0x7f, 0x3e, 0xdf, 0xae, 0x49, 0x9e, 0x77, 0xdc, 0x91, 0xcd, 0xd9, 0xc8, 0xe3, 0xc7, - 0x86, 0x92, 0xa2, 0xff, 0x2c, 0x27, 0xf0, 0x30, 0xe5, 0x7f, 0xe6, 0xaa, 0x37, 0xbc, 0x34, 0xb9, - 0x44, 0x88, 0x94, 0x4d, 0xe5, 0x6f, 0x02, 0xf4, 0x69, 0x60, 0x3e, 0xa3, 0x0e, 0x67, 0x96, 0xd2, - 0x7b, 0xb9, 0x4f, 0x83, 0x1f, 0x60, 0x87, 0x88, 0x37, 0xc5, 0xf0, 0x38, 0x60, 0x16, 0x1e, 0xc0, - 0xaa, 0x51, 0xec, 0xd3, 0xe0, 0x71, 0xc0, 0xac, 0xc4, 0x5e, 0x8b, 0x2f, 0x63, 0xaf, 0x69, 0x7d, - 0x97, 0x66, 0xf5, 0xfd, 0xf3, 0x5c, 0x7c, 0x3b, 0xe2, 0xf0, 0xe1, 0xff, 0x53, 0x17, 0xbf, 0xc1, - 0x9c, 0x22, 0x0d, 0x02, 0xe4, 0x87, 0xf0, 0x4a, 0x74, 0x2b, 0xcd, 0x31, 0xde, 0xd6, 0xd0, 0x0a, - 0x5f, 0xec, 0x72, 0xd7, 0x26, 0xe9, 0xee, 0x80, 0x7c, 0x06, 0x6f, 0xcc, 0xf8, 0xa0, 0x68, 0x82, - 0xdc, 0x0b, 0xb9, 0xa2, 0xd7, 0xd2, 0xae, 0x28, 0x94, 0x1f, 0x6b, 0x6f, 0xf5, 0xa5, 0xdc, 0x9a, - 0xcb, 0x22, 0x84, 0x4d, 0xc2, 0xdb, 0x3c, 0x9b, 0xd0, 0xff, 0xac, 0x41, 0x75, 0x66, 0x81, 0xe4, - 0x03, 0x58, 0x93, 0x08, 0xac, 0x9d, 0x59, 0x08, 0x41, 0x8d, 0xab, 0x3d, 0x49, 0x06, 0xb2, 0x07, - 0x25, 0xa6, 0xa2, 0x6b, 0xa5, 0x94, 0x2b, 0x4b, 0x82, 0x70, 0xc5, 0x1f, 0xb1, 0x91, 0x3b, 0x50, - 0x8e, 0x54, 0xbf, 0x24, 0x73, 0x8b, 0x4e, 0x4e, 0x09, 0x89, 0x19, 0xf5, 0x7d, 0xa8, 0x24, 0x96, - 0x47, 0xbe, 0x01, 0xe5, 0x11, 0x9d, 0xaa, 0x74, 0x4b, 0x06, 0xd0, 0xa5, 0x11, 0x9d, 0x62, 0xa6, - 0x45, 0xde, 0x80, 0xa2, 0x18, 0xec, 0x53, 0x79, 0x90, 0xab, 0x46, 0x61, 0x44, 0xa7, 0xdf, 0xa7, - 0x81, 0xfe, 0x0b, 0x0d, 0x36, 0xd3, 0xeb, 0x24, 0x6f, 0x03, 0x11, 0xb4, 0xb4, 0xcf, 0x4c, 0x67, - 0x3c, 0x92, 0x18, 0x19, 0x4a, 0xac, 0x8e, 0xe8, 0x74, 0xaf, 0xcf, 0x1e, 0x8c, 0x47, 0x38, 0x75, - 0x40, 0xee, 0x43, 0x2d, 0x24, 0x0e, 0x8b, 0x5d, 0x4a, 0x2b, 0xe7, 0x4f, 0x25, 0xbb, 0x77, 0x14, - 0x81, 0xcc, 0x75, 0x7f, 0x2d, 0x72, 0xdd, 0x4d, 0x29, 0x2f, 0x1c, 0xd1, 0xdf, 0x87, 0xea, 0xcc, - 0x8e, 0x89, 0x0e, 0x1b, 0xde, 0xb8, 0x6b, 0x1e, 0xb1, 0x63, 0x13, 0x55, 0x82, 0xa6, 0x5e, 0x36, - 0x2a, 0xde, 0xb8, 0xfb, 0x31, 0x3b, 0x16, 0x59, 0x47, 0xa0, 0xf7, 0x60, 0x33, 0x9d, 0x4c, 0x09, - 0xe0, 0xf0, 0xdd, 0xb1, 0x63, 0xe1, 0xba, 0xd7, 0x0c, 0xd9, 0x20, 0xb7, 0x60, 0x6d, 0xe2, 0x4a, - 0x6b, 0x3e, 0x2b, 0x7b, 0x3a, 0x74, 0x39, 0x4b, 0xa4, 0x64, 0x92, 0x47, 0x0f, 0x60, 0x0d, 0xed, - 0x52, 0xd8, 0x18, 0xa6, 0x45, 0x2a, 0x70, 0x11, 0xdf, 0xe4, 0x10, 0x80, 0x72, 0xee, 0xdb, 0xdd, - 0x71, 0x2c, 0xbe, 0x9e, 0x14, 0x3f, 0xb4, 0xbb, 0x41, 0xf3, 0x68, 0xd2, 0x3c, 0xa0, 0xb6, 0xdf, - 0xba, 0xa0, 0x2c, 0xfb, 0x5c, 0xcc, 0x93, 0xb0, 0xee, 0x84, 0x24, 0xfd, 0xab, 0x3c, 0x14, 0x64, - 0xba, 0x49, 0x3e, 0x4c, 0x17, 0x3f, 0x2a, 0xbb, 0x5b, 0x8b, 0x96, 0x2f, 0xa9, 0xd4, 0xea, 0xa3, - 0x08, 0xea, 0xea, 0x6c, 0x45, 0xa1, 0x55, 0x39, 0x79, 0xbe, 0x5d, 0xc4, 0xe8, 0xa3, 0x73, 0x27, - 0x2e, 0x2f, 0x2c, 0xca, 0xae, 0xc3, 0x5a, 0x46, 0xfe, 0x85, 0x6b, 0x19, 0x6d, 0xd8, 0x48, 0x84, - 0x5b, 0xb6, 0xa5, 0xf2, 0x94, 0xad, 0xb3, 0x2e, 0x5d, 0xe7, 0x8e, 0x5a, 0x7f, 0x25, 0x0a, 0xc7, - 0x3a, 0x16, 0xd9, 0x49, 0x27, 0xd9, 0x18, 0xb5, 0xc9, 0x70, 0x21, 0x91, 0x37, 0x8b, 0x98, 0x4d, - 0x5c, 0x07, 0x71, 0xf9, 0x25, 0x89, 0x8c, 0x1e, 0x4a, 0xa2, 0x03, 0x07, 0xaf, 0x41, 0x35, 0x0e, - 0x6c, 0x24, 0x49, 0x49, 0x4a, 0x89, 0xbb, 0x91, 0xf0, 0x3d, 0x38, 0xe7, 0xb0, 0x29, 0x37, 0x67, - 0xa9, 0xcb, 0x48, 0x4d, 0xc4, 0xd8, 0x61, 0x9a, 0xe3, 0x0a, 0x6c, 0xc6, 0x2e, 0x14, 0x69, 0x41, - 0x96, 0x3e, 0xa2, 0x5e, 0x24, 0x3b, 0x0f, 0xa5, 0x28, 0xec, 0xac, 0x20, 0x41, 0x91, 0xca, 0x68, - 0x33, 0x0a, 0x64, 0x7d, 0x16, 0x8c, 0x87, 0x5c, 0x09, 0x59, 0x47, 0x1a, 0x0c, 0x64, 0x0d, 0xd9, - 0x8f, 0xb4, 0x97, 0x60, 0x23, 0xf4, 0x2a, 0x92, 0x6e, 0x03, 0xe9, 0xd6, 0xc3, 0x4e, 0x24, 0xba, - 0x0e, 0x35, 0xcf, 0x77, 0x3d, 0x37, 0x60, 0xbe, 0x49, 0x2d, 0xcb, 0x67, 0x41, 0x50, 0xdf, 0x94, - 0xf2, 0xc2, 0xfe, 0x3d, 0xd9, 0xad, 0x7f, 0x13, 0x8a, 0x61, 0x3c, 0x7d, 0x0e, 0xd6, 0x5a, 0x91, - 0x87, 0xcc, 0x1b, 0xb2, 0x21, 0xf0, 0x75, 0xcf, 0xf3, 0x54, 0x75, 0x4d, 0x7c, 0xea, 0x43, 0x28, - 0xaa, 0x03, 0x9b, 0x5b, 0x53, 0xb9, 0x0f, 0xeb, 0x1e, 0xf5, 0xc5, 0x36, 0x92, 0x95, 0x95, 0x45, - 0x19, 0xe1, 0x01, 0xf5, 0xf9, 0x43, 0xc6, 0x53, 0x05, 0x96, 0x0a, 0xf2, 0xcb, 0x2e, 0xfd, 0x26, - 0x6c, 0xa4, 0x68, 0xc4, 0x32, 0xb9, 0xcb, 0xe9, 0x30, 0xbc, 0xe8, 0xd8, 0x88, 0x56, 0x92, 0x8b, - 0x57, 0xa2, 0xdf, 0x82, 0x72, 0x74, 0x56, 0x22, 0xd1, 0x08, 0x55, 0xa1, 0x29, 0xf5, 0xcb, 0x26, - 0x16, 0x91, 0xdc, 0x67, 0xcc, 0x57, 0xd6, 0x2f, 0x1b, 0x3a, 0x4b, 0x38, 0x26, 0x89, 0x66, 0xe4, - 0x36, 0x14, 0x95, 0x63, 0x52, 0xf7, 0x71, 0x51, 0xb9, 0xe8, 0x00, 0x3d, 0x55, 0x58, 0x2e, 0x92, - 0x7e, 0x2b, 0x9e, 0x26, 0x97, 0x9c, 0xe6, 0xa7, 0x50, 0x0a, 0x9d, 0x4f, 0x1a, 0x25, 0xe4, 0x0c, - 0x17, 0x97, 0xa1, 0x84, 0x9a, 0x24, 0x66, 0x14, 0xd6, 0x14, 0xd8, 0x7d, 0x87, 0x59, 0x66, 0x7c, - 0x05, 0x71, 0xce, 0x92, 0x51, 0x95, 0x03, 0xf7, 0xc2, 0xfb, 0xa5, 0xbf, 0x07, 0x05, 0xb9, 0xd6, - 0xb9, 0x2e, 0x6e, 0x1e, 0xb4, 0xfe, 0x43, 0x83, 0x52, 0x08, 0x1f, 0x73, 0x99, 0x52, 0x9b, 0xc8, - 0x7d, 0xdd, 0x4d, 0xbc, 0x7c, 0x97, 0xf4, 0x0e, 0x10, 0xb4, 0x14, 0x73, 0xe2, 0x72, 0xdb, 0xe9, - 0x9b, 0xf2, 0x2c, 0x64, 0x24, 0x58, 0xc3, 0x91, 0x43, 0x1c, 0x38, 0x10, 0xfd, 0x6f, 0x5d, 0x82, - 0x4a, 0xa2, 0xca, 0x45, 0x8a, 0xb0, 0xfa, 0x80, 0x3d, 0xab, 0xad, 0x90, 0x0a, 0x14, 0x0d, 0x86, - 0x35, 0x82, 0x9a, 0xb6, 0xfb, 0x55, 0x11, 0xaa, 0x7b, 0xad, 0xfd, 0xce, 0x9e, 0xe7, 0x0d, 0xed, - 0x1e, 0xe2, 0x19, 0xf9, 0x04, 0xf2, 0x98, 0x27, 0x67, 0x78, 0xdf, 0x69, 0x64, 0x29, 0x38, 0x11, - 0x03, 0xd6, 0x30, 0x9d, 0x26, 0x59, 0x9e, 0x7d, 0x1a, 0x99, 0xea, 0x50, 0x62, 0x91, 0x68, 0x70, - 0x19, 0x5e, 0x83, 0x1a, 0x59, 0x8a, 0x53, 0xe4, 0x33, 0x28, 0xc7, 0x79, 0x72, 0xd6, 0x37, 0xa2, - 0x46, 0xe6, 0xb2, 0x95, 0x90, 0x1f, 0x67, 0x06, 0x59, 0x5f, 0x48, 0x1a, 0x99, 0xeb, 0x35, 0xe4, - 0x09, 0x14, 0xc3, 0x1c, 0x2c, 0xdb, 0x2b, 0x4e, 0x23, 0x63, 0x49, 0x49, 0x1c, 0x9f, 0x4c, 0x9d, - 0xb3, 0x3c, 0x55, 0x35, 0x32, 0xd5, 0xcd, 0xc8, 0x63, 0x28, 0xa8, 0xe0, 0x37, 0xd3, 0xfb, 0x4c, - 0x23, 0x5b, 0xa1, 0x48, 0x28, 0x39, 0x2e, 0x4e, 0x64, 0x7d, 0x9e, 0x6b, 0x64, 0x2e, 0x18, 0x12, - 0x0a, 0x90, 0xc8, 0xa7, 0x33, 0xbf, 0xbb, 0x35, 0xb2, 0x17, 0x02, 0xc9, 0x8f, 0xa1, 0x14, 0x65, - 0x4d, 0x19, 0xdf, 0xbf, 0x1a, 0x59, 0x6b, 0x71, 0xad, 0xce, 0x7f, 0xfe, 0xb6, 0xa5, 0xfd, 0xf6, - 0x64, 0x4b, 0xfb, 0xe2, 0x64, 0x4b, 0xfb, 0xf2, 0x64, 0x4b, 0xfb, 0xd3, 0xc9, 0x96, 0xf6, 0xd7, - 0x93, 0x2d, 0xed, 0x0f, 0x7f, 0xdf, 0xd2, 0x7e, 0xf4, 0xf6, 0xd2, 0x17, 0xe6, 0xf8, 0x75, 0xbc, - 0x5b, 0x40, 0x87, 0xf5, 0xad, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x5a, 0xa5, 0xa9, 0x6d, 0x32, - 0x1f, 0x00, 0x00, + 0x15, 0xde, 0xd1, 0x6a, 0x57, 0xd2, 0xd3, 0xee, 0x4a, 0x69, 0x3b, 0x89, 0x22, 0x92, 0x5d, 0xd7, + 0xf8, 0x6f, 0x9d, 0x04, 0x6d, 0x58, 0x2a, 0x54, 0x8c, 0x5d, 0xa1, 0x56, 0x6b, 0x07, 0xa9, 0x62, + 0x3b, 0x9b, 0xb1, 0xbd, 0x18, 0xa8, 0xca, 0x54, 0x4b, 0xd3, 0x96, 0xa6, 0x56, 0x9a, 0x99, 0xcc, + 0xb4, 0x64, 0x89, 0xe2, 0x4e, 0x51, 0xc5, 0x81, 0x0b, 0x55, 0x5c, 0xb8, 0x73, 0xe4, 0xc0, 0x21, + 0x47, 0x8e, 0x39, 0x70, 0xe0, 0xc0, 0xd9, 0xc0, 0xc2, 0x89, 0xca, 0x91, 0xa2, 0x38, 0x52, 0xfd, + 0xba, 0xe7, 0x4f, 0x2b, 0xad, 0xc6, 0xc1, 0x37, 0x2e, 0xd2, 0x74, 0xf7, 0x7b, 0xaf, 0xbb, 0x5f, + 0xbf, 0x7e, 0xdf, 0x7b, 0xaf, 0xe1, 0x35, 0xda, 0xe9, 0xda, 0x7b, 0x7c, 0xea, 0xb1, 0x40, 0xfe, + 0x36, 0x3c, 0xdf, 0xe5, 0x2e, 0x79, 0x95, 0x33, 0xc7, 0x62, 0xfe, 0xd0, 0x76, 0x78, 0x43, 0x90, + 0x34, 0x70, 0xb0, 0x7e, 0x8d, 0xf7, 0x6d, 0xdf, 0x32, 0x3d, 0xea, 0xf3, 0xe9, 0x1e, 0x52, 0xee, + 0xf5, 0xdc, 0x9e, 0x1b, 0x7f, 0x49, 0xf6, 0x7a, 0xbd, 0xeb, 0x4f, 0x3d, 0xee, 0xee, 0x0d, 0x99, + 0x7f, 0x32, 0x60, 0xea, 0x4f, 0x8d, 0x5d, 0x18, 0xd8, 0x9d, 0x60, 0xef, 0x64, 0x9c, 0x9c, 0xaf, + 0xbe, 0xd3, 0x73, 0xdd, 0xde, 0x80, 0x49, 0x99, 0x9d, 0xd1, 0xd3, 0x3d, 0x6e, 0x0f, 0x59, 0xc0, + 0xe9, 0xd0, 0x53, 0x04, 0xdb, 0xb3, 0x04, 0xd6, 0xc8, 0xa7, 0xdc, 0x76, 0x1d, 0x39, 0xae, 0xff, + 0x7b, 0x0d, 0x0a, 0x06, 0xfb, 0x7c, 0xc4, 0x02, 0x4e, 0x3e, 0x80, 0x3c, 0xeb, 0xf6, 0xdd, 0x5a, + 0xee, 0x92, 0xb6, 0x5b, 0xde, 0xd7, 0x1b, 0x73, 0xf7, 0xd2, 0x50, 0xd4, 0x77, 0xbb, 0x7d, 0xb7, + 0xb5, 0x62, 0x20, 0x07, 0xb9, 0x05, 0x6b, 0x4f, 0x07, 0xa3, 0xa0, 0x5f, 0x5b, 0x45, 0xd6, 0xcb, + 0xe7, 0xb3, 0x7e, 0x24, 0x48, 0x5b, 0x2b, 0x86, 0xe4, 0x11, 0xd3, 0xda, 0xce, 0x53, 0xb7, 0x96, + 0xcf, 0x32, 0x6d, 0xdb, 0x79, 0x8a, 0xd3, 0x0a, 0x0e, 0xd2, 0x02, 0x08, 0x18, 0x37, 0x5d, 0x4f, + 0x6c, 0xa8, 0xb6, 0x86, 0xfc, 0xd7, 0xcf, 0xe7, 0x7f, 0xc8, 0xf8, 0x27, 0x48, 0xde, 0x5a, 0x31, + 0x4a, 0x41, 0xd8, 0x10, 0x92, 0x6c, 0xc7, 0xe6, 0x66, 0xb7, 0x4f, 0x6d, 0xa7, 0xb6, 0x9e, 0x45, + 0x52, 0xdb, 0xb1, 0xf9, 0xa1, 0x20, 0x17, 0x92, 0xec, 0xb0, 0x21, 0x54, 0xf1, 0xf9, 0x88, 0xf9, + 0xd3, 0x5a, 0x21, 0x8b, 0x2a, 0x3e, 0x15, 0xa4, 0x42, 0x15, 0xc8, 0x43, 0x3e, 0x86, 0x72, 0x87, + 0xf5, 0x6c, 0xc7, 0xec, 0x0c, 0xdc, 0xee, 0x49, 0xad, 0x88, 0x22, 0x76, 0xcf, 0x17, 0xd1, 0x14, + 0x0c, 0x4d, 0x41, 0xdf, 0x5a, 0x31, 0xa0, 0x13, 0xb5, 0x48, 0x13, 0x8a, 0xdd, 0x3e, 0xeb, 0x9e, + 0x98, 0x7c, 0x52, 0x2b, 0xa1, 0xa4, 0xab, 0xe7, 0x4b, 0x3a, 0x14, 0xd4, 0x8f, 0x26, 0xad, 0x15, + 0xa3, 0xd0, 0x95, 0x9f, 0x42, 0x2f, 0x16, 0x1b, 0xd8, 0x63, 0xe6, 0x0b, 0x29, 0x17, 0xb2, 0xe8, + 0xe5, 0x8e, 0xa4, 0x47, 0x39, 0x25, 0x2b, 0x6c, 0x90, 0xbb, 0x50, 0x62, 0x8e, 0xa5, 0x36, 0x56, + 0x46, 0x41, 0xd7, 0x96, 0x58, 0x98, 0x63, 0x85, 0xdb, 0x2a, 0x32, 0xf5, 0x4d, 0x3e, 0x84, 0xf5, + 0xae, 0x3b, 0x1c, 0xda, 0xbc, 0xb6, 0x81, 0x32, 0xae, 0x2c, 0xd9, 0x12, 0xd2, 0xb6, 0x56, 0x0c, + 0xc5, 0xd5, 0x2c, 0xc0, 0xda, 0x98, 0x0e, 0x46, 0x4c, 0xbf, 0x0e, 0xe5, 0x84, 0x25, 0x93, 0x1a, + 0x14, 0x86, 0x2c, 0x08, 0x68, 0x8f, 0xd5, 0xb4, 0x4b, 0xda, 0x6e, 0xc9, 0x08, 0x9b, 0xfa, 0x16, + 0x6c, 0x24, 0xed, 0x56, 0x1f, 0x46, 0x8c, 0xc2, 0x16, 0x05, 0xe3, 0x98, 0xf9, 0x81, 0x30, 0x40, + 0xc5, 0xa8, 0x9a, 0xe4, 0x32, 0x6c, 0xe2, 0x6e, 0xcd, 0x70, 0x5c, 0xdc, 0xab, 0xbc, 0xb1, 0x81, + 0x9d, 0xc7, 0x8a, 0x68, 0x07, 0xca, 0xde, 0xbe, 0x17, 0x91, 0xac, 0x22, 0x09, 0x78, 0xfb, 0x9e, + 0x22, 0xd0, 0xbf, 0x0b, 0xd5, 0x59, 0xd3, 0x25, 0x55, 0x58, 0x3d, 0x61, 0x53, 0x35, 0x9f, 0xf8, + 0x24, 0x17, 0xd5, 0xb6, 0x70, 0x8e, 0x92, 0xa1, 0xf6, 0xf8, 0xbb, 0x5c, 0xc4, 0x1c, 0x59, 0xab, + 0xb8, 0x6e, 0xc2, 0x49, 0x20, 0x77, 0x79, 0xbf, 0xde, 0x90, 0x0e, 0xa2, 0x11, 0x3a, 0x88, 0xc6, + 0xa3, 0xd0, 0x83, 0x34, 0x8b, 0x5f, 0x3e, 0xdf, 0x59, 0xf9, 0xe5, 0x5f, 0x76, 0x34, 0x03, 0x39, + 0xc8, 0x1b, 0xc2, 0xa0, 0xa8, 0xed, 0x98, 0xb6, 0xa5, 0xe6, 0x29, 0x60, 0xbb, 0x6d, 0x91, 0x4f, + 0xa1, 0xda, 0x75, 0x9d, 0x80, 0x39, 0xc1, 0x28, 0x10, 0x6e, 0x8e, 0x0e, 0x03, 0xe5, 0x0b, 0x16, + 0x1d, 0xf2, 0x61, 0x48, 0x7e, 0x84, 0xd4, 0x46, 0xa5, 0x9b, 0xee, 0x20, 0xf7, 0x00, 0xc6, 0x74, + 0x60, 0x5b, 0x94, 0xbb, 0x7e, 0x50, 0xcb, 0x5f, 0x5a, 0x3d, 0x47, 0xd8, 0x71, 0x48, 0xf8, 0xd8, + 0xb3, 0x28, 0x67, 0xcd, 0xbc, 0x58, 0xb9, 0x91, 0xe0, 0x27, 0xd7, 0xa0, 0x42, 0x3d, 0xcf, 0x0c, + 0x38, 0xe5, 0xcc, 0xec, 0x4c, 0x39, 0x0b, 0xd0, 0x5f, 0x6c, 0x18, 0x9b, 0xd4, 0xf3, 0x1e, 0x8a, + 0xde, 0xa6, 0xe8, 0xd4, 0xad, 0xe8, 0xb4, 0xf1, 0x6a, 0x12, 0x02, 0x79, 0x8b, 0x72, 0x8a, 0xda, + 0xda, 0x30, 0xf0, 0x5b, 0xf4, 0x79, 0x94, 0xf7, 0x95, 0x0e, 0xf0, 0x9b, 0xbc, 0x06, 0xeb, 0x7d, + 0x66, 0xf7, 0xfa, 0x1c, 0xb7, 0xbd, 0x6a, 0xa8, 0x96, 0x38, 0x18, 0xcf, 0x77, 0xc7, 0x0c, 0xbd, + 0x5b, 0xd1, 0x90, 0x0d, 0xfd, 0x57, 0x39, 0x78, 0xe5, 0xcc, 0xf5, 0x15, 0x72, 0xfb, 0x34, 0xe8, + 0x87, 0x73, 0x89, 0x6f, 0x72, 0x4b, 0xc8, 0xa5, 0x16, 0xf3, 0x95, 0x57, 0x7e, 0x6b, 0x81, 0x06, + 0x5a, 0x48, 0xa4, 0x36, 0xae, 0x58, 0xc8, 0x63, 0xa8, 0x0e, 0x68, 0xc0, 0x4d, 0x69, 0xfb, 0x26, + 0x7a, 0xd9, 0xd5, 0x73, 0x3d, 0xc1, 0x3d, 0x1a, 0xde, 0x19, 0x61, 0xdc, 0x4a, 0xdc, 0xd6, 0x20, + 0xd5, 0x4b, 0x9e, 0xc0, 0xc5, 0xce, 0xf4, 0x27, 0xd4, 0xe1, 0xb6, 0xc3, 0xcc, 0x33, 0x67, 0xb4, + 0xb3, 0x40, 0xf4, 0xdd, 0xb1, 0x6d, 0x31, 0xa7, 0x1b, 0x1e, 0xce, 0x85, 0x48, 0x44, 0x74, 0x78, + 0x81, 0xfe, 0x04, 0xb6, 0xd2, 0xbe, 0x88, 0x6c, 0x41, 0x8e, 0x4f, 0x94, 0x46, 0x72, 0x7c, 0x42, + 0xbe, 0x03, 0x79, 0x21, 0x0e, 0xb5, 0xb1, 0xb5, 0x10, 0x2c, 0x14, 0xf7, 0xa3, 0xa9, 0xc7, 0x0c, + 0xa4, 0xd7, 0xf5, 0xe8, 0x26, 0x44, 0xfe, 0x69, 0x56, 0xb6, 0x7e, 0x03, 0x2a, 0x33, 0xae, 0x27, + 0x71, 0xac, 0x5a, 0xf2, 0x58, 0xf5, 0x0a, 0x6c, 0xa6, 0x3c, 0x8c, 0xfe, 0xc7, 0x75, 0x28, 0x1a, + 0x2c, 0xf0, 0x84, 0x11, 0x93, 0x16, 0x94, 0xd8, 0xa4, 0xcb, 0x24, 0x2c, 0x69, 0x4b, 0x9c, 0xb8, + 0xe4, 0xb9, 0x1b, 0xd2, 0x0b, 0xaf, 0x19, 0x31, 0x93, 0x9b, 0x29, 0x48, 0xbe, 0xbc, 0x4c, 0x48, + 0x12, 0x93, 0x6f, 0xa7, 0x31, 0xf9, 0xca, 0x12, 0xde, 0x19, 0x50, 0xbe, 0x99, 0x02, 0xe5, 0x65, + 0x13, 0xa7, 0x50, 0xb9, 0x3d, 0x07, 0x95, 0x97, 0x6d, 0x7f, 0x01, 0x2c, 0xb7, 0xe7, 0xc0, 0xf2, + 0xee, 0xd2, 0xb5, 0xcc, 0xc5, 0xe5, 0xdb, 0x69, 0x5c, 0x5e, 0xa6, 0x8e, 0x19, 0x60, 0xbe, 0x37, + 0x0f, 0x98, 0x6f, 0x2c, 0x91, 0xb1, 0x10, 0x99, 0x0f, 0xcf, 0x20, 0xf3, 0xb5, 0x25, 0xa2, 0xe6, + 0x40, 0x73, 0x3b, 0x05, 0xcd, 0x90, 0x49, 0x37, 0x0b, 0xb0, 0xf9, 0xa3, 0xb3, 0xd8, 0x7c, 0x7d, + 0x99, 0xa9, 0xcd, 0x03, 0xe7, 0xef, 0xcd, 0x80, 0xf3, 0xd5, 0x65, 0xbb, 0x5a, 0x88, 0xce, 0x37, + 0x84, 0x7f, 0x9c, 0xb9, 0x19, 0xc2, 0x97, 0x32, 0xdf, 0x77, 0x7d, 0x05, 0x7c, 0xb2, 0xa1, 0xef, + 0x0a, 0x8f, 0x1d, 0xdb, 0xff, 0x39, 0x48, 0x8e, 0x97, 0x36, 0x61, 0xed, 0xfa, 0x17, 0x5a, 0xcc, + 0x8b, 0x9e, 0x2d, 0xe9, 0xed, 0x4b, 0xca, 0xdb, 0x27, 0x00, 0x3e, 0x97, 0x06, 0xf8, 0x1d, 0x28, + 0x0b, 0x4c, 0x99, 0xc1, 0x6e, 0xea, 0x85, 0xd8, 0x4d, 0xde, 0x86, 0x57, 0xd0, 0xff, 0xca, 0x30, + 0x40, 0x39, 0x92, 0x3c, 0x3a, 0x92, 0x8a, 0x18, 0x90, 0x1a, 0x94, 0x40, 0xf1, 0x4d, 0xb8, 0x90, + 0xa0, 0x15, 0x72, 0x11, 0x0b, 0x24, 0x48, 0x55, 0x23, 0xea, 0x03, 0xcf, 0x6b, 0xd1, 0xa0, 0xaf, + 0xdf, 0x8f, 0x15, 0x14, 0xc7, 0x05, 0x04, 0xf2, 0x5d, 0xd7, 0x92, 0xfb, 0xde, 0x34, 0xf0, 0x5b, + 0xc4, 0x0a, 0x03, 0xb7, 0x87, 0x8b, 0x2b, 0x19, 0xe2, 0x53, 0x50, 0x45, 0x57, 0xbb, 0x24, 0xef, + 0xac, 0xfe, 0x7b, 0x2d, 0x96, 0x17, 0x87, 0x0a, 0xf3, 0x50, 0x5d, 0x7b, 0x99, 0xa8, 0x9e, 0xfb, + 0xdf, 0x50, 0x5d, 0xff, 0x97, 0x16, 0x1f, 0x69, 0x84, 0xd7, 0x5f, 0x4f, 0x05, 0xc2, 0xba, 0x6c, + 0xc7, 0x62, 0x13, 0x54, 0xf9, 0xaa, 0x21, 0x1b, 0x61, 0xa8, 0xb5, 0x8e, 0xc7, 0x90, 0x0e, 0xb5, + 0x0a, 0xd8, 0x27, 0x1b, 0xe4, 0x7d, 0xc4, 0x79, 0xf7, 0xa9, 0x72, 0x0d, 0x29, 0x10, 0x94, 0x49, + 0x5d, 0x43, 0x65, 0x73, 0x47, 0x82, 0xcc, 0x90, 0xd4, 0x09, 0x7c, 0x29, 0xa5, 0xc2, 0x86, 0x37, + 0xa1, 0x24, 0x96, 0x1e, 0x78, 0xb4, 0xcb, 0xf0, 0x6e, 0x97, 0x8c, 0xb8, 0x43, 0xb7, 0x80, 0x9c, + 0xf5, 0x31, 0xe4, 0x01, 0xac, 0xb3, 0x31, 0x73, 0xb8, 0x38, 0x23, 0xa1, 0xd6, 0x37, 0x17, 0x02, + 0x31, 0x73, 0x78, 0xb3, 0x26, 0x94, 0xf9, 0xcf, 0xe7, 0x3b, 0x55, 0xc9, 0xf3, 0xae, 0x3b, 0xb4, + 0x39, 0x1b, 0x7a, 0x7c, 0x6a, 0x28, 0x29, 0xfa, 0xcf, 0x72, 0x02, 0x0f, 0x53, 0xfe, 0x67, 0xae, + 0x7a, 0xc3, 0x4b, 0x93, 0x4b, 0x84, 0x48, 0xd9, 0x54, 0xfe, 0x16, 0x40, 0x8f, 0x06, 0xe6, 0x33, + 0xea, 0x70, 0x66, 0x29, 0xbd, 0x97, 0x7a, 0x34, 0xf8, 0x01, 0x76, 0x88, 0x78, 0x53, 0x0c, 0x8f, + 0x02, 0x66, 0xe1, 0x01, 0xac, 0x1a, 0x85, 0x1e, 0x0d, 0x1e, 0x07, 0xcc, 0x4a, 0xec, 0xb5, 0xf0, + 0x32, 0xf6, 0x9a, 0xd6, 0x77, 0x71, 0x56, 0xdf, 0x3f, 0xcf, 0xc5, 0xb7, 0x23, 0x0e, 0x1f, 0xfe, + 0x3f, 0x75, 0xf1, 0x1b, 0xcc, 0x29, 0xd2, 0x20, 0x40, 0x7e, 0x08, 0xaf, 0x44, 0xb7, 0xd2, 0x1c, + 0xe1, 0x6d, 0x0d, 0xad, 0xf0, 0xc5, 0x2e, 0x77, 0x75, 0x9c, 0xee, 0x0e, 0xc8, 0x67, 0xf0, 0xfa, + 0x8c, 0x0f, 0x8a, 0x26, 0xc8, 0xbd, 0x90, 0x2b, 0x7a, 0x35, 0xed, 0x8a, 0x42, 0xf9, 0xb1, 0xf6, + 0x56, 0x5f, 0xca, 0xad, 0xb9, 0x22, 0x42, 0xd8, 0x24, 0xbc, 0xcd, 0xb3, 0x09, 0xfd, 0xcf, 0x1a, + 0x54, 0x66, 0x16, 0x48, 0x3e, 0x80, 0x35, 0x89, 0xc0, 0xda, 0xb9, 0x85, 0x10, 0xd4, 0xb8, 0xda, + 0x93, 0x64, 0x20, 0x07, 0x50, 0x64, 0x2a, 0xba, 0x56, 0x4a, 0xb9, 0xba, 0x24, 0x08, 0x57, 0xfc, + 0x11, 0x1b, 0xb9, 0x03, 0xa5, 0x48, 0xf5, 0x4b, 0x32, 0xb7, 0xe8, 0xe4, 0x94, 0x90, 0x98, 0x51, + 0x3f, 0x84, 0x72, 0x62, 0x79, 0xe4, 0x1b, 0x50, 0x1a, 0xd2, 0x89, 0x4a, 0xb7, 0x64, 0x00, 0x5d, + 0x1c, 0xd2, 0x09, 0x66, 0x5a, 0xe4, 0x75, 0x28, 0x88, 0xc1, 0x1e, 0x95, 0x07, 0xb9, 0x6a, 0xac, + 0x0f, 0xe9, 0xe4, 0xfb, 0x34, 0xd0, 0x7f, 0xa1, 0xc1, 0x56, 0x7a, 0x9d, 0xe4, 0x1d, 0x20, 0x82, + 0x96, 0xf6, 0x98, 0xe9, 0x8c, 0x86, 0x12, 0x23, 0x43, 0x89, 0x95, 0x21, 0x9d, 0x1c, 0xf4, 0xd8, + 0x83, 0xd1, 0x10, 0xa7, 0x0e, 0xc8, 0x7d, 0xa8, 0x86, 0xc4, 0x61, 0xb1, 0x4b, 0x69, 0xe5, 0x8d, + 0x33, 0xc9, 0xee, 0x1d, 0x45, 0x20, 0x73, 0xdd, 0x5f, 0x8b, 0x5c, 0x77, 0x4b, 0xca, 0x0b, 0x47, + 0xf4, 0xf7, 0xa1, 0x32, 0xb3, 0x63, 0xa2, 0xc3, 0xa6, 0x37, 0xea, 0x98, 0x27, 0x6c, 0x6a, 0xa2, + 0x4a, 0xd0, 0xd4, 0x4b, 0x46, 0xd9, 0x1b, 0x75, 0x3e, 0x66, 0x53, 0x91, 0x75, 0x04, 0x7a, 0x17, + 0xb6, 0xd2, 0xc9, 0x94, 0x00, 0x0e, 0xdf, 0x1d, 0x39, 0x16, 0xae, 0x7b, 0xcd, 0x90, 0x0d, 0x72, + 0x0b, 0xd6, 0xc6, 0xae, 0xb4, 0xe6, 0xf3, 0xb2, 0xa7, 0x63, 0x97, 0xb3, 0x44, 0x4a, 0x26, 0x79, + 0xf4, 0x00, 0xd6, 0xd0, 0x2e, 0x85, 0x8d, 0x61, 0x5a, 0xa4, 0x02, 0x17, 0xf1, 0x4d, 0x8e, 0x01, + 0x28, 0xe7, 0xbe, 0xdd, 0x19, 0xc5, 0xe2, 0x6b, 0x49, 0xf1, 0x03, 0xbb, 0x13, 0x34, 0x4e, 0xc6, + 0x8d, 0x23, 0x6a, 0xfb, 0xcd, 0x37, 0x95, 0x65, 0x5f, 0x8c, 0x79, 0x12, 0xd6, 0x9d, 0x90, 0xa4, + 0x7f, 0x95, 0x87, 0x75, 0x99, 0x6e, 0x92, 0x0f, 0xd3, 0xc5, 0x8f, 0xf2, 0xfe, 0xf6, 0xa2, 0xe5, + 0x4b, 0x2a, 0xb5, 0xfa, 0x28, 0x82, 0xba, 0x36, 0x5b, 0x51, 0x68, 0x96, 0x4f, 0x9f, 0xef, 0x14, + 0x30, 0xfa, 0x68, 0xdf, 0x89, 0xcb, 0x0b, 0x8b, 0xb2, 0xeb, 0xb0, 0x96, 0x91, 0x7f, 0xe1, 0x5a, + 0x46, 0x0b, 0x36, 0x13, 0xe1, 0x96, 0x6d, 0xa9, 0x3c, 0x65, 0xfb, 0xbc, 0x4b, 0xd7, 0xbe, 0xa3, + 0xd6, 0x5f, 0x8e, 0xc2, 0xb1, 0xb6, 0x45, 0x76, 0xd3, 0x49, 0x36, 0x46, 0x6d, 0x32, 0x5c, 0x48, + 0xe4, 0xcd, 0x22, 0x66, 0x13, 0xd7, 0x41, 0x5c, 0x7e, 0x49, 0x22, 0xa3, 0x87, 0xa2, 0xe8, 0xc0, + 0xc1, 0xeb, 0x50, 0x89, 0x03, 0x1b, 0x49, 0x52, 0x94, 0x52, 0xe2, 0x6e, 0x24, 0x7c, 0x0f, 0x2e, + 0x3a, 0x6c, 0xc2, 0xcd, 0x59, 0xea, 0x12, 0x52, 0x13, 0x31, 0x76, 0x9c, 0xe6, 0xb8, 0x0a, 0x5b, + 0xb1, 0x0b, 0x45, 0x5a, 0x90, 0xa5, 0x8f, 0xa8, 0x17, 0xc9, 0xde, 0x80, 0x62, 0x14, 0x76, 0x96, + 0x91, 0xa0, 0x40, 0x65, 0xb4, 0x19, 0x05, 0xb2, 0x3e, 0x0b, 0x46, 0x03, 0xae, 0x84, 0x6c, 0x20, + 0x0d, 0x06, 0xb2, 0x86, 0xec, 0x47, 0xda, 0xcb, 0xb0, 0x19, 0x7a, 0x15, 0x49, 0xb7, 0x89, 0x74, + 0x1b, 0x61, 0x27, 0x12, 0xdd, 0x80, 0xaa, 0xe7, 0xbb, 0x9e, 0x1b, 0x30, 0xdf, 0xa4, 0x96, 0xe5, + 0xb3, 0x20, 0xa8, 0x6d, 0x49, 0x79, 0x61, 0xff, 0x81, 0xec, 0xd6, 0xbf, 0x05, 0x85, 0x30, 0x9e, + 0xbe, 0x08, 0x6b, 0xcd, 0xc8, 0x43, 0xe6, 0x0d, 0xd9, 0x10, 0xf8, 0x7a, 0xe0, 0x79, 0xaa, 0xba, + 0x26, 0x3e, 0xf5, 0x01, 0x14, 0xd4, 0x81, 0xcd, 0xad, 0xa9, 0xdc, 0x87, 0x0d, 0x8f, 0xfa, 0x62, + 0x1b, 0xc9, 0xca, 0xca, 0xa2, 0x8c, 0xf0, 0x88, 0xfa, 0xfc, 0x21, 0xe3, 0xa9, 0x02, 0x4b, 0x19, + 0xf9, 0x65, 0x97, 0x7e, 0x13, 0x36, 0x53, 0x34, 0x62, 0x99, 0xdc, 0xe5, 0x74, 0x10, 0x5e, 0x74, + 0x6c, 0x44, 0x2b, 0xc9, 0xc5, 0x2b, 0xd1, 0x6f, 0x41, 0x29, 0x3a, 0x2b, 0x91, 0x68, 0x84, 0xaa, + 0xd0, 0x94, 0xfa, 0x65, 0x13, 0x8b, 0x48, 0xee, 0x33, 0xe6, 0x2b, 0xeb, 0x97, 0x0d, 0x9d, 0x25, + 0x1c, 0x93, 0x44, 0x33, 0x72, 0x1b, 0x0a, 0xca, 0x31, 0xa9, 0xfb, 0xb8, 0xa8, 0x5c, 0x74, 0x84, + 0x9e, 0x2a, 0x2c, 0x17, 0x49, 0xbf, 0x15, 0x4f, 0x93, 0x4b, 0x4e, 0xf3, 0x53, 0x28, 0x86, 0xce, + 0x27, 0x8d, 0x12, 0x72, 0x86, 0x4b, 0xcb, 0x50, 0x42, 0x4d, 0x12, 0x33, 0x0a, 0x6b, 0x0a, 0xec, + 0x9e, 0xc3, 0x2c, 0x33, 0xbe, 0x82, 0x38, 0x67, 0xd1, 0xa8, 0xc8, 0x81, 0x7b, 0xe1, 0xfd, 0xd2, + 0xdf, 0x83, 0x75, 0xb9, 0xd6, 0xb9, 0x2e, 0x6e, 0x1e, 0xb4, 0xfe, 0x43, 0x83, 0x62, 0x08, 0x1f, + 0x73, 0x99, 0x52, 0x9b, 0xc8, 0x7d, 0xdd, 0x4d, 0xbc, 0x7c, 0x97, 0xf4, 0x2e, 0x10, 0xb4, 0x14, + 0x73, 0xec, 0x72, 0xdb, 0xe9, 0x99, 0xf2, 0x2c, 0x64, 0x24, 0x58, 0xc5, 0x91, 0x63, 0x1c, 0x38, + 0x12, 0xfd, 0x6f, 0x5f, 0x86, 0x72, 0xa2, 0xca, 0x45, 0x0a, 0xb0, 0xfa, 0x80, 0x3d, 0xab, 0xae, + 0x90, 0x32, 0x14, 0x0c, 0x86, 0x35, 0x82, 0xaa, 0xb6, 0xff, 0x55, 0x01, 0x2a, 0x07, 0xcd, 0xc3, + 0xf6, 0x81, 0xe7, 0x0d, 0xec, 0x2e, 0xe2, 0x19, 0xf9, 0x04, 0xf2, 0x98, 0x27, 0x67, 0x78, 0xdf, + 0xa9, 0x67, 0x29, 0x38, 0x11, 0x03, 0xd6, 0x30, 0x9d, 0x26, 0x59, 0x9e, 0x7d, 0xea, 0x99, 0xea, + 0x50, 0x62, 0x91, 0x68, 0x70, 0x19, 0x5e, 0x83, 0xea, 0x59, 0x8a, 0x53, 0xe4, 0x33, 0x28, 0xc5, + 0x79, 0x72, 0xd6, 0x37, 0xa2, 0x7a, 0xe6, 0xb2, 0x95, 0x90, 0x1f, 0x67, 0x06, 0x59, 0x5f, 0x48, + 0xea, 0x99, 0xeb, 0x35, 0xe4, 0x09, 0x14, 0xc2, 0x1c, 0x2c, 0xdb, 0x2b, 0x4e, 0x3d, 0x63, 0x49, + 0x49, 0x1c, 0x9f, 0x4c, 0x9d, 0xb3, 0x3c, 0x55, 0xd5, 0x33, 0xd5, 0xcd, 0xc8, 0x63, 0x58, 0x57, + 0xc1, 0x6f, 0xa6, 0xf7, 0x99, 0x7a, 0xb6, 0x42, 0x91, 0x50, 0x72, 0x5c, 0x9c, 0xc8, 0xfa, 0x3c, + 0x57, 0xcf, 0x5c, 0x30, 0x24, 0x14, 0x20, 0x91, 0x4f, 0x67, 0x7e, 0x77, 0xab, 0x67, 0x2f, 0x04, + 0x92, 0x1f, 0x43, 0x31, 0xca, 0x9a, 0x32, 0xbe, 0x7f, 0xd5, 0xb3, 0xd6, 0xe2, 0x9a, 0xed, 0xff, + 0xfc, 0x6d, 0x5b, 0xfb, 0xed, 0xe9, 0xb6, 0xf6, 0xc5, 0xe9, 0xb6, 0xf6, 0xe5, 0xe9, 0xb6, 0xf6, + 0xa7, 0xd3, 0x6d, 0xed, 0xaf, 0xa7, 0xdb, 0xda, 0x1f, 0xfe, 0xbe, 0xad, 0xfd, 0xe8, 0x9d, 0x9e, + 0xcd, 0xfb, 0xa3, 0x4e, 0xa3, 0xeb, 0x0e, 0xf7, 0x62, 0x81, 0xc9, 0xcf, 0xf8, 0x51, 0xbb, 0xb3, + 0x8e, 0x0e, 0xeb, 0xdb, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xce, 0x64, 0xb9, 0xe4, 0xe9, 0x1e, + 0x00, 0x00, } func (this *Request) Equal(that interface{}) bool { diff --git a/abci/types/types.proto b/abci/types/types.proto index 4483e685f..197da34c3 100644 --- a/abci/types/types.proto +++ b/abci/types/types.proto @@ -4,9 +4,9 @@ option go_package = "github.com/tendermint/tendermint/abci/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 "github.com/tendermint/tendermint/crypto/merkle/merkle.proto"; -import "github.com/tendermint/tendermint/libs/kv/types.proto"; +import "third_party/proto/gogoproto/gogo.proto"; +import "crypto/merkle/merkle.proto"; +import "libs/kv/types.proto"; import "google/protobuf/timestamp.proto"; import "google/protobuf/duration.proto"; diff --git a/buf.yaml b/buf.yaml new file mode 100644 index 000000000..1b97487f4 --- /dev/null +++ b/buf.yaml @@ -0,0 +1,16 @@ +build: + roots: + - . +lint: + use: + - MINIMAL + - FILE_LOWER_SNAKE_CASE + - UNARY_RPC + except: + - PACKAGE_DIRECTORY_MATCH + ignore: + - third_party +breaking: + use: + - FILE + - PACKAGE diff --git a/crypto/merkle/merkle.pb.go b/crypto/merkle/merkle.pb.go index 84d01e5b3..80823dd2b 100644 --- a/crypto/merkle/merkle.pb.go +++ b/crypto/merkle/merkle.pb.go @@ -146,22 +146,22 @@ func init() { func init() { proto.RegisterFile("crypto/merkle/merkle.proto", fileDescriptor_9c1c2162d560d38e) } var fileDescriptor_9c1c2162d560d38e = []byte{ - // 226 bytes of a gzipped FileDescriptorProto + // 230 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4a, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0xcf, 0x4d, 0x2d, 0xca, 0xce, 0x49, 0x85, 0x52, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0x12, 0x25, 0xa9, 0x79, 0x29, 0xa9, 0x45, 0xb9, 0x99, 0x79, 0x25, 0x7a, 0x10, 0x65, - 0x7a, 0x10, 0x79, 0x29, 0xdd, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, - 0xf4, 0xfc, 0xf4, 0x7c, 0x7d, 0xb0, 0x86, 0xa4, 0xd2, 0x34, 0x30, 0x0f, 0xcc, 0x01, 0xb3, 0x20, - 0x06, 0x29, 0x39, 0x73, 0xb1, 0x07, 0x14, 0xe5, 0xe7, 0xa7, 0xf9, 0x17, 0x08, 0x09, 0x71, 0xb1, - 0x94, 0x54, 0x16, 0xa4, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0x81, 0xd9, 0x42, 0x02, 0x5c, - 0xcc, 0xd9, 0xa9, 0x95, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0x3c, 0x41, 0x20, 0x26, 0x48, 0x55, 0x4a, - 0x62, 0x49, 0xa2, 0x04, 0x33, 0x58, 0x08, 0xcc, 0x56, 0x72, 0xe2, 0x62, 0x05, 0x1b, 0x22, 0x64, - 0xc9, 0xc5, 0x9c, 0x5f, 0x50, 0x2c, 0xc1, 0xa8, 0xc0, 0xac, 0xc1, 0x6d, 0xa4, 0xa8, 0x87, 0xcb, - 0x91, 0x7a, 0x50, 0x2b, 0x9d, 0x58, 0x4e, 0xdc, 0x93, 0x67, 0x08, 0x02, 0xe9, 0x71, 0x72, 0xf9, - 0xf1, 0x50, 0x8e, 0x71, 0xc5, 0x23, 0x39, 0xc6, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, - 0x7c, 0xf0, 0x48, 0x8e, 0x31, 0x4a, 0x0f, 0xc9, 0x37, 0x08, 0xd3, 0x90, 0x99, 0x28, 0x81, 0x94, - 0xc4, 0x06, 0xf6, 0x95, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xbb, 0x95, 0x22, 0x4e, 0x3c, 0x01, - 0x00, 0x00, + 0x7a, 0x10, 0x79, 0x29, 0xb5, 0x92, 0x8c, 0xcc, 0xa2, 0x94, 0xf8, 0x82, 0xc4, 0xa2, 0x92, 0x4a, + 0x7d, 0xb0, 0x62, 0xfd, 0xf4, 0xfc, 0xf4, 0x7c, 0x04, 0x0b, 0x62, 0x82, 0x92, 0x33, 0x17, 0x7b, + 0x40, 0x51, 0x7e, 0x7e, 0x9a, 0x7f, 0x81, 0x90, 0x10, 0x17, 0x4b, 0x49, 0x65, 0x41, 0xaa, 0x04, + 0xa3, 0x02, 0xa3, 0x06, 0x67, 0x10, 0x98, 0x2d, 0x24, 0xc0, 0xc5, 0x9c, 0x9d, 0x5a, 0x29, 0xc1, + 0xa4, 0xc0, 0xa8, 0xc1, 0x13, 0x04, 0x62, 0x82, 0x54, 0xa5, 0x24, 0x96, 0x24, 0x4a, 0x30, 0x83, + 0x85, 0xc0, 0x6c, 0x25, 0x27, 0x2e, 0x56, 0xb0, 0x21, 0x42, 0x96, 0x5c, 0xcc, 0xf9, 0x05, 0xc5, + 0x12, 0x8c, 0x0a, 0xcc, 0x1a, 0xdc, 0x46, 0x8a, 0x7a, 0xb8, 0x5c, 0xa7, 0x07, 0xb5, 0xd2, 0x89, + 0xe5, 0xc4, 0x3d, 0x79, 0x86, 0x20, 0x90, 0x1e, 0x27, 0x97, 0x1f, 0x0f, 0xe5, 0x18, 0x57, 0x3c, + 0x92, 0x63, 0x3c, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0xa3, + 0xf4, 0xd2, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0x11, 0xa6, 0x21, 0x33, + 0x51, 0x42, 0x27, 0x89, 0x0d, 0xec, 0x2b, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc8, 0xcc, + 0x2c, 0x91, 0x35, 0x01, 0x00, 0x00, } func (this *ProofOp) Equal(that interface{}) bool { @@ -729,6 +729,7 @@ func (m *Proof) Unmarshal(dAtA []byte) error { func skipMerkle(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 + depth := 0 for iNdEx < l { var wire uint64 for shift := uint(0); ; shift += 7 { @@ -760,10 +761,8 @@ func skipMerkle(dAtA []byte) (n int, err error) { break } } - return iNdEx, nil case 1: iNdEx += 8 - return iNdEx, nil case 2: var length int for shift := uint(0); ; shift += 7 { @@ -784,55 +783,30 @@ func skipMerkle(dAtA []byte) (n int, err error) { return 0, ErrInvalidLengthMerkle } iNdEx += length - if iNdEx < 0 { - return 0, ErrInvalidLengthMerkle - } - return iNdEx, nil case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowMerkle - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipMerkle(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - if iNdEx < 0 { - return 0, ErrInvalidLengthMerkle - } - } - return iNdEx, nil + depth++ case 4: - return iNdEx, nil + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupMerkle + } + depth-- case 5: iNdEx += 4 - return iNdEx, nil default: return 0, fmt.Errorf("proto: illegal wireType %d", wireType) } + if iNdEx < 0 { + return 0, ErrInvalidLengthMerkle + } + if depth == 0 { + return iNdEx, nil + } } - panic("unreachable") + return 0, io.ErrUnexpectedEOF } var ( - ErrInvalidLengthMerkle = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowMerkle = fmt.Errorf("proto: integer overflow") + ErrInvalidLengthMerkle = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowMerkle = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupMerkle = fmt.Errorf("proto: unexpected end of group") ) diff --git a/crypto/merkle/merkle.proto b/crypto/merkle/merkle.proto index 66854923e..9dbb2be07 100644 --- a/crypto/merkle/merkle.proto +++ b/crypto/merkle/merkle.proto @@ -4,7 +4,7 @@ option go_package = "github.com/tendermint/tendermint/crypto/merkle"; // 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 "third_party/proto/gogoproto/gogo.proto"; option (gogoproto.marshaler_all) = true; option (gogoproto.unmarshaler_all) = true; diff --git a/libs/kv/types.pb.go b/libs/kv/types.pb.go index 6354c77a5..b572ac205 100644 --- a/libs/kv/types.pb.go +++ b/libs/kv/types.pb.go @@ -149,20 +149,20 @@ func init() { proto.RegisterFile("libs/kv/types.proto", fileDescriptor_31432671d func init() { golang_proto.RegisterFile("libs/kv/types.proto", fileDescriptor_31432671d164f444) } var fileDescriptor_31432671d164f444 = []byte{ - // 193 bytes of a gzipped FileDescriptorProto + // 196 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xce, 0xc9, 0x4c, 0x2a, 0xd6, 0xcf, 0x2e, 0xd3, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x2a, 0x49, 0xcd, 0x4b, 0x49, 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x03, 0xc9, 0xeb, 0x65, - 0x97, 0x49, 0xe9, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0xa7, 0xe7, - 0xa7, 0xe7, 0xeb, 0x83, 0x95, 0x26, 0x95, 0xa6, 0x81, 0x79, 0x60, 0x0e, 0x98, 0x05, 0x31, 0x42, - 0x49, 0x8f, 0x8b, 0x25, 0x20, 0x31, 0xb3, 0x48, 0x48, 0x80, 0x8b, 0x39, 0x3b, 0xb5, 0x52, 0x82, - 0x51, 0x81, 0x51, 0x83, 0x27, 0x08, 0xc4, 0x14, 0x12, 0xe1, 0x62, 0x2d, 0x4b, 0xcc, 0x29, 0x4d, - 0x95, 0x60, 0x02, 0x8b, 0x41, 0x38, 0x4a, 0x46, 0x5c, 0x1c, 0xde, 0x9e, 0x66, 0x26, 0xc4, 0xe8, - 0x61, 0x86, 0xea, 0x71, 0x72, 0xfb, 0xf1, 0x50, 0x8e, 0x71, 0xc5, 0x23, 0x39, 0xc6, 0x1d, 0x8f, - 0xe4, 0x18, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x03, - 0x8f, 0xe5, 0x18, 0xa3, 0x34, 0x90, 0x1c, 0x8c, 0xf0, 0x0f, 0x32, 0x13, 0xea, 0xf5, 0x24, 0x36, - 0xb0, 0x93, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x01, 0x3f, 0x5a, 0xca, 0x0c, 0x01, 0x00, - 0x00, + 0x97, 0x49, 0xa9, 0x95, 0x64, 0x64, 0x16, 0xa5, 0xc4, 0x17, 0x24, 0x16, 0x95, 0x54, 0xea, 0x83, + 0x95, 0xe9, 0xa7, 0xe7, 0xa7, 0xe7, 0x23, 0x58, 0x10, 0xbd, 0x4a, 0x7a, 0x5c, 0x2c, 0x01, 0x89, + 0x99, 0x45, 0x42, 0x02, 0x5c, 0xcc, 0xd9, 0xa9, 0x95, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x3c, 0x41, + 0x20, 0xa6, 0x90, 0x08, 0x17, 0x6b, 0x59, 0x62, 0x4e, 0x69, 0xaa, 0x04, 0x13, 0x58, 0x0c, 0xc2, + 0x51, 0x32, 0xe2, 0xe2, 0xf0, 0xf6, 0x34, 0x33, 0x21, 0x46, 0x0f, 0x33, 0x54, 0x8f, 0x93, 0xdb, + 0x8f, 0x87, 0x72, 0x8c, 0x2b, 0x1e, 0xc9, 0x31, 0xee, 0x78, 0x24, 0xc7, 0x78, 0xe2, 0x91, 0x1c, + 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x1e, 0x78, 0x2c, 0xc7, 0x18, 0xa5, 0x91, + 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x8f, 0xf0, 0x08, 0x32, 0x13, 0xea, + 0xe7, 0x24, 0x36, 0xb0, 0x93, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xc5, 0x5f, 0x67, 0xcb, + 0x05, 0x01, 0x00, 0x00, } func (this *Pair) Equal(that interface{}) bool { diff --git a/libs/kv/types.proto b/libs/kv/types.proto index 59940c8d0..247022798 100644 --- a/libs/kv/types.proto +++ b/libs/kv/types.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package tendermint.libs.kv; option go_package = "github.com/tendermint/tendermint/libs/kv"; -import "github.com/gogo/protobuf/gogoproto/gogo.proto"; +import "third_party/proto/gogoproto/gogo.proto"; option (gogoproto.marshaler_all) = true; option (gogoproto.unmarshaler_all) = true; diff --git a/rpc/grpc/types.pb.go b/rpc/grpc/types.pb.go index 41cbc8488..f7fdf6b53 100644 --- a/rpc/grpc/types.pb.go +++ b/rpc/grpc/types.pb.go @@ -226,29 +226,29 @@ func init() { proto.RegisterFile("rpc/grpc/types.proto", fileDescriptor_15f63baa func init() { golang_proto.RegisterFile("rpc/grpc/types.proto", fileDescriptor_15f63baabf91876a) } var fileDescriptor_15f63baabf91876a = []byte{ - // 346 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x29, 0x2a, 0x48, 0xd6, - 0x4f, 0x07, 0x11, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0xc2, - 0x25, 0xa9, 0x79, 0x29, 0xa9, 0x45, 0xb9, 0x99, 0x79, 0x25, 0x7a, 0x45, 0x05, 0xc9, 0x7a, 0x20, - 0x05, 0x52, 0xba, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0xe9, 0xf9, - 0xe9, 0xf9, 0xfa, 0x60, 0xb5, 0x49, 0xa5, 0x69, 0x60, 0x1e, 0x98, 0x03, 0x66, 0x41, 0xcc, 0x90, - 0x32, 0x47, 0x52, 0x8e, 0x30, 0x0e, 0x99, 0x99, 0x98, 0x94, 0x9c, 0x09, 0xb1, 0x16, 0xd9, 0x72, - 0x25, 0x5e, 0x2e, 0xee, 0xa0, 0xd4, 0xc2, 0xd2, 0xd4, 0xe2, 0x92, 0x80, 0xcc, 0xbc, 0x74, 0x25, - 0x15, 0x2e, 0x21, 0x28, 0xd7, 0xa9, 0x28, 0x3f, 0x31, 0x25, 0x39, 0xb1, 0xb8, 0x24, 0xa4, 0x42, - 0x88, 0x8f, 0x8b, 0xa9, 0xa4, 0x42, 0x82, 0x51, 0x81, 0x51, 0x83, 0x27, 0x88, 0xa9, 0xa4, 0x42, - 0x89, 0x8f, 0x8b, 0x27, 0x28, 0xb5, 0xb8, 0x20, 0x3f, 0xaf, 0x38, 0x15, 0xac, 0x6b, 0x21, 0x23, - 0x97, 0x30, 0x4c, 0x00, 0x59, 0x9f, 0x23, 0x17, 0x47, 0x72, 0x46, 0x6a, 0x72, 0x76, 0x3c, 0x54, - 0x37, 0xb7, 0x91, 0x9a, 0x1e, 0x92, 0x67, 0x41, 0x4e, 0xd2, 0x83, 0x38, 0x06, 0xa6, 0xdb, 0x19, - 0xa4, 0x3c, 0xa4, 0x22, 0x88, 0x3d, 0x19, 0xc2, 0x10, 0x72, 0xe7, 0xe2, 0x4a, 0x49, 0xcd, 0xc9, - 0x2c, 0x4b, 0x2d, 0x02, 0x19, 0xc2, 0x04, 0x36, 0x44, 0x83, 0x80, 0x21, 0x2e, 0x10, 0x0d, 0x21, - 0x15, 0x41, 0x9c, 0x29, 0x30, 0xa6, 0xd1, 0x5e, 0x46, 0x2e, 0x1e, 0xb8, 0xdb, 0x1c, 0x03, 0x3c, - 0x85, 0xbc, 0xb9, 0x58, 0x40, 0x8e, 0x17, 0x52, 0xd0, 0xc3, 0x12, 0xfe, 0x7a, 0x48, 0x81, 0x22, - 0xa5, 0x88, 0x43, 0x05, 0x22, 0x04, 0x84, 0x12, 0xb8, 0xb8, 0x91, 0x3d, 0xae, 0x8e, 0xcf, 0x4c, - 0x24, 0x85, 0x52, 0x1a, 0x78, 0x8d, 0x46, 0x52, 0xe9, 0x14, 0xf8, 0xe3, 0xa1, 0x1c, 0xe3, 0x8a, - 0x47, 0x72, 0x8c, 0x3b, 0x1e, 0xc9, 0x31, 0x9e, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, - 0x83, 0x47, 0x72, 0x8c, 0x07, 0x1e, 0xcb, 0x31, 0x46, 0x19, 0x13, 0x8c, 0x7f, 0x58, 0xd2, 0xb3, - 0x4e, 0xce, 0x2f, 0x4a, 0x8d, 0x07, 0xb1, 0x92, 0xd8, 0xc0, 0x49, 0xc0, 0x18, 0x10, 0x00, 0x00, - 0xff, 0xff, 0xe9, 0x1d, 0x64, 0xc2, 0x97, 0x02, 0x00, 0x00, + // 344 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0xb1, 0x4e, 0xf3, 0x30, + 0x14, 0x85, 0xe5, 0xea, 0xd7, 0x0f, 0xdc, 0x96, 0x0e, 0x2e, 0x42, 0x28, 0x83, 0x55, 0x2a, 0x54, + 0x3a, 0x39, 0x52, 0x19, 0x99, 0x5a, 0x90, 0x10, 0x62, 0xa9, 0xa2, 0x4e, 0x2c, 0x25, 0x75, 0xac, + 0x34, 0x82, 0xc6, 0xc6, 0x71, 0x51, 0xfa, 0x38, 0x6c, 0x3c, 0x02, 0x0b, 0x12, 0x23, 0x23, 0x8f, + 0x00, 0xe1, 0x25, 0x18, 0x91, 0x93, 0x86, 0x78, 0x80, 0xb2, 0x44, 0x27, 0xd6, 0x39, 0x9f, 0xce, + 0xbd, 0xba, 0xb0, 0xa3, 0x24, 0x73, 0x43, 0xf3, 0xd1, 0x4b, 0xc9, 0x13, 0x2a, 0x95, 0xd0, 0x02, + 0xb7, 0x34, 0x8f, 0x03, 0xae, 0xe6, 0x51, 0xac, 0xa9, 0x92, 0x8c, 0x1a, 0x83, 0xd3, 0xd5, 0xb3, + 0x48, 0x05, 0x13, 0xe9, 0x2b, 0xbd, 0x74, 0x73, 0x9f, 0x1b, 0x8a, 0x50, 0x54, 0xaa, 0x08, 0x3b, + 0xbb, 0xfe, 0x94, 0x45, 0x05, 0xce, 0x86, 0x76, 0xb6, 0xa1, 0xee, 0xf1, 0xdb, 0x05, 0x4f, 0xf4, + 0x28, 0x8a, 0xc3, 0xce, 0x01, 0xe0, 0xd5, 0xef, 0x50, 0x09, 0x3f, 0x60, 0x7e, 0xa2, 0xc7, 0x29, + 0x6e, 0x42, 0x4d, 0xa7, 0x7b, 0xa8, 0x8d, 0x7a, 0x0d, 0xaf, 0xa6, 0xd3, 0x4e, 0x13, 0x1a, 0x1e, + 0x4f, 0xa4, 0x88, 0x13, 0x9e, 0xa7, 0xee, 0x11, 0xb4, 0xca, 0x07, 0x3b, 0x37, 0x80, 0x4d, 0x36, + 0xe3, 0xec, 0x7a, 0xb2, 0x4a, 0xd7, 0xfb, 0x5d, 0x6a, 0x0d, 0x61, 0x2a, 0xd1, 0xa2, 0x4c, 0x99, + 0x3e, 0x31, 0xf6, 0x71, 0xea, 0x6d, 0xb0, 0x42, 0xe0, 0x33, 0x80, 0x80, 0xdf, 0x44, 0x77, 0x5c, + 0x19, 0x48, 0x2d, 0x87, 0xf4, 0xfe, 0x80, 0x9c, 0x16, 0x81, 0x71, 0xea, 0x6d, 0x05, 0xa5, 0xec, + 0x3f, 0x21, 0x68, 0x7c, 0x77, 0x1b, 0x8c, 0xce, 0xf1, 0x05, 0xfc, 0x33, 0xe5, 0x71, 0x9b, 0xfe, + 0xb0, 0x57, 0x6a, 0x2d, 0xc5, 0xd9, 0xff, 0xc5, 0x51, 0x6d, 0x00, 0x5f, 0x41, 0xdd, 0x1e, 0xfc, + 0x70, 0x1d, 0xd3, 0x32, 0x3a, 0xbd, 0xb5, 0x68, 0xcb, 0x39, 0x1c, 0x7d, 0xbe, 0x13, 0xf4, 0x90, + 0x11, 0xf4, 0x98, 0x11, 0xf4, 0x92, 0x11, 0xf4, 0x9a, 0x11, 0xf4, 0x96, 0x11, 0xf4, 0xfc, 0x41, + 0xd0, 0x65, 0x3f, 0x8c, 0xf4, 0x6c, 0x31, 0xa5, 0x4c, 0xcc, 0xdd, 0x8a, 0x68, 0xcb, 0xf2, 0xa4, + 0x8e, 0x99, 0x50, 0xdc, 0x88, 0xe9, 0xff, 0xfc, 0x02, 0x8e, 0xbe, 0x02, 0x00, 0x00, 0xff, 0xff, + 0x30, 0xfd, 0xaa, 0xac, 0x6e, 0x02, 0x00, 0x00, } func (this *RequestPing) Equal(that interface{}) bool { @@ -1129,6 +1129,7 @@ func (m *ResponseBroadcastTx) Unmarshal(dAtA []byte) error { func skipTypes(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 + depth := 0 for iNdEx < l { var wire uint64 for shift := uint(0); ; shift += 7 { @@ -1160,10 +1161,8 @@ func skipTypes(dAtA []byte) (n int, err error) { break } } - return iNdEx, nil case 1: iNdEx += 8 - return iNdEx, nil case 2: var length int for shift := uint(0); ; shift += 7 { @@ -1184,55 +1183,30 @@ func skipTypes(dAtA []byte) (n int, err error) { return 0, ErrInvalidLengthTypes } iNdEx += length - if iNdEx < 0 { - return 0, ErrInvalidLengthTypes - } - return iNdEx, nil case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTypes - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipTypes(dAtA[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - if iNdEx < 0 { - return 0, ErrInvalidLengthTypes - } - } - return iNdEx, nil + depth++ case 4: - return iNdEx, nil + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- case 5: iNdEx += 4 - return iNdEx, nil default: return 0, fmt.Errorf("proto: illegal wireType %d", wireType) } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } } - panic("unreachable") + return 0, io.ErrUnexpectedEOF } var ( - ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") ) diff --git a/rpc/grpc/types.proto b/rpc/grpc/types.proto index 75054b0d2..0d18a7f40 100644 --- a/rpc/grpc/types.proto +++ b/rpc/grpc/types.proto @@ -1,9 +1,9 @@ syntax = "proto3"; package tendermint.rpc.grpc; -option go_package = "github.com/tendermint/tendermint/rpc/grpc;core_grpc"; +option go_package = "github.com/tendermint/tendermint/rpc/grpc;coregrpc"; -import "github.com/gogo/protobuf/gogoproto/gogo.proto"; -import "github.com/tendermint/tendermint/abci/types/types.proto"; +import "third_party/proto/gogoproto/gogo.proto"; +import "abci/types/types.proto"; option (gogoproto.marshaler_all) = true; option (gogoproto.unmarshaler_all) = true; diff --git a/scripts/protocgen.sh b/scripts/protocgen.sh new file mode 100644 index 000000000..922512ace --- /dev/null +++ b/scripts/protocgen.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -eo pipefail + +proto_dirs=$(find . -path ./third_party -prune -o -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq) +for dir in $proto_dirs; do + protoc \ + -I. \ + --gogo_out=Mgoogle/protobuf/timestamp.proto=github.com/golang/protobuf/ptypes/timestamp,Mgoogle/protobuf/duration.proto=github.com/golang/protobuf/ptypes/duration,plugins=grpc,paths=source_relative:. \ + $(find "${dir}" -name '*.proto') +done \ No newline at end of file diff --git a/third_party/proto/gogoproto/gogo.proto b/third_party/proto/gogoproto/gogo.proto new file mode 100644 index 000000000..27960ecfb --- /dev/null +++ b/third_party/proto/gogoproto/gogo.proto @@ -0,0 +1,147 @@ +// Protocol Buffers for Go with Gadgets +// +// Copied from https://github.com/gogo/protobuf/blob/master/gogoproto/gogo.proto +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; +package gogoproto; + +import "google/protobuf/descriptor.proto"; + +option java_package = "com.google.protobuf"; +option java_outer_classname = "GoGoProtos"; +option go_package = "github.com/gogo/protobuf/gogoproto"; + +extend google.protobuf.EnumOptions { + optional bool goproto_enum_prefix = 62001; + optional bool goproto_enum_stringer = 62021; + optional bool enum_stringer = 62022; + optional string enum_customname = 62023; + optional bool enumdecl = 62024; +} + +extend google.protobuf.EnumValueOptions { + optional string enumvalue_customname = 66001; +} + +extend google.protobuf.FileOptions { + optional bool goproto_getters_all = 63001; + optional bool goproto_enum_prefix_all = 63002; + optional bool goproto_stringer_all = 63003; + optional bool verbose_equal_all = 63004; + optional bool face_all = 63005; + optional bool gostring_all = 63006; + optional bool populate_all = 63007; + optional bool stringer_all = 63008; + optional bool onlyone_all = 63009; + + optional bool equal_all = 63013; + optional bool description_all = 63014; + optional bool testgen_all = 63015; + optional bool benchgen_all = 63016; + optional bool marshaler_all = 63017; + optional bool unmarshaler_all = 63018; + optional bool stable_marshaler_all = 63019; + + optional bool sizer_all = 63020; + + optional bool goproto_enum_stringer_all = 63021; + optional bool enum_stringer_all = 63022; + + optional bool unsafe_marshaler_all = 63023; + optional bool unsafe_unmarshaler_all = 63024; + + optional bool goproto_extensions_map_all = 63025; + optional bool goproto_unrecognized_all = 63026; + optional bool gogoproto_import = 63027; + optional bool protosizer_all = 63028; + optional bool compare_all = 63029; + optional bool typedecl_all = 63030; + optional bool enumdecl_all = 63031; + + optional bool goproto_registration = 63032; + optional bool messagename_all = 63033; + + optional bool goproto_sizecache_all = 63034; + optional bool goproto_unkeyed_all = 63035; +} + +extend google.protobuf.MessageOptions { + optional bool goproto_getters = 64001; + optional bool goproto_stringer = 64003; + optional bool verbose_equal = 64004; + optional bool face = 64005; + optional bool gostring = 64006; + optional bool populate = 64007; + optional bool stringer = 67008; + optional bool onlyone = 64009; + + optional bool equal = 64013; + optional bool description = 64014; + optional bool testgen = 64015; + optional bool benchgen = 64016; + optional bool marshaler = 64017; + optional bool unmarshaler = 64018; + optional bool stable_marshaler = 64019; + + optional bool sizer = 64020; + + optional bool unsafe_marshaler = 64023; + optional bool unsafe_unmarshaler = 64024; + + optional bool goproto_extensions_map = 64025; + optional bool goproto_unrecognized = 64026; + + optional bool protosizer = 64028; + optional bool compare = 64029; + + optional bool typedecl = 64030; + + optional bool messagename = 64033; + + optional bool goproto_sizecache = 64034; + optional bool goproto_unkeyed = 64035; +} + +extend google.protobuf.FieldOptions { + optional bool nullable = 65001; + optional bool embed = 65002; + optional string customtype = 65003; + optional string customname = 65004; + optional string jsontag = 65005; + optional string moretags = 65006; + optional string casttype = 65007; + optional string castkey = 65008; + optional string castvalue = 65009; + + optional bool stdtime = 65010; + optional bool stdduration = 65011; + optional bool wktpointer = 65012; + + optional string castrepeated = 65013; +} \ No newline at end of file diff --git a/tools.mk b/tools.mk index 140bcfd3e..7761311a9 100644 --- a/tools.mk +++ b/tools.mk @@ -38,8 +38,14 @@ mkfile_dir := $(shell cd $(shell dirname $(mkfile_path)); pwd) # Go tools ### +BIN ?= /usr/local/bin +UNAME_S ?= $(shell uname -s) +UNAME_M ?= $(shell uname -m) + TOOLS_DESTDIR ?= $(GOPATH)/bin +BUF_VERSION ?= 0.7.0 + CERTSTRAP = $(TOOLS_DESTDIR)/certstrap PROTOBUF = $(TOOLS_DESTDIR)/protoc GOODMAN = $(TOOLS_DESTDIR)/goodman @@ -65,6 +71,27 @@ $(PROTOBUF): @echo "Get GoGo Protobuf" @go get github.com/gogo/protobuf/protoc-gen-gogo@v1.3.1 +buf: protoc-gen-buf-check-breaking protoc-gen-buf-check-lint + @echo "Installing buf..." + @curl -sSL \ + "https://github.com/bufbuild/buf/releases/download/v${BUF_VERSION}/buf-${UNAME_S}-${UNAME_M}" \ + -o "${BIN}/buf" && \ + chmod +x "${BIN}/buf" + +protoc-gen-buf-check-breaking: + @echo "Installing protoc-gen-buf-check-breaking..." + @curl -sSL \ + "https://github.com/bufbuild/buf/releases/download/v${BUF_VERSION}/protoc-gen-buf-check-breaking-${UNAME_S}-${UNAME_M}" \ + -o "${BIN}/protoc-gen-buf-check-breaking" && \ + chmod +x "${BIN}/protoc-gen-buf-check-breaking" + +protoc-gen-buf-check-lint: + @echo "Installing protoc-gen-buf-check-lint..." + @curl -sSL \ + "https://github.com/bufbuild/buf/releases/download/v${BUF_VERSION}/protoc-gen-buf-check-lint-${UNAME_S}-${UNAME_M}" \ + -o "${BIN}/protoc-gen-buf-check-lint" && \ + chmod +x "${BIN}/protoc-gen-buf-check-lint" + goodman: $(GOODMAN) $(GOODMAN): @echo "Get Goodman" From da813e4e36748430700ea02b5b11f0628db9df4e Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Tue, 11 Feb 2020 10:41:58 +0100 Subject: [PATCH 36/45] lite2: manage witness dropout (#4380) * witnesses are dropped after no response * test witness dropout * corrected import structure * moved non responsiveness check to compare function * removed dropout test as witnesses are never dropped * created test to compare witnesses --- lite2/client.go | 45 ++++++++++++++++++++++++------------- lite2/client_test.go | 53 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 15 deletions(-) diff --git a/lite2/client.go b/lite2/client.go index 5dc1878eb..668a46203 100644 --- a/lite2/client.go +++ b/lite2/client.go @@ -915,27 +915,42 @@ func (c *Client) compareNewHeaderWithWitnesses(h *types.SignedHeader) error { return errors.New("could not find any witnesses") } - // 1. Loop through all witnesses. - for _, witness := range c.witnesses { + matchedHeader := false + + for attempt := uint16(1); attempt <= c.maxRetryAttempts; attempt++ { + // 1. Loop through all witnesses. + for _, witness := range c.witnesses { + + // 2. Fetch the header. + altH, err := witness.SignedHeader(h.Height) + if err != nil { + c.logger.Info("No Response from witness ", "witness", witness) + continue + } + + // 3. Compare hashes. + if !bytes.Equal(h.Hash(), altH.Hash()) { + // TODO: One of the providers is lying. Send the evidence to fork + // accountability server. + return errors.Errorf( + "header hash %X does not match one %X from the witness %v", + h.Hash(), altH.Hash(), witness) + } + + matchedHeader = true - // 2. Fetch the header. - altH, err := witness.SignedHeader(h.Height) - if err != nil { - return errors.Wrapf(err, - "failed to obtain header #%d from the witness %v", h.Height, witness) } - // 3. Compare hashes. - if !bytes.Equal(h.Hash(), altH.Hash()) { - // TODO: One of the providers is lying. Send the evidence to fork - // accountability server. - return errors.Errorf( - "header hash %X does not match one %X from the witness %v", - h.Hash(), altH.Hash(), witness) + // 4. Check that one responding witness has returned a matching header + if matchedHeader { + return nil } + + time.Sleep(backoffTimeout(attempt)) + } - return nil + return errors.New("awaiting response from all witnesses exceeded dropout time") } func (c *Client) removeNoLongerTrustedHeadersRoutine() { diff --git a/lite2/client_test.go b/lite2/client_test.go index 3f7038e89..4f0e9c600 100644 --- a/lite2/client_test.go +++ b/lite2/client_test.go @@ -1033,3 +1033,56 @@ func Test_NewClientFromTrustedStore(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 1, h.Height) } + +func TestCompareWithWitnesses(t *testing.T) { + const ( + chainID = "TestCompareWithWitnesses" + ) + + var ( + keys = genPrivKeys(4) + // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! + vals = keys.ToValidators(20, 10) + bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") + h1 = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) + h2 = keys.GenSignedHeaderLastBlockID(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys), types.BlockID{Hash: h1.Hash()}) + h3 = keys.GenSignedHeaderLastBlockID(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys), types.BlockID{Hash: h2.Hash()}) + liveProvider = mockp.New( + chainID, + map[int64]*types.SignedHeader{ + 1: h1, + 2: h2, + 3: h3, + }, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: vals, + 3: vals, + 4: vals, + }, + ) + deadProvider = mockp.NewDeadMock(chainID) + ) + + c, err := NewClient( + chainID, + TrustOptions{ + Period: 1 * time.Hour, + Height: 2, + Hash: h2.Hash(), + }, + liveProvider, + []provider.Provider{deadProvider, deadProvider, deadProvider}, + dbs.New(dbm.NewMemDB(), chainID), + UpdatePeriod(0), + Logger(log.TestingLogger()), + MaxRetryAttempts(1), + ) + require.NoError(t, err) + err = c.Update(time.Now()) + assert.Error(t, err) + +} From c494070b310857e4daa6910ed336af88b29d3411 Mon Sep 17 00:00:00 2001 From: Marko Date: Tue, 11 Feb 2020 10:57:26 +0100 Subject: [PATCH 37/45] docs: fix spec links (#4384) - erik fixed many of the broken links, just fixed two outstanding ones. - closes #4381 Signed-off-by: Marko Baricevic Co-authored-by: Anton Kaliaev --- UPGRADING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index ab2251ea7..dcf16d598 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -232,14 +232,14 @@ due to changes in how various data structures are hashed. Any implementations of Tendermint blockchain verification, including lite clients, will need to be updated. For specific details: -- [Merkle tree](./docs/spec/blockchain/encoding.md#merkle-trees) -- [ConsensusParams](./docs/spec/blockchain/state.md#consensusparams) +- [Merkle tree](https://github.com/tendermint/spec/blob/master/spec/blockchain/encoding.md#merkle-trees) +- [ConsensusParams](https://github.com/tendermint/spec/blob/master/spec/blockchain/state.md#consensusparams) There was also a small change to field ordering in the vote struct. Any implementations of an out-of-process validator (like a Key-Management Server) will need to be updated. For specific details: -- [Vote](https://github.com/tendermint/tendermint/blob/master/docs/spec/consensus/signing.md#votes) +- [Vote](https://github.com/tendermint/spec/blob/master/spec/consensus/signing.md#votes) Finally, the proposer selection algorithm continues to evolve. See the [work-in-progress From 9a9e8c5bb303a6aed56bb7fbd154f5bf706fed3e Mon Sep 17 00:00:00 2001 From: Marko Date: Tue, 11 Feb 2020 15:07:05 +0100 Subject: [PATCH 38/45] proto: minor linting to proto files (#4386) * proto: minor linting minor linting after working with the proto files in the sdk. there is no logic change just spacing fixes Signed-off-by: Marko Baricevic * hardcore linting --- abci/types/types.proto | 240 +++++++++++++++++++------------------ crypto/merkle/merkle.proto | 14 +-- libs/kv/types.proto | 20 ++-- rpc/grpc/types.proto | 26 ++-- types/proto3/block.proto | 36 +++--- 5 files changed, 168 insertions(+), 168 deletions(-) diff --git a/abci/types/types.proto b/abci/types/types.proto index 197da34c3..0d47ad9b3 100644 --- a/abci/types/types.proto +++ b/abci/types/types.proto @@ -1,6 +1,6 @@ syntax = "proto3"; package tendermint.abci.types; -option go_package = "github.com/tendermint/tendermint/abci/types"; +option go_package = "github.com/tendermint/tendermint/abci/types"; // For more information on gogo.proto, see: // https://github.com/gogo/protobuf/blob/master/extensions.md @@ -14,31 +14,31 @@ import "google/protobuf/duration.proto"; // NOTE: When using custom types, mind the warnings. // https://github.com/gogo/protobuf/blob/master/custom_types.md#warnings-and-issues -option (gogoproto.marshaler_all) = true; -option (gogoproto.unmarshaler_all) = true; -option (gogoproto.sizer_all) = true; +option (gogoproto.marshaler_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.sizer_all) = true; option (gogoproto.goproto_registration) = true; // Generate tests option (gogoproto.populate_all) = true; -option (gogoproto.equal_all) = true; -option (gogoproto.testgen_all) = true; +option (gogoproto.equal_all) = true; +option (gogoproto.testgen_all) = true; //---------------------------------------- // Request types message Request { oneof value { - RequestEcho echo = 2; - RequestFlush flush = 3; - RequestInfo info = 4; - RequestSetOption set_option = 5; - RequestInitChain init_chain = 6; - RequestQuery query = 7; + RequestEcho echo = 2; + RequestFlush flush = 3; + RequestInfo info = 4; + RequestSetOption set_option = 5; + RequestInitChain init_chain = 6; + RequestQuery query = 7; RequestBeginBlock begin_block = 8; - RequestCheckTx check_tx = 9; - RequestDeliverTx deliver_tx = 19; - RequestEndBlock end_block = 11; - RequestCommit commit = 12; + RequestCheckTx check_tx = 9; + RequestDeliverTx deliver_tx = 19; + RequestEndBlock end_block = 11; + RequestCommit commit = 12; } } @@ -46,50 +46,49 @@ message RequestEcho { string message = 1; } -message RequestFlush { -} +message RequestFlush {} message RequestInfo { - string version = 1; + string version = 1; uint64 block_version = 2; - uint64 p2p_version = 3; + uint64 p2p_version = 3; } // nondeterministic message RequestSetOption { - string key = 1; + string key = 1; string value = 2; } message RequestInitChain { - google.protobuf.Timestamp time = 1 [(gogoproto.nullable)=false, (gogoproto.stdtime)=true]; - string chain_id = 2; - ConsensusParams consensus_params = 3; - repeated ValidatorUpdate validators = 4 [(gogoproto.nullable)=false]; - bytes app_state_bytes = 5; + google.protobuf.Timestamp time = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + string chain_id = 2; + ConsensusParams consensus_params = 3; + repeated ValidatorUpdate validators = 4 [(gogoproto.nullable) = false]; + bytes app_state_bytes = 5; } message RequestQuery { - bytes data = 1; - string path = 2; - int64 height = 3; - bool prove = 4; + bytes data = 1; + string path = 2; + int64 height = 3; + bool prove = 4; } message RequestBeginBlock { - bytes hash = 1; - Header header = 2 [(gogoproto.nullable)=false]; - LastCommitInfo last_commit_info = 3 [(gogoproto.nullable)=false]; - repeated Evidence byzantine_validators = 4 [(gogoproto.nullable)=false]; + bytes hash = 1; + Header header = 2 [(gogoproto.nullable) = false]; + LastCommitInfo last_commit_info = 3 [(gogoproto.nullable) = false]; + repeated Evidence byzantine_validators = 4 [(gogoproto.nullable) = false]; } enum CheckTxType { - New = 0; + New = 0; Recheck = 1; } message RequestCheckTx { - bytes tx = 1; + bytes tx = 1; CheckTxType type = 2; } @@ -101,26 +100,25 @@ message RequestEndBlock { int64 height = 1; } -message RequestCommit { -} +message RequestCommit {} //---------------------------------------- // Response types message Response { oneof value { - ResponseException exception = 1; - ResponseEcho echo = 2; - ResponseFlush flush = 3; - ResponseInfo info = 4; - ResponseSetOption set_option = 5; - ResponseInitChain init_chain = 6; - ResponseQuery query = 7; + ResponseException exception = 1; + ResponseEcho echo = 2; + ResponseFlush flush = 3; + ResponseInfo info = 4; + ResponseSetOption set_option = 5; + ResponseInitChain init_chain = 6; + ResponseQuery query = 7; ResponseBeginBlock begin_block = 8; - ResponseCheckTx check_tx = 9; - ResponseDeliverTx deliver_tx = 10; - ResponseEndBlock end_block = 11; - ResponseCommit commit = 12; + ResponseCheckTx check_tx = 9; + ResponseDeliverTx deliver_tx = 10; + ResponseEndBlock end_block = 11; + ResponseCommit commit = 12; } } @@ -133,16 +131,15 @@ message ResponseEcho { string message = 1; } -message ResponseFlush { -} +message ResponseFlush {} message ResponseInfo { string data = 1; - string version = 2; + string version = 2; uint64 app_version = 3; - int64 last_block_height = 4; + int64 last_block_height = 4; bytes last_block_app_hash = 5; } @@ -150,58 +147,62 @@ message ResponseInfo { message ResponseSetOption { uint32 code = 1; // bytes data = 2; - string log = 3; + string log = 3; string info = 4; } message ResponseInitChain { - ConsensusParams consensus_params = 1; - repeated ValidatorUpdate validators = 2 [(gogoproto.nullable)=false]; + ConsensusParams consensus_params = 1; + repeated ValidatorUpdate validators = 2 [(gogoproto.nullable) = false]; } message ResponseQuery { uint32 code = 1; // bytes data = 2; // use "value" instead. - string log = 3; // nondeterministic - string info = 4; // nondeterministic - int64 index = 5; - bytes key = 6; - bytes value = 7; - tendermint.crypto.merkle.Proof proof = 8; - int64 height = 9; - string codespace = 10; + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 index = 5; + bytes key = 6; + bytes value = 7; + tendermint.crypto.merkle.Proof proof = 8; + int64 height = 9; + string codespace = 10; } message ResponseBeginBlock { - repeated Event events = 1 [(gogoproto.nullable)=false, (gogoproto.jsontag)="events,omitempty"]; + repeated Event events = 1 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; } message ResponseCheckTx { - uint32 code = 1; - bytes data = 2; - string log = 3; // nondeterministic - string info = 4; // nondeterministic - int64 gas_wanted = 5; - int64 gas_used = 6; - repeated Event events = 7 [(gogoproto.nullable)=false, (gogoproto.jsontag)="events,omitempty"]; + uint32 code = 1; + bytes data = 2; + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 gas_wanted = 5; + int64 gas_used = 6; + repeated Event events = 7 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; string codespace = 8; } message ResponseDeliverTx { - uint32 code = 1; - bytes data = 2; - string log = 3; // nondeterministic - string info = 4; // nondeterministic - int64 gas_wanted = 5; - int64 gas_used = 6; - repeated Event events = 7 [(gogoproto.nullable)=false, (gogoproto.jsontag)="events,omitempty"]; + uint32 code = 1; + bytes data = 2; + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 gas_wanted = 5; + int64 gas_used = 6; + repeated Event events = 7 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; string codespace = 8; } message ResponseEndBlock { - repeated ValidatorUpdate validator_updates = 1 [(gogoproto.nullable)=false]; - ConsensusParams consensus_param_updates = 2; - repeated Event events = 3 [(gogoproto.nullable)=false, (gogoproto.jsontag)="events,omitempty"]; + repeated ValidatorUpdate validator_updates = 1 [(gogoproto.nullable) = false]; + ConsensusParams consensus_param_updates = 2; + repeated Event events = 3 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; } message ResponseCommit { @@ -215,8 +216,8 @@ message ResponseCommit { // ConsensusParams contains all consensus-relevant parameters // that can be adjusted by the abci app message ConsensusParams { - BlockParams block = 1; - EvidenceParams evidence = 2; + BlockParams block = 1; + EvidenceParams evidence = 2; ValidatorParams validator = 3; } @@ -230,8 +231,9 @@ message BlockParams { message EvidenceParams { // Note: must be greater than 0 - int64 max_age_num_blocks = 1; - google.protobuf.Duration max_age_duration = 2 [(gogoproto.nullable)=false, (gogoproto.stdduration)=true]; + int64 max_age_num_blocks = 1; + google.protobuf.Duration max_age_duration = 2 + [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; } // ValidatorParams contains limits on validators. @@ -240,13 +242,14 @@ message ValidatorParams { } message LastCommitInfo { - int32 round = 1; - repeated VoteInfo votes = 2 [(gogoproto.nullable)=false]; + int32 round = 1; + repeated VoteInfo votes = 2 [(gogoproto.nullable) = false]; } message Event { - string type = 1; - repeated tendermint.libs.kv.Pair attributes = 2 [(gogoproto.nullable)=false, (gogoproto.jsontag)="attributes,omitempty"]; + string type = 1; + repeated tendermint.libs.kv.Pair attributes = 2 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "attributes,omitempty"]; } //---------------------------------------- @@ -254,63 +257,62 @@ message Event { message Header { // basic block info - Version version = 1 [(gogoproto.nullable)=false]; - string chain_id = 2 [(gogoproto.customname)="ChainID"]; - int64 height = 3; - google.protobuf.Timestamp time = 4 [(gogoproto.nullable)=false, (gogoproto.stdtime)=true]; + Version version = 1 [(gogoproto.nullable) = false]; + string chain_id = 2 [(gogoproto.customname) = "ChainID"]; + int64 height = 3; + google.protobuf.Timestamp time = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; // prev block info - BlockID last_block_id = 5 [(gogoproto.nullable)=false]; + BlockID last_block_id = 5 [(gogoproto.nullable) = false]; // hashes of block data - bytes last_commit_hash = 6; // commit from validators from the last block - bytes data_hash = 7; // transactions + bytes last_commit_hash = 6; // commit from validators from the last block + bytes data_hash = 7; // transactions // hashes from the app output from the prev block - bytes validators_hash = 8; // validators for the current block + bytes validators_hash = 8; // validators for the current block bytes next_validators_hash = 9; // validators for the next block - bytes consensus_hash = 10; // consensus params for current block - bytes app_hash = 11; // state after txs from the previous block - bytes last_results_hash = 12;// root hash of all results from the txs from the previous block + bytes consensus_hash = 10; // consensus params for current block + bytes app_hash = 11; // state after txs from the previous block + bytes last_results_hash = 12; // root hash of all results from the txs from the previous block // consensus info - bytes evidence_hash = 13; // evidence included in the block - bytes proposer_address = 14; // original proposer of the block + bytes evidence_hash = 13; // evidence included in the block + bytes proposer_address = 14; // original proposer of the block } message Version { uint64 Block = 1; - uint64 App = 2; + uint64 App = 2; } - message BlockID { - bytes hash = 1; - PartSetHeader parts_header = 2 [(gogoproto.nullable)=false]; + bytes hash = 1; + PartSetHeader parts_header = 2 [(gogoproto.nullable) = false]; } message PartSetHeader { int32 total = 1; - bytes hash = 2; + bytes hash = 2; } // Validator message Validator { bytes address = 1; - //PubKey pub_key = 2 [(gogoproto.nullable)=false]; + // PubKey pub_key = 2 [(gogoproto.nullable)=false]; int64 power = 3; } // ValidatorUpdate message ValidatorUpdate { - PubKey pub_key = 1 [(gogoproto.nullable)=false]; - int64 power = 2; + PubKey pub_key = 1 [(gogoproto.nullable) = false]; + int64 power = 2; } // VoteInfo message VoteInfo { - Validator validator = 1 [(gogoproto.nullable)=false]; - bool signed_last_block = 2; + Validator validator = 1 [(gogoproto.nullable) = false]; + bool signed_last_block = 2; } message PubKey { @@ -319,18 +321,18 @@ message PubKey { } message Evidence { - string type = 1; - Validator validator = 2 [(gogoproto.nullable)=false]; - int64 height = 3; - google.protobuf.Timestamp time = 4 [(gogoproto.nullable)=false, (gogoproto.stdtime)=true]; - int64 total_voting_power = 5; + string type = 1; + Validator validator = 2 [(gogoproto.nullable) = false]; + int64 height = 3; + google.protobuf.Timestamp time = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + int64 total_voting_power = 5; } //---------------------------------------- // Service Definition service ABCIApplication { - rpc Echo(RequestEcho) returns (ResponseEcho) ; + rpc Echo(RequestEcho) returns (ResponseEcho); rpc Flush(RequestFlush) returns (ResponseFlush); rpc Info(RequestInfo) returns (ResponseInfo); rpc SetOption(RequestSetOption) returns (ResponseSetOption); diff --git a/crypto/merkle/merkle.proto b/crypto/merkle/merkle.proto index 9dbb2be07..159fc58c9 100644 --- a/crypto/merkle/merkle.proto +++ b/crypto/merkle/merkle.proto @@ -1,17 +1,17 @@ syntax = "proto3"; package tendermint.crypto.merkle; -option go_package = "github.com/tendermint/tendermint/crypto/merkle"; +option go_package = "github.com/tendermint/tendermint/crypto/merkle"; // For more information on gogo.proto, see: // https://github.com/gogo/protobuf/blob/master/extensions.md import "third_party/proto/gogoproto/gogo.proto"; -option (gogoproto.marshaler_all) = true; +option (gogoproto.marshaler_all) = true; option (gogoproto.unmarshaler_all) = true; -option (gogoproto.sizer_all) = true; +option (gogoproto.sizer_all) = true; option (gogoproto.populate_all) = true; -option (gogoproto.equal_all) = true; +option (gogoproto.equal_all) = true; //---------------------------------------- // Message types @@ -21,11 +21,11 @@ option (gogoproto.equal_all) = true; // for example neighbouring node hash message ProofOp { string type = 1; - bytes key = 2; - bytes data = 3; + bytes key = 2; + bytes data = 3; } // Proof is Merkle proof defined by the list of ProofOps message Proof { - repeated ProofOp ops = 1 [(gogoproto.nullable)=false]; + repeated ProofOp ops = 1 [(gogoproto.nullable) = false]; } diff --git a/libs/kv/types.proto b/libs/kv/types.proto index 247022798..7e1375c21 100644 --- a/libs/kv/types.proto +++ b/libs/kv/types.proto @@ -1,29 +1,29 @@ syntax = "proto3"; package tendermint.libs.kv; -option go_package = "github.com/tendermint/tendermint/libs/kv"; +option go_package = "github.com/tendermint/tendermint/libs/kv"; import "third_party/proto/gogoproto/gogo.proto"; -option (gogoproto.marshaler_all) = true; -option (gogoproto.unmarshaler_all) = true; -option (gogoproto.sizer_all) = true; +option (gogoproto.marshaler_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.sizer_all) = true; option (gogoproto.goproto_registration) = true; // Generate tests option (gogoproto.populate_all) = true; -option (gogoproto.equal_all) = true; -option (gogoproto.testgen_all) = true; +option (gogoproto.equal_all) = true; +option (gogoproto.testgen_all) = true; //---------------------------------------- // Abstract types -// Define these here for compatibility but use tmlibs/common.KVPair. +// Define these here for compatibility but use tmlibs/kv.Pair. message Pair { - bytes key = 1; + bytes key = 1; bytes value = 2; } -// Define these here for compatibility but use tmlibs/common.KI64Pair. +// Define these here for compatibility but use tmlibs/kv.KI64Pair. message KI64Pair { - bytes key = 1; + bytes key = 1; int64 value = 2; } diff --git a/rpc/grpc/types.proto b/rpc/grpc/types.proto index 0d18a7f40..fc778cacd 100644 --- a/rpc/grpc/types.proto +++ b/rpc/grpc/types.proto @@ -1,26 +1,25 @@ syntax = "proto3"; package tendermint.rpc.grpc; -option go_package = "github.com/tendermint/tendermint/rpc/grpc;coregrpc"; +option go_package = "github.com/tendermint/tendermint/rpc/grpc;coregrpc"; import "third_party/proto/gogoproto/gogo.proto"; import "abci/types/types.proto"; -option (gogoproto.marshaler_all) = true; -option (gogoproto.unmarshaler_all) = true; -option (gogoproto.sizer_all) = true; +option (gogoproto.marshaler_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.sizer_all) = true; option (gogoproto.goproto_registration) = true; // Generate tests option (gogoproto.populate_all) = true; -option (gogoproto.equal_all) = true; -option (gogoproto.testgen_all) = true; +option (gogoproto.equal_all) = true; +option (gogoproto.testgen_all) = true; //---------------------------------------- // Message types //---------------------------------------- // Request types -message RequestPing { -} +message RequestPing {} message RequestBroadcastTx { bytes tx = 1; @@ -29,11 +28,10 @@ message RequestBroadcastTx { //---------------------------------------- // Response types -message ResponsePing{ -} +message ResponsePing {} -message ResponseBroadcastTx{ - tendermint.abci.types.ResponseCheckTx check_tx = 1; +message ResponseBroadcastTx { + tendermint.abci.types.ResponseCheckTx check_tx = 1; tendermint.abci.types.ResponseDeliverTx deliver_tx = 2; } @@ -41,6 +39,6 @@ message ResponseBroadcastTx{ // Service Definition service BroadcastAPI { - rpc Ping(RequestPing) returns (ResponsePing) ; - rpc BroadcastTx(RequestBroadcastTx) returns (ResponseBroadcastTx) ; + rpc Ping(RequestPing) returns (ResponsePing); + rpc BroadcastTx(RequestBroadcastTx) returns (ResponseBroadcastTx); } diff --git a/types/proto3/block.proto b/types/proto3/block.proto index fb81c4763..adaa0a00d 100644 --- a/types/proto3/block.proto +++ b/types/proto3/block.proto @@ -1,47 +1,47 @@ syntax = "proto3"; package tendermint.types.proto3; -option go_package = "github.com/tendermint/tendermint/types/proto3"; +option go_package = "github.com/tendermint/tendermint/types/proto3"; message PartSetHeader { int32 Total = 1; - bytes Hash = 2; + bytes Hash = 2; } message BlockID { - bytes Hash = 1; + bytes Hash = 1; PartSetHeader PartsHeader = 2; } message Header { // basic block info - Version Version = 1; - string ChainID = 2; - int64 Height = 3; - Timestamp Time = 4; + Version Version = 1; + string ChainID = 2; + int64 Height = 3; + Timestamp Time = 4; // prev block info BlockID LastBlockID = 5; // hashes of block data - bytes LastCommitHash = 6; // commit from validators from the last block - bytes DataHash = 7; // transactions + bytes LastCommitHash = 6; // commit from validators from the last block + bytes DataHash = 7; // transactions // hashes from the app output from the prev block - bytes ValidatorsHash = 8; // validators for the current block - bytes NextValidatorsHash = 9; // validators for the next block - bytes ConsensusHash = 10; // consensus params for current block - bytes AppHash = 11; // state after txs from the previous block - bytes LastResultsHash = 12; // root hash of all results from the txs from the previous block + bytes ValidatorsHash = 8; // validators for the current block + bytes NextValidatorsHash = 9; // validators for the next block + bytes ConsensusHash = 10; // consensus params for current block + bytes AppHash = 11; // state after txs from the previous block + bytes LastResultsHash = 12; // root hash of all results from the txs from the previous block // consensus info - bytes EvidenceHash = 13; // evidence included in the block - bytes ProposerAddress = 14; // original proposer of the block + bytes EvidenceHash = 13; // evidence included in the block + bytes ProposerAddress = 14; // original proposer of the block } message Version { uint64 Block = 1; - uint64 App = 2; + uint64 App = 2; } // Timestamp wraps how amino encodes time. @@ -51,5 +51,5 @@ message Version { // NOTE/XXX: nanos do not get skipped if they are zero in amino. message Timestamp { int64 seconds = 1; - int32 nanos = 2; + int32 nanos = 2; } From 4787f7c2dd9f4a311ffb65651c6609c581f4e9f2 Mon Sep 17 00:00:00 2001 From: Callum Michael Waters Date: Tue, 11 Feb 2020 17:17:48 +0100 Subject: [PATCH 39/45] refactored lite client tests --- lite2/client_test.go | 541 ++++++++----------------------------------- 1 file changed, 101 insertions(+), 440 deletions(-) diff --git a/lite2/client_test.go b/lite2/client_test.go index 4f0e9c600..b4823eaf9 100644 --- a/lite2/client_test.go +++ b/lite2/client_test.go @@ -17,19 +17,44 @@ import ( "github.com/tendermint/tendermint/types" ) -func TestClient_SequentialVerification(t *testing.T) { - const ( - chainID = "sequential-verification" - ) +const ( + chainID = "test" +) - var ( - keys = genPrivKeys(4) - // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! - vals = keys.ToValidators(20, 10) - bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") - header = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) +var ( + keys = genPrivKeys(4) + vals = keys.ToValidators(20, 10) + bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") + h1 = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) + h2 = keys.GenSignedHeaderLastBlockID(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys), types.BlockID{Hash: h1.Hash()}) + h3 = keys.GenSignedHeaderLastBlockID(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals, + []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys), types.BlockID{Hash: h2.Hash()}) + trustPeriod = 4 * time.Hour + trustOptions = TrustOptions{ + Period: 4 * time.Hour, + Height: 1, + Hash: h1.Hash(), + } + fullNode = mockp.New( + chainID, + map[int64]*types.SignedHeader{ + 1: h1, + 2: h2, + 3: h3, + }, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: vals, + 3: vals, + 4: vals, + }, ) + deadNode = mockp.NewDeadMock(chainID) +) + +func TestClient_SequentialVerification(t *testing.T) { testCases := []struct { otherHeaders map[int64]*types.SignedHeader // all except ^ @@ -41,13 +66,11 @@ func TestClient_SequentialVerification(t *testing.T) { { map[int64]*types.SignedHeader{ // trusted header - 1: header, + 1: h1, // interim header (3/3 signed) - 2: keys.GenSignedHeader(chainID, 2, bTime.Add(1*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), + 2: h2, // last header (3/3 signed) - 3: keys.GenSignedHeader(chainID, 3, bTime.Add(2*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), + 3: h3, }, map[int64]*types.ValidatorSet{ 1: vals, @@ -75,7 +98,7 @@ func TestClient_SequentialVerification(t *testing.T) { { map[int64]*types.SignedHeader{ // trusted header - 1: header, + 1: h1, // interim header (1/3 signed) 2: keys.GenSignedHeader(chainID, 2, bTime.Add(1*time.Hour), nil, vals, vals, []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), len(keys)-1, len(keys)), @@ -96,7 +119,7 @@ func TestClient_SequentialVerification(t *testing.T) { { map[int64]*types.SignedHeader{ // trusted header - 1: header, + 1: h1, // interim header (3/3 signed) 2: keys.GenSignedHeader(chainID, 2, bTime.Add(1*time.Hour), nil, vals, vals, []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), @@ -118,11 +141,7 @@ func TestClient_SequentialVerification(t *testing.T) { for _, tc := range testCases { c, err := NewClient( chainID, - TrustOptions{ - Period: 4 * time.Hour, - Height: 1, - Hash: header.Hash(), - }, + trustOptions, mockp.New( chainID, tc.otherHeaders, @@ -157,18 +176,6 @@ func TestClient_SequentialVerification(t *testing.T) { } func TestClient_SkippingVerification(t *testing.T) { - const ( - chainID = "skipping-verification" - ) - - var ( - keys = genPrivKeys(4) - // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! - vals = keys.ToValidators(20, 10) - bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") - header = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - ) // required for 2nd test case newKeys := genPrivKeys(4) @@ -177,17 +184,14 @@ func TestClient_SkippingVerification(t *testing.T) { testCases := []struct { otherHeaders map[int64]*types.SignedHeader // all except ^ vals map[int64]*types.ValidatorSet - initErr bool - verifyErr bool }{ // good { map[int64]*types.SignedHeader{ // trusted header - 1: header, + 1: h1, // last header (3/3 signed) - 3: keys.GenSignedHeader(chainID, 3, bTime.Add(2*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), + 3: h3, }, map[int64]*types.ValidatorSet{ 1: vals, @@ -195,14 +199,12 @@ func TestClient_SkippingVerification(t *testing.T) { 3: vals, 4: vals, }, - false, - false, }, // good, val set changes 100% at height 2 { map[int64]*types.SignedHeader{ // trusted header - 1: header, + 1: h1, // interim header (3/3 signed) 2: keys.GenSignedHeader(chainID, 2, bTime.Add(1*time.Hour), nil, vals, newVals, []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), @@ -216,19 +218,13 @@ func TestClient_SkippingVerification(t *testing.T) { 3: newVals, 4: newVals, }, - false, - false, }, } for _, tc := range testCases { c, err := NewClient( chainID, - TrustOptions{ - Period: 4 * time.Hour, - Height: 1, - Hash: header.Hash(), - }, + trustOptions, mockp.New( chainID, tc.otherHeaders, @@ -242,68 +238,23 @@ func TestClient_SkippingVerification(t *testing.T) { dbs.New(dbm.NewMemDB(), chainID), SkippingVerification(DefaultTrustLevel), ) - if tc.initErr { - require.Error(t, err) - continue - } else { - require.NoError(t, err) - } + require.NoError(t, err) err = c.Start() require.NoError(t, err) defer c.Stop() _, err = c.VerifyHeaderAtHeight(3, bTime.Add(3*time.Hour)) - if tc.verifyErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) - } + assert.NoError(t, err) } } func TestClientRemovesNoLongerTrustedHeaders(t *testing.T) { - const ( - chainID = "TestClientRemovesNoLongerTrustedHeaders" - ) - - var ( - keys = genPrivKeys(4) - // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! - vals = keys.ToValidators(20, 10) - bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") - header = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - ) - - primary := mockp.New( - chainID, - map[int64]*types.SignedHeader{ - // trusted header - 1: header, - // interim header (3/3 signed) - 2: keys.GenSignedHeader(chainID, 2, bTime.Add(2*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - // last header (3/3 signed) - 3: keys.GenSignedHeader(chainID, 3, bTime.Add(4*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - 3: vals, - 4: vals, - }, - ) c, err := NewClient( chainID, - TrustOptions{ - Period: 4 * time.Hour, - Height: 1, - Hash: header.Hash(), - }, - primary, - []provider.Provider{primary}, + trustOptions, + fullNode, + []provider.Provider{fullNode}, dbs.New(dbm.NewMemDB(), chainID), Logger(log.TestingLogger()), ) @@ -340,40 +291,12 @@ func TestClientRemovesNoLongerTrustedHeaders(t *testing.T) { } func TestClient_Cleanup(t *testing.T) { - const ( - chainID = "TestClient_Cleanup" - ) - - var ( - keys = genPrivKeys(4) - // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! - vals = keys.ToValidators(20, 10) - bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") - header = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - ) - - primary := mockp.New( - chainID, - map[int64]*types.SignedHeader{ - // trusted header - 1: header, - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - }, - ) c, err := NewClient( chainID, - TrustOptions{ - Period: 4 * time.Hour, - Height: 1, - Hash: header.Hash(), - }, - primary, - []provider.Provider{primary}, + trustOptions, + fullNode, + []provider.Provider{fullNode}, dbs.New(dbm.NewMemDB(), chainID), Logger(log.TestingLogger()), ) @@ -392,46 +315,18 @@ func TestClient_Cleanup(t *testing.T) { // trustedHeader.Height == options.Height func TestClientRestoreTrustedHeaderAfterStartup1(t *testing.T) { - const ( - chainID = "TestClientRestoreTrustedHeaderAfterStartup1" - ) - - var ( - keys = genPrivKeys(4) - // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! - vals = keys.ToValidators(20, 10) - bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") - header = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - ) // 1. options.Hash == trustedHeader.Hash { trustedStore := dbs.New(dbm.NewMemDB(), chainID) - err := trustedStore.SaveSignedHeaderAndNextValidatorSet(header, vals) + err := trustedStore.SaveSignedHeaderAndNextValidatorSet(h1, vals) require.NoError(t, err) - primary := mockp.New( - chainID, - map[int64]*types.SignedHeader{ - // trusted header - 1: header, - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - }, - ) - c, err := NewClient( chainID, - TrustOptions{ - Period: 4 * time.Hour, - Height: 1, - Hash: header.Hash(), - }, - primary, - []provider.Provider{primary}, + trustOptions, + fullNode, + []provider.Provider{fullNode}, trustedStore, Logger(log.TestingLogger()), ) @@ -443,13 +338,13 @@ func TestClientRestoreTrustedHeaderAfterStartup1(t *testing.T) { h, err := c.TrustedHeader(1, bTime.Add(1*time.Second)) assert.NoError(t, err) assert.NotNil(t, h) - assert.Equal(t, h.Hash(), header.Hash()) + assert.Equal(t, h.Hash(), h1.Hash()) } // 2. options.Hash != trustedHeader.Hash { trustedStore := dbs.New(dbm.NewMemDB(), chainID) - err := trustedStore.SaveSignedHeaderAndNextValidatorSet(header, vals) + err := trustedStore.SaveSignedHeaderAndNextValidatorSet(h1, vals) require.NoError(t, err) // header1 != header @@ -494,49 +389,22 @@ func TestClientRestoreTrustedHeaderAfterStartup1(t *testing.T) { // trustedHeader.Height < options.Height func TestClientRestoreTrustedHeaderAfterStartup2(t *testing.T) { - const ( - chainID = "TestClientRestoreTrustedHeaderAfterStartup2" - ) - - var ( - keys = genPrivKeys(4) - // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! - vals = keys.ToValidators(20, 10) - bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") - header = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - ) // 1. options.Hash == trustedHeader.Hash { trustedStore := dbs.New(dbm.NewMemDB(), chainID) - err := trustedStore.SaveSignedHeaderAndNextValidatorSet(header, vals) + err := trustedStore.SaveSignedHeaderAndNextValidatorSet(h1, vals) require.NoError(t, err) - header2 := keys.GenSignedHeader(chainID, 2, bTime.Add(2*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - - primary := mockp.New( - chainID, - map[int64]*types.SignedHeader{ - 1: header, - 2: header2, - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - 3: vals, - }, - ) c, err := NewClient( chainID, TrustOptions{ Period: 4 * time.Hour, Height: 2, - Hash: header2.Hash(), + Hash: h2.Hash(), }, - primary, - []provider.Provider{primary}, + fullNode, + []provider.Provider{fullNode}, trustedStore, Logger(log.TestingLogger()), ) @@ -549,28 +417,28 @@ func TestClientRestoreTrustedHeaderAfterStartup2(t *testing.T) { h, err := c.TrustedHeader(1, bTime.Add(2*time.Hour).Add(1*time.Second)) assert.NoError(t, err) assert.NotNil(t, h) - assert.Equal(t, h.Hash(), header.Hash()) + assert.Equal(t, h.Hash(), h1.Hash()) } // 2. options.Hash != trustedHeader.Hash // This could happen if previous provider was lying to us. { trustedStore := dbs.New(dbm.NewMemDB(), chainID) - err := trustedStore.SaveSignedHeaderAndNextValidatorSet(header, vals) + err := trustedStore.SaveSignedHeaderAndNextValidatorSet(h1, vals) require.NoError(t, err) // header1 != header - header1 := keys.GenSignedHeader(chainID, 1, bTime.Add(1*time.Hour), nil, vals, vals, + diffHeader1 := keys.GenSignedHeader(chainID, 1, bTime.Add(1*time.Hour), nil, vals, vals, []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - header2 := keys.GenSignedHeader(chainID, 2, bTime.Add(2*time.Hour), nil, vals, vals, + diffHeader2 := keys.GenSignedHeader(chainID, 2, bTime.Add(2*time.Hour), nil, vals, vals, []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) primary := mockp.New( chainID, map[int64]*types.SignedHeader{ - 1: header1, - 2: header2, + 1: diffHeader1, + 2: diffHeader2, }, map[int64]*types.ValidatorSet{ 1: vals, @@ -584,7 +452,7 @@ func TestClientRestoreTrustedHeaderAfterStartup2(t *testing.T) { TrustOptions{ Period: 4 * time.Hour, Height: 2, - Hash: header2.Hash(), + Hash: diffHeader2.Hash(), }, primary, []provider.Provider{primary}, @@ -605,35 +473,23 @@ func TestClientRestoreTrustedHeaderAfterStartup2(t *testing.T) { // trustedHeader.Height > options.Height func TestClientRestoreTrustedHeaderAfterStartup3(t *testing.T) { - const ( - chainID = "TestClientRestoreTrustedHeaderAfterStartup3" - ) - - var ( - keys = genPrivKeys(4) - // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! - vals = keys.ToValidators(20, 10) - bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") - header = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - ) // 1. options.Hash == trustedHeader.Hash { trustedStore := dbs.New(dbm.NewMemDB(), chainID) - err := trustedStore.SaveSignedHeaderAndNextValidatorSet(header, vals) + err := trustedStore.SaveSignedHeaderAndNextValidatorSet(h1, vals) require.NoError(t, err) - header2 := keys.GenSignedHeader(chainID, 2, bTime.Add(2*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - err = trustedStore.SaveSignedHeaderAndNextValidatorSet(header2, vals) + //header2 := keys.GenSignedHeader(chainID, 2, bTime.Add(2*time.Hour), nil, vals, vals, + // []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) + err = trustedStore.SaveSignedHeaderAndNextValidatorSet(h2, vals) require.NoError(t, err) primary := mockp.New( chainID, map[int64]*types.SignedHeader{ - 1: header, - 2: header2, + 1: h1, + 2: h2, }, map[int64]*types.ValidatorSet{ 1: vals, @@ -644,11 +500,7 @@ func TestClientRestoreTrustedHeaderAfterStartup3(t *testing.T) { c, err := NewClient( chainID, - TrustOptions{ - Period: 4 * time.Hour, - Height: 1, - Hash: header.Hash(), - }, + trustOptions, primary, []provider.Provider{primary}, trustedStore, @@ -663,7 +515,7 @@ func TestClientRestoreTrustedHeaderAfterStartup3(t *testing.T) { h, err := c.TrustedHeader(1, bTime.Add(2*time.Hour).Add(1*time.Second)) assert.NoError(t, err) assert.NotNil(t, h) - assert.Equal(t, h.Hash(), header.Hash()) + assert.Equal(t, h.Hash(), h1.Hash()) // Check we no longer have 2nd header (+header2+). h, err = c.TrustedHeader(2, bTime.Add(2*time.Hour).Add(1*time.Second)) @@ -675,7 +527,7 @@ func TestClientRestoreTrustedHeaderAfterStartup3(t *testing.T) { // This could happen if previous provider was lying to us. { trustedStore := dbs.New(dbm.NewMemDB(), chainID) - err := trustedStore.SaveSignedHeaderAndNextValidatorSet(header, vals) + err := trustedStore.SaveSignedHeaderAndNextValidatorSet(h1, vals) require.NoError(t, err) // header1 != header @@ -729,48 +581,12 @@ func TestClientRestoreTrustedHeaderAfterStartup3(t *testing.T) { } func TestClient_Update(t *testing.T) { - const ( - chainID = "TestClient_Update" - ) - - var ( - keys = genPrivKeys(4) - // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! - vals = keys.ToValidators(20, 10) - bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") - header = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - ) - - primary := mockp.New( - chainID, - map[int64]*types.SignedHeader{ - // trusted header - 1: header, - // interim header (3/3 signed) - 2: keys.GenSignedHeader(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - // last header (3/3 signed) - 3: keys.GenSignedHeader(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - 3: vals, - 4: vals, - }, - ) c, err := NewClient( chainID, - TrustOptions{ - Period: 4 * time.Hour, - Height: 1, - Hash: header.Hash(), - }, - primary, - []provider.Provider{primary}, + trustOptions, + fullNode, + []provider.Provider{fullNode}, dbs.New(dbm.NewMemDB(), chainID), Logger(log.TestingLogger()), ) @@ -790,48 +606,12 @@ func TestClient_Update(t *testing.T) { } func TestClient_Concurrency(t *testing.T) { - const ( - chainID = "TestClient_Concurrency" - ) - - var ( - keys = genPrivKeys(4) - // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! - vals = keys.ToValidators(20, 10) - bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") - header = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - ) - - primary := mockp.New( - chainID, - map[int64]*types.SignedHeader{ - // trusted header - 1: header, - // interim header (3/3 signed) - 2: keys.GenSignedHeader(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - // last header (3/3 signed) - 3: keys.GenSignedHeader(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - 3: vals, - 4: vals, - }, - ) c, err := NewClient( chainID, - TrustOptions{ - Period: 4 * time.Hour, - Height: 1, - Hash: header.Hash(), - }, - primary, - []provider.Provider{primary}, + trustOptions, + fullNode, + []provider.Provider{fullNode}, dbs.New(dbm.NewMemDB(), chainID), UpdatePeriod(0), Logger(log.TestingLogger()), @@ -875,93 +655,26 @@ func TestClient_Concurrency(t *testing.T) { } func TestProvider_Replacement(t *testing.T) { - const ( - chainID = "TestProvider_Replacement" - ) - - var ( - keys = genPrivKeys(4) - // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! - vals = keys.ToValidators(20, 10) - bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") - header = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - primary = mockp.NewDeadMock(chainID) - witness = mockp.New( - chainID, - map[int64]*types.SignedHeader{ - // trusted header - 1: header, - // interim header (3/3 signed) - 2: keys.GenSignedHeader(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - // last header (3/3 signed) - 3: keys.GenSignedHeader(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)), - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - 3: vals, - 4: vals, - }, - ) - ) c, err := NewClient( chainID, - TrustOptions{ - Period: 4 * time.Hour, - Height: 1, - Hash: header.Hash(), - }, - primary, - []provider.Provider{witness}, + trustOptions, + deadNode, + []provider.Provider{fullNode, fullNode}, dbs.New(dbm.NewMemDB(), chainID), UpdatePeriod(0), Logger(log.TestingLogger()), MaxRetryAttempts(1), ) require.NoError(t, err) - err = c.Start() + err = c.Update(bTime.Add(2 * time.Hour)) require.NoError(t, err) - defer c.Stop() - assert.NotEqual(t, c.Primary(), primary) - assert.Equal(t, 0, len(c.Witnesses())) + assert.NotEqual(t, c.Primary(), deadNode) + assert.Equal(t, 1, len(c.Witnesses())) } func TestProvider_TrustedHeaderFetchesMissingHeader(t *testing.T) { - const ( - chainID = "TestProvider_TrustedHeaderFetchesMissingHeader" - ) - - var ( - keys = genPrivKeys(4) - // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! - vals = keys.ToValidators(20, 10) - bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") - h1 = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - h2 = keys.GenSignedHeaderLastBlockID(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys), types.BlockID{Hash: h1.Hash()}) - h3 = keys.GenSignedHeaderLastBlockID(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys), types.BlockID{Hash: h2.Hash()}) - primary = mockp.New( - chainID, - map[int64]*types.SignedHeader{ - 1: h1, - 2: h2, - 3: h3, - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - 3: vals, - 4: vals, - }, - ) - ) c, err := NewClient( chainID, @@ -970,8 +683,8 @@ func TestProvider_TrustedHeaderFetchesMissingHeader(t *testing.T) { Height: 3, Hash: h3.Hash(), }, - primary, - []provider.Provider{primary}, + fullNode, + []provider.Provider{fullNode}, dbs.New(dbm.NewMemDB(), chainID), UpdatePeriod(0), Logger(log.TestingLogger()), @@ -995,35 +708,18 @@ func TestProvider_TrustedHeaderFetchesMissingHeader(t *testing.T) { } func Test_NewClientFromTrustedStore(t *testing.T) { - const ( - chainID = "Test_NewClientFromTrustedStore" - ) - - var ( - keys = genPrivKeys(4) - // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! - vals = keys.ToValidators(20, 10) - bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") - header = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - primary = mockp.New( - chainID, - map[int64]*types.SignedHeader{}, - map[int64]*types.ValidatorSet{}, - ) - ) // 1) Initiate DB and fill with a "trusted" header db := dbs.New(dbm.NewMemDB(), chainID) - err := db.SaveSignedHeaderAndNextValidatorSet(header, vals) + err := db.SaveSignedHeaderAndNextValidatorSet(h1, vals) require.NoError(t, err) // 2) Initialize Lite Client from Trusted Store c, err := NewClientFromTrustedStore( chainID, - 1*time.Hour, - primary, - []provider.Provider{primary}, + trustPeriod, + fullNode, + []provider.Provider{fullNode}, db, ) require.NoError(t, err) @@ -1035,47 +731,12 @@ func Test_NewClientFromTrustedStore(t *testing.T) { } func TestCompareWithWitnesses(t *testing.T) { - const ( - chainID = "TestCompareWithWitnesses" - ) - - var ( - keys = genPrivKeys(4) - // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! - vals = keys.ToValidators(20, 10) - bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") - h1 = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) - h2 = keys.GenSignedHeaderLastBlockID(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys), types.BlockID{Hash: h1.Hash()}) - h3 = keys.GenSignedHeaderLastBlockID(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals, - []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys), types.BlockID{Hash: h2.Hash()}) - liveProvider = mockp.New( - chainID, - map[int64]*types.SignedHeader{ - 1: h1, - 2: h2, - 3: h3, - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - 3: vals, - 4: vals, - }, - ) - deadProvider = mockp.NewDeadMock(chainID) - ) c, err := NewClient( chainID, - TrustOptions{ - Period: 1 * time.Hour, - Height: 2, - Hash: h2.Hash(), - }, - liveProvider, - []provider.Provider{deadProvider, deadProvider, deadProvider}, + trustOptions, + fullNode, + []provider.Provider{deadNode, deadNode, deadNode}, dbs.New(dbm.NewMemDB(), chainID), UpdatePeriod(0), Logger(log.TestingLogger()), From ab6ac6d435225a5501084654d53ac862228315fe Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Tue, 11 Feb 2020 17:30:26 +0100 Subject: [PATCH 40/45] lite2: improve string output of all existing providers (#4387) before: &http{AFBSD743A...} after: http{https://127.0.0.1:26657} Co-authored-by: Marko --- lite2/provider/http/http.go | 6 +++++ lite2/provider/mock/deadmock.go | 33 ++++++++++++++++++++++++++++ lite2/provider/mock/mock.go | 39 ++++++++++++++------------------- lite2/provider/provider.go | 4 +++- rpc/client/httpclient.go | 6 +++++ 5 files changed, 65 insertions(+), 23 deletions(-) create mode 100644 lite2/provider/mock/deadmock.go diff --git a/lite2/provider/http/http.go b/lite2/provider/http/http.go index 5e9fc5192..bbe6e92ae 100644 --- a/lite2/provider/http/http.go +++ b/lite2/provider/http/http.go @@ -13,6 +13,8 @@ import ( type SignStatusClient interface { rpcclient.SignClient rpcclient.StatusClient + // Remote returns the remote network address in a string form. + Remote() string } // http provider uses an RPC client (or SignStatusClient more generally) to @@ -45,6 +47,10 @@ func (p *http) ChainID() string { return p.chainID } +func (p *http) String() string { + return fmt.Sprintf("http{%s}", p.client.Remote()) +} + // SignedHeader fetches a SignedHeader at the given height and checks the // chainID matches. func (p *http) SignedHeader(height int64) (*types.SignedHeader, error) { diff --git a/lite2/provider/mock/deadmock.go b/lite2/provider/mock/deadmock.go new file mode 100644 index 000000000..77c474411 --- /dev/null +++ b/lite2/provider/mock/deadmock.go @@ -0,0 +1,33 @@ +package mock + +import ( + "errors" + + "github.com/tendermint/tendermint/lite2/provider" + "github.com/tendermint/tendermint/types" +) + +type deadMock struct { + chainID string +} + +// NewDeadMock creates a mock provider that always errors. +func NewDeadMock(chainID string) provider.Provider { + return &deadMock{chainID: chainID} +} + +func (p *deadMock) ChainID() string { + return p.chainID +} + +func (p *deadMock) String() string { + return "deadMock" +} + +func (p *deadMock) SignedHeader(height int64) (*types.SignedHeader, error) { + return nil, errors.New("no response from provider") +} + +func (p *deadMock) ValidatorSet(height int64) (*types.ValidatorSet, error) { + return nil, errors.New("no response from provider") +} diff --git a/lite2/provider/mock/mock.go b/lite2/provider/mock/mock.go index f41358345..7ff7bc9a1 100644 --- a/lite2/provider/mock/mock.go +++ b/lite2/provider/mock/mock.go @@ -1,7 +1,8 @@ package mock import ( - "github.com/pkg/errors" + "fmt" + "strings" "github.com/tendermint/tendermint/lite2/provider" "github.com/tendermint/tendermint/types" @@ -23,10 +24,25 @@ func New(chainID string, headers map[int64]*types.SignedHeader, vals map[int64]* } } +// ChainID returns the blockchain ID. func (p *mock) ChainID() string { return p.chainID } +func (p *mock) String() string { + var headers strings.Builder + for _, h := range p.headers { + fmt.Fprintf(&headers, " %d:%X", h.Height, h.Hash()) + } + + var vals strings.Builder + for _, v := range p.vals { + fmt.Fprintf(&vals, " %X", v.Hash()) + } + + return fmt.Sprintf("mock{headers: %s, vals: %v}", headers.String(), vals.String()) +} + func (p *mock) SignedHeader(height int64) (*types.SignedHeader, error) { if height == 0 && len(p.headers) > 0 { return p.headers[int64(len(p.headers))], nil @@ -46,24 +62,3 @@ func (p *mock) ValidatorSet(height int64) (*types.ValidatorSet, error) { } return nil, provider.ErrValidatorSetNotFound } - -type deadMock struct { - chainID string -} - -// NewDeadMock creates a mock provider that always errors. -func NewDeadMock(chainID string) provider.Provider { - return &deadMock{chainID: chainID} -} - -func (p *deadMock) ChainID() string { - return p.chainID -} - -func (p *deadMock) SignedHeader(height int64) (*types.SignedHeader, error) { - return nil, errors.New("no response from provider") -} - -func (p *deadMock) ValidatorSet(height int64) (*types.ValidatorSet, error) { - return nil, errors.New("no response from provider") -} diff --git a/lite2/provider/provider.go b/lite2/provider/provider.go index 3f146fc6b..773e17e32 100644 --- a/lite2/provider/provider.go +++ b/lite2/provider/provider.go @@ -1,6 +1,8 @@ package provider -import "github.com/tendermint/tendermint/types" +import ( + "github.com/tendermint/tendermint/types" +) // Provider provides information for the lite client to sync (verification // happens in the client). diff --git a/rpc/client/httpclient.go b/rpc/client/httpclient.go index 021df82e6..c844113c3 100644 --- a/rpc/client/httpclient.go +++ b/rpc/client/httpclient.go @@ -123,10 +123,16 @@ func NewHTTPWithClient(remote, wsEndpoint string, client *http.Client) (*HTTP, e var _ Client = (*HTTP)(nil) +// SetLogger sets a logger. func (c *HTTP) SetLogger(l log.Logger) { c.WSEvents.SetLogger(l) } +// Remote returns the remote network address in a string form. +func (c *HTTP) Remote() string { + return c.remote +} + // NewBatch creates a new batch client for this HTTP client. func (c *HTTP) NewBatch() *BatchHTTP { rpcBatch := c.rpc.NewRequestBatch() From b712c1cbb53b83097324dcb4ef9803c1f982025b Mon Sep 17 00:00:00 2001 From: Erik Grinaker Date: Tue, 11 Feb 2020 18:20:26 +0100 Subject: [PATCH 41/45] autofile: resolve relative paths (#4390) Fixes #2649 --- libs/autofile/autofile.go | 6 ++++++ libs/autofile/autofile_test.go | 36 ++++++++++++++++++++++++++-------- libs/autofile/group.go | 6 ++++-- libs/autofile/group_test.go | 23 ++++++++++++++++++++++ 4 files changed, 61 insertions(+), 10 deletions(-) diff --git a/libs/autofile/autofile.go b/libs/autofile/autofile.go index 3a6244894..061726f7d 100644 --- a/libs/autofile/autofile.go +++ b/libs/autofile/autofile.go @@ -3,6 +3,7 @@ package autofile import ( "os" "os/signal" + "path/filepath" "sync" "syscall" "time" @@ -57,6 +58,11 @@ type AutoFile struct { // an error, it will be of type *PathError or *ErrPermissionsChanged (if file's // permissions got changed (should be 0600)). func OpenAutoFile(path string) (*AutoFile, error) { + var err error + path, err = filepath.Abs(path) + if err != nil { + return nil, err + } af := &AutoFile{ ID: tmrand.Str(12) + ":" + path, Path: path, diff --git a/libs/autofile/autofile_test.go b/libs/autofile/autofile_test.go index 664264cdc..24ca6343d 100644 --- a/libs/autofile/autofile_test.go +++ b/libs/autofile/autofile_test.go @@ -3,26 +3,34 @@ package autofile import ( "io/ioutil" "os" + "path/filepath" "syscall" "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" tmos "github.com/tendermint/tendermint/libs/os" ) func TestSIGHUP(t *testing.T) { - // First, create an AutoFile writing to a tempfile dir - file, err := ioutil.TempFile("", "sighup_test") + origDir, err := os.Getwd() require.NoError(t, err) - err = file.Close() - require.NoError(t, err) - name := file.Name() + defer os.Chdir(origDir) - // Here is the actual AutoFile + // First, create a temporary directory and move into it + dir, err := ioutil.TempDir("", "sighup_test") + require.NoError(t, err) + defer os.RemoveAll(dir) + err = os.Chdir(dir) + require.NoError(t, err) + + // Create an AutoFile in the temporary directory + name := "sighup_test" af, err := OpenAutoFile(name) require.NoError(t, err) + require.True(t, filepath.IsAbs(af.Path)) // Write to the file. _, err = af.Write([]byte("Line 1\n")) @@ -34,6 +42,13 @@ func TestSIGHUP(t *testing.T) { err = os.Rename(name, name+"_old") require.NoError(t, err) + // Move into a different temporary directory + otherDir, err := ioutil.TempDir("", "sighup_test_other") + require.NoError(t, err) + defer os.RemoveAll(otherDir) + err = os.Chdir(otherDir) + require.NoError(t, err) + // Send SIGHUP to self. syscall.Kill(syscall.Getpid(), syscall.SIGHUP) @@ -49,12 +64,17 @@ func TestSIGHUP(t *testing.T) { require.NoError(t, err) // Both files should exist - if body := tmos.MustReadFile(name + "_old"); string(body) != "Line 1\nLine 2\n" { + if body := tmos.MustReadFile(filepath.Join(dir, name+"_old")); string(body) != "Line 1\nLine 2\n" { t.Errorf("unexpected body %s", body) } - if body := tmos.MustReadFile(name); string(body) != "Line 3\nLine 4\n" { + if body := tmos.MustReadFile(filepath.Join(dir, name)); string(body) != "Line 3\nLine 4\n" { t.Errorf("unexpected body %s", body) } + + // The current directory should be empty + files, err := ioutil.ReadDir(".") + require.NoError(t, err) + assert.Empty(t, files) } // // Manually modify file permissions, close, and reopen using autofile: diff --git a/libs/autofile/group.go b/libs/autofile/group.go index e859149b9..ca9f57003 100644 --- a/libs/autofile/group.go +++ b/libs/autofile/group.go @@ -6,7 +6,6 @@ import ( "fmt" "io" "os" - "path" "path/filepath" "regexp" "strconv" @@ -79,7 +78,10 @@ type Group struct { // OpenGroup creates a new Group with head at headPath. It returns an error if // it fails to open head file. func OpenGroup(headPath string, groupOptions ...func(*Group)) (g *Group, err error) { - dir := path.Dir(headPath) + dir, err := filepath.Abs(filepath.Dir(headPath)) + if err != nil { + return nil, err + } head, err := OpenAutoFile(headPath) if err != nil { return nil, err diff --git a/libs/autofile/group_test.go b/libs/autofile/group_test.go index a91ef0633..de29a0fba 100644 --- a/libs/autofile/group_test.go +++ b/libs/autofile/group_test.go @@ -4,6 +4,7 @@ import ( "io" "io/ioutil" "os" + "path/filepath" "testing" "github.com/stretchr/testify/assert" @@ -105,6 +106,23 @@ func TestCheckHeadSizeLimit(t *testing.T) { func TestRotateFile(t *testing.T) { g := createTestGroupWithHeadSizeLimit(t, 0) + + // Create a different temporary directory and move into it, to make sure + // relative paths are resolved at Group creation + origDir, err := os.Getwd() + require.NoError(t, err) + defer os.Chdir(origDir) + + dir, err := ioutil.TempDir("", "rotate_test") + require.NoError(t, err) + defer os.RemoveAll(dir) + err = os.Chdir(dir) + require.NoError(t, err) + + require.True(t, filepath.IsAbs(g.Head.Path)) + require.True(t, filepath.IsAbs(g.Dir)) + + // Create and rotate files g.WriteLine("Line 1") g.WriteLine("Line 2") g.WriteLine("Line 3") @@ -129,6 +147,11 @@ func TestRotateFile(t *testing.T) { t.Errorf("got unexpected contents: [%v]", string(body2)) } + // Make sure there are no files in the current, temporary directory + files, err := ioutil.ReadDir(".") + require.NoError(t, err) + assert.Empty(t, files) + // Cleanup destroyTestGroup(t, g) } From 2b709e79e7ea5ca8fa5b5a5127b535ae708318c0 Mon Sep 17 00:00:00 2001 From: Marko Date: Wed, 12 Feb 2020 12:45:24 +0100 Subject: [PATCH 42/45] make: remove sentry setup cmds (#4383) * make: remove sentry setup cmds removal of make comands for sentry setup. it was unclear if they were being maintained and there has not been a mention of people using them - closes #4379 Signed-off-by: Marko Baricevic * remove depreacted readme * add not being maintained section to docs --- Makefile | 25 +------- docs/networks/terraform-and-ansible.md | 2 + networks/local/README.md | 82 +------------------------- 3 files changed, 5 insertions(+), 104 deletions(-) diff --git a/Makefile b/Makefile index 540d157b8..610a0c6b5 100644 --- a/Makefile +++ b/Makefile @@ -180,27 +180,6 @@ localnet-start: localnet-stop build-docker-localnode localnet-stop: docker-compose down -############################################################################### -### Remote full-nodes (sentry) using terraform and ansible ### -############################################################################### - -# Server management -sentry-start: - @if [ -z "$(DO_API_TOKEN)" ]; then echo "DO_API_TOKEN environment variable not set." ; false ; fi - @if ! [ -f $(HOME)/.ssh/id_rsa.pub ]; then ssh-keygen ; fi - cd networks/remote/terraform && terraform init && terraform apply -var DO_API_TOKEN="$(DO_API_TOKEN)" -var SSH_KEY_FILE="$(HOME)/.ssh/id_rsa.pub" - @if ! [ -f $(CURDIR)/build/node0/config/genesis.json ]; then docker run --rm -v $(CURDIR)/build:/tendermint:Z tendermint/localnode testnet --v 0 --n 4 --o . ; fi - cd networks/remote/ansible && ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i inventory/digital_ocean.py -l sentrynet install.yml - @echo "Next step: Add your validator setup in the genesis.json and config.tml files and run \"make sentry-config\". (Public key of validator, chain ID, peer IP and node ID.)" - -# Configuration management -sentry-config: - cd networks/remote/ansible && ansible-playbook -i inventory/digital_ocean.py -l sentrynet config.yml -e BINARY=$(CURDIR)/build/tendermint -e CONFIGDIR=$(CURDIR)/build - -sentry-stop: - @if [ -z "$(DO_API_TOKEN)" ]; then echo "DO_API_TOKEN environment variable not set." ; false ; fi - cd networks/remote/terraform && terraform destroy -var DO_API_TOKEN="$(DO_API_TOKEN)" -var SSH_KEY_FILE="$(HOME)/.ssh/id_rsa.pub" - # Build hooks for dredd, to skip or add information on some steps build-contract-tests-hooks: ifeq ($(OS),Windows_NT) @@ -221,7 +200,7 @@ contract-tests: # unless there is a reason not to. # https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html .PHONY: check build build_race build_abci dist install install_abci check_tools tools update_tools draw_deps \ - gen_certs clean_certs grpc_dbserver fmt build-linux localnet-start \ - localnet-stop build-docker build-docker-localnode sentry-start sentry-config sentry-stop \ + protoc_abci protoc_libs gen_certs clean_certs grpc_dbserver fmt build-linux localnet-start \ + localnet-stop build-docker build-docker-localnode protoc_grpc protoc_all \ build_c install_c test_with_deadlock cleanup_after_test_with_deadlock lint build-contract-tests-hooks contract-tests \ build_c-amazonlinux diff --git a/docs/networks/terraform-and-ansible.md b/docs/networks/terraform-and-ansible.md index b55563ea9..ec6cee1ba 100644 --- a/docs/networks/terraform-and-ansible.md +++ b/docs/networks/terraform-and-ansible.md @@ -4,6 +4,8 @@ order: 3 # Terraform & Ansible +> Note: These commands/files are not being maintained by the tendermint team currently. Please use them carefully. + Automated deployments are done using [Terraform](https://www.terraform.io/) to create servers on Digital Ocean then [Ansible](http://www.ansible.com/) to create and manage diff --git a/networks/local/README.md b/networks/local/README.md index 8d4299693..dcb31ae71 100644 --- a/networks/local/README.md +++ b/networks/local/README.md @@ -1,83 +1,3 @@ # Local Cluster with Docker Compose -DEPRECATED! - -See the [docs](https://tendermint.com/docs/networks/docker-compose.html). - -## Requirements - -- [Install tendermint](/docs/install.md) -- [Install docker](https://docs.docker.com/engine/installation/) -- [Install docker-compose](https://docs.docker.com/compose/install/) - -## Build - -Build the `tendermint` binary and the `tendermint/localnode` docker image. - -Note the binary will be mounted into the container so it can be updated without -rebuilding the image. - -``` -cd $GOPATH/src/github.com/tendermint/tendermint - -# Build the linux binary in ./build -make build-linux - -# Build tendermint/localnode image -make build-docker-localnode -``` - - -## Run a testnet - -To start a 4 node testnet run: - -``` -make localnet-start -``` - -The nodes bind their RPC servers to ports 26657, 26660, 26662, and 26664 on the host. -This file creates a 4-node network using the localnode image. -The nodes of the network expose their P2P and RPC endpoints to the host machine on ports 26656-26657, 26659-26660, 26661-26662, and 26663-26664 respectively. - -To update the binary, just rebuild it and restart the nodes: - -``` -make build-linux -make localnet-stop -make localnet-start -``` - -## Configuration - -The `make localnet-start` creates files for a 4-node testnet in `./build` by calling the `tendermint testnet` command. - -The `./build` directory is mounted to the `/tendermint` mount point to attach the binary and config files to the container. - -For instance, to create a single node testnet: - -``` -cd $GOPATH/src/github.com/tendermint/tendermint - -# Clear the build folder -rm -rf ./build - -# Build binary -make build-linux - -# Create configuration -docker run -e LOG="stdout" -v `pwd`/build:/tendermint tendermint/localnode testnet --o . --v 1 - -#Run the node -docker run -v `pwd`/build:/tendermint tendermint/localnode - -``` - -## Logging - -Log is saved under the attached volume, in the `tendermint.log` file. If the `LOG` environment variable is set to `stdout` at start, the log is not saved, but printed on the screen. - -## Special binaries - -If you have multiple binaries with different names, you can specify which one to run with the BINARY environment variable. The path of the binary is relative to the attached volume. - +See the [docs](https://docs.tendermint.com/master/networks/docker-compose.html). From 67837e5f40cbfffa35d20c99c08e259d26e672fe Mon Sep 17 00:00:00 2001 From: Marko Date: Wed, 12 Feb 2020 15:50:07 +0100 Subject: [PATCH 43/45] readme: fix link to original paper (#4391) Signed-off-by: Marko Baricevic --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index bd3cc866e..61391f51e 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,5 @@ Additional documentation is found [here](/docs/tools). - [The latest gossip on BFT consensus](https://arxiv.org/abs/1807.04938) - [Master's Thesis on Tendermint](https://atrium.lib.uoguelph.ca/xmlui/handle/10214/9769) -- [Original Whitepaper](https://github.com/tendermint/spec) - - You can find the link at the bottom of the readme +- [Original Whitepaper: "Tendermint: Consensus Without Mining"](https://tendermint.com/static/docs/tendermint.pdf) - [Blog](https://blog.cosmos.network/tendermint/home) From fb5751d2c597a8239325a9dc293f613b96d295ba Mon Sep 17 00:00:00 2001 From: Marko Date: Thu, 13 Feb 2020 16:38:00 +0100 Subject: [PATCH 44/45] release: minor release 0.33.1 (#4401) * release: minor release 0.33.1 - minor release for 0.33.1 Signed-off-by: Marko Baricevic * remvoe wording * version bump --- CHANGELOG.md | 24 ++++++++++++++++++++++++ CHANGELOG_PENDING.md | 12 +----------- CONTRIBUTING.md | 2 +- version/version.go | 2 +- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3dbe07d9..6040849c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +## v0.33.1 + +*Feburary 13, 2020* + +Special thanks to external contributors on this release: +@princesinha19 + +Friendly reminder, we have a [bug bounty +program](https://hackerone.com/tendermint). + +### FEATURES: + +- [rpc] [\#3333](https://github.com/tendermint/tendermint/issues/3333) Add `order_by` to `/tx_search` endpoint, allowing to change default ordering from asc to desc (@princesinha19) + +### IMPROVEMENTS: + +- [proto] [\#4369](https://github.com/tendermint/tendermint/issues/4369) Add [buf](https://buf.build/) for usage with linting and checking if there are breaking changes with the master branch. +- [proto] [\#4369](https://github.com/tendermint/tendermint/issues/4369) Add `make proto-gen` cmd to generate proto stubs outside of GOPATH. + +### BUG FIXES: + +- [node] [\#4311](https://github.com/tendermint/tendermint/issues/4311) Use `GRPCMaxOpenConnections` when creating the gRPC server, not `MaxOpenConnections` +- [rpc] [\#4319](https://github.com/tendermint/tendermint/issues/4319) Check `BlockMeta` is not nil in `/block` & `/block_by_hash` + ## v0.33 Special thanks to external contributors on this release: @mrekucci, @PSalant726, @princesinha19, @greg-szabo, @dongsam, @cuonglm, @jgimeno, @yenkhoon diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 50ce5d8d6..bf41c1b5b 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -1,9 +1,8 @@ -## v0.33.1 +## v0.33.2 \*\* Special thanks to external contributors on this release: -@princesinha19 Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint). @@ -18,15 +17,6 @@ program](https://hackerone.com/tendermint). ### FEATURES: -- [rpc] [\#3333] Add `order_by` to `/tx_search` endpoint, allowing to change default ordering from asc to desc (more in the future) (@princesinha19) - ### IMPROVEMENTS: -- [proto] [\#4369] Add [buf](https://buf.build/) for usage with linting and checking if there are breaking changes with the master branch. -- [proto] [\#4369] Add `make proto-gen` cmd to generate proto stubs outside of GOPATH. - - ### BUG FIXES: - -- [node] [#\4311] Use `GRPCMaxOpenConnections` when creating the gRPC server, not `MaxOpenConnections` -- [rpc] [#\4319] Check `BlockMeta` is not nil in `/block` & `/block_by_hash` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7b348ad76..623cfb53a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,7 +31,7 @@ at the RFC stage will build collective understanding of the dimensions of the problems and help structure conversations around trade-offs. When the problem is well understood but the solution leads to large -strucural changes to the code base, these changes should be proposed in +structural changes to the code base, these changes should be proposed in the form of an [Architectural Decision Record (ADR)](./docs/architecture/). The ADR will help build consensus on an overall strategy to ensure the code base maintains coherence diff --git a/version/version.go b/version/version.go index 603e44702..57ef21f1f 100644 --- a/version/version.go +++ b/version/version.go @@ -20,7 +20,7 @@ const ( // Must be a string because scripts like dist.sh read this file. // XXX: Don't change the name of this variable or you will break // automation :) - TMCoreSemVer = "0.32.8" + TMCoreSemVer = "0.33.1" // ABCISemVer is the semantic version of the ABCI library ABCISemVer = "0.16.1" From 42d8bc5124ee0a6c3a82a9fc822bdc1754d4b264 Mon Sep 17 00:00:00 2001 From: Marko Baricevic Date: Thu, 13 Feb 2020 17:13:48 +0100 Subject: [PATCH 45/45] upgrade: update upgrade.md for protobuf changes Signed-off-by: Marko Baricevic --- UPGRADING.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/UPGRADING.md b/UPGRADING.md index dcf16d598..d568c6e94 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -7,9 +7,13 @@ a newer version of Tendermint Core. +## v0.33.1 + +This release is compatible with the previous version. The only change that is required is if you are fetching the protobuf files for application use. + ### Protobuf Changes -When upgrading to version you will have to fetch the `third_party` directory along with the updated proto files. +When upgrading to version 0.33.1 you will have to fetch the `third_party` directory along with the updated proto files. ## v0.33.0