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.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 be210ae52..bf41c1b5b 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -1,4 +1,4 @@ -## v0.33.1 +## v0.33.2 \*\* @@ -20,5 +20,3 @@ program](https://hackerone.com/tendermint). ### IMPROVEMENTS: ### BUG FIXES: - - diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 52d5532f5..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 @@ -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 a6c1df45c..610a0c6b5 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,18 +92,13 @@ 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 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,24 +107,12 @@ 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 - - -######################################## -### Formatting, linting, and vetting +############################################################################### +### Formatting, linting, and vetting ### +############################################################################### fmt: @go fmt ./... @@ -134,8 +123,9 @@ lint: DESTINATION = ./index.html.md -########################################################### -### Documentation +############################################################################### +### Documentation ### +############################################################################### build-docs: cd docs && \ @@ -154,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 @@ -188,26 +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) @@ -229,6 +201,6 @@ contract-tests: # 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 \ + 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/README.md b/README.md index 6d25546e1..61391f51e 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 @@ -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/ @@ -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) diff --git a/UPGRADING.md b/UPGRADING.md index bb531d32f..d568c6e94 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -3,6 +3,18 @@ This guide provides steps to be followed when you upgrade your applications to a newer version of Tendermint Core. +## Unreleased + + + +## 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 0.33.1 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. @@ -224,14 +236,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 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) 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..0d47ad9b3 100644 --- a/abci/types/types.proto +++ b/abci/types/types.proto @@ -1,12 +1,12 @@ 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 -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"; @@ -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/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/cmd/tendermint/commands/lite.go b/cmd/tendermint/commands/lite.go index b86714419..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,19 +109,20 @@ 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), ) if err != nil { return err } - c.SetLogger(liteLogger) p := lproxy.Proxy{ 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/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/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/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/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/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..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 "github.com/gogo/protobuf/gogoproto/gogo.proto"; +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/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/architecture/README.md b/docs/architecture/README.md index cc507ae78..7055a3676 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -64,3 +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-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/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/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 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. 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 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 ``` 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/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/docs/package-lock.json b/docs/package-lock.json index e96344500..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", @@ -9624,4 +10658,4 @@ "integrity": "sha1-4Se9nmb9hGvl6rSME5SIL3wOT5g=" } } -} \ No newline at end of file +} diff --git a/docs/package.json b/docs/package.json index 0358a91a3..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.73" + "vuepress-theme-cosmos": "^1.0.148" }, "devDependencies": { "@vuepress/plugin-google-analytics": "^1.2.0" 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/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/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/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/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 diff --git a/go.mod b/go.mod index 9fe06e48e..b52f7ca4b 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 @@ -25,12 +25,12 @@ 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 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.1 ) diff --git a/go.sum b/go.sum index fbbeb485e..19cfd4cb8 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= @@ -199,6 +201,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= @@ -284,6 +288,10 @@ 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= +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= 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) } 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..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 "github.com/gogo/protobuf/gogoproto/gogo.proto"; +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/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..668a46203 100644 --- a/lite2/client.go +++ b/lite2/client.go @@ -3,13 +3,15 @@ package lite import ( "bytes" "fmt" + "math/rand" + "sync" "time" "github.com/pkg/errors" + "github.com/tendermint/tendermint/crypto/tmhash" "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" @@ -42,13 +44,32 @@ 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 ( sequential mode = iota + 1 skipping + defaultUpdatePeriod = 5 * time.Second defaultRemoveNoLongerTrustedHeadersPeriod = 24 * time.Hour + defaultMaxRetryAttempts = 10 ) // Option sets a parameter for the light client. @@ -73,20 +94,16 @@ 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 } } -// 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 { +// UpdatePeriod option can be used to change default polling period (5s). +func UpdatePeriod(d time.Duration) Option { return func(c *Client) { - c.alternatives = providers + c.updatePeriod = d } } @@ -109,23 +126,42 @@ 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 + } +} + +// 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). // +// 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 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 // 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 @@ -134,11 +170,15 @@ type Client struct { // Highest next validator set from the store (height=H+1). trustedNextVals *types.ValidatorSet + // See UpdatePeriod option + updatePeriod time.Duration + // See RemoveNoLongerTrustedHeadersPeriod option removeNoLongerTrustedHeadersPeriod time.Duration - + // See ConfirmationFunction option confirmationFn func(action string) bool - quit chan struct{} + routinesWaitGroup sync.WaitGroup + quit chan struct{} logger log.Logger } @@ -147,34 +187,28 @@ 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) { - c := &Client{ - chainID: chainID, - trustingPeriod: trustOptions.Period, - verificationMode: skipping, - trustLevel: DefaultTrustLevel, - primary: primary, - trustedStore: trustedStore, - removeNoLongerTrustedHeadersPeriod: defaultRemoveNoLongerTrustedHeadersPeriod, - confirmationFn: func(action string) bool { return true }, - quit: make(chan struct{}), - logger: log.NewNopLogger(), + if err := trustOptions.ValidateBasic(); err != nil { + return nil, errors.Wrap(err, "invalid TrustOptions") } - for _, o := range options { - o(c) - } - - if err := c.restoreTrustedHeaderAndNextVals(); err != nil { + 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 @@ -187,8 +221,60 @@ func NewClient( } } - if c.removeNoLongerTrustedHeadersPeriod > 0 { - go c.removeNoLongerTrustedHeadersRoutine() + 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: trustingPeriod, + verificationMode: skipping, + trustLevel: DefaultTrustLevel, + maxRetryAttempts: defaultMaxRetryAttempts, + primary: primary, + witnesses: witnesses, + trustedStore: trustedStore, + updatePeriod: defaultUpdatePeriod, + removeNoLongerTrustedHeadersPeriod: defaultRemoveNoLongerTrustedHeadersPeriod, + confirmationFn: func(action string) bool { return true }, + quit: make(chan struct{}), + logger: log.NewNopLogger(), + } + + for _, o := range options { + 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 } return c, nil @@ -243,7 +329,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 } @@ -262,8 +348,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) @@ -297,7 +381,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 } @@ -312,7 +396,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 } @@ -330,7 +414,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 } @@ -339,21 +423,39 @@ func (c *Client) initializeWithTrustOptions(options TrustOptions) error { return c.updateTrustedHeaderAndVals(h, nextVals) } -// Stop stops the light client. +// 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() } -// 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. +// 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. // @@ -361,29 +463,44 @@ 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 has not been verified yet +// +// 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") } - 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 h == nil { - return nil, nil + 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} } @@ -391,13 +508,57 @@ func (c *Client) TrustedHeader(height int64, now time.Time) (*types.SignedHeader return h, nil } +// 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; +// - 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 (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 + } + + return c.trustedStore.ValidatorSet(height) +} + // 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 +567,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,17 +598,20 @@ 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()) + 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) } - if len(c.alternatives) > 0 { - if err := c.compareNewHeaderWithRandomAlternative(newHeader); err != nil { - return err - } + if err := c.compareNewHeaderWithWitnesses(newHeader); err != nil { + c.logger.Error("Error when comparing new header with one from a witness", "err", err) + return err } var err error @@ -462,20 +628,39 @@ 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) } -// Cleanup removes all the data (headers and validator sets) stored. +// 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 { - c.logger.Info("Cleanup everything") + c.logger.Info("Removing all the data") 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() @@ -490,7 +675,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++ { @@ -503,6 +688,10 @@ func (c *Client) cleanup(stopHeight int64) error { c.trustedHeader = nil c.trustedNextVals = nil + err = c.restoreTrustedHeaderAndNextVals() + if err != nil { + return err + } return nil } @@ -516,7 +705,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) } @@ -536,7 +725,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) } @@ -590,7 +779,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) } @@ -633,42 +822,140 @@ 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) } 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))] +// 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) - // 2. Fetch the header. - altHeader, err := p.SignedHeader(h.Height) + closestHeader, err := c.trustedStore.SignedHeaderAfter(height) if err != nil { - return errors.Wrapf(err, - "failed to obtain header #%d from alternative provider %v", h.Height, p) + return nil, errors.Wrapf(err, "can't get signed header after %d", height) } - // 3. Compare hashes. - if !bytes.Equal(h.Hash(), altHeader.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()) + // Perform backwards verification from closestHeader to header at the given + // height. + h, err := c.backwards(height, closestHeader, now) + if err != nil { + return nil, err } - return nil + // 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 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") + } + + 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 + + } + + // 4. Check that one responding witness has returned a matching header + if matchedHeader { + return nil + } + + time.Sleep(backoffTimeout(attempt)) + + } + + return errors.New("awaiting response from all witnesses exceeded dropout time") } func (c *Client) removeNoLongerTrustedHeadersRoutine() { + defer c.routinesWaitGroup.Done() + ticker := time.NewTicker(c.removeNoLongerTrustedHeadersPeriod) defer ticker.Stop() @@ -688,11 +975,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() @@ -700,6 +990,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++ { @@ -708,10 +1001,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 +1014,125 @@ func (c *Client) RemoveNoLongerTrustedHeaders(now time.Time) { } } } + +func (c *Client) autoUpdateRoutine() { + defer c.routinesWaitGroup.Done() + + ticker := time.NewTicker(c.updatePeriod) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + err := c.Update(time.Now()) + if err != nil { + c.logger.Error("Error during auto update", "err", err) + } + case <-c.quit: + return + } + } +} + +// 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) Update(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 + } + + latestHeader, latestVals, err := c.fetchHeaderAndValsAtHeight(0) + if err != nil { + return errors.Wrapf(err, "can't get latest header and vals") + } + + if latestHeader.Height > lastTrustedHeight { + err = c.VerifyHeader(latestHeader, latestVals, now) + if err != nil { + return err + } + + c.logger.Info("Advanced to new state", "height", latestHeader.Height, "hash", latestHeader.Hash()) + } + + 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 := uint16(1); attempt <= c.maxRetryAttempts; attempt++ { + c.providerMutex.Lock() + h, err := c.primary.SignedHeader(height) + c.providerMutex.Unlock() + 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)) + } + + 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 := uint16(1); attempt <= c.maxRetryAttempts; attempt++ { + c.providerMutex.Lock() + vals, err := c.primary.ValidatorSet(height) + c.providerMutex.Unlock() + if err == nil || err == provider.ErrValidatorSetNotFound { + return vals, 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 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 c7bafd6bb..b4823eaf9 100644 --- a/lite2/client_test.go +++ b/lite2/client_test.go @@ -1,6 +1,7 @@ package lite import ( + "sync" "testing" "time" @@ -10,24 +11,50 @@ 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" ) -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 ^ @@ -39,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, @@ -73,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)), @@ -94,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)), @@ -116,16 +141,17 @@ 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, tc.vals, ), + []provider.Provider{mockp.New( + chainID, + tc.otherHeaders, + tc.vals, + )}, dbs.New(dbm.NewMemDB(), chainID), SequentialVerification(), ) @@ -136,6 +162,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)) @@ -148,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) @@ -168,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, @@ -186,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)), @@ -207,89 +218,56 @@ 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, tc.vals, ), + []provider.Provider{mockp.New( + chainID, + tc.otherHeaders, + tc.vals, + )}, 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)) - ) c, 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(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, - }, - ), + trustOptions, + fullNode, + []provider.Provider{fullNode}, 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) defer c.Stop() - c.SetLogger(log.TestingLogger()) // Verify new headers. _, err = c.VerifyHeaderAtHeight(2, bTime.Add(2*time.Hour).Add(1*time.Second)) @@ -303,7 +281,7 @@ func TestClientRemovesNoLongerTrustedHeaders(t *testing.T) { // Check expired headers are no longer available. h, err := c.TrustedHeader(1, now) - assert.NoError(t, err) + assert.Error(t, err) assert.Nil(t, h) // Check not expired headers are available. @@ -313,110 +291,78 @@ 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)) - ) c, err := NewClient( chainID, - TrustOptions{ - Period: 4 * time.Hour, - Height: 1, - Hash: header.Hash(), - }, - mockp.New( - chainID, - map[int64]*types.SignedHeader{ - // trusted header - 1: header, - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - }, - ), + trustOptions, + fullNode, + []provider.Provider{fullNode}, dbs.New(dbm.NewMemDB(), chainID), + Logger(log.TestingLogger()), ) require.NoError(t, err) - c.SetLogger(log.TestingLogger()) + err = c.Start() + require.NoError(t, err) + c.Stop() c.Cleanup() // Check no headers exist after Cleanup. h, err := c.TrustedHeader(1, bTime.Add(1*time.Second)) - assert.NoError(t, err) + assert.Error(t, err) assert.Nil(t, h) } // 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) c, err := NewClient( chainID, - TrustOptions{ - Period: 4 * time.Hour, - Height: 1, - Hash: header.Hash(), - }, - mockp.New( - chainID, - map[int64]*types.SignedHeader{ - // trusted header - 1: header, - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - }, - ), + trustOptions, + fullNode, + []provider.Provider{fullNode}, trustedStore, + Logger(log.TestingLogger()), ) require.NoError(t, err) - c.SetLogger(log.TestingLogger()) + err = c.Start() + require.NoError(t, err) + defer c.Stop() 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 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{ @@ -424,21 +370,15 @@ 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()), ) require.NoError(t, err) - c.SetLogger(log.TestingLogger()) + err = c.Start() + require.NoError(t, err) + defer c.Stop() h, err := c.TrustedHeader(1, bTime.Add(1*time.Second)) assert.NoError(t, err) @@ -449,163 +389,137 @@ 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)) - c, err := NewClient( chainID, TrustOptions{ Period: 4 * time.Hour, Height: 2, - Hash: header2.Hash(), + Hash: h2.Hash(), }, - mockp.New( - chainID, - map[int64]*types.SignedHeader{ - 1: header, - 2: header2, - }, - map[int64]*types.ValidatorSet{ - 1: vals, - 2: vals, - 3: vals, - }, - ), + fullNode, + []provider.Provider{fullNode}, trustedStore, + Logger(log.TestingLogger()), ) require.NoError(t, err) - c.SetLogger(log.TestingLogger()) + 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)) 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: diffHeader1, + 2: diffHeader2, + }, + 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: diffHeader2.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()), ) require.NoError(t, err) - c.SetLogger(log.TestingLogger()) + 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)) - assert.NoError(t, err) + assert.Error(t, err) assert.Nil(t, h) } } // 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: h1, + 2: h2, + }, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: vals, + 3: vals, + }, + ) + c, err := NewClient( chainID, - TrustOptions{ - Period: 4 * time.Hour, - 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, - }, - ), + trustOptions, + primary, + []provider.Provider{primary}, trustedStore, + Logger(log.TestingLogger()), ) require.NoError(t, err) - c.SetLogger(log.TestingLogger()) + 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)) 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)) - assert.NoError(t, err) + assert.Error(t, err) assert.Nil(t, h) } @@ -613,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 @@ -625,6 +539,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{ @@ -632,20 +557,15 @@ 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()), ) require.NoError(t, err) - c.SetLogger(log.TestingLogger()) + 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)) @@ -655,7 +575,175 @@ func TestClientRestoreTrustedHeaderAfterStartup3(t *testing.T) { // Check we no longer have invalid 2nd header (+header2+). h, err = c.TrustedHeader(2, bTime.Add(2*time.Hour).Add(1*time.Second)) - assert.NoError(t, err) + assert.Error(t, err) assert.Nil(t, h) } } + +func TestClient_Update(t *testing.T) { + + c, err := NewClient( + chainID, + trustOptions, + fullNode, + []provider.Provider{fullNode}, + dbs.New(dbm.NewMemDB(), chainID), + Logger(log.TestingLogger()), + ) + require.NoError(t, err) + err = c.Start() + require.NoError(t, err) + defer c.Stop() + + // should result in downloading & verifying header #3 + err = c.Update(bTime.Add(2 * time.Hour)) + require.NoError(t, err) + + h, err := c.TrustedHeader(3, bTime.Add(2*time.Hour)) + assert.NoError(t, err) + require.NotNil(t, h) + assert.EqualValues(t, 3, h.Height) +} + +func TestClient_Concurrency(t *testing.T) { + + c, err := NewClient( + chainID, + trustOptions, + fullNode, + []provider.Provider{fullNode}, + dbs.New(dbm.NewMemDB(), chainID), + UpdatePeriod(0), + 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) + go func() { + defer wg.Done() + + // NOTE: Cleanup, Stop, VerifyHeaderAtHeight and Verify are not supposed + // to be concurrenly safe. + + assert.Equal(t, chainID, c.ChainID()) + + _, err := c.LastTrustedHeight() + assert.NoError(t, err) + + _, err = c.FirstTrustedHeight() + assert.NoError(t, err) + + 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) + }() + } + + wg.Wait() +} + +func TestProvider_Replacement(t *testing.T) { + + c, err := NewClient( + chainID, + trustOptions, + deadNode, + []provider.Provider{fullNode, fullNode}, + dbs.New(dbm.NewMemDB(), chainID), + UpdatePeriod(0), + Logger(log.TestingLogger()), + MaxRetryAttempts(1), + ) + require.NoError(t, err) + err = c.Update(bTime.Add(2 * time.Hour)) + require.NoError(t, err) + + assert.NotEqual(t, c.Primary(), deadNode) + assert.Equal(t, 1, len(c.Witnesses())) +} + +func TestProvider_TrustedHeaderFetchesMissingHeader(t *testing.T) { + + c, err := NewClient( + chainID, + TrustOptions{ + Period: 1 * time.Hour, + Height: 3, + Hash: h3.Hash(), + }, + fullNode, + []provider.Provider{fullNode}, + 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) +} + +func Test_NewClientFromTrustedStore(t *testing.T) { + + // 1) Initiate DB and fill with a "trusted" header + db := dbs.New(dbm.NewMemDB(), chainID) + err := db.SaveSignedHeaderAndNextValidatorSet(h1, vals) + require.NoError(t, err) + + // 2) Initialize Lite Client from Trusted Store + c, err := NewClientFromTrustedStore( + chainID, + trustPeriod, + fullNode, + []provider.Provider{fullNode}, + 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) +} + +func TestCompareWithWitnesses(t *testing.T) { + + c, err := NewClient( + chainID, + trustOptions, + fullNode, + []provider.Provider{deadNode, deadNode, deadNode}, + 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) + +} diff --git a/lite2/example_test.go b/lite2/example_test.go index 5afa07900..87e839d9b 100644 --- a/lite2/example_test.go +++ b/lite2/example_test.go @@ -8,18 +8,18 @@ import ( "testing" "time" - "github.com/pkg/errors" - dbm "github.com/tendermint/tm-db" "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" ) -func TestExample_Client(t *testing.T) { +// Automatically getting new headers and verifying them. +func TestExample_Client_AutoUpdate(t *testing.T) { // give Tendermint time to generate some blocks time.Sleep(5 * time.Second) @@ -34,12 +34,12 @@ func TestExample_Client(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) } @@ -56,13 +56,90 @@ func TestExample_Client(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()), ) if err != nil { stdlog.Fatal(err) } - c.SetLogger(log.TestingLogger()) + err = c.Start() + if err != nil { + stdlog.Fatal(err) + } + defer func() { + c.Stop() + c.Cleanup() + }() + + time.Sleep(2 * time.Second) + + h, err := c.TrustedHeader(0, time.Now()) + if err != nil { + stdlog.Fatal(err) + } + + fmt.Println("got header", h.Height) + // Output: got header 3 +} + +// Manually getting headers and verifying them. +func TestExample_Client_ManualUpdate(t *testing.T) { + // give Tendermint time to generate some blocks + time.Sleep(5 * time.Second) + + dbDir, err := ioutil.TempDir("", "lite-client-example") + if err != nil { + stdlog.Fatal(err) + } + defer os.RemoveAll(dbDir) + + var ( + config = rpctest.GetConfig() + chainID = config.ChainID() + ) + + primary, err := httpp.New(chainID, config.RPC.ListenAddress) + if err != nil { + stdlog.Fatal(err) + } + + header, err := primary.SignedHeader(2) + if err != nil { + stdlog.Fatal(err) + } + + db, err := dbm.NewGoLevelDB("lite-client-db", dbDir) + if err != nil { + stdlog.Fatal(err) + } + + c, err := NewClient( + chainID, + TrustOptions{ + Period: 504 * time.Hour, // 21 days + Height: 2, + Hash: header.Hash(), + }, + primary, + []provider.Provider{primary}, // TODO: primary should not be used here + dbs.New(db, chainID), + UpdatePeriod(0), + Logger(log.TestingLogger()), + ) + if err != nil { + stdlog.Fatal(err) + } + err = c.Start() + if err != nil { + stdlog.Fatal(err) + } + defer func() { + c.Stop() + c.Cleanup() + }() _, err = c.VerifyHeaderAtHeight(3, time.Now()) if err != nil { @@ -78,70 +155,6 @@ func TestExample_Client(t *testing.T) { // Output: got header 3 } -func TestExample_AutoClient(t *testing.T) { - // give Tendermint time to generate some blocks - time.Sleep(5 * time.Second) - - dbDir, err := ioutil.TempDir("", "lite-client-example") - if err != nil { - stdlog.Fatal(err) - } - defer os.RemoveAll(dbDir) - - var ( - config = rpctest.GetConfig() - chainID = config.ChainID() - ) - - provider, err := httpp.New(chainID, config.RPC.ListenAddress) - if err != nil { - stdlog.Fatal(err) - } - - header, err := provider.SignedHeader(2) - if err != nil { - stdlog.Fatal(err) - } - - db, err := dbm.NewGoLevelDB("lite-client-db", dbDir) - if err != nil { - stdlog.Fatal(err) - } - - base, err := NewClient( - chainID, - TrustOptions{ - Period: 504 * time.Hour, // 21 days - Height: 2, - Hash: header.Hash(), - }, - provider, - dbs.New(db, chainID), - ) - if err != nil { - stdlog.Fatal(err) - } - base.SetLogger(log.TestingLogger()) - - c := NewAutoClient(base, 1*time.Second) - defer c.Stop() - - select { - case h := <-c.TrustedHeaders(): - fmt.Println("got header", h.Height) - // Output: got header 3 - case err := <-c.Errs(): - switch errors.Cause(err).(type) { - case ErrOldHeaderExpired: - // reobtain trust height and hash - stdlog.Fatal(err) - default: - // try with another full node - stdlog.Fatal(err) - } - } -} - func TestMain(m *testing.M) { // start a tendermint node (and kvstore) in the background to test against app := kvstore.NewApplication() diff --git a/lite2/provider/errors.go b/lite2/provider/errors.go new file mode 100644 index 000000000..05a242acd --- /dev/null +++ b/lite2/provider/errors.go @@ -0,0 +1,12 @@ +package provider + +import "errors" + +var ( + // ErrSignedHeaderNotFound is returned when a provider can't find the + // requested header. + ErrSignedHeaderNotFound = errors.New("signed header not found") + // ErrValidatorSetNotFound is returned when a provider can't find the + // requested validator set. + ErrValidatorSetNotFound = errors.New("validator set not found") +) diff --git a/lite2/provider/http/http.go b/lite2/provider/http/http.go index 24c9d5527..bbe6e92ae 100644 --- a/lite2/provider/http/http.go +++ b/lite2/provider/http/http.go @@ -2,6 +2,7 @@ package http import ( "fmt" + "strings" "github.com/tendermint/tendermint/lite2/provider" rpcclient "github.com/tendermint/tendermint/rpc/client" @@ -12,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 @@ -44,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) { @@ -54,6 +61,10 @@ func (p *http) SignedHeader(height int64) (*types.SignedHeader, error) { commit, err := p.client.Commit(h) if err != nil { + // TODO: standartise errors on the RPC side + if strings.Contains(err.Error(), "height must be less than or equal") { + return nil, provider.ErrSignedHeaderNotFound + } return nil, err } @@ -76,6 +87,10 @@ func (p *http) ValidatorSet(height int64) (*types.ValidatorSet, error) { const maxPerPage = 100 res, err := p.client.Validators(h, 0, maxPerPage) if err != nil { + // TODO: standartise errors on the RPC side + if strings.Contains(err.Error(), "height must be less than or equal") { + return nil, provider.ErrValidatorSetNotFound + } return nil, err } 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 83548e2c3..7ff7bc9a1 100644 --- a/lite2/provider/mock/mock.go +++ b/lite2/provider/mock/mock.go @@ -1,21 +1,21 @@ package mock import ( - "github.com/pkg/errors" + "fmt" + "strings" "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, @@ -24,20 +24,41 @@ 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 + } if _, ok := p.headers[height]; ok { return p.headers[height], nil } - return nil, errors.Errorf("no header at height %d", height) + return nil, provider.ErrSignedHeaderNotFound } 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 } - return nil, errors.Errorf("no vals for height %d", height) + return nil, provider.ErrValidatorSetNotFound } diff --git a/lite2/provider/provider.go b/lite2/provider/provider.go index 14a1df993..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). @@ -17,7 +19,7 @@ type Provider interface { // If the provider fails to fetch the SignedHeader due to the IO or other // issues, an error will be returned. // If there's no SignedHeader for the given height, ErrSignedHeaderNotFound - // will be returned. + // error is returned. SignedHeader(height int64) (*types.SignedHeader, error) // ValidatorSet returns the ValidatorSet that corresponds to height. @@ -28,6 +30,6 @@ type Provider interface { // If the provider fails to fetch the ValidatorSet due to the IO or other // issues, an error will be returned. // If there's no ValidatorSet for the given height, ErrValidatorSetNotFound - // will be returned. + // error is returned. ValidatorSet(height int64) (*types.ValidatorSet, error) } 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/lite2/store/db/db.go b/lite2/store/db/db.go index ee0d26141..89897ed7f 100644 --- a/lite2/store/db/db.go +++ b/lite2/store/db/db.go @@ -5,6 +5,7 @@ import ( "regexp" "strconv" + "github.com/pkg/errors" "github.com/tendermint/go-amino" dbm "github.com/tendermint/tm-db" @@ -37,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 @@ -60,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. @@ -78,7 +81,7 @@ func (s *dbs) SignedHeader(height int64) (*types.SignedHeader, error) { panic(err) } if len(bz) == 0 { - return nil, nil + return nil, store.ErrSignedHeaderNotFound } var signedHeader *types.SignedHeader @@ -97,7 +100,7 @@ func (s *dbs) ValidatorSet(height int64) (*types.ValidatorSet, error) { panic(err) } if len(bz) == 0 { - return nil, nil + return nil, store.ErrValidatorSetNotFound } var valSet *types.ValidatorSet @@ -151,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 9edc1b2d9..a1dc3000e 100644 --- a/lite2/store/db/db_test.go +++ b/lite2/store/db/db_test.go @@ -42,11 +42,11 @@ func Test_SaveSignedHeaderAndNextValidatorSet(t *testing.T) { // Empty store h, err := dbStore.SignedHeader(1) - require.NoError(t, err) + require.Error(t, err) assert.Nil(t, h) valSet, err := dbStore.ValidatorSet(2) - require.NoError(t, err) + require.Error(t, err) assert.Nil(t, valSet) // 1 key @@ -67,10 +67,29 @@ func Test_SaveSignedHeaderAndNextValidatorSet(t *testing.T) { require.NoError(t, err) h, err = dbStore.SignedHeader(1) - require.NoError(t, err) + require.Error(t, err) assert.Nil(t, h) valSet, err = dbStore.ValidatorSet(2) - require.NoError(t, err) + 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 cdcc25fa5..33b94821d 100644 --- a/lite2/store/store.go +++ b/lite2/store/store.go @@ -21,16 +21,14 @@ type Store interface { // // height must be > 0. // - // If the store is empty and the latest SignedHeader is requested, 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 the store is empty and the latest ValidatorSet is requested, 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. @@ -42,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), + } +} 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). 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 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/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/client/httpclient.go b/rpc/client/httpclient.go index 29175fe19..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() @@ -348,13 +354,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/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 ed3c4257b..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) @@ -76,24 +75,29 @@ 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 } // 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 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) @@ -101,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 @@ -121,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..a2a619ea5 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() @@ -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() @@ -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/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/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..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" @@ -15,9 +17,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,11 +54,12 @@ 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 -func TxSearch(ctx *rpctypes.Context, query string, prove bool, page, perPage int) (*ctypes.ResultTxSearch, error) { +// More: https://docs.tendermint.com/master/rpc/#/Info/tx_search +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) @@ -101,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/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..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;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; -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/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/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/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 { 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/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 { 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) 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" diff --git a/types/block.go b/types/block.go index 206ea4414..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 -// - /docs/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"` 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; } diff --git a/version/version.go b/version/version.go index 989e8ddb1..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.33.0" + TMCoreSemVer = "0.33.1" // ABCISemVer is the semantic version of the ABCI library ABCISemVer = "0.16.1"