aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/CONTRIBUTING.md2
-rw-r--r--.gitignore2
-rw-r--r--.mailmap14
-rw-r--r--.travis.yml11
-rw-r--r--AUTHORS92
-rw-r--r--Makefile6
-rw-r--r--README.md30
-rw-r--r--VERSION2
-rw-r--r--accounts/abi/abi.go7
-rw-r--r--accounts/abi/abi_test.go6
-rw-r--r--accounts/abi/argument.go140
-rw-r--r--accounts/abi/bind/backend.go29
-rw-r--r--accounts/abi/bind/backends/simulated.go163
-rw-r--r--accounts/abi/bind/base.go125
-rw-r--r--accounts/abi/bind/bind.go96
-rw-r--r--accounts/abi/bind/bind_test.go294
-rw-r--r--accounts/abi/bind/template.go169
-rw-r--r--accounts/abi/bind/topics.go189
-rw-r--r--accounts/abi/bind/util_test.go6
-rw-r--r--accounts/abi/event.go11
-rw-r--r--accounts/abi/pack_test.go2
-rw-r--r--accounts/abi/unpack.go37
-rw-r--r--accounts/abi/unpack_test.go119
-rw-r--r--accounts/errors.go2
-rw-r--r--accounts/usbwallet/internal/trezor/messages.proto2
-rw-r--r--accounts/usbwallet/internal/trezor/trezor.go2
-rw-r--r--accounts/usbwallet/internal/trezor/types.proto2
-rw-r--r--accounts/usbwallet/trezor.go2
-rw-r--r--build/ci.go38
-rw-r--r--build/update-license.go5
-rw-r--r--cmd/bootnode/main.go30
-rw-r--r--cmd/ethkey/generate.go63
-rw-r--r--cmd/ethkey/inspect.go17
-rw-r--r--cmd/ethkey/main.go33
-rw-r--r--cmd/ethkey/message.go97
-rw-r--r--cmd/ethkey/message_test.go70
-rw-r--r--cmd/ethkey/run_test.go54
-rw-r--r--cmd/evm/json_logger.go14
-rw-r--r--cmd/evm/runner.go4
-rw-r--r--cmd/faucet/faucet.go4
-rw-r--r--cmd/faucet/website.go25
-rw-r--r--cmd/geth/chaincmd.go7
-rw-r--r--cmd/geth/config.go19
-rw-r--r--cmd/geth/consolecmd.go3
-rw-r--r--cmd/geth/main.go9
-rw-r--r--cmd/geth/misccmd.go3
-rw-r--r--cmd/geth/usage.go7
-rw-r--r--cmd/p2psim/main.go16
-rw-r--r--cmd/puppeth/genesis.go38
-rw-r--r--cmd/puppeth/module_dashboard.go78
-rw-r--r--cmd/puppeth/module_faucet.go8
-rw-r--r--cmd/puppeth/module_node.go54
-rw-r--r--cmd/puppeth/wizard.go3
-rw-r--r--cmd/puppeth/wizard_explorer.go2
-rw-r--r--cmd/puppeth/wizard_faucet.go8
-rw-r--r--cmd/puppeth/wizard_netstats.go14
-rw-r--r--cmd/puppeth/wizard_node.go10
-rw-r--r--cmd/puppeth/wizard_wallet.go2
-rw-r--r--cmd/swarm/config.go2
-rw-r--r--cmd/swarm/run_test.go2
-rw-r--r--cmd/swarm/upload_test.go2
-rw-r--r--cmd/utils/cmd.go31
-rw-r--r--cmd/utils/fdlimit_windows.go47
-rw-r--r--cmd/utils/flags.go113
-rw-r--r--cmd/wnode/main.go65
-rw-r--r--common/bitutil/bitutil.go8
-rw-r--r--common/fdlimit/fdlimit_freebsd.go (renamed from cmd/utils/fdlimit_freebsd.go)28
-rw-r--r--common/fdlimit/fdlimit_test.go (renamed from cmd/utils/fdlimit_test.go)24
-rw-r--r--common/fdlimit/fdlimit_unix.go (renamed from cmd/utils/fdlimit_unix.go)28
-rw-r--r--common/fdlimit/fdlimit_windows.go47
-rw-r--r--common/size.go27
-rw-r--r--consensus/errors.go4
-rw-r--r--consensus/ethash/algorithm.go6
-rw-r--r--consensus/ethash/algorithm_go1.7.go4
-rw-r--r--consensus/ethash/algorithm_go1.8.go34
-rw-r--r--consensus/ethash/algorithm_go1.8_test.go23
-rw-r--r--consensus/ethash/algorithm_test.go4
-rw-r--r--consensus/ethash/consensus.go38
-rw-r--r--consensus/ethash/ethash.go288
-rw-r--r--consensus/ethash/ethash_test.go39
-rw-r--r--consensus/ethash/sealer.go17
-rw-r--r--console/console.go3
-rw-r--r--console/prompter.go3
-rw-r--r--containers/docker/develop-alpine/Dockerfile2
-rw-r--r--containers/docker/develop-ubuntu/Dockerfile6
-rw-r--r--containers/docker/master-alpine/Dockerfile4
-rw-r--r--containers/docker/master-ubuntu/Dockerfile8
-rw-r--r--contracts/chequebook/cheque.go6
-rw-r--r--contracts/chequebook/contract/chequebook.go418
-rw-r--r--contracts/chequebook/contract/chequebook.sol10
-rw-r--r--contracts/chequebook/contract/code.go2
-rw-r--r--contracts/chequebook/contract/mortal.sol10
-rw-r--r--contracts/chequebook/contract/owned.sol15
-rw-r--r--contracts/chequebook/gencode.go9
-rw-r--r--contracts/ens/contract/AbstractENS.sol23
-rw-r--r--contracts/ens/contract/ENS.sol94
-rw-r--r--contracts/ens/contract/FIFSRegistrar.sol39
-rw-r--r--contracts/ens/contract/PublicResolver.sol212
-rw-r--r--contracts/ens/contract/ens.go1086
-rw-r--r--contracts/ens/contract/ens.sol226
-rw-r--r--contracts/ens/contract/fifsregistrar.go195
-rw-r--r--contracts/ens/contract/publicresolver.go1321
-rw-r--r--contracts/ens/ens.go37
-rw-r--r--contracts/ens/ens_test.go28
-rw-r--r--contracts/release/contract.go432
-rw-r--r--contracts/release/contract.sol249
-rw-r--r--contracts/release/contract_test.go374
-rw-r--r--contracts/release/release.go164
-rw-r--r--core/bench_test.go13
-rw-r--r--core/block_validator.go45
-rw-r--r--core/block_validator_test.go8
-rw-r--r--core/blockchain.go375
-rw-r--r--core/blockchain_test.go231
-rw-r--r--core/chain_indexer.go3
-rw-r--r--core/chain_makers.go12
-rw-r--r--core/chain_makers_test.go8
-rw-r--r--core/dao_test.go24
-rw-r--r--core/database_util_test.go14
-rw-r--r--core/evm.go2
-rw-r--r--core/gaspool.go34
-rw-r--r--core/gen_genesis.go6
-rw-r--r--core/gen_genesis_account.go8
-rw-r--r--core/genesis.go28
-rw-r--r--core/genesis_test.go6
-rw-r--r--core/state/database.go51
-rw-r--r--core/state/iterator_test.go17
-rw-r--r--core/state/journal.go2
-rw-r--r--core/state/state_object.go5
-rw-r--r--core/state/state_test.go6
-rw-r--r--core/state/statedb.go55
-rw-r--r--core/state/statedb_test.go18
-rw-r--r--core/state/sync_test.go44
-rw-r--r--core/state_processor.go34
-rw-r--r--core/state_transition.go132
-rw-r--r--core/tx_list.go13
-rw-r--r--core/tx_list_test.go3
-rw-r--r--core/tx_pool.go11
-rw-r--r--core/tx_pool_test.go238
-rw-r--r--core/types.go6
-rw-r--r--core/types/block.go27
-rw-r--r--core/types/block_test.go6
-rw-r--r--core/types/gen_header_json.go22
-rw-r--r--core/types/gen_log_json.go6
-rw-r--r--core/types/gen_receipt_json.go23
-rw-r--r--core/types/gen_tx_json.go14
-rw-r--r--core/types/receipt.go40
-rw-r--r--core/types/transaction.go47
-rw-r--r--core/types/transaction_signing_test.go8
-rw-r--r--core/types/transaction_test.go10
-rw-r--r--core/vm/contracts_test.go16
-rw-r--r--core/vm/evm.go4
-rw-r--r--core/vm/gas_table.go6
-rw-r--r--core/vm/gen_structlog.go34
-rw-r--r--core/vm/instructions.go2
-rw-r--r--core/vm/instructions_test.go16
-rw-r--r--core/vm/interface.go4
-rw-r--r--core/vm/interpreter.go7
-rw-r--r--core/vm/logger.go40
-rw-r--r--core/vm/noop.go4
-rw-r--r--core/vm/runtime/env.go4
-rw-r--r--crypto/crypto.go10
-rw-r--r--crypto/ecies/ecies.go2
-rw-r--r--dashboard/README.md2
-rw-r--r--dashboard/assets.go9904
-rw-r--r--dashboard/assets/.eslintrc5
-rw-r--r--dashboard/assets/common.jsx (renamed from dashboard/assets/components/Common.jsx)32
-rw-r--r--dashboard/assets/components/Body.jsx19
-rw-r--r--dashboard/assets/components/ChartRow.jsx (renamed from dashboard/assets/components/ChartGrid.jsx)46
-rw-r--r--dashboard/assets/components/CustomTooltip.jsx95
-rw-r--r--dashboard/assets/components/Dashboard.jsx244
-rw-r--r--dashboard/assets/components/Footer.jsx173
-rw-r--r--dashboard/assets/components/Header.jsx62
-rw-r--r--dashboard/assets/components/Home.jsx72
-rw-r--r--dashboard/assets/components/Main.jsx39
-rw-r--r--dashboard/assets/components/SideBar.jsx84
-rw-r--r--dashboard/assets/dashboard.html (renamed from dashboard/assets/public/dashboard.html)0
-rw-r--r--dashboard/assets/index.jsx22
-rw-r--r--dashboard/assets/package-lock.json1366
-rw-r--r--dashboard/assets/package.json15
-rw-r--r--dashboard/assets/types/content.jsx47
-rw-r--r--dashboard/assets/webpack.config.js2
-rw-r--r--dashboard/config.go2
-rw-r--r--dashboard/cpu.go (renamed from dashboard/assets/types/message.jsx)58
-rw-r--r--dashboard/cpu_windows.go23
-rw-r--r--dashboard/dashboard.go182
-rw-r--r--dashboard/message.go23
-rw-r--r--eth/api.go4
-rw-r--r--eth/api_test.go2
-rw-r--r--eth/api_tracer.go141
-rw-r--r--eth/backend.go14
-rw-r--r--eth/bind.go138
-rw-r--r--eth/config.go14
-rw-r--r--eth/downloader/downloader.go356
-rw-r--r--eth/downloader/downloader_test.go207
-rw-r--r--eth/downloader/queue.go169
-rw-r--r--eth/downloader/statesync.go36
-rw-r--r--eth/fetcher/fetcher_test.go2
-rw-r--r--eth/filters/api.go7
-rw-r--r--eth/filters/filter_system.go11
-rw-r--r--eth/filters/filter_system_test.go29
-rw-r--r--eth/filters/filter_test.go10
-rw-r--r--eth/gasprice/gasprice.go49
-rw-r--r--eth/gen_config.go58
-rw-r--r--eth/handler.go20
-rw-r--r--eth/handler_test.go30
-rw-r--r--eth/helper_test.go24
-rw-r--r--eth/protocol_test.go20
-rw-r--r--eth/sync.go15
-rw-r--r--eth/sync_test.go4
-rw-r--r--eth/tracers/internal/tracers/assets.go40
-rw-r--r--eth/tracers/tracer.go2
-rw-r--r--eth/tracers/tracer_test.go2
-rw-r--r--eth/tracers/tracers_test.go4
-rw-r--r--ethclient/ethclient.go12
-rw-r--r--ethdb/database.go9
-rw-r--r--ethdb/interface.go2
-rw-r--r--ethdb/memory_database.go5
-rw-r--r--ethstats/ethstats.go9
-rw-r--r--interfaces.go4
-rw-r--r--internal/build/env.go2
-rw-r--r--internal/cmdtest/test_cmd.go24
-rw-r--r--internal/ethapi/addrlock.go2
-rw-r--r--internal/ethapi/api.go151
-rw-r--r--internal/ethapi/backend.go3
-rw-r--r--internal/jsre/deps/bindata.go28
-rw-r--r--internal/web3ext/web3ext.go6
-rw-r--r--les/backend.go10
-rw-r--r--les/fetcher.go33
-rw-r--r--les/handler.go246
-rw-r--r--les/handler_test.go170
-rw-r--r--les/helper_test.go49
-rw-r--r--les/odr_requests.go26
-rw-r--r--les/odr_test.go9
-rw-r--r--les/peer.go5
-rw-r--r--les/protocol.go9
-rw-r--r--les/retrieve.go2
-rw-r--r--les/server.go38
-rw-r--r--les/serverpool.go2
-rw-r--r--light/lightchain.go39
-rw-r--r--light/nodeset.go37
-rw-r--r--light/odr_test.go22
-rw-r--r--light/odr_util.go9
-rw-r--r--light/postprocess.go103
-rw-r--r--light/trie.go18
-rw-r--r--light/trie_test.go2
-rw-r--r--light/txpool.go9
-rw-r--r--light/txpool_test.go4
-rw-r--r--miner/worker.go10
-rw-r--r--mobile/android_test.go15
-rw-r--r--mobile/bind.go6
-rw-r--r--mobile/ethclient.go4
-rw-r--r--mobile/ethereum.go5
-rw-r--r--mobile/geth.go1
-rw-r--r--mobile/types.go28
-rw-r--r--node/api.go12
-rw-r--r--node/config.go11
-rw-r--r--node/defaults.go7
-rw-r--r--node/node.go29
-rw-r--r--p2p/dial.go13
-rw-r--r--p2p/dial_test.go44
-rw-r--r--p2p/discover/database.go17
-rw-r--r--p2p/discover/database_test.go18
-rw-r--r--p2p/discover/node.go6
-rw-r--r--p2p/discover/table.go486
-rw-r--r--p2p/discover/table_test.go171
-rw-r--r--p2p/discover/udp.go118
-rw-r--r--p2p/discover/udp_test.go28
-rw-r--r--p2p/discv5/database.go6
-rw-r--r--p2p/discv5/net.go43
-rw-r--r--p2p/discv5/net_test.go2
-rw-r--r--p2p/discv5/nodeevent_string.go6
-rw-r--r--p2p/discv5/sim_test.go2
-rw-r--r--p2p/discv5/ticket.go16
-rw-r--r--p2p/discv5/udp.go67
-rw-r--r--p2p/enr/enr.go290
-rw-r--r--p2p/enr/enr_test.go318
-rw-r--r--p2p/enr/entries.go160
-rw-r--r--p2p/netutil/net.go131
-rw-r--r--p2p/netutil/net_test.go89
-rw-r--r--p2p/peer.go6
-rw-r--r--p2p/server.go150
-rw-r--r--p2p/simulations/adapters/state.go1
-rw-r--r--params/bootnodes.go21
-rw-r--r--params/protocol_params.go20
-rw-r--r--params/version.go2
-rw-r--r--rpc/http.go68
-rw-r--r--rpc/types_test.go2
-rw-r--r--swarm/api/http/error_templates.go20
-rw-r--r--swarm/api/http/error_test.go2
-rw-r--r--swarm/api/http/server_test.go6
-rw-r--r--swarm/api/http/templates.go3
-rw-r--r--swarm/storage/chunker_test.go8
-rw-r--r--swarm/storage/pyramid.go2
-rw-r--r--tests/block_test_util.go24
-rw-r--r--tests/difficulty_test.go1
-rw-r--r--tests/difficulty_test_util.go1
-rw-r--r--tests/gen_btheader.go20
-rw-r--r--tests/gen_stenv.go8
-rw-r--r--tests/gen_sttransaction.go4
-rw-r--r--tests/gen_tttransaction.go12
-rw-r--r--tests/gen_vmexec.go8
-rw-r--r--tests/init.go2
-rw-r--r--tests/init_test.go2
-rw-r--r--tests/state_test.go15
-rw-r--r--tests/state_test_util.go16
m---------tests/testdata0
-rw-r--r--tests/transaction_test_util.go8
-rw-r--r--trie/database.go355
-rw-r--r--trie/hasher.go156
-rw-r--r--trie/iterator_test.go125
-rw-r--r--trie/proof.go47
-rw-r--r--trie/secure_trie.go70
-rw-r--r--trie/secure_trie_test.go20
-rw-r--r--trie/sync.go14
-rw-r--r--trie/sync_test.go103
-rw-r--r--trie/trie.go93
-rw-r--r--trie/trie_test.go104
-rw-r--r--vendor/github.com/StackExchange/wmi/LICENSE20
-rw-r--r--vendor/github.com/StackExchange/wmi/README.md6
-rw-r--r--vendor/github.com/StackExchange/wmi/swbemservices.go260
-rw-r--r--vendor/github.com/StackExchange/wmi/wmi.go486
-rw-r--r--vendor/github.com/elastic/gosigar/CHANGELOG.md102
-rw-r--r--vendor/github.com/elastic/gosigar/LICENSE201
-rw-r--r--vendor/github.com/elastic/gosigar/NOTICE9
-rw-r--r--vendor/github.com/elastic/gosigar/README.md57
-rw-r--r--vendor/github.com/elastic/gosigar/Vagrantfile25
-rw-r--r--vendor/github.com/elastic/gosigar/codecov.yml21
-rw-r--r--vendor/github.com/elastic/gosigar/concrete_sigar.go83
-rw-r--r--vendor/github.com/elastic/gosigar/sigar_darwin.go494
-rw-r--r--vendor/github.com/elastic/gosigar/sigar_format.go126
-rw-r--r--vendor/github.com/elastic/gosigar/sigar_freebsd.go108
-rw-r--r--vendor/github.com/elastic/gosigar/sigar_interface.go197
-rw-r--r--vendor/github.com/elastic/gosigar/sigar_linux.go84
-rw-r--r--vendor/github.com/elastic/gosigar/sigar_linux_common.go468
-rw-r--r--vendor/github.com/elastic/gosigar/sigar_openbsd.go418
-rw-r--r--vendor/github.com/elastic/gosigar/sigar_stub.go71
-rw-r--r--vendor/github.com/elastic/gosigar/sigar_unix.go69
-rw-r--r--vendor/github.com/elastic/gosigar/sigar_util.go22
-rw-r--r--vendor/github.com/elastic/gosigar/sigar_windows.go437
-rw-r--r--vendor/github.com/elastic/gosigar/sys/windows/doc.go2
-rw-r--r--vendor/github.com/elastic/gosigar/sys/windows/ntquery.go132
-rw-r--r--vendor/github.com/elastic/gosigar/sys/windows/privileges.go272
-rw-r--r--vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go385
-rw-r--r--vendor/github.com/elastic/gosigar/sys/windows/version.go43
-rw-r--r--vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go260
-rw-r--r--vendor/github.com/go-ole/go-ole/ChangeLog.md49
-rw-r--r--vendor/github.com/go-ole/go-ole/LICENSE21
-rw-r--r--vendor/github.com/go-ole/go-ole/README.md46
-rw-r--r--vendor/github.com/go-ole/go-ole/appveyor.yml54
-rw-r--r--vendor/github.com/go-ole/go-ole/com.go329
-rw-r--r--vendor/github.com/go-ole/go-ole/com_func.go174
-rw-r--r--vendor/github.com/go-ole/go-ole/connect.go192
-rw-r--r--vendor/github.com/go-ole/go-ole/constants.go153
-rw-r--r--vendor/github.com/go-ole/go-ole/error.go51
-rw-r--r--vendor/github.com/go-ole/go-ole/error_func.go8
-rw-r--r--vendor/github.com/go-ole/go-ole/error_windows.go24
-rw-r--r--vendor/github.com/go-ole/go-ole/guid.go284
-rw-r--r--vendor/github.com/go-ole/go-ole/iconnectionpoint.go20
-rw-r--r--vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go21
-rw-r--r--vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go43
-rw-r--r--vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go17
-rw-r--r--vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go11
-rw-r--r--vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go25
-rw-r--r--vendor/github.com/go-ole/go-ole/idispatch.go94
-rw-r--r--vendor/github.com/go-ole/go-ole/idispatch_func.go19
-rw-r--r--vendor/github.com/go-ole/go-ole/idispatch_windows.go197
-rw-r--r--vendor/github.com/go-ole/go-ole/ienumvariant.go19
-rw-r--r--vendor/github.com/go-ole/go-ole/ienumvariant_func.go19
-rw-r--r--vendor/github.com/go-ole/go-ole/ienumvariant_windows.go63
-rw-r--r--vendor/github.com/go-ole/go-ole/iinspectable.go18
-rw-r--r--vendor/github.com/go-ole/go-ole/iinspectable_func.go15
-rw-r--r--vendor/github.com/go-ole/go-ole/iinspectable_windows.go72
-rw-r--r--vendor/github.com/go-ole/go-ole/iprovideclassinfo.go21
-rw-r--r--vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go7
-rw-r--r--vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go21
-rw-r--r--vendor/github.com/go-ole/go-ole/itypeinfo.go34
-rw-r--r--vendor/github.com/go-ole/go-ole/itypeinfo_func.go7
-rw-r--r--vendor/github.com/go-ole/go-ole/itypeinfo_windows.go21
-rw-r--r--vendor/github.com/go-ole/go-ole/iunknown.go57
-rw-r--r--vendor/github.com/go-ole/go-ole/iunknown_func.go19
-rw-r--r--vendor/github.com/go-ole/go-ole/iunknown_windows.go58
-rw-r--r--vendor/github.com/go-ole/go-ole/ole.go157
-rw-r--r--vendor/github.com/go-ole/go-ole/oleutil/connection.go100
-rw-r--r--vendor/github.com/go-ole/go-ole/oleutil/connection_func.go10
-rw-r--r--vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go58
-rw-r--r--vendor/github.com/go-ole/go-ole/oleutil/go-get.go6
-rw-r--r--vendor/github.com/go-ole/go-ole/oleutil/oleutil.go127
-rw-r--r--vendor/github.com/go-ole/go-ole/safearray.go27
-rw-r--r--vendor/github.com/go-ole/go-ole/safearray_func.go211
-rw-r--r--vendor/github.com/go-ole/go-ole/safearray_windows.go337
-rw-r--r--vendor/github.com/go-ole/go-ole/safearrayconversion.go140
-rw-r--r--vendor/github.com/go-ole/go-ole/safearrayslices.go33
-rw-r--r--vendor/github.com/go-ole/go-ole/utility.go101
-rw-r--r--vendor/github.com/go-ole/go-ole/variables.go16
-rw-r--r--vendor/github.com/go-ole/go-ole/variant.go105
-rw-r--r--vendor/github.com/go-ole/go-ole/variant_386.go11
-rw-r--r--vendor/github.com/go-ole/go-ole/variant_amd64.go12
-rw-r--r--vendor/github.com/go-ole/go-ole/variant_s390x.go12
-rw-r--r--vendor/github.com/go-ole/go-ole/vt_string.go58
-rw-r--r--vendor/github.com/go-ole/go-ole/winrt.go99
-rw-r--r--vendor/github.com/go-ole/go-ole/winrt_doc.go36
-rw-r--r--vendor/github.com/pkg/errors/LICENSE23
-rw-r--r--vendor/github.com/pkg/errors/README.md52
-rw-r--r--vendor/github.com/pkg/errors/appveyor.yml32
-rw-r--r--vendor/github.com/pkg/errors/errors.go269
-rw-r--r--vendor/github.com/pkg/errors/stack.go187
-rw-r--r--vendor/github.com/rjeczalik/notify/README.md2
-rw-r--r--vendor/github.com/rjeczalik/notify/appveyor.yml2
-rw-r--r--vendor/github.com/rjeczalik/notify/debug.go50
-rw-r--r--vendor/github.com/rjeczalik/notify/debug_debug.go36
-rw-r--r--vendor/github.com/rjeczalik/notify/debug_nodebug.go9
-rw-r--r--vendor/github.com/rjeczalik/notify/doc.go7
-rw-r--r--vendor/github.com/rjeczalik/notify/event.go2
-rw-r--r--vendor/github.com/rjeczalik/notify/event_inotify.go40
-rw-r--r--vendor/github.com/rjeczalik/notify/event_readdcw.go14
-rw-r--r--vendor/github.com/rjeczalik/notify/node.go7
-rw-r--r--vendor/github.com/rjeczalik/notify/watcher_fen.go11
-rw-r--r--vendor/github.com/rjeczalik/notify/watcher_fsevents.go8
-rw-r--r--vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go7
-rw-r--r--vendor/github.com/rjeczalik/notify/watcher_inotify.go79
-rw-r--r--vendor/github.com/rjeczalik/notify/watcher_kqueue.go14
-rw-r--r--vendor/github.com/rjeczalik/notify/watcher_readdcw.go50
-rw-r--r--vendor/github.com/rjeczalik/notify/watcher_trigger.go21
-rw-r--r--vendor/github.com/syndtr/goleveldb/.travis.yml12
-rw-r--r--vendor/github.com/syndtr/goleveldb/README.md4
-rw-r--r--vendor/github.com/syndtr/goleveldb/leveldb/db.go17
-rw-r--r--vendor/github.com/syndtr/goleveldb/leveldb/db_write.go10
-rw-r--r--vendor/vendor.json48
-rw-r--r--whisper/mailserver/mailserver.go2
-rw-r--r--whisper/mailserver/server_test.go2
-rw-r--r--whisper/whisperv2/whisper.go4
-rw-r--r--whisper/whisperv5/api.go2
-rw-r--r--whisper/whisperv5/filter.go8
-rw-r--r--whisper/whisperv5/filter_test.go48
-rw-r--r--whisper/whisperv5/gen_criteria_json.go14
-rw-r--r--whisper/whisperv5/gen_message_json.go28
-rw-r--r--whisper/whisperv5/gen_newmessage_json.go26
-rw-r--r--whisper/whisperv6/api.go20
-rw-r--r--whisper/whisperv6/config.go2
-rw-r--r--whisper/whisperv6/doc.go35
-rw-r--r--whisper/whisperv6/envelope.go62
-rw-r--r--whisper/whisperv6/filter.go29
-rw-r--r--whisper/whisperv6/filter_test.go50
-rw-r--r--whisper/whisperv6/gen_criteria_json.go16
-rw-r--r--whisper/whisperv6/gen_message_json.go30
-rw-r--r--whisper/whisperv6/gen_newmessage_json.go28
-rw-r--r--whisper/whisperv6/message.go214
-rw-r--r--whisper/whisperv6/message_test.go57
-rw-r--r--whisper/whisperv6/peer.go115
-rw-r--r--whisper/whisperv6/peer_test.go251
-rw-r--r--whisper/whisperv6/topic.go4
-rw-r--r--whisper/whisperv6/whisper.go633
-rw-r--r--whisper/whisperv6/whisper_test.go79
453 files changed, 25896 insertions, 14333 deletions
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index a332b815d..9f2dbfcb8 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -2,7 +2,7 @@
Before you do a feature request please check and make sure that it isn't possible
through some other means. The JavaScript enabled console is a powerful feature
-in the right hands. Please check our [Bitchin' tricks](https://github.com/ethereum/go-ethereum/wiki/bitchin-tricks) wiki page for more info
+in the right hands. Please check our [Wiki page](https://github.com/ethereum/go-ethereum/wiki) for more info
and help.
## Contributing
diff --git a/.gitignore b/.gitignore
index 9e054bad1..0763d8492 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,4 +38,4 @@ profile.cov
/dashboard/assets/flow-typed
/dashboard/assets/node_modules
/dashboard/assets/stats.json
-/dashboard/assets/public/bundle.js
+/dashboard/assets/bundle.js
diff --git a/.mailmap b/.mailmap
index d51c7b609..cc4b871a3 100644
--- a/.mailmap
+++ b/.mailmap
@@ -65,7 +65,8 @@ Enrique Fynn <enriquefynn@gmail.com>
Vincent G <caktux@gmail.com>
-RJ Catalano <rj@erisindustries.com>
+RJ Catalano <catalanor0220@gmail.com>
+RJ Catalano <catalanor0220@gmail.com> <rj@erisindustries.com>
Nchinda Nchinda <nchinda2@gmail.com>
@@ -109,3 +110,14 @@ Frank Wang <eternnoir@gmail.com>
Gary Rong <garyrong0905@gmail.com>
Guillaume Nicolas <guin56@gmail.com>
+
+Sorin Neacsu <sorin.neacsu@gmail.com>
+Sorin Neacsu <sorin.neacsu@gmail.com> <sorin@users.noreply.github.com>
+
+Valentin Wüstholz <wuestholz@gmail.com>
+Valentin Wüstholz <wuestholz@gmail.com> <wuestholz@users.noreply.github.com>
+
+Armin Braun <me@obrown.io>
+
+Ernesto del Toro <ernesto.deltoro@gmail.com>
+Ernesto del Toro <ernesto.deltoro@gmail.com> <ernestodeltoro@users.noreply.github.com>
diff --git a/.travis.yml b/.travis.yml
index cc1b185fc..3941fa785 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -40,6 +40,7 @@ matrix:
- os: osx
go: 1.9.x
script:
+ - unset -f cd # workaround for https://github.com/travis-ci/travis-ci/issues/8703
- brew update
- brew install caskroom/cask/brew-cask
- brew cask install osxfuse
@@ -87,13 +88,13 @@ matrix:
- sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross
- sudo ln -s /usr/include/asm-generic /usr/include/asm
- - GOARM=5 CC=arm-linux-gnueabi-gcc go run build/ci.go install -arch arm
+ - GOARM=5 go run build/ci.go install -arch arm -cc arm-linux-gnueabi-gcc
- GOARM=5 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
- - GOARM=6 CC=arm-linux-gnueabi-gcc go run build/ci.go install -arch arm
+ - GOARM=6 go run build/ci.go install -arch arm -cc arm-linux-gnueabi-gcc
- GOARM=6 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
- - GOARM=7 CC=arm-linux-gnueabihf-gcc go run build/ci.go install -arch arm
+ - GOARM=7 go run build/ci.go install -arch arm -cc arm-linux-gnueabihf-gcc
- GOARM=7 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
- - CC=aarch64-linux-gnu-gcc go run build/ci.go install -arch arm64
+ - go run build/ci.go install -arch arm64 -cc aarch64-linux-gnu-gcc
- go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
# This builder does the Linux Azure MIPS xgo uploads
@@ -184,6 +185,8 @@ matrix:
- xctool -version
- xcrun simctl list
+ # Workaround for https://github.com/golang/go/issues/23749
+ - export CGO_CFLAGS_ALLOW='-fmodules|-fblocks|-fobjc-arc'
- go run build/ci.go xcode -signer IOS_SIGNING_KEY -deploy trunk -upload gethstore/builds
# This builder does the Azure archive purges to avoid accumulating junk
diff --git a/AUTHORS b/AUTHORS
index faa19d281..bd44a3de5 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,85 +1,173 @@
# This is the official list of go-ethereum authors for copyright purposes.
+Afri Schoedon <5chdn@users.noreply.github.com>
+Agustin Armellini Fischer <armellini13@gmail.com>
+Airead <fgh1987168@gmail.com>
+Alan Chen <alanchchen@users.noreply.github.com>
+Alejandro Isaza <alejandro.isaza@gmail.com>
Ales Katona <ales@coinbase.com>
Alex Leverington <alex@ethdev.com>
+Alex Wu <wuyiding@gmail.com>
Alexandre Van de Sande <alex.vandesande@ethdev.com>
+Ali Hajimirza <Ali92hm@users.noreply.github.com>
+Anton Evangelatov <anton.evangelatov@gmail.com>
+Arba Sasmoyo <arba.sasmoyo@gmail.com>
+Armani Ferrante <armaniferrante@berkeley.edu>
+Armin Braun <me@obrown.io>
Aron Fischer <github@aron.guru>
Bas van Kervel <bas@ethdev.com>
Benjamin Brent <benjamin@benjaminbrent.com>
+Benoit Verkindt <benoit.verkindt@gmail.com>
+Bo <bohende@gmail.com>
+Bo Ye <boy.e.computer.1982@outlook.com>
+Bob Glickstein <bobg@users.noreply.github.com>
Brian Schroeder <bts@gmail.com>
Casey Detrio <cdetrio@gmail.com>
+Chase Wright <mysticryuujin@gmail.com>
Christoph Jentzsch <jentzsch.software@gmail.com>
Daniel A. Nagy <nagy.da@gmail.com>
+Daniel Sloof <goapsychadelic@gmail.com>
+Darrel Herbst <dherbst@gmail.com>
+Dave Appleton <calistralabs@gmail.com>
Diego Siqueira <DiSiqueira@users.noreply.github.com>
+Dmitry Shulyak <yashulyak@gmail.com>
+Egon Elbre <egonelbre@gmail.com>
+Elias Naur <elias.naur@gmail.com>
Elliot Shepherd <elliot@identitii.com>
Enrique Fynn <enriquefynn@gmail.com>
+Ernesto del Toro <ernesto.deltoro@gmail.com>
Ethan Buchman <ethan@coinculture.info>
+Eugene Valeyev <evgen.povt@gmail.com>
+Evangelos Pappas <epappas@evalonlabs.com>
+Evgeny Danilenko <6655321@bk.ru>
Fabian Vogelsteller <fabian@frozeman.de>
+Fabio Barone <fabio.barone.co@gmail.com>
Fabio Berger <fabioberger1991@gmail.com>
+FaceHo <facehoshi@gmail.com>
Felix Lange <fjl@twurst.com>
+Fiisio <liangcszzu@163.com>
Frank Wang <eternnoir@gmail.com>
+Furkan KAMACI <furkankamaci@gmail.com>
Gary Rong <garyrong0905@gmail.com>
+George Ornbo <george@shapeshed.com>
Gregg Dourgarian <greggd@tempworks.com>
+Guillaume Ballet <gballet@gmail.com>
Guillaume Nicolas <guin56@gmail.com>
Gustav Simonsson <gustav.simonsson@gmail.com>
Hao Bryan Cheng <haobcheng@gmail.com>
Henning Diedrich <hd@eonblast.com>
Isidoro Ghezzi <isidoro.ghezzi@icloud.com>
+Ivan Daniluk <ivan.daniluk@gmail.com>
Jae Kwon <jkwon.work@gmail.com>
Jamie Pitts <james.pitts@gmail.com>
+Janoš Guljaš <janos@users.noreply.github.com>
Jason Carver <jacarver@linkedin.com>
+Jay Guo <guojiannan1101@gmail.com>
Jeff R. Allen <jra@nella.org>
Jeffrey Wilcke <jeffrey@ethereum.org>
Jens Agerberg <github@agerberg.me>
+Jia Chenhui <jiachenhui1989@gmail.com>
+Jim McDonald <Jim@mcdee.net>
+Joel Burget <joelburget@gmail.com>
Jonathan Brown <jbrown@bluedroplet.com>
Joseph Chow <ethereum@outlook.com>
Justin Clark-Casey <justincc@justincc.org>
Justin Drake <drakefjustin@gmail.com>
Kenji Siu <kenji@isuntv.com>
Kobi Gurkan <kobigurk@gmail.com>
+Konrad Feldmeier <konrad@brainbot.com>
+Kurkó Mihály <kurkomisi@users.noreply.github.com>
+Kyuntae Ethan Kim <ethan.kyuntae.kim@gmail.com>
Lefteris Karapetsas <lefteris@refu.co>
Leif Jurvetson <leijurv@gmail.com>
+Leo Shklovskii <leo@thermopylae.net>
Lewis Marshall <lewis@lmars.net>
+Lio李欧 <lionello@users.noreply.github.com>
Louis Holbrook <dev@holbrook.no>
Luca Zeug <luclu@users.noreply.github.com>
+Magicking <s@6120.eu>
Maran Hidskes <maran.hidskes@gmail.com>
Marek Kotewicz <marek.kotewicz@gmail.com>
+Mark <markya0616@gmail.com>
Martin Holst Swende <martin@swende.se>
Matthew Di Ferrante <mattdf@users.noreply.github.com>
Matthew Wampler-Doty <matthew.wampler.doty@gmail.com>
+Maximilian Meister <mmeister@suse.de>
Micah Zoltu <micah@zoltu.net>
+Michael Ruminer <michael.ruminer+github@gmail.com>
+Miguel Mota <miguelmota2@gmail.com>
+Miya Chen <miyatlchen@gmail.com>
Nchinda Nchinda <nchinda2@gmail.com>
Nick Dodson <silentcicero@outlook.com>
Nick Johnson <arachnid@notdot.net>
+Nicolas Guillaume <gunicolas@sqli.com>
+Noman <noman@noman.land>
+Oli Bye <olibye@users.noreply.github.com>
+Paul Litvak <litvakpol@012.net.il>
Paulo L F Casaretto <pcasaretto@gmail.com>
+Paweł Bylica <chfast@gmail.com>
Peter Pratscher <pratscher@gmail.com>
+Petr Mikusek <petr@mikusek.info>
Péter Szilágyi <peterke@gmail.com>
-RJ Catalano <rj@erisindustries.com>
+RJ Catalano <catalanor0220@gmail.com>
Ramesh Nair <ram@hiddentao.com>
Ricardo Catalinas Jiménez <r@untroubled.be>
+Ricardo Domingos <ricardohsd@gmail.com>
+Richard Hart <richardhart92@gmail.com>
+Rob <robert@rojotek.com>
+Robert Zaremba <robert.zaremba@scale-it.pl>
+Russ Cox <rsc@golang.org>
Rémy Roy <remyroy@remyroy.com>
+S. Matthew English <s-matthew-english@users.noreply.github.com>
Shintaro Kaneko <kaneshin0120@gmail.com>
+Sorin Neacsu <sorin.neacsu@gmail.com>
Stein Dekker <dekker.stein@gmail.com>
+Steve Waldman <swaldman@mchange.com>
Steven Roose <stevenroose@gmail.com>
Taylor Gerring <taylor.gerring@gmail.com>
Thomas Bocek <tom@tomp2p.net>
+Ti Zhou <tizhou1986@gmail.com>
Tosh Camille <tochecamille@gmail.com>
-Valentin Wüstholz <wuestholz@users.noreply.github.com>
+Valentin Wüstholz <wuestholz@gmail.com>
Victor Farazdagi <simple.square@gmail.com>
Victor Tran <vu.tran54@gmail.com>
Viktor Trón <viktor.tron@gmail.com>
Ville Sundell <github@solarius.fi>
Vincent G <caktux@gmail.com>
Vitalik Buterin <v@buterin.com>
+Vitaly V <vvelikodny@gmail.com>
Vivek Anand <vivekanand1101@users.noreply.github.com>
Vlad Gluhovsky <gluk256@users.noreply.github.com>
Yohann Léon <sybiload@gmail.com>
Yoichi Hirai <i@yoichihirai.com>
+Yondon Fu <yondon.fu@gmail.com>
+Zach <zach.ramsay@gmail.com>
Zahoor Mohamed <zahoor@zahoor.in>
+Zoe Nolan <github@zoenolan.org>
Zsolt Felföldi <zsfelfoldi@gmail.com>
+am2rican5 <am2rican5@gmail.com>
+ayeowch <ayeowch@gmail.com>
+b00ris <b00ris@mail.ru>
+bailantaotao <Edwin@maicoin.com>
+baizhenxuan <nkbai@163.com>
+bloonfield <bloonfield@163.com>
+changhong <changhong.yu@shanbay.com>
+evgk <evgeniy.kamyshev@gmail.com>
+ferhat elmas <elmas.ferhat@gmail.com>
holisticode <holistic.computing@gmail.com>
+jtakalai <juuso.takalainen@streamr.com>
ken10100147 <sunhongping@kanjian.com>
ligi <ligi@ligi.de>
+mark.lin <mark@maicoin.com>
+necaremus <necaremus@gmail.com>
+njupt-moon <1015041018@njupt.edu.cn>
+nkbai <nkbai@163.com>
+rhaps107 <dod-source@yandex.ru>
+slumber1122 <slumber1122@gmail.com>
+sunxiaojun2014 <sunxiaojun-xy@360.cn>
+terasum <terasum@163.com>
+tsarpaul <Litvakpol@012.net.il>
xiekeyang <xiekeyang@users.noreply.github.com>
+yoza <yoza.is12s@gmail.com>
ΞTHΞЯSPHΞЯΞ <{viktor.tron,nagydani,zsfelfoldi}@gmail.com>
Максим Чусовлянов <mchusovlianov@gmail.com>
diff --git a/Makefile b/Makefile
index 2cfd1110e..3922d6015 100644
--- a/Makefile
+++ b/Makefile
@@ -45,9 +45,13 @@ clean:
devtools:
env GOBIN= go get -u golang.org/x/tools/cmd/stringer
- env GOBIN= go get -u github.com/jteeuwen/go-bindata/go-bindata
+ env GOBIN= go get -u github.com/kevinburke/go-bindata/go-bindata
env GOBIN= go get -u github.com/fjl/gencodec
+ env GOBIN= go get -u github.com/golang/protobuf/protoc-gen-go
env GOBIN= go install ./cmd/abigen
+ @type "npm" 2> /dev/null || echo 'Please install node.js and npm'
+ @type "solc" 2> /dev/null || echo 'Please install solc'
+ @type "protoc" 2> /dev/null || echo 'Please install protoc'
# Cross Compilation Targets (xgo)
diff --git a/README.md b/README.md
index 61e36afec..aad14ed7d 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,7 @@ Official golang implementation of the Ethereum protocol.
[![API Reference](
https://camo.githubusercontent.com/915b7be44ada53c290eb157634330494ebe3e30a/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f676f6c616e672f6764646f3f7374617475732e737667
)](https://godoc.org/github.com/ethereum/go-ethereum)
+[![Go Report Card](https://goreportcard.com/badge/github.com/ethereum/go-ethereum)](https://goreportcard.com/report/github.com/ethereum/go-ethereum)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ethereum/go-ethereum?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
Automated builds are available for stable releases and the unstable master branch.
@@ -56,16 +57,14 @@ the user doesn't care about years-old historical data, so we can fast-sync quick
state of the network. To do so:
```
-$ geth --fast --cache=512 console
+$ geth console
```
This command will:
- * Start geth in fast sync mode (`--fast`), causing it to download more data in exchange for avoiding
- processing the entire history of the Ethereum network, which is very CPU intensive.
- * Bump the memory allowance of the database to 512MB (`--cache=512`), which can help significantly in
- sync times especially for HDD users. This flag is optional and you can set it as high or as low as
- you'd like, though we'd recommend the 512MB - 2GB range.
+ * Start geth in fast sync mode (default, can be changed with the `--syncmode` flag), causing it to
+ download more data in exchange for avoiding processing the entire history of the Ethereum network,
+ which is very CPU intensive.
* Start up Geth's built-in interactive [JavaScript console](https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console),
(via the trailing `console` subcommand) through which you can invoke all official [`web3` methods](https://github.com/ethereum/wiki/wiki/JavaScript-API)
as well as Geth's own [management APIs](https://github.com/ethereum/go-ethereum/wiki/Management-APIs).
@@ -80,12 +79,11 @@ entire system. In other words, instead of attaching to the main network, you wan
network with your node, which is fully equivalent to the main network, but with play-Ether only.
```
-$ geth --testnet --fast --cache=512 console
+$ geth --testnet console
```
-The `--fast`, `--cache` flags and `console` subcommand have the exact same meaning as above and they
-are equally useful on the testnet too. Please see above for their explanations if you've skipped to
-here.
+The `console` subcommand have the exact same meaning as above and they are equally useful on the
+testnet too. Please see above for their explanations if you've skipped to here.
Specifying the `--testnet` flag however will reconfigure your Geth instance a bit:
@@ -102,6 +100,14 @@ over between the main network and test network, you should make sure to always u
for play-money and real-money. Unless you manually move accounts, Geth will by default correctly
separate the two networks and will not make any accounts available between them.*
+### Full node on the Rinkeby test network
+
+The above test network is a cross client one based on the ethash proof-of-work consensus algorithm. As such, it has certain extra overhead and is more susceptible to reorganization attacks due to the network's low difficulty / security. Go Ethereum also supports connecting to a proof-of-authority based test network called [*Rinkeby*](https://www.rinkeby.io) (operated by members of the community). This network is lighter, more secure, but is only supported by go-ethereum.
+
+```
+$ geth --rinkeby console
+```
+
### Configuration
As an alternative to passing the numerous flags to the `geth` binary, you can also pass a configuration file via:
@@ -125,10 +131,10 @@ One of the quickest ways to get Ethereum up and running on your machine is by us
```
docker run -d --name ethereum-node -v /Users/alice/ethereum:/root \
-p 8545:8545 -p 30303:30303 \
- ethereum/client-go --fast --cache=512
+ ethereum/client-go
```
-This will start geth in fast sync mode with a DB memory allowance of 512MB just as the above command does. It will also create a persistent volume in your home directory for saving your blockchain as well as map the default ports. There is also an `alpine` tag available for a slim version of the image.
+This will start geth in fast-sync mode with a DB memory allowance of 1GB just as the above command does. It will also create a persistent volume in your home directory for saving your blockchain as well as map the default ports. There is also an `alpine` tag available for a slim version of the image.
Do not forget `--rpcaddr 0.0.0.0`, if you want to access RPC from other containers and/or hosts. By default, `geth` binds to the local interface and RPC endpoints is not accessible from the outside.
diff --git a/VERSION b/VERSION
index 27f9cd322..53adb84c8 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.8.0
+1.8.2
diff --git a/accounts/abi/abi.go b/accounts/abi/abi.go
index cbcf4ca92..254b1f7fb 100644
--- a/accounts/abi/abi.go
+++ b/accounts/abi/abi.go
@@ -97,7 +97,6 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
Type string
Name string
Constant bool
- Indexed bool
Anonymous bool
Inputs []Argument
Outputs []Argument
@@ -137,11 +136,11 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
// MethodById looks up a method by the 4-byte id
// returns nil if none found
-func (abi *ABI) MethodById(sigdata []byte) *Method {
+func (abi *ABI) MethodById(sigdata []byte) (*Method, error) {
for _, method := range abi.Methods {
if bytes.Equal(method.Id(), sigdata[:4]) {
- return &method
+ return &method, nil
}
}
- return nil
+ return nil, fmt.Errorf("no method with id: %#x", sigdata[:4])
}
diff --git a/accounts/abi/abi_test.go b/accounts/abi/abi_test.go
index 2d43b631c..35e0094dd 100644
--- a/accounts/abi/abi_test.go
+++ b/accounts/abi/abi_test.go
@@ -689,7 +689,11 @@ func TestABI_MethodById(t *testing.T) {
}
for name, m := range abi.Methods {
a := fmt.Sprintf("%v", m)
- b := fmt.Sprintf("%v", abi.MethodById(m.Id()))
+ m2, err := abi.MethodById(m.Id())
+ if err != nil {
+ t.Fatalf("Failed to look up ABI method: %v", err)
+ }
+ b := fmt.Sprintf("%v", m2)
if a != b {
t.Errorf("Method %v (id %v) not 'findable' by id in ABI", name, common.ToHex(m.Id()))
}
diff --git a/accounts/abi/argument.go b/accounts/abi/argument.go
index ad17fbf2b..f171f4cc6 100644
--- a/accounts/abi/argument.go
+++ b/accounts/abi/argument.go
@@ -67,6 +67,17 @@ func (arguments Arguments) LengthNonIndexed() int {
return out
}
+// NonIndexed returns the arguments with indexed arguments filtered out
+func (arguments Arguments) NonIndexed() Arguments {
+ var ret []Argument
+ for _, arg := range arguments {
+ if !arg.Indexed {
+ ret = append(ret, arg)
+ }
+ }
+ return ret
+}
+
// isTuple returns true for non-atomic constructs, like (uint,uint) or uint[]
func (arguments Arguments) isTuple() bool {
return len(arguments) > 1
@@ -74,21 +85,25 @@ func (arguments Arguments) isTuple() bool {
// Unpack performs the operation hexdata -> Go format
func (arguments Arguments) Unpack(v interface{}, data []byte) error {
- if arguments.isTuple() {
- return arguments.unpackTuple(v, data)
- }
- return arguments.unpackAtomic(v, data)
-}
-func (arguments Arguments) unpackTuple(v interface{}, output []byte) error {
// make sure the passed value is arguments pointer
- valueOf := reflect.ValueOf(v)
- if reflect.Ptr != valueOf.Kind() {
+ if reflect.Ptr != reflect.ValueOf(v).Kind() {
return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
}
+ marshalledValues, err := arguments.UnpackValues(data)
+ if err != nil {
+ return err
+ }
+ if arguments.isTuple() {
+ return arguments.unpackTuple(v, marshalledValues)
+ }
+ return arguments.unpackAtomic(v, marshalledValues)
+}
+
+func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error {
var (
- value = valueOf.Elem()
+ value = reflect.ValueOf(v).Elem()
typ = value.Type()
kind = value.Kind()
)
@@ -96,37 +111,30 @@ func (arguments Arguments) unpackTuple(v interface{}, output []byte) error {
if err := requireUnpackKind(value, typ, kind, arguments); err != nil {
return err
}
- // `i` counts the nonindexed arguments.
- // `j` counts the number of complex types.
- // both `i` and `j` are used to to correctly compute `data` offset.
-
- i, j := -1, 0
- for _, arg := range arguments {
-
- if arg.Indexed {
- // can't read, continue
- continue
- }
- i++
- marshalledValue, err := toGoType((i+j)*32, arg.Type, output)
- if err != nil {
- return err
- }
-
- if arg.Type.T == ArrayTy {
- // combined index ('i' + 'j') need to be adjusted only by size of array, thus
- // we need to decrement 'j' because 'i' was incremented
- j += arg.Type.Size - 1
+ // If the output interface is a struct, make sure names don't collide
+ if kind == reflect.Struct {
+ exists := make(map[string]bool)
+ for _, arg := range arguments {
+ field := capitalise(arg.Name)
+ if field == "" {
+ return fmt.Errorf("abi: purely underscored output cannot unpack to struct")
+ }
+ if exists[field] {
+ return fmt.Errorf("abi: multiple outputs mapping to the same struct field '%s'", field)
+ }
+ exists[field] = true
}
+ }
+ for i, arg := range arguments.NonIndexed() {
- reflectValue := reflect.ValueOf(marshalledValue)
+ reflectValue := reflect.ValueOf(marshalledValues[i])
switch kind {
case reflect.Struct:
+ name := capitalise(arg.Name)
for j := 0; j < typ.NumField(); j++ {
- field := typ.Field(j)
// TODO read tags: `abi:"fieldName"`
- if field.Name == strings.ToUpper(arg.Name[:1])+arg.Name[1:] {
+ if typ.Field(j).Name == name {
if err := set(value.Field(j), reflectValue, arg); err != nil {
return err
}
@@ -152,34 +160,52 @@ func (arguments Arguments) unpackTuple(v interface{}, output []byte) error {
}
// unpackAtomic unpacks ( hexdata -> go ) a single value
-func (arguments Arguments) unpackAtomic(v interface{}, output []byte) error {
- // make sure the passed value is arguments pointer
- valueOf := reflect.ValueOf(v)
- if reflect.Ptr != valueOf.Kind() {
- return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
- }
- arg := arguments[0]
- if arg.Indexed {
- return fmt.Errorf("abi: attempting to unpack indexed variable into element.")
+func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues []interface{}) error {
+ if len(marshalledValues) != 1 {
+ return fmt.Errorf("abi: wrong length, expected single value, got %d", len(marshalledValues))
}
+ elem := reflect.ValueOf(v).Elem()
+ reflectValue := reflect.ValueOf(marshalledValues[0])
+ return set(elem, reflectValue, arguments.NonIndexed()[0])
+}
- value := valueOf.Elem()
+// UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification,
+// without supplying a struct to unpack into. Instead, this method returns a list containing the
+// values. An atomic argument will be a list with one element.
+func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
+ retval := make([]interface{}, 0, arguments.LengthNonIndexed())
+ virtualArgs := 0
+ for index, arg := range arguments.NonIndexed() {
+ marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data)
+ if arg.Type.T == ArrayTy {
+ // If we have a static array, like [3]uint256, these are coded as
+ // just like uint256,uint256,uint256.
+ // This means that we need to add two 'virtual' arguments when
+ // we count the index from now on
- marshalledValue, err := toGoType(0, arg.Type, output)
- if err != nil {
- return err
+ virtualArgs += arg.Type.Size - 1
+ }
+ if err != nil {
+ return nil, err
+ }
+ retval = append(retval, marshalledValue)
}
- return set(value, reflect.ValueOf(marshalledValue), arg)
+ return retval, nil
+}
+
+// PackValues performs the operation Go format -> Hexdata
+// It is the semantic opposite of UnpackValues
+func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) {
+ return arguments.Pack(args...)
}
-// Unpack performs the operation Go format -> Hexdata
+// Pack performs the operation Go format -> Hexdata
func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
// Make sure arguments match up and pack them
abiArgs := arguments
if len(args) != len(abiArgs) {
return nil, fmt.Errorf("argument count mismatch: %d for %d", len(args), len(abiArgs))
}
-
// variable input is the output appended at the end of packed
// output. This is used for strings and bytes types input.
var variableInput []byte
@@ -188,12 +214,11 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
inputOffset := 0
for _, abiArg := range abiArgs {
if abiArg.Type.T == ArrayTy {
- inputOffset += (32 * abiArg.Type.Size)
+ inputOffset += 32 * abiArg.Type.Size
} else {
inputOffset += 32
}
}
-
var ret []byte
for i, a := range args {
input := abiArgs[i]
@@ -202,7 +227,6 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
if err != nil {
return nil, err
}
-
// check for a slice type (string, bytes, slice)
if input.Type.requiresLengthPrefix() {
// calculate the offset
@@ -222,3 +246,15 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
return ret, nil
}
+
+// capitalise makes the first character of a string upper case, also removing any
+// prefixing underscores from the variable names.
+func capitalise(input string) string {
+ for len(input) > 0 && input[0] == '_' {
+ input = input[1:]
+ }
+ if len(input) == 0 {
+ return ""
+ }
+ return strings.ToUpper(input[:1]) + input[1:]
+}
diff --git a/accounts/abi/bind/backend.go b/accounts/abi/bind/backend.go
index 25b61928e..ca60cc1b4 100644
--- a/accounts/abi/bind/backend.go
+++ b/accounts/abi/bind/backend.go
@@ -52,12 +52,6 @@ type ContractCaller interface {
CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error)
}
-// DeployBackend wraps the operations needed by WaitMined and WaitDeployed.
-type DeployBackend interface {
- TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
- CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error)
-}
-
// PendingContractCaller defines methods to perform contract calls on the pending state.
// Call will try to discover this interface when access to the pending state is requested.
// If the backend does not support the pending state, Call returns ErrNoPendingState.
@@ -85,13 +79,34 @@ type ContractTransactor interface {
// There is no guarantee that this is the true gas limit requirement as other
// transactions may be added or removed by miners, but it should provide a basis
// for setting a reasonable default.
- EstimateGas(ctx context.Context, call ethereum.CallMsg) (usedGas *big.Int, err error)
+ EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error)
// SendTransaction injects the transaction into the pending pool for execution.
SendTransaction(ctx context.Context, tx *types.Transaction) error
}
+// ContractFilterer defines the methods needed to access log events using one-off
+// queries or continuous event subscriptions.
+type ContractFilterer interface {
+ // FilterLogs executes a log filter operation, blocking during execution and
+ // returning all the results in one batch.
+ //
+ // TODO(karalabe): Deprecate when the subscription one can return past data too.
+ FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error)
+
+ // SubscribeFilterLogs creates a background log filtering operation, returning
+ // a subscription immediately, which can be used to stream the found events.
+ SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error)
+}
+
+// DeployBackend wraps the operations needed by WaitMined and WaitDeployed.
+type DeployBackend interface {
+ TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
+ CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error)
+}
+
// ContractBackend defines the methods needed to work with contracts on a read-write basis.
type ContractBackend interface {
ContractCaller
ContractTransactor
+ ContractFilterer
}
diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go
index 2cf6b9f78..bd342a8cb 100644
--- a/accounts/abi/bind/backends/simulated.go
+++ b/accounts/abi/bind/backends/simulated.go
@@ -30,11 +30,15 @@ import (
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/rpc"
)
// This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend.
@@ -53,6 +57,8 @@ type SimulatedBackend struct {
pendingBlock *types.Block // Currently pending block that will be imported on request
pendingState *state.StateDB // Currently pending state that will be the active on on request
+ events *filters.EventSystem // Event system for filtering log events live
+
config *params.ChainConfig
}
@@ -62,8 +68,14 @@ func NewSimulatedBackend(alloc core.GenesisAlloc) *SimulatedBackend {
database, _ := ethdb.NewMemDatabase()
genesis := core.Genesis{Config: params.AllEthashProtocolChanges, Alloc: alloc}
genesis.MustCommit(database)
- blockchain, _ := core.NewBlockChain(database, genesis.Config, ethash.NewFaker(), vm.Config{})
- backend := &SimulatedBackend{database: database, blockchain: blockchain, config: genesis.Config}
+ blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{})
+
+ backend := &SimulatedBackend{
+ database: database,
+ blockchain: blockchain,
+ config: genesis.Config,
+ events: filters.NewEventSystem(new(event.TypeMux), &filterBackend{database, blockchain}, false),
+ }
backend.rollback()
return backend
}
@@ -90,8 +102,10 @@ func (b *SimulatedBackend) Rollback() {
func (b *SimulatedBackend) rollback() {
blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(int, *core.BlockGen) {})
+ statedb, _ := b.blockchain.State()
+
b.pendingBlock = blocks[0]
- b.pendingState, _ = state.New(b.pendingBlock.Root(), state.NewDatabase(b.database))
+ b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database())
}
// CodeAt returns the code associated with a certain account in the blockchain.
@@ -200,7 +214,7 @@ func (b *SimulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error
// EstimateGas executes the requested code against the currently pending block/state and
// returns the used amount of gas.
-func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (*big.Int, error) {
+func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) {
b.mu.Lock()
defer b.mu.Unlock()
@@ -210,16 +224,16 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
hi uint64
cap uint64
)
- if call.Gas != nil && call.Gas.Uint64() >= params.TxGas {
- hi = call.Gas.Uint64()
+ if call.Gas >= params.TxGas {
+ hi = call.Gas
} else {
- hi = b.pendingBlock.GasLimit().Uint64()
+ hi = b.pendingBlock.GasLimit()
}
cap = hi
// Create a helper to check if a gas allowance results in an executable transaction
executable := func(gas uint64) bool {
- call.Gas = new(big.Int).SetUint64(gas)
+ call.Gas = gas
snapshot := b.pendingState.Snapshot()
_, _, failed, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
@@ -242,21 +256,21 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
// Reject the transaction as invalid if it still fails at the highest allowance
if hi == cap {
if !executable(hi) {
- return nil, errGasEstimationFailed
+ return 0, errGasEstimationFailed
}
}
- return new(big.Int).SetUint64(hi), nil
+ return hi, nil
}
-// callContract implemens common code between normal and pending contract calls.
+// callContract implements common code between normal and pending contract calls.
// state is modified during execution, make sure to copy it if necessary.
-func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, statedb *state.StateDB) ([]byte, *big.Int, bool, error) {
+func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, statedb *state.StateDB) ([]byte, uint64, bool, error) {
// Ensure message is initialized properly.
if call.GasPrice == nil {
call.GasPrice = big.NewInt(1)
}
- if call.Gas == nil || call.Gas.Sign() == 0 {
- call.Gas = big.NewInt(50000000)
+ if call.Gas == 0 {
+ call.Gas = 50000000
}
if call.Value == nil {
call.Value = new(big.Int)
@@ -271,9 +285,9 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
vmenv := vm.NewEVM(evmContext, statedb, b.config, vm.Config{})
- gaspool := new(core.GasPool).AddGas(math.MaxBig256)
- ret, gasUsed, _, failed, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
- return ret, gasUsed, failed, err
+ gaspool := new(core.GasPool).AddGas(math.MaxUint64)
+
+ return core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
}
// SendTransaction updates the pending block to include the given transaction.
@@ -297,12 +311,76 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
}
block.AddTx(tx)
})
+ statedb, _ := b.blockchain.State()
+
b.pendingBlock = blocks[0]
- b.pendingState, _ = state.New(b.pendingBlock.Root(), state.NewDatabase(b.database))
+ b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database())
return nil
}
-// JumpTimeInSeconds adds skip seconds to the clock
+// FilterLogs executes a log filter operation, blocking during execution and
+// returning all the results in one batch.
+//
+// TODO(karalabe): Deprecate when the subscription one can return past data too.
+func (b *SimulatedBackend) FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error) {
+ // Initialize unset filter boundaried to run from genesis to chain head
+ from := int64(0)
+ if query.FromBlock != nil {
+ from = query.FromBlock.Int64()
+ }
+ to := int64(-1)
+ if query.ToBlock != nil {
+ to = query.ToBlock.Int64()
+ }
+ // Construct and execute the filter
+ filter := filters.New(&filterBackend{b.database, b.blockchain}, from, to, query.Addresses, query.Topics)
+
+ logs, err := filter.Logs(ctx)
+ if err != nil {
+ return nil, err
+ }
+ res := make([]types.Log, len(logs))
+ for i, log := range logs {
+ res[i] = *log
+ }
+ return res, nil
+}
+
+// SubscribeFilterLogs creates a background log filtering operation, returning a
+// subscription immediately, which can be used to stream the found events.
+func (b *SimulatedBackend) SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) {
+ // Subscribe to contract events
+ sink := make(chan []*types.Log)
+
+ sub, err := b.events.SubscribeLogs(query, sink)
+ if err != nil {
+ return nil, err
+ }
+ // Since we're getting logs in batches, we need to flatten them into a plain stream
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case logs := <-sink:
+ for _, log := range logs {
+ select {
+ case ch <- *log:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// AdjustTime adds a time shift to the simulated clock.
func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
b.mu.Lock()
defer b.mu.Unlock()
@@ -312,8 +390,10 @@ func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
}
block.OffsetTime(int64(adjustment.Seconds()))
})
+ statedb, _ := b.blockchain.State()
+
b.pendingBlock = blocks[0]
- b.pendingState, _ = state.New(b.pendingBlock.Root(), state.NewDatabase(b.database))
+ b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database())
return nil
}
@@ -328,6 +408,47 @@ func (m callmsg) Nonce() uint64 { return 0 }
func (m callmsg) CheckNonce() bool { return false }
func (m callmsg) To() *common.Address { return m.CallMsg.To }
func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
-func (m callmsg) Gas() *big.Int { return m.CallMsg.Gas }
+func (m callmsg) Gas() uint64 { return m.CallMsg.Gas }
func (m callmsg) Value() *big.Int { return m.CallMsg.Value }
func (m callmsg) Data() []byte { return m.CallMsg.Data }
+
+// filterBackend implements filters.Backend to support filtering for logs without
+// taking bloom-bits acceleration structures into account.
+type filterBackend struct {
+ db ethdb.Database
+ bc *core.BlockChain
+}
+
+func (fb *filterBackend) ChainDb() ethdb.Database { return fb.db }
+func (fb *filterBackend) EventMux() *event.TypeMux { panic("not supported") }
+
+func (fb *filterBackend) HeaderByNumber(ctx context.Context, block rpc.BlockNumber) (*types.Header, error) {
+ if block == rpc.LatestBlockNumber {
+ return fb.bc.CurrentHeader(), nil
+ }
+ return fb.bc.GetHeaderByNumber(uint64(block.Int64())), nil
+}
+func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
+ return core.GetBlockReceipts(fb.db, hash, core.GetBlockNumber(fb.db, hash)), nil
+}
+
+func (fb *filterBackend) SubscribeTxPreEvent(ch chan<- core.TxPreEvent) event.Subscription {
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ <-quit
+ return nil
+ })
+}
+func (fb *filterBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
+ return fb.bc.SubscribeChainEvent(ch)
+}
+func (fb *filterBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
+ return fb.bc.SubscribeRemovedLogsEvent(ch)
+}
+func (fb *filterBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
+ return fb.bc.SubscribeLogsEvent(ch)
+}
+
+func (fb *filterBackend) BloomStatus() (uint64, uint64) { return 4096, 0 }
+func (fb *filterBackend) ServiceFilter(ctx context.Context, ms *bloombits.MatcherSession) {
+ panic("not supported")
+}
diff --git a/accounts/abi/bind/base.go b/accounts/abi/bind/base.go
index b40bd65e8..83ad1c8ae 100644
--- a/accounts/abi/bind/base.go
+++ b/accounts/abi/bind/base.go
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/event"
)
// SignerFn is a signer function callback when a contract requires a method to
@@ -50,11 +51,27 @@ type TransactOpts struct {
Value *big.Int // Funds to transfer along along the transaction (nil = 0 = no funds)
GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle)
- GasLimit *big.Int // Gas limit to set for the transaction execution (nil = estimate + 10%)
+ GasLimit uint64 // Gas limit to set for the transaction execution (0 = estimate)
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
}
+// FilterOpts is the collection of options to fine tune filtering for events
+// within a bound contract.
+type FilterOpts struct {
+ Start uint64 // Start of the queried range
+ End *uint64 // End of the range (nil = latest)
+
+ Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
+}
+
+// WatchOpts is the collection of options to fine tune subscribing for events
+// within a bound contract.
+type WatchOpts struct {
+ Start *uint64 // Start of the queried range (nil = latest)
+ Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
+}
+
// BoundContract is the base wrapper object that reflects a contract on the
// Ethereum network. It contains a collection of methods that are used by the
// higher level contract bindings to operate.
@@ -63,16 +80,18 @@ type BoundContract struct {
abi abi.ABI // Reflect based ABI to access the correct Ethereum methods
caller ContractCaller // Read interface to interact with the blockchain
transactor ContractTransactor // Write interface to interact with the blockchain
+ filterer ContractFilterer // Event filtering to interact with the blockchain
}
// NewBoundContract creates a low level contract interface through which calls
// and transactions may be made through.
-func NewBoundContract(address common.Address, abi abi.ABI, caller ContractCaller, transactor ContractTransactor) *BoundContract {
+func NewBoundContract(address common.Address, abi abi.ABI, caller ContractCaller, transactor ContractTransactor, filterer ContractFilterer) *BoundContract {
return &BoundContract{
address: address,
abi: abi,
caller: caller,
transactor: transactor,
+ filterer: filterer,
}
}
@@ -80,7 +99,7 @@ func NewBoundContract(address common.Address, abi abi.ABI, caller ContractCaller
// deployment address with a Go wrapper.
func DeployContract(opts *TransactOpts, abi abi.ABI, bytecode []byte, backend ContractBackend, params ...interface{}) (common.Address, *types.Transaction, *BoundContract, error) {
// Otherwise try to deploy the contract
- c := NewBoundContract(common.Address{}, abi, backend, backend)
+ c := NewBoundContract(common.Address{}, abi, backend, backend, backend)
input, err := c.abi.Pack("", params...)
if err != nil {
@@ -189,7 +208,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
}
}
gasLimit := opts.GasLimit
- if gasLimit == nil {
+ if gasLimit == 0 {
// Gas estimation cannot succeed without code for method invocations
if contract != nil {
if code, err := c.transactor.PendingCodeAt(ensureContext(opts.Context), c.address); err != nil {
@@ -225,6 +244,104 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
return signedTx, nil
}
+// FilterLogs filters contract logs for past blocks, returning the necessary
+// channels to construct a strongly typed bound iterator on top of them.
+func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]interface{}) (chan types.Log, event.Subscription, error) {
+ // Don't crash on a lazy user
+ if opts == nil {
+ opts = new(FilterOpts)
+ }
+ // Append the event selector to the query parameters and construct the topic set
+ query = append([][]interface{}{{c.abi.Events[name].Id()}}, query...)
+
+ topics, err := makeTopics(query...)
+ if err != nil {
+ return nil, nil, err
+ }
+ // Start the background filtering
+ logs := make(chan types.Log, 128)
+
+ config := ethereum.FilterQuery{
+ Addresses: []common.Address{c.address},
+ Topics: topics,
+ FromBlock: new(big.Int).SetUint64(opts.Start),
+ }
+ if opts.End != nil {
+ config.ToBlock = new(big.Int).SetUint64(*opts.End)
+ }
+ /* TODO(karalabe): Replace the rest of the method below with this when supported
+ sub, err := c.filterer.SubscribeFilterLogs(ensureContext(opts.Context), config, logs)
+ */
+ buff, err := c.filterer.FilterLogs(ensureContext(opts.Context), config)
+ if err != nil {
+ return nil, nil, err
+ }
+ sub, err := event.NewSubscription(func(quit <-chan struct{}) error {
+ for _, log := range buff {
+ select {
+ case logs <- log:
+ case <-quit:
+ return nil
+ }
+ }
+ return nil
+ }), nil
+
+ if err != nil {
+ return nil, nil, err
+ }
+ return logs, sub, nil
+}
+
+// WatchLogs filters subscribes to contract logs for future blocks, returning a
+// subscription object that can be used to tear down the watcher.
+func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]interface{}) (chan types.Log, event.Subscription, error) {
+ // Don't crash on a lazy user
+ if opts == nil {
+ opts = new(WatchOpts)
+ }
+ // Append the event selector to the query parameters and construct the topic set
+ query = append([][]interface{}{{c.abi.Events[name].Id()}}, query...)
+
+ topics, err := makeTopics(query...)
+ if err != nil {
+ return nil, nil, err
+ }
+ // Start the background filtering
+ logs := make(chan types.Log, 128)
+
+ config := ethereum.FilterQuery{
+ Addresses: []common.Address{c.address},
+ Topics: topics,
+ }
+ if opts.Start != nil {
+ config.FromBlock = new(big.Int).SetUint64(*opts.Start)
+ }
+ sub, err := c.filterer.SubscribeFilterLogs(ensureContext(opts.Context), config, logs)
+ if err != nil {
+ return nil, nil, err
+ }
+ return logs, sub, nil
+}
+
+// UnpackLog unpacks a retrieved log into the provided output structure.
+func (c *BoundContract) UnpackLog(out interface{}, event string, log types.Log) error {
+ if len(log.Data) > 0 {
+ if err := c.abi.Unpack(out, event, log.Data); err != nil {
+ return err
+ }
+ }
+ var indexed abi.Arguments
+ for _, arg := range c.abi.Events[event].Inputs {
+ if arg.Indexed {
+ indexed = append(indexed, arg)
+ }
+ }
+ return parseTopics(out, indexed, log.Topics[1:])
+}
+
+// ensureContext is a helper method to ensure a context is not nil, even if the
+// user specified it as such.
func ensureContext(ctx context.Context) context.Context {
if ctx == nil {
return context.TODO()
diff --git a/accounts/abi/bind/bind.go b/accounts/abi/bind/bind.go
index 4dce79b77..e31b45481 100644
--- a/accounts/abi/bind/bind.go
+++ b/accounts/abi/bind/bind.go
@@ -63,10 +63,11 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La
return r
}, abis[i])
- // Extract the call and transact methods, and sort them alphabetically
+ // Extract the call and transact methods; events; and sort them alphabetically
var (
calls = make(map[string]*tmplMethod)
transacts = make(map[string]*tmplMethod)
+ events = make(map[string]*tmplEvent)
)
for _, original := range evmABI.Methods {
// Normalize the method for capital cases and non-anonymous inputs/outputs
@@ -89,11 +90,33 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La
}
// Append the methods to the call or transact lists
if original.Const {
- calls[original.Name] = &tmplMethod{Original: original, Normalized: normalized, Structured: structured(original)}
+ calls[original.Name] = &tmplMethod{Original: original, Normalized: normalized, Structured: structured(original.Outputs)}
} else {
- transacts[original.Name] = &tmplMethod{Original: original, Normalized: normalized, Structured: structured(original)}
+ transacts[original.Name] = &tmplMethod{Original: original, Normalized: normalized, Structured: structured(original.Outputs)}
}
}
+ for _, original := range evmABI.Events {
+ // Skip anonymous events as they don't support explicit filtering
+ if original.Anonymous {
+ continue
+ }
+ // Normalize the event for capital cases and non-anonymous outputs
+ normalized := original
+ normalized.Name = methodNormalizer[lang](original.Name)
+
+ normalized.Inputs = make([]abi.Argument, len(original.Inputs))
+ copy(normalized.Inputs, original.Inputs)
+ for j, input := range normalized.Inputs {
+ // Indexed fields are input, non-indexed ones are outputs
+ if input.Indexed {
+ if input.Name == "" {
+ normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j)
+ }
+ }
+ }
+ // Append the event to the accumulator list
+ events[original.Name] = &tmplEvent{Original: original, Normalized: normalized}
+ }
contracts[types[i]] = &tmplContract{
Type: capitalise(types[i]),
InputABI: strings.Replace(strippedABI, "\"", "\\\"", -1),
@@ -101,6 +124,7 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La
Constructor: evmABI.Constructor,
Calls: calls,
Transacts: transacts,
+ Events: events,
}
}
// Generate the contract template data content and render it
@@ -111,10 +135,11 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La
buffer := new(bytes.Buffer)
funcs := map[string]interface{}{
- "bindtype": bindType[lang],
- "namedtype": namedType[lang],
- "capitalise": capitalise,
- "decapitalise": decapitalise,
+ "bindtype": bindType[lang],
+ "bindtopictype": bindTopicType[lang],
+ "namedtype": namedType[lang],
+ "capitalise": capitalise,
+ "decapitalise": decapitalise,
}
tmpl := template.Must(template.New("").Funcs(funcs).Parse(tmplSource[lang]))
if err := tmpl.Execute(buffer, data); err != nil {
@@ -133,7 +158,7 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La
}
// bindType is a set of type binders that convert Solidity types to some supported
-// programming language.
+// programming language types.
var bindType = map[Lang]func(kind abi.Type) string{
LangGo: bindTypeGo,
LangJava: bindTypeJava,
@@ -254,6 +279,33 @@ func bindTypeJava(kind abi.Type) string {
}
}
+// bindTopicType is a set of type binders that convert Solidity types to some
+// supported programming language topic types.
+var bindTopicType = map[Lang]func(kind abi.Type) string{
+ LangGo: bindTopicTypeGo,
+ LangJava: bindTopicTypeJava,
+}
+
+// bindTypeGo converts a Solidity topic type to a Go one. It is almost the same
+// funcionality as for simple types, but dynamic types get converted to hashes.
+func bindTopicTypeGo(kind abi.Type) string {
+ bound := bindTypeGo(kind)
+ if bound == "string" || bound == "[]byte" {
+ bound = "common.Hash"
+ }
+ return bound
+}
+
+// bindTypeGo converts a Solidity topic type to a Java one. It is almost the same
+// funcionality as for simple types, but dynamic types get converted to hashes.
+func bindTopicTypeJava(kind abi.Type) string {
+ bound := bindTypeJava(kind)
+ if bound == "String" || bound == "Bytes" {
+ bound = "Hash"
+ }
+ return bound
+}
+
// namedType is a set of functions that transform language specific types to
// named versions that my be used inside method names.
var namedType = map[Lang]func(string, abi.Type) string{
@@ -304,8 +356,15 @@ var methodNormalizer = map[Lang]func(string) string{
LangJava: decapitalise,
}
-// capitalise makes the first character of a string upper case.
+// capitalise makes the first character of a string upper case, also removing any
+// prefixing underscores from the variable names.
func capitalise(input string) string {
+ for len(input) > 0 && input[0] == '_' {
+ input = input[1:]
+ }
+ if len(input) == 0 {
+ return ""
+ }
return strings.ToUpper(input[:1]) + input[1:]
}
@@ -314,16 +373,25 @@ func decapitalise(input string) string {
return strings.ToLower(input[:1]) + input[1:]
}
-// structured checks whether a method has enough information to return a proper
-// Go struct ot if flat returns are needed.
-func structured(method abi.Method) bool {
- if len(method.Outputs) < 2 {
+// structured checks whether a list of ABI data types has enough information to
+// operate through a proper Go struct or if flat returns are needed.
+func structured(args abi.Arguments) bool {
+ if len(args) < 2 {
return false
}
- for _, out := range method.Outputs {
+ exists := make(map[string]bool)
+ for _, out := range args {
+ // If the name is anonymous, we can't organize into a struct
if out.Name == "" {
return false
}
+ // If the field name is empty when normalized or collides (var, Var, _var, _Var),
+ // we can't organize into a struct
+ field := capitalise(out.Name)
+ if field == "" || exists[field] {
+ return false
+ }
+ exists[field] = true
}
return true
}
diff --git a/accounts/abi/bind/bind_test.go b/accounts/abi/bind/bind_test.go
index 43ed53b92..c4838e647 100644
--- a/accounts/abi/bind/bind_test.go
+++ b/accounts/abi/bind/bind_test.go
@@ -126,6 +126,7 @@ var bindTests = []struct {
{"type":"function","name":"namedOutput","constant":true,"inputs":[],"outputs":[{"name":"str","type":"string"}]},
{"type":"function","name":"anonOutput","constant":true,"inputs":[],"outputs":[{"name":"","type":"string"}]},
{"type":"function","name":"namedOutputs","constant":true,"inputs":[],"outputs":[{"name":"str1","type":"string"},{"name":"str2","type":"string"}]},
+ {"type":"function","name":"collidingOutputs","constant":true,"inputs":[],"outputs":[{"name":"str","type":"string"},{"name":"Str","type":"string"}]},
{"type":"function","name":"anonOutputs","constant":true,"inputs":[],"outputs":[{"name":"","type":"string"},{"name":"","type":"string"}]},
{"type":"function","name":"mixedOutputs","constant":true,"inputs":[],"outputs":[{"name":"","type":"string"},{"name":"str","type":"string"}]}
]
@@ -140,12 +141,71 @@ var bindTests = []struct {
str1, err = b.NamedOutput(nil)
str1, err = b.AnonOutput(nil)
res, _ := b.NamedOutputs(nil)
+ str1, str2, err = b.CollidingOutputs(nil)
str1, str2, err = b.AnonOutputs(nil)
str1, str2, err = b.MixedOutputs(nil)
fmt.Println(str1, str2, res.Str1, res.Str2, err)
}`,
},
+ // Tests that named, anonymous and indexed events are handled correctly
+ {
+ `EventChecker`, ``, ``,
+ `
+ [
+ {"type":"event","name":"empty","inputs":[]},
+ {"type":"event","name":"indexed","inputs":[{"name":"addr","type":"address","indexed":true},{"name":"num","type":"int256","indexed":true}]},
+ {"type":"event","name":"mixed","inputs":[{"name":"addr","type":"address","indexed":true},{"name":"num","type":"int256"}]},
+ {"type":"event","name":"anonymous","anonymous":true,"inputs":[]},
+ {"type":"event","name":"dynamic","inputs":[{"name":"idxStr","type":"string","indexed":true},{"name":"idxDat","type":"bytes","indexed":true},{"name":"str","type":"string"},{"name":"dat","type":"bytes"}]}
+ ]
+ `,
+ `if e, err := NewEventChecker(common.Address{}, nil); e == nil || err != nil {
+ t.Fatalf("binding (%v) nil or error (%v) not nil", e, nil)
+ } else if false { // Don't run, just compile and test types
+ var (
+ err error
+ res bool
+ str string
+ dat []byte
+ hash common.Hash
+ )
+ _, err = e.FilterEmpty(nil)
+ _, err = e.FilterIndexed(nil, []common.Address{}, []*big.Int{})
+
+ mit, err := e.FilterMixed(nil, []common.Address{})
+
+ res = mit.Next() // Make sure the iterator has a Next method
+ err = mit.Error() // Make sure the iterator has an Error method
+ err = mit.Close() // Make sure the iterator has a Close method
+
+ fmt.Println(mit.Event.Raw.BlockHash) // Make sure the raw log is contained within the results
+ fmt.Println(mit.Event.Num) // Make sure the unpacked non-indexed fields are present
+ fmt.Println(mit.Event.Addr) // Make sure the reconstructed indexed fields are present
+
+ dit, err := e.FilterDynamic(nil, []string{}, [][]byte{})
+
+ str = dit.Event.Str // Make sure non-indexed strings retain their type
+ dat = dit.Event.Dat // Make sure non-indexed bytes retain their type
+ hash = dit.Event.IdxStr // Make sure indexed strings turn into hashes
+ hash = dit.Event.IdxDat // Make sure indexed bytes turn into hashes
+
+ sink := make(chan *EventCheckerMixed)
+ sub, err := e.WatchMixed(nil, sink, []common.Address{})
+ defer sub.Unsubscribe()
+
+ event := <-sink
+ fmt.Println(event.Raw.BlockHash) // Make sure the raw log is contained within the results
+ fmt.Println(event.Num) // Make sure the unpacked non-indexed fields are present
+ fmt.Println(event.Addr) // Make sure the reconstructed indexed fields are present
+
+ fmt.Println(res, str, dat, hash, err)
+ }
+ // Run a tiny reflection test to ensure disallowed methods don't appear
+ if _, ok := reflect.TypeOf(&EventChecker{}).MethodByName("FilterAnonymous"); ok {
+ t.Errorf("binding has disallowed method (FilterAnonymous)")
+ }`,
+ },
// Test that contract interactions (deploy, transact and call) generate working code
{
`Interactor`,
@@ -397,7 +457,6 @@ var bindTests = []struct {
sim.Commit()
// Set the field with automatic estimation and check that it succeeds
- auth.GasLimit = nil
if _, err := limiter.SetField(auth, "automatic"); err != nil {
t.Fatalf("Failed to call automatically gased transaction: %v", err)
}
@@ -447,6 +506,237 @@ var bindTests = []struct {
}
`,
},
+ {
+ `Underscorer`,
+ `
+ contract Underscorer {
+ function UnderscoredOutput() constant returns (int _int, string _string) {
+ return (314, "pi");
+ }
+ function LowerLowerCollision() constant returns (int _res, int res) {
+ return (1, 2);
+ }
+ function LowerUpperCollision() constant returns (int _res, int Res) {
+ return (1, 2);
+ }
+ function UpperLowerCollision() constant returns (int _Res, int res) {
+ return (1, 2);
+ }
+ function UpperUpperCollision() constant returns (int _Res, int Res) {
+ return (1, 2);
+ }
+ function PurelyUnderscoredOutput() constant returns (int _, int res) {
+ return (1, 2);
+ }
+ function AllPurelyUnderscoredOutput() constant returns (int _, int __) {
+ return (1, 2);
+ }
+ }
+ `, `6060604052341561000f57600080fd5b6103498061001e6000396000f300606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806303a592131461008857806367e6633d146100b85780639df484851461014d578063af7486ab1461017d578063b564b34d146101ad578063e02ab24d146101dd578063e409ca451461020d575b600080fd5b341561009357600080fd5b61009b61023d565b604051808381526020018281526020019250505060405180910390f35b34156100c357600080fd5b6100cb610252565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156101115780820151818401526020810190506100f6565b50505050905090810190601f16801561013e5780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b341561015857600080fd5b6101606102a0565b604051808381526020018281526020019250505060405180910390f35b341561018857600080fd5b6101906102b5565b604051808381526020018281526020019250505060405180910390f35b34156101b857600080fd5b6101c06102ca565b604051808381526020018281526020019250505060405180910390f35b34156101e857600080fd5b6101f06102df565b604051808381526020018281526020019250505060405180910390f35b341561021857600080fd5b6102206102f4565b604051808381526020018281526020019250505060405180910390f35b60008060016002819150809050915091509091565b600061025c610309565b61013a8090506040805190810160405280600281526020017f7069000000000000000000000000000000000000000000000000000000000000815250915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b6020604051908101604052806000815250905600a165627a7a72305820c11dcfa136fc7d182ee4d34f0b12d988496228f7e2d02d2b5376d996ca1743d00029`,
+ `[{"constant":true,"inputs":[],"name":"LowerUpperCollision","outputs":[{"name":"_res","type":"int256"},{"name":"Res","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"UnderscoredOutput","outputs":[{"name":"_int","type":"int256"},{"name":"_string","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PurelyUnderscoredOutput","outputs":[{"name":"_","type":"int256"},{"name":"res","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"UpperLowerCollision","outputs":[{"name":"_Res","type":"int256"},{"name":"res","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"AllPurelyUnderscoredOutput","outputs":[{"name":"_","type":"int256"},{"name":"__","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"UpperUpperCollision","outputs":[{"name":"_Res","type":"int256"},{"name":"Res","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"LowerLowerCollision","outputs":[{"name":"_res","type":"int256"},{"name":"res","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"}]`,
+ `
+ // Generate a new random account and a funded simulator
+ key, _ := crypto.GenerateKey()
+ auth := bind.NewKeyedTransactor(key)
+ sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
+
+ // Deploy a underscorer tester contract and execute a structured call on it
+ _, _, underscorer, err := DeployUnderscorer(auth, sim)
+ if err != nil {
+ t.Fatalf("Failed to deploy underscorer contract: %v", err)
+ }
+ sim.Commit()
+
+ // Verify that underscored return values correctly parse into structs
+ if res, err := underscorer.UnderscoredOutput(nil); err != nil {
+ t.Errorf("Failed to call constant function: %v", err)
+ } else if res.Int.Cmp(big.NewInt(314)) != 0 || res.String != "pi" {
+ t.Errorf("Invalid result, want: {314, \"pi\"}, got: %+v", res)
+ }
+ // Verify that underscored and non-underscored name collisions force tuple outputs
+ var a, b *big.Int
+
+ a, b, _ = underscorer.LowerLowerCollision(nil)
+ a, b, _ = underscorer.LowerUpperCollision(nil)
+ a, b, _ = underscorer.UpperLowerCollision(nil)
+ a, b, _ = underscorer.UpperUpperCollision(nil)
+ a, b, _ = underscorer.PurelyUnderscoredOutput(nil)
+ a, b, _ = underscorer.AllPurelyUnderscoredOutput(nil)
+
+ fmt.Println(a, b, err)
+ `,
+ },
+ // Tests that logs can be successfully filtered and decoded.
+ {
+ `Eventer`,
+ `
+ contract Eventer {
+ event SimpleEvent (
+ address indexed Addr,
+ bytes32 indexed Id,
+ bool indexed Flag,
+ uint Value
+ );
+ function raiseSimpleEvent(address addr, bytes32 id, bool flag, uint value) {
+ SimpleEvent(addr, id, flag, value);
+ }
+
+ event NodataEvent (
+ uint indexed Number,
+ int16 indexed Short,
+ uint32 indexed Long
+ );
+ function raiseNodataEvent(uint number, int16 short, uint32 long) {
+ NodataEvent(number, short, long);
+ }
+
+ event DynamicEvent (
+ string indexed IndexedString,
+ bytes indexed IndexedBytes,
+ string NonIndexedString,
+ bytes NonIndexedBytes
+ );
+ function raiseDynamicEvent(string str, bytes blob) {
+ DynamicEvent(str, blob, str, blob);
+ }
+ }
+ `,
+ `6060604052341561000f57600080fd5b61042c8061001e6000396000f300606060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063528300ff1461005c578063630c31e2146100fc578063c7d116dd14610156575b600080fd5b341561006757600080fd5b6100fa600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050610194565b005b341561010757600080fd5b610154600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035600019169060200190919080351515906020019091908035906020019091905050610367565b005b341561016157600080fd5b610192600480803590602001909190803560010b90602001909190803563ffffffff169060200190919050506103c3565b005b806040518082805190602001908083835b6020831015156101ca57805182526020820191506020810190506020830392506101a5565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020826040518082805190602001908083835b60208310151561022d5780518252602082019150602081019050602083039250610208565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f3281fd4f5e152dd3385df49104a3f633706e21c9e80672e88d3bcddf33101f008484604051808060200180602001838103835285818151815260200191508051906020019080838360005b838110156102c15780820151818401526020810190506102a6565b50505050905090810190601f1680156102ee5780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b8381101561032757808201518184015260208101905061030c565b50505050905090810190601f1680156103545780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a35050565b81151583600019168573ffffffffffffffffffffffffffffffffffffffff167f1f097de4289df643bd9c11011cc61367aa12983405c021056e706eb5ba1250c8846040518082815260200191505060405180910390a450505050565b8063ffffffff168260010b847f3ca7f3a77e5e6e15e781850bc82e32adfa378a2a609370db24b4d0fae10da2c960405160405180910390a45050505600a165627a7a72305820d1f8a8bbddbc5bb29f285891d6ae1eef8420c52afdc05e1573f6114d8e1714710029`,
+ `[{"constant":false,"inputs":[{"name":"str","type":"string"},{"name":"blob","type":"bytes"}],"name":"raiseDynamicEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"},{"name":"id","type":"bytes32"},{"name":"flag","type":"bool"},{"name":"value","type":"uint256"}],"name":"raiseSimpleEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"number","type":"uint256"},{"name":"short","type":"int16"},{"name":"long","type":"uint32"}],"name":"raiseNodataEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"Addr","type":"address"},{"indexed":true,"name":"Id","type":"bytes32"},{"indexed":true,"name":"Flag","type":"bool"},{"indexed":false,"name":"Value","type":"uint256"}],"name":"SimpleEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"Number","type":"uint256"},{"indexed":true,"name":"Short","type":"int16"},{"indexed":true,"name":"Long","type":"uint32"}],"name":"NodataEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"IndexedString","type":"string"},{"indexed":true,"name":"IndexedBytes","type":"bytes"},{"indexed":false,"name":"NonIndexedString","type":"string"},{"indexed":false,"name":"NonIndexedBytes","type":"bytes"}],"name":"DynamicEvent","type":"event"}]`,
+ `
+ // Generate a new random account and a funded simulator
+ key, _ := crypto.GenerateKey()
+ auth := bind.NewKeyedTransactor(key)
+ sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
+
+ // Deploy an eventer contract
+ _, _, eventer, err := DeployEventer(auth, sim)
+ if err != nil {
+ t.Fatalf("Failed to deploy eventer contract: %v", err)
+ }
+ sim.Commit()
+
+ // Inject a few events into the contract, gradually more in each block
+ for i := 1; i <= 3; i++ {
+ for j := 1; j <= i; j++ {
+ if _, err := eventer.RaiseSimpleEvent(auth, common.Address{byte(j)}, [32]byte{byte(j)}, true, big.NewInt(int64(10*i+j))); err != nil {
+ t.Fatalf("block %d, event %d: raise failed: %v", i, j, err)
+ }
+ }
+ sim.Commit()
+ }
+ // Test filtering for certain events and ensure they can be found
+ sit, err := eventer.FilterSimpleEvent(nil, []common.Address{common.Address{1}, common.Address{3}}, [][32]byte{{byte(1)}, {byte(2)}, {byte(3)}}, []bool{true})
+ if err != nil {
+ t.Fatalf("failed to filter for simple events: %v", err)
+ }
+ defer sit.Close()
+
+ sit.Next()
+ if sit.Event.Value.Uint64() != 11 || !sit.Event.Flag {
+ t.Errorf("simple log content mismatch: have %v, want {11, true}", sit.Event)
+ }
+ sit.Next()
+ if sit.Event.Value.Uint64() != 21 || !sit.Event.Flag {
+ t.Errorf("simple log content mismatch: have %v, want {21, true}", sit.Event)
+ }
+ sit.Next()
+ if sit.Event.Value.Uint64() != 31 || !sit.Event.Flag {
+ t.Errorf("simple log content mismatch: have %v, want {31, true}", sit.Event)
+ }
+ sit.Next()
+ if sit.Event.Value.Uint64() != 33 || !sit.Event.Flag {
+ t.Errorf("simple log content mismatch: have %v, want {33, true}", sit.Event)
+ }
+
+ if sit.Next() {
+ t.Errorf("unexpected simple event found: %+v", sit.Event)
+ }
+ if err = sit.Error(); err != nil {
+ t.Fatalf("simple event iteration failed: %v", err)
+ }
+ // Test raising and filtering for an event with no data component
+ if _, err := eventer.RaiseNodataEvent(auth, big.NewInt(314), 141, 271); err != nil {
+ t.Fatalf("failed to raise nodata event: %v", err)
+ }
+ sim.Commit()
+
+ nit, err := eventer.FilterNodataEvent(nil, []*big.Int{big.NewInt(314)}, []int16{140, 141, 142}, []uint32{271})
+ if err != nil {
+ t.Fatalf("failed to filter for nodata events: %v", err)
+ }
+ defer nit.Close()
+
+ if !nit.Next() {
+ t.Fatalf("nodata log not found: %v", nit.Error())
+ }
+ if nit.Event.Number.Uint64() != 314 {
+ t.Errorf("nodata log content mismatch: have %v, want 314", nit.Event.Number)
+ }
+ if nit.Next() {
+ t.Errorf("unexpected nodata event found: %+v", nit.Event)
+ }
+ if err = nit.Error(); err != nil {
+ t.Fatalf("nodata event iteration failed: %v", err)
+ }
+ // Test raising and filtering for events with dynamic indexed components
+ if _, err := eventer.RaiseDynamicEvent(auth, "Hello", []byte("World")); err != nil {
+ t.Fatalf("failed to raise dynamic event: %v", err)
+ }
+ sim.Commit()
+
+ dit, err := eventer.FilterDynamicEvent(nil, []string{"Hi", "Hello", "Bye"}, [][]byte{[]byte("World")})
+ if err != nil {
+ t.Fatalf("failed to filter for dynamic events: %v", err)
+ }
+ defer dit.Close()
+
+ if !dit.Next() {
+ t.Fatalf("dynamic log not found: %v", dit.Error())
+ }
+ if dit.Event.NonIndexedString != "Hello" || string(dit.Event.NonIndexedBytes) != "World" || dit.Event.IndexedString != common.HexToHash("0x06b3dfaec148fb1bb2b066f10ec285e7c9bf402ab32aa78a5d38e34566810cd2") || dit.Event.IndexedBytes != common.HexToHash("0xf2208c967df089f60420785795c0a9ba8896b0f6f1867fa7f1f12ad6f79c1a18") {
+ t.Errorf("dynamic log content mismatch: have %v, want {'0x06b3dfaec148fb1bb2b066f10ec285e7c9bf402ab32aa78a5d38e34566810cd2, '0xf2208c967df089f60420785795c0a9ba8896b0f6f1867fa7f1f12ad6f79c1a18', 'Hello', 'World'}", dit.Event)
+ }
+ if dit.Next() {
+ t.Errorf("unexpected dynamic event found: %+v", dit.Event)
+ }
+ if err = dit.Error(); err != nil {
+ t.Fatalf("dynamic event iteration failed: %v", err)
+ }
+ // Test subscribing to an event and raising it afterwards
+ ch := make(chan *EventerSimpleEvent, 16)
+ sub, err := eventer.WatchSimpleEvent(nil, ch, nil, nil, nil)
+ if err != nil {
+ t.Fatalf("failed to subscribe to simple events: %v", err)
+ }
+ if _, err := eventer.RaiseSimpleEvent(auth, common.Address{255}, [32]byte{255}, true, big.NewInt(255)); err != nil {
+ t.Fatalf("failed to raise subscribed simple event: %v", err)
+ }
+ sim.Commit()
+
+ select {
+ case event := <-ch:
+ if event.Value.Uint64() != 255 {
+ t.Errorf("simple log content mismatch: have %v, want 255", event)
+ }
+ case <-time.After(250 * time.Millisecond):
+ t.Fatalf("subscribed simple event didn't arrive")
+ }
+ // Unsubscribe from the event and make sure we're not delivered more
+ sub.Unsubscribe()
+
+ if _, err := eventer.RaiseSimpleEvent(auth, common.Address{254}, [32]byte{254}, true, big.NewInt(254)); err != nil {
+ t.Fatalf("failed to raise subscribed simple event: %v", err)
+ }
+ sim.Commit()
+
+ select {
+ case event := <-ch:
+ t.Fatalf("unsubscribed simple event arrived: %v", event)
+ case <-time.After(250 * time.Millisecond):
+ }
+ `,
+ },
}
// Tests that packages generated by the binder can be successfully compiled and
@@ -498,7 +788,7 @@ func TestBindings(t *testing.T) {
}
}
// Test the entire package and report any failures
- cmd := exec.Command(gocmd, "test", "-v")
+ cmd := exec.Command(gocmd, "test", "-v", "-count", "1")
cmd.Dir = pkg
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("failed to run binding test: %v\n%s", err, out)
diff --git a/accounts/abi/bind/template.go b/accounts/abi/bind/template.go
index d07610e7c..7202ee67a 100644
--- a/accounts/abi/bind/template.go
+++ b/accounts/abi/bind/template.go
@@ -32,6 +32,7 @@ type tmplContract struct {
Constructor abi.Method // Contract constructor for deploy parametrization
Calls map[string]*tmplMethod // Contract calls that only read state data
Transacts map[string]*tmplMethod // Contract calls that write state data
+ Events map[string]*tmplEvent // Contract events accessors
}
// tmplMethod is a wrapper around an abi.Method that contains a few preprocessed
@@ -39,7 +40,13 @@ type tmplContract struct {
type tmplMethod struct {
Original abi.Method // Original method as parsed by the abi package
Normalized abi.Method // Normalized version of the parsed method (capitalized names, non-anonymous args/returns)
- Structured bool // Whether the returns should be accumulated into a contract
+ Structured bool // Whether the returns should be accumulated into a struct
+}
+
+// tmplEvent is a wrapper around an a
+type tmplEvent struct {
+ Original abi.Event // Original event as parsed by the abi package
+ Normalized abi.Event // Normalized version of the parsed fields
}
// tmplSource is language to template mapping containing all the supported
@@ -75,7 +82,7 @@ package {{.Package}}
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &{{.Type}}{ {{.Type}}Caller: {{.Type}}Caller{contract: contract}, {{.Type}}Transactor: {{.Type}}Transactor{contract: contract} }, nil
+ return address, tx, &{{.Type}}{ {{.Type}}Caller: {{.Type}}Caller{contract: contract}, {{.Type}}Transactor: {{.Type}}Transactor{contract: contract}, {{.Type}}Filterer: {{.Type}}Filterer{contract: contract} }, nil
}
{{end}}
@@ -83,6 +90,7 @@ package {{.Package}}
type {{.Type}} struct {
{{.Type}}Caller // Read-only binding to the contract
{{.Type}}Transactor // Write-only binding to the contract
+ {{.Type}}Filterer // Log filterer for contract events
}
// {{.Type}}Caller is an auto generated read-only Go binding around an Ethereum contract.
@@ -95,6 +103,11 @@ package {{.Package}}
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
+ // {{.Type}}Filterer is an auto generated log filtering Go binding around an Ethereum contract events.
+ type {{.Type}}Filterer struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+ }
+
// {{.Type}}Session is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type {{.Type}}Session struct {
@@ -134,16 +147,16 @@ package {{.Package}}
// New{{.Type}} creates a new instance of {{.Type}}, bound to a specific deployed contract.
func New{{.Type}}(address common.Address, backend bind.ContractBackend) (*{{.Type}}, error) {
- contract, err := bind{{.Type}}(address, backend, backend)
+ contract, err := bind{{.Type}}(address, backend, backend, backend)
if err != nil {
return nil, err
}
- return &{{.Type}}{ {{.Type}}Caller: {{.Type}}Caller{contract: contract}, {{.Type}}Transactor: {{.Type}}Transactor{contract: contract} }, nil
+ return &{{.Type}}{ {{.Type}}Caller: {{.Type}}Caller{contract: contract}, {{.Type}}Transactor: {{.Type}}Transactor{contract: contract}, {{.Type}}Filterer: {{.Type}}Filterer{contract: contract} }, nil
}
// New{{.Type}}Caller creates a new read-only instance of {{.Type}}, bound to a specific deployed contract.
func New{{.Type}}Caller(address common.Address, caller bind.ContractCaller) (*{{.Type}}Caller, error) {
- contract, err := bind{{.Type}}(address, caller, nil)
+ contract, err := bind{{.Type}}(address, caller, nil, nil)
if err != nil {
return nil, err
}
@@ -152,20 +165,29 @@ package {{.Package}}
// New{{.Type}}Transactor creates a new write-only instance of {{.Type}}, bound to a specific deployed contract.
func New{{.Type}}Transactor(address common.Address, transactor bind.ContractTransactor) (*{{.Type}}Transactor, error) {
- contract, err := bind{{.Type}}(address, nil, transactor)
+ contract, err := bind{{.Type}}(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &{{.Type}}Transactor{contract: contract}, nil
}
+ // New{{.Type}}Filterer creates a new log filterer instance of {{.Type}}, bound to a specific deployed contract.
+ func New{{.Type}}Filterer(address common.Address, filterer bind.ContractFilterer) (*{{.Type}}Filterer, error) {
+ contract, err := bind{{.Type}}(address, nil, nil, filterer)
+ if err != nil {
+ return nil, err
+ }
+ return &{{.Type}}Filterer{contract: contract}, nil
+ }
+
// bind{{.Type}} binds a generic wrapper to an already deployed contract.
- func bind{{.Type}}(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
+ func bind{{.Type}}(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader({{.Type}}ABI))
if err != nil {
return nil, err
}
- return bind.NewBoundContract(address, parsed, caller, transactor), nil
+ return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
@@ -263,6 +285,137 @@ package {{.Package}}
return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.TransactOpts {{range $i, $_ := .Normalized.Inputs}}, {{.Name}}{{end}})
}
{{end}}
+
+ {{range .Events}}
+ // {{$contract.Type}}{{.Normalized.Name}}Iterator is returned from Filter{{.Normalized.Name}} and is used to iterate over the raw logs and unpacked data for {{.Normalized.Name}} events raised by the {{$contract.Type}} contract.
+ type {{$contract.Type}}{{.Normalized.Name}}Iterator struct {
+ Event *{{$contract.Type}}{{.Normalized.Name}} // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+ }
+ // Next advances the iterator to the subsequent event, returning whether there
+ // are any more events found. In case of a retrieval or parsing error, false is
+ // returned and Error() can be queried for the exact failure.
+ func (it *{{$contract.Type}}{{.Normalized.Name}}Iterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if (it.fail != nil) {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if (it.done) {
+ select {
+ case log := <-it.logs:
+ it.Event = new({{$contract.Type}}{{.Normalized.Name}})
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new({{$contract.Type}}{{.Normalized.Name}})
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+ }
+ // Error returns any retrieval or parsing error occurred during filtering.
+ func (it *{{$contract.Type}}{{.Normalized.Name}}Iterator) Error() error {
+ return it.fail
+ }
+ // Close terminates the iteration process, releasing any pending underlying
+ // resources.
+ func (it *{{$contract.Type}}{{.Normalized.Name}}Iterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+ }
+
+ // {{$contract.Type}}{{.Normalized.Name}} represents a {{.Normalized.Name}} event raised by the {{$contract.Type}} contract.
+ type {{$contract.Type}}{{.Normalized.Name}} struct { {{range .Normalized.Inputs}}
+ {{capitalise .Name}} {{if .Indexed}}{{bindtopictype .Type}}{{else}}{{bindtype .Type}}{{end}}; {{end}}
+ Raw types.Log // Blockchain specific contextual infos
+ }
+
+ // Filter{{.Normalized.Name}} is a free log retrieval operation binding the contract event 0x{{printf "%x" .Original.Id}}.
+ //
+ // Solidity: {{.Original.String}}
+ func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Filter{{.Normalized.Name}}(opts *bind.FilterOpts{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}} []{{bindtype .Type}}{{end}}{{end}}) (*{{$contract.Type}}{{.Normalized.Name}}Iterator, error) {
+ {{range .Normalized.Inputs}}
+ {{if .Indexed}}var {{.Name}}Rule []interface{}
+ for _, {{.Name}}Item := range {{.Name}} {
+ {{.Name}}Rule = append({{.Name}}Rule, {{.Name}}Item)
+ }{{end}}{{end}}
+
+ logs, sub, err := _{{$contract.Type}}.contract.FilterLogs(opts, "{{.Original.Name}}"{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}}Rule{{end}}{{end}})
+ if err != nil {
+ return nil, err
+ }
+ return &{{$contract.Type}}{{.Normalized.Name}}Iterator{contract: _{{$contract.Type}}.contract, event: "{{.Original.Name}}", logs: logs, sub: sub}, nil
+ }
+
+ // Watch{{.Normalized.Name}} is a free log subscription operation binding the contract event 0x{{printf "%x" .Original.Id}}.
+ //
+ // Solidity: {{.Original.String}}
+ func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Watch{{.Normalized.Name}}(opts *bind.WatchOpts, sink chan<- *{{$contract.Type}}{{.Normalized.Name}}{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}} []{{bindtype .Type}}{{end}}{{end}}) (event.Subscription, error) {
+ {{range .Normalized.Inputs}}
+ {{if .Indexed}}var {{.Name}}Rule []interface{}
+ for _, {{.Name}}Item := range {{.Name}} {
+ {{.Name}}Rule = append({{.Name}}Rule, {{.Name}}Item)
+ }{{end}}{{end}}
+
+ logs, sub, err := _{{$contract.Type}}.contract.WatchLogs(opts, "{{.Original.Name}}"{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}}Rule{{end}}{{end}})
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new({{$contract.Type}}{{.Normalized.Name}})
+ if err := _{{$contract.Type}}.contract.UnpackLog(event, "{{.Original.Name}}", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+ }
+ {{end}}
{{end}}
`
diff --git a/accounts/abi/bind/topics.go b/accounts/abi/bind/topics.go
new file mode 100644
index 000000000..600dfcda9
--- /dev/null
+++ b/accounts/abi/bind/topics.go
@@ -0,0 +1,189 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package bind
+
+import (
+ "errors"
+ "fmt"
+ "math/big"
+ "reflect"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+)
+
+// makeTopics converts a filter query argument list into a filter topic set.
+func makeTopics(query ...[]interface{}) ([][]common.Hash, error) {
+ topics := make([][]common.Hash, len(query))
+ for i, filter := range query {
+ for _, rule := range filter {
+ var topic common.Hash
+
+ // Try to generate the topic based on simple types
+ switch rule := rule.(type) {
+ case common.Hash:
+ copy(topic[:], rule[:])
+ case common.Address:
+ copy(topic[common.HashLength-common.AddressLength:], rule[:])
+ case *big.Int:
+ blob := rule.Bytes()
+ copy(topic[common.HashLength-len(blob):], blob)
+ case bool:
+ if rule {
+ topic[common.HashLength-1] = 1
+ }
+ case int8:
+ blob := big.NewInt(int64(rule)).Bytes()
+ copy(topic[common.HashLength-len(blob):], blob)
+ case int16:
+ blob := big.NewInt(int64(rule)).Bytes()
+ copy(topic[common.HashLength-len(blob):], blob)
+ case int32:
+ blob := big.NewInt(int64(rule)).Bytes()
+ copy(topic[common.HashLength-len(blob):], blob)
+ case int64:
+ blob := big.NewInt(rule).Bytes()
+ copy(topic[common.HashLength-len(blob):], blob)
+ case uint8:
+ blob := new(big.Int).SetUint64(uint64(rule)).Bytes()
+ copy(topic[common.HashLength-len(blob):], blob)
+ case uint16:
+ blob := new(big.Int).SetUint64(uint64(rule)).Bytes()
+ copy(topic[common.HashLength-len(blob):], blob)
+ case uint32:
+ blob := new(big.Int).SetUint64(uint64(rule)).Bytes()
+ copy(topic[common.HashLength-len(blob):], blob)
+ case uint64:
+ blob := new(big.Int).SetUint64(rule).Bytes()
+ copy(topic[common.HashLength-len(blob):], blob)
+ case string:
+ hash := crypto.Keccak256Hash([]byte(rule))
+ copy(topic[:], hash[:])
+ case []byte:
+ hash := crypto.Keccak256Hash(rule)
+ copy(topic[:], hash[:])
+
+ default:
+ // Attempt to generate the topic from funky types
+ val := reflect.ValueOf(rule)
+
+ switch {
+ case val.Kind() == reflect.Array && reflect.TypeOf(rule).Elem().Kind() == reflect.Uint8:
+ reflect.Copy(reflect.ValueOf(topic[common.HashLength-val.Len():]), val)
+
+ default:
+ return nil, fmt.Errorf("unsupported indexed type: %T", rule)
+ }
+ }
+ topics[i] = append(topics[i], topic)
+ }
+ }
+ return topics, nil
+}
+
+// Big batch of reflect types for topic reconstruction.
+var (
+ reflectHash = reflect.TypeOf(common.Hash{})
+ reflectAddress = reflect.TypeOf(common.Address{})
+ reflectBigInt = reflect.TypeOf(new(big.Int))
+)
+
+// parseTopics converts the indexed topic fields into actual log field values.
+//
+// Note, dynamic types cannot be reconstructed since they get mapped to Keccak256
+// hashes as the topic value!
+func parseTopics(out interface{}, fields abi.Arguments, topics []common.Hash) error {
+ // Sanity check that the fields and topics match up
+ if len(fields) != len(topics) {
+ return errors.New("topic/field count mismatch")
+ }
+ // Iterate over all the fields and reconstruct them from topics
+ for _, arg := range fields {
+ if !arg.Indexed {
+ return errors.New("non-indexed field in topic reconstruction")
+ }
+ field := reflect.ValueOf(out).Elem().FieldByName(capitalise(arg.Name))
+
+ // Try to parse the topic back into the fields based on primitive types
+ switch field.Kind() {
+ case reflect.Bool:
+ if topics[0][common.HashLength-1] == 1 {
+ field.Set(reflect.ValueOf(true))
+ }
+ case reflect.Int8:
+ num := new(big.Int).SetBytes(topics[0][:])
+ field.Set(reflect.ValueOf(int8(num.Int64())))
+
+ case reflect.Int16:
+ num := new(big.Int).SetBytes(topics[0][:])
+ field.Set(reflect.ValueOf(int16(num.Int64())))
+
+ case reflect.Int32:
+ num := new(big.Int).SetBytes(topics[0][:])
+ field.Set(reflect.ValueOf(int32(num.Int64())))
+
+ case reflect.Int64:
+ num := new(big.Int).SetBytes(topics[0][:])
+ field.Set(reflect.ValueOf(num.Int64()))
+
+ case reflect.Uint8:
+ num := new(big.Int).SetBytes(topics[0][:])
+ field.Set(reflect.ValueOf(uint8(num.Uint64())))
+
+ case reflect.Uint16:
+ num := new(big.Int).SetBytes(topics[0][:])
+ field.Set(reflect.ValueOf(uint16(num.Uint64())))
+
+ case reflect.Uint32:
+ num := new(big.Int).SetBytes(topics[0][:])
+ field.Set(reflect.ValueOf(uint32(num.Uint64())))
+
+ case reflect.Uint64:
+ num := new(big.Int).SetBytes(topics[0][:])
+ field.Set(reflect.ValueOf(num.Uint64()))
+
+ default:
+ // Ran out of plain primitive types, try custom types
+ switch field.Type() {
+ case reflectHash: // Also covers all dynamic types
+ field.Set(reflect.ValueOf(topics[0]))
+
+ case reflectAddress:
+ var addr common.Address
+ copy(addr[:], topics[0][common.HashLength-common.AddressLength:])
+ field.Set(reflect.ValueOf(addr))
+
+ case reflectBigInt:
+ num := new(big.Int).SetBytes(topics[0][:])
+ field.Set(reflect.ValueOf(num))
+
+ default:
+ // Ran out of custom types, try the crazies
+ switch {
+ case arg.Type.T == abi.FixedBytesTy:
+ reflect.Copy(field, reflect.ValueOf(topics[0][common.HashLength-arg.Type.Size:]))
+
+ default:
+ return fmt.Errorf("unsupported indexed type: %v", arg.Type)
+ }
+ }
+ }
+ topics = topics[1:]
+ }
+ return nil
+}
diff --git a/accounts/abi/bind/util_test.go b/accounts/abi/bind/util_test.go
index d24aa721e..49e6dc813 100644
--- a/accounts/abi/bind/util_test.go
+++ b/accounts/abi/bind/util_test.go
@@ -34,18 +34,18 @@ var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d
var waitDeployedTests = map[string]struct {
code string
- gas *big.Int
+ gas uint64
wantAddress common.Address
wantErr error
}{
"successful deploy": {
code: `6060604052600a8060106000396000f360606040526008565b00`,
- gas: big.NewInt(3000000),
+ gas: 3000000,
wantAddress: common.HexToAddress("0x3a220f351252089d385b29beca14e27f204c296a"),
},
"empty code": {
code: ``,
- gas: big.NewInt(300000),
+ gas: 300000,
wantErr: bind.ErrNoCodeAfterDeploy,
wantAddress: common.HexToAddress("0x3a220f351252089d385b29beca14e27f204c296a"),
},
diff --git a/accounts/abi/event.go b/accounts/abi/event.go
index 726bac90e..595f169f3 100644
--- a/accounts/abi/event.go
+++ b/accounts/abi/event.go
@@ -33,6 +33,17 @@ type Event struct {
Inputs Arguments
}
+func (event Event) String() string {
+ inputs := make([]string, len(event.Inputs))
+ for i, input := range event.Inputs {
+ inputs[i] = fmt.Sprintf("%v %v", input.Name, input.Type)
+ if input.Indexed {
+ inputs[i] = fmt.Sprintf("%v indexed %v", input.Name, input.Type)
+ }
+ }
+ return fmt.Sprintf("event %v(%v)", event.Name, strings.Join(inputs, ", "))
+}
+
// Id returns the canonical representation of the event's signature used by the
// abi definition to identify event names and types.
func (e Event) Id() common.Hash {
diff --git a/accounts/abi/pack_test.go b/accounts/abi/pack_test.go
index 36401ee67..14ab516ac 100644
--- a/accounts/abi/pack_test.go
+++ b/accounts/abi/pack_test.go
@@ -1,4 +1,4 @@
-// Copyright 2015 The go-ethereum Authors
+// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
diff --git a/accounts/abi/unpack.go b/accounts/abi/unpack.go
index 80efb3f7e..761c80edf 100644
--- a/accounts/abi/unpack.go
+++ b/accounts/abi/unpack.go
@@ -1,4 +1,4 @@
-// Copyright 2015 The go-ethereum Authors
+// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
@@ -95,6 +95,9 @@ func readFixedBytes(t Type, word []byte) (interface{}, error) {
// iteratively unpack elements
func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error) {
+ if size < 0 {
+ return nil, fmt.Errorf("cannot marshal input to array, size is negative (%d)", size)
+ }
if start+32*size > len(output) {
return nil, fmt.Errorf("abi: cannot marshal in to go array: offset %d would go over slice boundary (len=%d)", len(output), start+32*size)
}
@@ -181,16 +184,32 @@ func toGoType(index int, t Type, output []byte) (interface{}, error) {
// interprets a 32 byte slice as an offset and then determines which indice to look to decode the type.
func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err error) {
- offset := int(binary.BigEndian.Uint64(output[index+24 : index+32]))
- if offset+32 > len(output) {
- return 0, 0, fmt.Errorf("abi: cannot marshal in to go slice: offset %d would go over slice boundary (len=%d)", len(output), offset+32)
+ bigOffsetEnd := big.NewInt(0).SetBytes(output[index : index+32])
+ bigOffsetEnd.Add(bigOffsetEnd, common.Big32)
+ outputLength := big.NewInt(int64(len(output)))
+
+ if bigOffsetEnd.Cmp(outputLength) > 0 {
+ return 0, 0, fmt.Errorf("abi: cannot marshal in to go slice: offset %v would go over slice boundary (len=%v)", bigOffsetEnd, outputLength)
}
- length = int(binary.BigEndian.Uint64(output[offset+24 : offset+32]))
- if offset+32+length > len(output) {
- return 0, 0, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %d require %d", len(output), offset+32+length)
+
+ if bigOffsetEnd.BitLen() > 63 {
+ return 0, 0, fmt.Errorf("abi offset larger than int64: %v", bigOffsetEnd)
}
- start = offset + 32
- //fmt.Printf("LENGTH PREFIX INFO: \nsize: %v\noffset: %v\nstart: %v\n", length, offset, start)
+ offsetEnd := int(bigOffsetEnd.Uint64())
+ lengthBig := big.NewInt(0).SetBytes(output[offsetEnd-32 : offsetEnd])
+
+ totalSize := big.NewInt(0)
+ totalSize.Add(totalSize, bigOffsetEnd)
+ totalSize.Add(totalSize, lengthBig)
+ if totalSize.BitLen() > 63 {
+ return 0, 0, fmt.Errorf("abi length larger than int64: %v", totalSize)
+ }
+
+ if totalSize.Cmp(outputLength) > 0 {
+ return 0, 0, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %v require %v", outputLength, totalSize)
+ }
+ start = int(bigOffsetEnd.Uint64())
+ length = int(lengthBig.Uint64())
return
}
diff --git a/accounts/abi/unpack_test.go b/accounts/abi/unpack_test.go
index 391095073..742211244 100644
--- a/accounts/abi/unpack_test.go
+++ b/accounts/abi/unpack_test.go
@@ -1,4 +1,4 @@
-// Copyright 2015 The go-ethereum Authors
+// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
@@ -130,7 +130,7 @@ var unpackTests = []unpackTest{
{
def: `[{"type": "bytes32"}]`,
enc: "0100000000000000000000000000000000000000000000000000000000000000",
- want: common.HexToHash("0100000000000000000000000000000000000000000000000000000000000000"),
+ want: [32]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
},
{
def: `[{"type": "function"}]`,
@@ -259,6 +259,51 @@ var unpackTests = []unpackTest{
enc: "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003",
want: [3]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)},
},
+ // struct outputs
+ {
+ def: `[{"name":"int1","type":"int256"},{"name":"int2","type":"int256"}]`,
+ enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
+ want: struct {
+ Int1 *big.Int
+ Int2 *big.Int
+ }{big.NewInt(1), big.NewInt(2)},
+ },
+ {
+ def: `[{"name":"int","type":"int256"},{"name":"Int","type":"int256"}]`,
+ enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
+ want: struct {
+ Int1 *big.Int
+ Int2 *big.Int
+ }{},
+ err: "abi: multiple outputs mapping to the same struct field 'Int'",
+ },
+ {
+ def: `[{"name":"int","type":"int256"},{"name":"_int","type":"int256"}]`,
+ enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
+ want: struct {
+ Int1 *big.Int
+ Int2 *big.Int
+ }{},
+ err: "abi: multiple outputs mapping to the same struct field 'Int'",
+ },
+ {
+ def: `[{"name":"Int","type":"int256"},{"name":"_int","type":"int256"}]`,
+ enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
+ want: struct {
+ Int1 *big.Int
+ Int2 *big.Int
+ }{},
+ err: "abi: multiple outputs mapping to the same struct field 'Int'",
+ },
+ {
+ def: `[{"name":"Int","type":"int256"},{"name":"_","type":"int256"}]`,
+ enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
+ want: struct {
+ Int1 *big.Int
+ Int2 *big.Int
+ }{},
+ err: "abi: purely underscored output cannot unpack to struct",
+ },
}
func TestUnpack(t *testing.T) {
@@ -638,3 +683,73 @@ func TestUnmarshal(t *testing.T) {
t.Fatal("expected error:", err)
}
}
+
+func TestOOMMaliciousInput(t *testing.T) {
+ oomTests := []unpackTest{
+ {
+ def: `[{"type": "uint8[]"}]`,
+ enc: "0000000000000000000000000000000000000000000000000000000000000020" + // offset
+ "0000000000000000000000000000000000000000000000000000000000000003" + // num elems
+ "0000000000000000000000000000000000000000000000000000000000000001" + // elem 1
+ "0000000000000000000000000000000000000000000000000000000000000002", // elem 2
+ },
+ { // Length larger than 64 bits
+ def: `[{"type": "uint8[]"}]`,
+ enc: "0000000000000000000000000000000000000000000000000000000000000020" + // offset
+ "00ffffffffffffffffffffffffffffffffffffffffffffff0000000000000002" + // num elems
+ "0000000000000000000000000000000000000000000000000000000000000001" + // elem 1
+ "0000000000000000000000000000000000000000000000000000000000000002", // elem 2
+ },
+ { // Offset very large (over 64 bits)
+ def: `[{"type": "uint8[]"}]`,
+ enc: "00ffffffffffffffffffffffffffffffffffffffffffffff0000000000000020" + // offset
+ "0000000000000000000000000000000000000000000000000000000000000002" + // num elems
+ "0000000000000000000000000000000000000000000000000000000000000001" + // elem 1
+ "0000000000000000000000000000000000000000000000000000000000000002", // elem 2
+ },
+ { // Offset very large (below 64 bits)
+ def: `[{"type": "uint8[]"}]`,
+ enc: "0000000000000000000000000000000000000000000000007ffffffffff00020" + // offset
+ "0000000000000000000000000000000000000000000000000000000000000002" + // num elems
+ "0000000000000000000000000000000000000000000000000000000000000001" + // elem 1
+ "0000000000000000000000000000000000000000000000000000000000000002", // elem 2
+ },
+ { // Offset negative (as 64 bit)
+ def: `[{"type": "uint8[]"}]`,
+ enc: "000000000000000000000000000000000000000000000000f000000000000020" + // offset
+ "0000000000000000000000000000000000000000000000000000000000000002" + // num elems
+ "0000000000000000000000000000000000000000000000000000000000000001" + // elem 1
+ "0000000000000000000000000000000000000000000000000000000000000002", // elem 2
+ },
+
+ { // Negative length
+ def: `[{"type": "uint8[]"}]`,
+ enc: "0000000000000000000000000000000000000000000000000000000000000020" + // offset
+ "000000000000000000000000000000000000000000000000f000000000000002" + // num elems
+ "0000000000000000000000000000000000000000000000000000000000000001" + // elem 1
+ "0000000000000000000000000000000000000000000000000000000000000002", // elem 2
+ },
+ { // Very large length
+ def: `[{"type": "uint8[]"}]`,
+ enc: "0000000000000000000000000000000000000000000000000000000000000020" + // offset
+ "0000000000000000000000000000000000000000000000007fffffffff000002" + // num elems
+ "0000000000000000000000000000000000000000000000000000000000000001" + // elem 1
+ "0000000000000000000000000000000000000000000000000000000000000002", // elem 2
+ },
+ }
+ for i, test := range oomTests {
+ def := fmt.Sprintf(`[{ "name" : "method", "outputs": %s}]`, test.def)
+ abi, err := JSON(strings.NewReader(def))
+ if err != nil {
+ t.Fatalf("invalid ABI definition %s: %v", def, err)
+ }
+ encb, err := hex.DecodeString(test.enc)
+ if err != nil {
+ t.Fatalf("invalid hex: %s" + test.enc)
+ }
+ _, err = abi.Methods["method"].Outputs.UnpackValues(encb)
+ if err == nil {
+ t.Fatalf("Expected error on malicious input, test %d", i)
+ }
+ }
+}
diff --git a/accounts/errors.go b/accounts/errors.go
index 64da8821c..40b21ed17 100644
--- a/accounts/errors.go
+++ b/accounts/errors.go
@@ -62,7 +62,7 @@ func NewAuthNeededError(needed string) error {
}
}
-// Error implements the standard error interfacel.
+// Error implements the standard error interface.
func (err *AuthNeededError) Error() string {
return fmt.Sprintf("authentication needed: %s", err.Needed)
}
diff --git a/accounts/usbwallet/internal/trezor/messages.proto b/accounts/usbwallet/internal/trezor/messages.proto
index 178956457..8cb9c8cc2 100644
--- a/accounts/usbwallet/internal/trezor/messages.proto
+++ b/accounts/usbwallet/internal/trezor/messages.proto
@@ -2,6 +2,8 @@
// https://github.com/trezor/trezor-common/blob/master/protob/messages.proto
// dated 28.07.2017, commit dd8ec3231fb5f7992360aff9bdfe30bb58130f4b.
+syntax = "proto2";
+
/**
* Messages for TREZOR communication
*/
diff --git a/accounts/usbwallet/internal/trezor/trezor.go b/accounts/usbwallet/internal/trezor/trezor.go
index 487aeb5f8..8ae9e726e 100644
--- a/accounts/usbwallet/internal/trezor/trezor.go
+++ b/accounts/usbwallet/internal/trezor/trezor.go
@@ -18,7 +18,7 @@
// wallets. The wire protocol spec can be found on the SatoshiLabs website:
// https://doc.satoshilabs.com/trezor-tech/api-protobuf.html
-//go:generate protoc --go_out=Mgoogle/protobuf/descriptor.proto=github.com/golang/protobuf/protoc-gen-go/descriptor,import_path=trezor:. types.proto messages.proto
+//go:generate protoc --go_out=import_path=trezor:. types.proto messages.proto
// Package trezor contains the wire protocol wrapper in Go.
package trezor
diff --git a/accounts/usbwallet/internal/trezor/types.proto b/accounts/usbwallet/internal/trezor/types.proto
index 3a358a584..acbe79e3f 100644
--- a/accounts/usbwallet/internal/trezor/types.proto
+++ b/accounts/usbwallet/internal/trezor/types.proto
@@ -2,6 +2,8 @@
// https://github.com/trezor/trezor-common/blob/master/protob/types.proto
// dated 28.07.2017, commit dd8ec3231fb5f7992360aff9bdfe30bb58130f4b.
+syntax = "proto2";
+
/**
* Types for TREZOR communication
*
diff --git a/accounts/usbwallet/trezor.go b/accounts/usbwallet/trezor.go
index 159cb2ea9..b84a95599 100644
--- a/accounts/usbwallet/trezor.go
+++ b/accounts/usbwallet/trezor.go
@@ -180,7 +180,7 @@ func (w *trezorDriver) trezorSign(derivationPath []uint32, tx *types.Transaction
AddressN: derivationPath,
Nonce: new(big.Int).SetUint64(tx.Nonce()).Bytes(),
GasPrice: tx.GasPrice().Bytes(),
- GasLimit: tx.Gas().Bytes(),
+ GasLimit: new(big.Int).SetUint64(tx.Gas()).Bytes(),
Value: tx.Value().Bytes(),
DataLength: &length,
}
diff --git a/build/ci.go b/build/ci.go
index 987f0bb18..544483c42 100644
--- a/build/ci.go
+++ b/build/ci.go
@@ -23,7 +23,7 @@ Usage: go run build/ci.go <command> <command flags/arguments>
Available commands are:
- install [ -arch architecture ] [ packages... ] -- builds packages and executables
+ install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables
test [ -coverage ] [ packages... ] -- runs the tests
lint -- runs certain pre-selected linters
archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -upload dest ] -- archives build artefacts
@@ -121,7 +121,8 @@ var (
// Note: vivid is unsupported because there is no golang-1.6 package for it.
// Note: wily is unsupported because it was officially deprecated on lanchpad.
// Note: yakkety is unsupported because it was officially deprecated on lanchpad.
- debDistros = []string{"trusty", "xenial", "zesty", "artful"}
+ // Note: zesty is unsupported because it was officially deprecated on lanchpad.
+ debDistros = []string{"trusty", "xenial", "artful", "bionic"}
)
var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin"))
@@ -173,17 +174,24 @@ func main() {
func doInstall(cmdline []string) {
var (
arch = flag.String("arch", "", "Architecture to cross build for")
+ cc = flag.String("cc", "", "C compiler to cross build with")
)
flag.CommandLine.Parse(cmdline)
env := build.Env()
// Check Go version. People regularly open issues about compilation
// failure with outdated Go. This should save them the trouble.
- if runtime.Version() < "go1.7" && !strings.Contains(runtime.Version(), "devel") {
- log.Println("You have Go version", runtime.Version())
- log.Println("go-ethereum requires at least Go version 1.7 and cannot")
- log.Println("be compiled with an earlier version. Please upgrade your Go installation.")
- os.Exit(1)
+ if !strings.Contains(runtime.Version(), "devel") {
+ // Figure out the minor version number since we can't textually compare (1.10 < 1.7)
+ var minor int
+ fmt.Sscanf(strings.TrimPrefix(runtime.Version(), "go1."), "%d", &minor)
+
+ if minor < 7 {
+ log.Println("You have Go version", runtime.Version())
+ log.Println("go-ethereum requires at least Go version 1.7 and cannot")
+ log.Println("be compiled with an earlier version. Please upgrade your Go installation.")
+ os.Exit(1)
+ }
}
// Compile packages given as arguments, or everything if there are no arguments.
packages := []string{"./..."}
@@ -207,7 +215,7 @@ func doInstall(cmdline []string) {
}
}
// Seems we are cross compiling, work around forbidden GOBIN
- goinstall := goToolArch(*arch, "install", buildFlags(env)...)
+ goinstall := goToolArch(*arch, *cc, "install", buildFlags(env)...)
goinstall.Args = append(goinstall.Args, "-v")
goinstall.Args = append(goinstall.Args, []string{"-buildmode", "archive"}...)
goinstall.Args = append(goinstall.Args, packages...)
@@ -221,7 +229,7 @@ func doInstall(cmdline []string) {
}
for name := range pkgs {
if name == "main" {
- gobuild := goToolArch(*arch, "build", buildFlags(env)...)
+ gobuild := goToolArch(*arch, *cc, "build", buildFlags(env)...)
gobuild.Args = append(gobuild.Args, "-v")
gobuild.Args = append(gobuild.Args, []string{"-o", executablePath(cmd.Name())}...)
gobuild.Args = append(gobuild.Args, "."+string(filepath.Separator)+filepath.Join("cmd", cmd.Name()))
@@ -249,15 +257,18 @@ func buildFlags(env build.Environment) (flags []string) {
}
func goTool(subcmd string, args ...string) *exec.Cmd {
- return goToolArch(runtime.GOARCH, subcmd, args...)
+ return goToolArch(runtime.GOARCH, os.Getenv("CC"), subcmd, args...)
}
-func goToolArch(arch string, subcmd string, args ...string) *exec.Cmd {
+func goToolArch(arch string, cc string, subcmd string, args ...string) *exec.Cmd {
cmd := build.GoTool(subcmd, args...)
if subcmd == "build" || subcmd == "install" || subcmd == "test" {
// Go CGO has a Windows linker error prior to 1.8 (https://github.com/golang/go/issues/8756).
// Work around issue by allowing multiple definitions for <1.8 builds.
- if runtime.GOOS == "windows" && runtime.Version() < "go1.8" {
+ var minor int
+ fmt.Sscanf(strings.TrimPrefix(runtime.Version(), "go1."), "%d", &minor)
+
+ if runtime.GOOS == "windows" && minor < 8 {
cmd.Args = append(cmd.Args, []string{"-ldflags", "-extldflags -Wl,--allow-multiple-definition"}...)
}
}
@@ -268,6 +279,9 @@ func goToolArch(arch string, subcmd string, args ...string) *exec.Cmd {
cmd.Env = append(cmd.Env, "CGO_ENABLED=1")
cmd.Env = append(cmd.Env, "GOARCH="+arch)
}
+ if cc != "" {
+ cmd.Env = append(cmd.Env, "CC="+cc)
+ }
for _, e := range os.Environ() {
if strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "GOBIN=") {
continue
diff --git a/build/update-license.go b/build/update-license.go
index 3d69598b7..22e403342 100644
--- a/build/update-license.go
+++ b/build/update-license.go
@@ -55,10 +55,9 @@ var (
"crypto/sha3/",
"internal/jsre/deps",
"log/",
+ "common/bitutil/bitutil",
// don't license generated files
- "contracts/chequebook/contract/",
- "contracts/ens/contract/",
- "contracts/release/contract.go",
+ "contracts/chequebook/contract/code.go",
}
// paths with this prefix are licensed as GPL. all other files are LGPL.
diff --git a/cmd/bootnode/main.go b/cmd/bootnode/main.go
index e1734d89a..2e93cc04d 100644
--- a/cmd/bootnode/main.go
+++ b/cmd/bootnode/main.go
@@ -21,6 +21,7 @@ import (
"crypto/ecdsa"
"flag"
"fmt"
+ "net"
"os"
"github.com/ethereum/go-ethereum/cmd/utils"
@@ -96,12 +97,37 @@ func main() {
}
}
+ addr, err := net.ResolveUDPAddr("udp", *listenAddr)
+ if err != nil {
+ utils.Fatalf("-ResolveUDPAddr: %v", err)
+ }
+ conn, err := net.ListenUDP("udp", addr)
+ if err != nil {
+ utils.Fatalf("-ListenUDP: %v", err)
+ }
+
+ realaddr := conn.LocalAddr().(*net.UDPAddr)
+ if natm != nil {
+ if !realaddr.IP.IsLoopback() {
+ go nat.Map(natm, nil, "udp", realaddr.Port, realaddr.Port, "ethereum discovery")
+ }
+ // TODO: react to external IP changes over time.
+ if ext, err := natm.ExternalIP(); err == nil {
+ realaddr = &net.UDPAddr{IP: ext, Port: realaddr.Port}
+ }
+ }
+
if *runv5 {
- if _, err := discv5.ListenUDP(nodeKey, *listenAddr, natm, "", restrictList); err != nil {
+ if _, err := discv5.ListenUDP(nodeKey, conn, realaddr, "", restrictList); err != nil {
utils.Fatalf("%v", err)
}
} else {
- if _, err := discover.ListenUDP(nodeKey, *listenAddr, natm, "", restrictList); err != nil {
+ cfg := discover.Config{
+ PrivateKey: nodeKey,
+ AnnounceAddr: realaddr,
+ NetRestrict: restrictList,
+ }
+ if _, err := discover.ListenUDP(conn, cfg); err != nil {
utils.Fatalf("%v", err)
}
}
diff --git a/cmd/ethkey/generate.go b/cmd/ethkey/generate.go
index dee0e9d70..6d57d17fb 100644
--- a/cmd/ethkey/generate.go
+++ b/cmd/ethkey/generate.go
@@ -1,8 +1,23 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+
package main
import (
"crypto/ecdsa"
- "crypto/rand"
"fmt"
"io/ioutil"
"os"
@@ -26,16 +41,16 @@ var commandGenerate = cli.Command{
ArgsUsage: "[ <keyfile> ]",
Description: `
Generate a new keyfile.
-If you want to use an existing private key to use in the keyfile, it can be
-specified by setting --privatekey with the location of the file containing the
-private key.`,
+
+If you want to encrypt an existing private key, it can be specified by setting
+--privatekey with the location of the file containing the private key.
+`,
Flags: []cli.Flag{
passphraseFlag,
jsonFlag,
cli.StringFlag{
- Name: "privatekey",
- Usage: "the file from where to read the private key to " +
- "generate a keyfile for",
+ Name: "privatekey",
+ Usage: "file containing a raw private key to encrypt",
},
},
Action: func(ctx *cli.Context) error {
@@ -51,32 +66,19 @@ private key.`,
}
var privateKey *ecdsa.PrivateKey
-
- // First check if a private key file is provided.
- privateKeyFile := ctx.String("privatekey")
- if privateKeyFile != "" {
- privateKeyBytes, err := ioutil.ReadFile(privateKeyFile)
+ var err error
+ if file := ctx.String("privatekey"); file != "" {
+ // Load private key from file.
+ privateKey, err = crypto.LoadECDSA(file)
if err != nil {
- utils.Fatalf("Failed to read the private key file '%s': %v",
- privateKeyFile, err)
+ utils.Fatalf("Can't load private key: %v", err)
}
-
- pk, err := crypto.HexToECDSA(string(privateKeyBytes))
- if err != nil {
- utils.Fatalf(
- "Could not construct ECDSA private key from file content: %v",
- err)
- }
- privateKey = pk
- }
-
- // If not loaded, generate random.
- if privateKey == nil {
- pk, err := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
+ } else {
+ // If not loaded, generate random.
+ privateKey, err = crypto.GenerateKey()
if err != nil {
utils.Fatalf("Failed to generate random private key: %v", err)
}
- privateKey = pk
}
// Create the keyfile object with a random UUID.
@@ -89,8 +91,7 @@ private key.`,
// Encrypt key with passphrase.
passphrase := getPassPhrase(ctx, true)
- keyjson, err := keystore.EncryptKey(key, passphrase,
- keystore.StandardScryptN, keystore.StandardScryptP)
+ keyjson, err := keystore.EncryptKey(key, passphrase, keystore.StandardScryptN, keystore.StandardScryptP)
if err != nil {
utils.Fatalf("Error encrypting key: %v", err)
}
@@ -110,7 +111,7 @@ private key.`,
if ctx.Bool(jsonFlag.Name) {
mustPrintJSON(out)
} else {
- fmt.Println("Address: ", out.Address)
+ fmt.Println("Address:", out.Address)
}
return nil
},
diff --git a/cmd/ethkey/inspect.go b/cmd/ethkey/inspect.go
index 8a7aeef84..dbf5afc0c 100644
--- a/cmd/ethkey/inspect.go
+++ b/cmd/ethkey/inspect.go
@@ -1,3 +1,19 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+
package main
import (
@@ -23,6 +39,7 @@ var commandInspect = cli.Command{
ArgsUsage: "<keyfile>",
Description: `
Print various information about the keyfile.
+
Private key information can be printed by using the --private flag;
make sure to use this feature with great caution!`,
Flags: []cli.Flag{
diff --git a/cmd/ethkey/main.go b/cmd/ethkey/main.go
index b9b7a18e0..2a9e5ee48 100644
--- a/cmd/ethkey/main.go
+++ b/cmd/ethkey/main.go
@@ -28,40 +28,37 @@ const (
defaultKeyfileName = "keyfile.json"
)
-var (
- gitCommit = "" // Git SHA1 commit hash of the release (set via linker flags)
+// Git SHA1 commit hash of the release (set via linker flags)
+var gitCommit = ""
- app *cli.App // the main app instance
-)
+var app *cli.App
-var ( // Commonly used command line flags.
+func init() {
+ app = utils.NewApp(gitCommit, "an Ethereum key manager")
+ app.Commands = []cli.Command{
+ commandGenerate,
+ commandInspect,
+ commandSignMessage,
+ commandVerifyMessage,
+ }
+}
+
+// Commonly used command line flags.
+var (
passphraseFlag = cli.StringFlag{
Name: "passwordfile",
Usage: "the file that contains the passphrase for the keyfile",
}
-
jsonFlag = cli.BoolFlag{
Name: "json",
Usage: "output JSON instead of human-readable format",
}
-
messageFlag = cli.StringFlag{
Name: "message",
Usage: "the file that contains the message to sign/verify",
}
)
-// Configure the app instance.
-func init() {
- app = utils.NewApp(gitCommit, "an Ethereum key manager")
- app.Commands = []cli.Command{
- commandGenerate,
- commandInspect,
- commandSignMessage,
- commandVerifyMessage,
- }
-}
-
func main() {
if err := app.Run(os.Args); err != nil {
fmt.Fprintln(os.Stderr, err)
diff --git a/cmd/ethkey/message.go b/cmd/ethkey/message.go
index ae6b6552d..531a931c8 100644
--- a/cmd/ethkey/message.go
+++ b/cmd/ethkey/message.go
@@ -1,11 +1,25 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+
package main
import (
"encoding/hex"
"fmt"
"io/ioutil"
- "os"
- "strings"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/cmd/utils"
@@ -18,26 +32,33 @@ type outputSign struct {
Signature string
}
+var msgfileFlag = cli.StringFlag{
+ Name: "msgfile",
+ Usage: "file containing the message to sign/verify",
+}
+
var commandSignMessage = cli.Command{
Name: "signmessage",
Usage: "sign a message",
- ArgsUsage: "<keyfile> <message/file>",
+ ArgsUsage: "<keyfile> <message>",
Description: `
Sign the message with a keyfile.
-It is possible to refer to a file containing the message.`,
+
+To sign a message contained in a file, use the --msgfile flag.
+`,
Flags: []cli.Flag{
passphraseFlag,
jsonFlag,
+ msgfileFlag,
},
Action: func(ctx *cli.Context) error {
- keyfilepath := ctx.Args().First()
- message := []byte(ctx.Args().Get(1))
+ message := getMessage(ctx, 1)
// Load the keyfile.
+ keyfilepath := ctx.Args().First()
keyjson, err := ioutil.ReadFile(keyfilepath)
if err != nil {
- utils.Fatalf("Failed to read the keyfile at '%s': %v",
- keyfilepath, err)
+ utils.Fatalf("Failed to read the keyfile at '%s': %v", keyfilepath, err)
}
// Decrypt key with passphrase.
@@ -47,29 +68,15 @@ It is possible to refer to a file containing the message.`,
utils.Fatalf("Error decrypting key: %v", err)
}
- if len(message) == 0 {
- utils.Fatalf("A message must be provided")
- }
- // Read message if file.
- if _, err := os.Stat(string(message)); err == nil {
- message, err = ioutil.ReadFile(string(message))
- if err != nil {
- utils.Fatalf("Failed to read the message file: %v", err)
- }
- }
-
signature, err := crypto.Sign(signHash(message), key.PrivateKey)
if err != nil {
utils.Fatalf("Failed to sign message: %v", err)
}
-
- out := outputSign{
- Signature: hex.EncodeToString(signature),
- }
+ out := outputSign{Signature: hex.EncodeToString(signature)}
if ctx.Bool(jsonFlag.Name) {
mustPrintJSON(out)
} else {
- fmt.Println("Signature: ", out.Signature)
+ fmt.Println("Signature:", out.Signature)
}
return nil
},
@@ -84,53 +91,40 @@ type outputVerify struct {
var commandVerifyMessage = cli.Command{
Name: "verifymessage",
Usage: "verify the signature of a signed message",
- ArgsUsage: "<address> <signature> <message/file>",
+ ArgsUsage: "<address> <signature> <message>",
Description: `
Verify the signature of the message.
It is possible to refer to a file containing the message.`,
Flags: []cli.Flag{
jsonFlag,
+ msgfileFlag,
},
Action: func(ctx *cli.Context) error {
addressStr := ctx.Args().First()
signatureHex := ctx.Args().Get(1)
- message := []byte(ctx.Args().Get(2))
+ message := getMessage(ctx, 2)
- // Determine whether it is a keyfile, public key or address.
if !common.IsHexAddress(addressStr) {
utils.Fatalf("Invalid address: %s", addressStr)
}
address := common.HexToAddress(addressStr)
-
signature, err := hex.DecodeString(signatureHex)
if err != nil {
utils.Fatalf("Signature encoding is not hexadecimal: %v", err)
}
- if len(message) == 0 {
- utils.Fatalf("A message must be provided")
- }
- // Read message if file.
- if _, err := os.Stat(string(message)); err == nil {
- message, err = ioutil.ReadFile(string(message))
- if err != nil {
- utils.Fatalf("Failed to read the message file: %v", err)
- }
- }
-
recoveredPubkey, err := crypto.SigToPub(signHash(message), signature)
if err != nil || recoveredPubkey == nil {
utils.Fatalf("Signature verification failed: %v", err)
}
recoveredPubkeyBytes := crypto.FromECDSAPub(recoveredPubkey)
recoveredAddress := crypto.PubkeyToAddress(*recoveredPubkey)
-
success := address == recoveredAddress
out := outputVerify{
Success: success,
RecoveredPublicKey: hex.EncodeToString(recoveredPubkeyBytes),
- RecoveredAddress: strings.ToLower(recoveredAddress.Hex()),
+ RecoveredAddress: recoveredAddress.Hex(),
}
if ctx.Bool(jsonFlag.Name) {
mustPrintJSON(out)
@@ -140,9 +134,26 @@ It is possible to refer to a file containing the message.`,
} else {
fmt.Println("Signature verification failed!")
}
- fmt.Println("Recovered public key: ", out.RecoveredPublicKey)
- fmt.Println("Recovered address: ", out.RecoveredAddress)
+ fmt.Println("Recovered public key:", out.RecoveredPublicKey)
+ fmt.Println("Recovered address:", out.RecoveredAddress)
}
return nil
},
}
+
+func getMessage(ctx *cli.Context, msgarg int) []byte {
+ if file := ctx.String("msgfile"); file != "" {
+ if len(ctx.Args()) > msgarg {
+ utils.Fatalf("Can't use --msgfile and message argument at the same time.")
+ }
+ msg, err := ioutil.ReadFile(file)
+ if err != nil {
+ utils.Fatalf("Can't read message file: %v", err)
+ }
+ return msg
+ } else if len(ctx.Args()) == msgarg+1 {
+ return []byte(ctx.Args().Get(msgarg))
+ }
+ utils.Fatalf("Invalid number of arguments: want %d, got %d", msgarg+1, len(ctx.Args()))
+ return nil
+}
diff --git a/cmd/ethkey/message_test.go b/cmd/ethkey/message_test.go
new file mode 100644
index 000000000..39352b1d2
--- /dev/null
+++ b/cmd/ethkey/message_test.go
@@ -0,0 +1,70 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+
+package main
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "testing"
+)
+
+func TestMessageSignVerify(t *testing.T) {
+ tmpdir, err := ioutil.TempDir("", "ethkey-test")
+ if err != nil {
+ t.Fatal("Can't create temporary directory:", err)
+ }
+ defer os.RemoveAll(tmpdir)
+
+ keyfile := filepath.Join(tmpdir, "the-keyfile")
+ message := "test message"
+
+ // Create the key.
+ generate := runEthkey(t, "generate", keyfile)
+ generate.Expect(`
+!! Unsupported terminal, password will be echoed.
+Passphrase: {{.InputLine "foobar"}}
+Repeat passphrase: {{.InputLine "foobar"}}
+`)
+ _, matches := generate.ExpectRegexp(`Address: (0x[0-9a-fA-F]{40})\n`)
+ address := matches[1]
+ generate.ExpectExit()
+
+ // Sign a message.
+ sign := runEthkey(t, "signmessage", keyfile, message)
+ sign.Expect(`
+!! Unsupported terminal, password will be echoed.
+Passphrase: {{.InputLine "foobar"}}
+`)
+ _, matches = sign.ExpectRegexp(`Signature: ([0-9a-f]+)\n`)
+ signature := matches[1]
+ sign.ExpectExit()
+
+ // Verify the message.
+ verify := runEthkey(t, "verifymessage", address, signature, message)
+ _, matches = verify.ExpectRegexp(`
+Signature verification successful!
+Recovered public key: [0-9a-f]+
+Recovered address: (0x[0-9a-fA-F]{40})
+`)
+ recovered := matches[1]
+ verify.ExpectExit()
+
+ if recovered != address {
+ t.Error("recovered address doesn't match generated key")
+ }
+}
diff --git a/cmd/ethkey/run_test.go b/cmd/ethkey/run_test.go
new file mode 100644
index 000000000..6006f6b5b
--- /dev/null
+++ b/cmd/ethkey/run_test.go
@@ -0,0 +1,54 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "testing"
+
+ "github.com/docker/docker/pkg/reexec"
+ "github.com/ethereum/go-ethereum/internal/cmdtest"
+)
+
+type testEthkey struct {
+ *cmdtest.TestCmd
+}
+
+// spawns ethkey with the given command line args.
+func runEthkey(t *testing.T, args ...string) *testEthkey {
+ tt := new(testEthkey)
+ tt.TestCmd = cmdtest.NewTestCmd(t, tt)
+ tt.Run("ethkey-test", args...)
+ return tt
+}
+
+func TestMain(m *testing.M) {
+ // Run the app if we've been exec'd as "ethkey-test" in runEthkey.
+ reexec.Register("ethkey-test", func() {
+ if err := app.Run(os.Args); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ os.Exit(0)
+ })
+ // check if we have been reexec'd
+ if reexec.Init() {
+ return
+ }
+ os.Exit(m.Run())
+}
diff --git a/cmd/evm/json_logger.go b/cmd/evm/json_logger.go
index 47daf7dbb..0e7a91189 100644
--- a/cmd/evm/json_logger.go
+++ b/cmd/evm/json_logger.go
@@ -1,18 +1,18 @@
// Copyright 2017 The go-ethereum Authors
-// This file is part of the go-ethereum library.
+// This file is part of go-ethereum.
//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
-// The go-ethereum library is distributed in the hope that it will be useful,
+// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
+// GNU General Public License for more details.
//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package main
diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go
index 96de0c76a..a9a2e5420 100644
--- a/cmd/evm/runner.go
+++ b/cmd/evm/runner.go
@@ -96,7 +96,9 @@ func runCmd(ctx *cli.Context) error {
}
if ctx.GlobalString(GenesisFlag.Name) != "" {
gen := readGenesis(ctx.GlobalString(GenesisFlag.Name))
- _, statedb = gen.ToBlock()
+ db, _ := ethdb.NewMemDatabase()
+ genesis := gen.ToBlock(db)
+ statedb, _ = state.New(genesis.Root(), state.NewDatabase(db))
chainConfig = gen.Config
} else {
db, _ := ethdb.NewMemDatabase()
diff --git a/cmd/faucet/faucet.go b/cmd/faucet/faucet.go
index 75ec124c1..99527f9d1 100644
--- a/cmd/faucet/faucet.go
+++ b/cmd/faucet/faucet.go
@@ -18,6 +18,7 @@
package main
//go:generate go-bindata -nometadata -o website.go faucet.html
+//go:generate gofmt -w -s website.go
import (
"bytes"
@@ -222,7 +223,6 @@ func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network u
NoDiscovery: true,
DiscoveryV5: true,
ListenAddr: fmt.Sprintf(":%d", port),
- DiscoveryV5Addr: fmt.Sprintf(":%d", port+1),
MaxPeers: 25,
BootstrapNodesV5: enodes,
},
@@ -473,7 +473,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
amount = new(big.Int).Mul(amount, new(big.Int).Exp(big.NewInt(5), big.NewInt(int64(msg.Tier)), nil))
amount = new(big.Int).Div(amount, new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(msg.Tier)), nil))
- tx := types.NewTransaction(f.nonce+uint64(len(f.reqs)), address, amount, big.NewInt(21000), f.price, nil)
+ tx := types.NewTransaction(f.nonce+uint64(len(f.reqs)), address, amount, 21000, f.price, nil)
signed, err := f.keystore.SignTx(f.account, tx, f.config.ChainId)
if err != nil {
f.lock.Unlock()
diff --git a/cmd/faucet/website.go b/cmd/faucet/website.go
index 7936b158e..fab1d4346 100644
--- a/cmd/faucet/website.go
+++ b/cmd/faucet/website.go
@@ -1,7 +1,6 @@
-// Code generated by go-bindata.
+// Code generated by go-bindata. DO NOT EDIT.
// sources:
// faucet.html
-// DO NOT EDIT!
package main
@@ -92,8 +91,8 @@ func faucetHtml() (*asset, error) {
// It returns an error if the asset could not be found or
// could not be loaded.
func Asset(name string) ([]byte, error) {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- if f, ok := _bindata[cannonicalName]; ok {
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ if f, ok := _bindata[canonicalName]; ok {
a, err := f()
if err != nil {
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
@@ -118,8 +117,8 @@ func MustAsset(name string) []byte {
// It returns an error if the asset could not be found or
// could not be loaded.
func AssetInfo(name string) (os.FileInfo, error) {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- if f, ok := _bindata[cannonicalName]; ok {
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ if f, ok := _bindata[canonicalName]; ok {
a, err := f()
if err != nil {
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
@@ -159,8 +158,8 @@ var _bindata = map[string]func() (*asset, error){
func AssetDir(name string) ([]string, error) {
node := _bintree
if len(name) != 0 {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- pathList := strings.Split(cannonicalName, "/")
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ pathList := strings.Split(canonicalName, "/")
for _, p := range pathList {
node = node.Children[p]
if node == nil {
@@ -205,11 +204,7 @@ func RestoreAsset(dir, name string) error {
if err != nil {
return err
}
- err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
- if err != nil {
- return err
- }
- return nil
+ return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
}
// RestoreAssets restores an asset under the given directory recursively
@@ -230,6 +225,6 @@ func RestoreAssets(dir, name string) error {
}
func _filePath(dir, name string) string {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
}
diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go
index 4a9a7b11b..85d0c3aca 100644
--- a/cmd/geth/chaincmd.go
+++ b/cmd/geth/chaincmd.go
@@ -67,6 +67,9 @@ It expects the genesis file as argument.`,
utils.DataDirFlag,
utils.CacheFlag,
utils.LightModeFlag,
+ utils.GCModeFlag,
+ utils.CacheDatabaseFlag,
+ utils.CacheGCFlag,
},
Category: "BLOCKCHAIN COMMANDS",
Description: `
@@ -202,7 +205,7 @@ func importChain(ctx *cli.Context) error {
if len(ctx.Args()) == 1 {
if err := utils.ImportChain(chain, ctx.Args().First()); err != nil {
- utils.Fatalf("Import error: %v", err)
+ log.Error("Import error", "err", err)
}
} else {
for _, arg := range ctx.Args() {
@@ -211,7 +214,7 @@ func importChain(ctx *cli.Context) error {
}
}
}
-
+ chain.Stop()
fmt.Printf("Import done in %v.\n\n", time.Since(start))
// Output pre-compaction stats mostly to see the import trashing
diff --git a/cmd/geth/config.go b/cmd/geth/config.go
index 27490c404..50e4de2e7 100644
--- a/cmd/geth/config.go
+++ b/cmd/geth/config.go
@@ -18,7 +18,6 @@ package main
import (
"bufio"
- "encoding/hex"
"errors"
"fmt"
"io"
@@ -29,7 +28,6 @@ import (
cli "gopkg.in/urfave/cli.v1"
"github.com/ethereum/go-ethereum/cmd/utils"
- "github.com/ethereum/go-ethereum/contracts/release"
"github.com/ethereum/go-ethereum/dashboard"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/node"
@@ -158,7 +156,7 @@ func makeFullNode(ctx *cli.Context) *node.Node {
utils.RegisterEthService(stack, &cfg.Eth)
if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) {
- utils.RegisterDashboardService(stack, &cfg.Dashboard)
+ utils.RegisterDashboardService(stack, &cfg.Dashboard, gitCommit)
}
// Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode
shhEnabled := enableWhisper(ctx)
@@ -177,21 +175,6 @@ func makeFullNode(ctx *cli.Context) *node.Node {
if cfg.Ethstats.URL != "" {
utils.RegisterEthStatsService(stack, cfg.Ethstats.URL)
}
-
- // Add the release oracle service so it boots along with node.
- if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
- config := release.Config{
- Oracle: relOracle,
- Major: uint32(params.VersionMajor),
- Minor: uint32(params.VersionMinor),
- Patch: uint32(params.VersionPatch),
- }
- commit, _ := hex.DecodeString(gitCommit)
- copy(config.Commit[:], commit)
- return release.NewReleaseService(ctx, config)
- }); err != nil {
- utils.Fatalf("Failed to register the Geth release oracle service: %v", err)
- }
return stack
}
diff --git a/cmd/geth/consolecmd.go b/cmd/geth/consolecmd.go
index 9d5cc38a1..7eca4d59f 100644
--- a/cmd/geth/consolecmd.go
+++ b/cmd/geth/consolecmd.go
@@ -22,6 +22,7 @@ import (
"os/signal"
"path/filepath"
"strings"
+ "syscall"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/console"
@@ -207,7 +208,7 @@ func ephemeralConsole(ctx *cli.Context) error {
}
// Wait for pending callbacks, but stop for Ctrl-C.
abort := make(chan os.Signal, 1)
- signal.Notify(abort, os.Interrupt)
+ signal.Notify(abort, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-abort
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index bdb7fad62..a82e5c89c 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -85,10 +85,13 @@ var (
utils.FastSyncFlag,
utils.LightModeFlag,
utils.SyncModeFlag,
+ utils.GCModeFlag,
utils.LightServFlag,
utils.LightPeersFlag,
utils.LightKDFFlag,
utils.CacheFlag,
+ utils.CacheDatabaseFlag,
+ utils.CacheGCFlag,
utils.TrieCacheGenFlag,
utils.ListenPortFlag,
utils.MaxPeersFlag,
@@ -111,6 +114,7 @@ var (
utils.VMEnableDebugFlag,
utils.NetworkIdFlag,
utils.RPCCORSDomainFlag,
+ utils.RPCVirtualHostsFlag,
utils.EthStatsURLFlag,
utils.MetricsEnabledFlag,
utils.FakePoWFlag,
@@ -278,9 +282,12 @@ func startNode(ctx *cli.Context, stack *node.Node) {
// Start auxiliary services if enabled
if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) {
// Mining only makes sense if a full Ethereum node is running
+ if ctx.GlobalBool(utils.LightModeFlag.Name) || ctx.GlobalString(utils.SyncModeFlag.Name) == "light" {
+ utils.Fatalf("Light clients do not support mining")
+ }
var ethereum *eth.Ethereum
if err := stack.Service(&ethereum); err != nil {
- utils.Fatalf("ethereum service not running: %v", err)
+ utils.Fatalf("Ethereum service not running: %v", err)
}
// Use a reduced number of threads if requested
if threads := ctx.GlobalInt(utils.MinerThreadsFlag.Name); threads > 0 {
diff --git a/cmd/geth/misccmd.go b/cmd/geth/misccmd.go
index 2e68dcda3..aa9b1ee56 100644
--- a/cmd/geth/misccmd.go
+++ b/cmd/geth/misccmd.go
@@ -134,7 +134,6 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with geth. If not, see <http://www.gnu.org/licenses/>.
-`)
+along with geth. If not, see <http://www.gnu.org/licenses/>.`)
return nil
}
diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go
index a834d5b7a..a1558c233 100644
--- a/cmd/geth/usage.go
+++ b/cmd/geth/usage.go
@@ -22,10 +22,11 @@ import (
"io"
"sort"
+ "strings"
+
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/internal/debug"
"gopkg.in/urfave/cli.v1"
- "strings"
)
// AppHelpTemplate is the test template for the default, global app help topic.
@@ -74,6 +75,7 @@ var AppHelpFlagGroups = []flagGroup{
utils.TestnetFlag,
utils.RinkebyFlag,
utils.SyncModeFlag,
+ utils.GCModeFlag,
utils.EthStatsURLFlag,
utils.IdentityFlag,
utils.LightServFlag,
@@ -127,6 +129,8 @@ var AppHelpFlagGroups = []flagGroup{
Name: "PERFORMANCE TUNING",
Flags: []cli.Flag{
utils.CacheFlag,
+ utils.CacheDatabaseFlag,
+ utils.CacheGCFlag,
utils.TrieCacheGenFlag,
},
},
@@ -152,6 +156,7 @@ var AppHelpFlagGroups = []flagGroup{
utils.IPCDisabledFlag,
utils.IPCPathFlag,
utils.RPCCORSDomainFlag,
+ utils.RPCVirtualHostsFlag,
utils.JSpathFlag,
utils.ExecFlag,
utils.PreloadJSFlag,
diff --git a/cmd/p2psim/main.go b/cmd/p2psim/main.go
index 56b74d135..0c8ed038d 100644
--- a/cmd/p2psim/main.go
+++ b/cmd/p2psim/main.go
@@ -1,3 +1,19 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+
// p2psim provides a command-line client for a simulation HTTP API.
//
// Here is an example of creating a 2 node network with the first node
diff --git a/cmd/puppeth/genesis.go b/cmd/puppeth/genesis.go
index 5e36f7fce..f747f4739 100644
--- a/cmd/puppeth/genesis.go
+++ b/cmd/puppeth/genesis.go
@@ -44,7 +44,7 @@ type cppEthereumGenesisSpec struct {
MaximumExtraDataSize hexutil.Uint64 `json:"maximumExtraDataSize"`
MinGasLimit hexutil.Uint64 `json:"minGasLimit"`
MaxGasLimit hexutil.Uint64 `json:"maxGasLimit"`
- GasLimitBoundDivisor *hexutil.Big `json:"gasLimitBoundDivisor"`
+ GasLimitBoundDivisor hexutil.Uint64 `json:"gasLimitBoundDivisor"`
MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"`
DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"`
DurationLimit *hexutil.Big `json:"durationLimit"`
@@ -107,11 +107,11 @@ func newCppEthereumGenesisSpec(network string, genesis *core.Genesis) (*cppEther
spec.Params.ChainID = (hexutil.Uint64)(genesis.Config.ChainId.Uint64())
spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
- spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit.Uint64())
+ spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit)
spec.Params.MaxGasLimit = (hexutil.Uint64)(math.MaxUint64)
spec.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty)
spec.Params.DifficultyBoundDivisor = (*hexutil.Big)(params.DifficultyBoundDivisor)
- spec.Params.GasLimitBoundDivisor = (*hexutil.Big)(params.GasLimitBoundDivisor)
+ spec.Params.GasLimitBoundDivisor = (hexutil.Uint64)(params.GasLimitBoundDivisor)
spec.Params.DurationLimit = (*hexutil.Big)(params.DurationLimit)
spec.Params.BlockReward = (*hexutil.Big)(ethash.FrontierBlockReward)
@@ -168,26 +168,26 @@ type parityChainSpec struct {
Engine struct {
Ethash struct {
Params struct {
- MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"`
- DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"`
- GasLimitBoundDivisor *hexutil.Big `json:"gasLimitBoundDivisor"`
- DurationLimit *hexutil.Big `json:"durationLimit"`
- BlockReward *hexutil.Big `json:"blockReward"`
- HomesteadTransition uint64 `json:"homesteadTransition"`
- EIP150Transition uint64 `json:"eip150Transition"`
- EIP160Transition uint64 `json:"eip160Transition"`
- EIP161abcTransition uint64 `json:"eip161abcTransition"`
- EIP161dTransition uint64 `json:"eip161dTransition"`
- EIP649Reward *hexutil.Big `json:"eip649Reward"`
- EIP100bTransition uint64 `json:"eip100bTransition"`
- EIP649Transition uint64 `json:"eip649Transition"`
+ MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"`
+ DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"`
+ GasLimitBoundDivisor hexutil.Uint64 `json:"gasLimitBoundDivisor"`
+ DurationLimit *hexutil.Big `json:"durationLimit"`
+ BlockReward *hexutil.Big `json:"blockReward"`
+ HomesteadTransition uint64 `json:"homesteadTransition"`
+ EIP150Transition uint64 `json:"eip150Transition"`
+ EIP160Transition uint64 `json:"eip160Transition"`
+ EIP161abcTransition uint64 `json:"eip161abcTransition"`
+ EIP161dTransition uint64 `json:"eip161dTransition"`
+ EIP649Reward *hexutil.Big `json:"eip649Reward"`
+ EIP100bTransition uint64 `json:"eip100bTransition"`
+ EIP649Transition uint64 `json:"eip649Transition"`
} `json:"params"`
} `json:"Ethash"`
} `json:"engine"`
Params struct {
MaximumExtraDataSize hexutil.Uint64 `json:"maximumExtraDataSize"`
- MinGasLimit *hexutil.Big `json:"minGasLimit"`
+ MinGasLimit hexutil.Uint64 `json:"minGasLimit"`
NetworkID hexutil.Uint64 `json:"networkID"`
MaxCodeSize uint64 `json:"maxCodeSize"`
EIP155Transition uint64 `json:"eip155Transition"`
@@ -270,7 +270,7 @@ func newParityChainSpec(network string, genesis *core.Genesis, bootnodes []strin
}
spec.Engine.Ethash.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty)
spec.Engine.Ethash.Params.DifficultyBoundDivisor = (*hexutil.Big)(params.DifficultyBoundDivisor)
- spec.Engine.Ethash.Params.GasLimitBoundDivisor = (*hexutil.Big)(params.GasLimitBoundDivisor)
+ spec.Engine.Ethash.Params.GasLimitBoundDivisor = (hexutil.Uint64)(params.GasLimitBoundDivisor)
spec.Engine.Ethash.Params.DurationLimit = (*hexutil.Big)(params.DurationLimit)
spec.Engine.Ethash.Params.BlockReward = (*hexutil.Big)(ethash.FrontierBlockReward)
spec.Engine.Ethash.Params.HomesteadTransition = genesis.Config.HomesteadBlock.Uint64()
@@ -283,7 +283,7 @@ func newParityChainSpec(network string, genesis *core.Genesis, bootnodes []strin
spec.Engine.Ethash.Params.EIP649Transition = genesis.Config.ByzantiumBlock.Uint64()
spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
- spec.Params.MinGasLimit = (*hexutil.Big)(params.MinGasLimit)
+ spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit)
spec.Params.NetworkID = (hexutil.Uint64)(genesis.Config.ChainId.Uint64())
spec.Params.MaxCodeSize = params.MaxCodeSize
spec.Params.EIP155Transition = genesis.Config.EIP155Block.Uint64()
diff --git a/cmd/puppeth/module_dashboard.go b/cmd/puppeth/module_dashboard.go
index 1092c4c88..1cb2d4549 100644
--- a/cmd/puppeth/module_dashboard.go
+++ b/cmd/puppeth/module_dashboard.go
@@ -117,7 +117,7 @@ var dashboardContent = `
<br/>
<p>To run an archive node, download <a href="/{{.GethGenesis}}"><code>{{.GethGenesis}}</code></a> and start Geth with:
<pre>geth --datadir=$HOME/.{{.Network}} init {{.GethGenesis}}</pre>
- <pre>geth --networkid={{.NetworkID}} --datadir=$HOME/.{{.Network}} --cache=1024 --syncmode=full{{if .Ethstats}} --ethstats='{{.Ethstats}}'{{end}} --bootnodes={{.BootnodesFullFlat}}</pre>
+ <pre>geth --networkid={{.NetworkID}} --datadir=$HOME/.{{.Network}} --cache=1024 --syncmode=full{{if .Ethstats}} --ethstats='{{.Ethstats}}'{{end}} --bootnodes={{.BootnodesFlat}}</pre>
</p>
<br/>
<p>You can download Geth from <a href="https://geth.ethereum.org/downloads/" target="about:blank">https://geth.ethereum.org/downloads/</a>.</p>
@@ -136,7 +136,7 @@ var dashboardContent = `
<br/>
<p>To run a full node, download <a href="/{{.GethGenesis}}"><code>{{.GethGenesis}}</code></a> and start Geth with:
<pre>geth --datadir=$HOME/.{{.Network}} init {{.GethGenesis}}</pre>
- <pre>geth --networkid={{.NetworkID}} --datadir=$HOME/.{{.Network}} --cache=512{{if .Ethstats}} --ethstats='{{.Ethstats}}'{{end}} --bootnodes={{.BootnodesFullFlat}}</pre>
+ <pre>geth --networkid={{.NetworkID}} --datadir=$HOME/.{{.Network}} --cache=512{{if .Ethstats}} --ethstats='{{.Ethstats}}'{{end}} --bootnodes={{.BootnodesFlat}}</pre>
</p>
<br/>
<p>You can download Geth from <a href="https://geth.ethereum.org/downloads/" target="about:blank">https://geth.ethereum.org/downloads/</a>.</p>
@@ -158,7 +158,7 @@ var dashboardContent = `
<br/>
<p>To run a light node, download <a href="/{{.GethGenesis}}"><code>{{.GethGenesis}}</code></a> and start Geth with:
<pre>geth --datadir=$HOME/.{{.Network}} init {{.GethGenesis}}</pre>
- <pre>geth --networkid={{.NetworkID}} --datadir=$HOME/.{{.Network}} --syncmode=light{{if .Ethstats}} --ethstats='{{.Ethstats}}'{{end}} --bootnodes={{.BootnodesLightFlat}}</pre>
+ <pre>geth --networkid={{.NetworkID}} --datadir=$HOME/.{{.Network}} --syncmode=light{{if .Ethstats}} --ethstats='{{.Ethstats}}'{{end}} --bootnodes={{.BootnodesFlat}}</pre>
</p>
<br/>
<p>You can download Geth from <a href="https://geth.ethereum.org/downloads/" target="about:blank">https://geth.ethereum.org/downloads/</a>.</p>
@@ -177,7 +177,7 @@ var dashboardContent = `
<br/>
<p>To run an embedded node, download <a href="/{{.GethGenesis}}"><code>{{.GethGenesis}}</code></a> and start Geth with:
<pre>geth --datadir=$HOME/.{{.Network}} init {{.GethGenesis}}</pre>
- <pre>geth --networkid={{.NetworkID}} --datadir=$HOME/.{{.Network}} --cache=16 --ethash.cachesinmem=1 --syncmode=light{{if .Ethstats}} --ethstats='{{.Ethstats}}'{{end}} --bootnodes={{.BootnodesLightFlat}}</pre>
+ <pre>geth --networkid={{.NetworkID}} --datadir=$HOME/.{{.Network}} --cache=16 --ethash.cachesinmem=1 --syncmode=light{{if .Ethstats}} --ethstats='{{.Ethstats}}'{{end}} --bootnodes={{.BootnodesFlat}}</pre>
</p>
<br/>
<p>You can download Geth from <a href="https://geth.ethereum.org/downloads/" target="about:blank">https://geth.ethereum.org/downloads/</a>.</p>
@@ -208,7 +208,7 @@ var dashboardContent = `
<pre>geth --datadir=$HOME/.{{.Network}} init {{.GethGenesis}}</pre>
</p>
<p>With your local chain initialized, you can start the Ethereum Wallet:
- <pre>ethereumwallet --rpc $HOME/.{{.Network}}/geth.ipc --node-networkid={{.NetworkID}} --node-datadir=$HOME/.{{.Network}}{{if .Ethstats}} --node-ethstats='{{.Ethstats}}'{{end}} --node-bootnodes={{.BootnodesFullFlat}}</pre>
+ <pre>ethereumwallet --rpc $HOME/.{{.Network}}/geth.ipc --node-networkid={{.NetworkID}} --node-datadir=$HOME/.{{.Network}}{{if .Ethstats}} --node-ethstats='{{.Ethstats}}'{{end}} --node-bootnodes={{.BootnodesFlat}}</pre>
<p>
<br/>
<p>You can download the Ethereum Wallet from <a href="https://github.com/ethereum/mist/releases" target="about:blank">https://github.com/ethereum/mist/releases</a>.</p>
@@ -229,7 +229,7 @@ var dashboardContent = `
<pre>geth --datadir=$HOME/.{{.Network}} init {{.GethGenesis}}</pre>
</p>
<p>With your local chain initialized, you can start Mist:
- <pre>mist --rpc $HOME/.{{.Network}}/geth.ipc --node-networkid={{.NetworkID}} --node-datadir=$HOME/.{{.Network}}{{if .Ethstats}} --node-ethstats='{{.Ethstats}}'{{end}} --node-bootnodes={{.BootnodesFullFlat}}</pre>
+ <pre>mist --rpc $HOME/.{{.Network}}/geth.ipc --node-networkid={{.NetworkID}} --node-datadir=$HOME/.{{.Network}}{{if .Ethstats}} --node-ethstats='{{.Ethstats}}'{{end}} --node-bootnodes={{.BootnodesFlat}}</pre>
<p>
<br/>
<p>You can download the Mist browser from <a href="https://github.com/ethereum/mist/releases" target="about:blank">https://github.com/ethereum/mist/releases</a>.</p>
@@ -261,7 +261,7 @@ var dashboardContent = `
<p>Inside your Java code you can now import the geth archive and connect to Ethereum:
<pre>import org.ethereum.geth.*;</pre>
<pre>
-Enodes bootnodes = new Enodes();{{range .BootnodesLight}}
+Enodes bootnodes = new Enodes();{{range .Bootnodes}}
bootnodes.append(new Enode("{{.}}"));{{end}}
NodeConfig config = new NodeConfig();
@@ -294,7 +294,7 @@ node.start();
<pre>
var error: NSError?
-let bootnodes = GethNewEnodesEmpty(){{range .BootnodesLight}}
+let bootnodes = GethNewEnodesEmpty(){{range .Bootnodes}}
bootnodes?.append(GethNewEnode("{{.}}", &error)){{end}}
let config = GethNewNodeConfig()
@@ -595,44 +595,42 @@ func deployDashboard(client *sshClient, network string, conf *config, config *da
statsLogin = ""
}
indexfile := new(bytes.Buffer)
- bootCpp := make([]string, len(conf.bootFull))
- for i, boot := range conf.bootFull {
+ bootCpp := make([]string, len(conf.bootnodes))
+ for i, boot := range conf.bootnodes {
bootCpp[i] = "required:" + strings.TrimPrefix(boot, "enode://")
}
- bootHarmony := make([]string, len(conf.bootFull))
- for i, boot := range conf.bootFull {
+ bootHarmony := make([]string, len(conf.bootnodes))
+ for i, boot := range conf.bootnodes {
bootHarmony[i] = fmt.Sprintf("-Dpeer.active.%d.url=%s", i, boot)
}
- bootPython := make([]string, len(conf.bootFull))
- for i, boot := range conf.bootFull {
+ bootPython := make([]string, len(conf.bootnodes))
+ for i, boot := range conf.bootnodes {
bootPython[i] = "'" + boot + "'"
}
template.Must(template.New("").Parse(dashboardContent)).Execute(indexfile, map[string]interface{}{
- "Network": network,
- "NetworkID": conf.Genesis.Config.ChainId,
- "NetworkTitle": strings.Title(network),
- "EthstatsPage": config.ethstats,
- "ExplorerPage": config.explorer,
- "WalletPage": config.wallet,
- "FaucetPage": config.faucet,
- "GethGenesis": network + ".json",
- "BootnodesFull": conf.bootFull,
- "BootnodesLight": conf.bootLight,
- "BootnodesFullFlat": strings.Join(conf.bootFull, ","),
- "BootnodesLightFlat": strings.Join(conf.bootLight, ","),
- "Ethstats": statsLogin,
- "Ethash": conf.Genesis.Config.Ethash != nil,
- "CppGenesis": network + "-cpp.json",
- "CppBootnodes": strings.Join(bootCpp, " "),
- "HarmonyGenesis": network + "-harmony.json",
- "HarmonyBootnodes": strings.Join(bootHarmony, " "),
- "ParityGenesis": network + "-parity.json",
- "PythonGenesis": network + "-python.json",
- "PythonBootnodes": strings.Join(bootPython, ","),
- "Homestead": conf.Genesis.Config.HomesteadBlock,
- "Tangerine": conf.Genesis.Config.EIP150Block,
- "Spurious": conf.Genesis.Config.EIP155Block,
- "Byzantium": conf.Genesis.Config.ByzantiumBlock,
+ "Network": network,
+ "NetworkID": conf.Genesis.Config.ChainId,
+ "NetworkTitle": strings.Title(network),
+ "EthstatsPage": config.ethstats,
+ "ExplorerPage": config.explorer,
+ "WalletPage": config.wallet,
+ "FaucetPage": config.faucet,
+ "GethGenesis": network + ".json",
+ "Bootnodes": conf.bootnodes,
+ "BootnodesFlat": strings.Join(conf.bootnodes, ","),
+ "Ethstats": statsLogin,
+ "Ethash": conf.Genesis.Config.Ethash != nil,
+ "CppGenesis": network + "-cpp.json",
+ "CppBootnodes": strings.Join(bootCpp, " "),
+ "HarmonyGenesis": network + "-harmony.json",
+ "HarmonyBootnodes": strings.Join(bootHarmony, " "),
+ "ParityGenesis": network + "-parity.json",
+ "PythonGenesis": network + "-python.json",
+ "PythonBootnodes": strings.Join(bootPython, ","),
+ "Homestead": conf.Genesis.Config.HomesteadBlock,
+ "Tangerine": conf.Genesis.Config.EIP150Block,
+ "Spurious": conf.Genesis.Config.EIP155Block,
+ "Byzantium": conf.Genesis.Config.ByzantiumBlock,
})
files[filepath.Join(workdir, "index.html")] = indexfile.Bytes()
@@ -651,7 +649,7 @@ func deployDashboard(client *sshClient, network string, conf *config, config *da
harmonySpecJSON, _ := conf.Genesis.MarshalJSON()
files[filepath.Join(workdir, network+"-harmony.json")] = harmonySpecJSON
- paritySpec, err := newParityChainSpec(network, conf.Genesis, conf.bootFull)
+ paritySpec, err := newParityChainSpec(network, conf.Genesis, conf.bootnodes)
if err != nil {
return nil, err
}
diff --git a/cmd/puppeth/module_faucet.go b/cmd/puppeth/module_faucet.go
index 92b4cb286..976bf04d0 100644
--- a/cmd/puppeth/module_faucet.go
+++ b/cmd/puppeth/module_faucet.go
@@ -93,7 +93,7 @@ func deployFaucet(client *sshClient, network string, bootnodes []string, config
"NetworkID": config.node.network,
"Bootnodes": strings.Join(bootnodes, ","),
"Ethstats": config.node.ethstats,
- "EthPort": config.node.portFull,
+ "EthPort": config.node.port,
"CaptchaToken": config.captchaToken,
"CaptchaSecret": config.captchaSecret,
"FaucetName": strings.Title(network),
@@ -110,7 +110,7 @@ func deployFaucet(client *sshClient, network string, bootnodes []string, config
"Datadir": config.node.datadir,
"VHost": config.host,
"ApiPort": config.port,
- "EthPort": config.node.portFull,
+ "EthPort": config.node.port,
"EthName": config.node.ethstats[:strings.Index(config.node.ethstats, ":")],
"CaptchaToken": config.captchaToken,
"CaptchaSecret": config.captchaSecret,
@@ -158,7 +158,7 @@ func (info *faucetInfos) Report() map[string]string {
report := map[string]string{
"Website address": info.host,
"Website listener port": strconv.Itoa(info.port),
- "Ethereum listener port": strconv.Itoa(info.node.portFull),
+ "Ethereum listener port": strconv.Itoa(info.node.port),
"Funding amount (base tier)": fmt.Sprintf("%d Ethers", info.amount),
"Funding cooldown (base tier)": fmt.Sprintf("%d mins", info.minutes),
"Funding tiers": strconv.Itoa(info.tiers),
@@ -228,7 +228,7 @@ func checkFaucet(client *sshClient, network string) (*faucetInfos, error) {
return &faucetInfos{
node: &nodeInfos{
datadir: infos.volumes["/root/.faucet"],
- portFull: infos.portmap[infos.envvars["ETH_PORT"]+"/tcp"],
+ port: infos.portmap[infos.envvars["ETH_PORT"]+"/tcp"],
ethstats: infos.envvars["ETH_NAME"],
keyJSON: keyJSON,
keyPass: keyPass,
diff --git a/cmd/puppeth/module_node.go b/cmd/puppeth/module_node.go
index 69cb19c34..2609fd976 100644
--- a/cmd/puppeth/module_node.go
+++ b/cmd/puppeth/module_node.go
@@ -42,7 +42,7 @@ ADD genesis.json /genesis.json
RUN \
echo 'geth --cache 512 init /genesis.json' > geth.sh && \{{if .Unlock}}
echo 'mkdir -p /root/.ethereum/keystore/ && cp /signer.json /root/.ethereum/keystore/' >> geth.sh && \{{end}}
- echo $'geth --networkid {{.NetworkID}} --cache 512 --port {{.Port}} --maxpeers {{.Peers}} {{.LightFlag}} --ethstats \'{{.Ethstats}}\' {{if .BootV4}}--bootnodesv4 {{.BootV4}}{{end}} {{if .BootV5}}--bootnodesv5 {{.BootV5}}{{end}} {{if .Etherbase}}--etherbase {{.Etherbase}} --mine --minerthreads 1{{end}} {{if .Unlock}}--unlock 0 --password /signer.pass --mine{{end}} --targetgaslimit {{.GasTarget}} --gasprice {{.GasPrice}}' >> geth.sh
+ echo $'geth --networkid {{.NetworkID}} --cache 512 --port {{.Port}} --maxpeers {{.Peers}} {{.LightFlag}} --ethstats \'{{.Ethstats}}\' {{if .Bootnodes}}--bootnodes {{.Bootnodes}}{{end}} {{if .Etherbase}}--etherbase {{.Etherbase}} --mine --minerthreads 1{{end}} {{if .Unlock}}--unlock 0 --password /signer.pass --mine{{end}} --targetgaslimit {{.GasTarget}} --gasprice {{.GasPrice}}' >> geth.sh
ENTRYPOINT ["/bin/sh", "geth.sh"]
`
@@ -56,15 +56,13 @@ services:
build: .
image: {{.Network}}/{{.Type}}
ports:
- - "{{.FullPort}}:{{.FullPort}}"
- - "{{.FullPort}}:{{.FullPort}}/udp"{{if .Light}}
- - "{{.LightPort}}:{{.LightPort}}/udp"{{end}}
+ - "{{.Port}}:{{.Port}}"
+ - "{{.Port}}:{{.Port}}/udp"
volumes:
- {{.Datadir}}:/root/.ethereum{{if .Ethashdir}}
- {{.Ethashdir}}:/root/.ethash{{end}}
environment:
- - FULL_PORT={{.FullPort}}/tcp
- - LIGHT_PORT={{.LightPort}}/udp
+ - PORT={{.Port}}/tcp
- TOTAL_PEERS={{.TotalPeers}}
- LIGHT_PEERS={{.LightPeers}}
- STATS_NAME={{.Ethstats}}
@@ -82,12 +80,11 @@ services:
// deployNode deploys a new Ethereum node container to a remote machine via SSH,
// docker and docker-compose. If an instance with the specified network name
// already exists there, it will be overwritten!
-func deployNode(client *sshClient, network string, bootv4, bootv5 []string, config *nodeInfos, nocache bool) ([]byte, error) {
+func deployNode(client *sshClient, network string, bootnodes []string, config *nodeInfos, nocache bool) ([]byte, error) {
kind := "sealnode"
if config.keyJSON == "" && config.etherbase == "" {
kind = "bootnode"
- bootv4 = make([]string, 0)
- bootv5 = make([]string, 0)
+ bootnodes = make([]string, 0)
}
// Generate the content to upload to the server
workdir := fmt.Sprintf("%d", rand.Int63())
@@ -100,11 +97,10 @@ func deployNode(client *sshClient, network string, bootv4, bootv5 []string, conf
dockerfile := new(bytes.Buffer)
template.Must(template.New("").Parse(nodeDockerfile)).Execute(dockerfile, map[string]interface{}{
"NetworkID": config.network,
- "Port": config.portFull,
+ "Port": config.port,
"Peers": config.peersTotal,
"LightFlag": lightFlag,
- "BootV4": strings.Join(bootv4, ","),
- "BootV5": strings.Join(bootv5, ","),
+ "Bootnodes": strings.Join(bootnodes, ","),
"Ethstats": config.ethstats,
"Etherbase": config.etherbase,
"GasTarget": uint64(1000000 * config.gasTarget),
@@ -119,10 +115,9 @@ func deployNode(client *sshClient, network string, bootv4, bootv5 []string, conf
"Datadir": config.datadir,
"Ethashdir": config.ethashdir,
"Network": network,
- "FullPort": config.portFull,
+ "Port": config.port,
"TotalPeers": config.peersTotal,
"Light": config.peersLight > 0,
- "LightPort": config.portFull + 1,
"LightPeers": config.peersLight,
"Ethstats": config.ethstats[:strings.Index(config.ethstats, ":")],
"Etherbase": config.etherbase,
@@ -157,10 +152,8 @@ type nodeInfos struct {
datadir string
ethashdir string
ethstats string
- portFull int
- portLight int
- enodeFull string
- enodeLight string
+ port int
+ enode string
peersTotal int
peersLight int
etherbase string
@@ -174,15 +167,11 @@ type nodeInfos struct {
// most - but not all - fields for reporting to the user.
func (info *nodeInfos) Report() map[string]string {
report := map[string]string{
- "Data directory": info.datadir,
- "Listener port (full nodes)": strconv.Itoa(info.portFull),
- "Peer count (all total)": strconv.Itoa(info.peersTotal),
- "Peer count (light nodes)": strconv.Itoa(info.peersLight),
- "Ethstats username": info.ethstats,
- }
- if info.peersLight > 0 {
- // Light server enabled
- report["Listener port (light nodes)"] = strconv.Itoa(info.portLight)
+ "Data directory": info.datadir,
+ "Listener port": strconv.Itoa(info.port),
+ "Peer count (all total)": strconv.Itoa(info.peersTotal),
+ "Peer count (light nodes)": strconv.Itoa(info.peersLight),
+ "Ethstats username": info.ethstats,
}
if info.gasTarget > 0 {
// Miner or signer node
@@ -250,7 +239,7 @@ func checkNode(client *sshClient, network string, boot bool) (*nodeInfos, error)
keyPass = string(bytes.TrimSpace(out))
}
// Run a sanity check to see if the devp2p is reachable
- port := infos.portmap[infos.envvars["FULL_PORT"]]
+ port := infos.portmap[infos.envvars["PORT"]]
if err = checkPort(client.server, port); err != nil {
log.Warn(fmt.Sprintf("%s devp2p port seems unreachable", strings.Title(kind)), "server", client.server, "port", port, "err", err)
}
@@ -259,8 +248,7 @@ func checkNode(client *sshClient, network string, boot bool) (*nodeInfos, error)
genesis: genesis,
datadir: infos.volumes["/root/.ethereum"],
ethashdir: infos.volumes["/root/.ethash"],
- portFull: infos.portmap[infos.envvars["FULL_PORT"]],
- portLight: infos.portmap[infos.envvars["LIGHT_PORT"]],
+ port: port,
peersTotal: totalPeers,
peersLight: lightPeers,
ethstats: infos.envvars["STATS_NAME"],
@@ -270,9 +258,7 @@ func checkNode(client *sshClient, network string, boot bool) (*nodeInfos, error)
gasTarget: gasTarget,
gasPrice: gasPrice,
}
- stats.enodeFull = fmt.Sprintf("enode://%s@%s:%d", id, client.address, stats.portFull)
- if stats.portLight != 0 {
- stats.enodeLight = fmt.Sprintf("enode://%s@%s:%d?discport=%d", id, client.address, stats.portFull, stats.portLight)
- }
+ stats.enode = fmt.Sprintf("enode://%s@%s:%d", id, client.address, stats.port)
+
return stats, nil
}
diff --git a/cmd/puppeth/wizard.go b/cmd/puppeth/wizard.go
index 2e2b4644c..b88a61de7 100644
--- a/cmd/puppeth/wizard.go
+++ b/cmd/puppeth/wizard.go
@@ -40,8 +40,7 @@ import (
// between sessions.
type config struct {
path string // File containing the configuration values
- bootFull []string // Bootnodes to always connect to by full nodes
- bootLight []string // Bootnodes to always connect to by light nodes
+ bootnodes []string // Bootnodes to always connect to by all nodes
ethstats string // Ethstats settings to cache for node deploys
Genesis *core.Genesis `json:"genesis,omitempty"` // Genesis block to cache for node deploys
diff --git a/cmd/puppeth/wizard_explorer.go b/cmd/puppeth/wizard_explorer.go
index 10ef72f78..413511c1c 100644
--- a/cmd/puppeth/wizard_explorer.go
+++ b/cmd/puppeth/wizard_explorer.go
@@ -55,7 +55,7 @@ func (w *wizard) deployExplorer() {
}
existed := err == nil
- chainspec, err := newParityChainSpec(w.network, w.conf.Genesis, w.conf.bootFull)
+ chainspec, err := newParityChainSpec(w.network, w.conf.Genesis, w.conf.bootnodes)
if err != nil {
log.Error("Failed to create chain spec for explorer", "err", err)
return
diff --git a/cmd/puppeth/wizard_faucet.go b/cmd/puppeth/wizard_faucet.go
index 191575b16..9a429bc96 100644
--- a/cmd/puppeth/wizard_faucet.go
+++ b/cmd/puppeth/wizard_faucet.go
@@ -38,7 +38,7 @@ func (w *wizard) deployFaucet() {
infos, err := checkFaucet(client, w.network)
if err != nil {
infos = &faucetInfos{
- node: &nodeInfos{portFull: 30303, peersTotal: 25},
+ node: &nodeInfos{port: 30303, peersTotal: 25},
port: 80,
host: client.server,
amount: 1,
@@ -113,8 +113,8 @@ func (w *wizard) deployFaucet() {
}
// Figure out which port to listen on
fmt.Println()
- fmt.Printf("Which TCP/UDP port should the light client listen on? (default = %d)\n", infos.node.portFull)
- infos.node.portFull = w.readDefaultInt(infos.node.portFull)
+ fmt.Printf("Which TCP/UDP port should the light client listen on? (default = %d)\n", infos.node.port)
+ infos.node.port = w.readDefaultInt(infos.node.port)
// Set a proper name to report on the stats page
fmt.Println()
@@ -168,7 +168,7 @@ func (w *wizard) deployFaucet() {
fmt.Printf("Should the faucet be built from scratch (y/n)? (default = no)\n")
nocache = w.readDefaultString("n") != "n"
}
- if out, err := deployFaucet(client, w.network, w.conf.bootLight, infos, nocache); err != nil {
+ if out, err := deployFaucet(client, w.network, w.conf.bootnodes, infos, nocache); err != nil {
log.Error("Failed to deploy faucet container", "err", err)
if len(out) > 0 {
fmt.Printf("%s\n", out)
diff --git a/cmd/puppeth/wizard_netstats.go b/cmd/puppeth/wizard_netstats.go
index e19180bb1..90bf7ae3c 100644
--- a/cmd/puppeth/wizard_netstats.go
+++ b/cmd/puppeth/wizard_netstats.go
@@ -37,8 +37,7 @@ func (w *wizard) networkStats() {
}
// Clear out some previous configs to refill from current scan
w.conf.ethstats = ""
- w.conf.bootFull = w.conf.bootFull[:0]
- w.conf.bootLight = w.conf.bootLight[:0]
+ w.conf.bootnodes = w.conf.bootnodes[:0]
// Iterate over all the specified hosts and check their status
var pend sync.WaitGroup
@@ -76,8 +75,7 @@ func (w *wizard) gatherStats(server string, pubkey []byte, client *sshClient) *s
var (
genesis string
ethstats string
- bootFull []string
- bootLight []string
+ bootnodes []string
)
// Ensure a valid SSH connection to the remote server
logger := log.New("server", server)
@@ -123,10 +121,7 @@ func (w *wizard) gatherStats(server string, pubkey []byte, client *sshClient) *s
stat.services["bootnode"] = infos.Report()
genesis = string(infos.genesis)
- bootFull = append(bootFull, infos.enodeFull)
- if infos.enodeLight != "" {
- bootLight = append(bootLight, infos.enodeLight)
- }
+ bootnodes = append(bootnodes, infos.enode)
}
logger.Debug("Checking for sealnode availability")
if infos, err := checkNode(client, w.network, false); err != nil {
@@ -184,8 +179,7 @@ func (w *wizard) gatherStats(server string, pubkey []byte, client *sshClient) *s
if ethstats != "" {
w.conf.ethstats = ethstats
}
- w.conf.bootFull = append(w.conf.bootFull, bootFull...)
- w.conf.bootLight = append(w.conf.bootLight, bootLight...)
+ w.conf.bootnodes = append(w.conf.bootnodes, bootnodes...)
return stat
}
diff --git a/cmd/puppeth/wizard_node.go b/cmd/puppeth/wizard_node.go
index 097e2e41a..a60948bc6 100644
--- a/cmd/puppeth/wizard_node.go
+++ b/cmd/puppeth/wizard_node.go
@@ -48,9 +48,9 @@ func (w *wizard) deployNode(boot bool) {
infos, err := checkNode(client, w.network, boot)
if err != nil {
if boot {
- infos = &nodeInfos{portFull: 30303, peersTotal: 512, peersLight: 256}
+ infos = &nodeInfos{port: 30303, peersTotal: 512, peersLight: 256}
} else {
- infos = &nodeInfos{portFull: 30303, peersTotal: 50, peersLight: 0, gasTarget: 4.7, gasPrice: 18}
+ infos = &nodeInfos{port: 30303, peersTotal: 50, peersLight: 0, gasTarget: 4.7, gasPrice: 18}
}
}
existed := err == nil
@@ -79,8 +79,8 @@ func (w *wizard) deployNode(boot bool) {
}
// Figure out which port to listen on
fmt.Println()
- fmt.Printf("Which TCP/UDP port to listen on? (default = %d)\n", infos.portFull)
- infos.portFull = w.readDefaultInt(infos.portFull)
+ fmt.Printf("Which TCP/UDP port to listen on? (default = %d)\n", infos.port)
+ infos.port = w.readDefaultInt(infos.port)
// Figure out how many peers to allow (different based on node type)
fmt.Println()
@@ -163,7 +163,7 @@ func (w *wizard) deployNode(boot bool) {
fmt.Printf("Should the node be built from scratch (y/n)? (default = no)\n")
nocache = w.readDefaultString("n") != "n"
}
- if out, err := deployNode(client, w.network, w.conf.bootFull, w.conf.bootLight, infos, nocache); err != nil {
+ if out, err := deployNode(client, w.network, w.conf.bootnodes, infos, nocache); err != nil {
log.Error("Failed to deploy Ethereum node container", "err", err)
if len(out) > 0 {
fmt.Printf("%s\n", out)
diff --git a/cmd/puppeth/wizard_wallet.go b/cmd/puppeth/wizard_wallet.go
index 7c3896a17..933cd9ae5 100644
--- a/cmd/puppeth/wizard_wallet.go
+++ b/cmd/puppeth/wizard_wallet.go
@@ -98,7 +98,7 @@ func (w *wizard) deployWallet() {
fmt.Printf("Should the wallet be built from scratch (y/n)? (default = no)\n")
nocache = w.readDefaultString("n") != "n"
}
- if out, err := deployWallet(client, w.network, w.conf.bootFull, infos, nocache); err != nil {
+ if out, err := deployWallet(client, w.network, w.conf.bootnodes, infos, nocache); err != nil {
log.Error("Failed to deploy wallet container", "err", err)
if len(out) > 0 {
fmt.Printf("%s\n", out)
diff --git a/cmd/swarm/config.go b/cmd/swarm/config.go
index 33235ca06..29b5faefa 100644
--- a/cmd/swarm/config.go
+++ b/cmd/swarm/config.go
@@ -315,7 +315,7 @@ func checkDeprecated(ctx *cli.Context) {
func printConfig(config *bzzapi.Config) string {
out, err := tomlSettings.Marshal(&config)
if err != nil {
- return (fmt.Sprintf("Something is not right with the configuration: %v", err))
+ return fmt.Sprintf("Something is not right with the configuration: %v", err)
}
return string(out)
}
diff --git a/cmd/swarm/run_test.go b/cmd/swarm/run_test.go
index ed1502868..594cfa55c 100644
--- a/cmd/swarm/run_test.go
+++ b/cmd/swarm/run_test.go
@@ -1,4 +1,4 @@
-// Copyright 2016 The go-ethereum Authors
+// Copyright 2017 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
diff --git a/cmd/swarm/upload_test.go b/cmd/swarm/upload_test.go
index 5656186e1..df7fc216a 100644
--- a/cmd/swarm/upload_test.go
+++ b/cmd/swarm/upload_test.go
@@ -1,4 +1,4 @@
-// Copyright 2016 The go-ethereum Authors
+// Copyright 2017 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index 23b10c2d7..186d18d8f 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -25,6 +25,7 @@ import (
"os/signal"
"runtime"
"strings"
+ "syscall"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
@@ -64,7 +65,7 @@ func StartNode(stack *node.Node) {
}
go func() {
sigc := make(chan os.Signal, 1)
- signal.Notify(sigc, os.Interrupt)
+ signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM)
defer signal.Stop(sigc)
<-sigc
log.Info("Got interrupt, shutting down...")
@@ -85,7 +86,7 @@ func ImportChain(chain *core.BlockChain, fn string) error {
// If a signal is received, the import will stop at the next batch.
interrupt := make(chan os.Signal, 1)
stop := make(chan struct{})
- signal.Notify(interrupt, os.Interrupt)
+ signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM)
defer signal.Stop(interrupt)
defer close(interrupt)
go func() {
@@ -116,7 +117,6 @@ func ImportChain(chain *core.BlockChain, fn string) error {
return err
}
}
-
stream := rlp.NewStream(reader, 0)
// Run actual the import.
@@ -150,25 +150,34 @@ func ImportChain(chain *core.BlockChain, fn string) error {
if checkInterrupt() {
return fmt.Errorf("interrupted")
}
- if hasAllBlocks(chain, blocks[:i]) {
+ missing := missingBlocks(chain, blocks[:i])
+ if len(missing) == 0 {
log.Info("Skipping batch as all blocks present", "batch", batch, "first", blocks[0].Hash(), "last", blocks[i-1].Hash())
continue
}
-
- if _, err := chain.InsertChain(blocks[:i]); err != nil {
+ if _, err := chain.InsertChain(missing); err != nil {
return fmt.Errorf("invalid block %d: %v", n, err)
}
}
return nil
}
-func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool {
- for _, b := range bs {
- if !chain.HasBlock(b.Hash(), b.NumberU64()) {
- return false
+func missingBlocks(chain *core.BlockChain, blocks []*types.Block) []*types.Block {
+ head := chain.CurrentBlock()
+ for i, block := range blocks {
+ // If we're behind the chain head, only check block, state is available at head
+ if head.NumberU64() > block.NumberU64() {
+ if !chain.HasBlock(block.Hash(), block.NumberU64()) {
+ return blocks[i:]
+ }
+ continue
+ }
+ // If we're above the chain head, state availability is a must
+ if !chain.HasBlockAndState(block.Hash(), block.NumberU64()) {
+ return blocks[i:]
}
}
- return true
+ return nil
}
func ExportChain(blockchain *core.BlockChain, fn string) error {
diff --git a/cmd/utils/fdlimit_windows.go b/cmd/utils/fdlimit_windows.go
deleted file mode 100644
index f239683d2..000000000
--- a/cmd/utils/fdlimit_windows.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of go-ethereum.
-//
-// go-ethereum is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// go-ethereum is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
-
-package utils
-
-import "errors"
-
-// raiseFdLimit tries to maximize the file descriptor allowance of this process
-// to the maximum hard-limit allowed by the OS.
-func raiseFdLimit(max uint64) error {
- // This method is NOP by design:
- // * Linux/Darwin counterparts need to manually increase per process limits
- // * On Windows Go uses the CreateFile API, which is limited to 16K files, non
- // changeable from within a running process
- // This way we can always "request" raising the limits, which will either have
- // or not have effect based on the platform we're running on.
- if max > 16384 {
- return errors.New("file descriptor limit (16384) reached")
- }
- return nil
-}
-
-// getFdLimit retrieves the number of file descriptors allowed to be opened by this
-// process.
-func getFdLimit() (int, error) {
- // Please see raiseFdLimit for the reason why we use hard coded 16K as the limit
- return 16384, nil
-}
-
-// getFdMaxLimit retrieves the maximum number of file descriptors this process is
-// allowed to request for itself.
-func getFdMaxLimit() (int, error) {
- return getFdLimit()
-}
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 30edf199c..5fd5013f0 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/fdlimit"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/consensus/ethash"
@@ -96,7 +97,7 @@ func NewApp(gitCommit, usage string) *cli.App {
//app.Authors = nil
app.Email = ""
app.Version = params.Version
- if gitCommit != "" {
+ if len(gitCommit) >= 8 {
app.Version += "-" + gitCommit[:8]
}
app.Usage = usage
@@ -169,7 +170,11 @@ var (
Usage: `Blockchain sync mode ("fast", "full", or "light")`,
Value: &defaultSyncMode,
}
-
+ GCModeFlag = cli.StringFlag{
+ Name: "gcmode",
+ Usage: `Blockchain garbage collection mode ("full", "archive")`,
+ Value: "full",
+ }
LightServFlag = cli.IntFlag{
Name: "lightserv",
Usage: "Maximum percentage of time allowed for serving LES requests (0-90)",
@@ -178,7 +183,7 @@ var (
LightPeersFlag = cli.IntFlag{
Name: "lightpeers",
Usage: "Maximum number of LES client peers",
- Value: 20,
+ Value: eth.DefaultConfig.LightPeers,
}
LightKDFFlag = cli.BoolFlag{
Name: "lightkdf",
@@ -292,8 +297,18 @@ var (
// Performance tuning settings
CacheFlag = cli.IntFlag{
Name: "cache",
- Usage: "Megabytes of memory allocated to internal caching (min 16MB / database forced)",
- Value: 128,
+ Usage: "Megabytes of memory allocated to internal caching",
+ Value: 1024,
+ }
+ CacheDatabaseFlag = cli.IntFlag{
+ Name: "cache.database",
+ Usage: "Percentage of cache memory allowance to use for database io",
+ Value: 75,
+ }
+ CacheGCFlag = cli.IntFlag{
+ Name: "cache.gc",
+ Usage: "Percentage of cache memory allowance to use for trie pruning",
+ Value: 25,
}
TrieCacheGenFlag = cli.IntFlag{
Name: "trie-cache-gens",
@@ -313,7 +328,7 @@ var (
TargetGasLimitFlag = cli.Uint64Flag{
Name: "targetgaslimit",
Usage: "Target gas limit sets the artificial target gas floor for the blocks to mine",
- Value: params.GenesisGasLimit.Uint64(),
+ Value: params.GenesisGasLimit,
}
EtherbaseFlag = cli.StringFlag{
Name: "etherbase",
@@ -382,6 +397,11 @@ var (
Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
Value: "",
}
+ RPCVirtualHostsFlag = cli.StringFlag{
+ Name: "rpcvhosts",
+ Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
+ Value: "localhost",
+ }
RPCApiFlag = cli.StringFlag{
Name: "rpcapi",
Usage: "API's offered over the HTTP-RPC interface",
@@ -611,7 +631,7 @@ func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) {
urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
}
case ctx.GlobalBool(RinkebyFlag.Name):
- urls = params.RinkebyV5Bootnodes
+ urls = params.RinkebyBootnodes
case cfg.BootstrapNodesV5 != nil:
return // already set, don't apply defaults.
}
@@ -635,14 +655,6 @@ func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
}
}
-// setDiscoveryV5Address creates a UDP listening address string from set command
-// line flags for the V5 discovery protocol.
-func setDiscoveryV5Address(ctx *cli.Context, cfg *p2p.Config) {
- if ctx.GlobalIsSet(ListenPortFlag.Name) {
- cfg.DiscoveryV5Addr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)+1)
- }
-}
-
// setNAT creates a port mapper from command line flags.
func setNAT(ctx *cli.Context, cfg *p2p.Config) {
if ctx.GlobalIsSet(NATFlag.Name) {
@@ -683,6 +695,8 @@ func setHTTP(ctx *cli.Context, cfg *node.Config) {
if ctx.GlobalIsSet(RPCApiFlag.Name) {
cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name))
}
+
+ cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name))
}
// setWS creates the WebSocket RPC listener interface string from the set
@@ -721,13 +735,15 @@ func setIPC(ctx *cli.Context, cfg *node.Config) {
// makeDatabaseHandles raises out the number of allowed file handles per process
// for Geth and returns half of the allowance to assign to the database.
func makeDatabaseHandles() int {
- if err := raiseFdLimit(2048); err != nil {
- Fatalf("Failed to raise file descriptor allowance: %v", err)
- }
- limit, err := getFdLimit()
+ limit, err := fdlimit.Current()
if err != nil {
Fatalf("Failed to retrieve file descriptor allowance: %v", err)
}
+ if limit < 2048 {
+ if err := fdlimit.Raise(2048); err != nil {
+ Fatalf("Failed to raise file descriptor allowance: %v", err)
+ }
+ }
if limit > 2048 { // cap database file descriptors even if more is available
limit = 2048
}
@@ -793,24 +809,43 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
setNodeKey(ctx, cfg)
setNAT(ctx, cfg)
setListenAddress(ctx, cfg)
- setDiscoveryV5Address(ctx, cfg)
setBootstrapNodes(ctx, cfg)
setBootstrapNodesV5(ctx, cfg)
+ lightClient := ctx.GlobalBool(LightModeFlag.Name) || ctx.GlobalString(SyncModeFlag.Name) == "light"
+ lightServer := ctx.GlobalInt(LightServFlag.Name) != 0
+ lightPeers := ctx.GlobalInt(LightPeersFlag.Name)
+
if ctx.GlobalIsSet(MaxPeersFlag.Name) {
cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name)
+ } else {
+ if lightServer {
+ cfg.MaxPeers += lightPeers
+ }
+ if lightClient && ctx.GlobalIsSet(LightPeersFlag.Name) && cfg.MaxPeers < lightPeers {
+ cfg.MaxPeers = lightPeers
+ }
+ }
+ if !(lightClient || lightServer) {
+ lightPeers = 0
+ }
+ ethPeers := cfg.MaxPeers - lightPeers
+ if lightClient {
+ ethPeers = 0
}
+ log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers)
+
if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) {
cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name)
}
- if ctx.GlobalIsSet(NoDiscoverFlag.Name) || ctx.GlobalBool(LightModeFlag.Name) {
+ if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient {
cfg.NoDiscovery = true
}
// if we're running a light client or server, force enable the v5 peer discovery
// unless it is explicitly disabled with --nodiscover note that explicitly specifying
// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
- forceV5Discovery := (ctx.GlobalBool(LightModeFlag.Name) || ctx.GlobalInt(LightServFlag.Name) > 0) && !ctx.GlobalBool(NoDiscoverFlag.Name)
+ forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name)
if ctx.GlobalIsSet(DiscoveryV5Flag.Name) {
cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name)
} else if forceV5Discovery {
@@ -829,7 +864,6 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
// --dev mode can't use p2p networking.
cfg.MaxPeers = 0
cfg.ListenAddr = ":0"
- cfg.DiscoveryV5Addr = ":0"
cfg.NoDiscovery = true
cfg.DiscoveryV5 = false
}
@@ -1008,11 +1042,19 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
}
- if ctx.GlobalIsSet(CacheFlag.Name) {
- cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name)
+ if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) {
+ cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
}
cfg.DatabaseHandles = makeDatabaseHandles()
+ if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
+ Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
+ }
+ cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive"
+
+ if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
+ cfg.TrieCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
+ }
if ctx.GlobalIsSet(MinerThreadsFlag.Name) {
cfg.MinerThreads = ctx.GlobalInt(MinerThreadsFlag.Name)
}
@@ -1103,9 +1145,9 @@ func RegisterEthService(stack *node.Node, cfg *eth.Config) {
}
// RegisterDashboardService adds a dashboard to the stack.
-func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config) {
+func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) {
stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
- return dashboard.New(cfg)
+ return dashboard.New(cfg, commit)
})
}
@@ -1138,13 +1180,13 @@ func RegisterEthStatsService(stack *node.Node, url string) {
// SetupNetwork configures the system for either the main net or some test network.
func SetupNetwork(ctx *cli.Context) {
// TODO(fjl): move target gas limit into config
- params.TargetGasLimit = new(big.Int).SetUint64(ctx.GlobalUint64(TargetGasLimitFlag.Name))
+ params.TargetGasLimit = ctx.GlobalUint64(TargetGasLimitFlag.Name)
}
// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
var (
- cache = ctx.GlobalInt(CacheFlag.Name)
+ cache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
handles = makeDatabaseHandles()
)
name := "chaindata"
@@ -1196,8 +1238,19 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai
})
}
}
+ if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
+ Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
+ }
+ cache := &core.CacheConfig{
+ Disabled: ctx.GlobalString(GCModeFlag.Name) == "archive",
+ TrieNodeLimit: eth.DefaultConfig.TrieCache,
+ TrieTimeLimit: eth.DefaultConfig.TrieTimeout,
+ }
+ if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
+ cache.TrieNodeLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
+ }
vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
- chain, err = core.NewBlockChain(chainDb, config, engine, vmcfg)
+ chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg)
if err != nil {
Fatalf("Can't create BlockChain: %v", err)
}
diff --git a/cmd/wnode/main.go b/cmd/wnode/main.go
index 05e6b2908..971b1c0ab 100644
--- a/cmd/wnode/main.go
+++ b/cmd/wnode/main.go
@@ -43,7 +43,7 @@ import (
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/whisper/mailserver"
- whisper "github.com/ethereum/go-ethereum/whisper/whisperv5"
+ whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
"golang.org/x/crypto/pbkdf2"
)
@@ -61,15 +61,17 @@ var (
// encryption
var (
- symKey []byte
- pub *ecdsa.PublicKey
- asymKey *ecdsa.PrivateKey
- nodeid *ecdsa.PrivateKey
- topic whisper.TopicType
- asymKeyID string
- filterID string
- symPass string
- msPassword string
+ symKey []byte
+ pub *ecdsa.PublicKey
+ asymKey *ecdsa.PrivateKey
+ nodeid *ecdsa.PrivateKey
+ topic whisper.TopicType
+
+ asymKeyID string
+ asymFilterID string
+ symFilterID string
+ symPass string
+ msPassword string
)
// cmd arguments
@@ -263,7 +265,7 @@ func initialize() {
Config: p2p.Config{
PrivateKey: nodeid,
MaxPeers: maxPeers,
- Name: common.MakeName("wnode", "5.0"),
+ Name: common.MakeName("wnode", "6.0"),
Protocols: shh.Protocols(),
ListenAddr: *argIP,
NAT: nat.Any(),
@@ -363,13 +365,22 @@ func configureNode() {
}
}
- filter := whisper.Filter{
+ symFilter := whisper.Filter{
KeySym: symKey,
+ Topics: [][]byte{topic[:]},
+ AllowP2P: p2pAccept,
+ }
+ symFilterID, err = shh.Subscribe(&symFilter)
+ if err != nil {
+ utils.Fatalf("Failed to install filter: %s", err)
+ }
+
+ asymFilter := whisper.Filter{
KeyAsym: asymKey,
Topics: [][]byte{topic[:]},
AllowP2P: p2pAccept,
}
- filterID, err = shh.Subscribe(&filter)
+ asymFilterID, err = shh.Subscribe(&asymFilter)
if err != nil {
utils.Fatalf("Failed to install filter: %s", err)
}
@@ -522,9 +533,14 @@ func sendMsg(payload []byte) common.Hash {
}
func messageLoop() {
- f := shh.GetFilter(filterID)
- if f == nil {
- utils.Fatalf("filter is not installed")
+ sf := shh.GetFilter(symFilterID)
+ if sf == nil {
+ utils.Fatalf("symmetric filter is not installed")
+ }
+
+ af := shh.GetFilter(asymFilterID)
+ if af == nil {
+ utils.Fatalf("asymmetric filter is not installed")
}
ticker := time.NewTicker(time.Millisecond * 50)
@@ -532,7 +548,16 @@ func messageLoop() {
for {
select {
case <-ticker.C:
- messages := f.Retrieve()
+ messages := sf.Retrieve()
+ for _, msg := range messages {
+ if *fileExMode || len(msg.Payload) > 2048 {
+ writeMessageToFile(*argSaveDir, msg)
+ } else {
+ printMessageInfo(msg)
+ }
+ }
+
+ messages = af.Retrieve()
for _, msg := range messages {
if *fileExMode || len(msg.Payload) > 2048 {
writeMessageToFile(*argSaveDir, msg)
@@ -601,7 +626,7 @@ func requestExpiredMessagesLoop() {
if err != nil {
utils.Fatalf("Failed to save symmetric key for mail request: %s", err)
}
- peerID = extractIdFromEnode(*argEnode)
+ peerID = extractIDFromEnode(*argEnode)
shh.AllowP2PMessagesFromPeer(peerID)
for {
@@ -631,7 +656,7 @@ func requestExpiredMessagesLoop() {
params.PoW = *argServerPoW
params.Payload = data
params.KeySym = key
- params.Src = nodeid
+ params.Src = asymKey
params.WorkTime = 5
msg, err := whisper.NewSentMessage(&params)
@@ -652,7 +677,7 @@ func requestExpiredMessagesLoop() {
}
}
-func extractIdFromEnode(s string) []byte {
+func extractIDFromEnode(s string) []byte {
n, err := discover.ParseNode(s)
if err != nil {
utils.Fatalf("Failed to parse enode: %s", err)
diff --git a/common/bitutil/bitutil.go b/common/bitutil/bitutil.go
index 117616543..cd3e72169 100644
--- a/common/bitutil/bitutil.go
+++ b/common/bitutil/bitutil.go
@@ -40,7 +40,7 @@ func fastXORBytes(dst, a, b []byte) int {
dw[i] = aw[i] ^ bw[i]
}
}
- for i := (n - n%wordSize); i < n; i++ {
+ for i := n - n%wordSize; i < n; i++ {
dst[i] = a[i] ^ b[i]
}
return n
@@ -84,7 +84,7 @@ func fastANDBytes(dst, a, b []byte) int {
dw[i] = aw[i] & bw[i]
}
}
- for i := (n - n%wordSize); i < n; i++ {
+ for i := n - n%wordSize; i < n; i++ {
dst[i] = a[i] & b[i]
}
return n
@@ -128,7 +128,7 @@ func fastORBytes(dst, a, b []byte) int {
dw[i] = aw[i] | bw[i]
}
}
- for i := (n - n%wordSize); i < n; i++ {
+ for i := n - n%wordSize; i < n; i++ {
dst[i] = a[i] | b[i]
}
return n
@@ -168,7 +168,7 @@ func fastTestBytes(p []byte) bool {
}
}
}
- for i := (n - n%wordSize); i < n; i++ {
+ for i := n - n%wordSize; i < n; i++ {
if p[i] != 0 {
return true
}
diff --git a/cmd/utils/fdlimit_freebsd.go b/common/fdlimit/fdlimit_freebsd.go
index f9ed8937e..c126b0c26 100644
--- a/cmd/utils/fdlimit_freebsd.go
+++ b/common/fdlimit/fdlimit_freebsd.go
@@ -1,22 +1,22 @@
// Copyright 2016 The go-ethereum Authors
-// This file is part of go-ethereum.
+// This file is part of the go-ethereum library.
//
-// go-ethereum is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
-// go-ethereum is distributed in the hope that it will be useful,
+// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
+// GNU Lesser General Public License for more details.
//
-// You should have received a copy of the GNU General Public License
-// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// +build freebsd
-package utils
+package fdlimit
import "syscall"
@@ -24,9 +24,9 @@ import "syscall"
// but Rlimit fields have type int64 on FreeBSD so it needs
// an extra conversion.
-// raiseFdLimit tries to maximize the file descriptor allowance of this process
+// Raise tries to maximize the file descriptor allowance of this process
// to the maximum hard-limit allowed by the OS.
-func raiseFdLimit(max uint64) error {
+func Raise(max uint64) error {
// Get the current limit
var limit syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
@@ -43,9 +43,9 @@ func raiseFdLimit(max uint64) error {
return nil
}
-// getFdLimit retrieves the number of file descriptors allowed to be opened by this
+// Current retrieves the number of file descriptors allowed to be opened by this
// process.
-func getFdLimit() (int, error) {
+func Current() (int, error) {
var limit syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
return 0, err
@@ -53,9 +53,9 @@ func getFdLimit() (int, error) {
return int(limit.Cur), nil
}
-// getFdMaxLimit retrieves the maximum number of file descriptors this process is
+// Maximum retrieves the maximum number of file descriptors this process is
// allowed to request for itself.
-func getFdMaxLimit() (int, error) {
+func Maximum() (int, error) {
var limit syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
return 0, err
diff --git a/cmd/utils/fdlimit_test.go b/common/fdlimit/fdlimit_test.go
index 48489cf4c..a9ee9ab36 100644
--- a/cmd/utils/fdlimit_test.go
+++ b/common/fdlimit/fdlimit_test.go
@@ -1,20 +1,20 @@
// Copyright 2016 The go-ethereum Authors
-// This file is part of go-ethereum.
+// This file is part of the go-ethereum library.
//
-// go-ethereum is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
-// go-ethereum is distributed in the hope that it will be useful,
+// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
+// GNU Lesser General Public License for more details.
//
-// You should have received a copy of the GNU General Public License
-// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package utils
+package fdlimit
import (
"fmt"
@@ -25,7 +25,7 @@ import (
// per this process can be retrieved.
func TestFileDescriptorLimits(t *testing.T) {
target := 4096
- hardlimit, err := getFdMaxLimit()
+ hardlimit, err := Maximum()
if err != nil {
t.Fatal(err)
}
@@ -33,13 +33,13 @@ func TestFileDescriptorLimits(t *testing.T) {
t.Skip(fmt.Sprintf("system limit is less than desired test target: %d < %d", hardlimit, target))
}
- if limit, err := getFdLimit(); err != nil || limit <= 0 {
+ if limit, err := Current(); err != nil || limit <= 0 {
t.Fatalf("failed to retrieve file descriptor limit (%d): %v", limit, err)
}
- if err := raiseFdLimit(uint64(target)); err != nil {
+ if err := Raise(uint64(target)); err != nil {
t.Fatalf("failed to raise file allowance")
}
- if limit, err := getFdLimit(); err != nil || limit < target {
+ if limit, err := Current(); err != nil || limit < target {
t.Fatalf("failed to retrieve raised descriptor limit (have %v, want %v): %v", limit, target, err)
}
}
diff --git a/cmd/utils/fdlimit_unix.go b/common/fdlimit/fdlimit_unix.go
index c08d1fab0..a25813235 100644
--- a/cmd/utils/fdlimit_unix.go
+++ b/common/fdlimit/fdlimit_unix.go
@@ -1,28 +1,28 @@
// Copyright 2016 The go-ethereum Authors
-// This file is part of go-ethereum.
+// This file is part of the go-ethereum library.
//
-// go-ethereum is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
-// go-ethereum is distributed in the hope that it will be useful,
+// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
+// GNU Lesser General Public License for more details.
//
-// You should have received a copy of the GNU General Public License
-// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// +build linux darwin netbsd openbsd solaris
-package utils
+package fdlimit
import "syscall"
-// raiseFdLimit tries to maximize the file descriptor allowance of this process
+// Raise tries to maximize the file descriptor allowance of this process
// to the maximum hard-limit allowed by the OS.
-func raiseFdLimit(max uint64) error {
+func Raise(max uint64) error {
// Get the current limit
var limit syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
@@ -39,9 +39,9 @@ func raiseFdLimit(max uint64) error {
return nil
}
-// getFdLimit retrieves the number of file descriptors allowed to be opened by this
+// Current retrieves the number of file descriptors allowed to be opened by this
// process.
-func getFdLimit() (int, error) {
+func Current() (int, error) {
var limit syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
return 0, err
@@ -49,9 +49,9 @@ func getFdLimit() (int, error) {
return int(limit.Cur), nil
}
-// getFdMaxLimit retrieves the maximum number of file descriptors this process is
+// Maximum retrieves the maximum number of file descriptors this process is
// allowed to request for itself.
-func getFdMaxLimit() (int, error) {
+func Maximum() (int, error) {
var limit syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
return 0, err
diff --git a/common/fdlimit/fdlimit_windows.go b/common/fdlimit/fdlimit_windows.go
new file mode 100644
index 000000000..863c58bed
--- /dev/null
+++ b/common/fdlimit/fdlimit_windows.go
@@ -0,0 +1,47 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package fdlimit
+
+import "errors"
+
+// Raise tries to maximize the file descriptor allowance of this process
+// to the maximum hard-limit allowed by the OS.
+func Raise(max uint64) error {
+ // This method is NOP by design:
+ // * Linux/Darwin counterparts need to manually increase per process limits
+ // * On Windows Go uses the CreateFile API, which is limited to 16K files, non
+ // changeable from within a running process
+ // This way we can always "request" raising the limits, which will either have
+ // or not have effect based on the platform we're running on.
+ if max > 16384 {
+ return errors.New("file descriptor limit (16384) reached")
+ }
+ return nil
+}
+
+// Current retrieves the number of file descriptors allowed to be opened by this
+// process.
+func Current() (int, error) {
+ // Please see Raise for the reason why we use hard coded 16K as the limit
+ return 16384, nil
+}
+
+// Maximum retrieves the maximum number of file descriptors this process is
+// allowed to request for itself.
+func Maximum() (int, error) {
+ return Current()
+}
diff --git a/common/size.go b/common/size.go
index c5a0cb0f2..bd0fc85c7 100644
--- a/common/size.go
+++ b/common/size.go
@@ -20,18 +20,29 @@ import (
"fmt"
)
+// StorageSize is a wrapper around a float value that supports user friendly
+// formatting.
type StorageSize float64
-func (self StorageSize) String() string {
- if self > 1000000 {
- return fmt.Sprintf("%.2f mB", self/1000000)
- } else if self > 1000 {
- return fmt.Sprintf("%.2f kB", self/1000)
+// String implements the stringer interface.
+func (s StorageSize) String() string {
+ if s > 1000000 {
+ return fmt.Sprintf("%.2f mB", s/1000000)
+ } else if s > 1000 {
+ return fmt.Sprintf("%.2f kB", s/1000)
} else {
- return fmt.Sprintf("%.2f B", self)
+ return fmt.Sprintf("%.2f B", s)
}
}
-func (self StorageSize) Int64() int64 {
- return int64(self)
+// TerminalString implements log.TerminalStringer, formatting a string for console
+// output during logging.
+func (s StorageSize) TerminalString() string {
+ if s > 1000000 {
+ return fmt.Sprintf("%.2fmB", s/1000000)
+ } else if s > 1000 {
+ return fmt.Sprintf("%.2fkB", s/1000)
+ } else {
+ return fmt.Sprintf("%.2fB", s)
+ }
}
diff --git a/consensus/errors.go b/consensus/errors.go
index 3b136dbdd..a005c5f63 100644
--- a/consensus/errors.go
+++ b/consensus/errors.go
@@ -23,6 +23,10 @@ var (
// that is unknown.
ErrUnknownAncestor = errors.New("unknown ancestor")
+ // ErrPrunedAncestor is returned when validating a block requires an ancestor
+ // that is known, but the state of which is not available.
+ ErrPrunedAncestor = errors.New("pruned ancestor")
+
// ErrFutureBlock is returned when a block's timestamp is in the future according
// to the current node.
ErrFutureBlock = errors.New("block in the future")
diff --git a/consensus/ethash/algorithm.go b/consensus/ethash/algorithm.go
index 76f19252f..10767bb31 100644
--- a/consensus/ethash/algorithm.go
+++ b/consensus/ethash/algorithm.go
@@ -355,9 +355,11 @@ func hashimotoFull(dataset []uint32, hash []byte, nonce uint64) ([]byte, []byte)
return hashimoto(hash, nonce, uint64(len(dataset))*4, lookup)
}
+const maxEpoch = 2048
+
// datasetSizes is a lookup table for the ethash dataset size for the first 2048
// epochs (i.e. 61440000 blocks).
-var datasetSizes = []uint64{
+var datasetSizes = [maxEpoch]uint64{
1073739904, 1082130304, 1090514816, 1098906752, 1107293056,
1115684224, 1124070016, 1132461952, 1140849536, 1149232768,
1157627776, 1166013824, 1174404736, 1182786944, 1191180416,
@@ -771,7 +773,7 @@ var datasetSizes = []uint64{
// cacheSizes is a lookup table for the ethash verification cache size for the
// first 2048 epochs (i.e. 61440000 blocks).
-var cacheSizes = []uint64{
+var cacheSizes = [maxEpoch]uint64{
16776896, 16907456, 17039296, 17170112, 17301056, 17432512, 17563072,
17693888, 17824192, 17955904, 18087488, 18218176, 18349504, 18481088,
18611392, 18742336, 18874304, 19004224, 19135936, 19267264, 19398208,
diff --git a/consensus/ethash/algorithm_go1.7.go b/consensus/ethash/algorithm_go1.7.go
index c34d041c3..c7f7f48e4 100644
--- a/consensus/ethash/algorithm_go1.7.go
+++ b/consensus/ethash/algorithm_go1.7.go
@@ -25,7 +25,7 @@ package ethash
func cacheSize(block uint64) uint64 {
// If we have a pre-generated value, use that
epoch := int(block / epochLength)
- if epoch < len(cacheSizes) {
+ if epoch < maxEpoch {
return cacheSizes[epoch]
}
// We don't have a way to verify primes fast before Go 1.8
@@ -39,7 +39,7 @@ func cacheSize(block uint64) uint64 {
func datasetSize(block uint64) uint64 {
// If we have a pre-generated value, use that
epoch := int(block / epochLength)
- if epoch < len(datasetSizes) {
+ if epoch < maxEpoch {
return datasetSizes[epoch]
}
// We don't have a way to verify primes fast before Go 1.8
diff --git a/consensus/ethash/algorithm_go1.8.go b/consensus/ethash/algorithm_go1.8.go
index d691b758f..975fdffe5 100644
--- a/consensus/ethash/algorithm_go1.8.go
+++ b/consensus/ethash/algorithm_go1.8.go
@@ -20,17 +20,20 @@ package ethash
import "math/big"
-// cacheSize calculates and returns the size of the ethash verification cache that
-// belongs to a certain block number. The cache size grows linearly, however, we
-// always take the highest prime below the linearly growing threshold in order to
-// reduce the risk of accidental regularities leading to cyclic behavior.
+// cacheSize returns the size of the ethash verification cache that belongs to a certain
+// block number.
func cacheSize(block uint64) uint64 {
- // If we have a pre-generated value, use that
epoch := int(block / epochLength)
- if epoch < len(cacheSizes) {
+ if epoch < maxEpoch {
return cacheSizes[epoch]
}
- // No known cache size, calculate manually (sanity branch only)
+ return calcCacheSize(epoch)
+}
+
+// calcCacheSize calculates the cache size for epoch. The cache size grows linearly,
+// however, we always take the highest prime below the linearly growing threshold in order
+// to reduce the risk of accidental regularities leading to cyclic behavior.
+func calcCacheSize(epoch int) uint64 {
size := cacheInitBytes + cacheGrowthBytes*uint64(epoch) - hashBytes
for !new(big.Int).SetUint64(size / hashBytes).ProbablyPrime(1) { // Always accurate for n < 2^64
size -= 2 * hashBytes
@@ -38,17 +41,20 @@ func cacheSize(block uint64) uint64 {
return size
}
-// datasetSize calculates and returns the size of the ethash mining dataset that
-// belongs to a certain block number. The dataset size grows linearly, however, we
-// always take the highest prime below the linearly growing threshold in order to
-// reduce the risk of accidental regularities leading to cyclic behavior.
+// datasetSize returns the size of the ethash mining dataset that belongs to a certain
+// block number.
func datasetSize(block uint64) uint64 {
- // If we have a pre-generated value, use that
epoch := int(block / epochLength)
- if epoch < len(datasetSizes) {
+ if epoch < maxEpoch {
return datasetSizes[epoch]
}
- // No known dataset size, calculate manually (sanity branch only)
+ return calcDatasetSize(epoch)
+}
+
+// calcDatasetSize calculates the dataset size for epoch. The dataset size grows linearly,
+// however, we always take the highest prime below the linearly growing threshold in order
+// to reduce the risk of accidental regularities leading to cyclic behavior.
+func calcDatasetSize(epoch int) uint64 {
size := datasetInitBytes + datasetGrowthBytes*uint64(epoch) - mixBytes
for !new(big.Int).SetUint64(size / mixBytes).ProbablyPrime(1) { // Always accurate for n < 2^64
size -= 2 * mixBytes
diff --git a/consensus/ethash/algorithm_go1.8_test.go b/consensus/ethash/algorithm_go1.8_test.go
index a822944a6..6648bd6a9 100644
--- a/consensus/ethash/algorithm_go1.8_test.go
+++ b/consensus/ethash/algorithm_go1.8_test.go
@@ -23,24 +23,15 @@ import "testing"
// Tests whether the dataset size calculator works correctly by cross checking the
// hard coded lookup table with the value generated by it.
func TestSizeCalculations(t *testing.T) {
- var tests []uint64
-
- // Verify all the cache sizes from the lookup table
- defer func(sizes []uint64) { cacheSizes = sizes }(cacheSizes)
- tests, cacheSizes = cacheSizes, []uint64{}
-
- for i, test := range tests {
- if size := cacheSize(uint64(i*epochLength) + 1); size != test {
- t.Errorf("cache %d: cache size mismatch: have %d, want %d", i, size, test)
+ // Verify all the cache and dataset sizes from the lookup table.
+ for epoch, want := range cacheSizes {
+ if size := calcCacheSize(epoch); size != want {
+ t.Errorf("cache %d: cache size mismatch: have %d, want %d", epoch, size, want)
}
}
- // Verify all the dataset sizes from the lookup table
- defer func(sizes []uint64) { datasetSizes = sizes }(datasetSizes)
- tests, datasetSizes = datasetSizes, []uint64{}
-
- for i, test := range tests {
- if size := datasetSize(uint64(i*epochLength) + 1); size != test {
- t.Errorf("dataset %d: dataset size mismatch: have %d, want %d", i, size, test)
+ for epoch, want := range datasetSizes {
+ if size := calcDatasetSize(epoch); size != want {
+ t.Errorf("dataset %d: dataset size mismatch: have %d, want %d", epoch, size, want)
}
}
}
diff --git a/consensus/ethash/algorithm_test.go b/consensus/ethash/algorithm_test.go
index 7765ff9fe..a54f3b582 100644
--- a/consensus/ethash/algorithm_test.go
+++ b/consensus/ethash/algorithm_test.go
@@ -688,8 +688,8 @@ func TestConcurrentDiskCacheGeneration(t *testing.T) {
TxHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),
ReceiptHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),
Difficulty: big.NewInt(167925187834220),
- GasLimit: big.NewInt(4015682),
- GasUsed: big.NewInt(0),
+ GasLimit: 4015682,
+ GasUsed: 0,
Time: big.NewInt(1488928920),
Extra: []byte("www.bw.com"),
MixDigest: common.HexToHash("0x3e140b0784516af5e5ec6730f2fb20cca22f32be399b9e4ad77d32541f798cd0"),
diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go
index 5fe67c851..92a23d4a4 100644
--- a/consensus/ethash/consensus.go
+++ b/consensus/ethash/consensus.go
@@ -246,24 +246,24 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *
return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected)
}
// Verify that the gas limit is <= 2^63-1
- if header.GasLimit.Cmp(math.MaxBig63) > 0 {
- return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, math.MaxBig63)
+ cap := uint64(0x7fffffffffffffff)
+ if header.GasLimit > cap {
+ return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
}
// Verify that the gasUsed is <= gasLimit
- if header.GasUsed.Cmp(header.GasLimit) > 0 {
- return fmt.Errorf("invalid gasUsed: have %v, gasLimit %v", header.GasUsed, header.GasLimit)
+ if header.GasUsed > header.GasLimit {
+ return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
}
// Verify that the gas limit remains within allowed bounds
- diff := new(big.Int).Set(parent.GasLimit)
- diff = diff.Sub(diff, header.GasLimit)
- diff.Abs(diff)
-
- limit := new(big.Int).Set(parent.GasLimit)
- limit = limit.Div(limit, params.GasLimitBoundDivisor)
+ diff := int64(parent.GasLimit) - int64(header.GasLimit)
+ if diff < 0 {
+ diff *= -1
+ }
+ limit := parent.GasLimit / params.GasLimitBoundDivisor
- if diff.Cmp(limit) >= 0 || header.GasLimit.Cmp(params.MinGasLimit) < 0 {
- return fmt.Errorf("invalid gas limit: have %v, want %v += %v", header.GasLimit, parent.GasLimit, limit)
+ if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit {
+ return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit)
}
// Verify that the block number is parent's +1
if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 {
@@ -347,7 +347,7 @@ func calcDifficultyByzantium(time uint64, parent *types.Header) *big.Int {
if x.Cmp(bigMinus99) < 0 {
x.Set(bigMinus99)
}
- // (parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
+ // parent_diff + (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99))
y.Div(parent.Difficulty, params.DifficultyBoundDivisor)
x.Mul(y, x)
x.Add(parent.Difficulty, x)
@@ -381,7 +381,7 @@ func calcDifficultyByzantium(time uint64, parent *types.Header) *big.Int {
// the difficulty that a new block should have when created at time given the
// parent block's time and difficulty. The calculation uses the Homestead rules.
func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int {
- // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.mediawiki
+ // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md
// algorithm:
// diff = (parent_diff +
// (parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
@@ -476,7 +476,7 @@ func (ethash *Ethash) VerifySeal(chain consensus.ChainReader, header *types.Head
}
// Sanity check that the block number is below the lookup table size (60M blocks)
number := header.Number.Uint64()
- if number/epochLength >= uint64(len(cacheSizes)) {
+ if number/epochLength >= maxEpoch {
// Go < 1.7 cannot calculate new cache/dataset sizes (no fast prime check)
return errNonceOutOfRange
}
@@ -484,14 +484,18 @@ func (ethash *Ethash) VerifySeal(chain consensus.ChainReader, header *types.Head
if header.Difficulty.Sign() <= 0 {
return errInvalidDifficulty
}
+
// Recompute the digest and PoW value and verify against the header
cache := ethash.cache(number)
-
size := datasetSize(number)
if ethash.config.PowMode == ModeTest {
size = 32 * 1024
}
- digest, result := hashimotoLight(size, cache, header.HashNoNonce().Bytes(), header.Nonce.Uint64())
+ digest, result := hashimotoLight(size, cache.cache, header.HashNoNonce().Bytes(), header.Nonce.Uint64())
+ // Caches are unmapped in a finalizer. Ensure that the cache stays live
+ // until after the call to hashimotoLight so it's not unmapped while being used.
+ runtime.KeepAlive(cache)
+
if !bytes.Equal(header.MixDigest[:], digest) {
return errInvalidMixDigest
}
diff --git a/consensus/ethash/ethash.go b/consensus/ethash/ethash.go
index a78b3a895..91e20112a 100644
--- a/consensus/ethash/ethash.go
+++ b/consensus/ethash/ethash.go
@@ -26,6 +26,7 @@ import (
"os"
"path/filepath"
"reflect"
+ "runtime"
"strconv"
"sync"
"time"
@@ -35,6 +36,7 @@ import (
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
+ "github.com/hashicorp/golang-lru/simplelru"
metrics "github.com/rcrowley/go-metrics"
)
@@ -142,32 +144,82 @@ func memoryMapAndGenerate(path string, size uint64, generator func(buffer []uint
return memoryMap(path)
}
+// lru tracks caches or datasets by their last use time, keeping at most N of them.
+type lru struct {
+ what string
+ new func(epoch uint64) interface{}
+ mu sync.Mutex
+ // Items are kept in a LRU cache, but there is a special case:
+ // We always keep an item for (highest seen epoch) + 1 as the 'future item'.
+ cache *simplelru.LRU
+ future uint64
+ futureItem interface{}
+}
+
+// newlru create a new least-recently-used cache for ither the verification caches
+// or the mining datasets.
+func newlru(what string, maxItems int, new func(epoch uint64) interface{}) *lru {
+ if maxItems <= 0 {
+ maxItems = 1
+ }
+ cache, _ := simplelru.NewLRU(maxItems, func(key, value interface{}) {
+ log.Trace("Evicted ethash "+what, "epoch", key)
+ })
+ return &lru{what: what, new: new, cache: cache}
+}
+
+// get retrieves or creates an item for the given epoch. The first return value is always
+// non-nil. The second return value is non-nil if lru thinks that an item will be useful in
+// the near future.
+func (lru *lru) get(epoch uint64) (item, future interface{}) {
+ lru.mu.Lock()
+ defer lru.mu.Unlock()
+
+ // Get or create the item for the requested epoch.
+ item, ok := lru.cache.Get(epoch)
+ if !ok {
+ if lru.future > 0 && lru.future == epoch {
+ item = lru.futureItem
+ } else {
+ log.Trace("Requiring new ethash "+lru.what, "epoch", epoch)
+ item = lru.new(epoch)
+ }
+ lru.cache.Add(epoch, item)
+ }
+ // Update the 'future item' if epoch is larger than previously seen.
+ if epoch < maxEpoch-1 && lru.future < epoch+1 {
+ log.Trace("Requiring new future ethash "+lru.what, "epoch", epoch+1)
+ future = lru.new(epoch + 1)
+ lru.future = epoch + 1
+ lru.futureItem = future
+ }
+ return item, future
+}
+
// cache wraps an ethash cache with some metadata to allow easier concurrent use.
type cache struct {
- epoch uint64 // Epoch for which this cache is relevant
-
- dump *os.File // File descriptor of the memory mapped cache
- mmap mmap.MMap // Memory map itself to unmap before releasing
+ epoch uint64 // Epoch for which this cache is relevant
+ dump *os.File // File descriptor of the memory mapped cache
+ mmap mmap.MMap // Memory map itself to unmap before releasing
+ cache []uint32 // The actual cache data content (may be memory mapped)
+ once sync.Once // Ensures the cache is generated only once
+}
- cache []uint32 // The actual cache data content (may be memory mapped)
- used time.Time // Timestamp of the last use for smarter eviction
- once sync.Once // Ensures the cache is generated only once
- lock sync.Mutex // Ensures thread safety for updating the usage time
+// newCache creates a new ethash verification cache and returns it as a plain Go
+// interface to be usable in an LRU cache.
+func newCache(epoch uint64) interface{} {
+ return &cache{epoch: epoch}
}
// generate ensures that the cache content is generated before use.
func (c *cache) generate(dir string, limit int, test bool) {
c.once.Do(func() {
- // If we have a testing cache, generate and return
- if test {
- c.cache = make([]uint32, 1024/4)
- generateCache(c.cache, c.epoch, seedHash(c.epoch*epochLength+1))
- return
- }
- // If we don't store anything on disk, generate and return
size := cacheSize(c.epoch*epochLength + 1)
seed := seedHash(c.epoch*epochLength + 1)
-
+ if test {
+ size = 1024
+ }
+ // If we don't store anything on disk, generate and return.
if dir == "" {
c.cache = make([]uint32, size/4)
generateCache(c.cache, c.epoch, seed)
@@ -181,6 +233,10 @@ func (c *cache) generate(dir string, limit int, test bool) {
path := filepath.Join(dir, fmt.Sprintf("cache-R%d-%x%s", algorithmRevision, seed[:8], endian))
logger := log.New("epoch", c.epoch)
+ // We're about to mmap the file, ensure that the mapping is cleaned up when the
+ // cache becomes unused.
+ runtime.SetFinalizer(c, (*cache).finalizer)
+
// Try to load the file from disk and memory map it
var err error
c.dump, c.mmap, c.cache, err = memoryMap(path)
@@ -207,49 +263,41 @@ func (c *cache) generate(dir string, limit int, test bool) {
})
}
-// release closes any file handlers and memory maps open.
-func (c *cache) release() {
+// finalizer unmaps the memory and closes the file.
+func (c *cache) finalizer() {
if c.mmap != nil {
c.mmap.Unmap()
- c.mmap = nil
- }
- if c.dump != nil {
c.dump.Close()
- c.dump = nil
+ c.mmap, c.dump = nil, nil
}
}
// dataset wraps an ethash dataset with some metadata to allow easier concurrent use.
type dataset struct {
- epoch uint64 // Epoch for which this cache is relevant
-
- dump *os.File // File descriptor of the memory mapped cache
- mmap mmap.MMap // Memory map itself to unmap before releasing
+ epoch uint64 // Epoch for which this cache is relevant
+ dump *os.File // File descriptor of the memory mapped cache
+ mmap mmap.MMap // Memory map itself to unmap before releasing
+ dataset []uint32 // The actual cache data content
+ once sync.Once // Ensures the cache is generated only once
+}
- dataset []uint32 // The actual cache data content
- used time.Time // Timestamp of the last use for smarter eviction
- once sync.Once // Ensures the cache is generated only once
- lock sync.Mutex // Ensures thread safety for updating the usage time
+// newDataset creates a new ethash mining dataset and returns it as a plain Go
+// interface to be usable in an LRU cache.
+func newDataset(epoch uint64) interface{} {
+ return &dataset{epoch: epoch}
}
// generate ensures that the dataset content is generated before use.
func (d *dataset) generate(dir string, limit int, test bool) {
d.once.Do(func() {
- // If we have a testing dataset, generate and return
- if test {
- cache := make([]uint32, 1024/4)
- generateCache(cache, d.epoch, seedHash(d.epoch*epochLength+1))
-
- d.dataset = make([]uint32, 32*1024/4)
- generateDataset(d.dataset, d.epoch, cache)
-
- return
- }
- // If we don't store anything on disk, generate and return
csize := cacheSize(d.epoch*epochLength + 1)
dsize := datasetSize(d.epoch*epochLength + 1)
seed := seedHash(d.epoch*epochLength + 1)
-
+ if test {
+ csize = 1024
+ dsize = 32 * 1024
+ }
+ // If we don't store anything on disk, generate and return
if dir == "" {
cache := make([]uint32, csize/4)
generateCache(cache, d.epoch, seed)
@@ -265,6 +313,10 @@ func (d *dataset) generate(dir string, limit int, test bool) {
path := filepath.Join(dir, fmt.Sprintf("full-R%d-%x%s", algorithmRevision, seed[:8], endian))
logger := log.New("epoch", d.epoch)
+ // We're about to mmap the file, ensure that the mapping is cleaned up when the
+ // cache becomes unused.
+ runtime.SetFinalizer(d, (*dataset).finalizer)
+
// Try to load the file from disk and memory map it
var err error
d.dump, d.mmap, d.dataset, err = memoryMap(path)
@@ -294,15 +346,12 @@ func (d *dataset) generate(dir string, limit int, test bool) {
})
}
-// release closes any file handlers and memory maps open.
-func (d *dataset) release() {
+// finalizer closes any file handlers and memory maps open.
+func (d *dataset) finalizer() {
if d.mmap != nil {
d.mmap.Unmap()
- d.mmap = nil
- }
- if d.dump != nil {
d.dump.Close()
- d.dump = nil
+ d.mmap, d.dump = nil, nil
}
}
@@ -310,14 +359,12 @@ func (d *dataset) release() {
func MakeCache(block uint64, dir string) {
c := cache{epoch: block / epochLength}
c.generate(dir, math.MaxInt32, false)
- c.release()
}
// MakeDataset generates a new ethash dataset and optionally stores it to disk.
func MakeDataset(block uint64, dir string) {
d := dataset{epoch: block / epochLength}
d.generate(dir, math.MaxInt32, false)
- d.release()
}
// Mode defines the type and amount of PoW verification an ethash engine makes.
@@ -347,10 +394,8 @@ type Config struct {
type Ethash struct {
config Config
- caches map[uint64]*cache // In memory caches to avoid regenerating too often
- fcache *cache // Pre-generated cache for the estimated future epoch
- datasets map[uint64]*dataset // In memory datasets to avoid regenerating too often
- fdataset *dataset // Pre-generated dataset for the estimated future epoch
+ caches *lru // In memory caches to avoid regenerating too often
+ datasets *lru // In memory datasets to avoid regenerating too often
// Mining related fields
rand *rand.Rand // Properly seeded random source for nonces
@@ -380,8 +425,8 @@ func New(config Config) *Ethash {
}
return &Ethash{
config: config,
- caches: make(map[uint64]*cache),
- datasets: make(map[uint64]*dataset),
+ caches: newlru("cache", config.CachesInMem, newCache),
+ datasets: newlru("dataset", config.DatasetsInMem, newDataset),
update: make(chan struct{}),
hashrate: metrics.NewMeter(),
}
@@ -390,16 +435,7 @@ func New(config Config) *Ethash {
// NewTester creates a small sized ethash PoW scheme useful only for testing
// purposes.
func NewTester() *Ethash {
- return &Ethash{
- config: Config{
- CachesInMem: 1,
- PowMode: ModeTest,
- },
- caches: make(map[uint64]*cache),
- datasets: make(map[uint64]*dataset),
- update: make(chan struct{}),
- hashrate: metrics.NewMeter(),
- }
+ return New(Config{CachesInMem: 1, PowMode: ModeTest})
}
// NewFaker creates a ethash consensus engine with a fake PoW scheme that accepts
@@ -456,126 +492,40 @@ func NewShared() *Ethash {
// cache tries to retrieve a verification cache for the specified block number
// by first checking against a list of in-memory caches, then against caches
// stored on disk, and finally generating one if none can be found.
-func (ethash *Ethash) cache(block uint64) []uint32 {
+func (ethash *Ethash) cache(block uint64) *cache {
epoch := block / epochLength
+ currentI, futureI := ethash.caches.get(epoch)
+ current := currentI.(*cache)
- // If we have a PoW for that epoch, use that
- ethash.lock.Lock()
-
- current, future := ethash.caches[epoch], (*cache)(nil)
- if current == nil {
- // No in-memory cache, evict the oldest if the cache limit was reached
- for len(ethash.caches) > 0 && len(ethash.caches) >= ethash.config.CachesInMem {
- var evict *cache
- for _, cache := range ethash.caches {
- if evict == nil || evict.used.After(cache.used) {
- evict = cache
- }
- }
- delete(ethash.caches, evict.epoch)
- evict.release()
-
- log.Trace("Evicted ethash cache", "epoch", evict.epoch, "used", evict.used)
- }
- // If we have the new cache pre-generated, use that, otherwise create a new one
- if ethash.fcache != nil && ethash.fcache.epoch == epoch {
- log.Trace("Using pre-generated cache", "epoch", epoch)
- current, ethash.fcache = ethash.fcache, nil
- } else {
- log.Trace("Requiring new ethash cache", "epoch", epoch)
- current = &cache{epoch: epoch}
- }
- ethash.caches[epoch] = current
-
- // If we just used up the future cache, or need a refresh, regenerate
- if ethash.fcache == nil || ethash.fcache.epoch <= epoch {
- if ethash.fcache != nil {
- ethash.fcache.release()
- }
- log.Trace("Requiring new future ethash cache", "epoch", epoch+1)
- future = &cache{epoch: epoch + 1}
- ethash.fcache = future
- }
- // New current cache, set its initial timestamp
- current.used = time.Now()
- }
- ethash.lock.Unlock()
-
- // Wait for generation finish, bump the timestamp and finalize the cache
+ // Wait for generation finish.
current.generate(ethash.config.CacheDir, ethash.config.CachesOnDisk, ethash.config.PowMode == ModeTest)
- current.lock.Lock()
- current.used = time.Now()
- current.lock.Unlock()
-
- // If we exhausted the future cache, now's a good time to regenerate it
- if future != nil {
+ // If we need a new future cache, now's a good time to regenerate it.
+ if futureI != nil {
+ future := futureI.(*cache)
go future.generate(ethash.config.CacheDir, ethash.config.CachesOnDisk, ethash.config.PowMode == ModeTest)
}
- return current.cache
+ return current
}
// dataset tries to retrieve a mining dataset for the specified block number
// by first checking against a list of in-memory datasets, then against DAGs
// stored on disk, and finally generating one if none can be found.
-func (ethash *Ethash) dataset(block uint64) []uint32 {
+func (ethash *Ethash) dataset(block uint64) *dataset {
epoch := block / epochLength
+ currentI, futureI := ethash.datasets.get(epoch)
+ current := currentI.(*dataset)
- // If we have a PoW for that epoch, use that
- ethash.lock.Lock()
-
- current, future := ethash.datasets[epoch], (*dataset)(nil)
- if current == nil {
- // No in-memory dataset, evict the oldest if the dataset limit was reached
- for len(ethash.datasets) > 0 && len(ethash.datasets) >= ethash.config.DatasetsInMem {
- var evict *dataset
- for _, dataset := range ethash.datasets {
- if evict == nil || evict.used.After(dataset.used) {
- evict = dataset
- }
- }
- delete(ethash.datasets, evict.epoch)
- evict.release()
-
- log.Trace("Evicted ethash dataset", "epoch", evict.epoch, "used", evict.used)
- }
- // If we have the new cache pre-generated, use that, otherwise create a new one
- if ethash.fdataset != nil && ethash.fdataset.epoch == epoch {
- log.Trace("Using pre-generated dataset", "epoch", epoch)
- current = &dataset{epoch: ethash.fdataset.epoch} // Reload from disk
- ethash.fdataset = nil
- } else {
- log.Trace("Requiring new ethash dataset", "epoch", epoch)
- current = &dataset{epoch: epoch}
- }
- ethash.datasets[epoch] = current
-
- // If we just used up the future dataset, or need a refresh, regenerate
- if ethash.fdataset == nil || ethash.fdataset.epoch <= epoch {
- if ethash.fdataset != nil {
- ethash.fdataset.release()
- }
- log.Trace("Requiring new future ethash dataset", "epoch", epoch+1)
- future = &dataset{epoch: epoch + 1}
- ethash.fdataset = future
- }
- // New current dataset, set its initial timestamp
- current.used = time.Now()
- }
- ethash.lock.Unlock()
-
- // Wait for generation finish, bump the timestamp and finalize the cache
+ // Wait for generation finish.
current.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.PowMode == ModeTest)
- current.lock.Lock()
- current.used = time.Now()
- current.lock.Unlock()
-
- // If we exhausted the future dataset, now's a good time to regenerate it
- if future != nil {
+ // If we need a new future dataset, now's a good time to regenerate it.
+ if futureI != nil {
+ future := futureI.(*dataset)
go future.generate(ethash.config.DatasetDir, ethash.config.DatasetsOnDisk, ethash.config.PowMode == ModeTest)
}
- return current.dataset
+
+ return current
}
// Threads returns the number of mining threads currently enabled. This doesn't
diff --git a/consensus/ethash/ethash_test.go b/consensus/ethash/ethash_test.go
index b3a2f32f7..31116da43 100644
--- a/consensus/ethash/ethash_test.go
+++ b/consensus/ethash/ethash_test.go
@@ -17,7 +17,11 @@
package ethash
import (
+ "io/ioutil"
"math/big"
+ "math/rand"
+ "os"
+ "sync"
"testing"
"github.com/ethereum/go-ethereum/core/types"
@@ -38,3 +42,38 @@ func TestTestMode(t *testing.T) {
t.Fatalf("unexpected verification error: %v", err)
}
}
+
+// This test checks that cache lru logic doesn't crash under load.
+// It reproduces https://github.com/ethereum/go-ethereum/issues/14943
+func TestCacheFileEvict(t *testing.T) {
+ tmpdir, err := ioutil.TempDir("", "ethash-test")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpdir)
+ e := New(Config{CachesInMem: 3, CachesOnDisk: 10, CacheDir: tmpdir, PowMode: ModeTest})
+
+ workers := 8
+ epochs := 100
+ var wg sync.WaitGroup
+ wg.Add(workers)
+ for i := 0; i < workers; i++ {
+ go verifyTest(&wg, e, i, epochs)
+ }
+ wg.Wait()
+}
+
+func verifyTest(wg *sync.WaitGroup, e *Ethash, workerIndex, epochs int) {
+ defer wg.Done()
+
+ const wiggle = 4 * epochLength
+ r := rand.New(rand.NewSource(int64(workerIndex)))
+ for epoch := 0; epoch < epochs; epoch++ {
+ block := int64(epoch)*epochLength - wiggle/2 + r.Int63n(wiggle)
+ if block < 0 {
+ block = 0
+ }
+ head := &types.Header{Number: big.NewInt(block), Difficulty: big.NewInt(100)}
+ e.VerifySeal(nil, head)
+ }
+}
diff --git a/consensus/ethash/sealer.go b/consensus/ethash/sealer.go
index c2447e473..b5e742d8b 100644
--- a/consensus/ethash/sealer.go
+++ b/consensus/ethash/sealer.go
@@ -97,10 +97,9 @@ func (ethash *Ethash) Seal(chain consensus.ChainReader, block *types.Block, stop
func (ethash *Ethash) mine(block *types.Block, id int, seed uint64, abort chan struct{}, found chan *types.Block) {
// Extract some data from the header
var (
- header = block.Header()
- hash = header.HashNoNonce().Bytes()
- target = new(big.Int).Div(maxUint256, header.Difficulty)
-
+ header = block.Header()
+ hash = header.HashNoNonce().Bytes()
+ target = new(big.Int).Div(maxUint256, header.Difficulty)
number = header.Number.Uint64()
dataset = ethash.dataset(number)
)
@@ -111,13 +110,14 @@ func (ethash *Ethash) mine(block *types.Block, id int, seed uint64, abort chan s
)
logger := log.New("miner", id)
logger.Trace("Started ethash search for new nonces", "seed", seed)
+search:
for {
select {
case <-abort:
// Mining terminated, update stats and abort
logger.Trace("Ethash nonce search aborted", "attempts", nonce-seed)
ethash.hashrate.Mark(attempts)
- return
+ break search
default:
// We don't have to update hash rate on every nonce, so update after after 2^X nonces
@@ -127,7 +127,7 @@ func (ethash *Ethash) mine(block *types.Block, id int, seed uint64, abort chan s
attempts = 0
}
// Compute the PoW value of this nonce
- digest, result := hashimotoFull(dataset, hash, nonce)
+ digest, result := hashimotoFull(dataset.dataset, hash, nonce)
if new(big.Int).SetBytes(result).Cmp(target) <= 0 {
// Correct nonce found, create a new header with it
header = types.CopyHeader(header)
@@ -141,9 +141,12 @@ func (ethash *Ethash) mine(block *types.Block, id int, seed uint64, abort chan s
case <-abort:
logger.Trace("Ethash nonce found but discarded", "attempts", nonce-seed, "nonce", nonce)
}
- return
+ break search
}
nonce++
}
}
+ // Datasets are unmapped in a finalizer. Ensure that the dataset stays live
+ // during sealing so it's not unmapped while being read.
+ runtime.KeepAlive(dataset)
}
diff --git a/console/console.go b/console/console.go
index 52fe1f542..b280d4e65 100644
--- a/console/console.go
+++ b/console/console.go
@@ -26,6 +26,7 @@ import (
"regexp"
"sort"
"strings"
+ "syscall"
"github.com/ethereum/go-ethereum/internal/jsre"
"github.com/ethereum/go-ethereum/internal/web3ext"
@@ -332,7 +333,7 @@ func (c *Console) Interactive() {
}()
// Monitor Ctrl-C too in case the input is empty and we need to bail
abort := make(chan os.Signal, 1)
- signal.Notify(abort, os.Interrupt)
+ signal.Notify(abort, syscall.SIGINT, syscall.SIGTERM)
// Start sending prompts to the user and reading back inputs
for {
diff --git a/console/prompter.go b/console/prompter.go
index ea03694d4..c477b4817 100644
--- a/console/prompter.go
+++ b/console/prompter.go
@@ -155,8 +155,7 @@ func (p *terminalPrompter) SetHistory(history []string) {
p.State.ReadHistory(strings.NewReader(strings.Join(history, "\n")))
}
-// AppendHistory appends an entry to the scrollback history. It should be called
-// if and only if the prompt to append was a valid command.
+// AppendHistory appends an entry to the scrollback history.
func (p *terminalPrompter) AppendHistory(command string) {
p.State.AppendHistory(command)
}
diff --git a/containers/docker/develop-alpine/Dockerfile b/containers/docker/develop-alpine/Dockerfile
index d239129d5..1f3e1112e 100644
--- a/containers/docker/develop-alpine/Dockerfile
+++ b/containers/docker/develop-alpine/Dockerfile
@@ -1,4 +1,4 @@
-FROM alpine:3.5
+FROM alpine:3.7
RUN \
apk add --update go git make gcc musl-dev linux-headers ca-certificates && \
diff --git a/containers/docker/develop-ubuntu/Dockerfile b/containers/docker/develop-ubuntu/Dockerfile
index c79becb55..8c4fe9f59 100644
--- a/containers/docker/develop-ubuntu/Dockerfile
+++ b/containers/docker/develop-ubuntu/Dockerfile
@@ -1,12 +1,14 @@
FROM ubuntu:xenial
+ENV PATH=/usr/lib/go-1.9/bin:$PATH
+
RUN \
apt-get update && apt-get upgrade -q -y && \
- apt-get install -y --no-install-recommends golang git make gcc libc-dev ca-certificates && \
+ apt-get install -y --no-install-recommends golang-1.9 git make gcc libc-dev ca-certificates && \
git clone --depth 1 https://github.com/ethereum/go-ethereum && \
(cd go-ethereum && make geth) && \
cp go-ethereum/build/bin/geth /geth && \
- apt-get remove -y golang git make gcc libc-dev && apt autoremove -y && apt-get clean && \
+ apt-get remove -y golang-1.9 git make gcc libc-dev && apt autoremove -y && apt-get clean && \
rm -rf /go-ethereum
EXPOSE 8545
diff --git a/containers/docker/master-alpine/Dockerfile b/containers/docker/master-alpine/Dockerfile
index 44402361d..8d4e7fe81 100644
--- a/containers/docker/master-alpine/Dockerfile
+++ b/containers/docker/master-alpine/Dockerfile
@@ -1,8 +1,8 @@
-FROM alpine:3.5
+FROM alpine:3.7
RUN \
apk add --update go git make gcc musl-dev linux-headers ca-certificates && \
- git clone --depth 1 --branch release/1.7 https://github.com/ethereum/go-ethereum && \
+ git clone --depth 1 --branch release/1.8 https://github.com/ethereum/go-ethereum && \
(cd go-ethereum && make geth) && \
cp go-ethereum/build/bin/geth /geth && \
apk del go git make gcc musl-dev linux-headers && \
diff --git a/containers/docker/master-ubuntu/Dockerfile b/containers/docker/master-ubuntu/Dockerfile
index cc4fad10c..4cfc4f58c 100644
--- a/containers/docker/master-ubuntu/Dockerfile
+++ b/containers/docker/master-ubuntu/Dockerfile
@@ -1,12 +1,14 @@
FROM ubuntu:xenial
+ENV PATH=/usr/lib/go-1.9/bin:$PATH
+
RUN \
apt-get update && apt-get upgrade -q -y && \
- apt-get install -y --no-install-recommends golang git make gcc libc-dev ca-certificates && \
- git clone --depth 1 --branch release/1.7 https://github.com/ethereum/go-ethereum && \
+ apt-get install -y --no-install-recommends golang-1.9 git make gcc libc-dev ca-certificates && \
+ git clone --depth 1 --branch release/1.8 https://github.com/ethereum/go-ethereum && \
(cd go-ethereum && make geth) && \
cp go-ethereum/build/bin/geth /geth && \
- apt-get remove -y golang git make gcc libc-dev && apt autoremove -y && apt-get clean && \
+ apt-get remove -y golang-1.9 git make gcc libc-dev && apt autoremove -y && apt-get clean && \
rm -rf /go-ethereum
EXPOSE 8545
diff --git a/contracts/chequebook/cheque.go b/contracts/chequebook/cheque.go
index 09daa9248..92bd896e0 100644
--- a/contracts/chequebook/cheque.go
+++ b/contracts/chequebook/cheque.go
@@ -21,7 +21,7 @@
// as well as (auto)depositing ether to the chequebook contract.
package chequebook
-//go:generate abigen --sol contract/chequebook.sol --pkg contract --out contract/chequebook.go
+//go:generate abigen --sol contract/chequebook.sol --exc contract/mortal.sol:mortal,contract/owned.sol:owned --pkg contract --out contract/chequebook.go
//go:generate go run ./gencode.go
import (
@@ -56,8 +56,8 @@ import (
// * watching incoming ether
var (
- gasToCash = big.NewInt(2000000) // gas cost of a cash transaction using chequebook
- // gasToDeploy = big.NewInt(3000000)
+ gasToCash = uint64(2000000) // gas cost of a cash transaction using chequebook
+ // gasToDeploy = uint64(3000000)
)
// Backend wraps all methods required for chequebook operation.
diff --git a/contracts/chequebook/contract/chequebook.go b/contracts/chequebook/contract/chequebook.go
index 47090152c..e275ac9b8 100644
--- a/contracts/chequebook/contract/chequebook.go
+++ b/contracts/chequebook/contract/chequebook.go
@@ -1,5 +1,5 @@
-// This file is an automatically generated Go binding. Do not modify as any
-// change will likely be lost upon the next re-generation!
+// Code generated - DO NOT EDIT.
+// This file is a generated binding and any manual changes will be lost.
package contract
@@ -7,17 +7,19 @@ import (
"math/big"
"strings"
+ ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/event"
)
// ChequebookABI is the input ABI used to generate the binding from.
-const ChequebookABI = `[{"constant":false,"inputs":[],"name":"kill","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"sent","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"beneficiary","type":"address"},{"name":"amount","type":"uint256"},{"name":"sig_v","type":"uint8"},{"name":"sig_r","type":"bytes32"},{"name":"sig_s","type":"bytes32"}],"name":"cash","outputs":[],"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"deadbeat","type":"address"}],"name":"Overdraft","type":"event"}]`
+const ChequebookABI = "[{\"constant\":false,\"inputs\":[],\"name\":\"kill\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"sent\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"beneficiary\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"sig_v\",\"type\":\"uint8\"},{\"name\":\"sig_r\",\"type\":\"bytes32\"},{\"name\":\"sig_s\",\"type\":\"bytes32\"}],\"name\":\"cash\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"deadbeat\",\"type\":\"address\"}],\"name\":\"Overdraft\",\"type\":\"event\"}]"
// ChequebookBin is the compiled bytecode used for deploying new contracts.
-const ChequebookBin = `0x606060405260008054600160a060020a031916331790556101ff806100246000396000f3606060405260e060020a600035046341c0e1b581146100315780637bf786f814610059578063fbf788d614610071575b005b61002f60005433600160a060020a03908116911614156100bd57600054600160a060020a0316ff5b6100ab60043560016020526000908152604090205481565b61002f600435602435604435606435608435600160a060020a03851660009081526001602052604081205485116100bf575b505050505050565b60408051918252519081900360200190f35b565b50604080516c0100000000000000000000000030600160a060020a0390811682028352881602601482015260288101869052815190819003604801812080825260ff861660208381019190915282840186905260608301859052925190926001926080818101939182900301816000866161da5a03f11561000257505060405151600054600160a060020a0390811691161461015a576100a3565b600160a060020a038681166000908152600160205260409020543090911631908603106101b357604060008181208790559051600160a060020a0388169190819081818181818881f1935050505015156100a357610002565b60005460408051600160a060020a03929092168252517f2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f9789181900360200190a185600160a060020a0316ff`
+const ChequebookBin = `0x606060405260008054600160a060020a033316600160a060020a03199091161790556102ec806100306000396000f3006060604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166341c0e1b581146100585780637bf786f81461006b578063fbf788d61461009c575b005b341561006357600080fd5b6100566100ca565b341561007657600080fd5b61008a600160a060020a03600435166100f1565b60405190815260200160405180910390f35b34156100a757600080fd5b610056600160a060020a036004351660243560ff60443516606435608435610103565b60005433600160a060020a03908116911614156100ef57600054600160a060020a0316ff5b565b60016020526000908152604090205481565b600160a060020a0385166000908152600160205260408120548190861161012957600080fd5b3087876040516c01000000000000000000000000600160a060020a03948516810282529290931690910260148301526028820152604801604051809103902091506001828686866040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f115156101cf57600080fd5b505060206040510351600054600160a060020a039081169116146101f257600080fd5b50600160a060020a03808716600090815260016020526040902054860390301631811161026257600160a060020a0387166000818152600160205260409081902088905582156108fc0290839051600060405180830381858888f19350505050151561025d57600080fd5b6102b7565b6000547f2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f97890600160a060020a0316604051600160a060020a03909116815260200160405180910390a186600160a060020a0316ff5b505050505050505600a165627a7a72305820533e856fc37e3d64d1706bcc7dfb6b1d490c8d566ea498d9d01ec08965a896ca0029`
// DeployChequebook deploys a new Ethereum contract, binding an instance of Chequebook to it.
func DeployChequebook(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Chequebook, error) {
@@ -29,13 +31,14 @@ func DeployChequebook(auth *bind.TransactOpts, backend bind.ContractBackend) (co
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &Chequebook{ChequebookCaller: ChequebookCaller{contract: contract}, ChequebookTransactor: ChequebookTransactor{contract: contract}}, nil
+ return address, tx, &Chequebook{ChequebookCaller: ChequebookCaller{contract: contract}, ChequebookTransactor: ChequebookTransactor{contract: contract}, ChequebookFilterer: ChequebookFilterer{contract: contract}}, nil
}
// Chequebook is an auto generated Go binding around an Ethereum contract.
type Chequebook struct {
ChequebookCaller // Read-only binding to the contract
ChequebookTransactor // Write-only binding to the contract
+ ChequebookFilterer // Log filterer for contract events
}
// ChequebookCaller is an auto generated read-only Go binding around an Ethereum contract.
@@ -48,6 +51,11 @@ type ChequebookTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
+// ChequebookFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
+type ChequebookFilterer struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
// ChequebookSession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type ChequebookSession struct {
@@ -87,16 +95,16 @@ type ChequebookTransactorRaw struct {
// NewChequebook creates a new instance of Chequebook, bound to a specific deployed contract.
func NewChequebook(address common.Address, backend bind.ContractBackend) (*Chequebook, error) {
- contract, err := bindChequebook(address, backend, backend)
+ contract, err := bindChequebook(address, backend, backend, backend)
if err != nil {
return nil, err
}
- return &Chequebook{ChequebookCaller: ChequebookCaller{contract: contract}, ChequebookTransactor: ChequebookTransactor{contract: contract}}, nil
+ return &Chequebook{ChequebookCaller: ChequebookCaller{contract: contract}, ChequebookTransactor: ChequebookTransactor{contract: contract}, ChequebookFilterer: ChequebookFilterer{contract: contract}}, nil
}
// NewChequebookCaller creates a new read-only instance of Chequebook, bound to a specific deployed contract.
func NewChequebookCaller(address common.Address, caller bind.ContractCaller) (*ChequebookCaller, error) {
- contract, err := bindChequebook(address, caller, nil)
+ contract, err := bindChequebook(address, caller, nil, nil)
if err != nil {
return nil, err
}
@@ -105,20 +113,29 @@ func NewChequebookCaller(address common.Address, caller bind.ContractCaller) (*C
// NewChequebookTransactor creates a new write-only instance of Chequebook, bound to a specific deployed contract.
func NewChequebookTransactor(address common.Address, transactor bind.ContractTransactor) (*ChequebookTransactor, error) {
- contract, err := bindChequebook(address, nil, transactor)
+ contract, err := bindChequebook(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &ChequebookTransactor{contract: contract}, nil
}
+// NewChequebookFilterer creates a new log filterer instance of Chequebook, bound to a specific deployed contract.
+func NewChequebookFilterer(address common.Address, filterer bind.ContractFilterer) (*ChequebookFilterer, error) {
+ contract, err := bindChequebook(address, nil, nil, filterer)
+ if err != nil {
+ return nil, err
+ }
+ return &ChequebookFilterer{contract: contract}, nil
+}
+
// bindChequebook binds a generic wrapper to an already deployed contract.
-func bindChequebook(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
+func bindChequebook(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(ChequebookABI))
if err != nil {
return nil, err
}
- return bind.NewBoundContract(address, parsed, caller, transactor), nil
+ return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
@@ -227,315 +244,124 @@ func (_Chequebook *ChequebookTransactorSession) Kill() (*types.Transaction, erro
return _Chequebook.Contract.Kill(&_Chequebook.TransactOpts)
}
-// MortalABI is the input ABI used to generate the binding from.
-const MortalABI = `[{"constant":false,"inputs":[],"name":"kill","outputs":[],"type":"function"}]`
-
-// MortalBin is the compiled bytecode used for deploying new contracts.
-const MortalBin = `0x606060405260008054600160a060020a03191633179055605c8060226000396000f3606060405260e060020a600035046341c0e1b58114601a575b005b60186000543373ffffffffffffffffffffffffffffffffffffffff90811691161415605a5760005473ffffffffffffffffffffffffffffffffffffffff16ff5b56`
-
-// DeployMortal deploys a new Ethereum contract, binding an instance of Mortal to it.
-func DeployMortal(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Mortal, error) {
- parsed, err := abi.JSON(strings.NewReader(MortalABI))
- if err != nil {
- return common.Address{}, nil, nil, err
- }
- address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(MortalBin), backend)
- if err != nil {
- return common.Address{}, nil, nil, err
- }
- return address, tx, &Mortal{MortalCaller: MortalCaller{contract: contract}, MortalTransactor: MortalTransactor{contract: contract}}, nil
-}
-
-// Mortal is an auto generated Go binding around an Ethereum contract.
-type Mortal struct {
- MortalCaller // Read-only binding to the contract
- MortalTransactor // Write-only binding to the contract
-}
-
-// MortalCaller is an auto generated read-only Go binding around an Ethereum contract.
-type MortalCaller struct {
- contract *bind.BoundContract // Generic contract wrapper for the low level calls
-}
-
-// MortalTransactor is an auto generated write-only Go binding around an Ethereum contract.
-type MortalTransactor struct {
- contract *bind.BoundContract // Generic contract wrapper for the low level calls
-}
-
-// MortalSession is an auto generated Go binding around an Ethereum contract,
-// with pre-set call and transact options.
-type MortalSession struct {
- Contract *Mortal // Generic contract binding to set the session for
- CallOpts bind.CallOpts // Call options to use throughout this session
- TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
-}
-
-// MortalCallerSession is an auto generated read-only Go binding around an Ethereum contract,
-// with pre-set call options.
-type MortalCallerSession struct {
- Contract *MortalCaller // Generic contract caller binding to set the session for
- CallOpts bind.CallOpts // Call options to use throughout this session
-}
-
-// MortalTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
-// with pre-set transact options.
-type MortalTransactorSession struct {
- Contract *MortalTransactor // Generic contract transactor binding to set the session for
- TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
-}
-
-// MortalRaw is an auto generated low-level Go binding around an Ethereum contract.
-type MortalRaw struct {
- Contract *Mortal // Generic contract binding to access the raw methods on
-}
-
-// MortalCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
-type MortalCallerRaw struct {
- Contract *MortalCaller // Generic read-only contract binding to access the raw methods on
-}
+// ChequebookOverdraftIterator is returned from FilterOverdraft and is used to iterate over the raw logs and unpacked data for Overdraft events raised by the Chequebook contract.
+type ChequebookOverdraftIterator struct {
+ Event *ChequebookOverdraft // Event containing the contract specifics and raw log
-// MortalTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
-type MortalTransactorRaw struct {
- Contract *MortalTransactor // Generic write-only contract binding to access the raw methods on
-}
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
-// NewMortal creates a new instance of Mortal, bound to a specific deployed contract.
-func NewMortal(address common.Address, backend bind.ContractBackend) (*Mortal, error) {
- contract, err := bindMortal(address, backend, backend)
- if err != nil {
- return nil, err
- }
- return &Mortal{MortalCaller: MortalCaller{contract: contract}, MortalTransactor: MortalTransactor{contract: contract}}, nil
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
}
-// NewMortalCaller creates a new read-only instance of Mortal, bound to a specific deployed contract.
-func NewMortalCaller(address common.Address, caller bind.ContractCaller) (*MortalCaller, error) {
- contract, err := bindMortal(address, caller, nil)
- if err != nil {
- return nil, err
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *ChequebookOverdraftIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
}
- return &MortalCaller{contract: contract}, nil
-}
-
-// NewMortalTransactor creates a new write-only instance of Mortal, bound to a specific deployed contract.
-func NewMortalTransactor(address common.Address, transactor bind.ContractTransactor) (*MortalTransactor, error) {
- contract, err := bindMortal(address, nil, transactor)
- if err != nil {
- return nil, err
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(ChequebookOverdraft)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
}
- return &MortalTransactor{contract: contract}, nil
-}
-
-// bindMortal binds a generic wrapper to an already deployed contract.
-func bindMortal(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
- parsed, err := abi.JSON(strings.NewReader(MortalABI))
- if err != nil {
- return nil, err
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(ChequebookOverdraft)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
}
- return bind.NewBoundContract(address, parsed, caller, transactor), nil
-}
-
-// Call invokes the (constant) contract method with params as input values and
-// sets the output to result. The result type might be a single field for simple
-// returns, a slice of interfaces for anonymous returns and a struct for named
-// returns.
-func (_Mortal *MortalRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
- return _Mortal.Contract.MortalCaller.contract.Call(opts, result, method, params...)
-}
-
-// Transfer initiates a plain transaction to move funds to the contract, calling
-// its default method if one is available.
-func (_Mortal *MortalRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _Mortal.Contract.MortalTransactor.contract.Transfer(opts)
-}
-
-// Transact invokes the (paid) contract method with params as input values.
-func (_Mortal *MortalRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _Mortal.Contract.MortalTransactor.contract.Transact(opts, method, params...)
-}
-
-// Call invokes the (constant) contract method with params as input values and
-// sets the output to result. The result type might be a single field for simple
-// returns, a slice of interfaces for anonymous returns and a struct for named
-// returns.
-func (_Mortal *MortalCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
- return _Mortal.Contract.contract.Call(opts, result, method, params...)
-}
-
-// Transfer initiates a plain transaction to move funds to the contract, calling
-// its default method if one is available.
-func (_Mortal *MortalTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _Mortal.Contract.contract.Transfer(opts)
}
-// Transact invokes the (paid) contract method with params as input values.
-func (_Mortal *MortalTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _Mortal.Contract.contract.Transact(opts, method, params...)
+// Error retruned any retrieval or parsing error occurred during filtering.
+func (it *ChequebookOverdraftIterator) Error() error {
+ return it.fail
}
-// Kill is a paid mutator transaction binding the contract method 0x41c0e1b5.
-//
-// Solidity: function kill() returns()
-func (_Mortal *MortalTransactor) Kill(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _Mortal.contract.Transact(opts, "kill")
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *ChequebookOverdraftIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
}
-// Kill is a paid mutator transaction binding the contract method 0x41c0e1b5.
-//
-// Solidity: function kill() returns()
-func (_Mortal *MortalSession) Kill() (*types.Transaction, error) {
- return _Mortal.Contract.Kill(&_Mortal.TransactOpts)
+// ChequebookOverdraft represents a Overdraft event raised by the Chequebook contract.
+type ChequebookOverdraft struct {
+ Deadbeat common.Address
+ Raw types.Log // Blockchain specific contextual infos
}
-// Kill is a paid mutator transaction binding the contract method 0x41c0e1b5.
+// FilterOverdraft is a free log retrieval operation binding the contract event 0x2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f978.
//
-// Solidity: function kill() returns()
-func (_Mortal *MortalTransactorSession) Kill() (*types.Transaction, error) {
- return _Mortal.Contract.Kill(&_Mortal.TransactOpts)
-}
-
-// OwnedABI is the input ABI used to generate the binding from.
-const OwnedABI = `[{"inputs":[],"type":"constructor"}]`
-
-// OwnedBin is the compiled bytecode used for deploying new contracts.
-const OwnedBin = `0x606060405260008054600160a060020a0319163317905560068060226000396000f3606060405200`
-
-// DeployOwned deploys a new Ethereum contract, binding an instance of Owned to it.
-func DeployOwned(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Owned, error) {
- parsed, err := abi.JSON(strings.NewReader(OwnedABI))
- if err != nil {
- return common.Address{}, nil, nil, err
- }
- address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(OwnedBin), backend)
- if err != nil {
- return common.Address{}, nil, nil, err
- }
- return address, tx, &Owned{OwnedCaller: OwnedCaller{contract: contract}, OwnedTransactor: OwnedTransactor{contract: contract}}, nil
-}
-
-// Owned is an auto generated Go binding around an Ethereum contract.
-type Owned struct {
- OwnedCaller // Read-only binding to the contract
- OwnedTransactor // Write-only binding to the contract
-}
-
-// OwnedCaller is an auto generated read-only Go binding around an Ethereum contract.
-type OwnedCaller struct {
- contract *bind.BoundContract // Generic contract wrapper for the low level calls
-}
-
-// OwnedTransactor is an auto generated write-only Go binding around an Ethereum contract.
-type OwnedTransactor struct {
- contract *bind.BoundContract // Generic contract wrapper for the low level calls
-}
-
-// OwnedSession is an auto generated Go binding around an Ethereum contract,
-// with pre-set call and transact options.
-type OwnedSession struct {
- Contract *Owned // Generic contract binding to set the session for
- CallOpts bind.CallOpts // Call options to use throughout this session
- TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
-}
-
-// OwnedCallerSession is an auto generated read-only Go binding around an Ethereum contract,
-// with pre-set call options.
-type OwnedCallerSession struct {
- Contract *OwnedCaller // Generic contract caller binding to set the session for
- CallOpts bind.CallOpts // Call options to use throughout this session
-}
-
-// OwnedTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
-// with pre-set transact options.
-type OwnedTransactorSession struct {
- Contract *OwnedTransactor // Generic contract transactor binding to set the session for
- TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
-}
-
-// OwnedRaw is an auto generated low-level Go binding around an Ethereum contract.
-type OwnedRaw struct {
- Contract *Owned // Generic contract binding to access the raw methods on
-}
+// Solidity: event Overdraft(deadbeat address)
+func (_Chequebook *ChequebookFilterer) FilterOverdraft(opts *bind.FilterOpts) (*ChequebookOverdraftIterator, error) {
-// OwnedCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
-type OwnedCallerRaw struct {
- Contract *OwnedCaller // Generic read-only contract binding to access the raw methods on
-}
-
-// OwnedTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
-type OwnedTransactorRaw struct {
- Contract *OwnedTransactor // Generic write-only contract binding to access the raw methods on
-}
-
-// NewOwned creates a new instance of Owned, bound to a specific deployed contract.
-func NewOwned(address common.Address, backend bind.ContractBackend) (*Owned, error) {
- contract, err := bindOwned(address, backend, backend)
- if err != nil {
- return nil, err
- }
- return &Owned{OwnedCaller: OwnedCaller{contract: contract}, OwnedTransactor: OwnedTransactor{contract: contract}}, nil
-}
-
-// NewOwnedCaller creates a new read-only instance of Owned, bound to a specific deployed contract.
-func NewOwnedCaller(address common.Address, caller bind.ContractCaller) (*OwnedCaller, error) {
- contract, err := bindOwned(address, caller, nil)
+ logs, sub, err := _Chequebook.contract.FilterLogs(opts, "Overdraft")
if err != nil {
return nil, err
}
- return &OwnedCaller{contract: contract}, nil
+ return &ChequebookOverdraftIterator{contract: _Chequebook.contract, event: "Overdraft", logs: logs, sub: sub}, nil
}
-// NewOwnedTransactor creates a new write-only instance of Owned, bound to a specific deployed contract.
-func NewOwnedTransactor(address common.Address, transactor bind.ContractTransactor) (*OwnedTransactor, error) {
- contract, err := bindOwned(address, nil, transactor)
- if err != nil {
- return nil, err
- }
- return &OwnedTransactor{contract: contract}, nil
-}
+// WatchOverdraft is a free log subscription operation binding the contract event 0x2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f978.
+//
+// Solidity: event Overdraft(deadbeat address)
+func (_Chequebook *ChequebookFilterer) WatchOverdraft(opts *bind.WatchOpts, sink chan<- *ChequebookOverdraft) (event.Subscription, error) {
-// bindOwned binds a generic wrapper to an already deployed contract.
-func bindOwned(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
- parsed, err := abi.JSON(strings.NewReader(OwnedABI))
+ logs, sub, err := _Chequebook.contract.WatchLogs(opts, "Overdraft")
if err != nil {
return nil, err
}
- return bind.NewBoundContract(address, parsed, caller, transactor), nil
-}
-
-// Call invokes the (constant) contract method with params as input values and
-// sets the output to result. The result type might be a single field for simple
-// returns, a slice of interfaces for anonymous returns and a struct for named
-// returns.
-func (_Owned *OwnedRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
- return _Owned.Contract.OwnedCaller.contract.Call(opts, result, method, params...)
-}
-
-// Transfer initiates a plain transaction to move funds to the contract, calling
-// its default method if one is available.
-func (_Owned *OwnedRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _Owned.Contract.OwnedTransactor.contract.Transfer(opts)
-}
-
-// Transact invokes the (paid) contract method with params as input values.
-func (_Owned *OwnedRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _Owned.Contract.OwnedTransactor.contract.Transact(opts, method, params...)
-}
-
-// Call invokes the (constant) contract method with params as input values and
-// sets the output to result. The result type might be a single field for simple
-// returns, a slice of interfaces for anonymous returns and a struct for named
-// returns.
-func (_Owned *OwnedCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
- return _Owned.Contract.contract.Call(opts, result, method, params...)
-}
-
-// Transfer initiates a plain transaction to move funds to the contract, calling
-// its default method if one is available.
-func (_Owned *OwnedTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _Owned.Contract.contract.Transfer(opts)
-}
-
-// Transact invokes the (paid) contract method with params as input values.
-func (_Owned *OwnedTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _Owned.Contract.contract.Transact(opts, method, params...)
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(ChequebookOverdraft)
+ if err := _Chequebook.contract.UnpackLog(event, "Overdraft", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
}
diff --git a/contracts/chequebook/contract/chequebook.sol b/contracts/chequebook/contract/chequebook.sol
index 8d6e85d11..c386cceed 100644
--- a/contracts/chequebook/contract/chequebook.sol
+++ b/contracts/chequebook/contract/chequebook.sol
@@ -1,6 +1,6 @@
pragma solidity ^0.4.18;
-import "https://github.com/ethereum/solidity/std/mortal.sol";
+import "./mortal.sol";
/// @title Chequebook for Ethereum micropayments
/// @author Daniel A. Nagy <daniel@ethereum.org>
@@ -11,6 +11,9 @@ contract chequebook is mortal {
/// @notice Overdraft event
event Overdraft(address deadbeat);
+ // Allow sending ether to the chequebook.
+ function() public payable { }
+
/// @notice Cash cheque
///
/// @param beneficiary beneficiary address
@@ -19,8 +22,7 @@ contract chequebook is mortal {
/// @param sig_r signature parameter r
/// @param sig_s signature parameter s
/// The digital signature is calculated on the concatenated triplet of contract address, beneficiary address and cumulative amount
- function cash(address beneficiary, uint256 amount,
- uint8 sig_v, bytes32 sig_r, bytes32 sig_s) {
+ function cash(address beneficiary, uint256 amount, uint8 sig_v, bytes32 sig_r, bytes32 sig_s) public {
// Check if the cheque is old.
// Only cheques that are more recent than the last cashed one are considered.
require(amount > sent[beneficiary]);
@@ -31,7 +33,7 @@ contract chequebook is mortal {
// and the cumulative amount on the last cashed cheque to beneficiary.
uint256 diff = amount - sent[beneficiary];
if (diff <= this.balance) {
- // update the cumulative amount before sending
+ // update the cumulative amount before sending
sent[beneficiary] = amount;
beneficiary.transfer(diff);
} else {
diff --git a/contracts/chequebook/contract/code.go b/contracts/chequebook/contract/code.go
index b08e04e71..d837a9d60 100644
--- a/contracts/chequebook/contract/code.go
+++ b/contracts/chequebook/contract/code.go
@@ -2,4 +2,4 @@ package contract
// ContractDeployedCode is used to detect suicides. This constant needs to be
// updated when the contract code is changed.
-const ContractDeployedCode = "0x606060405260e060020a600035046341c0e1b581146100315780637bf786f814610059578063fbf788d614610071575b005b61002f60005433600160a060020a03908116911614156100bd57600054600160a060020a0316ff5b6100ab60043560016020526000908152604090205481565b61002f600435602435604435606435608435600160a060020a03851660009081526001602052604081205485116100bf575b505050505050565b60408051918252519081900360200190f35b565b50604080516c0100000000000000000000000030600160a060020a0390811682028352881602601482015260288101869052815190819003604801812080825260ff861660208381019190915282840186905260608301859052925190926001926080818101939182900301816000866161da5a03f11561000257505060405151600054600160a060020a0390811691161461015a576100a3565b600160a060020a038681166000908152600160205260409020543090911631908603106101b357604060008181208790559051600160a060020a0388169190819081818181818881f1935050505015156100a357610002565b60005460408051600160a060020a03929092168252517f2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f9789181900360200190a185600160a060020a0316ff"
+const ContractDeployedCode = "0x6060604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166341c0e1b581146100585780637bf786f81461006b578063fbf788d61461009c575b005b341561006357600080fd5b6100566100ca565b341561007657600080fd5b61008a600160a060020a03600435166100f1565b60405190815260200160405180910390f35b34156100a757600080fd5b610056600160a060020a036004351660243560ff60443516606435608435610103565b60005433600160a060020a03908116911614156100ef57600054600160a060020a0316ff5b565b60016020526000908152604090205481565b600160a060020a0385166000908152600160205260408120548190861161012957600080fd5b3087876040516c01000000000000000000000000600160a060020a03948516810282529290931690910260148301526028820152604801604051809103902091506001828686866040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f115156101cf57600080fd5b505060206040510351600054600160a060020a039081169116146101f257600080fd5b50600160a060020a03808716600090815260016020526040902054860390301631811161026257600160a060020a0387166000818152600160205260409081902088905582156108fc0290839051600060405180830381858888f19350505050151561025d57600080fd5b6102b7565b6000547f2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f97890600160a060020a0316604051600160a060020a03909116815260200160405180910390a186600160a060020a0316ff5b505050505050505600a165627a7a72305820533e856fc37e3d64d1706bcc7dfb6b1d490c8d566ea498d9d01ec08965a896ca0029"
diff --git a/contracts/chequebook/contract/mortal.sol b/contracts/chequebook/contract/mortal.sol
new file mode 100644
index 000000000..c43f1e4f7
--- /dev/null
+++ b/contracts/chequebook/contract/mortal.sol
@@ -0,0 +1,10 @@
+pragma solidity ^0.4.0;
+
+import "./owned.sol";
+
+contract mortal is owned {
+ function kill() public {
+ if (msg.sender == owner)
+ selfdestruct(owner);
+ }
+}
diff --git a/contracts/chequebook/contract/owned.sol b/contracts/chequebook/contract/owned.sol
new file mode 100644
index 000000000..ee9860d34
--- /dev/null
+++ b/contracts/chequebook/contract/owned.sol
@@ -0,0 +1,15 @@
+pragma solidity ^0.4.0;
+
+contract owned {
+ address owner;
+
+ modifier onlyowner() {
+ if (msg.sender == owner) {
+ _;
+ }
+ }
+
+ function owned() public {
+ owner = msg.sender;
+ }
+}
diff --git a/contracts/chequebook/gencode.go b/contracts/chequebook/gencode.go
index faa927279..45f6d68f3 100644
--- a/contracts/chequebook/gencode.go
+++ b/contracts/chequebook/gencode.go
@@ -33,15 +33,14 @@ import (
)
var (
- testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- testAccount = core.GenesisAccount{
- Address: crypto.PubkeyToAddress(testKey.PublicKey),
- Balance: big.NewInt(500000000000),
+ testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ testAlloc = core.GenesisAlloc{
+ crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(500000000000)},
}
)
func main() {
- backend := backends.NewSimulatedBackend(testAccount)
+ backend := backends.NewSimulatedBackend(testAlloc)
auth := bind.NewKeyedTransactor(testKey)
// Deploy the contract, get the code.
diff --git a/contracts/ens/contract/AbstractENS.sol b/contracts/ens/contract/AbstractENS.sol
new file mode 100644
index 000000000..b80a1b0e6
--- /dev/null
+++ b/contracts/ens/contract/AbstractENS.sol
@@ -0,0 +1,23 @@
+pragma solidity ^0.4.0;
+
+contract AbstractENS {
+ function owner(bytes32 node) constant returns(address);
+ function resolver(bytes32 node) constant returns(address);
+ function ttl(bytes32 node) constant returns(uint64);
+ function setOwner(bytes32 node, address owner);
+ function setSubnodeOwner(bytes32 node, bytes32 label, address owner);
+ function setResolver(bytes32 node, address resolver);
+ function setTTL(bytes32 node, uint64 ttl);
+
+ // Logged when the owner of a node assigns a new owner to a subnode.
+ event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
+
+ // Logged when the owner of a node transfers ownership to a new account.
+ event Transfer(bytes32 indexed node, address owner);
+
+ // Logged when the resolver for a node changes.
+ event NewResolver(bytes32 indexed node, address resolver);
+
+ // Logged when the TTL of a node changes
+ event NewTTL(bytes32 indexed node, uint64 ttl);
+}
diff --git a/contracts/ens/contract/ENS.sol b/contracts/ens/contract/ENS.sol
new file mode 100644
index 000000000..47050c19d
--- /dev/null
+++ b/contracts/ens/contract/ENS.sol
@@ -0,0 +1,94 @@
+pragma solidity ^0.4.0;
+
+import './AbstractENS.sol';
+
+/**
+ * The ENS registry contract.
+ */
+contract ENS is AbstractENS {
+ struct Record {
+ address owner;
+ address resolver;
+ uint64 ttl;
+ }
+
+ mapping(bytes32=>Record) records;
+
+ // Permits modifications only by the owner of the specified node.
+ modifier only_owner(bytes32 node) {
+ if (records[node].owner != msg.sender) throw;
+ _;
+ }
+
+ /**
+ * Constructs a new ENS registrar.
+ */
+ function ENS() {
+ records[0].owner = msg.sender;
+ }
+
+ /**
+ * Returns the address that owns the specified node.
+ */
+ function owner(bytes32 node) constant returns (address) {
+ return records[node].owner;
+ }
+
+ /**
+ * Returns the address of the resolver for the specified node.
+ */
+ function resolver(bytes32 node) constant returns (address) {
+ return records[node].resolver;
+ }
+
+ /**
+ * Returns the TTL of a node, and any records associated with it.
+ */
+ function ttl(bytes32 node) constant returns (uint64) {
+ return records[node].ttl;
+ }
+
+ /**
+ * Transfers ownership of a node to a new address. May only be called by the current
+ * owner of the node.
+ * @param node The node to transfer ownership of.
+ * @param owner The address of the new owner.
+ */
+ function setOwner(bytes32 node, address owner) only_owner(node) {
+ Transfer(node, owner);
+ records[node].owner = owner;
+ }
+
+ /**
+ * Transfers ownership of a subnode sha3(node, label) to a new address. May only be
+ * called by the owner of the parent node.
+ * @param node The parent node.
+ * @param label The hash of the label specifying the subnode.
+ * @param owner The address of the new owner.
+ */
+ function setSubnodeOwner(bytes32 node, bytes32 label, address owner) only_owner(node) {
+ var subnode = sha3(node, label);
+ NewOwner(node, label, owner);
+ records[subnode].owner = owner;
+ }
+
+ /**
+ * Sets the resolver address for the specified node.
+ * @param node The node to update.
+ * @param resolver The address of the resolver.
+ */
+ function setResolver(bytes32 node, address resolver) only_owner(node) {
+ NewResolver(node, resolver);
+ records[node].resolver = resolver;
+ }
+
+ /**
+ * Sets the TTL for the specified node.
+ * @param node The node to update.
+ * @param ttl The TTL in seconds.
+ */
+ function setTTL(bytes32 node, uint64 ttl) only_owner(node) {
+ NewTTL(node, ttl);
+ records[node].ttl = ttl;
+ }
+}
diff --git a/contracts/ens/contract/FIFSRegistrar.sol b/contracts/ens/contract/FIFSRegistrar.sol
new file mode 100644
index 000000000..51629c2b6
--- /dev/null
+++ b/contracts/ens/contract/FIFSRegistrar.sol
@@ -0,0 +1,39 @@
+pragma solidity ^0.4.0;
+
+import './AbstractENS.sol';
+
+/**
+ * A registrar that allocates subdomains to the first person to claim them.
+ */
+contract FIFSRegistrar {
+ AbstractENS ens;
+ bytes32 rootNode;
+
+ modifier only_owner(bytes32 subnode) {
+ var node = sha3(rootNode, subnode);
+ var currentOwner = ens.owner(node);
+
+ if (currentOwner != 0 && currentOwner != msg.sender) throw;
+
+ _;
+ }
+
+ /**
+ * Constructor.
+ * @param ensAddr The address of the ENS registry.
+ * @param node The node that this registrar administers.
+ */
+ function FIFSRegistrar(AbstractENS ensAddr, bytes32 node) {
+ ens = ensAddr;
+ rootNode = node;
+ }
+
+ /**
+ * Register a name, or change the owner of an existing registration.
+ * @param subnode The hash of the label to register.
+ * @param owner The address of the new owner.
+ */
+ function register(bytes32 subnode, address owner) only_owner(subnode) {
+ ens.setSubnodeOwner(rootNode, subnode, owner);
+ }
+}
diff --git a/contracts/ens/contract/PublicResolver.sol b/contracts/ens/contract/PublicResolver.sol
new file mode 100644
index 000000000..9dcc95689
--- /dev/null
+++ b/contracts/ens/contract/PublicResolver.sol
@@ -0,0 +1,212 @@
+pragma solidity ^0.4.0;
+
+import './AbstractENS.sol';
+
+/**
+ * A simple resolver anyone can use; only allows the owner of a node to set its
+ * address.
+ */
+contract PublicResolver {
+ bytes4 constant INTERFACE_META_ID = 0x01ffc9a7;
+ bytes4 constant ADDR_INTERFACE_ID = 0x3b3b57de;
+ bytes4 constant CONTENT_INTERFACE_ID = 0xd8389dc5;
+ bytes4 constant NAME_INTERFACE_ID = 0x691f3431;
+ bytes4 constant ABI_INTERFACE_ID = 0x2203ab56;
+ bytes4 constant PUBKEY_INTERFACE_ID = 0xc8690233;
+ bytes4 constant TEXT_INTERFACE_ID = 0x59d1d43c;
+
+ event AddrChanged(bytes32 indexed node, address a);
+ event ContentChanged(bytes32 indexed node, bytes32 hash);
+ event NameChanged(bytes32 indexed node, string name);
+ event ABIChanged(bytes32 indexed node, uint256 indexed contentType);
+ event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);
+ event TextChanged(bytes32 indexed node, string indexed indexedKey, string key);
+
+ struct PublicKey {
+ bytes32 x;
+ bytes32 y;
+ }
+
+ struct Record {
+ address addr;
+ bytes32 content;
+ string name;
+ PublicKey pubkey;
+ mapping(string=>string) text;
+ mapping(uint256=>bytes) abis;
+ }
+
+ AbstractENS ens;
+ mapping(bytes32=>Record) records;
+
+ modifier only_owner(bytes32 node) {
+ if (ens.owner(node) != msg.sender) throw;
+ _;
+ }
+
+ /**
+ * Constructor.
+ * @param ensAddr The ENS registrar contract.
+ */
+ function PublicResolver(AbstractENS ensAddr) {
+ ens = ensAddr;
+ }
+
+ /**
+ * Returns true if the resolver implements the interface specified by the provided hash.
+ * @param interfaceID The ID of the interface to check for.
+ * @return True if the contract implements the requested interface.
+ */
+ function supportsInterface(bytes4 interfaceID) constant returns (bool) {
+ return interfaceID == ADDR_INTERFACE_ID ||
+ interfaceID == CONTENT_INTERFACE_ID ||
+ interfaceID == NAME_INTERFACE_ID ||
+ interfaceID == ABI_INTERFACE_ID ||
+ interfaceID == PUBKEY_INTERFACE_ID ||
+ interfaceID == TEXT_INTERFACE_ID ||
+ interfaceID == INTERFACE_META_ID;
+ }
+
+ /**
+ * Returns the address associated with an ENS node.
+ * @param node The ENS node to query.
+ * @return The associated address.
+ */
+ function addr(bytes32 node) constant returns (address ret) {
+ ret = records[node].addr;
+ }
+
+ /**
+ * Sets the address associated with an ENS node.
+ * May only be called by the owner of that node in the ENS registry.
+ * @param node The node to update.
+ * @param addr The address to set.
+ */
+ function setAddr(bytes32 node, address addr) only_owner(node) {
+ records[node].addr = addr;
+ AddrChanged(node, addr);
+ }
+
+ /**
+ * Returns the content hash associated with an ENS node.
+ * Note that this resource type is not standardized, and will likely change
+ * in future to a resource type based on multihash.
+ * @param node The ENS node to query.
+ * @return The associated content hash.
+ */
+ function content(bytes32 node) constant returns (bytes32 ret) {
+ ret = records[node].content;
+ }
+
+ /**
+ * Sets the content hash associated with an ENS node.
+ * May only be called by the owner of that node in the ENS registry.
+ * Note that this resource type is not standardized, and will likely change
+ * in future to a resource type based on multihash.
+ * @param node The node to update.
+ * @param hash The content hash to set
+ */
+ function setContent(bytes32 node, bytes32 hash) only_owner(node) {
+ records[node].content = hash;
+ ContentChanged(node, hash);
+ }
+
+ /**
+ * Returns the name associated with an ENS node, for reverse records.
+ * Defined in EIP181.
+ * @param node The ENS node to query.
+ * @return The associated name.
+ */
+ function name(bytes32 node) constant returns (string ret) {
+ ret = records[node].name;
+ }
+
+ /**
+ * Sets the name associated with an ENS node, for reverse records.
+ * May only be called by the owner of that node in the ENS registry.
+ * @param node The node to update.
+ * @param name The name to set.
+ */
+ function setName(bytes32 node, string name) only_owner(node) {
+ records[node].name = name;
+ NameChanged(node, name);
+ }
+
+ /**
+ * Returns the ABI associated with an ENS node.
+ * Defined in EIP205.
+ * @param node The ENS node to query
+ * @param contentTypes A bitwise OR of the ABI formats accepted by the caller.
+ * @return contentType The content type of the return value
+ * @return data The ABI data
+ */
+ function ABI(bytes32 node, uint256 contentTypes) constant returns (uint256 contentType, bytes data) {
+ var record = records[node];
+ for(contentType = 1; contentType <= contentTypes; contentType <<= 1) {
+ if ((contentType & contentTypes) != 0 && record.abis[contentType].length > 0) {
+ data = record.abis[contentType];
+ return;
+ }
+ }
+ contentType = 0;
+ }
+
+ /**
+ * Sets the ABI associated with an ENS node.
+ * Nodes may have one ABI of each content type. To remove an ABI, set it to
+ * the empty string.
+ * @param node The node to update.
+ * @param contentType The content type of the ABI
+ * @param data The ABI data.
+ */
+ function setABI(bytes32 node, uint256 contentType, bytes data) only_owner(node) {
+ // Content types must be powers of 2
+ if (((contentType - 1) & contentType) != 0) throw;
+
+ records[node].abis[contentType] = data;
+ ABIChanged(node, contentType);
+ }
+
+ /**
+ * Returns the SECP256k1 public key associated with an ENS node.
+ * Defined in EIP 619.
+ * @param node The ENS node to query
+ * @return x, y the X and Y coordinates of the curve point for the public key.
+ */
+ function pubkey(bytes32 node) constant returns (bytes32 x, bytes32 y) {
+ return (records[node].pubkey.x, records[node].pubkey.y);
+ }
+
+ /**
+ * Sets the SECP256k1 public key associated with an ENS node.
+ * @param node The ENS node to query
+ * @param x the X coordinate of the curve point for the public key.
+ * @param y the Y coordinate of the curve point for the public key.
+ */
+ function setPubkey(bytes32 node, bytes32 x, bytes32 y) only_owner(node) {
+ records[node].pubkey = PublicKey(x, y);
+ PubkeyChanged(node, x, y);
+ }
+
+ /**
+ * Returns the text data associated with an ENS node and key.
+ * @param node The ENS node to query.
+ * @param key The text data key to query.
+ * @return The associated text data.
+ */
+ function text(bytes32 node, string key) constant returns (string ret) {
+ ret = records[node].text[key];
+ }
+
+ /**
+ * Sets the text data associated with an ENS node and key.
+ * May only be called by the owner of that node in the ENS registry.
+ * @param node The node to update.
+ * @param key The key to set.
+ * @param value The text data value to set.
+ */
+ function setText(bytes32 node, string key, string value) only_owner(node) {
+ records[node].text[key] = value;
+ TextChanged(node, key, key);
+ }
+}
diff --git a/contracts/ens/contract/ens.go b/contracts/ens/contract/ens.go
index aca16de50..cbf6cb05b 100644
--- a/contracts/ens/contract/ens.go
+++ b/contracts/ens/contract/ens.go
@@ -1,40 +1,43 @@
-// This file is an automatically generated Go binding. Do not modify as any
-// change will likely be lost upon the next re-generation!
+// Code generated - DO NOT EDIT.
+// This file is a generated binding and any manual changes will be lost.
package contract
import (
"strings"
+ ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/event"
)
// ENSABI is the input ABI used to generate the binding from.
-const ENSABI = `[{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"label","type":"bytes32"},{"name":"owner","type":"address"}],"name":"setSubnodeOwner","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"resolver","type":"address"}],"name":"setResolver","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"owner","type":"address"}],"name":"setOwner","outputs":[],"type":"function"},{"inputs":[{"name":"owner","type":"address"}],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":true,"name":"label","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"resolver","type":"address"}],"name":"NewResolver","type":"event"}]`
+const ENSABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"resolver\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"label\",\"type\":\"bytes32\"},{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"setSubnodeOwner\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"ttl\",\"type\":\"uint64\"}],\"name\":\"setTTL\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"ttl\",\"outputs\":[{\"name\":\"\",\"type\":\"uint64\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"setResolver\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"label\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"NewOwner\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"NewResolver\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"ttl\",\"type\":\"uint64\"}],\"name\":\"NewTTL\",\"type\":\"event\"}]"
// ENSBin is the compiled bytecode used for deploying new contracts.
-const ENSBin = `0x606060405260405160208061032683395060806040525160008080526020527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb58054600160a060020a03191682179055506102c88061005e6000396000f3606060405260e060020a60003504630178b8bf811461004757806302571be31461006e57806306ab5923146100915780631896f70a146100c85780635b0fc9c3146100fc575b005b610130600435600081815260208190526040902060010154600160a060020a03165b919050565b610130600435600081815260208190526040902054600160a060020a0316610069565b6100456004356024356044356000838152602081905260408120548490600160a060020a0390811633919091161461014d57610002565b6100456004356024356000828152602081905260409020548290600160a060020a039081163391909116146101e757610002565b6100456004356024356000828152602081905260409020548290600160a060020a0390811633919091161461025957610002565b60408051600160a060020a03929092168252519081900360200190f35b60408051868152602081810187905282519182900383018220600160a060020a03871683529251929450869288927fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e8292908290030190a382600060005060008460001916815260200190815260200160002060005060000160006101000a815481600160a060020a03021916908302179055505050505050565b60408051600160a060020a0384168152905184917f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a0919081900360200190a2506000828152602081905260409020600101805473ffffffffffffffffffffffffffffffffffffffff1916821790555050565b60408051600160a060020a0384168152905184917fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d266919081900360200190a2506000828152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff191682179055505056`
+const ENSBin = `0x6060604052341561000f57600080fd5b60008080526020527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb58054600160a060020a033316600160a060020a0319909116179055610503806100626000396000f3006060604052600436106100825763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630178b8bf811461008757806302571be3146100b957806306ab5923146100cf57806314ab9038146100f657806316a25cbd146101195780631896f70a1461014c5780635b0fc9c31461016e575b600080fd5b341561009257600080fd5b61009d600435610190565b604051600160a060020a03909116815260200160405180910390f35b34156100c457600080fd5b61009d6004356101ae565b34156100da57600080fd5b6100f4600435602435600160a060020a03604435166101c9565b005b341561010157600080fd5b6100f460043567ffffffffffffffff6024351661028b565b341561012457600080fd5b61012f600435610357565b60405167ffffffffffffffff909116815260200160405180910390f35b341561015757600080fd5b6100f4600435600160a060020a036024351661038e565b341561017957600080fd5b6100f4600435600160a060020a0360243516610434565b600090815260208190526040902060010154600160a060020a031690565b600090815260208190526040902054600160a060020a031690565b600083815260208190526040812054849033600160a060020a039081169116146101f257600080fd5b8484604051918252602082015260409081019051908190039020915083857fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e8285604051600160a060020a03909116815260200160405180910390a3506000908152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03929092169190911790555050565b600082815260208190526040902054829033600160a060020a039081169116146102b457600080fd5b827f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa688360405167ffffffffffffffff909116815260200160405180910390a250600091825260208290526040909120600101805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60009081526020819052604090206001015474010000000000000000000000000000000000000000900467ffffffffffffffff1690565b600082815260208190526040902054829033600160a060020a039081169116146103b757600080fd5b827f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a083604051600160a060020a03909116815260200160405180910390a250600091825260208290526040909120600101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03909216919091179055565b600082815260208190526040902054829033600160a060020a0390811691161461045d57600080fd5b827fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d26683604051600160a060020a03909116815260200160405180910390a250600091825260208290526040909120805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039092169190911790555600a165627a7a72305820f4c798d4c84c9912f389f64631e85e8d16c3e6644f8c2e1579936015c7d5f6660029`
// DeployENS deploys a new Ethereum contract, binding an instance of ENS to it.
-func DeployENS(auth *bind.TransactOpts, backend bind.ContractBackend, owner common.Address) (common.Address, *types.Transaction, *ENS, error) {
+func DeployENS(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ENS, error) {
parsed, err := abi.JSON(strings.NewReader(ENSABI))
if err != nil {
return common.Address{}, nil, nil, err
}
- address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ENSBin), backend, owner)
+ address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ENSBin), backend)
if err != nil {
return common.Address{}, nil, nil, err
}
- return address, tx, &ENS{ENSCaller: ENSCaller{contract: contract}, ENSTransactor: ENSTransactor{contract: contract}}, nil
+ return address, tx, &ENS{ENSCaller: ENSCaller{contract: contract}, ENSTransactor: ENSTransactor{contract: contract}, ENSFilterer: ENSFilterer{contract: contract}}, nil
}
// ENS is an auto generated Go binding around an Ethereum contract.
type ENS struct {
ENSCaller // Read-only binding to the contract
ENSTransactor // Write-only binding to the contract
+ ENSFilterer // Log filterer for contract events
}
// ENSCaller is an auto generated read-only Go binding around an Ethereum contract.
@@ -47,6 +50,11 @@ type ENSTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
+// ENSFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
+type ENSFilterer struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
// ENSSession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type ENSSession struct {
@@ -86,16 +94,16 @@ type ENSTransactorRaw struct {
// NewENS creates a new instance of ENS, bound to a specific deployed contract.
func NewENS(address common.Address, backend bind.ContractBackend) (*ENS, error) {
- contract, err := bindENS(address, backend, backend)
+ contract, err := bindENS(address, backend, backend, backend)
if err != nil {
return nil, err
}
- return &ENS{ENSCaller: ENSCaller{contract: contract}, ENSTransactor: ENSTransactor{contract: contract}}, nil
+ return &ENS{ENSCaller: ENSCaller{contract: contract}, ENSTransactor: ENSTransactor{contract: contract}, ENSFilterer: ENSFilterer{contract: contract}}, nil
}
// NewENSCaller creates a new read-only instance of ENS, bound to a specific deployed contract.
func NewENSCaller(address common.Address, caller bind.ContractCaller) (*ENSCaller, error) {
- contract, err := bindENS(address, caller, nil)
+ contract, err := bindENS(address, caller, nil, nil)
if err != nil {
return nil, err
}
@@ -104,20 +112,29 @@ func NewENSCaller(address common.Address, caller bind.ContractCaller) (*ENSCalle
// NewENSTransactor creates a new write-only instance of ENS, bound to a specific deployed contract.
func NewENSTransactor(address common.Address, transactor bind.ContractTransactor) (*ENSTransactor, error) {
- contract, err := bindENS(address, nil, transactor)
+ contract, err := bindENS(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &ENSTransactor{contract: contract}, nil
}
+// NewENSFilterer creates a new log filterer instance of ENS, bound to a specific deployed contract.
+func NewENSFilterer(address common.Address, filterer bind.ContractFilterer) (*ENSFilterer, error) {
+ contract, err := bindENS(address, nil, nil, filterer)
+ if err != nil {
+ return nil, err
+ }
+ return &ENSFilterer{contract: contract}, nil
+}
+
// bindENS binds a generic wrapper to an already deployed contract.
-func bindENS(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
+func bindENS(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(ENSABI))
if err != nil {
return nil, err
}
- return bind.NewBoundContract(address, parsed, caller, transactor), nil
+ return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
@@ -210,6 +227,32 @@ func (_ENS *ENSCallerSession) Resolver(node [32]byte) (common.Address, error) {
return _ENS.Contract.Resolver(&_ENS.CallOpts, node)
}
+// Ttl is a free data retrieval call binding the contract method 0x16a25cbd.
+//
+// Solidity: function ttl(node bytes32) constant returns(uint64)
+func (_ENS *ENSCaller) Ttl(opts *bind.CallOpts, node [32]byte) (uint64, error) {
+ var (
+ ret0 = new(uint64)
+ )
+ out := ret0
+ err := _ENS.contract.Call(opts, out, "ttl", node)
+ return *ret0, err
+}
+
+// Ttl is a free data retrieval call binding the contract method 0x16a25cbd.
+//
+// Solidity: function ttl(node bytes32) constant returns(uint64)
+func (_ENS *ENSSession) Ttl(node [32]byte) (uint64, error) {
+ return _ENS.Contract.Ttl(&_ENS.CallOpts, node)
+}
+
+// Ttl is a free data retrieval call binding the contract method 0x16a25cbd.
+//
+// Solidity: function ttl(node bytes32) constant returns(uint64)
+func (_ENS *ENSCallerSession) Ttl(node [32]byte) (uint64, error) {
+ return _ENS.Contract.Ttl(&_ENS.CallOpts, node)
+}
+
// SetOwner is a paid mutator transaction binding the contract method 0x5b0fc9c3.
//
// Solidity: function setOwner(node bytes32, owner address) returns()
@@ -273,649 +316,564 @@ func (_ENS *ENSTransactorSession) SetSubnodeOwner(node [32]byte, label [32]byte,
return _ENS.Contract.SetSubnodeOwner(&_ENS.TransactOpts, node, label, owner)
}
-// FIFSRegistrarABI is the input ABI used to generate the binding from.
-const FIFSRegistrarABI = `[{"constant":false,"inputs":[{"name":"subnode","type":"bytes32"},{"name":"owner","type":"address"}],"name":"register","outputs":[],"type":"function"},{"inputs":[{"name":"ensAddr","type":"address"},{"name":"node","type":"bytes32"}],"type":"constructor"}]`
-
-// FIFSRegistrarBin is the compiled bytecode used for deploying new contracts.
-const FIFSRegistrarBin = `0x6060604081815280610620833960a090525160805160008054600160a060020a031916831790558160a0610367806100878339018082600160a060020a03168152602001915050604051809103906000f0600160006101000a815481600160a060020a0302191690830217905550806002600050819055505050610232806103ee6000396000f3606060405260405160208061036783395060806040525160008054600160a060020a0319168217905550610330806100376000396000f36060604052361561004b5760e060020a60003504632dff694181146100535780633b3b57de1461007557806341b9dc2b146100a0578063c3d014d614610139578063d5fa2b00146101b2575b61022b610002565b61022d6004356000818152600260205260408120549081141561027057610002565b61023f600435600081815260016020526040812054600160a060020a03169081141561027057610002565b61025c60043560243560007f6164647200000000000000000000000000000000000000000000000000000000821480156100f05750600083815260016020526040812054600160a060020a031614155b8061013257507f636f6e74656e740000000000000000000000000000000000000000000000000082148015610132575060008381526002602052604081205414155b9392505050565b61022b600435602435600080546040805160e060020a6302571be30281526004810186905290518593600160a060020a033381169416926302571be392602482810193602093839003909101908290876161da5a03f11561000257505060405151600160a060020a031691909114905061027557610002565b61022b600435602435600080546040805160e060020a6302571be30281526004810186905290518593600160a060020a033381169416926302571be392602482810193602093839003909101908290876161da5a03f11561000257505060405151600160a060020a03169190911490506102c157610002565b005b60408051918252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b919050565b6000838152600260209081526040918290208490558151848152915185927f0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc92908290030190a2505050565b600083815260016020908152604091829020805473ffffffffffffffffffffffffffffffffffffffff1916851790558151600160a060020a0385168152915185927f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd292908290030190a250505056606060405260e060020a6000350463d22057a9811461001b575b005b61001960043560243560025460408051918252602082810185905260008054835194859003840185207f02571be300000000000000000000000000000000000000000000000000000000865260048601819052935193949193600160a060020a03909116926302571be39260248181019391829003018187876161da5a03f11561000257505060405151915050600160a060020a0381166000148015906100d4575033600160a060020a031681600160a060020a031614155b156100de57610002565b60408051600080546002547f06ab592300000000000000000000000000000000000000000000000000000000845260048401526024830188905230600160a060020a03908116604485015293519316926306ab5923926064818101939291829003018183876161da5a03f11561000257505060008054600154604080517f1896f70a00000000000000000000000000000000000000000000000000000000815260048101889052600160a060020a0392831660248201529051929091169350631896f70a926044828101939192829003018183876161da5a03f11561000257505060008054604080517f5b0fc9c300000000000000000000000000000000000000000000000000000000815260048101879052600160a060020a0388811660248301529151929091169350635b0fc9c3926044828101939192829003018183876161da5a03f115610002575050505050505056`
-
-// DeployFIFSRegistrar deploys a new Ethereum contract, binding an instance of FIFSRegistrar to it.
-func DeployFIFSRegistrar(auth *bind.TransactOpts, backend bind.ContractBackend, ensAddr common.Address, node [32]byte) (common.Address, *types.Transaction, *FIFSRegistrar, error) {
- parsed, err := abi.JSON(strings.NewReader(FIFSRegistrarABI))
- if err != nil {
- return common.Address{}, nil, nil, err
- }
- address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(FIFSRegistrarBin), backend, ensAddr, node)
- if err != nil {
- return common.Address{}, nil, nil, err
- }
- return address, tx, &FIFSRegistrar{FIFSRegistrarCaller: FIFSRegistrarCaller{contract: contract}, FIFSRegistrarTransactor: FIFSRegistrarTransactor{contract: contract}}, nil
+// SetTTL is a paid mutator transaction binding the contract method 0x14ab9038.
+//
+// Solidity: function setTTL(node bytes32, ttl uint64) returns()
+func (_ENS *ENSTransactor) SetTTL(opts *bind.TransactOpts, node [32]byte, ttl uint64) (*types.Transaction, error) {
+ return _ENS.contract.Transact(opts, "setTTL", node, ttl)
}
-// FIFSRegistrar is an auto generated Go binding around an Ethereum contract.
-type FIFSRegistrar struct {
- FIFSRegistrarCaller // Read-only binding to the contract
- FIFSRegistrarTransactor // Write-only binding to the contract
+// SetTTL is a paid mutator transaction binding the contract method 0x14ab9038.
+//
+// Solidity: function setTTL(node bytes32, ttl uint64) returns()
+func (_ENS *ENSSession) SetTTL(node [32]byte, ttl uint64) (*types.Transaction, error) {
+ return _ENS.Contract.SetTTL(&_ENS.TransactOpts, node, ttl)
}
-// FIFSRegistrarCaller is an auto generated read-only Go binding around an Ethereum contract.
-type FIFSRegistrarCaller struct {
- contract *bind.BoundContract // Generic contract wrapper for the low level calls
+// SetTTL is a paid mutator transaction binding the contract method 0x14ab9038.
+//
+// Solidity: function setTTL(node bytes32, ttl uint64) returns()
+func (_ENS *ENSTransactorSession) SetTTL(node [32]byte, ttl uint64) (*types.Transaction, error) {
+ return _ENS.Contract.SetTTL(&_ENS.TransactOpts, node, ttl)
}
-// FIFSRegistrarTransactor is an auto generated write-only Go binding around an Ethereum contract.
-type FIFSRegistrarTransactor struct {
- contract *bind.BoundContract // Generic contract wrapper for the low level calls
-}
+// ENSNewOwnerIterator is returned from FilterNewOwner and is used to iterate over the raw logs and unpacked data for NewOwner events raised by the ENS contract.
+type ENSNewOwnerIterator struct {
+ Event *ENSNewOwner // Event containing the contract specifics and raw log
-// FIFSRegistrarSession is an auto generated Go binding around an Ethereum contract,
-// with pre-set call and transact options.
-type FIFSRegistrarSession struct {
- Contract *FIFSRegistrar // Generic contract binding to set the session for
- CallOpts bind.CallOpts // Call options to use throughout this session
- TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
-}
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
-// FIFSRegistrarCallerSession is an auto generated read-only Go binding around an Ethereum contract,
-// with pre-set call options.
-type FIFSRegistrarCallerSession struct {
- Contract *FIFSRegistrarCaller // Generic contract caller binding to set the session for
- CallOpts bind.CallOpts // Call options to use throughout this session
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
}
-// FIFSRegistrarTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
-// with pre-set transact options.
-type FIFSRegistrarTransactorSession struct {
- Contract *FIFSRegistrarTransactor // Generic contract transactor binding to set the session for
- TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *ENSNewOwnerIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(ENSNewOwner)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(ENSNewOwner)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
}
-// FIFSRegistrarRaw is an auto generated low-level Go binding around an Ethereum contract.
-type FIFSRegistrarRaw struct {
- Contract *FIFSRegistrar // Generic contract binding to access the raw methods on
+// Error retruned any retrieval or parsing error occurred during filtering.
+func (it *ENSNewOwnerIterator) Error() error {
+ return it.fail
}
-// FIFSRegistrarCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
-type FIFSRegistrarCallerRaw struct {
- Contract *FIFSRegistrarCaller // Generic read-only contract binding to access the raw methods on
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *ENSNewOwnerIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
}
-// FIFSRegistrarTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
-type FIFSRegistrarTransactorRaw struct {
- Contract *FIFSRegistrarTransactor // Generic write-only contract binding to access the raw methods on
+// ENSNewOwner represents a NewOwner event raised by the ENS contract.
+type ENSNewOwner struct {
+ Node [32]byte
+ Label [32]byte
+ Owner common.Address
+ Raw types.Log // Blockchain specific contextual infos
}
-// NewFIFSRegistrar creates a new instance of FIFSRegistrar, bound to a specific deployed contract.
-func NewFIFSRegistrar(address common.Address, backend bind.ContractBackend) (*FIFSRegistrar, error) {
- contract, err := bindFIFSRegistrar(address, backend, backend)
- if err != nil {
- return nil, err
- }
- return &FIFSRegistrar{FIFSRegistrarCaller: FIFSRegistrarCaller{contract: contract}, FIFSRegistrarTransactor: FIFSRegistrarTransactor{contract: contract}}, nil
-}
+// FilterNewOwner is a free log retrieval operation binding the contract event 0xce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e82.
+//
+// Solidity: event NewOwner(node indexed bytes32, label indexed bytes32, owner address)
+func (_ENS *ENSFilterer) FilterNewOwner(opts *bind.FilterOpts, node [][32]byte, label [][32]byte) (*ENSNewOwnerIterator, error) {
-// NewFIFSRegistrarCaller creates a new read-only instance of FIFSRegistrar, bound to a specific deployed contract.
-func NewFIFSRegistrarCaller(address common.Address, caller bind.ContractCaller) (*FIFSRegistrarCaller, error) {
- contract, err := bindFIFSRegistrar(address, caller, nil)
- if err != nil {
- return nil, err
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
}
- return &FIFSRegistrarCaller{contract: contract}, nil
-}
-
-// NewFIFSRegistrarTransactor creates a new write-only instance of FIFSRegistrar, bound to a specific deployed contract.
-func NewFIFSRegistrarTransactor(address common.Address, transactor bind.ContractTransactor) (*FIFSRegistrarTransactor, error) {
- contract, err := bindFIFSRegistrar(address, nil, transactor)
- if err != nil {
- return nil, err
+ var labelRule []interface{}
+ for _, labelItem := range label {
+ labelRule = append(labelRule, labelItem)
}
- return &FIFSRegistrarTransactor{contract: contract}, nil
-}
-// bindFIFSRegistrar binds a generic wrapper to an already deployed contract.
-func bindFIFSRegistrar(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
- parsed, err := abi.JSON(strings.NewReader(FIFSRegistrarABI))
+ logs, sub, err := _ENS.contract.FilterLogs(opts, "NewOwner", nodeRule, labelRule)
if err != nil {
return nil, err
}
- return bind.NewBoundContract(address, parsed, caller, transactor), nil
-}
-
-// Call invokes the (constant) contract method with params as input values and
-// sets the output to result. The result type might be a single field for simple
-// returns, a slice of interfaces for anonymous returns and a struct for named
-// returns.
-func (_FIFSRegistrar *FIFSRegistrarRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
- return _FIFSRegistrar.Contract.FIFSRegistrarCaller.contract.Call(opts, result, method, params...)
-}
-
-// Transfer initiates a plain transaction to move funds to the contract, calling
-// its default method if one is available.
-func (_FIFSRegistrar *FIFSRegistrarRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _FIFSRegistrar.Contract.FIFSRegistrarTransactor.contract.Transfer(opts)
-}
-
-// Transact invokes the (paid) contract method with params as input values.
-func (_FIFSRegistrar *FIFSRegistrarRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _FIFSRegistrar.Contract.FIFSRegistrarTransactor.contract.Transact(opts, method, params...)
-}
-
-// Call invokes the (constant) contract method with params as input values and
-// sets the output to result. The result type might be a single field for simple
-// returns, a slice of interfaces for anonymous returns and a struct for named
-// returns.
-func (_FIFSRegistrar *FIFSRegistrarCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
- return _FIFSRegistrar.Contract.contract.Call(opts, result, method, params...)
-}
-
-// Transfer initiates a plain transaction to move funds to the contract, calling
-// its default method if one is available.
-func (_FIFSRegistrar *FIFSRegistrarTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _FIFSRegistrar.Contract.contract.Transfer(opts)
+ return &ENSNewOwnerIterator{contract: _ENS.contract, event: "NewOwner", logs: logs, sub: sub}, nil
}
-// Transact invokes the (paid) contract method with params as input values.
-func (_FIFSRegistrar *FIFSRegistrarTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _FIFSRegistrar.Contract.contract.Transact(opts, method, params...)
-}
-
-// Register is a paid mutator transaction binding the contract method 0xd22057a9.
+// WatchNewOwner is a free log subscription operation binding the contract event 0xce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e82.
//
-// Solidity: function register(subnode bytes32, owner address) returns()
-func (_FIFSRegistrar *FIFSRegistrarTransactor) Register(opts *bind.TransactOpts, subnode [32]byte, owner common.Address) (*types.Transaction, error) {
- return _FIFSRegistrar.contract.Transact(opts, "register", subnode, owner)
-}
+// Solidity: event NewOwner(node indexed bytes32, label indexed bytes32, owner address)
+func (_ENS *ENSFilterer) WatchNewOwner(opts *bind.WatchOpts, sink chan<- *ENSNewOwner, node [][32]byte, label [][32]byte) (event.Subscription, error) {
-// Register is a paid mutator transaction binding the contract method 0xd22057a9.
-//
-// Solidity: function register(subnode bytes32, owner address) returns()
-func (_FIFSRegistrar *FIFSRegistrarSession) Register(subnode [32]byte, owner common.Address) (*types.Transaction, error) {
- return _FIFSRegistrar.Contract.Register(&_FIFSRegistrar.TransactOpts, subnode, owner)
-}
-
-// Register is a paid mutator transaction binding the contract method 0xd22057a9.
-//
-// Solidity: function register(subnode bytes32, owner address) returns()
-func (_FIFSRegistrar *FIFSRegistrarTransactorSession) Register(subnode [32]byte, owner common.Address) (*types.Transaction, error) {
- return _FIFSRegistrar.Contract.Register(&_FIFSRegistrar.TransactOpts, subnode, owner)
-}
-
-// PublicResolverABI is the input ABI used to generate the binding from.
-const PublicResolverABI = `[{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"content","outputs":[{"name":"ret","type":"bytes32"}],"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"addr","outputs":[{"name":"ret","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"kind","type":"bytes32"}],"name":"has","outputs":[{"name":"","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"hash","type":"bytes32"}],"name":"setContent","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"addr","type":"address"}],"name":"setAddr","outputs":[],"type":"function"},{"inputs":[{"name":"ensAddr","type":"address"}],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"hash","type":"bytes32"}],"name":"ContentChanged","type":"event"}]`
-
-// PublicResolverBin is the compiled bytecode used for deploying new contracts.
-const PublicResolverBin = `0x606060405260405160208061036783395060806040525160008054600160a060020a0319168217905550610330806100376000396000f36060604052361561004b5760e060020a60003504632dff694181146100535780633b3b57de1461007557806341b9dc2b146100a0578063c3d014d614610139578063d5fa2b00146101b2575b61022b610002565b61022d6004356000818152600260205260408120549081141561027057610002565b61023f600435600081815260016020526040812054600160a060020a03169081141561027057610002565b61025c60043560243560007f6164647200000000000000000000000000000000000000000000000000000000821480156100f05750600083815260016020526040812054600160a060020a031614155b8061013257507f636f6e74656e740000000000000000000000000000000000000000000000000082148015610132575060008381526002602052604081205414155b9392505050565b61022b600435602435600080546040805160e060020a6302571be30281526004810186905290518593600160a060020a033381169416926302571be392602482810193602093839003909101908290876161da5a03f11561000257505060405151600160a060020a031691909114905061027557610002565b61022b600435602435600080546040805160e060020a6302571be30281526004810186905290518593600160a060020a033381169416926302571be392602482810193602093839003909101908290876161da5a03f11561000257505060405151600160a060020a03169190911490506102c157610002565b005b60408051918252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b919050565b6000838152600260209081526040918290208490558151848152915185927f0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc92908290030190a2505050565b600083815260016020908152604091829020805473ffffffffffffffffffffffffffffffffffffffff1916851790558151600160a060020a0385168152915185927f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd292908290030190a250505056`
-
-// DeployPublicResolver deploys a new Ethereum contract, binding an instance of PublicResolver to it.
-func DeployPublicResolver(auth *bind.TransactOpts, backend bind.ContractBackend, ensAddr common.Address) (common.Address, *types.Transaction, *PublicResolver, error) {
- parsed, err := abi.JSON(strings.NewReader(PublicResolverABI))
- if err != nil {
- return common.Address{}, nil, nil, err
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
}
- address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(PublicResolverBin), backend, ensAddr)
- if err != nil {
- return common.Address{}, nil, nil, err
+ var labelRule []interface{}
+ for _, labelItem := range label {
+ labelRule = append(labelRule, labelItem)
}
- return address, tx, &PublicResolver{PublicResolverCaller: PublicResolverCaller{contract: contract}, PublicResolverTransactor: PublicResolverTransactor{contract: contract}}, nil
-}
-
-// PublicResolver is an auto generated Go binding around an Ethereum contract.
-type PublicResolver struct {
- PublicResolverCaller // Read-only binding to the contract
- PublicResolverTransactor // Write-only binding to the contract
-}
-
-// PublicResolverCaller is an auto generated read-only Go binding around an Ethereum contract.
-type PublicResolverCaller struct {
- contract *bind.BoundContract // Generic contract wrapper for the low level calls
-}
-
-// PublicResolverTransactor is an auto generated write-only Go binding around an Ethereum contract.
-type PublicResolverTransactor struct {
- contract *bind.BoundContract // Generic contract wrapper for the low level calls
-}
-
-// PublicResolverSession is an auto generated Go binding around an Ethereum contract,
-// with pre-set call and transact options.
-type PublicResolverSession struct {
- Contract *PublicResolver // Generic contract binding to set the session for
- CallOpts bind.CallOpts // Call options to use throughout this session
- TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
-}
-
-// PublicResolverCallerSession is an auto generated read-only Go binding around an Ethereum contract,
-// with pre-set call options.
-type PublicResolverCallerSession struct {
- Contract *PublicResolverCaller // Generic contract caller binding to set the session for
- CallOpts bind.CallOpts // Call options to use throughout this session
-}
-
-// PublicResolverTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
-// with pre-set transact options.
-type PublicResolverTransactorSession struct {
- Contract *PublicResolverTransactor // Generic contract transactor binding to set the session for
- TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
-}
-
-// PublicResolverRaw is an auto generated low-level Go binding around an Ethereum contract.
-type PublicResolverRaw struct {
- Contract *PublicResolver // Generic contract binding to access the raw methods on
-}
-
-// PublicResolverCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
-type PublicResolverCallerRaw struct {
- Contract *PublicResolverCaller // Generic read-only contract binding to access the raw methods on
-}
-
-// PublicResolverTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
-type PublicResolverTransactorRaw struct {
- Contract *PublicResolverTransactor // Generic write-only contract binding to access the raw methods on
-}
-// NewPublicResolver creates a new instance of PublicResolver, bound to a specific deployed contract.
-func NewPublicResolver(address common.Address, backend bind.ContractBackend) (*PublicResolver, error) {
- contract, err := bindPublicResolver(address, backend, backend)
+ logs, sub, err := _ENS.contract.WatchLogs(opts, "NewOwner", nodeRule, labelRule)
if err != nil {
return nil, err
}
- return &PublicResolver{PublicResolverCaller: PublicResolverCaller{contract: contract}, PublicResolverTransactor: PublicResolverTransactor{contract: contract}}, nil
-}
-
-// NewPublicResolverCaller creates a new read-only instance of PublicResolver, bound to a specific deployed contract.
-func NewPublicResolverCaller(address common.Address, caller bind.ContractCaller) (*PublicResolverCaller, error) {
- contract, err := bindPublicResolver(address, caller, nil)
- if err != nil {
- return nil, err
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(ENSNewOwner)
+ if err := _ENS.contract.UnpackLog(event, "NewOwner", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// ENSNewResolverIterator is returned from FilterNewResolver and is used to iterate over the raw logs and unpacked data for NewResolver events raised by the ENS contract.
+type ENSNewResolverIterator struct {
+ Event *ENSNewResolver // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *ENSNewResolverIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
}
- return &PublicResolverCaller{contract: contract}, nil
-}
-
-// NewPublicResolverTransactor creates a new write-only instance of PublicResolver, bound to a specific deployed contract.
-func NewPublicResolverTransactor(address common.Address, transactor bind.ContractTransactor) (*PublicResolverTransactor, error) {
- contract, err := bindPublicResolver(address, nil, transactor)
- if err != nil {
- return nil, err
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(ENSNewResolver)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
}
- return &PublicResolverTransactor{contract: contract}, nil
-}
-
-// bindPublicResolver binds a generic wrapper to an already deployed contract.
-func bindPublicResolver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
- parsed, err := abi.JSON(strings.NewReader(PublicResolverABI))
- if err != nil {
- return nil, err
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(ENSNewResolver)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
}
- return bind.NewBoundContract(address, parsed, caller, transactor), nil
-}
-
-// Call invokes the (constant) contract method with params as input values and
-// sets the output to result. The result type might be a single field for simple
-// returns, a slice of interfaces for anonymous returns and a struct for named
-// returns.
-func (_PublicResolver *PublicResolverRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
- return _PublicResolver.Contract.PublicResolverCaller.contract.Call(opts, result, method, params...)
-}
-
-// Transfer initiates a plain transaction to move funds to the contract, calling
-// its default method if one is available.
-func (_PublicResolver *PublicResolverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _PublicResolver.Contract.PublicResolverTransactor.contract.Transfer(opts)
-}
-
-// Transact invokes the (paid) contract method with params as input values.
-func (_PublicResolver *PublicResolverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _PublicResolver.Contract.PublicResolverTransactor.contract.Transact(opts, method, params...)
-}
-
-// Call invokes the (constant) contract method with params as input values and
-// sets the output to result. The result type might be a single field for simple
-// returns, a slice of interfaces for anonymous returns and a struct for named
-// returns.
-func (_PublicResolver *PublicResolverCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
- return _PublicResolver.Contract.contract.Call(opts, result, method, params...)
-}
-
-// Transfer initiates a plain transaction to move funds to the contract, calling
-// its default method if one is available.
-func (_PublicResolver *PublicResolverTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _PublicResolver.Contract.contract.Transfer(opts)
-}
-
-// Transact invokes the (paid) contract method with params as input values.
-func (_PublicResolver *PublicResolverTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _PublicResolver.Contract.contract.Transact(opts, method, params...)
-}
-
-// Addr is a free data retrieval call binding the contract method 0x3b3b57de.
-//
-// Solidity: function addr(node bytes32) constant returns(ret address)
-func (_PublicResolver *PublicResolverCaller) Addr(opts *bind.CallOpts, node [32]byte) (common.Address, error) {
- var (
- ret0 = new(common.Address)
- )
- out := ret0
- err := _PublicResolver.contract.Call(opts, out, "addr", node)
- return *ret0, err
-}
-
-// Addr is a free data retrieval call binding the contract method 0x3b3b57de.
-//
-// Solidity: function addr(node bytes32) constant returns(ret address)
-func (_PublicResolver *PublicResolverSession) Addr(node [32]byte) (common.Address, error) {
- return _PublicResolver.Contract.Addr(&_PublicResolver.CallOpts, node)
-}
-
-// Addr is a free data retrieval call binding the contract method 0x3b3b57de.
-//
-// Solidity: function addr(node bytes32) constant returns(ret address)
-func (_PublicResolver *PublicResolverCallerSession) Addr(node [32]byte) (common.Address, error) {
- return _PublicResolver.Contract.Addr(&_PublicResolver.CallOpts, node)
-}
-
-// Content is a free data retrieval call binding the contract method 0x2dff6941.
-//
-// Solidity: function content(node bytes32) constant returns(ret bytes32)
-func (_PublicResolver *PublicResolverCaller) Content(opts *bind.CallOpts, node [32]byte) ([32]byte, error) {
- var (
- ret0 = new([32]byte)
- )
- out := ret0
- err := _PublicResolver.contract.Call(opts, out, "content", node)
- return *ret0, err
-}
-
-// Content is a free data retrieval call binding the contract method 0x2dff6941.
-//
-// Solidity: function content(node bytes32) constant returns(ret bytes32)
-func (_PublicResolver *PublicResolverSession) Content(node [32]byte) ([32]byte, error) {
- return _PublicResolver.Contract.Content(&_PublicResolver.CallOpts, node)
-}
-
-// Content is a free data retrieval call binding the contract method 0x2dff6941.
-//
-// Solidity: function content(node bytes32) constant returns(ret bytes32)
-func (_PublicResolver *PublicResolverCallerSession) Content(node [32]byte) ([32]byte, error) {
- return _PublicResolver.Contract.Content(&_PublicResolver.CallOpts, node)
}
-// Has is a paid mutator transaction binding the contract method 0x41b9dc2b.
-//
-// Solidity: function has(node bytes32, kind bytes32) returns(bool)
-func (_PublicResolver *PublicResolverTransactor) Has(opts *bind.TransactOpts, node [32]byte, kind [32]byte) (*types.Transaction, error) {
- return _PublicResolver.contract.Transact(opts, "has", node, kind)
-}
-
-// Has is a paid mutator transaction binding the contract method 0x41b9dc2b.
-//
-// Solidity: function has(node bytes32, kind bytes32) returns(bool)
-func (_PublicResolver *PublicResolverSession) Has(node [32]byte, kind [32]byte) (*types.Transaction, error) {
- return _PublicResolver.Contract.Has(&_PublicResolver.TransactOpts, node, kind)
+// Error retruned any retrieval or parsing error occurred during filtering.
+func (it *ENSNewResolverIterator) Error() error {
+ return it.fail
}
-// Has is a paid mutator transaction binding the contract method 0x41b9dc2b.
-//
-// Solidity: function has(node bytes32, kind bytes32) returns(bool)
-func (_PublicResolver *PublicResolverTransactorSession) Has(node [32]byte, kind [32]byte) (*types.Transaction, error) {
- return _PublicResolver.Contract.Has(&_PublicResolver.TransactOpts, node, kind)
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *ENSNewResolverIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
}
-// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00.
-//
-// Solidity: function setAddr(node bytes32, addr address) returns()
-func (_PublicResolver *PublicResolverTransactor) SetAddr(opts *bind.TransactOpts, node [32]byte, addr common.Address) (*types.Transaction, error) {
- return _PublicResolver.contract.Transact(opts, "setAddr", node, addr)
+// ENSNewResolver represents a NewResolver event raised by the ENS contract.
+type ENSNewResolver struct {
+ Node [32]byte
+ Resolver common.Address
+ Raw types.Log // Blockchain specific contextual infos
}
-// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00.
+// FilterNewResolver is a free log retrieval operation binding the contract event 0x335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a0.
//
-// Solidity: function setAddr(node bytes32, addr address) returns()
-func (_PublicResolver *PublicResolverSession) SetAddr(node [32]byte, addr common.Address) (*types.Transaction, error) {
- return _PublicResolver.Contract.SetAddr(&_PublicResolver.TransactOpts, node, addr)
-}
+// Solidity: event NewResolver(node indexed bytes32, resolver address)
+func (_ENS *ENSFilterer) FilterNewResolver(opts *bind.FilterOpts, node [][32]byte) (*ENSNewResolverIterator, error) {
-// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00.
-//
-// Solidity: function setAddr(node bytes32, addr address) returns()
-func (_PublicResolver *PublicResolverTransactorSession) SetAddr(node [32]byte, addr common.Address) (*types.Transaction, error) {
- return _PublicResolver.Contract.SetAddr(&_PublicResolver.TransactOpts, node, addr)
-}
-
-// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6.
-//
-// Solidity: function setContent(node bytes32, hash bytes32) returns()
-func (_PublicResolver *PublicResolverTransactor) SetContent(opts *bind.TransactOpts, node [32]byte, hash [32]byte) (*types.Transaction, error) {
- return _PublicResolver.contract.Transact(opts, "setContent", node, hash)
-}
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
-// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6.
-//
-// Solidity: function setContent(node bytes32, hash bytes32) returns()
-func (_PublicResolver *PublicResolverSession) SetContent(node [32]byte, hash [32]byte) (*types.Transaction, error) {
- return _PublicResolver.Contract.SetContent(&_PublicResolver.TransactOpts, node, hash)
+ logs, sub, err := _ENS.contract.FilterLogs(opts, "NewResolver", nodeRule)
+ if err != nil {
+ return nil, err
+ }
+ return &ENSNewResolverIterator{contract: _ENS.contract, event: "NewResolver", logs: logs, sub: sub}, nil
}
-// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6.
+// WatchNewResolver is a free log subscription operation binding the contract event 0x335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a0.
//
-// Solidity: function setContent(node bytes32, hash bytes32) returns()
-func (_PublicResolver *PublicResolverTransactorSession) SetContent(node [32]byte, hash [32]byte) (*types.Transaction, error) {
- return _PublicResolver.Contract.SetContent(&_PublicResolver.TransactOpts, node, hash)
-}
+// Solidity: event NewResolver(node indexed bytes32, resolver address)
+func (_ENS *ENSFilterer) WatchNewResolver(opts *bind.WatchOpts, sink chan<- *ENSNewResolver, node [][32]byte) (event.Subscription, error) {
-// ResolverABI is the input ABI used to generate the binding from.
-const ResolverABI = `[{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"content","outputs":[{"name":"ret","type":"bytes32"}],"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"addr","outputs":[{"name":"ret","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"kind","type":"bytes32"}],"name":"has","outputs":[{"name":"","type":"bool"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"hash","type":"bytes32"}],"name":"ContentChanged","type":"event"}]`
-
-// ResolverBin is the compiled bytecode used for deploying new contracts.
-const ResolverBin = `0x`
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
-// DeployResolver deploys a new Ethereum contract, binding an instance of Resolver to it.
-func DeployResolver(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Resolver, error) {
- parsed, err := abi.JSON(strings.NewReader(ResolverABI))
+ logs, sub, err := _ENS.contract.WatchLogs(opts, "NewResolver", nodeRule)
if err != nil {
- return common.Address{}, nil, nil, err
+ return nil, err
}
- address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ResolverBin), backend)
- if err != nil {
- return common.Address{}, nil, nil, err
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(ENSNewResolver)
+ if err := _ENS.contract.UnpackLog(event, "NewResolver", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// ENSNewTTLIterator is returned from FilterNewTTL and is used to iterate over the raw logs and unpacked data for NewTTL events raised by the ENS contract.
+type ENSNewTTLIterator struct {
+ Event *ENSNewTTL // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *ENSNewTTLIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(ENSNewTTL)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(ENSNewTTL)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
}
- return address, tx, &Resolver{ResolverCaller: ResolverCaller{contract: contract}, ResolverTransactor: ResolverTransactor{contract: contract}}, nil
-}
-
-// Resolver is an auto generated Go binding around an Ethereum contract.
-type Resolver struct {
- ResolverCaller // Read-only binding to the contract
- ResolverTransactor // Write-only binding to the contract
-}
-
-// ResolverCaller is an auto generated read-only Go binding around an Ethereum contract.
-type ResolverCaller struct {
- contract *bind.BoundContract // Generic contract wrapper for the low level calls
-}
-
-// ResolverTransactor is an auto generated write-only Go binding around an Ethereum contract.
-type ResolverTransactor struct {
- contract *bind.BoundContract // Generic contract wrapper for the low level calls
-}
-
-// ResolverSession is an auto generated Go binding around an Ethereum contract,
-// with pre-set call and transact options.
-type ResolverSession struct {
- Contract *Resolver // Generic contract binding to set the session for
- CallOpts bind.CallOpts // Call options to use throughout this session
- TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
-}
-
-// ResolverCallerSession is an auto generated read-only Go binding around an Ethereum contract,
-// with pre-set call options.
-type ResolverCallerSession struct {
- Contract *ResolverCaller // Generic contract caller binding to set the session for
- CallOpts bind.CallOpts // Call options to use throughout this session
}
-// ResolverTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
-// with pre-set transact options.
-type ResolverTransactorSession struct {
- Contract *ResolverTransactor // Generic contract transactor binding to set the session for
- TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+// Error retruned any retrieval or parsing error occurred during filtering.
+func (it *ENSNewTTLIterator) Error() error {
+ return it.fail
}
-// ResolverRaw is an auto generated low-level Go binding around an Ethereum contract.
-type ResolverRaw struct {
- Contract *Resolver // Generic contract binding to access the raw methods on
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *ENSNewTTLIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
}
-// ResolverCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
-type ResolverCallerRaw struct {
- Contract *ResolverCaller // Generic read-only contract binding to access the raw methods on
+// ENSNewTTL represents a NewTTL event raised by the ENS contract.
+type ENSNewTTL struct {
+ Node [32]byte
+ Ttl uint64
+ Raw types.Log // Blockchain specific contextual infos
}
-// ResolverTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
-type ResolverTransactorRaw struct {
- Contract *ResolverTransactor // Generic write-only contract binding to access the raw methods on
-}
+// FilterNewTTL is a free log retrieval operation binding the contract event 0x1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa68.
+//
+// Solidity: event NewTTL(node indexed bytes32, ttl uint64)
+func (_ENS *ENSFilterer) FilterNewTTL(opts *bind.FilterOpts, node [][32]byte) (*ENSNewTTLIterator, error) {
-// NewResolver creates a new instance of Resolver, bound to a specific deployed contract.
-func NewResolver(address common.Address, backend bind.ContractBackend) (*Resolver, error) {
- contract, err := bindResolver(address, backend, backend)
- if err != nil {
- return nil, err
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
}
- return &Resolver{ResolverCaller: ResolverCaller{contract: contract}, ResolverTransactor: ResolverTransactor{contract: contract}}, nil
-}
-// NewResolverCaller creates a new read-only instance of Resolver, bound to a specific deployed contract.
-func NewResolverCaller(address common.Address, caller bind.ContractCaller) (*ResolverCaller, error) {
- contract, err := bindResolver(address, caller, nil)
+ logs, sub, err := _ENS.contract.FilterLogs(opts, "NewTTL", nodeRule)
if err != nil {
return nil, err
}
- return &ResolverCaller{contract: contract}, nil
+ return &ENSNewTTLIterator{contract: _ENS.contract, event: "NewTTL", logs: logs, sub: sub}, nil
}
-// NewResolverTransactor creates a new write-only instance of Resolver, bound to a specific deployed contract.
-func NewResolverTransactor(address common.Address, transactor bind.ContractTransactor) (*ResolverTransactor, error) {
- contract, err := bindResolver(address, nil, transactor)
- if err != nil {
- return nil, err
+// WatchNewTTL is a free log subscription operation binding the contract event 0x1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa68.
+//
+// Solidity: event NewTTL(node indexed bytes32, ttl uint64)
+func (_ENS *ENSFilterer) WatchNewTTL(opts *bind.WatchOpts, sink chan<- *ENSNewTTL, node [][32]byte) (event.Subscription, error) {
+
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
}
- return &ResolverTransactor{contract: contract}, nil
-}
-// bindResolver binds a generic wrapper to an already deployed contract.
-func bindResolver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
- parsed, err := abi.JSON(strings.NewReader(ResolverABI))
+ logs, sub, err := _ENS.contract.WatchLogs(opts, "NewTTL", nodeRule)
if err != nil {
return nil, err
}
- return bind.NewBoundContract(address, parsed, caller, transactor), nil
-}
-
-// Call invokes the (constant) contract method with params as input values and
-// sets the output to result. The result type might be a single field for simple
-// returns, a slice of interfaces for anonymous returns and a struct for named
-// returns.
-func (_Resolver *ResolverRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
- return _Resolver.Contract.ResolverCaller.contract.Call(opts, result, method, params...)
-}
-
-// Transfer initiates a plain transaction to move funds to the contract, calling
-// its default method if one is available.
-func (_Resolver *ResolverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _Resolver.Contract.ResolverTransactor.contract.Transfer(opts)
-}
-
-// Transact invokes the (paid) contract method with params as input values.
-func (_Resolver *ResolverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _Resolver.Contract.ResolverTransactor.contract.Transact(opts, method, params...)
-}
-
-// Call invokes the (constant) contract method with params as input values and
-// sets the output to result. The result type might be a single field for simple
-// returns, a slice of interfaces for anonymous returns and a struct for named
-// returns.
-func (_Resolver *ResolverCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
- return _Resolver.Contract.contract.Call(opts, result, method, params...)
-}
-
-// Transfer initiates a plain transaction to move funds to the contract, calling
-// its default method if one is available.
-func (_Resolver *ResolverTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _Resolver.Contract.contract.Transfer(opts)
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(ENSNewTTL)
+ if err := _ENS.contract.UnpackLog(event, "NewTTL", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// ENSTransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the ENS contract.
+type ENSTransferIterator struct {
+ Event *ENSTransfer // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *ENSTransferIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(ENSTransfer)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(ENSTransfer)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
}
-// Transact invokes the (paid) contract method with params as input values.
-func (_Resolver *ResolverTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _Resolver.Contract.contract.Transact(opts, method, params...)
+// Error retruned any retrieval or parsing error occurred during filtering.
+func (it *ENSTransferIterator) Error() error {
+ return it.fail
}
-// Addr is a free data retrieval call binding the contract method 0x3b3b57de.
-//
-// Solidity: function addr(node bytes32) constant returns(ret address)
-func (_Resolver *ResolverCaller) Addr(opts *bind.CallOpts, node [32]byte) (common.Address, error) {
- var (
- ret0 = new(common.Address)
- )
- out := ret0
- err := _Resolver.contract.Call(opts, out, "addr", node)
- return *ret0, err
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *ENSTransferIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
}
-// Addr is a free data retrieval call binding the contract method 0x3b3b57de.
-//
-// Solidity: function addr(node bytes32) constant returns(ret address)
-func (_Resolver *ResolverSession) Addr(node [32]byte) (common.Address, error) {
- return _Resolver.Contract.Addr(&_Resolver.CallOpts, node)
+// ENSTransfer represents a Transfer event raised by the ENS contract.
+type ENSTransfer struct {
+ Node [32]byte
+ Owner common.Address
+ Raw types.Log // Blockchain specific contextual infos
}
-// Addr is a free data retrieval call binding the contract method 0x3b3b57de.
+// FilterTransfer is a free log retrieval operation binding the contract event 0xd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d266.
//
-// Solidity: function addr(node bytes32) constant returns(ret address)
-func (_Resolver *ResolverCallerSession) Addr(node [32]byte) (common.Address, error) {
- return _Resolver.Contract.Addr(&_Resolver.CallOpts, node)
-}
+// Solidity: event Transfer(node indexed bytes32, owner address)
+func (_ENS *ENSFilterer) FilterTransfer(opts *bind.FilterOpts, node [][32]byte) (*ENSTransferIterator, error) {
-// Content is a free data retrieval call binding the contract method 0x2dff6941.
-//
-// Solidity: function content(node bytes32) constant returns(ret bytes32)
-func (_Resolver *ResolverCaller) Content(opts *bind.CallOpts, node [32]byte) ([32]byte, error) {
- var (
- ret0 = new([32]byte)
- )
- out := ret0
- err := _Resolver.contract.Call(opts, out, "content", node)
- return *ret0, err
-}
-
-// Content is a free data retrieval call binding the contract method 0x2dff6941.
-//
-// Solidity: function content(node bytes32) constant returns(ret bytes32)
-func (_Resolver *ResolverSession) Content(node [32]byte) ([32]byte, error) {
- return _Resolver.Contract.Content(&_Resolver.CallOpts, node)
-}
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
-// Content is a free data retrieval call binding the contract method 0x2dff6941.
-//
-// Solidity: function content(node bytes32) constant returns(ret bytes32)
-func (_Resolver *ResolverCallerSession) Content(node [32]byte) ([32]byte, error) {
- return _Resolver.Contract.Content(&_Resolver.CallOpts, node)
+ logs, sub, err := _ENS.contract.FilterLogs(opts, "Transfer", nodeRule)
+ if err != nil {
+ return nil, err
+ }
+ return &ENSTransferIterator{contract: _ENS.contract, event: "Transfer", logs: logs, sub: sub}, nil
}
-// Has is a paid mutator transaction binding the contract method 0x41b9dc2b.
+// WatchTransfer is a free log subscription operation binding the contract event 0xd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d266.
//
-// Solidity: function has(node bytes32, kind bytes32) returns(bool)
-func (_Resolver *ResolverTransactor) Has(opts *bind.TransactOpts, node [32]byte, kind [32]byte) (*types.Transaction, error) {
- return _Resolver.contract.Transact(opts, "has", node, kind)
-}
+// Solidity: event Transfer(node indexed bytes32, owner address)
+func (_ENS *ENSFilterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *ENSTransfer, node [][32]byte) (event.Subscription, error) {
-// Has is a paid mutator transaction binding the contract method 0x41b9dc2b.
-//
-// Solidity: function has(node bytes32, kind bytes32) returns(bool)
-func (_Resolver *ResolverSession) Has(node [32]byte, kind [32]byte) (*types.Transaction, error) {
- return _Resolver.Contract.Has(&_Resolver.TransactOpts, node, kind)
-}
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
-// Has is a paid mutator transaction binding the contract method 0x41b9dc2b.
-//
-// Solidity: function has(node bytes32, kind bytes32) returns(bool)
-func (_Resolver *ResolverTransactorSession) Has(node [32]byte, kind [32]byte) (*types.Transaction, error) {
- return _Resolver.Contract.Has(&_Resolver.TransactOpts, node, kind)
+ logs, sub, err := _ENS.contract.WatchLogs(opts, "Transfer", nodeRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(ENSTransfer)
+ if err := _ENS.contract.UnpackLog(event, "Transfer", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
}
diff --git a/contracts/ens/contract/ens.sol b/contracts/ens/contract/ens.sol
deleted file mode 100644
index 114cd7319..000000000
--- a/contracts/ens/contract/ens.sol
+++ /dev/null
@@ -1,226 +0,0 @@
-// Ethereum Name Service contracts by Nick Johnson <nick@ethereum.org>
-//
-// To the extent possible under law, the person who associated CC0 with
-// ENS contracts has waived all copyright and related or neighboring rights
-// to ENS.
-//
-// You should have received a copy of the CC0 legalcode along with this
-// work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
-
-/**
- * The ENS registry contract.
- */
-contract ENS {
- struct Record {
- address owner;
- address resolver;
- }
-
- mapping(bytes32=>Record) records;
-
- // Logged when the owner of a node assigns a new owner to a subnode.
- event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
-
- // Logged when the owner of a node transfers ownership to a new account.
- event Transfer(bytes32 indexed node, address owner);
-
- // Logged when the owner of a node changes the resolver for that node.
- event NewResolver(bytes32 indexed node, address resolver);
-
- // Permits modifications only by the owner of the specified node.
- modifier only_owner(bytes32 node) {
- if(records[node].owner != msg.sender) throw;
- _
- }
-
- /**
- * Constructs a new ENS registrar, with the provided address as the owner of the root node.
- */
- function ENS(address owner) {
- records[0].owner = owner;
- }
-
- /**
- * Returns the address that owns the specified node.
- */
- function owner(bytes32 node) constant returns (address) {
- return records[node].owner;
- }
-
- /**
- * Returns the address of the resolver for the specified node.
- */
- function resolver(bytes32 node) constant returns (address) {
- return records[node].resolver;
- }
-
- /**
- * Transfers ownership of a node to a new address. May only be called by the current
- * owner of the node.
- * @param node The node to transfer ownership of.
- * @param owner The address of the new owner.
- */
- function setOwner(bytes32 node, address owner) only_owner(node) {
- Transfer(node, owner);
- records[node].owner = owner;
- }
-
- /**
- * Transfers ownership of a subnode sha3(node, label) to a new address. May only be
- * called by the owner of the parent node.
- * @param node The parent node.
- * @param label The hash of the label specifying the subnode.
- * @param owner The address of the new owner.
- */
- function setSubnodeOwner(bytes32 node, bytes32 label, address owner) only_owner(node) {
- var subnode = sha3(node, label);
- NewOwner(node, label, owner);
- records[subnode].owner = owner;
- }
-
- /**
- * Sets the resolver address for the specified node.
- * @param node The node to update.
- * @param resolver The address of the resolver.
- */
- function setResolver(bytes32 node, address resolver) only_owner(node) {
- NewResolver(node, resolver);
- records[node].resolver = resolver;
- }
-}
-
-/**
- * A registrar that allocates subdomains to the first person to claim them. It also deploys
- * a simple resolver contract and sets that as the default resolver on new names for
- * convenience.
- */
-contract FIFSRegistrar {
- ENS ens;
- PublicResolver defaultResolver;
- bytes32 rootNode;
-
- /**
- * Constructor.
- * @param ensAddr The address of the ENS registry.
- * @param node The node that this registrar administers.
- */
- function FIFSRegistrar(address ensAddr, bytes32 node) {
- ens = ENS(ensAddr);
- defaultResolver = new PublicResolver(ensAddr);
- rootNode = node;
- }
-
- /**
- * Register a name, or change the owner of an existing registration.
- * @param subnode The hash of the label to register.
- * @param owner The address of the new owner.
- */
- function register(bytes32 subnode, address owner) {
- var node = sha3(rootNode, subnode);
- var currentOwner = ens.owner(node);
- if(currentOwner != 0 && currentOwner != msg.sender)
- throw;
-
- // Temporarily set ourselves as the owner
- ens.setSubnodeOwner(rootNode, subnode, this);
- // Set up the default resolver
- ens.setResolver(node, defaultResolver);
- // Set the owner to the real owner
- ens.setOwner(node, owner);
- }
-}
-
-contract Resolver {
- event AddrChanged(bytes32 indexed node, address a);
- event ContentChanged(bytes32 indexed node, bytes32 hash);
-
- function has(bytes32 node, bytes32 kind) returns (bool);
- function addr(bytes32 node) constant returns (address ret);
- function content(bytes32 node) constant returns (bytes32 ret);
-}
-
-/**
- * A simple resolver anyone can use; only allows the owner of a node to set its
- * address.
- */
-contract PublicResolver is Resolver {
- ENS ens;
- mapping(bytes32=>address) addresses;
- mapping(bytes32=>bytes32) contents;
-
- modifier only_owner(bytes32 node) {
- if(ens.owner(node) != msg.sender) throw;
- _
- }
-
- /**
- * Constructor.
- * @param ensAddr The ENS registrar contract.
- */
- function PublicResolver(address ensAddr) {
- ens = ENS(ensAddr);
- }
-
- /**
- * Fallback function.
- */
- function() {
- throw;
- }
-
- /**
- * Returns true if the specified node has the specified record type.
- * @param node The ENS node to query.
- * @param kind The record type name, as specified in EIP137.
- * @return True if this resolver has a record of the provided type on the
- * provided node.
- */
- function has(bytes32 node, bytes32 kind) returns (bool) {
- return (kind == "addr" && addresses[node] != 0) ||
- (kind == "content" && contents[node] != 0);
- }
-
- /**
- * Returns the address associated with an ENS node.
- * @param node The ENS node to query.
- * @return The associated address.
- */
- function addr(bytes32 node) constant returns (address ret) {
- ret = addresses[node];
- if(ret == 0)
- throw;
- }
-
- /**
- * Returns the content hash associated with an ENS node.
- * @param node The ENS node to query.
- * @return The associated content hash.
- */
- function content(bytes32 node) constant returns (bytes32 ret) {
- ret = contents[node];
- if(ret == 0)
- throw;
- }
-
- /**
- * Sets the address associated with an ENS node.
- * May only be called by the owner of that node in the ENS registry.
- * @param node The node to update.
- * @param addr The address to set.
- */
- function setAddr(bytes32 node, address addr) only_owner(node) {
- addresses[node] = addr;
- AddrChanged(node, addr);
- }
-
- /**
- * Sets the content hash associated with an ENS node.
- * May only be called by the owner of that node in the ENS registry.
- * @param node The node to update.
- * @param hash The content hash to set.
- */
- function setContent(bytes32 node, bytes32 hash) only_owner(node) {
- contents[node] = hash;
- ContentChanged(node, hash);
- }
-}
diff --git a/contracts/ens/contract/fifsregistrar.go b/contracts/ens/contract/fifsregistrar.go
new file mode 100644
index 000000000..a08380adf
--- /dev/null
+++ b/contracts/ens/contract/fifsregistrar.go
@@ -0,0 +1,195 @@
+// Code generated - DO NOT EDIT.
+// This file is a generated binding and any manual changes will be lost.
+
+package contract
+
+import (
+ "strings"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+)
+
+// FIFSRegistrarABI is the input ABI used to generate the binding from.
+const FIFSRegistrarABI = "[{\"constant\":false,\"inputs\":[{\"name\":\"subnode\",\"type\":\"bytes32\"},{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"register\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"ensAddr\",\"type\":\"address\"},{\"name\":\"node\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]"
+
+// FIFSRegistrarBin is the compiled bytecode used for deploying new contracts.
+const FIFSRegistrarBin = `0x6060604052341561000f57600080fd5b604051604080610224833981016040528080519190602001805160008054600160a060020a03909516600160a060020a03199095169490941790935550506001556101c58061005f6000396000f3006060604052600436106100275763ffffffff60e060020a600035041663d22057a9811461002c575b600080fd5b341561003757600080fd5b61004e600435600160a060020a0360243516610050565b005b816000806001548360405191825260208201526040908101905190819003902060008054919350600160a060020a03909116906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156100c857600080fd5b6102c65a03f115156100d957600080fd5b5050506040518051915050600160a060020a0381161580159061010e575033600160a060020a031681600160a060020a031614155b1561011857600080fd5b600054600154600160a060020a03909116906306ab592390878760405160e060020a63ffffffff861602815260048101939093526024830191909152600160a060020a03166044820152606401600060405180830381600087803b151561017e57600080fd5b6102c65a03f1151561018f57600080fd5b50505050505050505600a165627a7a723058206fb963cb168d5e3a51af12cd6bb23e324dbd32dd4954f43653ba27e66b68ea650029`
+
+// DeployFIFSRegistrar deploys a new Ethereum contract, binding an instance of FIFSRegistrar to it.
+func DeployFIFSRegistrar(auth *bind.TransactOpts, backend bind.ContractBackend, ensAddr common.Address, node [32]byte) (common.Address, *types.Transaction, *FIFSRegistrar, error) {
+ parsed, err := abi.JSON(strings.NewReader(FIFSRegistrarABI))
+ if err != nil {
+ return common.Address{}, nil, nil, err
+ }
+ address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(FIFSRegistrarBin), backend, ensAddr, node)
+ if err != nil {
+ return common.Address{}, nil, nil, err
+ }
+ return address, tx, &FIFSRegistrar{FIFSRegistrarCaller: FIFSRegistrarCaller{contract: contract}, FIFSRegistrarTransactor: FIFSRegistrarTransactor{contract: contract}, FIFSRegistrarFilterer: FIFSRegistrarFilterer{contract: contract}}, nil
+}
+
+// FIFSRegistrar is an auto generated Go binding around an Ethereum contract.
+type FIFSRegistrar struct {
+ FIFSRegistrarCaller // Read-only binding to the contract
+ FIFSRegistrarTransactor // Write-only binding to the contract
+ FIFSRegistrarFilterer // Log filterer for contract events
+}
+
+// FIFSRegistrarCaller is an auto generated read-only Go binding around an Ethereum contract.
+type FIFSRegistrarCaller struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// FIFSRegistrarTransactor is an auto generated write-only Go binding around an Ethereum contract.
+type FIFSRegistrarTransactor struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// FIFSRegistrarFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
+type FIFSRegistrarFilterer struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// FIFSRegistrarSession is an auto generated Go binding around an Ethereum contract,
+// with pre-set call and transact options.
+type FIFSRegistrarSession struct {
+ Contract *FIFSRegistrar // Generic contract binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// FIFSRegistrarCallerSession is an auto generated read-only Go binding around an Ethereum contract,
+// with pre-set call options.
+type FIFSRegistrarCallerSession struct {
+ Contract *FIFSRegistrarCaller // Generic contract caller binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+}
+
+// FIFSRegistrarTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
+// with pre-set transact options.
+type FIFSRegistrarTransactorSession struct {
+ Contract *FIFSRegistrarTransactor // Generic contract transactor binding to set the session for
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// FIFSRegistrarRaw is an auto generated low-level Go binding around an Ethereum contract.
+type FIFSRegistrarRaw struct {
+ Contract *FIFSRegistrar // Generic contract binding to access the raw methods on
+}
+
+// FIFSRegistrarCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
+type FIFSRegistrarCallerRaw struct {
+ Contract *FIFSRegistrarCaller // Generic read-only contract binding to access the raw methods on
+}
+
+// FIFSRegistrarTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
+type FIFSRegistrarTransactorRaw struct {
+ Contract *FIFSRegistrarTransactor // Generic write-only contract binding to access the raw methods on
+}
+
+// NewFIFSRegistrar creates a new instance of FIFSRegistrar, bound to a specific deployed contract.
+func NewFIFSRegistrar(address common.Address, backend bind.ContractBackend) (*FIFSRegistrar, error) {
+ contract, err := bindFIFSRegistrar(address, backend, backend, backend)
+ if err != nil {
+ return nil, err
+ }
+ return &FIFSRegistrar{FIFSRegistrarCaller: FIFSRegistrarCaller{contract: contract}, FIFSRegistrarTransactor: FIFSRegistrarTransactor{contract: contract}, FIFSRegistrarFilterer: FIFSRegistrarFilterer{contract: contract}}, nil
+}
+
+// NewFIFSRegistrarCaller creates a new read-only instance of FIFSRegistrar, bound to a specific deployed contract.
+func NewFIFSRegistrarCaller(address common.Address, caller bind.ContractCaller) (*FIFSRegistrarCaller, error) {
+ contract, err := bindFIFSRegistrar(address, caller, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &FIFSRegistrarCaller{contract: contract}, nil
+}
+
+// NewFIFSRegistrarTransactor creates a new write-only instance of FIFSRegistrar, bound to a specific deployed contract.
+func NewFIFSRegistrarTransactor(address common.Address, transactor bind.ContractTransactor) (*FIFSRegistrarTransactor, error) {
+ contract, err := bindFIFSRegistrar(address, nil, transactor, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &FIFSRegistrarTransactor{contract: contract}, nil
+}
+
+// NewFIFSRegistrarFilterer creates a new log filterer instance of FIFSRegistrar, bound to a specific deployed contract.
+func NewFIFSRegistrarFilterer(address common.Address, filterer bind.ContractFilterer) (*FIFSRegistrarFilterer, error) {
+ contract, err := bindFIFSRegistrar(address, nil, nil, filterer)
+ if err != nil {
+ return nil, err
+ }
+ return &FIFSRegistrarFilterer{contract: contract}, nil
+}
+
+// bindFIFSRegistrar binds a generic wrapper to an already deployed contract.
+func bindFIFSRegistrar(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
+ parsed, err := abi.JSON(strings.NewReader(FIFSRegistrarABI))
+ if err != nil {
+ return nil, err
+ }
+ return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_FIFSRegistrar *FIFSRegistrarRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
+ return _FIFSRegistrar.Contract.FIFSRegistrarCaller.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_FIFSRegistrar *FIFSRegistrarRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _FIFSRegistrar.Contract.FIFSRegistrarTransactor.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_FIFSRegistrar *FIFSRegistrarRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _FIFSRegistrar.Contract.FIFSRegistrarTransactor.contract.Transact(opts, method, params...)
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_FIFSRegistrar *FIFSRegistrarCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
+ return _FIFSRegistrar.Contract.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_FIFSRegistrar *FIFSRegistrarTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _FIFSRegistrar.Contract.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_FIFSRegistrar *FIFSRegistrarTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _FIFSRegistrar.Contract.contract.Transact(opts, method, params...)
+}
+
+// Register is a paid mutator transaction binding the contract method 0xd22057a9.
+//
+// Solidity: function register(subnode bytes32, owner address) returns()
+func (_FIFSRegistrar *FIFSRegistrarTransactor) Register(opts *bind.TransactOpts, subnode [32]byte, owner common.Address) (*types.Transaction, error) {
+ return _FIFSRegistrar.contract.Transact(opts, "register", subnode, owner)
+}
+
+// Register is a paid mutator transaction binding the contract method 0xd22057a9.
+//
+// Solidity: function register(subnode bytes32, owner address) returns()
+func (_FIFSRegistrar *FIFSRegistrarSession) Register(subnode [32]byte, owner common.Address) (*types.Transaction, error) {
+ return _FIFSRegistrar.Contract.Register(&_FIFSRegistrar.TransactOpts, subnode, owner)
+}
+
+// Register is a paid mutator transaction binding the contract method 0xd22057a9.
+//
+// Solidity: function register(subnode bytes32, owner address) returns()
+func (_FIFSRegistrar *FIFSRegistrarTransactorSession) Register(subnode [32]byte, owner common.Address) (*types.Transaction, error) {
+ return _FIFSRegistrar.Contract.Register(&_FIFSRegistrar.TransactOpts, subnode, owner)
+}
diff --git a/contracts/ens/contract/publicresolver.go b/contracts/ens/contract/publicresolver.go
new file mode 100644
index 000000000..c567d5884
--- /dev/null
+++ b/contracts/ens/contract/publicresolver.go
@@ -0,0 +1,1321 @@
+// Code generated - DO NOT EDIT.
+// This file is a generated binding and any manual changes will be lost.
+
+package contract
+
+import (
+ "math/big"
+ "strings"
+
+ ethereum "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/event"
+)
+
+// PublicResolverABI is the input ABI used to generate the binding from.
+const PublicResolverABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"key\",\"type\":\"string\"},{\"name\":\"value\",\"type\":\"string\"}],\"name\":\"setText\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"contentTypes\",\"type\":\"uint256\"}],\"name\":\"ABI\",\"outputs\":[{\"name\":\"contentType\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"x\",\"type\":\"bytes32\"},{\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"setPubkey\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"content\",\"outputs\":[{\"name\":\"ret\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"name\":\"ret\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"key\",\"type\":\"string\"}],\"name\":\"text\",\"outputs\":[{\"name\":\"ret\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"contentType\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"setABI\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"name\",\"outputs\":[{\"name\":\"ret\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"name\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"setContent\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"pubkey\",\"outputs\":[{\"name\":\"x\",\"type\":\"bytes32\"},{\"name\":\"y\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"ensAddr\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"a\",\"type\":\"address\"}],\"name\":\"AddrChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"ContentChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NameChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"contentType\",\"type\":\"uint256\"}],\"name\":\"ABIChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"x\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"PubkeyChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"indexedKey\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"key\",\"type\":\"string\"}],\"name\":\"TextChanged\",\"type\":\"event\"}]"
+
+// PublicResolverBin is the compiled bytecode used for deploying new contracts.
+const PublicResolverBin = `0x6060604052341561000f57600080fd5b6040516020806111b28339810160405280805160008054600160a060020a03909216600160a060020a0319909216919091179055505061115e806100546000396000f3006060604052600436106100ab5763ffffffff60e060020a60003504166301ffc9a781146100b057806310f13a8c146100e45780632203ab561461017e57806329cd62ea146102155780632dff6941146102315780633b3b57de1461025957806359d1d43c1461028b578063623195b014610358578063691f3431146103b457806377372213146103ca578063c3d014d614610420578063c869023314610439578063d5fa2b0014610467575b600080fd5b34156100bb57600080fd5b6100d0600160e060020a031960043516610489565b604051901515815260200160405180910390f35b34156100ef57600080fd5b61017c600480359060446024803590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284378201915050505050509190803590602001908201803590602001908080601f0160208091040260200160405190810160405281815292919060208401838380828437509496506105f695505050505050565b005b341561018957600080fd5b610197600435602435610807565b60405182815260406020820181815290820183818151815260200191508051906020019080838360005b838110156101d95780820151838201526020016101c1565b50505050905090810190601f1680156102065780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b341561022057600080fd5b61017c600435602435604435610931565b341561023c57600080fd5b610247600435610a30565b60405190815260200160405180910390f35b341561026457600080fd5b61026f600435610a46565b604051600160a060020a03909116815260200160405180910390f35b341561029657600080fd5b6102e1600480359060446024803590810190830135806020601f82018190048102016040519081016040528181529291906020840183838082843750949650610a6195505050505050565b60405160208082528190810183818151815260200191508051906020019080838360005b8381101561031d578082015183820152602001610305565b50505050905090810190601f16801561034a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561036357600080fd5b61017c600480359060248035919060649060443590810190830135806020601f82018190048102016040519081016040528181529291906020840183838082843750949650610b8095505050505050565b34156103bf57600080fd5b6102e1600435610c7c565b34156103d557600080fd5b61017c600480359060446024803590810190830135806020601f82018190048102016040519081016040528181529291906020840183838082843750949650610d4295505050505050565b341561042b57600080fd5b61017c600435602435610e8c565b341561044457600080fd5b61044f600435610f65565b60405191825260208201526040908101905180910390f35b341561047257600080fd5b61017c600435600160a060020a0360243516610f82565b6000600160e060020a031982167f3b3b57de0000000000000000000000000000000000000000000000000000000014806104ec5750600160e060020a031982167fd8389dc500000000000000000000000000000000000000000000000000000000145b806105205750600160e060020a031982167f691f343100000000000000000000000000000000000000000000000000000000145b806105545750600160e060020a031982167f2203ab5600000000000000000000000000000000000000000000000000000000145b806105885750600160e060020a031982167fc869023300000000000000000000000000000000000000000000000000000000145b806105bc5750600160e060020a031982167f59d1d43c00000000000000000000000000000000000000000000000000000000145b806105f05750600160e060020a031982167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b600080548491600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561064f57600080fd5b6102c65a03f1151561066057600080fd5b50505060405180519050600160a060020a031614151561067f57600080fd5b6000848152600160205260409081902083916005909101908590518082805190602001908083835b602083106106c65780518252601f1990920191602091820191016106a7565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902090805161070a929160200190611085565b50826040518082805190602001908083835b6020831061073b5780518252601f19909201916020918201910161071c565b6001836020036101000a0380198251168184511617909252505050919091019250604091505051908190039020847fd8c9334b1a9c2f9da342a0a2b32629c1a229b6445dad78947f674b44444a75508560405160208082528190810183818151815260200191508051906020019080838360005b838110156107c75780820151838201526020016107af565b50505050905090810190601f1680156107f45780820380516001836020036101000a031916815260200191505b509250505060405180910390a350505050565b6000610811611103565b60008481526001602081905260409091209092505b838311610924578284161580159061085f5750600083815260068201602052604081205460026000196101006001841615020190911604115b15610919578060060160008481526020019081526020016000208054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561090d5780601f106108e25761010080835404028352916020019161090d565b820191906000526020600020905b8154815290600101906020018083116108f057829003601f168201915b50505050509150610929565b600290920291610826565b600092505b509250929050565b600080548491600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561098a57600080fd5b6102c65a03f1151561099b57600080fd5b50505060405180519050600160a060020a03161415156109ba57600080fd5b6040805190810160409081528482526020808301859052600087815260019091522060030181518155602082015160019091015550837f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e46848460405191825260208201526040908101905180910390a250505050565b6000908152600160208190526040909120015490565b600090815260016020526040902054600160a060020a031690565b610a69611103565b60008381526001602052604090819020600501908390518082805190602001908083835b60208310610aac5780518252601f199092019160209182019101610a8d565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b735780601f10610b4857610100808354040283529160200191610b73565b820191906000526020600020905b815481529060010190602001808311610b5657829003601f168201915b5050505050905092915050565b600080548491600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610bd957600080fd5b6102c65a03f11515610bea57600080fd5b50505060405180519050600160a060020a0316141515610c0957600080fd5b6000198301831615610c1a57600080fd5b60008481526001602090815260408083208684526006019091529020828051610c47929160200190611085565b5082847faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe360405160405180910390a350505050565b610c84611103565b6001600083600019166000191681526020019081526020016000206002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d365780601f10610d0b57610100808354040283529160200191610d36565b820191906000526020600020905b815481529060010190602001808311610d1957829003601f168201915b50505050509050919050565b600080548391600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610d9b57600080fd5b6102c65a03f11515610dac57600080fd5b50505060405180519050600160a060020a0316141515610dcb57600080fd5b6000838152600160205260409020600201828051610ded929160200190611085565b50827fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78360405160208082528190810183818151815260200191508051906020019080838360005b83811015610e4d578082015183820152602001610e35565b50505050905090810190601f168015610e7a5780820380516001836020036101000a031916815260200191505b509250505060405180910390a2505050565b600080548391600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610ee557600080fd5b6102c65a03f11515610ef657600080fd5b50505060405180519050600160a060020a0316141515610f1557600080fd5b6000838152600160208190526040918290200183905583907f0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc9084905190815260200160405180910390a2505050565b600090815260016020526040902060038101546004909101549091565b600080548391600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610fdb57600080fd5b6102c65a03f11515610fec57600080fd5b50505060405180519050600160a060020a031614151561100b57600080fd5b60008381526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03851617905583907f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd290849051600160a060020a03909116815260200160405180910390a2505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106110c657805160ff19168380011785556110f3565b828001600101855582156110f3579182015b828111156110f35782518255916020019190600101906110d8565b506110ff929150611115565b5090565b60206040519081016040526000815290565b61112f91905b808211156110ff576000815560010161111b565b905600a165627a7a723058201ecacbc445b9fbcd91b0ab164389f69d7283b856883bc7437eeed1008345a4920029`
+
+// DeployPublicResolver deploys a new Ethereum contract, binding an instance of PublicResolver to it.
+func DeployPublicResolver(auth *bind.TransactOpts, backend bind.ContractBackend, ensAddr common.Address) (common.Address, *types.Transaction, *PublicResolver, error) {
+ parsed, err := abi.JSON(strings.NewReader(PublicResolverABI))
+ if err != nil {
+ return common.Address{}, nil, nil, err
+ }
+ address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(PublicResolverBin), backend, ensAddr)
+ if err != nil {
+ return common.Address{}, nil, nil, err
+ }
+ return address, tx, &PublicResolver{PublicResolverCaller: PublicResolverCaller{contract: contract}, PublicResolverTransactor: PublicResolverTransactor{contract: contract}, PublicResolverFilterer: PublicResolverFilterer{contract: contract}}, nil
+}
+
+// PublicResolver is an auto generated Go binding around an Ethereum contract.
+type PublicResolver struct {
+ PublicResolverCaller // Read-only binding to the contract
+ PublicResolverTransactor // Write-only binding to the contract
+ PublicResolverFilterer // Log filterer for contract events
+}
+
+// PublicResolverCaller is an auto generated read-only Go binding around an Ethereum contract.
+type PublicResolverCaller struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// PublicResolverTransactor is an auto generated write-only Go binding around an Ethereum contract.
+type PublicResolverTransactor struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// PublicResolverFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
+type PublicResolverFilterer struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// PublicResolverSession is an auto generated Go binding around an Ethereum contract,
+// with pre-set call and transact options.
+type PublicResolverSession struct {
+ Contract *PublicResolver // Generic contract binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// PublicResolverCallerSession is an auto generated read-only Go binding around an Ethereum contract,
+// with pre-set call options.
+type PublicResolverCallerSession struct {
+ Contract *PublicResolverCaller // Generic contract caller binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+}
+
+// PublicResolverTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
+// with pre-set transact options.
+type PublicResolverTransactorSession struct {
+ Contract *PublicResolverTransactor // Generic contract transactor binding to set the session for
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// PublicResolverRaw is an auto generated low-level Go binding around an Ethereum contract.
+type PublicResolverRaw struct {
+ Contract *PublicResolver // Generic contract binding to access the raw methods on
+}
+
+// PublicResolverCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
+type PublicResolverCallerRaw struct {
+ Contract *PublicResolverCaller // Generic read-only contract binding to access the raw methods on
+}
+
+// PublicResolverTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
+type PublicResolverTransactorRaw struct {
+ Contract *PublicResolverTransactor // Generic write-only contract binding to access the raw methods on
+}
+
+// NewPublicResolver creates a new instance of PublicResolver, bound to a specific deployed contract.
+func NewPublicResolver(address common.Address, backend bind.ContractBackend) (*PublicResolver, error) {
+ contract, err := bindPublicResolver(address, backend, backend, backend)
+ if err != nil {
+ return nil, err
+ }
+ return &PublicResolver{PublicResolverCaller: PublicResolverCaller{contract: contract}, PublicResolverTransactor: PublicResolverTransactor{contract: contract}, PublicResolverFilterer: PublicResolverFilterer{contract: contract}}, nil
+}
+
+// NewPublicResolverCaller creates a new read-only instance of PublicResolver, bound to a specific deployed contract.
+func NewPublicResolverCaller(address common.Address, caller bind.ContractCaller) (*PublicResolverCaller, error) {
+ contract, err := bindPublicResolver(address, caller, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &PublicResolverCaller{contract: contract}, nil
+}
+
+// NewPublicResolverTransactor creates a new write-only instance of PublicResolver, bound to a specific deployed contract.
+func NewPublicResolverTransactor(address common.Address, transactor bind.ContractTransactor) (*PublicResolverTransactor, error) {
+ contract, err := bindPublicResolver(address, nil, transactor, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &PublicResolverTransactor{contract: contract}, nil
+}
+
+// NewPublicResolverFilterer creates a new log filterer instance of PublicResolver, bound to a specific deployed contract.
+func NewPublicResolverFilterer(address common.Address, filterer bind.ContractFilterer) (*PublicResolverFilterer, error) {
+ contract, err := bindPublicResolver(address, nil, nil, filterer)
+ if err != nil {
+ return nil, err
+ }
+ return &PublicResolverFilterer{contract: contract}, nil
+}
+
+// bindPublicResolver binds a generic wrapper to an already deployed contract.
+func bindPublicResolver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
+ parsed, err := abi.JSON(strings.NewReader(PublicResolverABI))
+ if err != nil {
+ return nil, err
+ }
+ return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_PublicResolver *PublicResolverRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
+ return _PublicResolver.Contract.PublicResolverCaller.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_PublicResolver *PublicResolverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _PublicResolver.Contract.PublicResolverTransactor.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_PublicResolver *PublicResolverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _PublicResolver.Contract.PublicResolverTransactor.contract.Transact(opts, method, params...)
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_PublicResolver *PublicResolverCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
+ return _PublicResolver.Contract.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_PublicResolver *PublicResolverTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _PublicResolver.Contract.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_PublicResolver *PublicResolverTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _PublicResolver.Contract.contract.Transact(opts, method, params...)
+}
+
+// ABI is a free data retrieval call binding the contract method 0x2203ab56.
+//
+// Solidity: function ABI(node bytes32, contentTypes uint256) constant returns(contentType uint256, data bytes)
+func (_PublicResolver *PublicResolverCaller) ABI(opts *bind.CallOpts, node [32]byte, contentTypes *big.Int) (struct {
+ ContentType *big.Int
+ Data []byte
+}, error) {
+ ret := new(struct {
+ ContentType *big.Int
+ Data []byte
+ })
+ out := ret
+ err := _PublicResolver.contract.Call(opts, out, "ABI", node, contentTypes)
+ return *ret, err
+}
+
+// ABI is a free data retrieval call binding the contract method 0x2203ab56.
+//
+// Solidity: function ABI(node bytes32, contentTypes uint256) constant returns(contentType uint256, data bytes)
+func (_PublicResolver *PublicResolverSession) ABI(node [32]byte, contentTypes *big.Int) (struct {
+ ContentType *big.Int
+ Data []byte
+}, error) {
+ return _PublicResolver.Contract.ABI(&_PublicResolver.CallOpts, node, contentTypes)
+}
+
+// ABI is a free data retrieval call binding the contract method 0x2203ab56.
+//
+// Solidity: function ABI(node bytes32, contentTypes uint256) constant returns(contentType uint256, data bytes)
+func (_PublicResolver *PublicResolverCallerSession) ABI(node [32]byte, contentTypes *big.Int) (struct {
+ ContentType *big.Int
+ Data []byte
+}, error) {
+ return _PublicResolver.Contract.ABI(&_PublicResolver.CallOpts, node, contentTypes)
+}
+
+// Addr is a free data retrieval call binding the contract method 0x3b3b57de.
+//
+// Solidity: function addr(node bytes32) constant returns(ret address)
+func (_PublicResolver *PublicResolverCaller) Addr(opts *bind.CallOpts, node [32]byte) (common.Address, error) {
+ var (
+ ret0 = new(common.Address)
+ )
+ out := ret0
+ err := _PublicResolver.contract.Call(opts, out, "addr", node)
+ return *ret0, err
+}
+
+// Addr is a free data retrieval call binding the contract method 0x3b3b57de.
+//
+// Solidity: function addr(node bytes32) constant returns(ret address)
+func (_PublicResolver *PublicResolverSession) Addr(node [32]byte) (common.Address, error) {
+ return _PublicResolver.Contract.Addr(&_PublicResolver.CallOpts, node)
+}
+
+// Addr is a free data retrieval call binding the contract method 0x3b3b57de.
+//
+// Solidity: function addr(node bytes32) constant returns(ret address)
+func (_PublicResolver *PublicResolverCallerSession) Addr(node [32]byte) (common.Address, error) {
+ return _PublicResolver.Contract.Addr(&_PublicResolver.CallOpts, node)
+}
+
+// Content is a free data retrieval call binding the contract method 0x2dff6941.
+//
+// Solidity: function content(node bytes32) constant returns(ret bytes32)
+func (_PublicResolver *PublicResolverCaller) Content(opts *bind.CallOpts, node [32]byte) ([32]byte, error) {
+ var (
+ ret0 = new([32]byte)
+ )
+ out := ret0
+ err := _PublicResolver.contract.Call(opts, out, "content", node)
+ return *ret0, err
+}
+
+// Content is a free data retrieval call binding the contract method 0x2dff6941.
+//
+// Solidity: function content(node bytes32) constant returns(ret bytes32)
+func (_PublicResolver *PublicResolverSession) Content(node [32]byte) ([32]byte, error) {
+ return _PublicResolver.Contract.Content(&_PublicResolver.CallOpts, node)
+}
+
+// Content is a free data retrieval call binding the contract method 0x2dff6941.
+//
+// Solidity: function content(node bytes32) constant returns(ret bytes32)
+func (_PublicResolver *PublicResolverCallerSession) Content(node [32]byte) ([32]byte, error) {
+ return _PublicResolver.Contract.Content(&_PublicResolver.CallOpts, node)
+}
+
+// Name is a free data retrieval call binding the contract method 0x691f3431.
+//
+// Solidity: function name(node bytes32) constant returns(ret string)
+func (_PublicResolver *PublicResolverCaller) Name(opts *bind.CallOpts, node [32]byte) (string, error) {
+ var (
+ ret0 = new(string)
+ )
+ out := ret0
+ err := _PublicResolver.contract.Call(opts, out, "name", node)
+ return *ret0, err
+}
+
+// Name is a free data retrieval call binding the contract method 0x691f3431.
+//
+// Solidity: function name(node bytes32) constant returns(ret string)
+func (_PublicResolver *PublicResolverSession) Name(node [32]byte) (string, error) {
+ return _PublicResolver.Contract.Name(&_PublicResolver.CallOpts, node)
+}
+
+// Name is a free data retrieval call binding the contract method 0x691f3431.
+//
+// Solidity: function name(node bytes32) constant returns(ret string)
+func (_PublicResolver *PublicResolverCallerSession) Name(node [32]byte) (string, error) {
+ return _PublicResolver.Contract.Name(&_PublicResolver.CallOpts, node)
+}
+
+// Pubkey is a free data retrieval call binding the contract method 0xc8690233.
+//
+// Solidity: function pubkey(node bytes32) constant returns(x bytes32, y bytes32)
+func (_PublicResolver *PublicResolverCaller) Pubkey(opts *bind.CallOpts, node [32]byte) (struct {
+ X [32]byte
+ Y [32]byte
+}, error) {
+ ret := new(struct {
+ X [32]byte
+ Y [32]byte
+ })
+ out := ret
+ err := _PublicResolver.contract.Call(opts, out, "pubkey", node)
+ return *ret, err
+}
+
+// Pubkey is a free data retrieval call binding the contract method 0xc8690233.
+//
+// Solidity: function pubkey(node bytes32) constant returns(x bytes32, y bytes32)
+func (_PublicResolver *PublicResolverSession) Pubkey(node [32]byte) (struct {
+ X [32]byte
+ Y [32]byte
+}, error) {
+ return _PublicResolver.Contract.Pubkey(&_PublicResolver.CallOpts, node)
+}
+
+// Pubkey is a free data retrieval call binding the contract method 0xc8690233.
+//
+// Solidity: function pubkey(node bytes32) constant returns(x bytes32, y bytes32)
+func (_PublicResolver *PublicResolverCallerSession) Pubkey(node [32]byte) (struct {
+ X [32]byte
+ Y [32]byte
+}, error) {
+ return _PublicResolver.Contract.Pubkey(&_PublicResolver.CallOpts, node)
+}
+
+// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7.
+//
+// Solidity: function supportsInterface(interfaceID bytes4) constant returns(bool)
+func (_PublicResolver *PublicResolverCaller) SupportsInterface(opts *bind.CallOpts, interfaceID [4]byte) (bool, error) {
+ var (
+ ret0 = new(bool)
+ )
+ out := ret0
+ err := _PublicResolver.contract.Call(opts, out, "supportsInterface", interfaceID)
+ return *ret0, err
+}
+
+// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7.
+//
+// Solidity: function supportsInterface(interfaceID bytes4) constant returns(bool)
+func (_PublicResolver *PublicResolverSession) SupportsInterface(interfaceID [4]byte) (bool, error) {
+ return _PublicResolver.Contract.SupportsInterface(&_PublicResolver.CallOpts, interfaceID)
+}
+
+// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7.
+//
+// Solidity: function supportsInterface(interfaceID bytes4) constant returns(bool)
+func (_PublicResolver *PublicResolverCallerSession) SupportsInterface(interfaceID [4]byte) (bool, error) {
+ return _PublicResolver.Contract.SupportsInterface(&_PublicResolver.CallOpts, interfaceID)
+}
+
+// Text is a free data retrieval call binding the contract method 0x59d1d43c.
+//
+// Solidity: function text(node bytes32, key string) constant returns(ret string)
+func (_PublicResolver *PublicResolverCaller) Text(opts *bind.CallOpts, node [32]byte, key string) (string, error) {
+ var (
+ ret0 = new(string)
+ )
+ out := ret0
+ err := _PublicResolver.contract.Call(opts, out, "text", node, key)
+ return *ret0, err
+}
+
+// Text is a free data retrieval call binding the contract method 0x59d1d43c.
+//
+// Solidity: function text(node bytes32, key string) constant returns(ret string)
+func (_PublicResolver *PublicResolverSession) Text(node [32]byte, key string) (string, error) {
+ return _PublicResolver.Contract.Text(&_PublicResolver.CallOpts, node, key)
+}
+
+// Text is a free data retrieval call binding the contract method 0x59d1d43c.
+//
+// Solidity: function text(node bytes32, key string) constant returns(ret string)
+func (_PublicResolver *PublicResolverCallerSession) Text(node [32]byte, key string) (string, error) {
+ return _PublicResolver.Contract.Text(&_PublicResolver.CallOpts, node, key)
+}
+
+// SetABI is a paid mutator transaction binding the contract method 0x623195b0.
+//
+// Solidity: function setABI(node bytes32, contentType uint256, data bytes) returns()
+func (_PublicResolver *PublicResolverTransactor) SetABI(opts *bind.TransactOpts, node [32]byte, contentType *big.Int, data []byte) (*types.Transaction, error) {
+ return _PublicResolver.contract.Transact(opts, "setABI", node, contentType, data)
+}
+
+// SetABI is a paid mutator transaction binding the contract method 0x623195b0.
+//
+// Solidity: function setABI(node bytes32, contentType uint256, data bytes) returns()
+func (_PublicResolver *PublicResolverSession) SetABI(node [32]byte, contentType *big.Int, data []byte) (*types.Transaction, error) {
+ return _PublicResolver.Contract.SetABI(&_PublicResolver.TransactOpts, node, contentType, data)
+}
+
+// SetABI is a paid mutator transaction binding the contract method 0x623195b0.
+//
+// Solidity: function setABI(node bytes32, contentType uint256, data bytes) returns()
+func (_PublicResolver *PublicResolverTransactorSession) SetABI(node [32]byte, contentType *big.Int, data []byte) (*types.Transaction, error) {
+ return _PublicResolver.Contract.SetABI(&_PublicResolver.TransactOpts, node, contentType, data)
+}
+
+// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00.
+//
+// Solidity: function setAddr(node bytes32, addr address) returns()
+func (_PublicResolver *PublicResolverTransactor) SetAddr(opts *bind.TransactOpts, node [32]byte, addr common.Address) (*types.Transaction, error) {
+ return _PublicResolver.contract.Transact(opts, "setAddr", node, addr)
+}
+
+// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00.
+//
+// Solidity: function setAddr(node bytes32, addr address) returns()
+func (_PublicResolver *PublicResolverSession) SetAddr(node [32]byte, addr common.Address) (*types.Transaction, error) {
+ return _PublicResolver.Contract.SetAddr(&_PublicResolver.TransactOpts, node, addr)
+}
+
+// SetAddr is a paid mutator transaction binding the contract method 0xd5fa2b00.
+//
+// Solidity: function setAddr(node bytes32, addr address) returns()
+func (_PublicResolver *PublicResolverTransactorSession) SetAddr(node [32]byte, addr common.Address) (*types.Transaction, error) {
+ return _PublicResolver.Contract.SetAddr(&_PublicResolver.TransactOpts, node, addr)
+}
+
+// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6.
+//
+// Solidity: function setContent(node bytes32, hash bytes32) returns()
+func (_PublicResolver *PublicResolverTransactor) SetContent(opts *bind.TransactOpts, node [32]byte, hash [32]byte) (*types.Transaction, error) {
+ return _PublicResolver.contract.Transact(opts, "setContent", node, hash)
+}
+
+// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6.
+//
+// Solidity: function setContent(node bytes32, hash bytes32) returns()
+func (_PublicResolver *PublicResolverSession) SetContent(node [32]byte, hash [32]byte) (*types.Transaction, error) {
+ return _PublicResolver.Contract.SetContent(&_PublicResolver.TransactOpts, node, hash)
+}
+
+// SetContent is a paid mutator transaction binding the contract method 0xc3d014d6.
+//
+// Solidity: function setContent(node bytes32, hash bytes32) returns()
+func (_PublicResolver *PublicResolverTransactorSession) SetContent(node [32]byte, hash [32]byte) (*types.Transaction, error) {
+ return _PublicResolver.Contract.SetContent(&_PublicResolver.TransactOpts, node, hash)
+}
+
+// SetName is a paid mutator transaction binding the contract method 0x77372213.
+//
+// Solidity: function setName(node bytes32, name string) returns()
+func (_PublicResolver *PublicResolverTransactor) SetName(opts *bind.TransactOpts, node [32]byte, name string) (*types.Transaction, error) {
+ return _PublicResolver.contract.Transact(opts, "setName", node, name)
+}
+
+// SetName is a paid mutator transaction binding the contract method 0x77372213.
+//
+// Solidity: function setName(node bytes32, name string) returns()
+func (_PublicResolver *PublicResolverSession) SetName(node [32]byte, name string) (*types.Transaction, error) {
+ return _PublicResolver.Contract.SetName(&_PublicResolver.TransactOpts, node, name)
+}
+
+// SetName is a paid mutator transaction binding the contract method 0x77372213.
+//
+// Solidity: function setName(node bytes32, name string) returns()
+func (_PublicResolver *PublicResolverTransactorSession) SetName(node [32]byte, name string) (*types.Transaction, error) {
+ return _PublicResolver.Contract.SetName(&_PublicResolver.TransactOpts, node, name)
+}
+
+// SetPubkey is a paid mutator transaction binding the contract method 0x29cd62ea.
+//
+// Solidity: function setPubkey(node bytes32, x bytes32, y bytes32) returns()
+func (_PublicResolver *PublicResolverTransactor) SetPubkey(opts *bind.TransactOpts, node [32]byte, x [32]byte, y [32]byte) (*types.Transaction, error) {
+ return _PublicResolver.contract.Transact(opts, "setPubkey", node, x, y)
+}
+
+// SetPubkey is a paid mutator transaction binding the contract method 0x29cd62ea.
+//
+// Solidity: function setPubkey(node bytes32, x bytes32, y bytes32) returns()
+func (_PublicResolver *PublicResolverSession) SetPubkey(node [32]byte, x [32]byte, y [32]byte) (*types.Transaction, error) {
+ return _PublicResolver.Contract.SetPubkey(&_PublicResolver.TransactOpts, node, x, y)
+}
+
+// SetPubkey is a paid mutator transaction binding the contract method 0x29cd62ea.
+//
+// Solidity: function setPubkey(node bytes32, x bytes32, y bytes32) returns()
+func (_PublicResolver *PublicResolverTransactorSession) SetPubkey(node [32]byte, x [32]byte, y [32]byte) (*types.Transaction, error) {
+ return _PublicResolver.Contract.SetPubkey(&_PublicResolver.TransactOpts, node, x, y)
+}
+
+// SetText is a paid mutator transaction binding the contract method 0x10f13a8c.
+//
+// Solidity: function setText(node bytes32, key string, value string) returns()
+func (_PublicResolver *PublicResolverTransactor) SetText(opts *bind.TransactOpts, node [32]byte, key string, value string) (*types.Transaction, error) {
+ return _PublicResolver.contract.Transact(opts, "setText", node, key, value)
+}
+
+// SetText is a paid mutator transaction binding the contract method 0x10f13a8c.
+//
+// Solidity: function setText(node bytes32, key string, value string) returns()
+func (_PublicResolver *PublicResolverSession) SetText(node [32]byte, key string, value string) (*types.Transaction, error) {
+ return _PublicResolver.Contract.SetText(&_PublicResolver.TransactOpts, node, key, value)
+}
+
+// SetText is a paid mutator transaction binding the contract method 0x10f13a8c.
+//
+// Solidity: function setText(node bytes32, key string, value string) returns()
+func (_PublicResolver *PublicResolverTransactorSession) SetText(node [32]byte, key string, value string) (*types.Transaction, error) {
+ return _PublicResolver.Contract.SetText(&_PublicResolver.TransactOpts, node, key, value)
+}
+
+// PublicResolverABIChangedIterator is returned from FilterABIChanged and is used to iterate over the raw logs and unpacked data for ABIChanged events raised by the PublicResolver contract.
+type PublicResolverABIChangedIterator struct {
+ Event *PublicResolverABIChanged // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *PublicResolverABIChangedIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(PublicResolverABIChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(PublicResolverABIChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+// Error retruned any retrieval or parsing error occurred during filtering.
+func (it *PublicResolverABIChangedIterator) Error() error {
+ return it.fail
+}
+
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *PublicResolverABIChangedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+// PublicResolverABIChanged represents a ABIChanged event raised by the PublicResolver contract.
+type PublicResolverABIChanged struct {
+ Node [32]byte
+ ContentType *big.Int
+ Raw types.Log // Blockchain specific contextual infos
+}
+
+// FilterABIChanged is a free log retrieval operation binding the contract event 0xaa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe3.
+//
+// Solidity: event ABIChanged(node indexed bytes32, contentType indexed uint256)
+func (_PublicResolver *PublicResolverFilterer) FilterABIChanged(opts *bind.FilterOpts, node [][32]byte, contentType []*big.Int) (*PublicResolverABIChangedIterator, error) {
+
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
+ var contentTypeRule []interface{}
+ for _, contentTypeItem := range contentType {
+ contentTypeRule = append(contentTypeRule, contentTypeItem)
+ }
+
+ logs, sub, err := _PublicResolver.contract.FilterLogs(opts, "ABIChanged", nodeRule, contentTypeRule)
+ if err != nil {
+ return nil, err
+ }
+ return &PublicResolverABIChangedIterator{contract: _PublicResolver.contract, event: "ABIChanged", logs: logs, sub: sub}, nil
+}
+
+// WatchABIChanged is a free log subscription operation binding the contract event 0xaa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe3.
+//
+// Solidity: event ABIChanged(node indexed bytes32, contentType indexed uint256)
+func (_PublicResolver *PublicResolverFilterer) WatchABIChanged(opts *bind.WatchOpts, sink chan<- *PublicResolverABIChanged, node [][32]byte, contentType []*big.Int) (event.Subscription, error) {
+
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
+ var contentTypeRule []interface{}
+ for _, contentTypeItem := range contentType {
+ contentTypeRule = append(contentTypeRule, contentTypeItem)
+ }
+
+ logs, sub, err := _PublicResolver.contract.WatchLogs(opts, "ABIChanged", nodeRule, contentTypeRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(PublicResolverABIChanged)
+ if err := _PublicResolver.contract.UnpackLog(event, "ABIChanged", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// PublicResolverAddrChangedIterator is returned from FilterAddrChanged and is used to iterate over the raw logs and unpacked data for AddrChanged events raised by the PublicResolver contract.
+type PublicResolverAddrChangedIterator struct {
+ Event *PublicResolverAddrChanged // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *PublicResolverAddrChangedIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(PublicResolverAddrChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(PublicResolverAddrChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+// Error retruned any retrieval or parsing error occurred during filtering.
+func (it *PublicResolverAddrChangedIterator) Error() error {
+ return it.fail
+}
+
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *PublicResolverAddrChangedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+// PublicResolverAddrChanged represents a AddrChanged event raised by the PublicResolver contract.
+type PublicResolverAddrChanged struct {
+ Node [32]byte
+ A common.Address
+ Raw types.Log // Blockchain specific contextual infos
+}
+
+// FilterAddrChanged is a free log retrieval operation binding the contract event 0x52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd2.
+//
+// Solidity: event AddrChanged(node indexed bytes32, a address)
+func (_PublicResolver *PublicResolverFilterer) FilterAddrChanged(opts *bind.FilterOpts, node [][32]byte) (*PublicResolverAddrChangedIterator, error) {
+
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
+
+ logs, sub, err := _PublicResolver.contract.FilterLogs(opts, "AddrChanged", nodeRule)
+ if err != nil {
+ return nil, err
+ }
+ return &PublicResolverAddrChangedIterator{contract: _PublicResolver.contract, event: "AddrChanged", logs: logs, sub: sub}, nil
+}
+
+// WatchAddrChanged is a free log subscription operation binding the contract event 0x52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd2.
+//
+// Solidity: event AddrChanged(node indexed bytes32, a address)
+func (_PublicResolver *PublicResolverFilterer) WatchAddrChanged(opts *bind.WatchOpts, sink chan<- *PublicResolverAddrChanged, node [][32]byte) (event.Subscription, error) {
+
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
+
+ logs, sub, err := _PublicResolver.contract.WatchLogs(opts, "AddrChanged", nodeRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(PublicResolverAddrChanged)
+ if err := _PublicResolver.contract.UnpackLog(event, "AddrChanged", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// PublicResolverContentChangedIterator is returned from FilterContentChanged and is used to iterate over the raw logs and unpacked data for ContentChanged events raised by the PublicResolver contract.
+type PublicResolverContentChangedIterator struct {
+ Event *PublicResolverContentChanged // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *PublicResolverContentChangedIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(PublicResolverContentChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(PublicResolverContentChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+// Error retruned any retrieval or parsing error occurred during filtering.
+func (it *PublicResolverContentChangedIterator) Error() error {
+ return it.fail
+}
+
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *PublicResolverContentChangedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+// PublicResolverContentChanged represents a ContentChanged event raised by the PublicResolver contract.
+type PublicResolverContentChanged struct {
+ Node [32]byte
+ Hash [32]byte
+ Raw types.Log // Blockchain specific contextual infos
+}
+
+// FilterContentChanged is a free log retrieval operation binding the contract event 0x0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc.
+//
+// Solidity: event ContentChanged(node indexed bytes32, hash bytes32)
+func (_PublicResolver *PublicResolverFilterer) FilterContentChanged(opts *bind.FilterOpts, node [][32]byte) (*PublicResolverContentChangedIterator, error) {
+
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
+
+ logs, sub, err := _PublicResolver.contract.FilterLogs(opts, "ContentChanged", nodeRule)
+ if err != nil {
+ return nil, err
+ }
+ return &PublicResolverContentChangedIterator{contract: _PublicResolver.contract, event: "ContentChanged", logs: logs, sub: sub}, nil
+}
+
+// WatchContentChanged is a free log subscription operation binding the contract event 0x0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc.
+//
+// Solidity: event ContentChanged(node indexed bytes32, hash bytes32)
+func (_PublicResolver *PublicResolverFilterer) WatchContentChanged(opts *bind.WatchOpts, sink chan<- *PublicResolverContentChanged, node [][32]byte) (event.Subscription, error) {
+
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
+
+ logs, sub, err := _PublicResolver.contract.WatchLogs(opts, "ContentChanged", nodeRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(PublicResolverContentChanged)
+ if err := _PublicResolver.contract.UnpackLog(event, "ContentChanged", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// PublicResolverNameChangedIterator is returned from FilterNameChanged and is used to iterate over the raw logs and unpacked data for NameChanged events raised by the PublicResolver contract.
+type PublicResolverNameChangedIterator struct {
+ Event *PublicResolverNameChanged // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *PublicResolverNameChangedIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(PublicResolverNameChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(PublicResolverNameChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+// Error retruned any retrieval or parsing error occurred during filtering.
+func (it *PublicResolverNameChangedIterator) Error() error {
+ return it.fail
+}
+
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *PublicResolverNameChangedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+// PublicResolverNameChanged represents a NameChanged event raised by the PublicResolver contract.
+type PublicResolverNameChanged struct {
+ Node [32]byte
+ Name string
+ Raw types.Log // Blockchain specific contextual infos
+}
+
+// FilterNameChanged is a free log retrieval operation binding the contract event 0xb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f7.
+//
+// Solidity: event NameChanged(node indexed bytes32, name string)
+func (_PublicResolver *PublicResolverFilterer) FilterNameChanged(opts *bind.FilterOpts, node [][32]byte) (*PublicResolverNameChangedIterator, error) {
+
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
+
+ logs, sub, err := _PublicResolver.contract.FilterLogs(opts, "NameChanged", nodeRule)
+ if err != nil {
+ return nil, err
+ }
+ return &PublicResolverNameChangedIterator{contract: _PublicResolver.contract, event: "NameChanged", logs: logs, sub: sub}, nil
+}
+
+// WatchNameChanged is a free log subscription operation binding the contract event 0xb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f7.
+//
+// Solidity: event NameChanged(node indexed bytes32, name string)
+func (_PublicResolver *PublicResolverFilterer) WatchNameChanged(opts *bind.WatchOpts, sink chan<- *PublicResolverNameChanged, node [][32]byte) (event.Subscription, error) {
+
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
+
+ logs, sub, err := _PublicResolver.contract.WatchLogs(opts, "NameChanged", nodeRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(PublicResolverNameChanged)
+ if err := _PublicResolver.contract.UnpackLog(event, "NameChanged", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// PublicResolverPubkeyChangedIterator is returned from FilterPubkeyChanged and is used to iterate over the raw logs and unpacked data for PubkeyChanged events raised by the PublicResolver contract.
+type PublicResolverPubkeyChangedIterator struct {
+ Event *PublicResolverPubkeyChanged // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *PublicResolverPubkeyChangedIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(PublicResolverPubkeyChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(PublicResolverPubkeyChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+// Error retruned any retrieval or parsing error occurred during filtering.
+func (it *PublicResolverPubkeyChangedIterator) Error() error {
+ return it.fail
+}
+
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *PublicResolverPubkeyChangedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+// PublicResolverPubkeyChanged represents a PubkeyChanged event raised by the PublicResolver contract.
+type PublicResolverPubkeyChanged struct {
+ Node [32]byte
+ X [32]byte
+ Y [32]byte
+ Raw types.Log // Blockchain specific contextual infos
+}
+
+// FilterPubkeyChanged is a free log retrieval operation binding the contract event 0x1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e46.
+//
+// Solidity: event PubkeyChanged(node indexed bytes32, x bytes32, y bytes32)
+func (_PublicResolver *PublicResolverFilterer) FilterPubkeyChanged(opts *bind.FilterOpts, node [][32]byte) (*PublicResolverPubkeyChangedIterator, error) {
+
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
+
+ logs, sub, err := _PublicResolver.contract.FilterLogs(opts, "PubkeyChanged", nodeRule)
+ if err != nil {
+ return nil, err
+ }
+ return &PublicResolverPubkeyChangedIterator{contract: _PublicResolver.contract, event: "PubkeyChanged", logs: logs, sub: sub}, nil
+}
+
+// WatchPubkeyChanged is a free log subscription operation binding the contract event 0x1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e46.
+//
+// Solidity: event PubkeyChanged(node indexed bytes32, x bytes32, y bytes32)
+func (_PublicResolver *PublicResolverFilterer) WatchPubkeyChanged(opts *bind.WatchOpts, sink chan<- *PublicResolverPubkeyChanged, node [][32]byte) (event.Subscription, error) {
+
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
+
+ logs, sub, err := _PublicResolver.contract.WatchLogs(opts, "PubkeyChanged", nodeRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(PublicResolverPubkeyChanged)
+ if err := _PublicResolver.contract.UnpackLog(event, "PubkeyChanged", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// PublicResolverTextChangedIterator is returned from FilterTextChanged and is used to iterate over the raw logs and unpacked data for TextChanged events raised by the PublicResolver contract.
+type PublicResolverTextChangedIterator struct {
+ Event *PublicResolverTextChanged // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *PublicResolverTextChangedIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(PublicResolverTextChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(PublicResolverTextChanged)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+// Error retruned any retrieval or parsing error occurred during filtering.
+func (it *PublicResolverTextChangedIterator) Error() error {
+ return it.fail
+}
+
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *PublicResolverTextChangedIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+// PublicResolverTextChanged represents a TextChanged event raised by the PublicResolver contract.
+type PublicResolverTextChanged struct {
+ Node [32]byte
+ IndexedKey common.Hash
+ Key string
+ Raw types.Log // Blockchain specific contextual infos
+}
+
+// FilterTextChanged is a free log retrieval operation binding the contract event 0xd8c9334b1a9c2f9da342a0a2b32629c1a229b6445dad78947f674b44444a7550.
+//
+// Solidity: event TextChanged(node indexed bytes32, indexedKey indexed string, key string)
+func (_PublicResolver *PublicResolverFilterer) FilterTextChanged(opts *bind.FilterOpts, node [][32]byte, indexedKey []string) (*PublicResolverTextChangedIterator, error) {
+
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
+ var indexedKeyRule []interface{}
+ for _, indexedKeyItem := range indexedKey {
+ indexedKeyRule = append(indexedKeyRule, indexedKeyItem)
+ }
+
+ logs, sub, err := _PublicResolver.contract.FilterLogs(opts, "TextChanged", nodeRule, indexedKeyRule)
+ if err != nil {
+ return nil, err
+ }
+ return &PublicResolverTextChangedIterator{contract: _PublicResolver.contract, event: "TextChanged", logs: logs, sub: sub}, nil
+}
+
+// WatchTextChanged is a free log subscription operation binding the contract event 0xd8c9334b1a9c2f9da342a0a2b32629c1a229b6445dad78947f674b44444a7550.
+//
+// Solidity: event TextChanged(node indexed bytes32, indexedKey indexed string, key string)
+func (_PublicResolver *PublicResolverFilterer) WatchTextChanged(opts *bind.WatchOpts, sink chan<- *PublicResolverTextChanged, node [][32]byte, indexedKey []string) (event.Subscription, error) {
+
+ var nodeRule []interface{}
+ for _, nodeItem := range node {
+ nodeRule = append(nodeRule, nodeItem)
+ }
+ var indexedKeyRule []interface{}
+ for _, indexedKeyItem := range indexedKey {
+ indexedKeyRule = append(indexedKeyRule, indexedKeyItem)
+ }
+
+ logs, sub, err := _PublicResolver.contract.WatchLogs(opts, "TextChanged", nodeRule, indexedKeyRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(PublicResolverTextChanged)
+ if err := _PublicResolver.contract.UnpackLog(event, "TextChanged", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
diff --git a/contracts/ens/ens.go b/contracts/ens/ens.go
index c292a1714..06045a5cd 100644
--- a/contracts/ens/ens.go
+++ b/contracts/ens/ens.go
@@ -16,10 +16,11 @@
package ens
-//go:generate abigen --sol contract/ens.sol --pkg contract --out contract/ens.go
+//go:generate abigen --sol contract/ENS.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/ens.go
+//go:generate abigen --sol contract/FIFSRegistrar.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/fifsregistrar.go
+//go:generate abigen --sol contract/PublicResolver.sol --exc contract/AbstractENS.sol:AbstractENS --pkg contract --out contract/publicresolver.go
import (
- "math/big"
"strings"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
@@ -58,31 +59,29 @@ func NewENS(transactOpts *bind.TransactOpts, contractAddr common.Address, contra
}
// DeployENS deploys an instance of the ENS nameservice, with a 'first-in, first-served' root registrar.
-func DeployENS(transactOpts *bind.TransactOpts, contractBackend bind.ContractBackend) (*ENS, error) {
- // Deploy the ENS registry
- ensAddr, _, _, err := contract.DeployENS(transactOpts, contractBackend, transactOpts.From)
+func DeployENS(transactOpts *bind.TransactOpts, contractBackend bind.ContractBackend) (common.Address, *ENS, error) {
+ // Deploy the ENS registry.
+ ensAddr, _, _, err := contract.DeployENS(transactOpts, contractBackend)
if err != nil {
- return nil, err
+ return ensAddr, nil, err
}
ens, err := NewENS(transactOpts, ensAddr, contractBackend)
if err != nil {
- return nil, err
+ return ensAddr, nil, err
}
- // Deploy the registrar
+ // Deploy the registrar.
regAddr, _, _, err := contract.DeployFIFSRegistrar(transactOpts, contractBackend, ensAddr, [32]byte{})
if err != nil {
- return nil, err
+ return ensAddr, nil, err
}
-
- // Set the registrar as owner of the ENS root
- _, err = ens.SetOwner([32]byte{}, regAddr)
- if err != nil {
- return nil, err
+ // Set the registrar as owner of the ENS root.
+ if _, err = ens.SetOwner([32]byte{}, regAddr); err != nil {
+ return ensAddr, nil, err
}
- return ens, nil
+ return ensAddr, ens, nil
}
func ensParentNode(name string) (common.Hash, common.Hash) {
@@ -156,15 +155,11 @@ func (self *ENS) Resolve(name string) (common.Hash, error) {
// Only works if the registrar for the parent domain implements the FIFS registrar protocol.
func (self *ENS) Register(name string) (*types.Transaction, error) {
parentNode, label := ensParentNode(name)
-
registrar, err := self.getRegistrar(parentNode)
if err != nil {
return nil, err
}
-
- opts := self.TransactOpts
- opts.GasLimit = big.NewInt(200000)
- return registrar.Contract.Register(&opts, label, self.TransactOpts.From)
+ return registrar.Contract.Register(&self.TransactOpts, label, self.TransactOpts.From)
}
// SetContentHash sets the content hash associated with a name. Only works if the caller
@@ -178,6 +173,6 @@ func (self *ENS) SetContentHash(name string, hash common.Hash) (*types.Transacti
}
opts := self.TransactOpts
- opts.GasLimit = big.NewInt(200000)
+ opts.GasLimit = 200000
return resolver.Contract.SetContent(&opts, node, hash)
}
diff --git a/contracts/ens/ens_test.go b/contracts/ens/ens_test.go
index 5faa9b1ad..0016f47db 100644
--- a/contracts/ens/ens_test.go
+++ b/contracts/ens/ens_test.go
@@ -22,6 +22,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
+ "github.com/ethereum/go-ethereum/contracts/ens/contract"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
)
@@ -36,27 +37,36 @@ var (
func TestENS(t *testing.T) {
contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}})
transactOpts := bind.NewKeyedTransactor(key)
- // Workaround for bug estimating gas in the call to Register
- transactOpts.GasLimit = big.NewInt(1000000)
- ens, err := DeployENS(transactOpts, contractBackend)
+ ensAddr, ens, err := DeployENS(transactOpts, contractBackend)
if err != nil {
- t.Fatalf("expected no error, got %v", err)
+ t.Fatalf("can't deploy root registry: %v", err)
}
contractBackend.Commit()
- _, err = ens.Register(name)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
+ // Set ourself as the owner of the name.
+ if _, err := ens.Register(name); err != nil {
+ t.Fatalf("can't register: %v", err)
}
contractBackend.Commit()
- _, err = ens.SetContentHash(name, hash)
+ // Deploy a resolver and make it responsible for the name.
+ resolverAddr, _, _, err := contract.DeployPublicResolver(transactOpts, contractBackend, ensAddr)
if err != nil {
- t.Fatalf("expected no error, got %v", err)
+ t.Fatalf("can't deploy resolver: %v", err)
+ }
+ if _, err := ens.SetResolver(ensNode(name), resolverAddr); err != nil {
+ t.Fatalf("can't set resolver: %v", err)
+ }
+ contractBackend.Commit()
+
+ // Set the content hash for the name.
+ if _, err = ens.SetContentHash(name, hash); err != nil {
+ t.Fatalf("can't set content hash: %v", err)
}
contractBackend.Commit()
+ // Try to resolve the name.
vhost, err := ens.Resolve(name)
if err != nil {
t.Fatalf("expected no error, got %v", err)
diff --git a/contracts/release/contract.go b/contracts/release/contract.go
deleted file mode 100644
index 6a0b09931..000000000
--- a/contracts/release/contract.go
+++ /dev/null
@@ -1,432 +0,0 @@
-// This file is an automatically generated Go binding. Do not modify as any
-// change will likely be lost upon the next re-generation!
-
-package release
-
-import (
- "math/big"
- "strings"
-
- "github.com/ethereum/go-ethereum/accounts/abi"
- "github.com/ethereum/go-ethereum/accounts/abi/bind"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
-)
-
-// ReleaseOracleABI is the input ABI used to generate the binding from.
-const ReleaseOracleABI = `[{"constant":true,"inputs":[],"name":"proposedVersion","outputs":[{"name":"major","type":"uint32"},{"name":"minor","type":"uint32"},{"name":"patch","type":"uint32"},{"name":"commit","type":"bytes20"},{"name":"pass","type":"address[]"},{"name":"fail","type":"address[]"}],"type":"function"},{"constant":true,"inputs":[],"name":"signers","outputs":[{"name":"","type":"address[]"}],"type":"function"},{"constant":false,"inputs":[{"name":"user","type":"address"}],"name":"demote","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"user","type":"address"}],"name":"authVotes","outputs":[{"name":"promote","type":"address[]"},{"name":"demote","type":"address[]"}],"type":"function"},{"constant":true,"inputs":[],"name":"currentVersion","outputs":[{"name":"major","type":"uint32"},{"name":"minor","type":"uint32"},{"name":"patch","type":"uint32"},{"name":"commit","type":"bytes20"},{"name":"time","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[],"name":"nuke","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"authProposals","outputs":[{"name":"","type":"address[]"}],"type":"function"},{"constant":false,"inputs":[{"name":"user","type":"address"}],"name":"promote","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"major","type":"uint32"},{"name":"minor","type":"uint32"},{"name":"patch","type":"uint32"},{"name":"commit","type":"bytes20"}],"name":"release","outputs":[],"type":"function"},{"inputs":[{"name":"signers","type":"address[]"}],"type":"constructor"}]`
-
-// ReleaseOracleBin is the compiled bytecode used for deploying new contracts.
-const ReleaseOracleBin = `0x606060405260405161135338038061135383398101604052805101600081516000141561008457600160a060020a0333168152602081905260408120805460ff19166001908117909155805480820180835582818380158290116100ff576000838152602090206100ff9181019083015b8082111561012f5760008155600101610070565b5060005b815181101561011f5760016000600050600084848151811015610002576020908102909101810151600160a060020a03168252810191909152604001600020805460ff1916909117905560018054808201808355828183801582901161013357600083815260209020610133918101908301610070565b5050506000928352506020909120018054600160a060020a031916331790555b50506111df806101746000396000f35b5090565b50505091909060005260206000209001600084848151811015610002575050506020838102850101518154600160a060020a0319161790555060010161008856606060405236156100775760e060020a600035046326db7648811461007957806346f0975a1461019e5780635c3d005d1461020a57806364ed31fe146102935780639d888e861461038d578063bc8fbbf8146103b2578063bf8ecf9c146103fc578063d0e0813a14610468578063d67cbec914610479575b005b610496604080516020818101835260008083528351808301855281815260045460068054875181870281018701909852808852939687968796879691959463ffffffff818116956401000000008304821695604060020a840490921694606060020a938490049093029390926007929184919083018282801561012657602002820191906000526020600020905b8154600160a060020a0316815260019190910190602001808311610107575b505050505091508080548060200260200160405190810160405280929190818152602001828054801561018357602002820191906000526020600020905b8154600160a060020a0316815260019190910190602001808311610164575b50505050509050955095509550955095509550909192939495565b6040805160208181018352600082526001805484518184028101840190955280855261055894928301828280156101ff57602002820191906000526020600020905b8154600160a060020a03168152600191909101906020018083116101e0575b505050505090505b90565b61007760043561066d8160005b600160a060020a033316600090815260208190526040812054819060ff161561070057600160a060020a038416815260026020526040812091505b8154811015610706578154600160a060020a033316908390839081101561000257600091825260209091200154600160a060020a0316141561075157610700565b6105a26004356040805160208181018352600080835283518083018552818152600160a060020a038616825260028352908490208054855181850281018501909652808652939491939092600184019291849183018282801561032057602002820191906000526020600020905b8154600160a060020a0316815260019190910190602001808311610301575b505050505091508080548060200260200160405190810160405280929190818152602001828054801561037d57602002820191906000526020600020905b8154600160a060020a031681526001919091019060200180831161035e575b5050505050905091509150915091565b61062760006000600060006000600060086000508054905060001415610670576106f1565b6100776106f96000808080805b600160a060020a033316600090815260208190526040812054819060ff16156111b657821580156103f257506006546000145b15610c2e576111b6565b6040805160208181018352600082526003805484518184028101840190955280855261055894928301828280156101ff57602002820191906000526020600020908154600160a060020a03168152600191909101906020018083116101e0575b50505050509050610207565b61007760043561066d816001610217565b6100776004356024356044356064356107008484848460016103bf565b604051808763ffffffff1681526020018663ffffffff1681526020018563ffffffff168152602001846bffffffffffffffffffffffff1916815260200180602001806020018381038352858181518152602001915080519060200190602002808383829060006004602084601f0104600302600f01f1509050018381038252848181518152602001915080519060200190602002808383829060006004602084601f0104600302600f01f1509050019850505050505050505060405180910390f35b60405180806020018281038252838181518152602001915080519060200190602002808383829060006004602084601f0104600302600f01f1509050019250505060405180910390f35b6040518080602001806020018381038352858181518152602001915080519060200190602002808383829060006004602084601f0104600302600f01f1509050018381038252848181518152602001915080519060200190602002808383829060006004602084601f0104600302600f01f15090500194505050505060405180910390f35b6040805163ffffffff9687168152948616602086015292909416838301526bffffffffffffffffffffffff19166060830152608082019290925290519081900360a00190f35b50565b600880546000198101908110156100025760009182526004027ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30190508054600182015463ffffffff8281169950640100000000830481169850604060020a8304169650606060020a91829004909102945067ffffffffffffffff16925090505b509091929394565b565b505050505b50505050565b5060005b60018201548110156107595733600160a060020a03168260010160005082815481101561000257600091825260209091200154600160a060020a031614156107a357610700565b600101610252565b8154600014801561076e575060018201546000145b156107cb57600380546001810180835582818380158290116107ab578183600052602060002091820191016107ab9190610851565b60010161070a565b5050506000928352506020909120018054600160a060020a031916851790555b821561086957815460018101808455839190828183801582901161089e5760008381526020902061089e918101908301610851565b5050506000928352506020909120018054600160a060020a031916851790555b600160a060020a038416600090815260026020908152604082208054838255818452918320909291610b2f91908101905b808211156108655760008155600101610851565b5090565b816001016000508054806001018281815481835581811511610950578183600052602060002091820191016109509190610851565b5050506000928352506020909120018054600160a060020a031916331790556001548254600290910490116108d257610700565b8280156108f85750600160a060020a03841660009081526020819052604090205460ff16155b1561098757600160a060020a0384166000908152602081905260409020805460ff1916600190811790915580548082018083558281838015829011610800578183600052602060002091820191016108009190610851565b5050506000928352506020909120018054600160a060020a031916331790556001805490830154600290910490116108d257610700565b821580156109ad5750600160a060020a03841660009081526020819052604090205460ff165b156108205750600160a060020a0383166000908152602081905260408120805460ff191690555b6001548110156108205783600160a060020a0316600160005082815481101561000257600091825260209091200154600160a060020a03161415610aa357600180546000198101908110156100025760206000908120929052600180549290910154600160a060020a031691839081101561000257906000526020600020900160006101000a815481600160a060020a030219169083021790555060016000508054809190600190039090815481835581811511610aab57600083815260209020610aab918101908301610851565b6001016109d4565b5050600060048181556005805467ffffffffffffffff19169055600680548382558184529194509192508290610b05907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f90810190610851565b5060018201805460008083559182526020909120610b2591810190610851565b5050505050610820565b5060018201805460008083559182526020909120610b4f91810190610851565b506000925050505b6003548110156107005783600160a060020a0316600360005082815481101561000257600091825260209091200154600160a060020a03161415610c2657600380546000198101908110156100025760206000908120929052600380549290910154600160a060020a031691839081101561000257906000526020600020900160006101000a815481600160a060020a0302191690830217905550600360005080548091906001900390908154818355818115116106fb576000838152602090206106fb918101908301610851565b600101610b57565b60065460001415610c8c576004805463ffffffff1916881767ffffffff0000000019166401000000008802176bffffffff00000000000000001916604060020a8702176bffffffffffffffffffffffff16606060020a808704021790555b828015610d08575060045463ffffffff8881169116141580610cc1575060045463ffffffff8781166401000000009092041614155b80610cde575060045463ffffffff868116604060020a9092041614155b80610d085750600454606060020a90819004026bffffffffffffffffffffffff1990811690851614155b15610d12576111b6565b506006905060005b8154811015610d5b578154600160a060020a033316908390839081101561000257600091825260209091200154600160a060020a03161415610da6576111b6565b5060005b6001820154811015610dae5733600160a060020a03168260010160005082815481101561000257600091825260209091200154600160a060020a03161415610de3576111b6565b600101610d1a565b8215610deb578154600181018084558391908281838015829011610e2057600083815260209020610e20918101908301610851565b600101610d5f565b816001016000508054806001018281815481835581811511610ea357818360005260206000209182019101610ea39190610851565b5050506000928352506020909120018054600160a060020a03191633179055600154825460029091049011610e54576111b6565b8215610eda576005805467ffffffffffffffff19164217905560088054600181018083558281838015829011610f2f57600402816004028360005260206000209182019101610f2f9190611048565b5050506000928352506020909120018054600160a060020a03191633179055600180549083015460029091049011610e54576111b6565b600060048181556005805467ffffffffffffffff191690556006805483825581845291929182906111bf907ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f90810190610851565b5050509190906000526020600020906004020160005060048054825463ffffffff191663ffffffff9182161780845582546401000000009081900483160267ffffffff000000001991909116178084558254604060020a908190049092169091026bffffffff00000000000000001991909116178083558154606060020a908190048102819004026bffffffffffffffffffffffff9190911617825560055460018301805467ffffffffffffffff191667ffffffffffffffff9092169190911790556006805460028401805482825560008281526020902094959491928392918201918582156110a75760005260206000209182015b828111156110a7578254825591600101919060010190611025565b505050506004015b8082111561086557600080825560018201805467ffffffffffffffff191690556002820180548282558183526020832083916110879190810190610851565b506001820180546000808355918252602090912061104091810190610851565b506110cd9291505b80821115610865578054600160a060020a03191681556001016110af565b505060018181018054918401805480835560008381526020902092938301929091821561111b5760005260206000209182015b8281111561111b578254825591600101919060010190611100565b506111279291506110af565b5050600060048181556005805467ffffffffffffffff191690556006805483825581845291975091955090935084925061118691507ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f90810190610851565b50600182018054600080835591825260209091206111a691810190610851565b50505050506111b6565b50505050505b50505050505050565b50600182018054600080835591825260209091206111b09181019061085156`
-
-// DeployReleaseOracle deploys a new Ethereum contract, binding an instance of ReleaseOracle to it.
-func DeployReleaseOracle(auth *bind.TransactOpts, backend bind.ContractBackend, signers []common.Address) (common.Address, *types.Transaction, *ReleaseOracle, error) {
- parsed, err := abi.JSON(strings.NewReader(ReleaseOracleABI))
- if err != nil {
- return common.Address{}, nil, nil, err
- }
- address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ReleaseOracleBin), backend, signers)
- if err != nil {
- return common.Address{}, nil, nil, err
- }
- return address, tx, &ReleaseOracle{ReleaseOracleCaller: ReleaseOracleCaller{contract: contract}, ReleaseOracleTransactor: ReleaseOracleTransactor{contract: contract}}, nil
-}
-
-// ReleaseOracle is an auto generated Go binding around an Ethereum contract.
-type ReleaseOracle struct {
- ReleaseOracleCaller // Read-only binding to the contract
- ReleaseOracleTransactor // Write-only binding to the contract
-}
-
-// ReleaseOracleCaller is an auto generated read-only Go binding around an Ethereum contract.
-type ReleaseOracleCaller struct {
- contract *bind.BoundContract // Generic contract wrapper for the low level calls
-}
-
-// ReleaseOracleTransactor is an auto generated write-only Go binding around an Ethereum contract.
-type ReleaseOracleTransactor struct {
- contract *bind.BoundContract // Generic contract wrapper for the low level calls
-}
-
-// ReleaseOracleSession is an auto generated Go binding around an Ethereum contract,
-// with pre-set call and transact options.
-type ReleaseOracleSession struct {
- Contract *ReleaseOracle // Generic contract binding to set the session for
- CallOpts bind.CallOpts // Call options to use throughout this session
- TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
-}
-
-// ReleaseOracleCallerSession is an auto generated read-only Go binding around an Ethereum contract,
-// with pre-set call options.
-type ReleaseOracleCallerSession struct {
- Contract *ReleaseOracleCaller // Generic contract caller binding to set the session for
- CallOpts bind.CallOpts // Call options to use throughout this session
-}
-
-// ReleaseOracleTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
-// with pre-set transact options.
-type ReleaseOracleTransactorSession struct {
- Contract *ReleaseOracleTransactor // Generic contract transactor binding to set the session for
- TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
-}
-
-// ReleaseOracleRaw is an auto generated low-level Go binding around an Ethereum contract.
-type ReleaseOracleRaw struct {
- Contract *ReleaseOracle // Generic contract binding to access the raw methods on
-}
-
-// ReleaseOracleCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
-type ReleaseOracleCallerRaw struct {
- Contract *ReleaseOracleCaller // Generic read-only contract binding to access the raw methods on
-}
-
-// ReleaseOracleTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
-type ReleaseOracleTransactorRaw struct {
- Contract *ReleaseOracleTransactor // Generic write-only contract binding to access the raw methods on
-}
-
-// NewReleaseOracle creates a new instance of ReleaseOracle, bound to a specific deployed contract.
-func NewReleaseOracle(address common.Address, backend bind.ContractBackend) (*ReleaseOracle, error) {
- contract, err := bindReleaseOracle(address, backend, backend)
- if err != nil {
- return nil, err
- }
- return &ReleaseOracle{ReleaseOracleCaller: ReleaseOracleCaller{contract: contract}, ReleaseOracleTransactor: ReleaseOracleTransactor{contract: contract}}, nil
-}
-
-// NewReleaseOracleCaller creates a new read-only instance of ReleaseOracle, bound to a specific deployed contract.
-func NewReleaseOracleCaller(address common.Address, caller bind.ContractCaller) (*ReleaseOracleCaller, error) {
- contract, err := bindReleaseOracle(address, caller, nil)
- if err != nil {
- return nil, err
- }
- return &ReleaseOracleCaller{contract: contract}, nil
-}
-
-// NewReleaseOracleTransactor creates a new write-only instance of ReleaseOracle, bound to a specific deployed contract.
-func NewReleaseOracleTransactor(address common.Address, transactor bind.ContractTransactor) (*ReleaseOracleTransactor, error) {
- contract, err := bindReleaseOracle(address, nil, transactor)
- if err != nil {
- return nil, err
- }
- return &ReleaseOracleTransactor{contract: contract}, nil
-}
-
-// bindReleaseOracle binds a generic wrapper to an already deployed contract.
-func bindReleaseOracle(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
- parsed, err := abi.JSON(strings.NewReader(ReleaseOracleABI))
- if err != nil {
- return nil, err
- }
- return bind.NewBoundContract(address, parsed, caller, transactor), nil
-}
-
-// Call invokes the (constant) contract method with params as input values and
-// sets the output to result. The result type might be a single field for simple
-// returns, a slice of interfaces for anonymous returns and a struct for named
-// returns.
-func (_ReleaseOracle *ReleaseOracleRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
- return _ReleaseOracle.Contract.ReleaseOracleCaller.contract.Call(opts, result, method, params...)
-}
-
-// Transfer initiates a plain transaction to move funds to the contract, calling
-// its default method if one is available.
-func (_ReleaseOracle *ReleaseOracleRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _ReleaseOracle.Contract.ReleaseOracleTransactor.contract.Transfer(opts)
-}
-
-// Transact invokes the (paid) contract method with params as input values.
-func (_ReleaseOracle *ReleaseOracleRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _ReleaseOracle.Contract.ReleaseOracleTransactor.contract.Transact(opts, method, params...)
-}
-
-// Call invokes the (constant) contract method with params as input values and
-// sets the output to result. The result type might be a single field for simple
-// returns, a slice of interfaces for anonymous returns and a struct for named
-// returns.
-func (_ReleaseOracle *ReleaseOracleCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
- return _ReleaseOracle.Contract.contract.Call(opts, result, method, params...)
-}
-
-// Transfer initiates a plain transaction to move funds to the contract, calling
-// its default method if one is available.
-func (_ReleaseOracle *ReleaseOracleTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _ReleaseOracle.Contract.contract.Transfer(opts)
-}
-
-// Transact invokes the (paid) contract method with params as input values.
-func (_ReleaseOracle *ReleaseOracleTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _ReleaseOracle.Contract.contract.Transact(opts, method, params...)
-}
-
-// AuthProposals is a free data retrieval call binding the contract method 0xbf8ecf9c.
-//
-// Solidity: function authProposals() constant returns(address[])
-func (_ReleaseOracle *ReleaseOracleCaller) AuthProposals(opts *bind.CallOpts) ([]common.Address, error) {
- var (
- ret0 = new([]common.Address)
- )
- out := ret0
- err := _ReleaseOracle.contract.Call(opts, out, "authProposals")
- return *ret0, err
-}
-
-// AuthProposals is a free data retrieval call binding the contract method 0xbf8ecf9c.
-//
-// Solidity: function authProposals() constant returns(address[])
-func (_ReleaseOracle *ReleaseOracleSession) AuthProposals() ([]common.Address, error) {
- return _ReleaseOracle.Contract.AuthProposals(&_ReleaseOracle.CallOpts)
-}
-
-// AuthProposals is a free data retrieval call binding the contract method 0xbf8ecf9c.
-//
-// Solidity: function authProposals() constant returns(address[])
-func (_ReleaseOracle *ReleaseOracleCallerSession) AuthProposals() ([]common.Address, error) {
- return _ReleaseOracle.Contract.AuthProposals(&_ReleaseOracle.CallOpts)
-}
-
-// AuthVotes is a free data retrieval call binding the contract method 0x64ed31fe.
-//
-// Solidity: function authVotes(user address) constant returns(promote address[], demote address[])
-func (_ReleaseOracle *ReleaseOracleCaller) AuthVotes(opts *bind.CallOpts, user common.Address) (struct {
- Promote []common.Address
- Demote []common.Address
-}, error) {
- ret := new(struct {
- Promote []common.Address
- Demote []common.Address
- })
- out := ret
- err := _ReleaseOracle.contract.Call(opts, out, "authVotes", user)
- return *ret, err
-}
-
-// AuthVotes is a free data retrieval call binding the contract method 0x64ed31fe.
-//
-// Solidity: function authVotes(user address) constant returns(promote address[], demote address[])
-func (_ReleaseOracle *ReleaseOracleSession) AuthVotes(user common.Address) (struct {
- Promote []common.Address
- Demote []common.Address
-}, error) {
- return _ReleaseOracle.Contract.AuthVotes(&_ReleaseOracle.CallOpts, user)
-}
-
-// AuthVotes is a free data retrieval call binding the contract method 0x64ed31fe.
-//
-// Solidity: function authVotes(user address) constant returns(promote address[], demote address[])
-func (_ReleaseOracle *ReleaseOracleCallerSession) AuthVotes(user common.Address) (struct {
- Promote []common.Address
- Demote []common.Address
-}, error) {
- return _ReleaseOracle.Contract.AuthVotes(&_ReleaseOracle.CallOpts, user)
-}
-
-// CurrentVersion is a free data retrieval call binding the contract method 0x9d888e86.
-//
-// Solidity: function currentVersion() constant returns(major uint32, minor uint32, patch uint32, commit bytes20, time uint256)
-func (_ReleaseOracle *ReleaseOracleCaller) CurrentVersion(opts *bind.CallOpts) (struct {
- Major uint32
- Minor uint32
- Patch uint32
- Commit [20]byte
- Time *big.Int
-}, error) {
- ret := new(struct {
- Major uint32
- Minor uint32
- Patch uint32
- Commit [20]byte
- Time *big.Int
- })
- out := ret
- err := _ReleaseOracle.contract.Call(opts, out, "currentVersion")
- return *ret, err
-}
-
-// CurrentVersion is a free data retrieval call binding the contract method 0x9d888e86.
-//
-// Solidity: function currentVersion() constant returns(major uint32, minor uint32, patch uint32, commit bytes20, time uint256)
-func (_ReleaseOracle *ReleaseOracleSession) CurrentVersion() (struct {
- Major uint32
- Minor uint32
- Patch uint32
- Commit [20]byte
- Time *big.Int
-}, error) {
- return _ReleaseOracle.Contract.CurrentVersion(&_ReleaseOracle.CallOpts)
-}
-
-// CurrentVersion is a free data retrieval call binding the contract method 0x9d888e86.
-//
-// Solidity: function currentVersion() constant returns(major uint32, minor uint32, patch uint32, commit bytes20, time uint256)
-func (_ReleaseOracle *ReleaseOracleCallerSession) CurrentVersion() (struct {
- Major uint32
- Minor uint32
- Patch uint32
- Commit [20]byte
- Time *big.Int
-}, error) {
- return _ReleaseOracle.Contract.CurrentVersion(&_ReleaseOracle.CallOpts)
-}
-
-// ProposedVersion is a free data retrieval call binding the contract method 0x26db7648.
-//
-// Solidity: function proposedVersion() constant returns(major uint32, minor uint32, patch uint32, commit bytes20, pass address[], fail address[])
-func (_ReleaseOracle *ReleaseOracleCaller) ProposedVersion(opts *bind.CallOpts) (struct {
- Major uint32
- Minor uint32
- Patch uint32
- Commit [20]byte
- Pass []common.Address
- Fail []common.Address
-}, error) {
- ret := new(struct {
- Major uint32
- Minor uint32
- Patch uint32
- Commit [20]byte
- Pass []common.Address
- Fail []common.Address
- })
- out := ret
- err := _ReleaseOracle.contract.Call(opts, out, "proposedVersion")
- return *ret, err
-}
-
-// ProposedVersion is a free data retrieval call binding the contract method 0x26db7648.
-//
-// Solidity: function proposedVersion() constant returns(major uint32, minor uint32, patch uint32, commit bytes20, pass address[], fail address[])
-func (_ReleaseOracle *ReleaseOracleSession) ProposedVersion() (struct {
- Major uint32
- Minor uint32
- Patch uint32
- Commit [20]byte
- Pass []common.Address
- Fail []common.Address
-}, error) {
- return _ReleaseOracle.Contract.ProposedVersion(&_ReleaseOracle.CallOpts)
-}
-
-// ProposedVersion is a free data retrieval call binding the contract method 0x26db7648.
-//
-// Solidity: function proposedVersion() constant returns(major uint32, minor uint32, patch uint32, commit bytes20, pass address[], fail address[])
-func (_ReleaseOracle *ReleaseOracleCallerSession) ProposedVersion() (struct {
- Major uint32
- Minor uint32
- Patch uint32
- Commit [20]byte
- Pass []common.Address
- Fail []common.Address
-}, error) {
- return _ReleaseOracle.Contract.ProposedVersion(&_ReleaseOracle.CallOpts)
-}
-
-// Signers is a free data retrieval call binding the contract method 0x46f0975a.
-//
-// Solidity: function signers() constant returns(address[])
-func (_ReleaseOracle *ReleaseOracleCaller) Signers(opts *bind.CallOpts) ([]common.Address, error) {
- var (
- ret0 = new([]common.Address)
- )
- out := ret0
- err := _ReleaseOracle.contract.Call(opts, out, "signers")
- return *ret0, err
-}
-
-// Signers is a free data retrieval call binding the contract method 0x46f0975a.
-//
-// Solidity: function signers() constant returns(address[])
-func (_ReleaseOracle *ReleaseOracleSession) Signers() ([]common.Address, error) {
- return _ReleaseOracle.Contract.Signers(&_ReleaseOracle.CallOpts)
-}
-
-// Signers is a free data retrieval call binding the contract method 0x46f0975a.
-//
-// Solidity: function signers() constant returns(address[])
-func (_ReleaseOracle *ReleaseOracleCallerSession) Signers() ([]common.Address, error) {
- return _ReleaseOracle.Contract.Signers(&_ReleaseOracle.CallOpts)
-}
-
-// Demote is a paid mutator transaction binding the contract method 0x5c3d005d.
-//
-// Solidity: function demote(user address) returns()
-func (_ReleaseOracle *ReleaseOracleTransactor) Demote(opts *bind.TransactOpts, user common.Address) (*types.Transaction, error) {
- return _ReleaseOracle.contract.Transact(opts, "demote", user)
-}
-
-// Demote is a paid mutator transaction binding the contract method 0x5c3d005d.
-//
-// Solidity: function demote(user address) returns()
-func (_ReleaseOracle *ReleaseOracleSession) Demote(user common.Address) (*types.Transaction, error) {
- return _ReleaseOracle.Contract.Demote(&_ReleaseOracle.TransactOpts, user)
-}
-
-// Demote is a paid mutator transaction binding the contract method 0x5c3d005d.
-//
-// Solidity: function demote(user address) returns()
-func (_ReleaseOracle *ReleaseOracleTransactorSession) Demote(user common.Address) (*types.Transaction, error) {
- return _ReleaseOracle.Contract.Demote(&_ReleaseOracle.TransactOpts, user)
-}
-
-// Nuke is a paid mutator transaction binding the contract method 0xbc8fbbf8.
-//
-// Solidity: function nuke() returns()
-func (_ReleaseOracle *ReleaseOracleTransactor) Nuke(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _ReleaseOracle.contract.Transact(opts, "nuke")
-}
-
-// Nuke is a paid mutator transaction binding the contract method 0xbc8fbbf8.
-//
-// Solidity: function nuke() returns()
-func (_ReleaseOracle *ReleaseOracleSession) Nuke() (*types.Transaction, error) {
- return _ReleaseOracle.Contract.Nuke(&_ReleaseOracle.TransactOpts)
-}
-
-// Nuke is a paid mutator transaction binding the contract method 0xbc8fbbf8.
-//
-// Solidity: function nuke() returns()
-func (_ReleaseOracle *ReleaseOracleTransactorSession) Nuke() (*types.Transaction, error) {
- return _ReleaseOracle.Contract.Nuke(&_ReleaseOracle.TransactOpts)
-}
-
-// Promote is a paid mutator transaction binding the contract method 0xd0e0813a.
-//
-// Solidity: function promote(user address) returns()
-func (_ReleaseOracle *ReleaseOracleTransactor) Promote(opts *bind.TransactOpts, user common.Address) (*types.Transaction, error) {
- return _ReleaseOracle.contract.Transact(opts, "promote", user)
-}
-
-// Promote is a paid mutator transaction binding the contract method 0xd0e0813a.
-//
-// Solidity: function promote(user address) returns()
-func (_ReleaseOracle *ReleaseOracleSession) Promote(user common.Address) (*types.Transaction, error) {
- return _ReleaseOracle.Contract.Promote(&_ReleaseOracle.TransactOpts, user)
-}
-
-// Promote is a paid mutator transaction binding the contract method 0xd0e0813a.
-//
-// Solidity: function promote(user address) returns()
-func (_ReleaseOracle *ReleaseOracleTransactorSession) Promote(user common.Address) (*types.Transaction, error) {
- return _ReleaseOracle.Contract.Promote(&_ReleaseOracle.TransactOpts, user)
-}
-
-// Release is a paid mutator transaction binding the contract method 0xd67cbec9.
-//
-// Solidity: function release(major uint32, minor uint32, patch uint32, commit bytes20) returns()
-func (_ReleaseOracle *ReleaseOracleTransactor) Release(opts *bind.TransactOpts, major uint32, minor uint32, patch uint32, commit [20]byte) (*types.Transaction, error) {
- return _ReleaseOracle.contract.Transact(opts, "release", major, minor, patch, commit)
-}
-
-// Release is a paid mutator transaction binding the contract method 0xd67cbec9.
-//
-// Solidity: function release(major uint32, minor uint32, patch uint32, commit bytes20) returns()
-func (_ReleaseOracle *ReleaseOracleSession) Release(major uint32, minor uint32, patch uint32, commit [20]byte) (*types.Transaction, error) {
- return _ReleaseOracle.Contract.Release(&_ReleaseOracle.TransactOpts, major, minor, patch, commit)
-}
-
-// Release is a paid mutator transaction binding the contract method 0xd67cbec9.
-//
-// Solidity: function release(major uint32, minor uint32, patch uint32, commit bytes20) returns()
-func (_ReleaseOracle *ReleaseOracleTransactorSession) Release(major uint32, minor uint32, patch uint32, commit [20]byte) (*types.Transaction, error) {
- return _ReleaseOracle.Contract.Release(&_ReleaseOracle.TransactOpts, major, minor, patch, commit)
-}
diff --git a/contracts/release/contract.sol b/contracts/release/contract.sol
deleted file mode 100644
index b9d94c756..000000000
--- a/contracts/release/contract.sol
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-// ReleaseOracle is an Ethereum contract to store the current and previous
-// versions of the go-ethereum implementation. Its goal is to allow Geth to
-// check for new releases automatically without the need to consult a central
-// repository.
-//
-// The contract takes a vote based approach on both assigning authorised signers
-// as well as signing off on new Geth releases.
-//
-// Note, when a signer is demoted, the currently pending release is auto-nuked.
-// The reason is to prevent suprises where a demotion actually tilts the votes
-// in favor of one voter party and pushing out a new release as a consequence of
-// a simple demotion.
-contract ReleaseOracle {
- // Votes is an internal data structure to count votes on a specific proposal
- struct Votes {
- address[] pass; // List of signers voting to pass a proposal
- address[] fail; // List of signers voting to fail a proposal
- }
-
- // Version is the version details of a particular Geth release
- struct Version {
- uint32 major; // Major version component of the release
- uint32 minor; // Minor version component of the release
- uint32 patch; // Patch version component of the release
- bytes20 commit; // Git SHA1 commit hash of the release
-
- uint64 time; // Timestamp of the release approval
- Votes votes; // Votes that passed this release
- }
-
- // Oracle authorization details
- mapping(address => bool) authorised; // Set of accounts allowed to vote on updating the contract
- address[] voters; // List of addresses currently accepted as signers
-
- // Various proposals being voted on
- mapping(address => Votes) authProps; // Currently running user authorization proposals
- address[] authPend; // List of addresses being voted on (map indexes)
-
- Version verProp; // Currently proposed release being voted on
- Version[] releases; // All the positively voted releases
-
- // isSigner is a modifier to authorize contract transactions.
- modifier isSigner() {
- if (authorised[msg.sender]) {
- _
- }
- }
-
- // Constructor to assign the initial set of signers.
- function ReleaseOracle(address[] signers) {
- // If no signers were specified, assign the creator as the sole signer
- if (signers.length == 0) {
- authorised[msg.sender] = true;
- voters.push(msg.sender);
- return;
- }
- // Otherwise assign the individual signers one by one
- for (uint i = 0; i < signers.length; i++) {
- authorised[signers[i]] = true;
- voters.push(signers[i]);
- }
- }
-
- // signers is an accessor method to retrieve all the signers (public accessor
- // generates an indexed one, not a retrieve-all version).
- function signers() constant returns(address[]) {
- return voters;
- }
-
- // authProposals retrieves the list of addresses that authorization proposals
- // are currently being voted on.
- function authProposals() constant returns(address[]) {
- return authPend;
- }
-
- // authVotes retrieves the current authorization votes for a particular user
- // to promote him into the list of signers, or demote him from there.
- function authVotes(address user) constant returns(address[] promote, address[] demote) {
- return (authProps[user].pass, authProps[user].fail);
- }
-
- // currentVersion retrieves the semantic version, commit hash and release time
- // of the currently votec active release.
- function currentVersion() constant returns (uint32 major, uint32 minor, uint32 patch, bytes20 commit, uint time) {
- if (releases.length == 0) {
- return (0, 0, 0, 0, 0);
- }
- var release = releases[releases.length - 1];
-
- return (release.major, release.minor, release.patch, release.commit, release.time);
- }
-
- // proposedVersion retrieves the semantic version, commit hash and the current
- // votes for the next proposed release.
- function proposedVersion() constant returns (uint32 major, uint32 minor, uint32 patch, bytes20 commit, address[] pass, address[] fail) {
- return (verProp.major, verProp.minor, verProp.patch, verProp.commit, verProp.votes.pass, verProp.votes.fail);
- }
-
- // promote pitches in on a voting campaign to promote a new user to a signer
- // position.
- function promote(address user) {
- updateSigner(user, true);
- }
-
- // demote pitches in on a voting campaign to demote an authorised user from
- // its signer position.
- function demote(address user) {
- updateSigner(user, false);
- }
-
- // release votes for a particular version to be included as the next release.
- function release(uint32 major, uint32 minor, uint32 patch, bytes20 commit) {
- updateRelease(major, minor, patch, commit, true);
- }
-
- // nuke votes for the currently proposed version to not be included as the next
- // release. Nuking doesn't require a specific version number for simplicity.
- function nuke() {
- updateRelease(0, 0, 0, 0, false);
- }
-
- // updateSigner marks a vote for changing the status of an Ethereum user, either
- // for or against the user being an authorised signer.
- function updateSigner(address user, bool authorize) internal isSigner {
- // Gather the current votes and ensure we don't double vote
- Votes votes = authProps[user];
- for (uint i = 0; i < votes.pass.length; i++) {
- if (votes.pass[i] == msg.sender) {
- return;
- }
- }
- for (i = 0; i < votes.fail.length; i++) {
- if (votes.fail[i] == msg.sender) {
- return;
- }
- }
- // If no authorization proposal is open, add the user to the index for later lookups
- if (votes.pass.length == 0 && votes.fail.length == 0) {
- authPend.push(user);
- }
- // Cast the vote and return if the proposal cannot be resolved yet
- if (authorize) {
- votes.pass.push(msg.sender);
- if (votes.pass.length <= voters.length / 2) {
- return;
- }
- } else {
- votes.fail.push(msg.sender);
- if (votes.fail.length <= voters.length / 2) {
- return;
- }
- }
- // Proposal resolved in our favor, execute whatever we voted on
- if (authorize && !authorised[user]) {
- authorised[user] = true;
- voters.push(user);
- } else if (!authorize && authorised[user]) {
- authorised[user] = false;
-
- for (i = 0; i < voters.length; i++) {
- if (voters[i] == user) {
- voters[i] = voters[voters.length - 1];
- voters.length--;
-
- delete verProp; // Nuke any version proposal (no surprise releases!)
- break;
- }
- }
- }
- // Finally delete the resolved proposal, index and garbage collect
- delete authProps[user];
-
- for (i = 0; i < authPend.length; i++) {
- if (authPend[i] == user) {
- authPend[i] = authPend[authPend.length - 1];
- authPend.length--;
- break;
- }
- }
- }
-
- // updateRelease votes for a particular version to be included as the next release,
- // or for the currently proposed release to be nuked out.
- function updateRelease(uint32 major, uint32 minor, uint32 patch, bytes20 commit, bool release) internal isSigner {
- // Skip nuke votes if no proposal is pending
- if (!release && verProp.votes.pass.length == 0) {
- return;
- }
- // Mark a new release if no proposal is pending
- if (verProp.votes.pass.length == 0) {
- verProp.major = major;
- verProp.minor = minor;
- verProp.patch = patch;
- verProp.commit = commit;
- }
- // Make sure positive votes match the current proposal
- if (release && (verProp.major != major || verProp.minor != minor || verProp.patch != patch || verProp.commit != commit)) {
- return;
- }
- // Gather the current votes and ensure we don't double vote
- Votes votes = verProp.votes;
- for (uint i = 0; i < votes.pass.length; i++) {
- if (votes.pass[i] == msg.sender) {
- return;
- }
- }
- for (i = 0; i < votes.fail.length; i++) {
- if (votes.fail[i] == msg.sender) {
- return;
- }
- }
- // Cast the vote and return if the proposal cannot be resolved yet
- if (release) {
- votes.pass.push(msg.sender);
- if (votes.pass.length <= voters.length / 2) {
- return;
- }
- } else {
- votes.fail.push(msg.sender);
- if (votes.fail.length <= voters.length / 2) {
- return;
- }
- }
- // Proposal resolved in our favor, execute whatever we voted on
- if (release) {
- verProp.time = uint64(now);
- releases.push(verProp);
- delete verProp;
- } else {
- delete verProp;
- }
- }
-}
diff --git a/contracts/release/contract_test.go b/contracts/release/contract_test.go
deleted file mode 100644
index 0b2b2f048..000000000
--- a/contracts/release/contract_test.go
+++ /dev/null
@@ -1,374 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-package release
-
-import (
- "crypto/ecdsa"
- "math/big"
- "testing"
-
- "github.com/ethereum/go-ethereum/accounts/abi/bind"
- "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/crypto"
-)
-
-// setupReleaseTest creates a blockchain simulator and deploys a version oracle
-// contract for testing.
-func setupReleaseTest(t *testing.T, prefund ...*ecdsa.PrivateKey) (*ecdsa.PrivateKey, *ReleaseOracle, *backends.SimulatedBackend) {
- // Generate a new random account and a funded simulator
- key, _ := crypto.GenerateKey()
- auth := bind.NewKeyedTransactor(key)
-
- alloc := core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}
- for _, key := range prefund {
- alloc[crypto.PubkeyToAddress(key.PublicKey)] = core.GenesisAccount{Balance: big.NewInt(10000000000)}
- }
- sim := backends.NewSimulatedBackend(alloc)
-
- // Deploy a version oracle contract, commit and return
- _, _, oracle, err := DeployReleaseOracle(auth, sim, []common.Address{auth.From})
- if err != nil {
- t.Fatalf("Failed to deploy version contract: %v", err)
- }
- sim.Commit()
-
- return key, oracle, sim
-}
-
-// Tests that the version contract can be deployed and the creator is assigned
-// the sole authorized signer.
-func TestContractCreation(t *testing.T) {
- key, oracle, _ := setupReleaseTest(t)
-
- owner := crypto.PubkeyToAddress(key.PublicKey)
- signers, err := oracle.Signers(nil)
- if err != nil {
- t.Fatalf("Failed to retrieve list of signers: %v", err)
- }
- if len(signers) != 1 || signers[0] != owner {
- t.Fatalf("Initial signer mismatch: have %v, want %v", signers, owner)
- }
-}
-
-// Tests that subsequent signers can be promoted, each requiring half plus one
-// votes for it to pass through.
-func TestSignerPromotion(t *testing.T) {
- // Prefund a few accounts to authorize with and create the oracle
- keys := make([]*ecdsa.PrivateKey, 5)
- for i := 0; i < len(keys); i++ {
- keys[i], _ = crypto.GenerateKey()
- }
- key, oracle, sim := setupReleaseTest(t, keys...)
-
- // Gradually promote the keys, until all are authorized
- keys = append([]*ecdsa.PrivateKey{key}, keys...)
- for i := 1; i < len(keys); i++ {
- // Check that no votes are accepted from the not yet authorized user
- if _, err := oracle.Promote(bind.NewKeyedTransactor(keys[i]), common.Address{}); err != nil {
- t.Fatalf("Iter #%d: failed invalid promotion attempt: %v", i, err)
- }
- sim.Commit()
-
- pend, err := oracle.AuthProposals(nil)
- if err != nil {
- t.Fatalf("Iter #%d: failed to retrieve active proposals: %v", i, err)
- }
- if len(pend) != 0 {
- t.Fatalf("Iter #%d: proposal count mismatch: have %d, want 0", i, len(pend))
- }
- // Promote with half - 1 voters and check that the user's not yet authorized
- for j := 0; j < i/2; j++ {
- if _, err = oracle.Promote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
- t.Fatalf("Iter #%d: failed valid promotion attempt: %v", i, err)
- }
- }
- sim.Commit()
-
- signers, err := oracle.Signers(nil)
- if err != nil {
- t.Fatalf("Iter #%d: failed to retrieve list of signers: %v", i, err)
- }
- if len(signers) != i {
- t.Fatalf("Iter #%d: signer count mismatch: have %v, want %v", i, len(signers), i)
- }
- // Promote with the last one needed to pass the promotion
- if _, err = oracle.Promote(bind.NewKeyedTransactor(keys[i/2]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
- t.Fatalf("Iter #%d: failed valid promotion completion attempt: %v", i, err)
- }
- sim.Commit()
-
- signers, err = oracle.Signers(nil)
- if err != nil {
- t.Fatalf("Iter #%d: failed to retrieve list of signers: %v", i, err)
- }
- if len(signers) != i+1 {
- t.Fatalf("Iter #%d: signer count mismatch: have %v, want %v", i, len(signers), i+1)
- }
- }
-}
-
-// Tests that subsequent signers can be demoted, each requiring half plus one
-// votes for it to pass through.
-func TestSignerDemotion(t *testing.T) {
- // Prefund a few accounts to authorize with and create the oracle
- keys := make([]*ecdsa.PrivateKey, 5)
- for i := 0; i < len(keys); i++ {
- keys[i], _ = crypto.GenerateKey()
- }
- key, oracle, sim := setupReleaseTest(t, keys...)
-
- // Authorize all the keys as valid signers and verify cardinality
- keys = append([]*ecdsa.PrivateKey{key}, keys...)
- for i := 1; i < len(keys); i++ {
- for j := 0; j <= i/2; j++ {
- if _, err := oracle.Promote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
- t.Fatalf("Iter #%d: failed valid promotion attempt: %v", i, err)
- }
- }
- sim.Commit()
- }
- signers, err := oracle.Signers(nil)
- if err != nil {
- t.Fatalf("Failed to retrieve list of signers: %v", err)
- }
- if len(signers) != len(keys) {
- t.Fatalf("Signer count mismatch: have %v, want %v", len(signers), len(keys))
- }
- // Gradually demote users until we run out of signers
- for i := len(keys) - 1; i >= 0; i-- {
- // Demote with half - 1 voters and check that the user's not yet dropped
- for j := 0; j < (i+1)/2; j++ {
- if _, err = oracle.Demote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
- t.Fatalf("Iter #%d: failed valid demotion attempt: %v", len(keys)-i, err)
- }
- }
- sim.Commit()
-
- signers, err := oracle.Signers(nil)
- if err != nil {
- t.Fatalf("Iter #%d: failed to retrieve list of signers: %v", len(keys)-i, err)
- }
- if len(signers) != i+1 {
- t.Fatalf("Iter #%d: signer count mismatch: have %v, want %v", len(keys)-i, len(signers), i+1)
- }
- // Demote with the last one needed to pass the demotion
- if _, err = oracle.Demote(bind.NewKeyedTransactor(keys[(i+1)/2]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
- t.Fatalf("Iter #%d: failed valid demotion completion attempt: %v", i, err)
- }
- sim.Commit()
-
- signers, err = oracle.Signers(nil)
- if err != nil {
- t.Fatalf("Iter #%d: failed to retrieve list of signers: %v", len(keys)-i, err)
- }
- if len(signers) != i {
- t.Fatalf("Iter #%d: signer count mismatch: have %v, want %v", len(keys)-i, len(signers), i)
- }
- // Check that no votes are accepted from the already demoted users
- if _, err = oracle.Promote(bind.NewKeyedTransactor(keys[i]), common.Address{}); err != nil {
- t.Fatalf("Iter #%d: failed invalid promotion attempt: %v", i, err)
- }
- sim.Commit()
-
- pend, err := oracle.AuthProposals(nil)
- if err != nil {
- t.Fatalf("Iter #%d: failed to retrieve active proposals: %v", i, err)
- }
- if len(pend) != 0 {
- t.Fatalf("Iter #%d: proposal count mismatch: have %d, want 0", i, len(pend))
- }
- }
-}
-
-// Tests that new versions can be released, honouring both voting rights as well
-// as the minimum required vote count.
-func TestVersionRelease(t *testing.T) {
- // Prefund a few accounts to authorize with and create the oracle
- keys := make([]*ecdsa.PrivateKey, 5)
- for i := 0; i < len(keys); i++ {
- keys[i], _ = crypto.GenerateKey()
- }
- key, oracle, sim := setupReleaseTest(t, keys...)
-
- // Track the "current release"
- var (
- verMajor = uint32(0)
- verMinor = uint32(0)
- verPatch = uint32(0)
- verCommit = [20]byte{}
- )
- // Gradually push releases, always requiring more signers than previously
- keys = append([]*ecdsa.PrivateKey{key}, keys...)
- for i := 1; i < len(keys); i++ {
- // Check that no votes are accepted from the not yet authorized user
- if _, err := oracle.Release(bind.NewKeyedTransactor(keys[i]), 0, 0, 0, [20]byte{0}); err != nil {
- t.Fatalf("Iter #%d: failed invalid release attempt: %v", i, err)
- }
- sim.Commit()
-
- prop, err := oracle.ProposedVersion(nil)
- if err != nil {
- t.Fatalf("Iter #%d: failed to retrieve active proposal: %v", i, err)
- }
- if len(prop.Pass) != 0 {
- t.Fatalf("Iter #%d: proposal vote count mismatch: have %d, want 0", i, len(prop.Pass))
- }
- // Authorize the user to make releases
- for j := 0; j <= i/2; j++ {
- if _, err = oracle.Promote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
- t.Fatalf("Iter #%d: failed valid promotion attempt: %v", i, err)
- }
- }
- sim.Commit()
-
- // Propose release with half voters and check that the release does not yet go through
- for j := 0; j < (i+1)/2; j++ {
- if _, err = oracle.Release(bind.NewKeyedTransactor(keys[j]), uint32(i), uint32(i+1), uint32(i+2), [20]byte{byte(i + 3)}); err != nil {
- t.Fatalf("Iter #%d: failed valid release attempt: %v", i, err)
- }
- }
- sim.Commit()
-
- ver, err := oracle.CurrentVersion(nil)
- if err != nil {
- t.Fatalf("Iter #%d: failed to retrieve current version: %v", i, err)
- }
- if ver.Major != verMajor || ver.Minor != verMinor || ver.Patch != verPatch || ver.Commit != verCommit {
- t.Fatalf("Iter #%d: version mismatch: have %d.%d.%d-%x, want %d.%d.%d-%x", i, ver.Major, ver.Minor, ver.Patch, ver.Commit, verMajor, verMinor, verPatch, verCommit)
- }
-
- // Pass the release and check that it became the next version
- verMajor, verMinor, verPatch, verCommit = uint32(i), uint32(i+1), uint32(i+2), [20]byte{byte(i + 3)}
- if _, err = oracle.Release(bind.NewKeyedTransactor(keys[(i+1)/2]), uint32(i), uint32(i+1), uint32(i+2), [20]byte{byte(i + 3)}); err != nil {
- t.Fatalf("Iter #%d: failed valid release completion attempt: %v", i, err)
- }
- sim.Commit()
-
- ver, err = oracle.CurrentVersion(nil)
- if err != nil {
- t.Fatalf("Iter #%d: failed to retrieve current version: %v", i, err)
- }
- if ver.Major != verMajor || ver.Minor != verMinor || ver.Patch != verPatch || ver.Commit != verCommit {
- t.Fatalf("Iter #%d: version mismatch: have %d.%d.%d-%x, want %d.%d.%d-%x", i, ver.Major, ver.Minor, ver.Patch, ver.Commit, verMajor, verMinor, verPatch, verCommit)
- }
- }
-}
-
-// Tests that proposed versions can be nuked out of existence.
-func TestVersionNuking(t *testing.T) {
- // Prefund a few accounts to authorize with and create the oracle
- keys := make([]*ecdsa.PrivateKey, 9)
- for i := 0; i < len(keys); i++ {
- keys[i], _ = crypto.GenerateKey()
- }
- key, oracle, sim := setupReleaseTest(t, keys...)
-
- // Authorize all the keys as valid signers
- keys = append([]*ecdsa.PrivateKey{key}, keys...)
- for i := 1; i < len(keys); i++ {
- for j := 0; j <= i/2; j++ {
- if _, err := oracle.Promote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
- t.Fatalf("Iter #%d: failed valid promotion attempt: %v", i, err)
- }
- }
- sim.Commit()
- }
- // Propose releases with more and more keys, always retaining enough users to nuke the proposals
- for i := 1; i < (len(keys)+1)/2; i++ {
- // Propose release with an initial set of signers
- for j := 0; j < i; j++ {
- if _, err := oracle.Release(bind.NewKeyedTransactor(keys[j]), uint32(i), uint32(i+1), uint32(i+2), [20]byte{byte(i + 3)}); err != nil {
- t.Fatalf("Iter #%d: failed valid proposal attempt: %v", i, err)
- }
- }
- sim.Commit()
-
- prop, err := oracle.ProposedVersion(nil)
- if err != nil {
- t.Fatalf("Iter #%d: failed to retrieve active proposal: %v", i, err)
- }
- if len(prop.Pass) != i {
- t.Fatalf("Iter #%d: proposal vote count mismatch: have %d, want %d", i, len(prop.Pass), i)
- }
- // Nuke the release with half+1 voters
- for j := i; j <= i+(len(keys)+1)/2; j++ {
- if _, err := oracle.Nuke(bind.NewKeyedTransactor(keys[j])); err != nil {
- t.Fatalf("Iter #%d: failed valid nuke attempt: %v", i, err)
- }
- }
- sim.Commit()
-
- prop, err = oracle.ProposedVersion(nil)
- if err != nil {
- t.Fatalf("Iter #%d: failed to retrieve active proposal: %v", i, err)
- }
- if len(prop.Pass) != 0 || len(prop.Fail) != 0 {
- t.Fatalf("Iter #%d: proposal vote count mismatch: have %d/%d pass/fail, want 0/0", i, len(prop.Pass), len(prop.Fail))
- }
- }
-}
-
-// Tests that demoting a signer will auto-nuke the currently pending release.
-func TestVersionAutoNuke(t *testing.T) {
- // Prefund a few accounts to authorize with and create the oracle
- keys := make([]*ecdsa.PrivateKey, 5)
- for i := 0; i < len(keys); i++ {
- keys[i], _ = crypto.GenerateKey()
- }
- key, oracle, sim := setupReleaseTest(t, keys...)
-
- // Authorize all the keys as valid signers
- keys = append([]*ecdsa.PrivateKey{key}, keys...)
- for i := 1; i < len(keys); i++ {
- for j := 0; j <= i/2; j++ {
- if _, err := oracle.Promote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
- t.Fatalf("Iter #%d: failed valid promotion attempt: %v", i, err)
- }
- }
- sim.Commit()
- }
- // Make a release proposal and check it's existence
- if _, err := oracle.Release(bind.NewKeyedTransactor(keys[0]), 1, 2, 3, [20]byte{4}); err != nil {
- t.Fatalf("Failed valid proposal attempt: %v", err)
- }
- sim.Commit()
-
- prop, err := oracle.ProposedVersion(nil)
- if err != nil {
- t.Fatalf("Failed to retrieve active proposal: %v", err)
- }
- if len(prop.Pass) != 1 {
- t.Fatalf("Proposal vote count mismatch: have %d, want 1", len(prop.Pass))
- }
- // Demote a signer and check release proposal deletion
- for i := 0; i <= len(keys)/2; i++ {
- if _, err := oracle.Demote(bind.NewKeyedTransactor(keys[i]), crypto.PubkeyToAddress(keys[len(keys)-1].PublicKey)); err != nil {
- t.Fatalf("Iter #%d: failed valid demotion attempt: %v", i, err)
- }
- }
- sim.Commit()
-
- prop, err = oracle.ProposedVersion(nil)
- if err != nil {
- t.Fatalf("Failed to retrieve active proposal: %v", err)
- }
- if len(prop.Pass) != 0 {
- t.Fatalf("Proposal vote count mismatch: have %d, want 0", len(prop.Pass))
- }
-}
diff --git a/contracts/release/release.go b/contracts/release/release.go
deleted file mode 100644
index 4442ce3e0..000000000
--- a/contracts/release/release.go
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2015 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-// Package release contains the node service that tracks client releases.
-package release
-
-//go:generate abigen --sol ./contract.sol --pkg release --out ./contract.go
-
-import (
- "context"
- "fmt"
- "strings"
- "time"
-
- "github.com/ethereum/go-ethereum/accounts/abi/bind"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/internal/ethapi"
- "github.com/ethereum/go-ethereum/les"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/node"
- "github.com/ethereum/go-ethereum/p2p"
- "github.com/ethereum/go-ethereum/rpc"
-)
-
-// Interval to check for new releases
-const releaseRecheckInterval = time.Hour
-
-// Config contains the configurations of the release service.
-type Config struct {
- Oracle common.Address // Ethereum address of the release oracle
- Major uint32 // Major version component of the release
- Minor uint32 // Minor version component of the release
- Patch uint32 // Patch version component of the release
- Commit [20]byte // Git SHA1 commit hash of the release
-}
-
-// ReleaseService is a node service that periodically checks the blockchain for
-// newly released versions of the client being run and issues a warning to the
-// user about it.
-type ReleaseService struct {
- config Config // Current version to check releases against
- oracle *ReleaseOracle // Native binding to the release oracle contract
- quit chan chan error // Quit channel to terminate the version checker
-}
-
-// NewReleaseService creates a new service to periodically check for new client
-// releases and notify the user of such.
-func NewReleaseService(ctx *node.ServiceContext, config Config) (node.Service, error) {
- // Retrieve the Ethereum service dependency to access the blockchain
- var apiBackend ethapi.Backend
- var ethereum *eth.Ethereum
- if err := ctx.Service(&ethereum); err == nil {
- apiBackend = ethereum.ApiBackend
- } else {
- var ethereum *les.LightEthereum
- if err := ctx.Service(&ethereum); err == nil {
- apiBackend = ethereum.ApiBackend
- } else {
- return nil, err
- }
- }
- // Construct the release service
- contract, err := NewReleaseOracle(config.Oracle, eth.NewContractBackend(apiBackend))
- if err != nil {
- return nil, err
- }
- return &ReleaseService{
- config: config,
- oracle: contract,
- quit: make(chan chan error),
- }, nil
-}
-
-// Protocols returns an empty list of P2P protocols as the release service does
-// not have a networking component.
-func (r *ReleaseService) Protocols() []p2p.Protocol { return nil }
-
-// APIs returns an empty list of RPC descriptors as the release service does not
-// expose any functioanlity to the outside world.
-func (r *ReleaseService) APIs() []rpc.API { return nil }
-
-// Start spawns the periodic version checker goroutine
-func (r *ReleaseService) Start(server *p2p.Server) error {
- go r.checker()
- return nil
-}
-
-// Stop terminates all goroutines belonging to the service, blocking until they
-// are all terminated.
-func (r *ReleaseService) Stop() error {
- errc := make(chan error)
- r.quit <- errc
- return <-errc
-}
-
-// checker runs indefinitely in the background, periodically checking for new
-// client releases.
-func (r *ReleaseService) checker() {
- // Set up the timers to periodically check for releases
- timer := time.NewTimer(0) // Immediately fire a version check
- defer timer.Stop()
-
- for {
- select {
- case <-timer.C:
- // Rechedule the timer before continuing
- timer.Reset(releaseRecheckInterval)
- r.checkVersion()
- case errc := <-r.quit:
- errc <- nil
- return
- }
- }
-}
-
-func (r *ReleaseService) checkVersion() {
- // Retrieve the current version, and handle missing contracts gracefully
- ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
- opts := &bind.CallOpts{Context: ctx}
- defer cancel()
-
- version, err := r.oracle.CurrentVersion(opts)
- if err != nil {
- if err == bind.ErrNoCode {
- log.Debug("Release oracle not found", "contract", r.config.Oracle)
- } else if err != les.ErrNoPeers {
- log.Error("Failed to retrieve current release", "err", err)
- }
- return
- }
- // Version was successfully retrieved, notify if newer than ours
- if version.Major > r.config.Major ||
- (version.Major == r.config.Major && version.Minor > r.config.Minor) ||
- (version.Major == r.config.Major && version.Minor == r.config.Minor && version.Patch > r.config.Patch) {
-
- warning := fmt.Sprintf("Client v%d.%d.%d-%x seems older than the latest upstream release v%d.%d.%d-%x",
- r.config.Major, r.config.Minor, r.config.Patch, r.config.Commit[:4], version.Major, version.Minor, version.Patch, version.Commit[:4])
- howtofix := fmt.Sprintf("Please check https://github.com/ethereum/go-ethereum/releases for new releases")
- separator := strings.Repeat("-", len(warning))
-
- log.Warn(separator)
- log.Warn(warning)
- log.Warn(howtofix)
- log.Warn(separator)
- } else {
- log.Debug("Client seems up to date with upstream",
- "local", fmt.Sprintf("v%d.%d.%d-%x", r.config.Major, r.config.Minor, r.config.Patch, r.config.Commit[:4]),
- "upstream", fmt.Sprintf("v%d.%d.%d-%x", version.Major, version.Minor, version.Patch, version.Commit[:4]))
- }
-}
diff --git a/core/bench_test.go b/core/bench_test.go
index 9c7cd81c4..e23f0d19d 100644
--- a/core/bench_test.go
+++ b/core/bench_test.go
@@ -84,7 +84,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
return func(i int, gen *BlockGen) {
toaddr := common.Address{}
data := make([]byte, nbytes)
- gas := IntrinsicGas(data, false, false)
+ gas, _ := IntrinsicGas(data, false, false)
tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data), types.HomesteadSigner{}, benchRootKey)
gen.AddTx(tx)
}
@@ -93,7 +93,6 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
var (
ringKeys = make([]*ecdsa.PrivateKey, 1000)
ringAddrs = make([]common.Address, len(ringKeys))
- bigTxGas = new(big.Int).SetUint64(params.TxGas)
)
func init() {
@@ -113,8 +112,8 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
return func(i int, gen *BlockGen) {
gas := CalcGasLimit(gen.PrevBlock(i - 1))
for {
- gas.Sub(gas, bigTxGas)
- if gas.Cmp(bigTxGas) < 0 {
+ gas -= params.TxGas
+ if gas < params.TxGas {
break
}
to := (from + 1) % naccounts
@@ -122,7 +121,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
gen.TxNonce(ringAddrs[from]),
ringAddrs[to],
benchRootFunds,
- bigTxGas,
+ params.TxGas,
nil,
nil,
)
@@ -174,7 +173,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
// Time the insertion of the new chain.
// State and blocks are stored in the same DB.
- chainman, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(), vm.Config{})
+ chainman, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
defer chainman.Stop()
b.ReportAllocs()
b.ResetTimer()
@@ -284,7 +283,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
if err != nil {
b.Fatalf("error opening database at %v: %v", dir, err)
}
- chain, err := NewBlockChain(db, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
+ chain, err := NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
if err != nil {
b.Fatalf("error creating chain: %v", err)
}
diff --git a/core/block_validator.go b/core/block_validator.go
index e9cfd0482..98958809b 100644
--- a/core/block_validator.go
+++ b/core/block_validator.go
@@ -18,9 +18,7 @@ package core
import (
"fmt"
- "math/big"
- "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
@@ -52,11 +50,14 @@ func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engin
// validated at this point.
func (v *BlockValidator) ValidateBody(block *types.Block) error {
// Check whether the block's known, and if not, that it's linkable
- if v.bc.HasBlockAndState(block.Hash()) {
+ if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) {
return ErrKnownBlock
}
- if !v.bc.HasBlockAndState(block.ParentHash()) {
- return consensus.ErrUnknownAncestor
+ if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
+ if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) {
+ return consensus.ErrUnknownAncestor
+ }
+ return consensus.ErrPrunedAncestor
}
// Header validity is known at this point, check the uncles and transactions
header := block.Header()
@@ -76,10 +77,10 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
// transition, such as amount of used gas, the receipt roots and the state root
// itself. ValidateState returns a database batch if the validation was a success
// otherwise nil and an error is returned.
-func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas *big.Int) error {
+func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error {
header := block.Header()
- if block.GasUsed().Cmp(usedGas) != 0 {
- return fmt.Errorf("invalid gas used (remote: %v local: %v)", block.GasUsed(), usedGas)
+ if block.GasUsed() != usedGas {
+ return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
}
// Validate the received block's bloom with the one derived from the generated receipts.
// For valid blocks this should always validate to true.
@@ -101,17 +102,13 @@ func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *stat
}
// CalcGasLimit computes the gas limit of the next block after parent.
-// The result may be modified by the caller.
// This is miner strategy, not consensus protocol.
-func CalcGasLimit(parent *types.Block) *big.Int {
+func CalcGasLimit(parent *types.Block) uint64 {
// contrib = (parentGasUsed * 3 / 2) / 1024
- contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3))
- contrib = contrib.Div(contrib, big.NewInt(2))
- contrib = contrib.Div(contrib, params.GasLimitBoundDivisor)
+ contrib := (parent.GasUsed() + parent.GasUsed()/2) / params.GasLimitBoundDivisor
// decay = parentGasLimit / 1024 -1
- decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor)
- decay.Sub(decay, big.NewInt(1))
+ decay := parent.GasLimit()/params.GasLimitBoundDivisor - 1
/*
strategy: gasLimit of block-to-mine is set based on parent's
@@ -120,15 +117,17 @@ func CalcGasLimit(parent *types.Block) *big.Int {
at that usage) the amount increased/decreased depends on how far away
from parentGasLimit * (2/3) parentGasUsed is.
*/
- gl := new(big.Int).Sub(parent.GasLimit(), decay)
- gl = gl.Add(gl, contrib)
- gl.Set(math.BigMax(gl, params.MinGasLimit))
-
+ limit := parent.GasLimit() - decay + contrib
+ if limit < params.MinGasLimit {
+ limit = params.MinGasLimit
+ }
// however, if we're now below the target (TargetGasLimit) we increase the
// limit as much as we can (parentGasLimit / 1024 -1)
- if gl.Cmp(params.TargetGasLimit) < 0 {
- gl.Add(parent.GasLimit(), decay)
- gl.Set(math.BigMin(gl, params.TargetGasLimit))
+ if limit < params.TargetGasLimit {
+ limit = parent.GasLimit() + decay
+ if limit > params.TargetGasLimit {
+ limit = params.TargetGasLimit
+ }
}
- return gl
+ return limit
}
diff --git a/core/block_validator_test.go b/core/block_validator_test.go
index e668601f3..e334b3c3c 100644
--- a/core/block_validator_test.go
+++ b/core/block_validator_test.go
@@ -42,7 +42,7 @@ func TestHeaderVerification(t *testing.T) {
headers[i] = block.Header()
}
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
- chain, _ := NewBlockChain(testdb, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
+ chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
defer chain.Stop()
for i := 0; i < len(blocks); i++ {
@@ -106,11 +106,11 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) {
var results <-chan error
if valid {
- chain, _ := NewBlockChain(testdb, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
+ chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
_, results = chain.engine.VerifyHeaders(chain, headers, seals)
chain.Stop()
} else {
- chain, _ := NewBlockChain(testdb, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{})
+ chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{})
_, results = chain.engine.VerifyHeaders(chain, headers, seals)
chain.Stop()
}
@@ -173,7 +173,7 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) {
defer runtime.GOMAXPROCS(old)
// Start the verifications and immediately abort
- chain, _ := NewBlockChain(testdb, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{})
+ chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{})
defer chain.Stop()
abort, results := chain.engine.VerifyHeaders(chain, headers, seals)
diff --git a/core/blockchain.go b/core/blockchain.go
index 325753c7a..4ae0e4f4e 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -42,6 +42,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/hashicorp/golang-lru"
+ "gopkg.in/karalabe/cookiejar.v2/collections/prque"
)
var (
@@ -56,11 +57,20 @@ const (
maxFutureBlocks = 256
maxTimeFutureBlocks = 30
badBlockLimit = 10
+ triesInMemory = 128
// BlockChainVersion ensures that an incompatible database forces a resync from scratch.
BlockChainVersion = 3
)
+// CacheConfig contains the configuration values for the trie caching/pruning
+// that's resident in a blockchain.
+type CacheConfig struct {
+ Disabled bool // Whether to disable trie write caching (archive node)
+ TrieNodeLimit int // Memory limit (MB) at which to flush the current in-memory trie to disk
+ TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk
+}
+
// BlockChain represents the canonical chain given a database with a genesis
// block. The Blockchain manages chain imports, reverts, chain reorganisations.
//
@@ -76,10 +86,14 @@ const (
// included in the canonical one where as GetBlockByNumber always represents the
// canonical chain.
type BlockChain struct {
- config *params.ChainConfig // chain & network configuration
+ chainConfig *params.ChainConfig // Chain & network configuration
+ cacheConfig *CacheConfig // Cache configuration for pruning
+
+ db ethdb.Database // Low level persistent database to store final content in
+ triegc *prque.Prque // Priority queue mapping block numbers to tries to gc
+ gcproc time.Duration // Accumulates canonical block processing for trie dumping
hc *HeaderChain
- chainDb ethdb.Database
rmLogsFeed event.Feed
chainFeed event.Feed
chainSideFeed event.Feed
@@ -119,7 +133,13 @@ type BlockChain struct {
// NewBlockChain returns a fully initialised block chain using information
// available in the database. It initialises the default Ethereum Validator and
// Processor.
-func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config) (*BlockChain, error) {
+func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config) (*BlockChain, error) {
+ if cacheConfig == nil {
+ cacheConfig = &CacheConfig{
+ TrieNodeLimit: 256 * 1024 * 1024,
+ TrieTimeLimit: 5 * time.Minute,
+ }
+ }
bodyCache, _ := lru.New(bodyCacheLimit)
bodyRLPCache, _ := lru.New(bodyCacheLimit)
blockCache, _ := lru.New(blockCacheLimit)
@@ -127,9 +147,11 @@ func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, engine co
badBlocks, _ := lru.New(badBlockLimit)
bc := &BlockChain{
- config: config,
- chainDb: chainDb,
- stateCache: state.NewDatabase(chainDb),
+ chainConfig: chainConfig,
+ cacheConfig: cacheConfig,
+ db: db,
+ triegc: prque.New(),
+ stateCache: state.NewDatabase(db),
quit: make(chan struct{}),
bodyCache: bodyCache,
bodyRLPCache: bodyRLPCache,
@@ -139,11 +161,11 @@ func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, engine co
vmConfig: vmConfig,
badBlocks: badBlocks,
}
- bc.SetValidator(NewBlockValidator(config, bc, engine))
- bc.SetProcessor(NewStateProcessor(config, bc, engine))
+ bc.SetValidator(NewBlockValidator(chainConfig, bc, engine))
+ bc.SetProcessor(NewStateProcessor(chainConfig, bc, engine))
var err error
- bc.hc, err = NewHeaderChain(chainDb, config, engine, bc.getProcInterrupt)
+ bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.getProcInterrupt)
if err != nil {
return nil, err
}
@@ -180,7 +202,7 @@ func (bc *BlockChain) getProcInterrupt() bool {
// assumes that the chain manager mutex is held.
func (bc *BlockChain) loadLastState() error {
// Restore the last known head block
- head := GetHeadBlockHash(bc.chainDb)
+ head := GetHeadBlockHash(bc.db)
if head == (common.Hash{}) {
// Corrupt or empty database, init from scratch
log.Warn("Empty database, resetting chain")
@@ -196,15 +218,17 @@ func (bc *BlockChain) loadLastState() error {
// Make sure the state associated with the block is available
if _, err := state.New(currentBlock.Root(), bc.stateCache); err != nil {
// Dangling block without a state associated, init from scratch
- log.Warn("Head state missing, resetting chain", "number", currentBlock.Number(), "hash", currentBlock.Hash())
- return bc.Reset()
+ log.Warn("Head state missing, repairing chain", "number", currentBlock.Number(), "hash", currentBlock.Hash())
+ if err := bc.repair(&currentBlock); err != nil {
+ return err
+ }
}
// Everything seems to be fine, set as the head block
bc.currentBlock = currentBlock
// Restore the last known head header
currentHeader := bc.currentBlock.Header()
- if head := GetHeadHeaderHash(bc.chainDb); head != (common.Hash{}) {
+ if head := GetHeadHeaderHash(bc.db); head != (common.Hash{}) {
if header := bc.GetHeaderByHash(head); header != nil {
currentHeader = header
}
@@ -213,7 +237,7 @@ func (bc *BlockChain) loadLastState() error {
// Restore the last known head fast block
bc.currentFastBlock = bc.currentBlock
- if head := GetHeadFastBlockHash(bc.chainDb); head != (common.Hash{}) {
+ if head := GetHeadFastBlockHash(bc.db); head != (common.Hash{}) {
if block := bc.GetBlockByHash(head); block != nil {
bc.currentFastBlock = block
}
@@ -243,7 +267,7 @@ func (bc *BlockChain) SetHead(head uint64) error {
// Rewind the header chain, deleting all block bodies until then
delFn := func(hash common.Hash, num uint64) {
- DeleteBody(bc.chainDb, hash, num)
+ DeleteBody(bc.db, hash, num)
}
bc.hc.SetHead(head, delFn)
currentHeader := bc.hc.CurrentHeader()
@@ -275,10 +299,10 @@ func (bc *BlockChain) SetHead(head uint64) error {
if bc.currentFastBlock == nil {
bc.currentFastBlock = bc.genesisBlock
}
- if err := WriteHeadBlockHash(bc.chainDb, bc.currentBlock.Hash()); err != nil {
+ if err := WriteHeadBlockHash(bc.db, bc.currentBlock.Hash()); err != nil {
log.Crit("Failed to reset head full block", "err", err)
}
- if err := WriteHeadFastBlockHash(bc.chainDb, bc.currentFastBlock.Hash()); err != nil {
+ if err := WriteHeadFastBlockHash(bc.db, bc.currentFastBlock.Hash()); err != nil {
log.Crit("Failed to reset head fast block", "err", err)
}
return bc.loadLastState()
@@ -292,7 +316,7 @@ func (bc *BlockChain) FastSyncCommitHead(hash common.Hash) error {
if block == nil {
return fmt.Errorf("non existent block [%x…]", hash[:4])
}
- if _, err := trie.NewSecure(block.Root(), bc.chainDb, 0); err != nil {
+ if _, err := trie.NewSecure(block.Root(), bc.stateCache.TrieDB(), 0); err != nil {
return err
}
// If all checks out, manually set the head block
@@ -305,21 +329,13 @@ func (bc *BlockChain) FastSyncCommitHead(hash common.Hash) error {
}
// GasLimit returns the gas limit of the current HEAD block.
-func (bc *BlockChain) GasLimit() *big.Int {
+func (bc *BlockChain) GasLimit() uint64 {
bc.mu.RLock()
defer bc.mu.RUnlock()
return bc.currentBlock.GasLimit()
}
-// LastBlockHash return the hash of the HEAD block.
-func (bc *BlockChain) LastBlockHash() common.Hash {
- bc.mu.RLock()
- defer bc.mu.RUnlock()
-
- return bc.currentBlock.Hash()
-}
-
// CurrentBlock retrieves the current head block of the canonical chain. The
// block is retrieved from the blockchain's internal cache.
func (bc *BlockChain) CurrentBlock() *types.Block {
@@ -338,15 +354,6 @@ func (bc *BlockChain) CurrentFastBlock() *types.Block {
return bc.currentFastBlock
}
-// Status returns status information about the current chain such as the HEAD Td,
-// the HEAD hash and the hash of the genesis block.
-func (bc *BlockChain) Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash) {
- bc.mu.RLock()
- defer bc.mu.RUnlock()
-
- return bc.GetTd(bc.currentBlock.Hash(), bc.currentBlock.NumberU64()), bc.currentBlock.Hash(), bc.genesisBlock.Hash()
-}
-
// SetProcessor sets the processor required for making state modifications.
func (bc *BlockChain) SetProcessor(processor Processor) {
bc.procmu.Lock()
@@ -404,7 +411,7 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error {
if err := bc.hc.WriteTd(genesis.Hash(), genesis.NumberU64(), genesis.Difficulty()); err != nil {
log.Crit("Failed to write genesis block TD", "err", err)
}
- if err := WriteBlock(bc.chainDb, genesis); err != nil {
+ if err := WriteBlock(bc.db, genesis); err != nil {
log.Crit("Failed to write genesis block", "err", err)
}
bc.genesisBlock = genesis
@@ -417,6 +424,24 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error {
return nil
}
+// repair tries to repair the current blockchain by rolling back the current block
+// until one with associated state is found. This is needed to fix incomplete db
+// writes caused either by crashes/power outages, or simply non-committed tries.
+//
+// This method only rolls back the current block. The current header and current
+// fast block are left intact.
+func (bc *BlockChain) repair(head **types.Block) error {
+ for {
+ // Abort if we've rewound to a head block that does have associated state
+ if _, err := state.New((*head).Root(), bc.stateCache); err == nil {
+ log.Info("Rewound blockchain to past state", "number", (*head).Number(), "hash", (*head).Hash())
+ return nil
+ }
+ // Otherwise rewind one block and recheck state availability there
+ (*head) = bc.GetBlock((*head).ParentHash(), (*head).NumberU64()-1)
+ }
+}
+
// Export writes the active chain to the given writer.
func (bc *BlockChain) Export(w io.Writer) error {
return bc.ExportN(w, uint64(0), bc.currentBlock.NumberU64())
@@ -454,22 +479,22 @@ func (bc *BlockChain) ExportN(w io.Writer, first uint64, last uint64) error {
// Note, this function assumes that the `mu` mutex is held!
func (bc *BlockChain) insert(block *types.Block) {
// If the block is on a side chain or an unknown one, force other heads onto it too
- updateHeads := GetCanonicalHash(bc.chainDb, block.NumberU64()) != block.Hash()
+ updateHeads := GetCanonicalHash(bc.db, block.NumberU64()) != block.Hash()
// Add the block to the canonical chain number scheme and mark as the head
- if err := WriteCanonicalHash(bc.chainDb, block.Hash(), block.NumberU64()); err != nil {
+ if err := WriteCanonicalHash(bc.db, block.Hash(), block.NumberU64()); err != nil {
log.Crit("Failed to insert block number", "err", err)
}
- if err := WriteHeadBlockHash(bc.chainDb, block.Hash()); err != nil {
+ if err := WriteHeadBlockHash(bc.db, block.Hash()); err != nil {
log.Crit("Failed to insert head block hash", "err", err)
}
bc.currentBlock = block
- // If the block is better than out head or is on a different chain, force update heads
+ // If the block is better than our head or is on a different chain, force update heads
if updateHeads {
bc.hc.SetCurrentHeader(block.Header())
- if err := WriteHeadFastBlockHash(bc.chainDb, block.Hash()); err != nil {
+ if err := WriteHeadFastBlockHash(bc.db, block.Hash()); err != nil {
log.Crit("Failed to insert head fast block hash", "err", err)
}
bc.currentFastBlock = block
@@ -489,7 +514,7 @@ func (bc *BlockChain) GetBody(hash common.Hash) *types.Body {
body := cached.(*types.Body)
return body
}
- body := GetBody(bc.chainDb, hash, bc.hc.GetBlockNumber(hash))
+ body := GetBody(bc.db, hash, bc.hc.GetBlockNumber(hash))
if body == nil {
return nil
}
@@ -505,7 +530,7 @@ func (bc *BlockChain) GetBodyRLP(hash common.Hash) rlp.RawValue {
if cached, ok := bc.bodyRLPCache.Get(hash); ok {
return cached.(rlp.RawValue)
}
- body := GetBodyRLP(bc.chainDb, hash, bc.hc.GetBlockNumber(hash))
+ body := GetBodyRLP(bc.db, hash, bc.hc.GetBlockNumber(hash))
if len(body) == 0 {
return nil
}
@@ -519,21 +544,25 @@ func (bc *BlockChain) HasBlock(hash common.Hash, number uint64) bool {
if bc.blockCache.Contains(hash) {
return true
}
- ok, _ := bc.chainDb.Has(blockBodyKey(hash, number))
+ ok, _ := bc.db.Has(blockBodyKey(hash, number))
return ok
}
+// HasState checks if state trie is fully present in the database or not.
+func (bc *BlockChain) HasState(hash common.Hash) bool {
+ _, err := bc.stateCache.OpenTrie(hash)
+ return err == nil
+}
+
// HasBlockAndState checks if a block and associated state trie is fully present
// in the database or not, caching it if present.
-func (bc *BlockChain) HasBlockAndState(hash common.Hash) bool {
+func (bc *BlockChain) HasBlockAndState(hash common.Hash, number uint64) bool {
// Check first that the block itself is known
- block := bc.GetBlockByHash(hash)
+ block := bc.GetBlock(hash, number)
if block == nil {
return false
}
- // Ensure the associated state is also present
- _, err := bc.stateCache.OpenTrie(block.Root())
- return err == nil
+ return bc.HasState(block.Root())
}
// GetBlock retrieves a block from the database by hash and number,
@@ -543,7 +572,7 @@ func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
if block, ok := bc.blockCache.Get(hash); ok {
return block.(*types.Block)
}
- block := GetBlock(bc.chainDb, hash, number)
+ block := GetBlock(bc.db, hash, number)
if block == nil {
return nil
}
@@ -560,13 +589,18 @@ func (bc *BlockChain) GetBlockByHash(hash common.Hash) *types.Block {
// GetBlockByNumber retrieves a block from the database by number, caching it
// (associated with its hash) if found.
func (bc *BlockChain) GetBlockByNumber(number uint64) *types.Block {
- hash := GetCanonicalHash(bc.chainDb, number)
+ hash := GetCanonicalHash(bc.db, number)
if hash == (common.Hash{}) {
return nil
}
return bc.GetBlock(hash, number)
}
+// GetReceiptsByHash retrieves the receipts for all transactions in a given block.
+func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
+ return GetBlockReceipts(bc.db, hash, GetBlockNumber(bc.db, hash))
+}
+
// GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors.
// [deprecated by eth/62]
func (bc *BlockChain) GetBlocksFromHash(hash common.Hash, n int) (blocks []*types.Block) {
@@ -594,6 +628,12 @@ func (bc *BlockChain) GetUnclesInChain(block *types.Block, length int) []*types.
return uncles
}
+// TrieNode retrieves a blob of data associated with a trie node (or code hash)
+// either from ephemeral in-memory cache, or from persistent storage.
+func (bc *BlockChain) TrieNode(hash common.Hash) ([]byte, error) {
+ return bc.stateCache.TrieDB().Node(hash)
+}
+
// Stop stops the blockchain service. If any imports are currently in progress
// it will abort them using the procInterrupt.
func (bc *BlockChain) Stop() {
@@ -606,6 +646,33 @@ func (bc *BlockChain) Stop() {
atomic.StoreInt32(&bc.procInterrupt, 1)
bc.wg.Wait()
+
+ // Ensure the state of a recent block is also stored to disk before exiting.
+ // It is fine if this state does not exist (fast start/stop cycle), but it is
+ // advisable to leave an N block gap from the head so 1) a restart loads up
+ // the last N blocks as sync assistance to remote nodes; 2) a restart during
+ // a (small) reorg doesn't require deep reprocesses; 3) chain "repair" from
+ // missing states are constantly tested.
+ //
+ // This may be tuned a bit on mainnet if its too annoying to reprocess the last
+ // N blocks.
+ if !bc.cacheConfig.Disabled {
+ triedb := bc.stateCache.TrieDB()
+ if number := bc.CurrentBlock().NumberU64(); number >= triesInMemory {
+ recent := bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - triesInMemory + 1)
+
+ log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root())
+ if err := triedb.Commit(recent.Root(), true); err != nil {
+ log.Error("Failed to commit recent state trie", "err", err)
+ }
+ }
+ for !bc.triegc.Empty() {
+ triedb.Dereference(bc.triegc.PopItem().(common.Hash), common.Hash{})
+ }
+ if size := triedb.Size(); size != 0 {
+ log.Error("Dangling trie nodes after full cleanup")
+ }
+ }
log.Info("Blockchain manager stopped")
}
@@ -650,11 +717,11 @@ func (bc *BlockChain) Rollback(chain []common.Hash) {
}
if bc.currentFastBlock.Hash() == hash {
bc.currentFastBlock = bc.GetBlock(bc.currentFastBlock.ParentHash(), bc.currentFastBlock.NumberU64()-1)
- WriteHeadFastBlockHash(bc.chainDb, bc.currentFastBlock.Hash())
+ WriteHeadFastBlockHash(bc.db, bc.currentFastBlock.Hash())
}
if bc.currentBlock.Hash() == hash {
bc.currentBlock = bc.GetBlock(bc.currentBlock.ParentHash(), bc.currentBlock.NumberU64()-1)
- WriteHeadBlockHash(bc.chainDb, bc.currentBlock.Hash())
+ WriteHeadBlockHash(bc.db, bc.currentBlock.Hash())
}
}
}
@@ -677,9 +744,9 @@ func SetReceiptsData(config *params.ChainConfig, block *types.Block, receipts ty
}
// The used gas can be calculated based on previous receipts
if j == 0 {
- receipts[j].GasUsed = new(big.Int).Set(receipts[j].CumulativeGasUsed)
+ receipts[j].GasUsed = receipts[j].CumulativeGasUsed
} else {
- receipts[j].GasUsed = new(big.Int).Sub(receipts[j].CumulativeGasUsed, receipts[j-1].CumulativeGasUsed)
+ receipts[j].GasUsed = receipts[j].CumulativeGasUsed - receipts[j-1].CumulativeGasUsed
}
// The derived log fields can simply be set from the block and transaction
for k := 0; k < len(receipts[j].Logs); k++ {
@@ -713,7 +780,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
stats = struct{ processed, ignored int32 }{}
start = time.Now()
bytes = 0
- batch = bc.chainDb.NewBatch()
+ batch = bc.db.NewBatch()
)
for i, block := range blockChain {
receipts := receiptChain[i]
@@ -731,7 +798,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
continue
}
// Compute all the non-consensus fields of the receipts
- SetReceiptsData(bc.config, block, receipts)
+ SetReceiptsData(bc.chainConfig, block, receipts)
// Write all the data out into the database
if err := WriteBody(batch, block.Hash(), block.NumberU64(), block.Body()); err != nil {
return i, fmt.Errorf("failed to write block body: %v", err)
@@ -749,7 +816,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
return 0, err
}
bytes += batch.ValueSize()
- batch = bc.chainDb.NewBatch()
+ batch.Reset()
}
}
if batch.ValueSize() > 0 {
@@ -764,7 +831,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
head := blockChain[len(blockChain)-1]
if td := bc.GetTd(head.Hash(), head.NumberU64()); td != nil { // Rewind may have occurred, skip in that case
if bc.GetTd(bc.currentFastBlock.Hash(), bc.currentFastBlock.NumberU64()).Cmp(td) < 0 {
- if err := WriteHeadFastBlockHash(bc.chainDb, head.Hash()); err != nil {
+ if err := WriteHeadFastBlockHash(bc.db, head.Hash()); err != nil {
log.Crit("Failed to update head fast block hash", "err", err)
}
bc.currentFastBlock = head
@@ -775,15 +842,33 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
log.Info("Imported new block receipts",
"count", stats.processed,
"elapsed", common.PrettyDuration(time.Since(start)),
- "bytes", bytes,
"number", head.Number(),
"hash", head.Hash(),
+ "size", common.StorageSize(bytes),
"ignored", stats.ignored)
return 0, nil
}
-// WriteBlock writes the block to the chain.
-func (bc *BlockChain) WriteBlockAndState(block *types.Block, receipts []*types.Receipt, state *state.StateDB) (status WriteStatus, err error) {
+var lastWrite uint64
+
+// WriteBlockWithoutState writes only the block and its metadata to the database,
+// but does not write any state. This is used to construct competing side forks
+// up to the point where they exceed the canonical total difficulty.
+func (bc *BlockChain) WriteBlockWithoutState(block *types.Block, td *big.Int) (err error) {
+ bc.wg.Add(1)
+ defer bc.wg.Done()
+
+ if err := bc.hc.WriteTd(block.Hash(), block.NumberU64(), td); err != nil {
+ return err
+ }
+ if err := WriteBlock(bc.db, block); err != nil {
+ return err
+ }
+ return nil
+}
+
+// WriteBlockWithState writes the block and all associated state to the database.
+func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.Receipt, state *state.StateDB) (status WriteStatus, err error) {
bc.wg.Add(1)
defer bc.wg.Done()
@@ -804,17 +889,69 @@ func (bc *BlockChain) WriteBlockAndState(block *types.Block, receipts []*types.R
return NonStatTy, err
}
// Write other block data using a batch.
- batch := bc.chainDb.NewBatch()
+ batch := bc.db.NewBatch()
if err := WriteBlock(batch, block); err != nil {
return NonStatTy, err
}
- if _, err := state.CommitTo(batch, bc.config.IsEIP158(block.Number())); err != nil {
+ root, err := state.Commit(bc.chainConfig.IsEIP158(block.Number()))
+ if err != nil {
return NonStatTy, err
}
+ triedb := bc.stateCache.TrieDB()
+
+ // If we're running an archive node, always flush
+ if bc.cacheConfig.Disabled {
+ if err := triedb.Commit(root, false); err != nil {
+ return NonStatTy, err
+ }
+ } else {
+ // Full but not archive node, do proper garbage collection
+ triedb.Reference(root, common.Hash{}) // metadata reference to keep trie alive
+ bc.triegc.Push(root, -float32(block.NumberU64()))
+
+ if current := block.NumberU64(); current > triesInMemory {
+ // Find the next state trie we need to commit
+ header := bc.GetHeaderByNumber(current - triesInMemory)
+ chosen := header.Number.Uint64()
+
+ // Only write to disk if we exceeded our memory allowance *and* also have at
+ // least a given number of tries gapped.
+ var (
+ size = triedb.Size()
+ limit = common.StorageSize(bc.cacheConfig.TrieNodeLimit) * 1024 * 1024
+ )
+ if size > limit || bc.gcproc > bc.cacheConfig.TrieTimeLimit {
+ // If we're exceeding limits but haven't reached a large enough memory gap,
+ // warn the user that the system is becoming unstable.
+ if chosen < lastWrite+triesInMemory {
+ switch {
+ case size >= 2*limit:
+ log.Warn("State memory usage too high, committing", "size", size, "limit", limit, "optimum", float64(chosen-lastWrite)/triesInMemory)
+ case bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit:
+ log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", bc.cacheConfig.TrieTimeLimit, "optimum", float64(chosen-lastWrite)/triesInMemory)
+ }
+ }
+ // If optimum or critical limits reached, write to disk
+ if chosen >= lastWrite+triesInMemory || size >= 2*limit || bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit {
+ triedb.Commit(header.Root, true)
+ lastWrite = chosen
+ bc.gcproc = 0
+ }
+ }
+ // Garbage collect anything below our required write retention
+ for !bc.triegc.Empty() {
+ root, number := bc.triegc.Pop()
+ if uint64(-number) > chosen {
+ bc.triegc.Push(root, number)
+ break
+ }
+ triedb.Dereference(root.(common.Hash), common.Hash{})
+ }
+ }
+ }
if err := WriteBlockReceipts(batch, block.Hash(), block.NumberU64(), receipts); err != nil {
return NonStatTy, err
}
-
// If the total difficulty is higher than our known, add it to the canonical chain
// Second clause in the if statement reduces the vulnerability to selfish mining.
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
@@ -835,7 +972,7 @@ func (bc *BlockChain) WriteBlockAndState(block *types.Block, receipts []*types.R
return NonStatTy, err
}
// Write hash preimages
- if err := WritePreimages(bc.chainDb, block.NumberU64(), state.Preimages()); err != nil {
+ if err := WritePreimages(bc.db, block.NumberU64(), state.Preimages()); err != nil {
return NonStatTy, err
}
status = CanonStatTy
@@ -927,31 +1064,64 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
if err == nil {
err = bc.Validator().ValidateBody(block)
}
- if err != nil {
- if err == ErrKnownBlock {
+ switch {
+ case err == ErrKnownBlock:
+ // Block and state both already known. However if the current block is below
+ // this number we did a rollback and we should reimport it nonetheless.
+ if bc.CurrentBlock().NumberU64() >= block.NumberU64() {
stats.ignored++
continue
}
- if err == consensus.ErrFutureBlock {
- // Allow up to MaxFuture second in the future blocks. If this limit
- // is exceeded the chain is discarded and processed at a later time
- // if given.
- max := big.NewInt(time.Now().Unix() + maxTimeFutureBlocks)
- if block.Time().Cmp(max) > 0 {
- return i, events, coalescedLogs, fmt.Errorf("future block: %v > %v", block.Time(), max)
+ case err == consensus.ErrFutureBlock:
+ // Allow up to MaxFuture second in the future blocks. If this limit is exceeded
+ // the chain is discarded and processed at a later time if given.
+ max := big.NewInt(time.Now().Unix() + maxTimeFutureBlocks)
+ if block.Time().Cmp(max) > 0 {
+ return i, events, coalescedLogs, fmt.Errorf("future block: %v > %v", block.Time(), max)
+ }
+ bc.futureBlocks.Add(block.Hash(), block)
+ stats.queued++
+ continue
+
+ case err == consensus.ErrUnknownAncestor && bc.futureBlocks.Contains(block.ParentHash()):
+ bc.futureBlocks.Add(block.Hash(), block)
+ stats.queued++
+ continue
+
+ case err == consensus.ErrPrunedAncestor:
+ // Block competing with the canonical chain, store in the db, but don't process
+ // until the competitor TD goes above the canonical TD
+ localTd := bc.GetTd(bc.currentBlock.Hash(), bc.currentBlock.NumberU64())
+ externTd := new(big.Int).Add(bc.GetTd(block.ParentHash(), block.NumberU64()-1), block.Difficulty())
+ if localTd.Cmp(externTd) > 0 {
+ if err = bc.WriteBlockWithoutState(block, externTd); err != nil {
+ return i, events, coalescedLogs, err
}
- bc.futureBlocks.Add(block.Hash(), block)
- stats.queued++
continue
}
+ // Competitor chain beat canonical, gather all blocks from the common ancestor
+ var winner []*types.Block
- if err == consensus.ErrUnknownAncestor && bc.futureBlocks.Contains(block.ParentHash()) {
- bc.futureBlocks.Add(block.Hash(), block)
- stats.queued++
- continue
+ parent := bc.GetBlock(block.ParentHash(), block.NumberU64()-1)
+ for !bc.HasState(parent.Root()) {
+ winner = append(winner, parent)
+ parent = bc.GetBlock(parent.ParentHash(), parent.NumberU64()-1)
+ }
+ for j := 0; j < len(winner)/2; j++ {
+ winner[j], winner[len(winner)-1-j] = winner[len(winner)-1-j], winner[j]
+ }
+ // Import all the pruned blocks to make the state available
+ bc.chainmu.Unlock()
+ _, evs, logs, err := bc.insertChain(winner)
+ bc.chainmu.Lock()
+ events, coalescedLogs = evs, logs
+
+ if err != nil {
+ return i, events, coalescedLogs, err
}
+ case err != nil:
bc.reportBlock(block, nil, err)
return i, events, coalescedLogs, err
}
@@ -979,8 +1149,10 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
bc.reportBlock(block, receipts, err)
return i, events, coalescedLogs, err
}
+ proctime := time.Since(bstart)
+
// Write the block to the chain and get the status.
- status, err := bc.WriteBlockAndState(block, receipts, state)
+ status, err := bc.WriteBlockWithState(block, receipts, state)
if err != nil {
return i, events, coalescedLogs, err
}
@@ -994,6 +1166,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
events = append(events, ChainEvent{block, block.Hash(), logs})
lastCanon = block
+ // Only count canonical blocks for GC processing time
+ bc.gcproc += proctime
+
case SideStatTy:
log.Debug("Inserted forked block", "number", block.Number(), "hash", block.Hash(), "diff", block.Difficulty(), "elapsed",
common.PrettyDuration(time.Since(bstart)), "txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()))
@@ -1002,11 +1177,11 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
events = append(events, ChainSideEvent{block})
}
stats.processed++
- stats.usedGas += usedGas.Uint64()
- stats.report(chain, i)
+ stats.usedGas += usedGas
+ stats.report(chain, i, bc.stateCache.TrieDB().Size())
}
// Append a single chain head event if we've progressed the chain
- if lastCanon != nil && bc.LastBlockHash() == lastCanon.Hash() {
+ if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
events = append(events, ChainHeadEvent{lastCanon})
}
return 0, events, coalescedLogs, nil
@@ -1026,7 +1201,7 @@ const statsReportLimit = 8 * time.Second
// report prints statistics if some number of blocks have been processed
// or more than a few seconds have passed since the last message.
-func (st *insertStats) report(chain []*types.Block, index int) {
+func (st *insertStats) report(chain []*types.Block, index int, cache common.StorageSize) {
// Fetch the timings for the batch
var (
now = mclock.Now()
@@ -1041,7 +1216,7 @@ func (st *insertStats) report(chain []*types.Block, index int) {
context := []interface{}{
"blocks", st.processed, "txs", txs, "mgas", float64(st.usedGas) / 1000000,
"elapsed", common.PrettyDuration(elapsed), "mgasps", float64(st.usedGas) * 1000 / float64(elapsed),
- "number", end.Number(), "hash", end.Hash(),
+ "number", end.Number(), "hash", end.Hash(), "cache", cache,
}
if st.queued > 0 {
context = append(context, []interface{}{"queued", st.queued}...)
@@ -1077,7 +1252,7 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
// These logs are later announced as deleted.
collectLogs = func(h common.Hash) {
// Coalesce logs and set 'Removed'.
- receipts := GetBlockReceipts(bc.chainDb, h, bc.hc.GetBlockNumber(h))
+ receipts := GetBlockReceipts(bc.db, h, bc.hc.GetBlockNumber(h))
for _, receipt := range receipts {
for _, log := range receipt.Logs {
del := *log
@@ -1140,24 +1315,23 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
} else {
log.Error("Impossible reorg, please file an issue", "oldnum", oldBlock.Number(), "oldhash", oldBlock.Hash(), "newnum", newBlock.Number(), "newhash", newBlock.Hash())
}
+ // Insert the new chain, taking care of the proper incremental order
var addedTxs types.Transactions
- // insert blocks. Order does not matter. Last block will be written in ImportChain itself which creates the new head properly
- for _, block := range newChain {
+ for i := len(newChain) - 1; i >= 0; i-- {
// insert the block in the canonical way, re-writing history
- bc.insert(block)
+ bc.insert(newChain[i])
// write lookup entries for hash based transaction/receipt searches
- if err := WriteTxLookupEntries(bc.chainDb, block); err != nil {
+ if err := WriteTxLookupEntries(bc.db, newChain[i]); err != nil {
return err
}
- addedTxs = append(addedTxs, block.Transactions()...)
+ addedTxs = append(addedTxs, newChain[i].Transactions()...)
}
-
// calculate the difference between deleted and added transactions
diff := types.TxDifference(deletedTxs, addedTxs)
// When transactions get deleted from the database that means the
// receipts that were created in the fork must also be deleted
for _, tx := range diff {
- DeleteTxLookupEntry(bc.chainDb, tx.Hash())
+ DeleteTxLookupEntry(bc.db, tx.Hash())
}
if len(deletedLogs) > 0 {
go bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs})
@@ -1196,10 +1370,11 @@ func (bc *BlockChain) PostChainEvents(events []interface{}, logs []*types.Log) {
}
func (bc *BlockChain) update() {
- futureTimer := time.Tick(5 * time.Second)
+ futureTimer := time.NewTicker(5 * time.Second)
+ defer futureTimer.Stop()
for {
select {
- case <-futureTimer:
+ case <-futureTimer.C:
bc.procFutureBlocks()
case <-bc.quit:
return
@@ -1248,7 +1423,7 @@ Hash: 0x%x
Error: %v
##############################
-`, bc.config, block.Number(), block.Hash(), receiptString, err))
+`, bc.chainConfig, block.Number(), block.Hash(), receiptString, err))
}
// InsertHeaderChain attempts to insert the given header chain in to the local
@@ -1355,7 +1530,7 @@ func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header {
}
// Config retrieves the blockchain's chain configuration.
-func (bc *BlockChain) Config() *params.ChainConfig { return bc.config }
+func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig }
// Engine retrieves the blockchain's consensus engine.
func (bc *BlockChain) Engine() consensus.Engine { return bc.engine }
diff --git a/core/blockchain_test.go b/core/blockchain_test.go
index cb2e47104..635379161 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -46,7 +46,7 @@ func newTestBlockChain(fake bool) *BlockChain {
if !fake {
engine = ethash.NewTester()
}
- blockchain, err := NewBlockChain(db, gspec.Config, engine, vm.Config{})
+ blockchain, err := NewBlockChain(db, nil, gspec.Config, engine, vm.Config{})
if err != nil {
panic(err)
}
@@ -148,9 +148,9 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
return err
}
blockchain.mu.Lock()
- WriteTd(blockchain.chainDb, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash())))
- WriteBlock(blockchain.chainDb, block)
- statedb.CommitTo(blockchain.chainDb, false)
+ WriteTd(blockchain.db, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash())))
+ WriteBlock(blockchain.db, block)
+ statedb.Commit(false)
blockchain.mu.Unlock()
}
return nil
@@ -166,8 +166,8 @@ func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error
}
// Manually insert the header into the database, but don't reorganise (allows subsequent testing)
blockchain.mu.Lock()
- WriteTd(blockchain.chainDb, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTdByHash(header.ParentHash)))
- WriteHeader(blockchain.chainDb, header)
+ WriteTd(blockchain.db, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTdByHash(header.ParentHash)))
+ WriteHeader(blockchain.db, header)
blockchain.mu.Unlock()
}
return nil
@@ -186,9 +186,9 @@ func TestLastBlock(t *testing.T) {
bchain := newTestBlockChain(false)
defer bchain.Stop()
- block := makeBlockChain(bchain.CurrentBlock(), 1, ethash.NewFaker(), bchain.chainDb, 0)[0]
+ block := makeBlockChain(bchain.CurrentBlock(), 1, ethash.NewFaker(), bchain.db, 0)[0]
bchain.insert(block)
- if block.Hash() != GetHeadBlockHash(bchain.chainDb) {
+ if block.Hash() != GetHeadBlockHash(bchain.db) {
t.Errorf("Write/Get HeadBlockHash failed")
}
}
@@ -340,11 +340,11 @@ func testBrokenChain(t *testing.T, full bool) {
type bproc struct{}
func (bproc) ValidateBody(*types.Block) error { return nil }
-func (bproc) ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas *big.Int) error {
+func (bproc) ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error {
return nil
}
-func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *big.Int, error) {
- return nil, nil, new(big.Int), nil
+func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) {
+ return nil, nil, 0, nil
}
func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Header {
@@ -496,7 +496,7 @@ func testReorgBadHashes(t *testing.T, full bool) {
}
// Create a new BlockChain and check that it rolled back the state.
- ncm, err := NewBlockChain(bc.chainDb, bc.config, ethash.NewFaker(), vm.Config{})
+ ncm, err := NewBlockChain(bc.db, nil, bc.chainConfig, ethash.NewFaker(), vm.Config{})
if err != nil {
t.Fatalf("failed to create new chain manager: %v", err)
}
@@ -506,8 +506,8 @@ func testReorgBadHashes(t *testing.T, full bool) {
if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() {
t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash())
}
- if blocks[2].Header().GasLimit.Cmp(ncm.GasLimit()) != 0 {
- t.Errorf("last block gasLimit mismatch: have: %x, want %x", ncm.GasLimit(), blocks[2].Header().GasLimit)
+ if blocks[2].Header().GasLimit != ncm.GasLimit() {
+ t.Errorf("last block gasLimit mismatch: have: %d, want %d", ncm.GasLimit(), blocks[2].Header().GasLimit)
}
} else {
if ncm.CurrentHeader().Hash() != headers[2].Hash() {
@@ -594,7 +594,7 @@ func TestFastVsFullChains(t *testing.T) {
// If the block number is multiple of 3, send a few bonus transactions to the miner
if i%3 == 2 {
for j := 0; j < i%4+1; j++ {
- tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), bigTxGas, nil, nil), signer, key)
+ tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key)
if err != nil {
panic(err)
}
@@ -609,7 +609,7 @@ func TestFastVsFullChains(t *testing.T) {
// Import the chain as an archive node for the comparison baseline
archiveDb, _ := ethdb.NewMemDatabase()
gspec.MustCommit(archiveDb)
- archive, _ := NewBlockChain(archiveDb, gspec.Config, ethash.NewFaker(), vm.Config{})
+ archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
defer archive.Stop()
if n, err := archive.InsertChain(blocks); err != nil {
@@ -618,7 +618,7 @@ func TestFastVsFullChains(t *testing.T) {
// Fast import the chain as a non-archive node to test
fastDb, _ := ethdb.NewMemDatabase()
gspec.MustCommit(fastDb)
- fast, _ := NewBlockChain(fastDb, gspec.Config, ethash.NewFaker(), vm.Config{})
+ fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
defer fast.Stop()
headers := make([]*types.Header, len(blocks))
@@ -696,7 +696,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
archiveDb, _ := ethdb.NewMemDatabase()
gspec.MustCommit(archiveDb)
- archive, _ := NewBlockChain(archiveDb, gspec.Config, ethash.NewFaker(), vm.Config{})
+ archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
if n, err := archive.InsertChain(blocks); err != nil {
t.Fatalf("failed to process block %d: %v", n, err)
}
@@ -709,7 +709,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Import the chain as a non-archive node and ensure all pointers are updated
fastDb, _ := ethdb.NewMemDatabase()
gspec.MustCommit(fastDb)
- fast, _ := NewBlockChain(fastDb, gspec.Config, ethash.NewFaker(), vm.Config{})
+ fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
defer fast.Stop()
headers := make([]*types.Header, len(blocks))
@@ -730,7 +730,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
lightDb, _ := ethdb.NewMemDatabase()
gspec.MustCommit(lightDb)
- light, _ := NewBlockChain(lightDb, gspec.Config, ethash.NewFaker(), vm.Config{})
+ light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
if n, err := light.InsertHeaderChain(headers, 1); err != nil {
t.Fatalf("failed to insert header %d: %v", n, err)
}
@@ -767,8 +767,8 @@ func TestChainTxReorgs(t *testing.T) {
// Create two transactions shared between the chains:
// - postponed: transaction included at a later block in the forked chain
// - swapped: transaction included at the same block number in the forked chain
- postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), bigTxGas, nil, nil), signer, key1)
- swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), bigTxGas, nil, nil), signer, key1)
+ postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
+ swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
// Create two transactions that will be dropped by the forked chain:
// - pastDrop: transaction dropped retroactively from a past block
@@ -784,13 +784,13 @@ func TestChainTxReorgs(t *testing.T) {
chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {
switch i {
case 0:
- pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), bigTxGas, nil, nil), signer, key2)
+ pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point
gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork
case 2:
- freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), bigTxGas, nil, nil), signer, key2)
+ freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point
gen.AddTx(swapped) // This transaction will be swapped out at the exact height
@@ -799,7 +799,7 @@ func TestChainTxReorgs(t *testing.T) {
}
})
// Import the chain. This runs all block validation rules.
- blockchain, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(), vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
if i, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
}
@@ -809,18 +809,18 @@ func TestChainTxReorgs(t *testing.T) {
chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) {
switch i {
case 0:
- pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key3)
+ pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3)
gen.AddTx(pastAdd) // This transaction needs to be injected during reorg
case 2:
gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain
gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain
- freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key3)
+ freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3)
gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time
case 3:
- futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key3)
+ futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3)
gen.AddTx(futureAdd) // This transaction will be added after a full reorg
}
})
@@ -870,14 +870,14 @@ func TestLogReorgs(t *testing.T) {
signer = types.NewEIP155Signer(gspec.Config.ChainId)
)
- blockchain, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(), vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
defer blockchain.Stop()
rmLogsCh := make(chan RemovedLogsEvent)
blockchain.SubscribeRemovedLogsEvent(rmLogsCh)
chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) {
if i == 1 {
- tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), code), signer, key1)
+ tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1)
if err != nil {
t.Fatalf("failed to create tx: %v", err)
}
@@ -917,7 +917,7 @@ func TestReorgSideEvent(t *testing.T) {
signer = types.NewEIP155Signer(gspec.Config.ChainId)
)
- blockchain, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(), vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
defer blockchain.Stop()
chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {})
@@ -926,7 +926,7 @@ func TestReorgSideEvent(t *testing.T) {
}
replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, gen *BlockGen) {
- tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil), signer, key1)
+ tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), nil), signer, key1)
if i == 2 {
gen.OffsetTime(-9)
}
@@ -992,7 +992,7 @@ func TestCanonicalBlockRetrieval(t *testing.T) {
bc := newTestBlockChain(true)
defer bc.Stop()
- chain, _ := GenerateChain(bc.config, bc.genesisBlock, ethash.NewFaker(), bc.chainDb, 10, func(i int, gen *BlockGen) {})
+ chain, _ := GenerateChain(bc.chainConfig, bc.genesisBlock, ethash.NewFaker(), bc.db, 10, func(i int, gen *BlockGen) {})
var pend sync.WaitGroup
pend.Add(len(chain))
@@ -1003,14 +1003,14 @@ func TestCanonicalBlockRetrieval(t *testing.T) {
// try to retrieve a block by its canonical hash and see if the block data can be retrieved.
for {
- ch := GetCanonicalHash(bc.chainDb, block.NumberU64())
+ ch := GetCanonicalHash(bc.db, block.NumberU64())
if ch == (common.Hash{}) {
continue // busy wait for canonical hash to be written
}
if ch != block.Hash() {
t.Fatalf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex())
}
- fb := GetBlock(bc.chainDb, ch, block.NumberU64())
+ fb := GetBlock(bc.db, ch, block.NumberU64())
if fb == nil {
t.Fatalf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex())
}
@@ -1043,7 +1043,7 @@ func TestEIP155Transition(t *testing.T) {
genesis = gspec.MustCommit(db)
)
- blockchain, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(), vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
defer blockchain.Stop()
blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, block *BlockGen) {
@@ -1051,7 +1051,7 @@ func TestEIP155Transition(t *testing.T) {
tx *types.Transaction
err error
basicTx = func(signer types.Signer) (*types.Transaction, error) {
- return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key)
+ return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key)
}
)
switch i {
@@ -1114,7 +1114,7 @@ func TestEIP155Transition(t *testing.T) {
tx *types.Transaction
err error
basicTx = func(signer types.Signer) (*types.Transaction, error) {
- return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key)
+ return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key)
}
)
switch i {
@@ -1151,7 +1151,7 @@ func TestEIP161AccountRemoval(t *testing.T) {
}
genesis = gspec.MustCommit(db)
)
- blockchain, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(), vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
defer blockchain.Stop()
blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, block *BlockGen) {
@@ -1162,11 +1162,11 @@ func TestEIP161AccountRemoval(t *testing.T) {
)
switch i {
case 0:
- tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key)
+ tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key)
case 1:
- tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key)
+ tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key)
case 2:
- tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key)
+ tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key)
}
if err != nil {
t.Fatal(err)
@@ -1197,3 +1197,150 @@ func TestEIP161AccountRemoval(t *testing.T) {
t.Error("account should not exist")
}
}
+
+// This is a regression test (i.e. as weird as it is, don't delete it ever), which
+// tests that under weird reorg conditions the blockchain and its internal header-
+// chain return the same latest block/header.
+//
+// https://github.com/ethereum/go-ethereum/pull/15941
+func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
+ // Generate a canonical chain to act as the main dataset
+ engine := ethash.NewFaker()
+
+ db, _ := ethdb.NewMemDatabase()
+ genesis := new(Genesis).MustCommit(db)
+ blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
+
+ // Generate a bunch of fork blocks, each side forking from the canonical chain
+ forks := make([]*types.Block, len(blocks))
+ for i := 0; i < len(forks); i++ {
+ parent := genesis
+ if i > 0 {
+ parent = blocks[i-1]
+ }
+ fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) })
+ forks[i] = fork[0]
+ }
+ // Import the canonical and fork chain side by side, verifying the current block
+ // and current header consistency
+ diskdb, _ := ethdb.NewMemDatabase()
+ new(Genesis).MustCommit(diskdb)
+
+ chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{})
+ if err != nil {
+ t.Fatalf("failed to create tester chain: %v", err)
+ }
+ for i := 0; i < len(blocks); i++ {
+ if _, err := chain.InsertChain(blocks[i : i+1]); err != nil {
+ t.Fatalf("block %d: failed to insert into chain: %v", i, err)
+ }
+ if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() {
+ t.Errorf("block %d: current block/header mismatch: block #%d [%x…], header #%d [%x…]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4])
+ }
+ if _, err := chain.InsertChain(forks[i : i+1]); err != nil {
+ t.Fatalf(" fork %d: failed to insert into chain: %v", i, err)
+ }
+ if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() {
+ t.Errorf(" fork %d: current block/header mismatch: block #%d [%x…], header #%d [%x…]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4])
+ }
+ }
+}
+
+// Tests that importing small side forks doesn't leave junk in the trie database
+// cache (which would eventually cause memory issues).
+func TestTrieForkGC(t *testing.T) {
+ // Generate a canonical chain to act as the main dataset
+ engine := ethash.NewFaker()
+
+ db, _ := ethdb.NewMemDatabase()
+ genesis := new(Genesis).MustCommit(db)
+ blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
+
+ // Generate a bunch of fork blocks, each side forking from the canonical chain
+ forks := make([]*types.Block, len(blocks))
+ for i := 0; i < len(forks); i++ {
+ parent := genesis
+ if i > 0 {
+ parent = blocks[i-1]
+ }
+ fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) })
+ forks[i] = fork[0]
+ }
+ // Import the canonical and fork chain side by side, forcing the trie cache to cache both
+ diskdb, _ := ethdb.NewMemDatabase()
+ new(Genesis).MustCommit(diskdb)
+
+ chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{})
+ if err != nil {
+ t.Fatalf("failed to create tester chain: %v", err)
+ }
+ for i := 0; i < len(blocks); i++ {
+ if _, err := chain.InsertChain(blocks[i : i+1]); err != nil {
+ t.Fatalf("block %d: failed to insert into chain: %v", i, err)
+ }
+ if _, err := chain.InsertChain(forks[i : i+1]); err != nil {
+ t.Fatalf("fork %d: failed to insert into chain: %v", i, err)
+ }
+ }
+ // Dereference all the recent tries and ensure no past trie is left in
+ for i := 0; i < triesInMemory; i++ {
+ chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root(), common.Hash{})
+ chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root(), common.Hash{})
+ }
+ if len(chain.stateCache.TrieDB().Nodes()) > 0 {
+ t.Fatalf("stale tries still alive after garbase collection")
+ }
+}
+
+// Tests that doing large reorgs works even if the state associated with the
+// forking point is not available any more.
+func TestLargeReorgTrieGC(t *testing.T) {
+ // Generate the original common chain segment and the two competing forks
+ engine := ethash.NewFaker()
+
+ db, _ := ethdb.NewMemDatabase()
+ genesis := new(Genesis).MustCommit(db)
+
+ shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
+ original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) })
+ competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) })
+
+ // Import the shared chain and the original canonical one
+ diskdb, _ := ethdb.NewMemDatabase()
+ new(Genesis).MustCommit(diskdb)
+
+ chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{})
+ if err != nil {
+ t.Fatalf("failed to create tester chain: %v", err)
+ }
+ if _, err := chain.InsertChain(shared); err != nil {
+ t.Fatalf("failed to insert shared chain: %v", err)
+ }
+ if _, err := chain.InsertChain(original); err != nil {
+ t.Fatalf("failed to insert shared chain: %v", err)
+ }
+ // Ensure that the state associated with the forking point is pruned away
+ if node, _ := chain.stateCache.TrieDB().Node(shared[len(shared)-1].Root()); node != nil {
+ t.Fatalf("common-but-old ancestor still cache")
+ }
+ // Import the competitor chain without exceeding the canonical's TD and ensure
+ // we have not processed any of the blocks (protection against malicious blocks)
+ if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil {
+ t.Fatalf("failed to insert competitor chain: %v", err)
+ }
+ for i, block := range competitor[:len(competitor)-2] {
+ if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil {
+ t.Fatalf("competitor %d: low TD chain became processed", i)
+ }
+ }
+ // Import the head of the competitor chain, triggering the reorg and ensure we
+ // successfully reprocess all the stashed away blocks.
+ if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil {
+ t.Fatalf("failed to finalize competitor chain: %v", err)
+ }
+ for i, block := range competitor[:len(competitor)-triesInMemory] {
+ if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil {
+ t.Fatalf("competitor %d: competing chain state missing", i)
+ }
+ }
+}
diff --git a/core/chain_indexer.go b/core/chain_indexer.go
index 7fb184aaa..158ed8324 100644
--- a/core/chain_indexer.go
+++ b/core/chain_indexer.go
@@ -203,6 +203,9 @@ func (c *ChainIndexer) eventLoop(currentHeader *types.Header, events chan ChainE
if header.ParentHash != prevHash {
// Reorg to the common ancestor (might not exist in light sync mode, skip reorg then)
// TODO(karalabe, zsfelfoldi): This seems a bit brittle, can we detect this case explicitly?
+
+ // TODO(karalabe): This operation is expensive and might block, causing the event system to
+ // potentially also lock up. We need to do with on a different thread somehow.
if h := FindCommonAncestor(c.chainDb, prevHeader, header); h != nil {
c.newHead(h.Number.Uint64(), true)
}
diff --git a/core/chain_makers.go b/core/chain_makers.go
index 0e5e3791e..6744428ff 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -86,7 +86,7 @@ func (b *BlockGen) AddTx(tx *types.Transaction) {
b.SetCoinbase(common.Address{})
}
b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs))
- receipt, _, err := ApplyTransaction(b.config, nil, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{})
+ receipt, _, err := ApplyTransaction(b.config, nil, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{})
if err != nil {
panic(err)
}
@@ -166,7 +166,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
genblock := func(i int, parent *types.Block, statedb *state.StateDB) (*types.Block, types.Receipts) {
// TODO(karalabe): This is needed for clique, which depends on multiple blocks.
// It's nonetheless ugly to spin up a blockchain here. Get rid of this somehow.
- blockchain, _ := NewBlockChain(db, config, engine, vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, config, engine, vm.Config{})
defer blockchain.Stop()
b := &BlockGen{i: i, parent: parent, chain: blocks, chainReader: blockchain, statedb: statedb, config: config, engine: engine}
@@ -192,10 +192,13 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
if b.engine != nil {
block, _ := b.engine.Finalize(b.chainReader, b.header, statedb, b.txs, b.uncles, b.receipts)
// Write state changes to db
- _, err := statedb.CommitTo(db, config.IsEIP158(b.header.Number))
+ root, err := statedb.Commit(config.IsEIP158(b.header.Number))
if err != nil {
panic(fmt.Sprintf("state write error: %v", err))
}
+ if err := statedb.Database().TrieDB().Commit(root, false); err != nil {
+ panic(fmt.Sprintf("trie write error: %v", err))
+ }
return block, b.receipts
}
return nil, nil
@@ -232,7 +235,6 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
UncleHash: parent.UncleHash(),
}),
GasLimit: CalcGasLimit(parent),
- GasUsed: new(big.Int),
Number: new(big.Int).Add(parent.Number(), common.Big1),
Time: time,
}
@@ -247,7 +249,7 @@ func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *B
db, _ := ethdb.NewMemDatabase()
genesis := gspec.MustCommit(db)
- blockchain, _ := NewBlockChain(db, params.AllEthashProtocolChanges, engine, vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{})
// Create and inject the requested chain
if n == 0 {
return db, blockchain, nil
diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go
index 011efe342..93be43ddc 100644
--- a/core/chain_makers_test.go
+++ b/core/chain_makers_test.go
@@ -54,13 +54,13 @@ func ExampleGenerateChain() {
switch i {
case 0:
// In block 1, addr1 sends addr2 some ether.
- tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), bigTxGas, nil, nil), signer, key1)
+ tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
gen.AddTx(tx)
case 1:
// In block 2, addr1 sends some more ether to addr2.
// addr2 passes it on to addr3.
- tx1, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(1000), bigTxGas, nil, nil), signer, key1)
- tx2, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key2)
+ tx1, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
+ tx2, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
gen.AddTx(tx1)
gen.AddTx(tx2)
case 2:
@@ -79,7 +79,7 @@ func ExampleGenerateChain() {
})
// Import the chain. This runs all block validation rules.
- blockchain, _ := NewBlockChain(db, gspec.Config, ethash.NewFaker(), vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
defer blockchain.Stop()
if i, err := blockchain.InsertChain(chain); err != nil {
diff --git a/core/dao_test.go b/core/dao_test.go
index 43e2982a5..e0a3e3ff3 100644
--- a/core/dao_test.go
+++ b/core/dao_test.go
@@ -45,7 +45,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
proConf.DAOForkBlock = forkBlock
proConf.DAOForkSupport = true
- proBc, _ := NewBlockChain(proDb, &proConf, ethash.NewFaker(), vm.Config{})
+ proBc, _ := NewBlockChain(proDb, nil, &proConf, ethash.NewFaker(), vm.Config{})
defer proBc.Stop()
conDb, _ := ethdb.NewMemDatabase()
@@ -55,7 +55,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
conConf.DAOForkBlock = forkBlock
conConf.DAOForkSupport = false
- conBc, _ := NewBlockChain(conDb, &conConf, ethash.NewFaker(), vm.Config{})
+ conBc, _ := NewBlockChain(conDb, nil, &conConf, ethash.NewFaker(), vm.Config{})
defer conBc.Stop()
if _, err := proBc.InsertChain(prefix); err != nil {
@@ -69,7 +69,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Create a pro-fork block, and try to feed into the no-fork chain
db, _ = ethdb.NewMemDatabase()
gspec.MustCommit(db)
- bc, _ := NewBlockChain(db, &conConf, ethash.NewFaker(), vm.Config{})
+ bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{})
defer bc.Stop()
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()))
@@ -79,6 +79,9 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import contra-fork chain for expansion: %v", err)
}
+ if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, true); err != nil {
+ t.Fatalf("failed to commit contra-fork head for expansion: %v", err)
+ }
blocks, _ = GenerateChain(&proConf, conBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {})
if _, err := conBc.InsertChain(blocks); err == nil {
t.Fatalf("contra-fork chain accepted pro-fork block: %v", blocks[0])
@@ -91,7 +94,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Create a no-fork block, and try to feed into the pro-fork chain
db, _ = ethdb.NewMemDatabase()
gspec.MustCommit(db)
- bc, _ = NewBlockChain(db, &proConf, ethash.NewFaker(), vm.Config{})
+ bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{})
defer bc.Stop()
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()))
@@ -101,6 +104,9 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import pro-fork chain for expansion: %v", err)
}
+ if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, true); err != nil {
+ t.Fatalf("failed to commit pro-fork head for expansion: %v", err)
+ }
blocks, _ = GenerateChain(&conConf, proBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {})
if _, err := proBc.InsertChain(blocks); err == nil {
t.Fatalf("pro-fork chain accepted contra-fork block: %v", blocks[0])
@@ -114,7 +120,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes
db, _ = ethdb.NewMemDatabase()
gspec.MustCommit(db)
- bc, _ := NewBlockChain(db, &conConf, ethash.NewFaker(), vm.Config{})
+ bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{})
defer bc.Stop()
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()))
@@ -124,6 +130,9 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import contra-fork chain for expansion: %v", err)
}
+ if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, true); err != nil {
+ t.Fatalf("failed to commit contra-fork head for expansion: %v", err)
+ }
blocks, _ = GenerateChain(&proConf, conBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {})
if _, err := conBc.InsertChain(blocks); err != nil {
t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err)
@@ -131,7 +140,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes
db, _ = ethdb.NewMemDatabase()
gspec.MustCommit(db)
- bc, _ = NewBlockChain(db, &proConf, ethash.NewFaker(), vm.Config{})
+ bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{})
defer bc.Stop()
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()))
@@ -141,6 +150,9 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import pro-fork chain for expansion: %v", err)
}
+ if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, true); err != nil {
+ t.Fatalf("failed to commit pro-fork head for expansion: %v", err)
+ }
blocks, _ = GenerateChain(&conConf, proBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {})
if _, err := proBc.InsertChain(blocks); err != nil {
t.Fatalf("pro-fork chain didn't accept contra-fork block post-fork: %v", err)
diff --git a/core/database_util_test.go b/core/database_util_test.go
index 36f43cf50..ab4e45a47 100644
--- a/core/database_util_test.go
+++ b/core/database_util_test.go
@@ -290,9 +290,9 @@ func TestHeadStorage(t *testing.T) {
func TestLookupStorage(t *testing.T) {
db, _ := ethdb.NewMemDatabase()
- tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), big.NewInt(1111), big.NewInt(11111), []byte{0x11, 0x11, 0x11})
- tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), big.NewInt(2222), big.NewInt(22222), []byte{0x22, 0x22, 0x22})
- tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), big.NewInt(3333), big.NewInt(33333), []byte{0x33, 0x33, 0x33})
+ tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11})
+ tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), 2222, big.NewInt(22222), []byte{0x22, 0x22, 0x22})
+ tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33})
txs := []*types.Transaction{tx1, tx2, tx3}
block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil, nil)
@@ -337,25 +337,25 @@ func TestBlockReceiptStorage(t *testing.T) {
receipt1 := &types.Receipt{
Status: types.ReceiptStatusFailed,
- CumulativeGasUsed: big.NewInt(1),
+ CumulativeGasUsed: 1,
Logs: []*types.Log{
{Address: common.BytesToAddress([]byte{0x11})},
{Address: common.BytesToAddress([]byte{0x01, 0x11})},
},
TxHash: common.BytesToHash([]byte{0x11, 0x11}),
ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
- GasUsed: big.NewInt(111111),
+ GasUsed: 111111,
}
receipt2 := &types.Receipt{
PostState: common.Hash{2}.Bytes(),
- CumulativeGasUsed: big.NewInt(2),
+ CumulativeGasUsed: 2,
Logs: []*types.Log{
{Address: common.BytesToAddress([]byte{0x22})},
{Address: common.BytesToAddress([]byte{0x02, 0x22})},
},
TxHash: common.BytesToHash([]byte{0x22, 0x22}),
ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
- GasUsed: big.NewInt(222222),
+ GasUsed: 222222,
}
receipts := []*types.Receipt{receipt1, receipt2}
diff --git a/core/evm.go b/core/evm.go
index 4912aa650..55db53927 100644
--- a/core/evm.go
+++ b/core/evm.go
@@ -53,7 +53,7 @@ func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author
BlockNumber: new(big.Int).Set(header.Number),
Time: new(big.Int).Set(header.Time),
Difficulty: new(big.Int).Set(header.Difficulty),
- GasLimit: new(big.Int).Set(header.GasLimit),
+ GasLimit: header.GasLimit,
GasPrice: new(big.Int).Set(msg.GasPrice()),
}
}
diff --git a/core/gaspool.go b/core/gaspool.go
index ef99908cf..e3795c1ee 100644
--- a/core/gaspool.go
+++ b/core/gaspool.go
@@ -16,31 +16,39 @@
package core
-import "math/big"
+import (
+ "fmt"
+ "math"
+)
-// GasPool tracks the amount of gas available during
-// execution of the transactions in a block.
-// The zero value is a pool with zero gas available.
-type GasPool big.Int
+// GasPool tracks the amount of gas available during execution of the transactions
+// in a block. The zero value is a pool with zero gas available.
+type GasPool uint64
// AddGas makes gas available for execution.
-func (gp *GasPool) AddGas(amount *big.Int) *GasPool {
- i := (*big.Int)(gp)
- i.Add(i, amount)
+func (gp *GasPool) AddGas(amount uint64) *GasPool {
+ if uint64(*gp) > math.MaxUint64-amount {
+ panic("gas pool pushed above uint64")
+ }
+ *(*uint64)(gp) += amount
return gp
}
// SubGas deducts the given amount from the pool if enough gas is
// available and returns an error otherwise.
-func (gp *GasPool) SubGas(amount *big.Int) error {
- i := (*big.Int)(gp)
- if i.Cmp(amount) < 0 {
+func (gp *GasPool) SubGas(amount uint64) error {
+ if uint64(*gp) < amount {
return ErrGasLimitReached
}
- i.Sub(i, amount)
+ *(*uint64)(gp) -= amount
return nil
}
+// Gas returns the amount of gas remaining in the pool.
+func (gp *GasPool) Gas() uint64 {
+ return uint64(*gp)
+}
+
func (gp *GasPool) String() string {
- return (*big.Int)(gp).String()
+ return fmt.Sprintf("%d", *gp)
}
diff --git a/core/gen_genesis.go b/core/gen_genesis.go
index 4d75704a6..bb8ea1d6a 100644
--- a/core/gen_genesis.go
+++ b/core/gen_genesis.go
@@ -13,6 +13,8 @@ import (
"github.com/ethereum/go-ethereum/params"
)
+var _ = (*genesisSpecMarshaling)(nil)
+
func (g Genesis) MarshalJSON() ([]byte, error) {
type Genesis struct {
Config *params.ChainConfig `json:"config"`
@@ -54,7 +56,7 @@ func (g *Genesis) UnmarshalJSON(input []byte) error {
Config *params.ChainConfig `json:"config"`
Nonce *math.HexOrDecimal64 `json:"nonce"`
Timestamp *math.HexOrDecimal64 `json:"timestamp"`
- ExtraData hexutil.Bytes `json:"extraData"`
+ ExtraData *hexutil.Bytes `json:"extraData"`
GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"`
Mixhash *common.Hash `json:"mixHash"`
@@ -78,7 +80,7 @@ func (g *Genesis) UnmarshalJSON(input []byte) error {
g.Timestamp = uint64(*dec.Timestamp)
}
if dec.ExtraData != nil {
- g.ExtraData = dec.ExtraData
+ g.ExtraData = *dec.ExtraData
}
if dec.GasLimit == nil {
return errors.New("missing required field 'gasLimit' for Genesis")
diff --git a/core/gen_genesis_account.go b/core/gen_genesis_account.go
index 15c9565a2..64fb9b924 100644
--- a/core/gen_genesis_account.go
+++ b/core/gen_genesis_account.go
@@ -38,18 +38,18 @@ func (g GenesisAccount) MarshalJSON() ([]byte, error) {
func (g *GenesisAccount) UnmarshalJSON(input []byte) error {
type GenesisAccount struct {
- Code hexutil.Bytes `json:"code,omitempty"`
+ Code *hexutil.Bytes `json:"code,omitempty"`
Storage map[storageJSON]storageJSON `json:"storage,omitempty"`
Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"`
Nonce *math.HexOrDecimal64 `json:"nonce,omitempty"`
- PrivateKey hexutil.Bytes `json:"secretKey,omitempty"`
+ PrivateKey *hexutil.Bytes `json:"secretKey,omitempty"`
}
var dec GenesisAccount
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Code != nil {
- g.Code = dec.Code
+ g.Code = *dec.Code
}
if dec.Storage != nil {
g.Storage = make(map[common.Hash]common.Hash, len(dec.Storage))
@@ -65,7 +65,7 @@ func (g *GenesisAccount) UnmarshalJSON(input []byte) error {
g.Nonce = uint64(*dec.Nonce)
}
if dec.PrivateKey != nil {
- g.PrivateKey = dec.PrivateKey
+ g.PrivateKey = *dec.PrivateKey
}
return nil
}
diff --git a/core/genesis.go b/core/genesis.go
index df491ce0f..b6ead2250 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -169,10 +169,9 @@ func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig
// Check whether the genesis block is already written.
if genesis != nil {
- block, _ := genesis.ToBlock()
- hash := block.Hash()
+ hash := genesis.ToBlock(nil).Hash()
if hash != stored {
- return genesis.Config, block.Hash(), &GenesisMismatchError{stored, hash}
+ return genesis.Config, hash, &GenesisMismatchError{stored, hash}
}
}
@@ -220,9 +219,12 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
}
}
-// ToBlock creates the block and state of a genesis specification.
-func (g *Genesis) ToBlock() (*types.Block, *state.StateDB) {
- db, _ := ethdb.NewMemDatabase()
+// ToBlock creates the genesis block and writes state of a genesis specification
+// to the given database (or discards it if nil).
+func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
+ if db == nil {
+ db, _ = ethdb.NewMemDatabase()
+ }
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
for addr, account := range g.Alloc {
statedb.AddBalance(addr, account.Balance)
@@ -239,8 +241,8 @@ func (g *Genesis) ToBlock() (*types.Block, *state.StateDB) {
Time: new(big.Int).SetUint64(g.Timestamp),
ParentHash: g.ParentHash,
Extra: g.ExtraData,
- GasLimit: new(big.Int).SetUint64(g.GasLimit),
- GasUsed: new(big.Int).SetUint64(g.GasUsed),
+ GasLimit: g.GasLimit,
+ GasUsed: g.GasUsed,
Difficulty: g.Difficulty,
MixDigest: g.Mixhash,
Coinbase: g.Coinbase,
@@ -252,19 +254,19 @@ func (g *Genesis) ToBlock() (*types.Block, *state.StateDB) {
if g.Difficulty == nil {
head.Difficulty = params.GenesisDifficulty
}
- return types.NewBlock(head, nil, nil, nil), statedb
+ statedb.Commit(false)
+ statedb.Database().TrieDB().Commit(root, true)
+
+ return types.NewBlock(head, nil, nil, nil)
}
// Commit writes the block and state of a genesis specification to the database.
// The block is committed as the canonical head block.
func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
- block, statedb := g.ToBlock()
+ block := g.ToBlock(db)
if block.Number().Sign() != 0 {
return nil, fmt.Errorf("can't commit genesis block with number > 0")
}
- if _, err := statedb.CommitTo(db, false); err != nil {
- return nil, fmt.Errorf("cannot write state: %v", err)
- }
if err := WriteTd(db, block.Hash(), block.NumberU64(), g.Difficulty); err != nil {
return nil, err
}
diff --git a/core/genesis_test.go b/core/genesis_test.go
index 2fe931b24..cd548d4b1 100644
--- a/core/genesis_test.go
+++ b/core/genesis_test.go
@@ -30,11 +30,11 @@ import (
)
func TestDefaultGenesisBlock(t *testing.T) {
- block, _ := DefaultGenesisBlock().ToBlock()
+ block := DefaultGenesisBlock().ToBlock(nil)
if block.Hash() != params.MainnetGenesisHash {
t.Errorf("wrong mainnet genesis hash, got %v, want %v", block.Hash(), params.MainnetGenesisHash)
}
- block, _ = DefaultTestnetGenesisBlock().ToBlock()
+ block = DefaultTestnetGenesisBlock().ToBlock(nil)
if block.Hash() != params.TestnetGenesisHash {
t.Errorf("wrong testnet genesis hash, got %v, want %v", block.Hash(), params.TestnetGenesisHash)
}
@@ -118,7 +118,7 @@ func TestSetupGenesis(t *testing.T) {
// Commit the 'old' genesis block with Homestead transition at #2.
// Advance to block #4, past the homestead transition block of customg.
genesis := oldcustomg.MustCommit(db)
- bc, _ := NewBlockChain(db, oldcustomg.Config, ethash.NewFullFaker(), vm.Config{})
+ bc, _ := NewBlockChain(db, nil, oldcustomg.Config, ethash.NewFullFaker(), vm.Config{})
defer bc.Stop()
bc.SetValidator(bproc{})
bc.InsertChain(makeBlockChainWithDiff(genesis, []int{2, 3, 4, 5}, 0))
diff --git a/core/state/database.go b/core/state/database.go
index 946625e76..36926ec69 100644
--- a/core/state/database.go
+++ b/core/state/database.go
@@ -40,16 +40,23 @@ const (
// Database wraps access to tries and contract code.
type Database interface {
- // Accessing tries:
// OpenTrie opens the main account trie.
- // OpenStorageTrie opens the storage trie of an account.
OpenTrie(root common.Hash) (Trie, error)
+
+ // OpenStorageTrie opens the storage trie of an account.
OpenStorageTrie(addrHash, root common.Hash) (Trie, error)
- // Accessing contract code:
- ContractCode(addrHash, codeHash common.Hash) ([]byte, error)
- ContractCodeSize(addrHash, codeHash common.Hash) (int, error)
+
// CopyTrie returns an independent copy of the given trie.
CopyTrie(Trie) Trie
+
+ // ContractCode retrieves a particular contract's code.
+ ContractCode(addrHash, codeHash common.Hash) ([]byte, error)
+
+ // ContractCodeSize retrieves a particular contracts code's size.
+ ContractCodeSize(addrHash, codeHash common.Hash) (int, error)
+
+ // TrieDB retrieves the low level trie database used for data storage.
+ TrieDB() *trie.Database
}
// Trie is a Ethereum Merkle Trie.
@@ -57,26 +64,33 @@ type Trie interface {
TryGet(key []byte) ([]byte, error)
TryUpdate(key, value []byte) error
TryDelete(key []byte) error
- CommitTo(trie.DatabaseWriter) (common.Hash, error)
+ Commit(onleaf trie.LeafCallback) (common.Hash, error)
Hash() common.Hash
NodeIterator(startKey []byte) trie.NodeIterator
GetKey([]byte) []byte // TODO(fjl): remove this when SecureTrie is removed
+ Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error
}
// NewDatabase creates a backing store for state. The returned database is safe for
-// concurrent use and retains cached trie nodes in memory.
+// concurrent use and retains cached trie nodes in memory. The pool is an optional
+// intermediate trie-node memory pool between the low level storage layer and the
+// high level trie abstraction.
func NewDatabase(db ethdb.Database) Database {
csc, _ := lru.New(codeSizeCacheSize)
- return &cachingDB{db: db, codeSizeCache: csc}
+ return &cachingDB{
+ db: trie.NewDatabase(db),
+ codeSizeCache: csc,
+ }
}
type cachingDB struct {
- db ethdb.Database
+ db *trie.Database
mu sync.Mutex
pastTries []*trie.SecureTrie
codeSizeCache *lru.Cache
}
+// OpenTrie opens the main account trie.
func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
db.mu.Lock()
defer db.mu.Unlock()
@@ -105,10 +119,12 @@ func (db *cachingDB) pushTrie(t *trie.SecureTrie) {
}
}
+// OpenStorageTrie opens the storage trie of an account.
func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) {
return trie.NewSecure(root, db.db, 0)
}
+// CopyTrie returns an independent copy of the given trie.
func (db *cachingDB) CopyTrie(t Trie) Trie {
switch t := t.(type) {
case cachedTrie:
@@ -120,14 +136,16 @@ func (db *cachingDB) CopyTrie(t Trie) Trie {
}
}
+// ContractCode retrieves a particular contract's code.
func (db *cachingDB) ContractCode(addrHash, codeHash common.Hash) ([]byte, error) {
- code, err := db.db.Get(codeHash[:])
+ code, err := db.db.Node(codeHash)
if err == nil {
db.codeSizeCache.Add(codeHash, len(code))
}
return code, err
}
+// ContractCodeSize retrieves a particular contracts code's size.
func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, error) {
if cached, ok := db.codeSizeCache.Get(codeHash); ok {
return cached.(int), nil
@@ -139,16 +157,25 @@ func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, erro
return len(code), err
}
+// TrieDB retrieves any intermediate trie-node caching layer.
+func (db *cachingDB) TrieDB() *trie.Database {
+ return db.db
+}
+
// cachedTrie inserts its trie into a cachingDB on commit.
type cachedTrie struct {
*trie.SecureTrie
db *cachingDB
}
-func (m cachedTrie) CommitTo(dbw trie.DatabaseWriter) (common.Hash, error) {
- root, err := m.SecureTrie.CommitTo(dbw)
+func (m cachedTrie) Commit(onleaf trie.LeafCallback) (common.Hash, error) {
+ root, err := m.SecureTrie.Commit(onleaf)
if err == nil {
m.db.pushTrie(m.SecureTrie)
}
return root, err
}
+
+func (m cachedTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error {
+ return m.SecureTrie.Prove(key, fromLevel, proofDb)
+}
diff --git a/core/state/iterator_test.go b/core/state/iterator_test.go
index ff66ba7a9..9e46c851c 100644
--- a/core/state/iterator_test.go
+++ b/core/state/iterator_test.go
@@ -21,12 +21,13 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/ethdb"
)
// Tests that the node iterator indeed walks over the entire database contents.
func TestNodeIteratorCoverage(t *testing.T) {
// Create some arbitrary test state to iterate
- db, mem, root, _ := makeTestState()
+ db, root, _ := makeTestState()
state, err := New(root, db)
if err != nil {
@@ -39,14 +40,18 @@ func TestNodeIteratorCoverage(t *testing.T) {
hashes[it.Hash] = struct{}{}
}
}
-
- // Cross check the hashes and the database itself
+ // Cross check the iterated hashes and the database/nodepool content
for hash := range hashes {
- if _, err := mem.Get(hash.Bytes()); err != nil {
- t.Errorf("failed to retrieve reported node %x: %v", hash, err)
+ if _, err := db.TrieDB().Node(hash); err != nil {
+ t.Errorf("failed to retrieve reported node %x", hash)
+ }
+ }
+ for _, hash := range db.TrieDB().Nodes() {
+ if _, ok := hashes[hash]; !ok {
+ t.Errorf("state entry not reported %x", hash)
}
}
- for _, key := range mem.Keys() {
+ for _, key := range db.TrieDB().DiskDB().(*ethdb.MemDatabase).Keys() {
if bytes.HasPrefix(key, []byte("secure-key-")) {
continue
}
diff --git a/core/state/journal.go b/core/state/journal.go
index ddc819fe5..a89bb3d13 100644
--- a/core/state/journal.go
+++ b/core/state/journal.go
@@ -62,7 +62,7 @@ type (
// Changes to other state values.
refundChange struct {
- prev *big.Int
+ prev uint64
}
addLogChange struct {
txhash common.Hash
diff --git a/core/state/state_object.go b/core/state/state_object.go
index b2378c69c..b2112bfae 100644
--- a/core/state/state_object.go
+++ b/core/state/state_object.go
@@ -25,7 +25,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie"
)
var emptyCodeHash = crypto.Keccak256(nil)
@@ -238,12 +237,12 @@ func (self *stateObject) updateRoot(db Database) {
// CommitTrie the storage trie of the object to dwb.
// This updates the trie root.
-func (self *stateObject) CommitTrie(db Database, dbw trie.DatabaseWriter) error {
+func (self *stateObject) CommitTrie(db Database) error {
self.updateTrie(db)
if self.dbErr != nil {
return self.dbErr
}
- root, err := self.trie.CommitTo(dbw)
+ root, err := self.trie.Commit(nil)
if err == nil {
self.data.Root = root
}
diff --git a/core/state/state_test.go b/core/state/state_test.go
index bbae3685b..6d42d63d8 100644
--- a/core/state/state_test.go
+++ b/core/state/state_test.go
@@ -48,7 +48,7 @@ func (s *StateSuite) TestDump(c *checker.C) {
// write some of them to the trie
s.state.updateStateObject(obj1)
s.state.updateStateObject(obj2)
- s.state.CommitTo(s.db, false)
+ s.state.Commit(false)
// check that dump contains the state objects that are in trie
got := string(s.state.Dump())
@@ -97,7 +97,7 @@ func (s *StateSuite) TestNull(c *checker.C) {
//value := common.FromHex("0x823140710bf13990e4500136726d8b55")
var value common.Hash
s.state.SetState(address, common.Hash{}, value)
- s.state.CommitTo(s.db, false)
+ s.state.Commit(false)
value = s.state.GetState(address, common.Hash{})
if !common.EmptyHash(value) {
c.Errorf("expected empty hash. got %x", value)
@@ -155,7 +155,7 @@ func TestSnapshot2(t *testing.T) {
so0.deleted = false
state.setStateObject(so0)
- root, _ := state.CommitTo(db, false)
+ root, _ := state.Commit(false)
state.Reset(root)
// and one with deleted == true
diff --git a/core/state/statedb.go b/core/state/statedb.go
index de9fb367d..776693e24 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -36,6 +36,14 @@ type revision struct {
journalIndex int
}
+var (
+ // emptyState is the known hash of an empty state trie entry.
+ emptyState = crypto.Keccak256Hash(nil)
+
+ // emptyCode is the known hash of the empty EVM bytecode.
+ emptyCode = crypto.Keccak256Hash(nil)
+)
+
// StateDBs within the ethereum protocol are used to store anything
// within the merkle trie. StateDBs take care of caching and storing
// nested states. It's the general query interface to retrieve:
@@ -57,7 +65,7 @@ type StateDB struct {
dbErr error
// The refund counter, also used by state transitioning.
- refund *big.Int
+ refund uint64
thash, bhash common.Hash
txIndex int
@@ -86,7 +94,6 @@ func New(root common.Hash, db Database) (*StateDB, error) {
trie: tr,
stateObjects: make(map[common.Address]*stateObject),
stateObjectsDirty: make(map[common.Address]struct{}),
- refund: new(big.Int),
logs: make(map[common.Hash][]*types.Log),
preimages: make(map[common.Hash][]byte),
}, nil
@@ -161,9 +168,9 @@ func (self *StateDB) Preimages() map[common.Hash][]byte {
return self.preimages
}
-func (self *StateDB) AddRefund(gas *big.Int) {
- self.journal = append(self.journal, refundChange{prev: new(big.Int).Set(self.refund)})
- self.refund.Add(self.refund, gas)
+func (self *StateDB) AddRefund(gas uint64) {
+ self.journal = append(self.journal, refundChange{prev: self.refund})
+ self.refund += gas
}
// Exist reports whether the given account address exists in the state.
@@ -236,6 +243,11 @@ func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash {
return common.Hash{}
}
+// Database retrieves the low level database supporting the lower level trie ops.
+func (self *StateDB) Database() Database {
+ return self.db
+}
+
// StorageTrie returns the storage trie of an account.
// The return value is a copy and is nil for non-existent accounts.
func (self *StateDB) StorageTrie(a common.Address) Trie {
@@ -456,7 +468,7 @@ func (self *StateDB) Copy() *StateDB {
trie: self.db.CopyTrie(self.trie),
stateObjects: make(map[common.Address]*stateObject, len(self.stateObjectsDirty)),
stateObjectsDirty: make(map[common.Address]struct{}, len(self.stateObjectsDirty)),
- refund: new(big.Int).Set(self.refund),
+ refund: self.refund,
logs: make(map[common.Hash][]*types.Log, len(self.logs)),
logSize: self.logSize,
preimages: make(map[common.Hash][]byte),
@@ -506,9 +518,7 @@ func (self *StateDB) RevertToSnapshot(revid int) {
}
// GetRefund returns the current value of the refund counter.
-// The return value must not be modified by the caller and will become
-// invalid at the next call to AddRefund.
-func (self *StateDB) GetRefund() *big.Int {
+func (self *StateDB) GetRefund() uint64 {
return self.refund
}
@@ -568,11 +578,11 @@ func (s *StateDB) DeleteSuicides() {
func (s *StateDB) clearJournalAndRefund() {
s.journal = nil
s.validRevisions = s.validRevisions[:0]
- s.refund = new(big.Int)
+ s.refund = 0
}
-// CommitTo writes the state to the given database.
-func (s *StateDB) CommitTo(dbw trie.DatabaseWriter, deleteEmptyObjects bool) (root common.Hash, err error) {
+// Commit writes the state to the underlying in-memory trie database.
+func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error) {
defer s.clearJournalAndRefund()
// Commit objects to the trie.
@@ -586,13 +596,11 @@ func (s *StateDB) CommitTo(dbw trie.DatabaseWriter, deleteEmptyObjects bool) (ro
case isDirty:
// Write any contract code associated with the state object
if stateObject.code != nil && stateObject.dirtyCode {
- if err := dbw.Put(stateObject.CodeHash(), stateObject.code); err != nil {
- return common.Hash{}, err
- }
+ s.db.TrieDB().Insert(common.BytesToHash(stateObject.CodeHash()), stateObject.code)
stateObject.dirtyCode = false
}
// Write any storage changes in the state object to its storage trie.
- if err := stateObject.CommitTrie(s.db, dbw); err != nil {
+ if err := stateObject.CommitTrie(s.db); err != nil {
return common.Hash{}, err
}
// Update the object in the main account trie.
@@ -601,7 +609,20 @@ func (s *StateDB) CommitTo(dbw trie.DatabaseWriter, deleteEmptyObjects bool) (ro
delete(s.stateObjectsDirty, addr)
}
// Write trie changes.
- root, err = s.trie.CommitTo(dbw)
+ root, err = s.trie.Commit(func(leaf []byte, parent common.Hash) error {
+ var account Account
+ if err := rlp.DecodeBytes(leaf, &account); err != nil {
+ return nil
+ }
+ if account.Root != emptyState {
+ s.db.TrieDB().Reference(account.Root, parent)
+ }
+ code := common.BytesToHash(account.CodeHash)
+ if code != emptyCode {
+ s.db.TrieDB().Reference(code, parent)
+ }
+ return nil
+ })
log.Debug("Trie cache stats after commit", "misses", trie.CacheMisses(), "unloads", trie.CacheUnloads())
return root, err
}
diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go
index e9944cd74..d9e3d9b79 100644
--- a/core/state/statedb_test.go
+++ b/core/state/statedb_test.go
@@ -97,10 +97,10 @@ func TestIntermediateLeaks(t *testing.T) {
}
// Commit and cross check the databases.
- if _, err := transState.CommitTo(transDb, false); err != nil {
+ if _, err := transState.Commit(false); err != nil {
t.Fatalf("failed to commit transition state: %v", err)
}
- if _, err := finalState.CommitTo(finalDb, false); err != nil {
+ if _, err := finalState.Commit(false); err != nil {
t.Fatalf("failed to commit final state: %v", err)
}
for _, key := range finalDb.Keys() {
@@ -122,8 +122,8 @@ func TestIntermediateLeaks(t *testing.T) {
// https://github.com/ethereum/go-ethereum/pull/15549.
func TestCopy(t *testing.T) {
// Create a random state test to copy and modify "independently"
- mem, _ := ethdb.NewMemDatabase()
- orig, _ := New(common.Hash{}, NewDatabase(mem))
+ db, _ := ethdb.NewMemDatabase()
+ orig, _ := New(common.Hash{}, NewDatabase(db))
for i := byte(0); i < 255; i++ {
obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
@@ -263,7 +263,7 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction {
{
name: "AddRefund",
fn: func(a testAction, s *StateDB) {
- s.AddRefund(big.NewInt(a.args[0]))
+ s.AddRefund(uint64(a.args[0]))
},
args: make([]int64, 1),
noAddr: true,
@@ -346,11 +346,10 @@ func (test *snapshotTest) run() bool {
}
action.fn(action, state)
}
-
// Revert all snapshots in reverse order. Each revert must yield a state
// that is equivalent to fresh state with all actions up the snapshot applied.
for sindex--; sindex >= 0; sindex-- {
- checkstate, _ := New(common.Hash{}, NewDatabase(db))
+ checkstate, _ := New(common.Hash{}, state.Database())
for _, action := range test.actions[:test.snapshots[sindex]] {
action.fn(action, checkstate)
}
@@ -396,7 +395,7 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
}
}
- if state.GetRefund().Cmp(checkstate.GetRefund()) != 0 {
+ if state.GetRefund() != checkstate.GetRefund() {
return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d",
state.GetRefund(), checkstate.GetRefund())
}
@@ -409,7 +408,7 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
func (s *StateSuite) TestTouchDelete(c *check.C) {
s.state.GetOrNewStateObject(common.Address{})
- root, _ := s.state.CommitTo(s.db, false)
+ root, _ := s.state.Commit(false)
s.state.Reset(root)
snapshot := s.state.Snapshot()
@@ -417,7 +416,6 @@ func (s *StateSuite) TestTouchDelete(c *check.C) {
if len(s.state.stateObjectsDirty) != 1 {
c.Fatal("expected one dirty state object")
}
-
s.state.RevertToSnapshot(snapshot)
if len(s.state.stateObjectsDirty) != 0 {
c.Fatal("expected no dirty state object")
diff --git a/core/state/sync_test.go b/core/state/sync_test.go
index 06c572ea6..8f14a44e7 100644
--- a/core/state/sync_test.go
+++ b/core/state/sync_test.go
@@ -36,10 +36,10 @@ type testAccount struct {
}
// makeTestState create a sample test state to test node-wise reconstruction.
-func makeTestState() (Database, *ethdb.MemDatabase, common.Hash, []*testAccount) {
+func makeTestState() (Database, common.Hash, []*testAccount) {
// Create an empty state
- mem, _ := ethdb.NewMemDatabase()
- db := NewDatabase(mem)
+ diskdb, _ := ethdb.NewMemDatabase()
+ db := NewDatabase(diskdb)
state, _ := New(common.Hash{}, db)
// Fill it with some arbitrary data
@@ -61,10 +61,10 @@ func makeTestState() (Database, *ethdb.MemDatabase, common.Hash, []*testAccount)
state.updateStateObject(obj)
accounts = append(accounts, acc)
}
- root, _ := state.CommitTo(mem, false)
+ root, _ := state.Commit(false)
// Return the generated state
- return db, mem, root, accounts
+ return db, root, accounts
}
// checkStateAccounts cross references a reconstructed state with an expected
@@ -96,7 +96,7 @@ func checkTrieConsistency(db ethdb.Database, root common.Hash) error {
if v, _ := db.Get(root[:]); v == nil {
return nil // Consider a non existent state consistent.
}
- trie, err := trie.New(root, db)
+ trie, err := trie.New(root, trie.NewDatabase(db))
if err != nil {
return err
}
@@ -138,7 +138,7 @@ func TestIterativeStateSyncBatched(t *testing.T) { testIterativeStateSync(t,
func testIterativeStateSync(t *testing.T, batch int) {
// Create a random state to copy
- _, srcMem, srcRoot, srcAccounts := makeTestState()
+ srcDb, srcRoot, srcAccounts := makeTestState()
// Create a destination state and sync with the scheduler
dstDb, _ := ethdb.NewMemDatabase()
@@ -148,9 +148,9 @@ func testIterativeStateSync(t *testing.T, batch int) {
for len(queue) > 0 {
results := make([]trie.SyncResult, len(queue))
for i, hash := range queue {
- data, err := srcMem.Get(hash.Bytes())
+ data, err := srcDb.TrieDB().Node(hash)
if err != nil {
- t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
+ t.Fatalf("failed to retrieve node data for %x", hash)
}
results[i] = trie.SyncResult{Hash: hash, Data: data}
}
@@ -170,7 +170,7 @@ func testIterativeStateSync(t *testing.T, batch int) {
// partial results are returned, and the others sent only later.
func TestIterativeDelayedStateSync(t *testing.T) {
// Create a random state to copy
- _, srcMem, srcRoot, srcAccounts := makeTestState()
+ srcDb, srcRoot, srcAccounts := makeTestState()
// Create a destination state and sync with the scheduler
dstDb, _ := ethdb.NewMemDatabase()
@@ -181,9 +181,9 @@ func TestIterativeDelayedStateSync(t *testing.T) {
// Sync only half of the scheduled nodes
results := make([]trie.SyncResult, len(queue)/2+1)
for i, hash := range queue[:len(results)] {
- data, err := srcMem.Get(hash.Bytes())
+ data, err := srcDb.TrieDB().Node(hash)
if err != nil {
- t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
+ t.Fatalf("failed to retrieve node data for %x", hash)
}
results[i] = trie.SyncResult{Hash: hash, Data: data}
}
@@ -207,7 +207,7 @@ func TestIterativeRandomStateSyncBatched(t *testing.T) { testIterativeRandomS
func testIterativeRandomStateSync(t *testing.T, batch int) {
// Create a random state to copy
- _, srcMem, srcRoot, srcAccounts := makeTestState()
+ srcDb, srcRoot, srcAccounts := makeTestState()
// Create a destination state and sync with the scheduler
dstDb, _ := ethdb.NewMemDatabase()
@@ -221,9 +221,9 @@ func testIterativeRandomStateSync(t *testing.T, batch int) {
// Fetch all the queued nodes in a random order
results := make([]trie.SyncResult, 0, len(queue))
for hash := range queue {
- data, err := srcMem.Get(hash.Bytes())
+ data, err := srcDb.TrieDB().Node(hash)
if err != nil {
- t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
+ t.Fatalf("failed to retrieve node data for %x", hash)
}
results = append(results, trie.SyncResult{Hash: hash, Data: data})
}
@@ -247,7 +247,7 @@ func testIterativeRandomStateSync(t *testing.T, batch int) {
// partial results are returned (Even those randomly), others sent only later.
func TestIterativeRandomDelayedStateSync(t *testing.T) {
// Create a random state to copy
- _, srcMem, srcRoot, srcAccounts := makeTestState()
+ srcDb, srcRoot, srcAccounts := makeTestState()
// Create a destination state and sync with the scheduler
dstDb, _ := ethdb.NewMemDatabase()
@@ -263,9 +263,9 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
for hash := range queue {
delete(queue, hash)
- data, err := srcMem.Get(hash.Bytes())
+ data, err := srcDb.TrieDB().Node(hash)
if err != nil {
- t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
+ t.Fatalf("failed to retrieve node data for %x", hash)
}
results = append(results, trie.SyncResult{Hash: hash, Data: data})
@@ -292,9 +292,9 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
// the database.
func TestIncompleteStateSync(t *testing.T) {
// Create a random state to copy
- _, srcMem, srcRoot, srcAccounts := makeTestState()
+ srcDb, srcRoot, srcAccounts := makeTestState()
- checkTrieConsistency(srcMem, srcRoot)
+ checkTrieConsistency(srcDb.TrieDB().DiskDB().(ethdb.Database), srcRoot)
// Create a destination state and sync with the scheduler
dstDb, _ := ethdb.NewMemDatabase()
@@ -306,9 +306,9 @@ func TestIncompleteStateSync(t *testing.T) {
// Fetch a batch of state nodes
results := make([]trie.SyncResult, len(queue))
for i, hash := range queue {
- data, err := srcMem.Get(hash.Bytes())
+ data, err := srcDb.TrieDB().Node(hash)
if err != nil {
- t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
+ t.Fatalf("failed to retrieve node data for %x", hash)
}
results[i] = trie.SyncResult{Hash: hash, Data: data}
}
diff --git a/core/state_processor.go b/core/state_processor.go
index 689c83785..4dc58b9de 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -17,8 +17,6 @@
package core
import (
- "math/big"
-
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc"
@@ -55,13 +53,13 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consen
// Process returns the receipts and logs accumulated during the process and
// returns the amount of gas that was used in the process. If any of the
// transactions failed to execute due to insufficient gas it will return an error.
-func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *big.Int, error) {
+func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) {
var (
- receipts types.Receipts
- totalUsedGas = big.NewInt(0)
- header = block.Header()
- allLogs []*types.Log
- gp = new(GasPool).AddGas(block.GasLimit())
+ receipts types.Receipts
+ usedGas = new(uint64)
+ header = block.Header()
+ allLogs []*types.Log
+ gp = new(GasPool).AddGas(block.GasLimit())
)
// Mutate the the block and state according to any hard-fork specs
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
@@ -70,9 +68,9 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
// Iterate over and process the individual transactions
for i, tx := range block.Transactions() {
statedb.Prepare(tx.Hash(), block.Hash(), i)
- receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, totalUsedGas, cfg)
+ receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg)
if err != nil {
- return nil, nil, nil, err
+ return nil, nil, 0, err
}
receipts = append(receipts, receipt)
allLogs = append(allLogs, receipt.Logs...)
@@ -80,17 +78,17 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), receipts)
- return receipts, allLogs, totalUsedGas, nil
+ return receipts, allLogs, *usedGas, nil
}
// ApplyTransaction attempts to apply a transaction to the given state database
// and uses the input parameters for its environment. It returns the receipt
// for the transaction, gas used and an error if the transaction failed,
// indicating the block was invalid.
-func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg vm.Config) (*types.Receipt, *big.Int, error) {
+func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, uint64, error) {
msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
if err != nil {
- return nil, nil, err
+ return nil, 0, err
}
// Create a new context to be used in the EVM environment
context := NewEVMContext(msg, header, bc, author)
@@ -100,9 +98,8 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common
// Apply the transaction to the current state (included in the env)
_, gas, failed, err := ApplyMessage(vmenv, msg, gp)
if err != nil {
- return nil, nil, err
+ return nil, 0, err
}
-
// Update the state with pending changes
var root []byte
if config.IsByzantium(header.Number) {
@@ -110,18 +107,17 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common
} else {
root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes()
}
- usedGas.Add(usedGas, gas)
+ *usedGas += gas
// Create a new receipt for the transaction, storing the intermediate root and gas used by the tx
// based on the eip phase, we're passing wether the root touch-delete accounts.
- receipt := types.NewReceipt(root, failed, usedGas)
+ receipt := types.NewReceipt(root, failed, *usedGas)
receipt.TxHash = tx.Hash()
- receipt.GasUsed = new(big.Int).Set(gas)
+ receipt.GasUsed = gas
// if the transaction created a contract, store the creation address in the receipt.
if msg.To() == nil {
receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce())
}
-
// Set the receipt logs and create a bloom for filtering
receipt.Logs = statedb.GetLogs(tx.Hash())
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
diff --git a/core/state_transition.go b/core/state_transition.go
index e7a068589..b19bc12e4 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -18,17 +18,16 @@ package core
import (
"errors"
+ "math"
"math/big"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
)
var (
- Big0 = big.NewInt(0)
errInsufficientBalanceForGas = errors.New("insufficient balance to pay for gas")
)
@@ -54,7 +53,7 @@ type StateTransition struct {
msg Message
gas uint64
gasPrice *big.Int
- initialGas *big.Int
+ initialGas uint64
value *big.Int
data []byte
state vm.StateDB
@@ -68,7 +67,7 @@ type Message interface {
To() *common.Address
GasPrice() *big.Int
- Gas() *big.Int
+ Gas() uint64
Value() *big.Int
Nonce() uint64
@@ -76,45 +75,49 @@ type Message interface {
Data() []byte
}
-// IntrinsicGas computes the 'intrinsic gas' for a message
-// with the given data.
-//
-// TODO convert to uint64
-func IntrinsicGas(data []byte, contractCreation, homestead bool) *big.Int {
- igas := new(big.Int)
+// IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
+func IntrinsicGas(data []byte, contractCreation, homestead bool) (uint64, error) {
+ // Set the starting gas for the raw transaction
+ var gas uint64
if contractCreation && homestead {
- igas.SetUint64(params.TxGasContractCreation)
+ gas = params.TxGasContractCreation
} else {
- igas.SetUint64(params.TxGas)
+ gas = params.TxGas
}
+ // Bump the required gas by the amount of transactional data
if len(data) > 0 {
- var nz int64
+ // Zero and non-zero bytes are priced differently
+ var nz uint64
for _, byt := range data {
if byt != 0 {
nz++
}
}
- m := big.NewInt(nz)
- m.Mul(m, new(big.Int).SetUint64(params.TxDataNonZeroGas))
- igas.Add(igas, m)
- m.SetInt64(int64(len(data)) - nz)
- m.Mul(m, new(big.Int).SetUint64(params.TxDataZeroGas))
- igas.Add(igas, m)
+ // Make sure we don't exceed uint64 for all data combinations
+ if (math.MaxUint64-gas)/params.TxDataNonZeroGas < nz {
+ return 0, vm.ErrOutOfGas
+ }
+ gas += nz * params.TxDataNonZeroGas
+
+ z := uint64(len(data)) - nz
+ if (math.MaxUint64-gas)/params.TxDataZeroGas < z {
+ return 0, vm.ErrOutOfGas
+ }
+ gas += z * params.TxDataZeroGas
}
- return igas
+ return gas, nil
}
// NewStateTransition initialises and returns a new state transition object.
func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition {
return &StateTransition{
- gp: gp,
- evm: evm,
- msg: msg,
- gasPrice: msg.GasPrice(),
- initialGas: new(big.Int),
- value: msg.Value(),
- data: msg.Data(),
- state: evm.StateDB,
+ gp: gp,
+ evm: evm,
+ msg: msg,
+ gasPrice: msg.GasPrice(),
+ value: msg.Value(),
+ data: msg.Data(),
+ state: evm.StateDB,
}
}
@@ -125,11 +128,8 @@ func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition
// the gas used (which includes gas refunds) and an error if it failed. An error always
// indicates a core error meaning that the message would always fail for that particular
// state and would never be accepted within a block.
-func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, *big.Int, bool, error) {
- st := NewStateTransition(evm, msg, gp)
-
- ret, _, gasUsed, failed, err := st.TransitionDb()
- return ret, gasUsed, failed, err
+func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, uint64, bool, error) {
+ return NewStateTransition(evm, msg, gp).TransitionDb()
}
func (st *StateTransition) from() vm.AccountRef {
@@ -166,26 +166,20 @@ func (st *StateTransition) useGas(amount uint64) error {
}
func (st *StateTransition) buyGas() error {
- mgas := st.msg.Gas()
- if mgas.BitLen() > 64 {
- return vm.ErrOutOfGas
- }
-
- mgval := new(big.Int).Mul(mgas, st.gasPrice)
-
var (
state = st.state
sender = st.from()
)
+ mgval := new(big.Int).Mul(new(big.Int).SetUint64(st.msg.Gas()), st.gasPrice)
if state.GetBalance(sender.Address()).Cmp(mgval) < 0 {
return errInsufficientBalanceForGas
}
- if err := st.gp.SubGas(mgas); err != nil {
+ if err := st.gp.SubGas(st.msg.Gas()); err != nil {
return err
}
- st.gas += mgas.Uint64()
+ st.gas += st.msg.Gas()
- st.initialGas.Set(mgas)
+ st.initialGas = st.msg.Gas()
state.SubBalance(sender.Address(), mgval)
return nil
}
@@ -206,10 +200,10 @@ func (st *StateTransition) preCheck() error {
return st.buyGas()
}
-// TransitionDb will transition the state by applying the current message and returning the result
-// including the required gas for the operation as well as the used gas. It returns an error if it
+// TransitionDb will transition the state by applying the current message and
+// returning the result including the the used gas. It returns an error if it
// failed. An error indicates a consensus issue.
-func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big.Int, failed bool, err error) {
+func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bool, err error) {
if err = st.preCheck(); err != nil {
return
}
@@ -220,13 +214,12 @@ func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big
contractCreation := msg.To() == nil
// Pay intrinsic gas
- // TODO convert to uint64
- intrinsicGas := IntrinsicGas(st.data, contractCreation, homestead)
- if intrinsicGas.BitLen() > 64 {
- return nil, nil, nil, false, vm.ErrOutOfGas
+ gas, err := IntrinsicGas(st.data, contractCreation, homestead)
+ if err != nil {
+ return nil, 0, false, err
}
- if err = st.useGas(intrinsicGas.Uint64()); err != nil {
- return nil, nil, nil, false, err
+ if err = st.useGas(gas); err != nil {
+ return nil, 0, false, err
}
var (
@@ -249,36 +242,35 @@ func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big
// sufficient balance to make the transfer happen. The first
// balance transfer may never fail.
if vmerr == vm.ErrInsufficientBalance {
- return nil, nil, nil, false, vmerr
+ return nil, 0, false, vmerr
}
}
- requiredGas = new(big.Int).Set(st.gasUsed())
-
st.refundGas()
- st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(st.gasUsed(), st.gasPrice))
+ st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
- return ret, requiredGas, st.gasUsed(), vmerr != nil, err
+ return ret, st.gasUsed(), vmerr != nil, err
}
func (st *StateTransition) refundGas() {
- // Return eth for remaining gas to the sender account,
- // exchanged at the original rate.
- sender := st.from() // err already checked
- remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice)
- st.state.AddBalance(sender.Address(), remaining)
-
// Apply refund counter, capped to half of the used gas.
- uhalf := remaining.Div(st.gasUsed(), common.Big2)
- refund := math.BigMin(uhalf, st.state.GetRefund())
- st.gas += refund.Uint64()
+ refund := st.gasUsed() / 2
+ if refund > st.state.GetRefund() {
+ refund = st.state.GetRefund()
+ }
+ st.gas += refund
- st.state.AddBalance(sender.Address(), refund.Mul(refund, st.gasPrice))
+ // Return ETH for remaining gas, exchanged at the original rate.
+ sender := st.from()
+
+ remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice)
+ st.state.AddBalance(sender.Address(), remaining)
// Also return remaining gas to the block gas counter so it is
// available for the next transaction.
- st.gp.AddGas(new(big.Int).SetUint64(st.gas))
+ st.gp.AddGas(st.gas)
}
-func (st *StateTransition) gasUsed() *big.Int {
- return new(big.Int).Sub(st.initialGas, new(big.Int).SetUint64(st.gas))
+// gasUsed returns the amount of gas used up by the state transition.
+func (st *StateTransition) gasUsed() uint64 {
+ return st.initialGas - st.gas
}
diff --git a/core/tx_list.go b/core/tx_list.go
index 838433b89..55fc42617 100644
--- a/core/tx_list.go
+++ b/core/tx_list.go
@@ -224,7 +224,7 @@ type txList struct {
txs *txSortedMap // Heap indexed sorted hash map of the transactions
costcap *big.Int // Price of the highest costing transaction (reset only if exceeds balance)
- gascap *big.Int // Gas limit of the highest spending transaction (reset only if exceeds block limit)
+ gascap uint64 // Gas limit of the highest spending transaction (reset only if exceeds block limit)
}
// newTxList create a new transaction list for maintaining nonce-indexable fast,
@@ -234,7 +234,6 @@ func newTxList(strict bool) *txList {
strict: strict,
txs: newTxSortedMap(),
costcap: new(big.Int),
- gascap: new(big.Int),
}
}
@@ -266,7 +265,7 @@ func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Tran
if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 {
l.costcap = cost
}
- if gas := tx.Gas(); l.gascap.Cmp(gas) < 0 {
+ if gas := tx.Gas(); l.gascap < gas {
l.gascap = gas
}
return true, old
@@ -288,16 +287,16 @@ func (l *txList) Forward(threshold uint64) types.Transactions {
// a point in calculating all the costs or if the balance covers all. If the threshold
// is lower than the costgas cap, the caps will be reset to a new high after removing
// the newly invalidated transactions.
-func (l *txList) Filter(costLimit, gasLimit *big.Int) (types.Transactions, types.Transactions) {
+func (l *txList) Filter(costLimit *big.Int, gasLimit uint64) (types.Transactions, types.Transactions) {
// If all transactions are below the threshold, short circuit
- if l.costcap.Cmp(costLimit) <= 0 && l.gascap.Cmp(gasLimit) <= 0 {
+ if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit {
return nil, nil
}
l.costcap = new(big.Int).Set(costLimit) // Lower the caps to the thresholds
- l.gascap = new(big.Int).Set(gasLimit)
+ l.gascap = gasLimit
// Filter out all the transactions above the account's funds
- removed := l.txs.Filter(func(tx *types.Transaction) bool { return tx.Cost().Cmp(costLimit) > 0 || tx.Gas().Cmp(gasLimit) > 0 })
+ removed := l.txs.Filter(func(tx *types.Transaction) bool { return tx.Cost().Cmp(costLimit) > 0 || tx.Gas() > gasLimit })
// If the list was strict, filter anything above the lowest nonce
var invalids types.Transactions
diff --git a/core/tx_list_test.go b/core/tx_list_test.go
index b4f0b5228..d579f501a 100644
--- a/core/tx_list_test.go
+++ b/core/tx_list_test.go
@@ -17,7 +17,6 @@
package core
import (
- "math/big"
"math/rand"
"testing"
@@ -33,7 +32,7 @@ func TestStrictTxListAdd(t *testing.T) {
txs := make(types.Transactions, 1024)
for i := 0; i < len(txs); i++ {
- txs[i] = transaction(uint64(i), new(big.Int), key)
+ txs[i] = transaction(uint64(i), 0, key)
}
// Insert the transactions in a random order
list := newTxList(true)
diff --git a/core/tx_pool.go b/core/tx_pool.go
index dade5d09f..dc3ddc423 100644
--- a/core/tx_pool.go
+++ b/core/tx_pool.go
@@ -197,7 +197,7 @@ type TxPool struct {
currentState *state.StateDB // Current state in the blockchain head
pendingState *state.ManagedState // Pending state tracking virtual nonces
- currentMaxGas *big.Int // Current gas limit for transaction caps
+ currentMaxGas uint64 // Current gas limit for transaction caps
locals *accountSet // Set of local transaction to exempt from eviction rules
journal *txJournal // Journal of local transaction to back up to disk
@@ -564,7 +564,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
return ErrNegativeValue
}
// Ensure the transaction doesn't exceed the current block limit gas.
- if pool.currentMaxGas.Cmp(tx.Gas()) < 0 {
+ if pool.currentMaxGas < tx.Gas() {
return ErrGasLimit
}
// Make sure the transaction is signed properly
@@ -586,8 +586,11 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
if pool.currentState.GetBalance(from).Cmp(tx.Cost()) < 0 {
return ErrInsufficientFunds
}
- intrGas := IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)
- if tx.Gas().Cmp(intrGas) < 0 {
+ intrGas, err := IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)
+ if err != nil {
+ return err
+ }
+ if tx.Gas() < intrGas {
return ErrIntrinsicGas
}
return nil
diff --git a/core/tx_pool_test.go b/core/tx_pool_test.go
index 1f193a06c..158b9776b 100644
--- a/core/tx_pool_test.go
+++ b/core/tx_pool_test.go
@@ -46,7 +46,7 @@ func init() {
type testBlockChain struct {
statedb *state.StateDB
- gasLimit *big.Int
+ gasLimit uint64
chainHeadFeed *event.Feed
}
@@ -68,19 +68,19 @@ func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) even
return bc.chainHeadFeed.Subscribe(ch)
}
-func transaction(nonce uint64, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
+func transaction(nonce uint64, gaslimit uint64, key *ecdsa.PrivateKey) *types.Transaction {
return pricedTransaction(nonce, gaslimit, big.NewInt(1), key)
}
-func pricedTransaction(nonce uint64, gaslimit, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
+func pricedTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, gasprice, nil), types.HomesteadSigner{}, key)
return tx
}
func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
- db, _ := ethdb.NewMemDatabase()
- statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
- blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ diskdb, _ := ethdb.NewMemDatabase()
+ statedb, _ := state.New(common.Hash{}, state.NewDatabase(diskdb))
+ blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
key, _ := crypto.GenerateKey()
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
@@ -184,10 +184,10 @@ func TestStateChangeDuringTransactionPoolReset(t *testing.T) {
// setup pool with 2 transaction in it
statedb.SetBalance(address, new(big.Int).SetUint64(params.Ether))
- blockchain := &testChain{&testBlockChain{statedb, big.NewInt(1000000000), new(event.Feed)}, address, &trigger}
+ blockchain := &testChain{&testBlockChain{statedb, 1000000000, new(event.Feed)}, address, &trigger}
- tx0 := transaction(0, big.NewInt(100000), key)
- tx1 := transaction(1, big.NewInt(100000), key)
+ tx0 := transaction(0, 100000, key)
+ tx1 := transaction(1, 100000, key)
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
defer pool.Stop()
@@ -230,7 +230,7 @@ func TestInvalidTransactions(t *testing.T) {
pool, key := setupTxPool()
defer pool.Stop()
- tx := transaction(0, big.NewInt(100), key)
+ tx := transaction(0, 100, key)
from, _ := deriveSender(tx)
pool.currentState.AddBalance(from, big.NewInt(1))
@@ -238,7 +238,7 @@ func TestInvalidTransactions(t *testing.T) {
t.Error("expected", ErrInsufficientFunds)
}
- balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(tx.Gas(), tx.GasPrice()))
+ balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice()))
pool.currentState.AddBalance(from, balance)
if err := pool.AddRemote(tx); err != ErrIntrinsicGas {
t.Error("expected", ErrIntrinsicGas, "got", err)
@@ -246,12 +246,12 @@ func TestInvalidTransactions(t *testing.T) {
pool.currentState.SetNonce(from, 1)
pool.currentState.AddBalance(from, big.NewInt(0xffffffffffffff))
- tx = transaction(0, big.NewInt(100000), key)
+ tx = transaction(0, 100000, key)
if err := pool.AddRemote(tx); err != ErrNonceTooLow {
t.Error("expected", ErrNonceTooLow)
}
- tx = transaction(1, big.NewInt(100000), key)
+ tx = transaction(1, 100000, key)
pool.gasPrice = big.NewInt(1000)
if err := pool.AddRemote(tx); err != ErrUnderpriced {
t.Error("expected", ErrUnderpriced, "got", err)
@@ -267,7 +267,7 @@ func TestTransactionQueue(t *testing.T) {
pool, key := setupTxPool()
defer pool.Stop()
- tx := transaction(0, big.NewInt(100), key)
+ tx := transaction(0, 100, key)
from, _ := deriveSender(tx)
pool.currentState.AddBalance(from, big.NewInt(1000))
pool.lockedReset(nil, nil)
@@ -278,7 +278,7 @@ func TestTransactionQueue(t *testing.T) {
t.Error("expected valid txs to be 1 is", len(pool.pending))
}
- tx = transaction(1, big.NewInt(100), key)
+ tx = transaction(1, 100, key)
from, _ = deriveSender(tx)
pool.currentState.SetNonce(from, 2)
pool.enqueueTx(tx.Hash(), tx)
@@ -294,9 +294,9 @@ func TestTransactionQueue(t *testing.T) {
pool, key = setupTxPool()
defer pool.Stop()
- tx1 := transaction(0, big.NewInt(100), key)
- tx2 := transaction(10, big.NewInt(100), key)
- tx3 := transaction(11, big.NewInt(100), key)
+ tx1 := transaction(0, 100, key)
+ tx2 := transaction(10, 100, key)
+ tx3 := transaction(11, 100, key)
from, _ = deriveSender(tx1)
pool.currentState.AddBalance(from, big.NewInt(1000))
pool.lockedReset(nil, nil)
@@ -321,7 +321,7 @@ func TestTransactionNegativeValue(t *testing.T) {
pool, key := setupTxPool()
defer pool.Stop()
- tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), big.NewInt(100), big.NewInt(1), nil), types.HomesteadSigner{}, key)
+ tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key)
from, _ := deriveSender(tx)
pool.currentState.AddBalance(from, big.NewInt(1))
if err := pool.AddRemote(tx); err != ErrNegativeValue {
@@ -341,12 +341,12 @@ func TestTransactionChainFork(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
statedb.AddBalance(addr, big.NewInt(100000000000000))
- pool.chain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)}
pool.lockedReset(nil, nil)
}
resetState()
- tx := transaction(0, big.NewInt(100000), key)
+ tx := transaction(0, 100000, key)
if _, err := pool.add(tx, false); err != nil {
t.Error("didn't expect error", err)
}
@@ -371,15 +371,15 @@ func TestTransactionDoubleNonce(t *testing.T) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
statedb.AddBalance(addr, big.NewInt(100000000000000))
- pool.chain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)}
pool.lockedReset(nil, nil)
}
resetState()
signer := types.HomesteadSigner{}
- tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(100000), big.NewInt(1), nil), signer, key)
- tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(2), nil), signer, key)
- tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(1), nil), signer, key)
+ tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 100000, big.NewInt(1), nil), signer, key)
+ tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(2), nil), signer, key)
+ tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(1), nil), signer, key)
// Add the first two transaction, ensure higher priced stays only
if replace, err := pool.add(tx1, false); err != nil || replace {
@@ -418,7 +418,7 @@ func TestTransactionMissingNonce(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey)
pool.currentState.AddBalance(addr, big.NewInt(100000000000000))
- tx := transaction(1, big.NewInt(100000), key)
+ tx := transaction(1, 100000, key)
if _, err := pool.add(tx, false); err != nil {
t.Error("didn't expect error", err)
}
@@ -445,7 +445,7 @@ func TestTransactionNonceRecovery(t *testing.T) {
pool.currentState.AddBalance(addr, big.NewInt(100000000000000))
pool.lockedReset(nil, nil)
- tx := transaction(n, big.NewInt(100000), key)
+ tx := transaction(n, 100000, key)
if err := pool.AddRemote(tx); err != nil {
t.Error(err)
}
@@ -466,17 +466,17 @@ func TestTransactionDropping(t *testing.T) {
pool, key := setupTxPool()
defer pool.Stop()
- account, _ := deriveSender(transaction(0, big.NewInt(0), key))
+ account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000))
// Add some pending and some queued transactions
var (
- tx0 = transaction(0, big.NewInt(100), key)
- tx1 = transaction(1, big.NewInt(200), key)
- tx2 = transaction(2, big.NewInt(300), key)
- tx10 = transaction(10, big.NewInt(100), key)
- tx11 = transaction(11, big.NewInt(200), key)
- tx12 = transaction(12, big.NewInt(300), key)
+ tx0 = transaction(0, 100, key)
+ tx1 = transaction(1, 200, key)
+ tx2 = transaction(2, 300, key)
+ tx10 = transaction(10, 100, key)
+ tx11 = transaction(11, 200, key)
+ tx12 = transaction(12, 300, key)
)
pool.promoteTx(account, tx0.Hash(), tx0)
pool.promoteTx(account, tx1.Hash(), tx1)
@@ -531,7 +531,7 @@ func TestTransactionDropping(t *testing.T) {
t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 4)
}
// Reduce the block gas limit, check that invalidated transactions are dropped
- pool.chain.(*testBlockChain).gasLimit = big.NewInt(100)
+ pool.chain.(*testBlockChain).gasLimit = 100
pool.lockedReset(nil, nil)
if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok {
@@ -561,7 +561,7 @@ func TestTransactionPostponing(t *testing.T) {
pool, key := setupTxPool()
defer pool.Stop()
- account, _ := deriveSender(transaction(0, big.NewInt(0), key))
+ account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000))
// Add a batch consecutive pending transactions for validation
@@ -569,9 +569,9 @@ func TestTransactionPostponing(t *testing.T) {
for i := 0; i < 100; i++ {
var tx *types.Transaction
if i%2 == 0 {
- tx = transaction(uint64(i), big.NewInt(100), key)
+ tx = transaction(uint64(i), 100, key)
} else {
- tx = transaction(uint64(i), big.NewInt(500), key)
+ tx = transaction(uint64(i), 500, key)
}
pool.promoteTx(account, tx.Hash(), tx)
txns = append(txns, tx)
@@ -638,7 +638,7 @@ func TestTransactionGapFilling(t *testing.T) {
pool, key := setupTxPool()
defer pool.Stop()
- account, _ := deriveSender(transaction(0, big.NewInt(0), key))
+ account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000000))
// Keep track of transaction events to ensure all executables get announced
@@ -647,10 +647,10 @@ func TestTransactionGapFilling(t *testing.T) {
defer sub.Unsubscribe()
// Create a pending and a queued transaction with a nonce-gap in between
- if err := pool.AddRemote(transaction(0, big.NewInt(100000), key)); err != nil {
+ if err := pool.AddRemote(transaction(0, 100000, key)); err != nil {
t.Fatalf("failed to add pending transaction: %v", err)
}
- if err := pool.AddRemote(transaction(2, big.NewInt(100000), key)); err != nil {
+ if err := pool.AddRemote(transaction(2, 100000, key)); err != nil {
t.Fatalf("failed to add queued transaction: %v", err)
}
pending, queued := pool.Stats()
@@ -667,7 +667,7 @@ func TestTransactionGapFilling(t *testing.T) {
t.Fatalf("pool internal state corrupted: %v", err)
}
// Fill the nonce gap and ensure all transactions become pending
- if err := pool.AddRemote(transaction(1, big.NewInt(100000), key)); err != nil {
+ if err := pool.AddRemote(transaction(1, 100000, key)); err != nil {
t.Fatalf("failed to add gapped transaction: %v", err)
}
pending, queued = pool.Stats()
@@ -694,12 +694,12 @@ func TestTransactionQueueAccountLimiting(t *testing.T) {
pool, key := setupTxPool()
defer pool.Stop()
- account, _ := deriveSender(transaction(0, big.NewInt(0), key))
+ account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000000))
// Keep queuing up transactions and make sure all above a limit are dropped
for i := uint64(1); i <= testTxPoolConfig.AccountQueue+5; i++ {
- if err := pool.AddRemote(transaction(i, big.NewInt(100000), key)); err != nil {
+ if err := pool.AddRemote(transaction(i, 100000, key)); err != nil {
t.Fatalf("tx %d: failed to add transaction: %v", i, err)
}
if len(pool.pending) != 0 {
@@ -738,7 +738,7 @@ func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) {
// Create the pool to test the limit enforcement with
db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
- blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig
config.NoLocals = nolocals
@@ -763,7 +763,7 @@ func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) {
key := keys[rand.Intn(len(keys)-1)] // skip adding transactions with the local account
addr := crypto.PubkeyToAddress(key.PublicKey)
- txs = append(txs, transaction(nonces[addr]+1, big.NewInt(100000), key))
+ txs = append(txs, transaction(nonces[addr]+1, 100000, key))
nonces[addr]++
}
// Import the batch and verify that limits have been enforced
@@ -782,7 +782,7 @@ func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) {
// Generate a batch of transactions from the local account and import them
txs = txs[:0]
for i := uint64(0); i < 3*config.GlobalQueue; i++ {
- txs = append(txs, transaction(i+1, big.NewInt(100000), local))
+ txs = append(txs, transaction(i+1, 100000, local))
}
pool.AddLocals(txs)
@@ -827,7 +827,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
// Create the pool to test the non-expiration enforcement
db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
- blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig
config.Lifetime = time.Second
@@ -844,10 +844,10 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000))
// Add the two transactions and ensure they both are queued up
- if err := pool.AddLocal(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), local)); err != nil {
+ if err := pool.AddLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil {
t.Fatalf("failed to add local transaction: %v", err)
}
- if err := pool.AddRemote(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), remote)); err != nil {
+ if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(1), remote)); err != nil {
t.Fatalf("failed to add remote transaction: %v", err)
}
pending, queued := pool.Stats()
@@ -891,7 +891,7 @@ func TestTransactionPendingLimiting(t *testing.T) {
pool, key := setupTxPool()
defer pool.Stop()
- account, _ := deriveSender(transaction(0, big.NewInt(0), key))
+ account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000000))
// Keep track of transaction events to ensure all executables get announced
@@ -901,7 +901,7 @@ func TestTransactionPendingLimiting(t *testing.T) {
// Keep queuing up transactions and make sure all above a limit are dropped
for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ {
- if err := pool.AddRemote(transaction(i, big.NewInt(100000), key)); err != nil {
+ if err := pool.AddRemote(transaction(i, 100000, key)); err != nil {
t.Fatalf("tx %d: failed to add transaction: %v", i, err)
}
if pool.pending[account].Len() != int(i)+1 {
@@ -934,11 +934,11 @@ func testTransactionLimitingEquivalency(t *testing.T, origin uint64) {
pool1, key1 := setupTxPool()
defer pool1.Stop()
- account1, _ := deriveSender(transaction(0, big.NewInt(0), key1))
+ account1, _ := deriveSender(transaction(0, 0, key1))
pool1.currentState.AddBalance(account1, big.NewInt(1000000))
for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ {
- if err := pool1.AddRemote(transaction(origin+i, big.NewInt(100000), key1)); err != nil {
+ if err := pool1.AddRemote(transaction(origin+i, 100000, key1)); err != nil {
t.Fatalf("tx %d: failed to add transaction: %v", i, err)
}
}
@@ -946,12 +946,12 @@ func testTransactionLimitingEquivalency(t *testing.T, origin uint64) {
pool2, key2 := setupTxPool()
defer pool2.Stop()
- account2, _ := deriveSender(transaction(0, big.NewInt(0), key2))
+ account2, _ := deriveSender(transaction(0, 0, key2))
pool2.currentState.AddBalance(account2, big.NewInt(1000000))
txns := []*types.Transaction{}
for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ {
- txns = append(txns, transaction(origin+i, big.NewInt(100000), key2))
+ txns = append(txns, transaction(origin+i, 100000, key2))
}
pool2.AddRemotes(txns)
@@ -982,7 +982,7 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) {
// Create the pool to test the limit enforcement with
db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
- blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig
config.GlobalSlots = config.AccountSlots * 10
@@ -1003,7 +1003,7 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) {
for _, key := range keys {
addr := crypto.PubkeyToAddress(key.PublicKey)
for j := 0; j < int(config.GlobalSlots)/len(keys)*2; j++ {
- txs = append(txs, transaction(nonces[addr], big.NewInt(100000), key))
+ txs = append(txs, transaction(nonces[addr], 100000, key))
nonces[addr]++
}
}
@@ -1029,7 +1029,7 @@ func TestTransactionCapClearsFromAll(t *testing.T) {
// Create the pool to test the limit enforcement with
db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
- blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig
config.AccountSlots = 2
@@ -1046,7 +1046,7 @@ func TestTransactionCapClearsFromAll(t *testing.T) {
txs := types.Transactions{}
for j := 0; j < int(config.GlobalSlots)*2; j++ {
- txs = append(txs, transaction(uint64(j), big.NewInt(100000), key))
+ txs = append(txs, transaction(uint64(j), 100000, key))
}
// Import the batch and verify that limits have been enforced
pool.AddRemotes(txs)
@@ -1064,7 +1064,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) {
// Create the pool to test the limit enforcement with
db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
- blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig
config.GlobalSlots = 0
@@ -1085,7 +1085,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) {
for _, key := range keys {
addr := crypto.PubkeyToAddress(key.PublicKey)
for j := 0; j < int(config.AccountSlots)*2; j++ {
- txs = append(txs, transaction(nonces[addr], big.NewInt(100000), key))
+ txs = append(txs, transaction(nonces[addr], 100000, key))
nonces[addr]++
}
}
@@ -1113,7 +1113,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
// Create the pool to test the pricing enforcement with
db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
- blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
defer pool.Stop()
@@ -1132,15 +1132,15 @@ func TestTransactionPoolRepricing(t *testing.T) {
// Generate and queue a batch of transactions, both pending and queued
txs := types.Transactions{}
- txs = append(txs, pricedTransaction(0, big.NewInt(100000), big.NewInt(2), keys[0]))
- txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[0]))
- txs = append(txs, pricedTransaction(2, big.NewInt(100000), big.NewInt(2), keys[0]))
+ txs = append(txs, pricedTransaction(0, 100000, big.NewInt(2), keys[0]))
+ txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[0]))
+ txs = append(txs, pricedTransaction(2, 100000, big.NewInt(2), keys[0]))
- txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(2), keys[1]))
- txs = append(txs, pricedTransaction(2, big.NewInt(100000), big.NewInt(1), keys[1]))
- txs = append(txs, pricedTransaction(3, big.NewInt(100000), big.NewInt(2), keys[1]))
+ txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[1]))
+ txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[1]))
+ txs = append(txs, pricedTransaction(3, 100000, big.NewInt(2), keys[1]))
- ltx := pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[2])
+ ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[2])
// Import the batch and that both pending and queued transactions match up
pool.AddRemotes(txs)
@@ -1176,10 +1176,10 @@ func TestTransactionPoolRepricing(t *testing.T) {
t.Fatalf("pool internal state corrupted: %v", err)
}
// Check that we can't add the old transactions back
- if err := pool.AddRemote(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[0])); err != ErrUnderpriced {
+ if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(1), keys[0])); err != ErrUnderpriced {
t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced)
}
- if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(1), keys[1])); err != ErrUnderpriced {
+ if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced {
t.Fatalf("adding underpriced queued transaction error mismatch: have %v, want %v", err, ErrUnderpriced)
}
if err := validateEvents(events, 0); err != nil {
@@ -1189,7 +1189,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
t.Fatalf("pool internal state corrupted: %v", err)
}
// However we can add local underpriced transactions
- tx := pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[2])
+ tx := pricedTransaction(1, 100000, big.NewInt(1), keys[2])
if err := pool.AddLocal(tx); err != nil {
t.Fatalf("failed to add underpriced local transaction: %v", err)
}
@@ -1212,7 +1212,7 @@ func TestTransactionPoolRepricingKeepsLocals(t *testing.T) {
// Create the pool to test the pricing enforcement with
db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
- blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
defer pool.Stop()
@@ -1226,12 +1226,12 @@ func TestTransactionPoolRepricingKeepsLocals(t *testing.T) {
// Create transaction (both pending and queued) with a linearly growing gasprice
for i := uint64(0); i < 500; i++ {
// Add pending
- p_tx := pricedTransaction(i, big.NewInt(100000), big.NewInt(int64(i)), keys[2])
+ p_tx := pricedTransaction(i, 100000, big.NewInt(int64(i)), keys[2])
if err := pool.AddLocal(p_tx); err != nil {
t.Fatal(err)
}
// Add queued
- q_tx := pricedTransaction(i+501, big.NewInt(100000), big.NewInt(int64(i)), keys[2])
+ q_tx := pricedTransaction(i+501, 100000, big.NewInt(int64(i)), keys[2])
if err := pool.AddLocal(q_tx); err != nil {
t.Fatal(err)
}
@@ -1275,7 +1275,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
// Create the pool to test the pricing enforcement with
db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
- blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig
config.GlobalSlots = 2
@@ -1298,12 +1298,12 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
// Generate and queue a batch of transactions, both pending and queued
txs := types.Transactions{}
- txs = append(txs, pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[0]))
- txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(2), keys[0]))
+ txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0]))
+ txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[0]))
- txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[1]))
+ txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[1]))
- ltx := pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[2])
+ ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[2])
// Import the batch and that both pending and queued transactions match up
pool.AddRemotes(txs)
@@ -1323,17 +1323,17 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
t.Fatalf("pool internal state corrupted: %v", err)
}
// Ensure that adding an underpriced transaction on block limit fails
- if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[1])); err != ErrUnderpriced {
+ if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced {
t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced)
}
// Ensure that adding high priced transactions drops cheap ones, but not own
- if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(3), keys[1])); err != nil {
+ if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(3), keys[1])); err != nil {
t.Fatalf("failed to add well priced transaction: %v", err)
}
- if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(4), keys[1])); err != nil {
+ if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(4), keys[1])); err != nil {
t.Fatalf("failed to add well priced transaction: %v", err)
}
- if err := pool.AddRemote(pricedTransaction(3, big.NewInt(100000), big.NewInt(5), keys[1])); err != nil {
+ if err := pool.AddRemote(pricedTransaction(3, 100000, big.NewInt(5), keys[1])); err != nil {
t.Fatalf("failed to add well priced transaction: %v", err)
}
pending, queued = pool.Stats()
@@ -1350,7 +1350,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
t.Fatalf("pool internal state corrupted: %v", err)
}
// Ensure that adding local transactions can push out even higher priced ones
- tx := pricedTransaction(1, big.NewInt(100000), big.NewInt(0), keys[2])
+ tx := pricedTransaction(1, 100000, big.NewInt(0), keys[2])
if err := pool.AddLocal(tx); err != nil {
t.Fatalf("failed to add underpriced local transaction: %v", err)
}
@@ -1377,7 +1377,7 @@ func TestTransactionReplacement(t *testing.T) {
// Create the pool to test the pricing enforcement with
db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
- blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
defer pool.Stop()
@@ -1395,49 +1395,49 @@ func TestTransactionReplacement(t *testing.T) {
price := int64(100)
threshold := (price * (100 + int64(testTxPoolConfig.PriceBump))) / 100
- if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), key)); err != nil {
+ if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), key)); err != nil {
t.Fatalf("failed to add original cheap pending transaction: %v", err)
}
- if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100001), big.NewInt(1), key)); err != ErrReplaceUnderpriced {
+ if err := pool.AddRemote(pricedTransaction(0, 100001, big.NewInt(1), key)); err != ErrReplaceUnderpriced {
t.Fatalf("original cheap pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
}
- if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(2), key)); err != nil {
+ if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(2), key)); err != nil {
t.Fatalf("failed to replace original cheap pending transaction: %v", err)
}
if err := validateEvents(events, 2); err != nil {
t.Fatalf("cheap replacement event firing failed: %v", err)
}
- if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(price), key)); err != nil {
+ if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(price), key)); err != nil {
t.Fatalf("failed to add original proper pending transaction: %v", err)
}
- if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100001), big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced {
+ if err := pool.AddRemote(pricedTransaction(0, 100001, big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced {
t.Fatalf("original proper pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
}
- if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(threshold), key)); err != nil {
+ if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(threshold), key)); err != nil {
t.Fatalf("failed to replace original proper pending transaction: %v", err)
}
if err := validateEvents(events, 2); err != nil {
t.Fatalf("proper replacement event firing failed: %v", err)
}
// Add queued transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too)
- if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(1), key)); err != nil {
+ if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(1), key)); err != nil {
t.Fatalf("failed to add original cheap queued transaction: %v", err)
}
- if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100001), big.NewInt(1), key)); err != ErrReplaceUnderpriced {
+ if err := pool.AddRemote(pricedTransaction(2, 100001, big.NewInt(1), key)); err != ErrReplaceUnderpriced {
t.Fatalf("original cheap queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
}
- if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(2), key)); err != nil {
+ if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(2), key)); err != nil {
t.Fatalf("failed to replace original cheap queued transaction: %v", err)
}
- if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(price), key)); err != nil {
+ if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(price), key)); err != nil {
t.Fatalf("failed to add original proper queued transaction: %v", err)
}
- if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100001), big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced {
+ if err := pool.AddRemote(pricedTransaction(2, 100001, big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced {
t.Fatalf("original proper queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
}
- if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(threshold), key)); err != nil {
+ if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(threshold), key)); err != nil {
t.Fatalf("failed to replace original proper queued transaction: %v", err)
}
@@ -1472,7 +1472,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
// Create the original pool to inject transaction into the journal
db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
- blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig
config.NoLocals = nolocals
@@ -1489,16 +1489,16 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000))
// Add three local and a remote transactions and ensure they are queued up
- if err := pool.AddLocal(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), local)); err != nil {
+ if err := pool.AddLocal(pricedTransaction(0, 100000, big.NewInt(1), local)); err != nil {
t.Fatalf("failed to add local transaction: %v", err)
}
- if err := pool.AddLocal(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), local)); err != nil {
+ if err := pool.AddLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil {
t.Fatalf("failed to add local transaction: %v", err)
}
- if err := pool.AddLocal(pricedTransaction(2, big.NewInt(100000), big.NewInt(1), local)); err != nil {
+ if err := pool.AddLocal(pricedTransaction(2, 100000, big.NewInt(1), local)); err != nil {
t.Fatalf("failed to add local transaction: %v", err)
}
- if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), remote)); err != nil {
+ if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), remote)); err != nil {
t.Fatalf("failed to add remote transaction: %v", err)
}
pending, queued := pool.Stats()
@@ -1514,7 +1514,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
// Terminate the old pool, bump the local nonce, create a new pool and ensure relevant transaction survive
pool.Stop()
statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1)
- blockchain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ blockchain = &testBlockChain{statedb, 1000000, new(event.Feed)}
pool = NewTxPool(config, params.TestChainConfig, blockchain)
@@ -1541,7 +1541,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
pool.Stop()
statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1)
- blockchain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ blockchain = &testBlockChain{statedb, 1000000, new(event.Feed)}
pool = NewTxPool(config, params.TestChainConfig, blockchain)
pending, queued = pool.Stats()
@@ -1571,7 +1571,7 @@ func TestTransactionStatusCheck(t *testing.T) {
// Create the pool to test the status retrievals with
db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
- blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
+ blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
defer pool.Stop()
@@ -1585,10 +1585,10 @@ func TestTransactionStatusCheck(t *testing.T) {
// Generate and queue a batch of transactions, both pending and queued
txs := types.Transactions{}
- txs = append(txs, pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[0])) // Pending only
- txs = append(txs, pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[1])) // Pending and queued
- txs = append(txs, pricedTransaction(2, big.NewInt(100000), big.NewInt(1), keys[1]))
- txs = append(txs, pricedTransaction(2, big.NewInt(100000), big.NewInt(1), keys[2])) // Queued only
+ txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0])) // Pending only
+ txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[1])) // Pending and queued
+ txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[1]))
+ txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2])) // Queued only
// Import the transaction and ensure they are correctly added
pool.AddRemotes(txs)
@@ -1631,11 +1631,11 @@ func benchmarkPendingDemotion(b *testing.B, size int) {
pool, key := setupTxPool()
defer pool.Stop()
- account, _ := deriveSender(transaction(0, big.NewInt(0), key))
+ account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000000))
for i := 0; i < size; i++ {
- tx := transaction(uint64(i), big.NewInt(100000), key)
+ tx := transaction(uint64(i), 100000, key)
pool.promoteTx(account, tx.Hash(), tx)
}
// Benchmark the speed of pool validation
@@ -1656,11 +1656,11 @@ func benchmarkFuturePromotion(b *testing.B, size int) {
pool, key := setupTxPool()
defer pool.Stop()
- account, _ := deriveSender(transaction(0, big.NewInt(0), key))
+ account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000000))
for i := 0; i < size; i++ {
- tx := transaction(uint64(1+i), big.NewInt(100000), key)
+ tx := transaction(uint64(1+i), 100000, key)
pool.enqueueTx(tx.Hash(), tx)
}
// Benchmark the speed of pool validation
@@ -1676,12 +1676,12 @@ func BenchmarkPoolInsert(b *testing.B) {
pool, key := setupTxPool()
defer pool.Stop()
- account, _ := deriveSender(transaction(0, big.NewInt(0), key))
+ account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000000))
txs := make(types.Transactions, b.N)
for i := 0; i < b.N; i++ {
- txs[i] = transaction(uint64(i), big.NewInt(100000), key)
+ txs[i] = transaction(uint64(i), 100000, key)
}
// Benchmark importing the transactions into the queue
b.ResetTimer()
@@ -1700,14 +1700,14 @@ func benchmarkPoolBatchInsert(b *testing.B, size int) {
pool, key := setupTxPool()
defer pool.Stop()
- account, _ := deriveSender(transaction(0, big.NewInt(0), key))
+ account, _ := deriveSender(transaction(0, 0, key))
pool.currentState.AddBalance(account, big.NewInt(1000000))
batches := make([]types.Transactions, b.N)
for i := 0; i < b.N; i++ {
batches[i] = make(types.Transactions, size)
for j := 0; j < size; j++ {
- batches[i][j] = transaction(uint64(size*i+j), big.NewInt(100000), key)
+ batches[i][j] = transaction(uint64(size*i+j), 100000, key)
}
}
// Benchmark importing the transactions into the queue
diff --git a/core/types.go b/core/types.go
index 1cfbbab29..d0bbaf0aa 100644
--- a/core/types.go
+++ b/core/types.go
@@ -17,8 +17,6 @@
package core
import (
- "math/big"
-
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
@@ -34,7 +32,7 @@ type Validator interface {
// ValidateState validates the given statedb and optionally the receipts and
// gas used.
- ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas *big.Int) error
+ ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error
}
// Processor is an interface for processing blocks using a given initial state.
@@ -44,5 +42,5 @@ type Validator interface {
// of gas used in the process and return an error if any of the internal rules
// failed.
type Processor interface {
- Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *big.Int, error)
+ Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error)
}
diff --git a/core/types/block.go b/core/types/block.go
index 1d00d9f93..92b868d9d 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -25,6 +25,7 @@ import (
"sort"
"sync/atomic"
"time"
+ "unsafe"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
@@ -77,8 +78,8 @@ type Header struct {
Bloom Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *big.Int `json:"difficulty" gencodec:"required"`
Number *big.Int `json:"number" gencodec:"required"`
- GasLimit *big.Int `json:"gasLimit" gencodec:"required"`
- GasUsed *big.Int `json:"gasUsed" gencodec:"required"`
+ GasLimit uint64 `json:"gasLimit" gencodec:"required"`
+ GasUsed uint64 `json:"gasUsed" gencodec:"required"`
Time *big.Int `json:"timestamp" gencodec:"required"`
Extra []byte `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash" gencodec:"required"`
@@ -89,8 +90,8 @@ type Header struct {
type headerMarshaling struct {
Difficulty *hexutil.Big
Number *hexutil.Big
- GasLimit *hexutil.Big
- GasUsed *hexutil.Big
+ GasLimit hexutil.Uint64
+ GasUsed hexutil.Uint64
Time *hexutil.Big
Extra hexutil.Bytes
Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON
@@ -121,6 +122,12 @@ func (h *Header) HashNoNonce() common.Hash {
})
}
+// Size returns the approximate memory used by all internal contents. It is used
+// to approximate and limit the memory consumption of various caches.
+func (h *Header) Size() common.StorageSize {
+ return common.StorageSize(unsafe.Sizeof(*h)) + common.StorageSize(len(h.Extra)+(h.Difficulty.BitLen()+h.Number.BitLen()+h.Time.BitLen())/8)
+}
+
func rlpHash(x interface{}) (h common.Hash) {
hw := sha3.NewKeccak256()
rlp.Encode(hw, x)
@@ -243,12 +250,6 @@ func CopyHeader(h *Header) *Header {
if cpy.Number = new(big.Int); h.Number != nil {
cpy.Number.Set(h.Number)
}
- if cpy.GasLimit = new(big.Int); h.GasLimit != nil {
- cpy.GasLimit.Set(h.GasLimit)
- }
- if cpy.GasUsed = new(big.Int); h.GasUsed != nil {
- cpy.GasUsed.Set(h.GasUsed)
- }
if len(h.Extra) > 0 {
cpy.Extra = make([]byte, len(h.Extra))
copy(cpy.Extra, h.Extra)
@@ -302,8 +303,8 @@ func (b *Block) Transaction(hash common.Hash) *Transaction {
}
func (b *Block) Number() *big.Int { return new(big.Int).Set(b.header.Number) }
-func (b *Block) GasLimit() *big.Int { return new(big.Int).Set(b.header.GasLimit) }
-func (b *Block) GasUsed() *big.Int { return new(big.Int).Set(b.header.GasUsed) }
+func (b *Block) GasLimit() uint64 { return b.header.GasLimit }
+func (b *Block) GasUsed() uint64 { return b.header.GasUsed }
func (b *Block) Difficulty() *big.Int { return new(big.Int).Set(b.header.Difficulty) }
func (b *Block) Time() *big.Int { return new(big.Int).Set(b.header.Time) }
@@ -328,6 +329,8 @@ func (b *Block) HashNoNonce() common.Hash {
return b.header.HashNoNonce()
}
+// Size returns the true RLP encoded storage size of the block, either by encoding
+// and returning it, or returning a previsouly cached value.
func (b *Block) Size() common.StorageSize {
if size := b.size.Load(); size != nil {
return size.(common.StorageSize)
diff --git a/core/types/block_test.go b/core/types/block_test.go
index 93435ca00..a35fbc25b 100644
--- a/core/types/block_test.go
+++ b/core/types/block_test.go
@@ -41,8 +41,8 @@ func TestBlockEncoding(t *testing.T) {
}
}
check("Difficulty", block.Difficulty(), big.NewInt(131072))
- check("GasLimit", block.GasLimit(), big.NewInt(3141592))
- check("GasUsed", block.GasUsed(), big.NewInt(21000))
+ check("GasLimit", block.GasLimit(), uint64(3141592))
+ check("GasUsed", block.GasUsed(), uint64(21000))
check("Coinbase", block.Coinbase(), common.HexToAddress("8888f1f195afa192cfee860698584c030f4c9db1"))
check("MixDigest", block.MixDigest(), common.HexToHash("bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498"))
check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017"))
@@ -51,7 +51,7 @@ func TestBlockEncoding(t *testing.T) {
check("Time", block.Time(), big.NewInt(1426516743))
check("Size", block.Size(), common.StorageSize(len(blockEnc)))
- tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), big.NewInt(50000), big.NewInt(10), nil)
+ tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), 50000, big.NewInt(10), nil)
tx1, _ = tx1.WithSignature(HomesteadSigner{}, common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100"))
fmt.Println(block.Transactions()[0].Hash())
diff --git a/core/types/gen_header_json.go b/core/types/gen_header_json.go
index bcff7a940..1b92cd9cf 100644
--- a/core/types/gen_header_json.go
+++ b/core/types/gen_header_json.go
@@ -11,6 +11,8 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
)
+var _ = (*headerMarshaling)(nil)
+
func (h Header) MarshalJSON() ([]byte, error) {
type Header struct {
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
@@ -22,8 +24,8 @@ func (h Header) MarshalJSON() ([]byte, error) {
Bloom Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
Number *hexutil.Big `json:"number" gencodec:"required"`
- GasLimit *hexutil.Big `json:"gasLimit" gencodec:"required"`
- GasUsed *hexutil.Big `json:"gasUsed" gencodec:"required"`
+ GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
+ GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
Time *hexutil.Big `json:"timestamp" gencodec:"required"`
Extra hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash" gencodec:"required"`
@@ -40,8 +42,8 @@ func (h Header) MarshalJSON() ([]byte, error) {
enc.Bloom = h.Bloom
enc.Difficulty = (*hexutil.Big)(h.Difficulty)
enc.Number = (*hexutil.Big)(h.Number)
- enc.GasLimit = (*hexutil.Big)(h.GasLimit)
- enc.GasUsed = (*hexutil.Big)(h.GasUsed)
+ enc.GasLimit = hexutil.Uint64(h.GasLimit)
+ enc.GasUsed = hexutil.Uint64(h.GasUsed)
enc.Time = (*hexutil.Big)(h.Time)
enc.Extra = h.Extra
enc.MixDigest = h.MixDigest
@@ -61,10 +63,10 @@ func (h *Header) UnmarshalJSON(input []byte) error {
Bloom *Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
Number *hexutil.Big `json:"number" gencodec:"required"`
- GasLimit *hexutil.Big `json:"gasLimit" gencodec:"required"`
- GasUsed *hexutil.Big `json:"gasUsed" gencodec:"required"`
+ GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
+ GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
Time *hexutil.Big `json:"timestamp" gencodec:"required"`
- Extra hexutil.Bytes `json:"extraData" gencodec:"required"`
+ Extra *hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest *common.Hash `json:"mixHash" gencodec:"required"`
Nonce *BlockNonce `json:"nonce" gencodec:"required"`
}
@@ -111,11 +113,11 @@ func (h *Header) UnmarshalJSON(input []byte) error {
if dec.GasLimit == nil {
return errors.New("missing required field 'gasLimit' for Header")
}
- h.GasLimit = (*big.Int)(dec.GasLimit)
+ h.GasLimit = uint64(*dec.GasLimit)
if dec.GasUsed == nil {
return errors.New("missing required field 'gasUsed' for Header")
}
- h.GasUsed = (*big.Int)(dec.GasUsed)
+ h.GasUsed = uint64(*dec.GasUsed)
if dec.Time == nil {
return errors.New("missing required field 'timestamp' for Header")
}
@@ -123,7 +125,7 @@ func (h *Header) UnmarshalJSON(input []byte) error {
if dec.Extra == nil {
return errors.New("missing required field 'extraData' for Header")
}
- h.Extra = dec.Extra
+ h.Extra = *dec.Extra
if dec.MixDigest == nil {
return errors.New("missing required field 'mixHash' for Header")
}
diff --git a/core/types/gen_log_json.go b/core/types/gen_log_json.go
index 92c699c2a..1b5ae3c65 100644
--- a/core/types/gen_log_json.go
+++ b/core/types/gen_log_json.go
@@ -10,6 +10,8 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
)
+var _ = (*logMarshaling)(nil)
+
func (l Log) MarshalJSON() ([]byte, error) {
type Log struct {
Address common.Address `json:"address" gencodec:"required"`
@@ -39,7 +41,7 @@ func (l *Log) UnmarshalJSON(input []byte) error {
type Log struct {
Address *common.Address `json:"address" gencodec:"required"`
Topics []common.Hash `json:"topics" gencodec:"required"`
- Data hexutil.Bytes `json:"data" gencodec:"required"`
+ Data *hexutil.Bytes `json:"data" gencodec:"required"`
BlockNumber *hexutil.Uint64 `json:"blockNumber"`
TxHash *common.Hash `json:"transactionHash" gencodec:"required"`
TxIndex *hexutil.Uint `json:"transactionIndex" gencodec:"required"`
@@ -62,7 +64,7 @@ func (l *Log) UnmarshalJSON(input []byte) error {
if dec.Data == nil {
return errors.New("missing required field 'data' for Log")
}
- l.Data = dec.Data
+ l.Data = *dec.Data
if dec.BlockNumber != nil {
l.BlockNumber = uint64(*dec.BlockNumber)
}
diff --git a/core/types/gen_receipt_json.go b/core/types/gen_receipt_json.go
index b95d99c95..c297adebb 100644
--- a/core/types/gen_receipt_json.go
+++ b/core/types/gen_receipt_json.go
@@ -5,52 +5,53 @@ package types
import (
"encoding/json"
"errors"
- "math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
+var _ = (*receiptMarshaling)(nil)
+
func (r Receipt) MarshalJSON() ([]byte, error) {
type Receipt struct {
PostState hexutil.Bytes `json:"root"`
Status hexutil.Uint `json:"status"`
- CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed" gencodec:"required"`
+ CumulativeGasUsed hexutil.Uint64 `json:"cumulativeGasUsed" gencodec:"required"`
Bloom Bloom `json:"logsBloom" gencodec:"required"`
Logs []*Log `json:"logs" gencodec:"required"`
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
ContractAddress common.Address `json:"contractAddress"`
- GasUsed *hexutil.Big `json:"gasUsed" gencodec:"required"`
+ GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
}
var enc Receipt
enc.PostState = r.PostState
enc.Status = hexutil.Uint(r.Status)
- enc.CumulativeGasUsed = (*hexutil.Big)(r.CumulativeGasUsed)
+ enc.CumulativeGasUsed = hexutil.Uint64(r.CumulativeGasUsed)
enc.Bloom = r.Bloom
enc.Logs = r.Logs
enc.TxHash = r.TxHash
enc.ContractAddress = r.ContractAddress
- enc.GasUsed = (*hexutil.Big)(r.GasUsed)
+ enc.GasUsed = hexutil.Uint64(r.GasUsed)
return json.Marshal(&enc)
}
func (r *Receipt) UnmarshalJSON(input []byte) error {
type Receipt struct {
- PostState hexutil.Bytes `json:"root"`
+ PostState *hexutil.Bytes `json:"root"`
Status *hexutil.Uint `json:"status"`
- CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed" gencodec:"required"`
+ CumulativeGasUsed *hexutil.Uint64 `json:"cumulativeGasUsed" gencodec:"required"`
Bloom *Bloom `json:"logsBloom" gencodec:"required"`
Logs []*Log `json:"logs" gencodec:"required"`
TxHash *common.Hash `json:"transactionHash" gencodec:"required"`
ContractAddress *common.Address `json:"contractAddress"`
- GasUsed *hexutil.Big `json:"gasUsed" gencodec:"required"`
+ GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
}
var dec Receipt
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.PostState != nil {
- r.PostState = dec.PostState
+ r.PostState = *dec.PostState
}
if dec.Status != nil {
r.Status = uint(*dec.Status)
@@ -58,7 +59,7 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
if dec.CumulativeGasUsed == nil {
return errors.New("missing required field 'cumulativeGasUsed' for Receipt")
}
- r.CumulativeGasUsed = (*big.Int)(dec.CumulativeGasUsed)
+ r.CumulativeGasUsed = uint64(*dec.CumulativeGasUsed)
if dec.Bloom == nil {
return errors.New("missing required field 'logsBloom' for Receipt")
}
@@ -77,6 +78,6 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
if dec.GasUsed == nil {
return errors.New("missing required field 'gasUsed' for Receipt")
}
- r.GasUsed = (*big.Int)(dec.GasUsed)
+ r.GasUsed = uint64(*dec.GasUsed)
return nil
}
diff --git a/core/types/gen_tx_json.go b/core/types/gen_tx_json.go
index 4fb658e0d..c27da6709 100644
--- a/core/types/gen_tx_json.go
+++ b/core/types/gen_tx_json.go
@@ -11,11 +11,13 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
)
+var _ = (*txdataMarshaling)(nil)
+
func (t txdata) MarshalJSON() ([]byte, error) {
type txdata struct {
AccountNonce hexutil.Uint64 `json:"nonce" gencodec:"required"`
Price *hexutil.Big `json:"gasPrice" gencodec:"required"`
- GasLimit *hexutil.Big `json:"gas" gencodec:"required"`
+ GasLimit hexutil.Uint64 `json:"gas" gencodec:"required"`
Recipient *common.Address `json:"to" rlp:"nil"`
Amount *hexutil.Big `json:"value" gencodec:"required"`
Payload hexutil.Bytes `json:"input" gencodec:"required"`
@@ -27,7 +29,7 @@ func (t txdata) MarshalJSON() ([]byte, error) {
var enc txdata
enc.AccountNonce = hexutil.Uint64(t.AccountNonce)
enc.Price = (*hexutil.Big)(t.Price)
- enc.GasLimit = (*hexutil.Big)(t.GasLimit)
+ enc.GasLimit = hexutil.Uint64(t.GasLimit)
enc.Recipient = t.Recipient
enc.Amount = (*hexutil.Big)(t.Amount)
enc.Payload = t.Payload
@@ -42,10 +44,10 @@ func (t *txdata) UnmarshalJSON(input []byte) error {
type txdata struct {
AccountNonce *hexutil.Uint64 `json:"nonce" gencodec:"required"`
Price *hexutil.Big `json:"gasPrice" gencodec:"required"`
- GasLimit *hexutil.Big `json:"gas" gencodec:"required"`
+ GasLimit *hexutil.Uint64 `json:"gas" gencodec:"required"`
Recipient *common.Address `json:"to" rlp:"nil"`
Amount *hexutil.Big `json:"value" gencodec:"required"`
- Payload hexutil.Bytes `json:"input" gencodec:"required"`
+ Payload *hexutil.Bytes `json:"input" gencodec:"required"`
V *hexutil.Big `json:"v" gencodec:"required"`
R *hexutil.Big `json:"r" gencodec:"required"`
S *hexutil.Big `json:"s" gencodec:"required"`
@@ -66,7 +68,7 @@ func (t *txdata) UnmarshalJSON(input []byte) error {
if dec.GasLimit == nil {
return errors.New("missing required field 'gas' for txdata")
}
- t.GasLimit = (*big.Int)(dec.GasLimit)
+ t.GasLimit = uint64(*dec.GasLimit)
if dec.Recipient != nil {
t.Recipient = dec.Recipient
}
@@ -77,7 +79,7 @@ func (t *txdata) UnmarshalJSON(input []byte) error {
if dec.Payload == nil {
return errors.New("missing required field 'input' for txdata")
}
- t.Payload = dec.Payload
+ t.Payload = *dec.Payload
if dec.V == nil {
return errors.New("missing required field 'v' for txdata")
}
diff --git a/core/types/receipt.go b/core/types/receipt.go
index bc3c996b4..f945f6f6a 100644
--- a/core/types/receipt.go
+++ b/core/types/receipt.go
@@ -20,7 +20,7 @@ import (
"bytes"
"fmt"
"io"
- "math/big"
+ "unsafe"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
@@ -45,46 +45,46 @@ const (
// Receipt represents the results of a transaction.
type Receipt struct {
// Consensus fields
- PostState []byte `json:"root"`
- Status uint `json:"status"`
- CumulativeGasUsed *big.Int `json:"cumulativeGasUsed" gencodec:"required"`
- Bloom Bloom `json:"logsBloom" gencodec:"required"`
- Logs []*Log `json:"logs" gencodec:"required"`
+ PostState []byte `json:"root"`
+ Status uint `json:"status"`
+ CumulativeGasUsed uint64 `json:"cumulativeGasUsed" gencodec:"required"`
+ Bloom Bloom `json:"logsBloom" gencodec:"required"`
+ Logs []*Log `json:"logs" gencodec:"required"`
// Implementation fields (don't reorder!)
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
ContractAddress common.Address `json:"contractAddress"`
- GasUsed *big.Int `json:"gasUsed" gencodec:"required"`
+ GasUsed uint64 `json:"gasUsed" gencodec:"required"`
}
type receiptMarshaling struct {
PostState hexutil.Bytes
Status hexutil.Uint
- CumulativeGasUsed *hexutil.Big
- GasUsed *hexutil.Big
+ CumulativeGasUsed hexutil.Uint64
+ GasUsed hexutil.Uint64
}
// receiptRLP is the consensus encoding of a receipt.
type receiptRLP struct {
PostStateOrStatus []byte
- CumulativeGasUsed *big.Int
+ CumulativeGasUsed uint64
Bloom Bloom
Logs []*Log
}
type receiptStorageRLP struct {
PostStateOrStatus []byte
- CumulativeGasUsed *big.Int
+ CumulativeGasUsed uint64
Bloom Bloom
TxHash common.Hash
ContractAddress common.Address
Logs []*LogForStorage
- GasUsed *big.Int
+ GasUsed uint64
}
// NewReceipt creates a barebone transaction receipt, copying the init fields.
-func NewReceipt(root []byte, failed bool, cumulativeGasUsed *big.Int) *Receipt {
- r := &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: new(big.Int).Set(cumulativeGasUsed)}
+func NewReceipt(root []byte, failed bool, cumulativeGasUsed uint64) *Receipt {
+ r := &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: cumulativeGasUsed}
if failed {
r.Status = ReceiptStatusFailed
} else {
@@ -137,6 +137,18 @@ func (r *Receipt) statusEncoding() []byte {
return r.PostState
}
+// Size returns the approximate memory used by all internal contents. It is used
+// to approximate and limit the memory consumption of various caches.
+func (r *Receipt) Size() common.StorageSize {
+ size := common.StorageSize(unsafe.Sizeof(*r)) + common.StorageSize(len(r.PostState))
+
+ size += common.StorageSize(len(r.Logs)) * common.StorageSize(unsafe.Sizeof(Log{}))
+ for _, log := range r.Logs {
+ size += common.StorageSize(len(log.Topics)*common.HashLength + len(log.Data))
+ }
+ return size
+}
+
// String implements the Stringer interface.
func (r *Receipt) String() string {
if len(r.PostState) == 0 {
diff --git a/core/types/transaction.go b/core/types/transaction.go
index ee4140ce4..5660582ba 100644
--- a/core/types/transaction.go
+++ b/core/types/transaction.go
@@ -57,7 +57,7 @@ type Transaction struct {
type txdata struct {
AccountNonce uint64 `json:"nonce" gencodec:"required"`
Price *big.Int `json:"gasPrice" gencodec:"required"`
- GasLimit *big.Int `json:"gas" gencodec:"required"`
+ GasLimit uint64 `json:"gas" gencodec:"required"`
Recipient *common.Address `json:"to" rlp:"nil"` // nil means contract creation
Amount *big.Int `json:"value" gencodec:"required"`
Payload []byte `json:"input" gencodec:"required"`
@@ -74,7 +74,7 @@ type txdata struct {
type txdataMarshaling struct {
AccountNonce hexutil.Uint64
Price *hexutil.Big
- GasLimit *hexutil.Big
+ GasLimit hexutil.Uint64
Amount *hexutil.Big
Payload hexutil.Bytes
V *hexutil.Big
@@ -82,15 +82,15 @@ type txdataMarshaling struct {
S *hexutil.Big
}
-func NewTransaction(nonce uint64, to common.Address, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction {
+func NewTransaction(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction {
return newTransaction(nonce, &to, amount, gasLimit, gasPrice, data)
}
-func NewContractCreation(nonce uint64, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction {
+func NewContractCreation(nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction {
return newTransaction(nonce, nil, amount, gasLimit, gasPrice, data)
}
-func newTransaction(nonce uint64, to *common.Address, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction {
+func newTransaction(nonce uint64, to *common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction {
if len(data) > 0 {
data = common.CopyBytes(data)
}
@@ -99,7 +99,7 @@ func newTransaction(nonce uint64, to *common.Address, amount, gasLimit, gasPrice
Recipient: to,
Payload: data,
Amount: new(big.Int),
- GasLimit: new(big.Int),
+ GasLimit: gasLimit,
Price: new(big.Int),
V: new(big.Int),
R: new(big.Int),
@@ -108,9 +108,6 @@ func newTransaction(nonce uint64, to *common.Address, amount, gasLimit, gasPrice
if amount != nil {
d.Amount.Set(amount)
}
- if gasLimit != nil {
- d.GasLimit.Set(gasLimit)
- }
if gasPrice != nil {
d.Price.Set(gasPrice)
}
@@ -182,7 +179,7 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
}
func (tx *Transaction) Data() []byte { return common.CopyBytes(tx.data.Payload) }
-func (tx *Transaction) Gas() *big.Int { return new(big.Int).Set(tx.data.GasLimit) }
+func (tx *Transaction) Gas() uint64 { return tx.data.GasLimit }
func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.data.Price) }
func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.data.Amount) }
func (tx *Transaction) Nonce() uint64 { return tx.data.AccountNonce }
@@ -209,6 +206,8 @@ func (tx *Transaction) Hash() common.Hash {
return v
}
+// Size returns the true RLP encoded storage size of the transaction, either by
+// encoding and returning it, or returning a previsouly cached value.
func (tx *Transaction) Size() common.StorageSize {
if size := tx.size.Load(); size != nil {
return size.(common.StorageSize)
@@ -227,8 +226,8 @@ func (tx *Transaction) Size() common.StorageSize {
func (tx *Transaction) AsMessage(s Signer) (Message, error) {
msg := Message{
nonce: tx.data.AccountNonce,
- price: new(big.Int).Set(tx.data.Price),
- gasLimit: new(big.Int).Set(tx.data.GasLimit),
+ gasLimit: tx.data.GasLimit,
+ gasPrice: new(big.Int).Set(tx.data.Price),
to: tx.data.Recipient,
amount: tx.data.Amount,
data: tx.data.Payload,
@@ -254,7 +253,7 @@ func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, e
// Cost returns amount + gasprice * gaslimit.
func (tx *Transaction) Cost() *big.Int {
- total := new(big.Int).Mul(tx.data.Price, tx.data.GasLimit)
+ total := new(big.Int).Mul(tx.data.Price, new(big.Int).SetUint64(tx.data.GasLimit))
total.Add(total, tx.data.Amount)
return total
}
@@ -440,22 +439,24 @@ func (t *TransactionsByPriceAndNonce) Pop() {
//
// NOTE: In a future PR this will be removed.
type Message struct {
- to *common.Address
- from common.Address
- nonce uint64
- amount, price, gasLimit *big.Int
- data []byte
- checkNonce bool
+ to *common.Address
+ from common.Address
+ nonce uint64
+ amount *big.Int
+ gasLimit uint64
+ gasPrice *big.Int
+ data []byte
+ checkNonce bool
}
-func NewMessage(from common.Address, to *common.Address, nonce uint64, amount, gasLimit, price *big.Int, data []byte, checkNonce bool) Message {
+func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, checkNonce bool) Message {
return Message{
from: from,
to: to,
nonce: nonce,
amount: amount,
- price: price,
gasLimit: gasLimit,
+ gasPrice: gasPrice,
data: data,
checkNonce: checkNonce,
}
@@ -463,9 +464,9 @@ func NewMessage(from common.Address, to *common.Address, nonce uint64, amount, g
func (m Message) From() common.Address { return m.from }
func (m Message) To() *common.Address { return m.to }
-func (m Message) GasPrice() *big.Int { return m.price }
+func (m Message) GasPrice() *big.Int { return m.gasPrice }
func (m Message) Value() *big.Int { return m.amount }
-func (m Message) Gas() *big.Int { return m.gasLimit }
+func (m Message) Gas() uint64 { return m.gasLimit }
func (m Message) Nonce() uint64 { return m.nonce }
func (m Message) Data() []byte { return m.data }
func (m Message) CheckNonce() bool { return m.checkNonce }
diff --git a/core/types/transaction_signing_test.go b/core/types/transaction_signing_test.go
index 7f799fb10..689fc38a9 100644
--- a/core/types/transaction_signing_test.go
+++ b/core/types/transaction_signing_test.go
@@ -30,7 +30,7 @@ func TestEIP155Signing(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey)
signer := NewEIP155Signer(big.NewInt(18))
- tx, err := SignTx(NewTransaction(0, addr, new(big.Int), new(big.Int), new(big.Int), nil), signer, key)
+ tx, err := SignTx(NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil), signer, key)
if err != nil {
t.Fatal(err)
}
@@ -49,7 +49,7 @@ func TestEIP155ChainId(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey)
signer := NewEIP155Signer(big.NewInt(18))
- tx, err := SignTx(NewTransaction(0, addr, new(big.Int), new(big.Int), new(big.Int), nil), signer, key)
+ tx, err := SignTx(NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil), signer, key)
if err != nil {
t.Fatal(err)
}
@@ -61,7 +61,7 @@ func TestEIP155ChainId(t *testing.T) {
t.Error("expected chainId to be", signer.chainId, "got", tx.ChainId())
}
- tx = NewTransaction(0, addr, new(big.Int), new(big.Int), new(big.Int), nil)
+ tx = NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil)
tx, err = SignTx(tx, HomesteadSigner{}, key)
if err != nil {
t.Fatal(err)
@@ -118,7 +118,7 @@ func TestEIP155SigningVitalik(t *testing.T) {
func TestChainId(t *testing.T) {
key, _ := defaultTestKey()
- tx := NewTransaction(0, common.Address{}, new(big.Int), new(big.Int), new(big.Int), nil)
+ tx := NewTransaction(0, common.Address{}, new(big.Int), 0, new(big.Int), nil)
var err error
tx, err = SignTx(tx, NewEIP155Signer(big.NewInt(1)), key)
diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go
index 82d74e3b3..d1861b14c 100644
--- a/core/types/transaction_test.go
+++ b/core/types/transaction_test.go
@@ -34,7 +34,7 @@ var (
emptyTx = NewTransaction(
0,
common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"),
- big.NewInt(0), big.NewInt(0), big.NewInt(0),
+ big.NewInt(0), 0, big.NewInt(0),
nil,
)
@@ -42,7 +42,7 @@ var (
3,
common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b"),
big.NewInt(10),
- big.NewInt(2000),
+ 2000,
big.NewInt(1),
common.FromHex("5544"),
).WithSignature(
@@ -139,7 +139,7 @@ func TestTransactionPriceNonceSort(t *testing.T) {
for start, key := range keys {
addr := crypto.PubkeyToAddress(key.PublicKey)
for i := 0; i < 25; i++ {
- tx, _ := SignTx(NewTransaction(uint64(start+i), common.Address{}, big.NewInt(100), big.NewInt(100), big.NewInt(int64(start+i)), nil), signer, key)
+ tx, _ := SignTx(NewTransaction(uint64(start+i), common.Address{}, big.NewInt(100), 100, big.NewInt(int64(start+i)), nil), signer, key)
groups[addr] = append(groups[addr], tx)
}
}
@@ -204,9 +204,9 @@ func TestTransactionJSON(t *testing.T) {
var tx *Transaction
switch i % 2 {
case 0:
- tx = NewTransaction(i, common.Address{1}, common.Big0, common.Big1, common.Big2, []byte("abcdef"))
+ tx = NewTransaction(i, common.Address{1}, common.Big0, 1, common.Big2, []byte("abcdef"))
case 1:
- tx = NewContractCreation(i, common.Big0, common.Big1, common.Big2, []byte("abcdef"))
+ tx = NewContractCreation(i, common.Big0, 1, common.Big2, []byte("abcdef"))
}
tx, err := SignTx(tx, signer, key)
diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go
index 513651835..96083337c 100644
--- a/core/vm/contracts_test.go
+++ b/core/vm/contracts_test.go
@@ -1,3 +1,19 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
package vm
import (
diff --git a/core/vm/evm.go b/core/vm/evm.go
index a3f3a97cb..46e7baff4 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -69,7 +69,7 @@ type Context struct {
// Block information
Coinbase common.Address // Provides information for COINBASE
- GasLimit *big.Int // Provides information for GASLIMIT
+ GasLimit uint64 // Provides information for GASLIMIT
BlockNumber *big.Int // Provides information for NUMBER
Time *big.Int // Provides information for TIME
Difficulty *big.Int // Provides information for DIFFICULTY
@@ -391,7 +391,7 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I
return ret, contractAddr, contract.Gas, err
}
-// ChainConfig returns the evmironment's chain configuration
+// ChainConfig returns the environment's chain configuration
func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }
// Interpreter returns the EVM interpreter
diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go
index ff109af57..83adba428 100644
--- a/core/vm/gas_table.go
+++ b/core/vm/gas_table.go
@@ -17,8 +17,6 @@
package vm
import (
- "math/big"
-
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/params"
@@ -130,7 +128,7 @@ func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, m
// 0 => non 0
return params.SstoreSetGas, nil
} else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) {
- evm.StateDB.AddRefund(new(big.Int).SetUint64(params.SstoreRefundGas))
+ evm.StateDB.AddRefund(params.SstoreRefundGas)
return params.SstoreClearGas, nil
} else {
@@ -405,7 +403,7 @@ func gasSuicide(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
}
if !evm.StateDB.HasSuicided(contract.Address()) {
- evm.StateDB.AddRefund(new(big.Int).SetUint64(params.SuicideRefundGas))
+ evm.StateDB.AddRefund(params.SuicideRefundGas)
}
return gas, nil
}
diff --git a/core/vm/gen_structlog.go b/core/vm/gen_structlog.go
index 88df942dc..ade3ca631 100644
--- a/core/vm/gen_structlog.go
+++ b/core/vm/gen_structlog.go
@@ -11,19 +11,22 @@ import (
"github.com/ethereum/go-ethereum/common/math"
)
+var _ = (*structLogMarshaling)(nil)
+
func (s StructLog) MarshalJSON() ([]byte, error) {
type StructLog struct {
- Pc uint64 `json:"pc"`
- Op OpCode `json:"op"`
- Gas math.HexOrDecimal64 `json:"gas"`
- GasCost math.HexOrDecimal64 `json:"gasCost"`
- Memory hexutil.Bytes `json:"memory"`
- MemorySize int `json:"memSize"`
- Stack []*math.HexOrDecimal256 `json:"stack"`
- Storage map[common.Hash]common.Hash `json:"-"`
- Depth int `json:"depth"`
- Err error `json:"error"`
- OpName string `json:"opName"`
+ Pc uint64 `json:"pc"`
+ Op OpCode `json:"op"`
+ Gas math.HexOrDecimal64 `json:"gas"`
+ GasCost math.HexOrDecimal64 `json:"gasCost"`
+ Memory hexutil.Bytes `json:"memory"`
+ MemorySize int `json:"memSize"`
+ Stack []*math.HexOrDecimal256 `json:"stack"`
+ Storage map[common.Hash]common.Hash `json:"-"`
+ Depth int `json:"depth"`
+ Err error `json:"-"`
+ OpName string `json:"opName"`
+ ErrorString string `json:"error"`
}
var enc StructLog
enc.Pc = s.Pc
@@ -42,6 +45,7 @@ func (s StructLog) MarshalJSON() ([]byte, error) {
enc.Depth = s.Depth
enc.Err = s.Err
enc.OpName = s.OpName()
+ enc.ErrorString = s.ErrorString()
return json.Marshal(&enc)
}
@@ -51,12 +55,12 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
Op *OpCode `json:"op"`
Gas *math.HexOrDecimal64 `json:"gas"`
GasCost *math.HexOrDecimal64 `json:"gasCost"`
- Memory hexutil.Bytes `json:"memory"`
+ Memory *hexutil.Bytes `json:"memory"`
MemorySize *int `json:"memSize"`
Stack []*math.HexOrDecimal256 `json:"stack"`
Storage map[common.Hash]common.Hash `json:"-"`
Depth *int `json:"depth"`
- Err *error `json:"error"`
+ Err error `json:"-"`
}
var dec StructLog
if err := json.Unmarshal(input, &dec); err != nil {
@@ -75,7 +79,7 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
s.GasCost = uint64(*dec.GasCost)
}
if dec.Memory != nil {
- s.Memory = dec.Memory
+ s.Memory = *dec.Memory
}
if dec.MemorySize != nil {
s.MemorySize = *dec.MemorySize
@@ -93,7 +97,7 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
s.Depth = *dec.Depth
}
if dec.Err != nil {
- s.Err = *dec.Err
+ s.Err = dec.Err
}
return nil
}
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index 1d1585fca..766172501 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -472,7 +472,7 @@ func opDifficulty(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stac
}
func opGasLimit(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(new(big.Int).Set(evm.GasLimit)))
+ stack.push(math.U256(new(big.Int).SetUint64(evm.GasLimit)))
return nil, nil
}
diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go
index 18644989c..180433ea8 100644
--- a/core/vm/instructions_test.go
+++ b/core/vm/instructions_test.go
@@ -1,3 +1,19 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
package vm
import (
diff --git a/core/vm/interface.go b/core/vm/interface.go
index c0c52732b..1ef91cf1d 100644
--- a/core/vm/interface.go
+++ b/core/vm/interface.go
@@ -39,8 +39,8 @@ type StateDB interface {
SetCode(common.Address, []byte)
GetCodeSize(common.Address) int
- AddRefund(*big.Int)
- GetRefund() *big.Int
+ AddRefund(uint64)
+ GetRefund() uint64
GetState(common.Address, common.Hash) common.Hash
SetState(common.Address, common.Hash, common.Hash)
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go
index 482e67a3a..82a6d3de6 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/interpreter.go
@@ -20,9 +20,7 @@ import (
"fmt"
"sync/atomic"
- "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
- "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
)
@@ -123,11 +121,6 @@ func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err er
return nil, nil
}
- codehash := contract.CodeHash // codehash is used when doing jump dest caching
- if codehash == (common.Hash{}) {
- codehash = crypto.Keccak256Hash(contract.Code)
- }
-
var (
op OpCode // current opcode
mem = NewMemory() // bound memory
diff --git a/core/vm/logger.go b/core/vm/logger.go
index 1a6e43ee3..4c820d8b5 100644
--- a/core/vm/logger.go
+++ b/core/vm/logger.go
@@ -62,22 +62,30 @@ type StructLog struct {
Stack []*big.Int `json:"stack"`
Storage map[common.Hash]common.Hash `json:"-"`
Depth int `json:"depth"`
- Err error `json:"error"`
+ Err error `json:"-"`
}
// overrides for gencodec
type structLogMarshaling struct {
- Stack []*math.HexOrDecimal256
- Gas math.HexOrDecimal64
- GasCost math.HexOrDecimal64
- Memory hexutil.Bytes
- OpName string `json:"opName"`
+ Stack []*math.HexOrDecimal256
+ Gas math.HexOrDecimal64
+ GasCost math.HexOrDecimal64
+ Memory hexutil.Bytes
+ OpName string `json:"opName"` // adds call to OpName() in MarshalJSON
+ ErrorString string `json:"error"` // adds call to ErrorString() in MarshalJSON
}
func (s *StructLog) OpName() string {
return s.Op.String()
}
+func (s *StructLog) ErrorString() string {
+ if s.Err != nil {
+ return s.Err.Error()
+ }
+ return ""
+}
+
// Tracer is used to collect execution traces from an EVM transaction
// execution. CaptureState is called for each step of the VM with the
// current VM state.
@@ -100,6 +108,8 @@ type StructLogger struct {
logs []StructLog
changedValues map[common.Address]Storage
+ output []byte
+ err error
}
// NewStructLogger returns a new logger
@@ -172,17 +182,19 @@ func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost ui
}
func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error {
- fmt.Printf("0x%x", output)
- if err != nil {
- fmt.Printf(" error: %v\n", err)
- }
+ l.output = output
+ l.err = err
return nil
}
-// StructLogs returns a list of captured log entries
-func (l *StructLogger) StructLogs() []StructLog {
- return l.logs
-}
+// StructLogs returns the captured log entries.
+func (l *StructLogger) StructLogs() []StructLog { return l.logs }
+
+// Error returns the VM error captured by the trace.
+func (l *StructLogger) Error() error { return l.err }
+
+// Output returns the VM return value captured by the trace.
+func (l *StructLogger) Output() []byte { return l.output }
// WriteTrace writes a formatted trace to the given writer
func WriteTrace(writer io.Writer, logs []StructLog) {
diff --git a/core/vm/noop.go b/core/vm/noop.go
index 2a04a9565..b71ead0d7 100644
--- a/core/vm/noop.go
+++ b/core/vm/noop.go
@@ -55,8 +55,8 @@ func (NoopStateDB) GetCodeHash(common.Address) common.Hash
func (NoopStateDB) GetCode(common.Address) []byte { return nil }
func (NoopStateDB) SetCode(common.Address, []byte) {}
func (NoopStateDB) GetCodeSize(common.Address) int { return 0 }
-func (NoopStateDB) AddRefund(*big.Int) {}
-func (NoopStateDB) GetRefund() *big.Int { return nil }
+func (NoopStateDB) AddRefund(uint64) {}
+func (NoopStateDB) GetRefund() uint64 { return 0 }
func (NoopStateDB) GetState(common.Address, common.Hash) common.Hash { return common.Hash{} }
func (NoopStateDB) SetState(common.Address, common.Hash, common.Hash) {}
func (NoopStateDB) Suicide(common.Address) bool { return false }
diff --git a/core/vm/runtime/env.go b/core/vm/runtime/env.go
index 818da1be2..31c9b9cf9 100644
--- a/core/vm/runtime/env.go
+++ b/core/vm/runtime/env.go
@@ -17,8 +17,6 @@
package runtime
import (
- "math/big"
-
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/vm"
@@ -35,7 +33,7 @@ func NewEnv(cfg *Config) *vm.EVM {
BlockNumber: cfg.BlockNumber,
Time: cfg.Time,
Difficulty: cfg.Difficulty,
- GasLimit: new(big.Int).SetUint64(cfg.GasLimit),
+ GasLimit: cfg.GasLimit,
GasPrice: cfg.GasPrice,
}
diff --git a/crypto/crypto.go b/crypto/crypto.go
index e51726e62..1c4d5a2e0 100644
--- a/crypto/crypto.go
+++ b/crypto/crypto.go
@@ -97,6 +97,16 @@ func toECDSA(d []byte, strict bool) (*ecdsa.PrivateKey, error) {
return nil, fmt.Errorf("invalid length, need %d bits", priv.Params().BitSize)
}
priv.D = new(big.Int).SetBytes(d)
+
+ // The priv.D must < N
+ if priv.D.Cmp(secp256k1_N) >= 0 {
+ return nil, fmt.Errorf("invalid private key, >=N")
+ }
+ // The priv.D must not be zero or negative.
+ if priv.D.Sign() <= 0 {
+ return nil, fmt.Errorf("invalid private key, zero or negative")
+ }
+
priv.PublicKey.X, priv.PublicKey.Y = priv.PublicKey.Curve.ScalarBaseMult(d)
if priv.PublicKey.X == nil {
return nil, errors.New("invalid private key")
diff --git a/crypto/ecies/ecies.go b/crypto/ecies/ecies.go
index 1d5f96ed2..2ed91c895 100644
--- a/crypto/ecies/ecies.go
+++ b/crypto/ecies/ecies.go
@@ -314,7 +314,7 @@ func (prv *PrivateKey) Decrypt(rand io.Reader, c, s1, s2 []byte) (m []byte, err
switch c[0] {
case 2, 3, 4:
- rLen = ((prv.PublicKey.Curve.Params().BitSize + 7) / 4)
+ rLen = (prv.PublicKey.Curve.Params().BitSize + 7) / 4
if len(c) < (rLen + hLen + 1) {
err = ErrInvalidMessage
return
diff --git a/dashboard/README.md b/dashboard/README.md
index da28f5a19..e010095ab 100644
--- a/dashboard/README.md
+++ b/dashboard/README.md
@@ -20,7 +20,7 @@ Normally the dashboard assets are bundled into Geth via `go-bindata` to avoid ex
```
$ (cd dashboard/assets && ./node_modules/.bin/webpack --watch)
-$ geth --dashboard --dashboard.assets=dashboard/assets/public --vmodule=dashboard=5
+$ geth --dashboard --dashboard.assets=dashboard/assets --vmodule=dashboard=5
```
To bundle up the final UI into Geth, run `go generate`:
diff --git a/dashboard/assets.go b/dashboard/assets.go
index 032e45dff..8337cf080 100644
--- a/dashboard/assets.go
+++ b/dashboard/assets.go
@@ -1,12 +1,12 @@
-// Code generated by go-bindata.
+// Code generated by go-bindata. DO NOT EDIT.
// sources:
-// assets/public/bundle.js
-// assets/public/dashboard.html
-// DO NOT EDIT!
+// assets/dashboard.html
+// assets/bundle.js
package dashboard
import (
+ "crypto/sha256"
"fmt"
"io/ioutil"
"os"
@@ -16,8 +16,9 @@ import (
)
type asset struct {
- bytes []byte
- info os.FileInfo
+ bytes []byte
+ info os.FileInfo
+ digest [sha256.Size]byte
}
type bindataFileInfo struct {
@@ -47,7 +48,48 @@ func (fi bindataFileInfo) Sys() interface{} {
}
//nolint:misspell
-var _publicBundleJs = []byte(`!function(modules) {
+var _dashboardHtml = []byte(`<!DOCTYPE html>
+<html lang="en" style="height: 100%">
+ <head>
+ <meta charset="UTF-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
+ <title>Go Ethereum Dashboard</title>
+ <link rel="shortcut icon" type="image/ico" href="https://ethereum.org/favicon.ico" />
+ <style>
+ ::-webkit-scrollbar {
+ width: 16px;
+ }
+ ::-webkit-scrollbar-thumb {
+ background: #212121;
+ }
+ </style>
+ </head>
+ <body style="height: 100%; margin: 0">
+ <div id="dashboard" style="height: 100%"></div>
+ <script src="bundle.js"></script>
+ </body>
+</html>
+`)
+
+func dashboardHtmlBytes() ([]byte, error) {
+ return _dashboardHtml, nil
+}
+
+func dashboardHtml() (*asset, error) {
+ bytes, err := dashboardHtmlBytes()
+ if err != nil {
+ return nil, err
+ }
+
+ info := bindataFileInfo{name: "dashboard.html", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+ a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6b, 0xd9, 0xa6, 0xeb, 0x32, 0x49, 0x9b, 0xe5, 0x3a, 0xcb, 0x99, 0xd3, 0xb6, 0x69, 0x7f, 0xde, 0x35, 0x9d, 0x5, 0x96, 0x84, 0xc0, 0x14, 0xef, 0xbe, 0x58, 0x10, 0x5e, 0x40, 0xf2, 0x12, 0x97}}
+ return a, nil
+}
+
+//nolint:misspell
+var _bundleJs = []byte((((((((((`!function(modules) {
function __webpack_require__(moduleId) {
if (installedModules[moduleId]) return installedModules[moduleId].exports;
var module = installedModules[moduleId] = {
@@ -74,45 +116,21 @@ var _publicBundleJs = []byte(`!function(modules) {
return __webpack_require__.d(getter, "a", getter), getter;
}, __webpack_require__.o = function(object, property) {
return Object.prototype.hasOwnProperty.call(object, property);
- }, __webpack_require__.p = "", __webpack_require__(__webpack_require__.s = 453);
-}([ function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _curry2(fn) {
- return function f2(a, b) {
- switch (arguments.length) {
- case 0:
- return f2;
-
- case 1:
- return Object(__WEBPACK_IMPORTED_MODULE_1__isPlaceholder__.a)(a) ? f2 : Object(__WEBPACK_IMPORTED_MODULE_0__curry1__.a)(function(_b) {
- return fn(a, _b);
- });
-
- default:
- return Object(__WEBPACK_IMPORTED_MODULE_1__isPlaceholder__.a)(a) && Object(__WEBPACK_IMPORTED_MODULE_1__isPlaceholder__.a)(b) ? f2 : Object(__WEBPACK_IMPORTED_MODULE_1__isPlaceholder__.a)(a) ? Object(__WEBPACK_IMPORTED_MODULE_0__curry1__.a)(function(_a) {
- return fn(_a, b);
- }) : Object(__WEBPACK_IMPORTED_MODULE_1__isPlaceholder__.a)(b) ? Object(__WEBPACK_IMPORTED_MODULE_0__curry1__.a)(function(_b) {
- return fn(a, _b);
- }) : fn(a, b);
- }
- };
- }
- __webpack_exports__.a = _curry2;
- var __WEBPACK_IMPORTED_MODULE_0__curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__isPlaceholder__ = __webpack_require__(133);
-}, function(module, exports, __webpack_require__) {
+ }, __webpack_require__.p = "", __webpack_require__(__webpack_require__.s = 331);
+}([ function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
- "production" === process.env.NODE_ENV ? module.exports = __webpack_require__(454) : module.exports = __webpack_require__(455);
- }).call(exports, __webpack_require__(3));
+ "production" === process.env.NODE_ENV ? module.exports = __webpack_require__(332) : module.exports = __webpack_require__(333);
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
(function(process) {
if ("production" !== process.env.NODE_ENV) {
var REACT_ELEMENT_TYPE = "function" == typeof Symbol && Symbol.for && Symbol.for("react.element") || 60103, isValidElement = function(object) {
return "object" == typeof object && null !== object && object.$$typeof === REACT_ELEMENT_TYPE;
};
- module.exports = __webpack_require__(496)(isValidElement, !0);
- } else module.exports = __webpack_require__(497)();
- }).call(exports, __webpack_require__(3));
+ module.exports = __webpack_require__(374)(isValidElement, !0);
+ } else module.exports = __webpack_require__(375)();
+ }).call(exports, __webpack_require__(2));
}, function(module, exports) {
function defaultSetTimout() {
throw new Error("setTimeout has not been defined");
@@ -202,56 +220,6 @@ var _publicBundleJs = []byte(`!function(modules) {
}, process.umask = function() {
return 0;
};
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _curry1(fn) {
- return function f1(a) {
- return 0 === arguments.length || Object(__WEBPACK_IMPORTED_MODULE_0__isPlaceholder__.a)(a) ? f1 : fn.apply(this, arguments);
- };
- }
- __webpack_exports__.a = _curry1;
- var __WEBPACK_IMPORTED_MODULE_0__isPlaceholder__ = __webpack_require__(133);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _curry3(fn) {
- return function f3(a, b, c) {
- switch (arguments.length) {
- case 0:
- return f3;
-
- case 1:
- return Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(a) ? f3 : Object(__WEBPACK_IMPORTED_MODULE_1__curry2__.a)(function(_b, _c) {
- return fn(a, _b, _c);
- });
-
- case 2:
- return Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(a) && Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(b) ? f3 : Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(a) ? Object(__WEBPACK_IMPORTED_MODULE_1__curry2__.a)(function(_a, _c) {
- return fn(_a, b, _c);
- }) : Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(b) ? Object(__WEBPACK_IMPORTED_MODULE_1__curry2__.a)(function(_b, _c) {
- return fn(a, _b, _c);
- }) : Object(__WEBPACK_IMPORTED_MODULE_0__curry1__.a)(function(_c) {
- return fn(a, b, _c);
- });
-
- default:
- return Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(a) && Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(b) && Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(c) ? f3 : Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(a) && Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(b) ? Object(__WEBPACK_IMPORTED_MODULE_1__curry2__.a)(function(_a, _b) {
- return fn(_a, _b, c);
- }) : Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(a) && Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(c) ? Object(__WEBPACK_IMPORTED_MODULE_1__curry2__.a)(function(_a, _c) {
- return fn(_a, b, _c);
- }) : Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(b) && Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(c) ? Object(__WEBPACK_IMPORTED_MODULE_1__curry2__.a)(function(_b, _c) {
- return fn(a, _b, _c);
- }) : Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(a) ? Object(__WEBPACK_IMPORTED_MODULE_0__curry1__.a)(function(_a) {
- return fn(_a, b, c);
- }) : Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(b) ? Object(__WEBPACK_IMPORTED_MODULE_0__curry1__.a)(function(_b) {
- return fn(a, _b, c);
- }) : Object(__WEBPACK_IMPORTED_MODULE_2__isPlaceholder__.a)(c) ? Object(__WEBPACK_IMPORTED_MODULE_0__curry1__.a)(function(_c) {
- return fn(a, b, _c);
- }) : fn(a, b, c);
- }
- };
- }
- __webpack_exports__.a = _curry3;
- var __WEBPACK_IMPORTED_MODULE_0__curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2__isPlaceholder__ = __webpack_require__(133);
}, function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
!function() {
@@ -281,6 +249,11 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return Array.from(arr);
}
+ function _objectWithoutProperties(obj, keys) {
+ var target = {};
+ for (var i in obj) keys.indexOf(i) >= 0 || Object.prototype.hasOwnProperty.call(obj, i) && (target[i] = obj[i]);
+ return target;
+ }
__webpack_require__.d(__webpack_exports__, "c", function() {
return PRESENTATION_ATTRIBUTES;
}), __webpack_require__.d(__webpack_exports__, "a", function() {
@@ -316,7 +289,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "o", function() {
return parseChildIndex;
});
- var __WEBPACK_IMPORTED_MODULE_0_lodash_isNil__ = __webpack_require__(28), __WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_1_lodash_isString__ = __webpack_require__(227), __WEBPACK_IMPORTED_MODULE_1_lodash_isString___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isString__), __WEBPACK_IMPORTED_MODULE_2_lodash_isObject__ = __webpack_require__(47), __WEBPACK_IMPORTED_MODULE_2_lodash_isObject___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isObject__), __WEBPACK_IMPORTED_MODULE_3_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_3_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_4_lodash_isArray__ = __webpack_require__(16), __WEBPACK_IMPORTED_MODULE_4_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_5_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_5_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_react__), __WEBPACK_IMPORTED_MODULE_6_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_6_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_prop_types__), __WEBPACK_IMPORTED_MODULE_7__DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_8__PureRender__ = __webpack_require__(8), PRESENTATION_ATTRIBUTES = {
+ var __WEBPACK_IMPORTED_MODULE_0_lodash_isNil__ = __webpack_require__(20), __WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_1_lodash_isString__ = __webpack_require__(164), __WEBPACK_IMPORTED_MODULE_1_lodash_isString___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isString__), __WEBPACK_IMPORTED_MODULE_2_lodash_isObject__ = __webpack_require__(31), __WEBPACK_IMPORTED_MODULE_2_lodash_isObject___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isObject__), __WEBPACK_IMPORTED_MODULE_3_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_3_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_4_lodash_isArray__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_4_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_5_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_5_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_react__), __WEBPACK_IMPORTED_MODULE_6_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_6_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_prop_types__), __WEBPACK_IMPORTED_MODULE_7__DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_8__PureRender__ = __webpack_require__(5), PRESENTATION_ATTRIBUTES = {
alignmentBaseline: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.string,
angle: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.number,
baselineShift: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.string,
@@ -472,7 +445,12 @@ var _publicBundleJs = []byte(`!function(modules) {
entry && entry.type && __WEBPACK_IMPORTED_MODULE_1_lodash_isString___default()(entry.type) && SVG_TAGS.indexOf(entry.type) >= 0 && svgElements.push(entry);
}), svgElements;
}, isSingleChildEqual = function(nextChild, prevChild) {
- return !(!__WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default()(nextChild) || !__WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default()(prevChild)) || !__WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default()(nextChild) && !__WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default()(prevChild) && Object(__WEBPACK_IMPORTED_MODULE_8__PureRender__.b)(nextChild.props, prevChild.props);
+ if (__WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default()(nextChild) && __WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default()(prevChild)) return !0;
+ if (!__WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default()(nextChild) && !__WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default()(prevChild)) {
+ var _ref = nextChild.props || {}, nextChildren = _ref.children, nextProps = _objectWithoutProperties(_ref, [ "children" ]), _ref2 = prevChild.props || {}, prevChildren = _ref2.children, prevProps = _objectWithoutProperties(_ref2, [ "children" ]);
+ return nextChildren && prevChildren ? Object(__WEBPACK_IMPORTED_MODULE_8__PureRender__.b)(nextProps, prevProps) && isChildrenEqual(nextChildren, prevChildren) : !nextChildren && !prevChildren && Object(__WEBPACK_IMPORTED_MODULE_8__PureRender__.b)(nextProps, prevProps);
+ }
+ return !1;
}, isChildrenEqual = function isChildrenEqual(nextChildren, prevChildren) {
if (nextChildren === prevChildren) return !0;
if (__WEBPACK_IMPORTED_MODULE_5_react__.Children.count(nextChildren) !== __WEBPACK_IMPORTED_MODULE_5_react__.Children.count(prevChildren)) return !1;
@@ -531,7 +509,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = !0;
- var _assign = __webpack_require__(268), _assign2 = function(obj) {
+ var _assign = __webpack_require__(205), _assign2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -549,7 +527,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var tag = baseGetTag(value);
return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
}
- var baseGetTag = __webpack_require__(59), isObject = __webpack_require__(47), asyncTag = "[object AsyncFunction]", funcTag = "[object Function]", genTag = "[object GeneratorFunction]", proxyTag = "[object Proxy]";
+ var baseGetTag = __webpack_require__(42), isObject = __webpack_require__(31), asyncTag = "[object AsyncFunction]", funcTag = "[object Function]", genTag = "[object GeneratorFunction]", proxyTag = "[object Proxy]";
module.exports = isFunction;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -574,7 +552,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "a", function() {
return findEntryInArray;
});
- var __WEBPACK_IMPORTED_MODULE_0_lodash_get__ = __webpack_require__(152), __WEBPACK_IMPORTED_MODULE_0_lodash_get___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_get__), __WEBPACK_IMPORTED_MODULE_1_lodash_isArray__ = __webpack_require__(16), __WEBPACK_IMPORTED_MODULE_1_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_2_lodash_isNaN__ = __webpack_require__(159), __WEBPACK_IMPORTED_MODULE_2_lodash_isNaN___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isNaN__), __WEBPACK_IMPORTED_MODULE_3_lodash_isNumber__ = __webpack_require__(232), __WEBPACK_IMPORTED_MODULE_3_lodash_isNumber___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_isNumber__), __WEBPACK_IMPORTED_MODULE_4_lodash_isString__ = __webpack_require__(227), __WEBPACK_IMPORTED_MODULE_4_lodash_isString___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_lodash_isString__), mathSign = function(value) {
+ var __WEBPACK_IMPORTED_MODULE_0_lodash_get__ = __webpack_require__(165), __WEBPACK_IMPORTED_MODULE_0_lodash_get___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_get__), __WEBPACK_IMPORTED_MODULE_1_lodash_isArray__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_1_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_2_lodash_isNaN__ = __webpack_require__(117), __WEBPACK_IMPORTED_MODULE_2_lodash_isNaN___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isNaN__), __WEBPACK_IMPORTED_MODULE_3_lodash_isNumber__ = __webpack_require__(170), __WEBPACK_IMPORTED_MODULE_3_lodash_isNumber___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_isNumber__), __WEBPACK_IMPORTED_MODULE_4_lodash_isString__ = __webpack_require__(164), __WEBPACK_IMPORTED_MODULE_4_lodash_isString___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_lodash_isString__), mathSign = function(value) {
return 0 === value ? 0 : value > 0 ? 1 : -1;
}, isPercent = function(value) {
return __WEBPACK_IMPORTED_MODULE_4_lodash_isString___default()(value) && value.indexOf("%") === value.length - 1;
@@ -630,42 +608,38 @@ var _publicBundleJs = []byte(`!function(modules) {
}
Object.defineProperty(exports, "__esModule", {
value: !0
- }), exports.sheetsManager = exports.preset = void 0;
- var _keys = __webpack_require__(51), _keys2 = _interopRequireDefault(_keys), _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _getPrototypeOf = __webpack_require__(38), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(39), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(40), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(41), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(42), _inherits3 = _interopRequireDefault(_inherits2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _map = __webpack_require__(519), _map2 = _interopRequireDefault(_map), _minSafeInteger = __webpack_require__(535), _minSafeInteger2 = _interopRequireDefault(_minSafeInteger), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), _hoistNonReactStatics = __webpack_require__(194), _hoistNonReactStatics2 = _interopRequireDefault(_hoistNonReactStatics), _wrapDisplayName = __webpack_require__(95), _wrapDisplayName2 = _interopRequireDefault(_wrapDisplayName), _getDisplayName = __webpack_require__(289), _getDisplayName2 = _interopRequireDefault(_getDisplayName), _contextTypes = __webpack_require__(538), _contextTypes2 = _interopRequireDefault(_contextTypes), _jss = __webpack_require__(291), _jssGlobal = __webpack_require__(561), _jssGlobal2 = _interopRequireDefault(_jssGlobal), _jssNested = __webpack_require__(562), _jssNested2 = _interopRequireDefault(_jssNested), _jssCamelCase = __webpack_require__(563), _jssCamelCase2 = _interopRequireDefault(_jssCamelCase), _jssDefaultUnit = __webpack_require__(564), _jssDefaultUnit2 = _interopRequireDefault(_jssDefaultUnit), _jssVendorPrefixer = __webpack_require__(566), _jssVendorPrefixer2 = _interopRequireDefault(_jssVendorPrefixer), _jssPropsSort = __webpack_require__(571), _jssPropsSort2 = _interopRequireDefault(_jssPropsSort), _ns = __webpack_require__(290), ns = function(obj) {
+ }), exports.sheetsManager = void 0;
+ var _keys = __webpack_require__(41), _keys2 = _interopRequireDefault(_keys), _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _getPrototypeOf = __webpack_require__(26), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(27), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(28), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(29), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(30), _inherits3 = _interopRequireDefault(_inherits2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _map = __webpack_require__(397), _map2 = _interopRequireDefault(_map), _minSafeInteger = __webpack_require__(413), _minSafeInteger2 = _interopRequireDefault(_minSafeInteger), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), _hoistNonReactStatics = __webpack_require__(152), _hoistNonReactStatics2 = _interopRequireDefault(_hoistNonReactStatics), _getDisplayName = __webpack_require__(226), _getDisplayName2 = _interopRequireDefault(_getDisplayName), _wrapDisplayName = __webpack_require__(75), _wrapDisplayName2 = _interopRequireDefault(_wrapDisplayName), _contextTypes = __webpack_require__(416), _contextTypes2 = _interopRequireDefault(_contextTypes), _jss = __webpack_require__(228), _ns = __webpack_require__(227), ns = function(obj) {
if (obj && obj.__esModule) return obj;
var newObj = {};
if (null != obj) for (var key in obj) Object.prototype.hasOwnProperty.call(obj, key) && (newObj[key] = obj[key]);
return newObj.default = obj, newObj;
- }(_ns), _createMuiTheme = __webpack_require__(193), _createMuiTheme2 = _interopRequireDefault(_createMuiTheme), _themeListener = __webpack_require__(192), _themeListener2 = _interopRequireDefault(_themeListener), _createGenerateClassName = __webpack_require__(572), _createGenerateClassName2 = _interopRequireDefault(_createGenerateClassName), _getStylesCreator = __webpack_require__(573), _getStylesCreator2 = _interopRequireDefault(_getStylesCreator), preset = exports.preset = function() {
- return {
- plugins: [ (0, _jssGlobal2.default)(), (0, _jssNested2.default)(), (0, _jssCamelCase2.default)(), (0,
- _jssDefaultUnit2.default)(), (0, _jssVendorPrefixer2.default)(), (0, _jssPropsSort2.default)() ]
- };
- }, jss = (0, _jss.create)(preset()), generateClassName = (0, _createGenerateClassName2.default)(), indexCounter = _minSafeInteger2.default, sheetsManager = exports.sheetsManager = new _map2.default(), noopTheme = {}, defaultTheme = void 0, withStyles = function(stylesOrCreator) {
+ }(_ns), _jssPreset = __webpack_require__(439), _jssPreset2 = _interopRequireDefault(_jssPreset), _createMuiTheme = __webpack_require__(151), _createMuiTheme2 = _interopRequireDefault(_createMuiTheme), _themeListener = __webpack_require__(150), _themeListener2 = _interopRequireDefault(_themeListener), _createGenerateClassName = __webpack_require__(451), _createGenerateClassName2 = _interopRequireDefault(_createGenerateClassName), _getStylesCreator = __webpack_require__(452), _getStylesCreator2 = _interopRequireDefault(_getStylesCreator), jss = (0,
+ _jss.create)((0, _jssPreset2.default)()), generateClassName = (0, _createGenerateClassName2.default)(), indexCounter = _minSafeInteger2.default, sheetsManager = exports.sheetsManager = new _map2.default(), noopTheme = {}, defaultTheme = void 0, withStyles = function(stylesOrCreator) {
var options = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
return function(Component) {
- var _options$withTheme = options.withTheme, withTheme = void 0 !== _options$withTheme && _options$withTheme, flip = options.flip, name = options.name, styleSheetOptions = (0,
+ var _options$withTheme = options.withTheme, withTheme = void 0 !== _options$withTheme && _options$withTheme, _options$flip = options.flip, flip = void 0 === _options$flip ? null : _options$flip, name = options.name, styleSheetOptions = (0,
_objectWithoutProperties3.default)(options, [ "withTheme", "flip", "name" ]), stylesCreator = (0,
_getStylesCreator2.default)(stylesOrCreator), listenToTheme = stylesCreator.themingEnabled || withTheme || "string" == typeof name;
- void 0 === stylesCreator.options.index && (indexCounter += 1, stylesCreator.options.index = indexCounter),
- "production" !== process.env.NODE_ENV && (0, _warning2.default)(indexCounter < 0, [ "Material-UI: you might have a memory leak.", "The indexCounter is not supposed to grow that much." ].join(" "));
- var Style = function(_React$Component) {
- function Style(props, context) {
- (0, _classCallCheck3.default)(this, Style);
- var _this = (0, _possibleConstructorReturn3.default)(this, (Style.__proto__ || (0,
- _getPrototypeOf2.default)(Style)).call(this, props, context));
- _this.state = {}, _this.unsubscribeId = null, _this.jss = null, _this.sheetsManager = sheetsManager,
- _this.disableStylesGeneration = !1, _this.stylesCreatorSaved = null, _this.theme = null,
- _this.sheetOptions = null, _this.theme = null;
+ indexCounter += 1, stylesCreator.options.index = indexCounter, "production" !== process.env.NODE_ENV && (0,
+ _warning2.default)(indexCounter < 0, [ "Material-UI: you might have a memory leak.", "The indexCounter is not supposed to grow that much." ].join(" "));
+ var WithStyles = function(_React$Component) {
+ function WithStyles(props, context) {
+ (0, _classCallCheck3.default)(this, WithStyles);
+ var _this = (0, _possibleConstructorReturn3.default)(this, (WithStyles.__proto__ || (0,
+ _getPrototypeOf2.default)(WithStyles)).call(this, props, context));
+ _this.state = {}, _this.disableStylesGeneration = !1, _this.jss = null, _this.sheetOptions = null,
+ _this.sheetsManager = sheetsManager, _this.stylesCreatorSaved = null, _this.theme = null,
+ _this.unsubscribeId = null, _this.jss = _this.context[ns.jss] || jss;
var muiThemeProviderOptions = _this.context.muiThemeProviderOptions;
- return _this.jss = _this.context[ns.jss] || jss, muiThemeProviderOptions && (muiThemeProviderOptions.sheetsManager && (_this.sheetsManager = muiThemeProviderOptions.sheetsManager),
+ return muiThemeProviderOptions && (muiThemeProviderOptions.sheetsManager && (_this.sheetsManager = muiThemeProviderOptions.sheetsManager),
_this.disableStylesGeneration = muiThemeProviderOptions.disableStylesGeneration),
_this.stylesCreatorSaved = stylesCreator, _this.sheetOptions = (0, _extends3.default)({
generateClassName: generateClassName
}, _this.context[ns.sheetOptions]), _this.theme = listenToTheme ? _themeListener2.default.initial(context) || getDefaultTheme() : noopTheme,
_this;
}
- return (0, _inherits3.default)(Style, _React$Component), (0, _createClass3.default)(Style, [ {
+ return (0, _inherits3.default)(WithStyles, _React$Component), (0, _createClass3.default)(WithStyles, [ {
key: "componentWillMount",
value: function() {
this.attach(this.theme);
@@ -703,10 +677,11 @@ var _publicBundleJs = []byte(`!function(modules) {
refs: 0,
sheet: null
}, sheetManager.set(theme, sheetManagerTheme)), 0 === sheetManagerTheme.refs) {
- var styles = stylesCreatorSaved.create(theme, name), meta = void 0;
- "production" !== process.env.NODE_ENV && (meta = name || (0, _getDisplayName2.default)(Component));
+ var styles = stylesCreatorSaved.create(theme, name), meta = name;
+ "production" === process.env.NODE_ENV || meta || (meta = (0, _getDisplayName2.default)(Component));
var sheet = this.jss.createStyleSheet(styles, (0, _extends3.default)({
meta: meta,
+ classNamePrefix: meta,
flip: "boolean" == typeof flip ? flip : "rtl" === theme.direction,
link: !1
}, this.sheetOptions, stylesCreatorSaved.options, {
@@ -741,10 +716,10 @@ var _publicBundleJs = []byte(`!function(modules) {
renderedClasses = sheetsManagerTheme.sheet.classes;
}
classes = classesProp ? (0, _extends3.default)({}, renderedClasses, (0, _keys2.default)(classesProp).reduce(function(accumulator, key) {
- return "production" !== process.env.NODE_ENV && (0, _warning2.default)(renderedClasses[key] || _this3.disableStylesGeneration, [ "Material-UI: the key ` + "`" + `" + key + "` + "`" + ` provided to the classes property is not implemented in " + (0,
+ return "production" !== process.env.NODE_ENV && (0, _warning2.default)(renderedClasses[key] || _this3.disableStylesGeneration, [ "Material-UI: the key ` + "`") + (`" + key + "` + ("`" + ` provided to the classes property is not implemented in " + (0,
_getDisplayName2.default)(Component) + ".", "You can only override one of the following: " + (0,
_keys2.default)(renderedClasses).join(",") ].join("\n")), "production" !== process.env.NODE_ENV && (0,
- _warning2.default)(!classesProp[key] || "string" == typeof classesProp[key], [ "Material-UI: the key ` + "`" + `" + key + "` + "`" + ` provided to the classes property is not valid for " + (0,
+ _warning2.default)(!classesProp[key] || "string" == typeof classesProp[key], [ "Material-UI: the key `))) + (("`" + (`" + key + "` + "`")) + (` provided to the classes property is not valid for " + (0,
_getDisplayName2.default)(Component) + ".", "You need to provide a non empty string instead of: " + classesProp[key] + "." ].join("\n")),
classesProp[key] && (accumulator[key] = renderedClasses[key] + " " + classesProp[key]),
accumulator;
@@ -757,21 +732,21 @@ var _publicBundleJs = []byte(`!function(modules) {
ref: innerRef
}));
}
- } ]), Style;
+ } ]), WithStyles;
}(_react2.default.Component);
- return Style.propTypes = "production" !== process.env.NODE_ENV ? {
+ return WithStyles.propTypes = "production" !== process.env.NODE_ENV ? {
classes: _propTypes2.default.object,
innerRef: _propTypes2.default.func
- } : {}, Style.contextTypes = (0, _extends3.default)({
+ } : {}, WithStyles.contextTypes = (0, _extends3.default)({
muiThemeProviderOptions: _propTypes2.default.object
}, _contextTypes2.default, listenToTheme ? _themeListener2.default.contextTypes : {}),
- "production" !== process.env.NODE_ENV && (Style.displayName = (0, _wrapDisplayName2.default)(Component, "withStyles")),
- (0, _hoistNonReactStatics2.default)(Style, Component), "production" !== process.env.NODE_ENV && (Style.Naked = Component,
- Style.options = options), Style;
+ "production" !== process.env.NODE_ENV && (WithStyles.displayName = (0, _wrapDisplayName2.default)(Component, "WithStyles")),
+ (0, _hoistNonReactStatics2.default)(WithStyles, Component), "production" !== process.env.NODE_ENV && (WithStyles.Naked = Component,
+ WithStyles.options = options), WithStyles;
};
};
exports.default = withStyles;
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -780,7 +755,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var len = arguments.length;
args = new Array(len > 2 ? len - 2 : 0);
for (var key = 2; key < len; key++) args[key - 2] = arguments[key];
- if (void 0 === format) throw new Error("` + "`" + `warning(condition, format, ...args)` + "`" + ` requires a warning message argument");
+ if (void 0 === format) throw new Error("` + ("`" + `warning(condition, format, ...args)`)))) + ((("`" + (` requires a warning message argument");
if (format.length < 10 || /^[s\W]*$/.test(format)) throw new Error("The warning format should be able to uniquely identify this warning. Please, use a more descriptive format than: " + format);
if (!condition) {
var argIndex = 0, message = "Warning: " + format.replace(/%s/g, function() {
@@ -792,34 +767,14 @@ var _publicBundleJs = []byte(`!function(modules) {
} catch (x) {}
}
}), module.exports = warning;
- }).call(exports, __webpack_require__(3));
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _dispatchable(methodNames, xf, fn) {
- return function() {
- if (0 === arguments.length) return fn();
- var args = Array.prototype.slice.call(arguments, 0), obj = args.pop();
- if (!Object(__WEBPACK_IMPORTED_MODULE_0__isArray__.a)(obj)) {
- for (var idx = 0; idx < methodNames.length; ) {
- if ("function" == typeof obj[methodNames[idx]]) return obj[methodNames[idx]].apply(obj, args);
- idx += 1;
- }
- if (Object(__WEBPACK_IMPORTED_MODULE_1__isTransformer__.a)(obj)) {
- return xf.apply(null, args)(obj);
- }
- }
- return fn.apply(this, arguments);
- };
- }
- __webpack_exports__.a = _dispatchable;
- var __WEBPACK_IMPORTED_MODULE_0__isArray__ = __webpack_require__(57), __WEBPACK_IMPORTED_MODULE_1__isTransformer__ = __webpack_require__(200);
+ }).call(exports, __webpack_require__(2));
}, function(module, exports) {
var isArray = Array.isArray;
module.exports = isArray;
}, function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = !0;
- var _defineProperty = __webpack_require__(185), _defineProperty2 = function(obj) {
+ var _defineProperty = __webpack_require__(143), _defineProperty2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -845,7 +800,7 @@ var _publicBundleJs = []byte(`!function(modules) {
className: layerClass
}, others), children);
}
- var __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), _extends = Object.assign || function(target) {
+ var __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -856,18 +811,8 @@ var _publicBundleJs = []byte(`!function(modules) {
children: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.oneOfType([ __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.arrayOf(__WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.node), __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.node ])
};
Layer.propTypes = propTypes, __webpack_exports__.a = Layer;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- __webpack_exports__.a = {
- init: function() {
- return this.xf["@@transducer/init"]();
- },
- result: function(result) {
- return this.xf["@@transducer/result"](result);
- }
- };
}, function(module, exports, __webpack_require__) {
- var global = __webpack_require__(221), core = __webpack_require__(222), hide = __webpack_require__(363), redefine = __webpack_require__(839), ctx = __webpack_require__(842), $export = function(type, name, source) {
+ var global = __webpack_require__(158), core = __webpack_require__(159), hide = __webpack_require__(244), redefine = __webpack_require__(534), ctx = __webpack_require__(537), $export = function(type, name, source) {
var key, own, out, exp, IS_FORCED = type & $export.F, IS_GLOBAL = type & $export.G, IS_STATIC = type & $export.S, IS_PROTO = type & $export.P, IS_BIND = type & $export.B, target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {}).prototype, exports = IS_GLOBAL ? core : core[name] || (core[name] = {}), expProto = exports.prototype || (exports.prototype = {});
IS_GLOBAL && (source = name);
for (key in source) own = !IS_FORCED && target && void 0 !== target[key], out = (own ? target : source)[key],
@@ -955,8 +900,8 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "y", function() {
return parseDomainOfCategoryAxis;
});
- var __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__ = __webpack_require__(49), __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_1_lodash_sortBy__ = __webpack_require__(402), __WEBPACK_IMPORTED_MODULE_1_lodash_sortBy___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_sortBy__), __WEBPACK_IMPORTED_MODULE_2_lodash_isNaN__ = __webpack_require__(159), __WEBPACK_IMPORTED_MODULE_2_lodash_isNaN___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isNaN__), __WEBPACK_IMPORTED_MODULE_3_lodash_isString__ = __webpack_require__(227), __WEBPACK_IMPORTED_MODULE_3_lodash_isString___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_isString__), __WEBPACK_IMPORTED_MODULE_4_lodash_max__ = __webpack_require__(1010), __WEBPACK_IMPORTED_MODULE_4_lodash_max___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_lodash_max__), __WEBPACK_IMPORTED_MODULE_5_lodash_min__ = __webpack_require__(405), __WEBPACK_IMPORTED_MODULE_5_lodash_min___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_lodash_min__), __WEBPACK_IMPORTED_MODULE_6_lodash_isArray__ = __webpack_require__(16), __WEBPACK_IMPORTED_MODULE_6_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_7_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_7_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_8_lodash_get__ = __webpack_require__(152), __WEBPACK_IMPORTED_MODULE_8_lodash_get___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_8_lodash_get__), __WEBPACK_IMPORTED_MODULE_9_lodash_isNil__ = __webpack_require__(28), __WEBPACK_IMPORTED_MODULE_9_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_9_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_10_recharts_scale__ = __webpack_require__(1011), __WEBPACK_IMPORTED_MODULE_11_d3_scale__ = (__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_10_recharts_scale__),
- __webpack_require__(408)), __WEBPACK_IMPORTED_MODULE_12_d3_shape__ = __webpack_require__(235), __WEBPACK_IMPORTED_MODULE_13__DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_14__cartesian_ReferenceDot__ = __webpack_require__(441), __WEBPACK_IMPORTED_MODULE_15__cartesian_ReferenceLine__ = __webpack_require__(442), __WEBPACK_IMPORTED_MODULE_16__cartesian_ReferenceArea__ = __webpack_require__(443), __WEBPACK_IMPORTED_MODULE_17__cartesian_ErrorBar__ = __webpack_require__(117), __WEBPACK_IMPORTED_MODULE_18__component_Legend__ = __webpack_require__(233), __WEBPACK_IMPORTED_MODULE_19__ReactUtils__ = __webpack_require__(7), _extends = Object.assign || function(target) {
+ var __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__ = __webpack_require__(34), __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_1_lodash_sortBy__ = __webpack_require__(281), __WEBPACK_IMPORTED_MODULE_1_lodash_sortBy___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_sortBy__), __WEBPACK_IMPORTED_MODULE_2_lodash_isNaN__ = __webpack_require__(117), __WEBPACK_IMPORTED_MODULE_2_lodash_isNaN___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isNaN__), __WEBPACK_IMPORTED_MODULE_3_lodash_isString__ = __webpack_require__(164), __WEBPACK_IMPORTED_MODULE_3_lodash_isString___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_isString__), __WEBPACK_IMPORTED_MODULE_4_lodash_max__ = __webpack_require__(702), __WEBPACK_IMPORTED_MODULE_4_lodash_max___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_lodash_max__), __WEBPACK_IMPORTED_MODULE_5_lodash_min__ = __webpack_require__(284), __WEBPACK_IMPORTED_MODULE_5_lodash_min___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_lodash_min__), __WEBPACK_IMPORTED_MODULE_6_lodash_isArray__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_6_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_7_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_7_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_8_lodash_get__ = __webpack_require__(165), __WEBPACK_IMPORTED_MODULE_8_lodash_get___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_8_lodash_get__), __WEBPACK_IMPORTED_MODULE_9_lodash_isNil__ = __webpack_require__(20), __WEBPACK_IMPORTED_MODULE_9_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_9_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_10_recharts_scale__ = __webpack_require__(703), __WEBPACK_IMPORTED_MODULE_11_d3_scale__ = (__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_10_recharts_scale__),
+ __webpack_require__(287)), __WEBPACK_IMPORTED_MODULE_12_d3_shape__ = __webpack_require__(173), __WEBPACK_IMPORTED_MODULE_13__DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_14__cartesian_ReferenceDot__ = __webpack_require__(320), __WEBPACK_IMPORTED_MODULE_15__cartesian_ReferenceLine__ = __webpack_require__(321), __WEBPACK_IMPORTED_MODULE_16__cartesian_ReferenceArea__ = __webpack_require__(322), __WEBPACK_IMPORTED_MODULE_17__cartesian_ErrorBar__ = __webpack_require__(91), __WEBPACK_IMPORTED_MODULE_18__component_Legend__ = __webpack_require__(171), __WEBPACK_IMPORTED_MODULE_19__ReactUtils__ = __webpack_require__(4), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -1453,12 +1398,6 @@ var _publicBundleJs = []byte(`!function(modules) {
"number" == typeof __e && (__e = core);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_arity__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_1__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_2__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_3__internal_curryN__ = __webpack_require__(135), curryN = Object(__WEBPACK_IMPORTED_MODULE_2__internal_curry2__.a)(function(length, fn) {
- return 1 === length ? Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry1__.a)(fn) : Object(__WEBPACK_IMPORTED_MODULE_0__internal_arity__.a)(length, Object(__WEBPACK_IMPORTED_MODULE_3__internal_curryN__.a)(length, [], fn));
- });
- __webpack_exports__.a = curryN;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
function newInterval(floori, offseti, count, field) {
function interval(date) {
return floori(date = new Date(+date)), date;
@@ -1497,7 +1436,7 @@ var _publicBundleJs = []byte(`!function(modules) {
__webpack_exports__.a = newInterval;
var t0 = new Date(), t1 = new Date();
}, function(module, exports, __webpack_require__) {
- var global = __webpack_require__(36), core = __webpack_require__(22), ctx = __webpack_require__(64), hide = __webpack_require__(56), $export = function(type, name, source) {
+ var global = __webpack_require__(24), core = __webpack_require__(17), ctx = __webpack_require__(47), hide = __webpack_require__(40), $export = function(type, name, source) {
var key, own, out, IS_FORCED = type & $export.F, IS_GLOBAL = type & $export.G, IS_STATIC = type & $export.S, IS_PROTO = type & $export.P, IS_BIND = type & $export.B, IS_WRAP = type & $export.W, exports = IS_GLOBAL ? core : core[name] || (core[name] = {}), expProto = exports.prototype, target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {}).prototype;
IS_GLOBAL && (source = name);
for (key in source) (own = !IS_FORCED && target && void 0 !== target[key]) && key in exports || (out = own ? target[key] : source[key],
@@ -1524,86 +1463,19 @@ var _publicBundleJs = []byte(`!function(modules) {
};
$export.F = 1, $export.G = 2, $export.S = 4, $export.P = 8, $export.B = 16, $export.W = 32,
$export.U = 64, $export.R = 128, module.exports = $export;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _has(prop, obj) {
- return Object.prototype.hasOwnProperty.call(obj, prop);
- }
- __webpack_exports__.a = _has;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_map__ = __webpack_require__(136), __WEBPACK_IMPORTED_MODULE_3__internal_reduce__ = __webpack_require__(30), __WEBPACK_IMPORTED_MODULE_4__internal_xmap__ = __webpack_require__(582), __WEBPACK_IMPORTED_MODULE_5__curryN__ = __webpack_require__(23), __WEBPACK_IMPORTED_MODULE_6__keys__ = __webpack_require__(44), map = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([ "fantasy-land/map", "map" ], __WEBPACK_IMPORTED_MODULE_4__internal_xmap__.a, function(fn, functor) {
- switch (Object.prototype.toString.call(functor)) {
- case "[object Function]":
- return Object(__WEBPACK_IMPORTED_MODULE_5__curryN__.a)(functor.length, function() {
- return fn.call(this, functor.apply(this, arguments));
- });
-
- case "[object Object]":
- return Object(__WEBPACK_IMPORTED_MODULE_3__internal_reduce__.a)(function(acc, key) {
- return acc[key] = fn(functor[key]), acc;
- }, {}, Object(__WEBPACK_IMPORTED_MODULE_6__keys__.a)(functor));
-
- default:
- return Object(__WEBPACK_IMPORTED_MODULE_2__internal_map__.a)(fn, functor);
- }
- }));
- __webpack_exports__.a = map;
}, function(module, exports) {
function isNil(value) {
return null == value;
}
module.exports = isNil;
}, function(module, exports, __webpack_require__) {
- var store = __webpack_require__(182)("wks"), uid = __webpack_require__(124), Symbol = __webpack_require__(36).Symbol, USE_SYMBOL = "function" == typeof Symbol;
+ var store = __webpack_require__(140)("wks"), uid = __webpack_require__(98), Symbol = __webpack_require__(24).Symbol, USE_SYMBOL = "function" == typeof Symbol;
(module.exports = function(name) {
return store[name] || (store[name] = USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)("Symbol." + name));
}).store = store;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _arrayReduce(xf, acc, list) {
- for (var idx = 0, len = list.length; idx < len; ) {
- if ((acc = xf["@@transducer/step"](acc, list[idx])) && acc["@@transducer/reduced"]) {
- acc = acc["@@transducer/value"];
- break;
- }
- idx += 1;
- }
- return xf["@@transducer/result"](acc);
- }
- function _iterableReduce(xf, acc, iter) {
- for (var step = iter.next(); !step.done; ) {
- if ((acc = xf["@@transducer/step"](acc, step.value)) && acc["@@transducer/reduced"]) {
- acc = acc["@@transducer/value"];
- break;
- }
- step = iter.next();
- }
- return xf["@@transducer/result"](acc);
- }
- function _methodReduce(xf, acc, obj, methodName) {
- return xf["@@transducer/result"](obj[methodName](Object(__WEBPACK_IMPORTED_MODULE_2__bind__.a)(xf["@@transducer/step"], xf), acc));
- }
- function _reduce(fn, acc, list) {
- if ("function" == typeof fn && (fn = Object(__WEBPACK_IMPORTED_MODULE_1__xwrap__.a)(fn)),
- Object(__WEBPACK_IMPORTED_MODULE_0__isArrayLike__.a)(list)) return _arrayReduce(fn, acc, list);
- if ("function" == typeof list["fantasy-land/reduce"]) return _methodReduce(fn, acc, list, "fantasy-land/reduce");
- if (null != list[symIterator]) return _iterableReduce(fn, acc, list[symIterator]());
- if ("function" == typeof list.next) return _iterableReduce(fn, acc, list);
- if ("function" == typeof list.reduce) return _methodReduce(fn, acc, list, "reduce");
- throw new TypeError("reduce: list must be array or iterable");
- }
- __webpack_exports__.a = _reduce;
- var __WEBPACK_IMPORTED_MODULE_0__isArrayLike__ = __webpack_require__(137), __WEBPACK_IMPORTED_MODULE_1__xwrap__ = __webpack_require__(298), __WEBPACK_IMPORTED_MODULE_2__bind__ = __webpack_require__(299), symIterator = "undefined" != typeof Symbol ? Symbol.iterator : "@@iterator";
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_equals__ = __webpack_require__(605), equals = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__internal_equals__.a)(a, b, [], []);
- });
- __webpack_exports__.a = equals;
}, function(module, exports, __webpack_require__) {
- var anObject = __webpack_require__(65), IE8_DOM_DEFINE = __webpack_require__(270), toPrimitive = __webpack_require__(176), dP = Object.defineProperty;
- exports.f = __webpack_require__(37) ? Object.defineProperty : function(O, P, Attributes) {
+ var anObject = __webpack_require__(48), IE8_DOM_DEFINE = __webpack_require__(207), toPrimitive = __webpack_require__(134), dP = Object.defineProperty;
+ exports.f = __webpack_require__(25) ? Object.defineProperty : function(O, P, Attributes) {
if (anObject(O), P = toPrimitive(P, !0), anObject(Attributes), IE8_DOM_DEFINE) try {
return dP(O, P, Attributes);
} catch (e) {}
@@ -1612,22 +1484,6 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- function _concat(set1, set2) {
- set1 = set1 || [], set2 = set2 || [];
- var idx, len1 = set1.length, len2 = set2.length, result = [];
- for (idx = 0; idx < len1; ) result[result.length] = set1[idx], idx += 1;
- for (idx = 0; idx < len2; ) result[result.length] = set2[idx], idx += 1;
- return result;
- }
- __webpack_exports__.a = _concat;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_checkForMethod__ = __webpack_require__(99), __WEBPACK_IMPORTED_MODULE_1__internal_curry3__ = __webpack_require__(5), slice = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry3__.a)(Object(__WEBPACK_IMPORTED_MODULE_0__internal_checkForMethod__.a)("slice", function(fromIndex, toIndex, list) {
- return Array.prototype.slice.call(list, fromIndex, toIndex);
- }));
- __webpack_exports__.a = slice;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
function _defineProperty(obj, key, value) {
return key in obj ? Object.defineProperty(obj, key, {
value: value,
@@ -1647,7 +1503,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "d", function() {
return inRangeOfSector;
});
- var __WEBPACK_IMPORTED_MODULE_0_lodash_isNil__ = __webpack_require__(28), __WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_1__DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_2__ChartUtils__ = __webpack_require__(21), _extends = Object.assign || function(target) {
+ var __WEBPACK_IMPORTED_MODULE_0_lodash_isNil__ = __webpack_require__(20), __WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_1__DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_2__ChartUtils__ = __webpack_require__(16), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -1748,7 +1604,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var global = module.exports = "undefined" != typeof window && window.Math == Math ? window : "undefined" != typeof self && self.Math == Math ? self : Function("return this")();
"number" == typeof __g && (__g = global);
}, function(module, exports, __webpack_require__) {
- module.exports = !__webpack_require__(66)(function() {
+ module.exports = !__webpack_require__(49)(function() {
return 7 != Object.defineProperty({}, "a", {
get: function() {
return 7;
@@ -1757,7 +1613,7 @@ var _publicBundleJs = []byte(`!function(modules) {
});
}, function(module, exports, __webpack_require__) {
module.exports = {
- default: __webpack_require__(472),
+ default: __webpack_require__(350),
__esModule: !0
};
}, function(module, exports, __webpack_require__) {
@@ -1768,7 +1624,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = !0;
- var _defineProperty = __webpack_require__(185), _defineProperty2 = function(obj) {
+ var _defineProperty = __webpack_require__(143), _defineProperty2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -1789,7 +1645,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = !0;
- var _typeof2 = __webpack_require__(126), _typeof3 = function(obj) {
+ var _typeof2 = __webpack_require__(100), _typeof3 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -1806,7 +1662,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}
exports.__esModule = !0;
- var _setPrototypeOf = __webpack_require__(489), _setPrototypeOf2 = _interopRequireDefault(_setPrototypeOf), _create = __webpack_require__(493), _create2 = _interopRequireDefault(_create), _typeof2 = __webpack_require__(126), _typeof3 = _interopRequireDefault(_typeof2);
+ var _setPrototypeOf = __webpack_require__(367), _setPrototypeOf2 = _interopRequireDefault(_setPrototypeOf), _create = __webpack_require__(371), _create2 = _interopRequireDefault(_create), _typeof2 = __webpack_require__(100), _typeof3 = _interopRequireDefault(_typeof2);
exports.default = function(subClass, superClass) {
if ("function" != typeof superClass && null !== superClass) throw new TypeError("Super expression must either be null or a function, not " + (void 0 === superClass ? "undefined" : (0,
_typeof3.default)(superClass)));
@@ -1819,101 +1675,6 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (_setPrototypeOf2.default ? (0, _setPrototypeOf2.default)(subClass, superClass) : subClass.__proto__ = superClass);
};
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _arity(n, fn) {
- switch (n) {
- case 0:
- return function() {
- return fn.apply(this, arguments);
- };
-
- case 1:
- return function(a0) {
- return fn.apply(this, arguments);
- };
-
- case 2:
- return function(a0, a1) {
- return fn.apply(this, arguments);
- };
-
- case 3:
- return function(a0, a1, a2) {
- return fn.apply(this, arguments);
- };
-
- case 4:
- return function(a0, a1, a2, a3) {
- return fn.apply(this, arguments);
- };
-
- case 5:
- return function(a0, a1, a2, a3, a4) {
- return fn.apply(this, arguments);
- };
-
- case 6:
- return function(a0, a1, a2, a3, a4, a5) {
- return fn.apply(this, arguments);
- };
-
- case 7:
- return function(a0, a1, a2, a3, a4, a5, a6) {
- return fn.apply(this, arguments);
- };
-
- case 8:
- return function(a0, a1, a2, a3, a4, a5, a6, a7) {
- return fn.apply(this, arguments);
- };
-
- case 9:
- return function(a0, a1, a2, a3, a4, a5, a6, a7, a8) {
- return fn.apply(this, arguments);
- };
-
- case 10:
- return function(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
- return fn.apply(this, arguments);
- };
-
- default:
- throw new Error("First argument to _arity must be a non-negative integer no greater than ten");
- }
- }
- __webpack_exports__.a = _arity;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__internal_has__ = __webpack_require__(26), __WEBPACK_IMPORTED_MODULE_2__internal_isArguments__ = __webpack_require__(300), hasEnumBug = !{
- toString: null
- }.propertyIsEnumerable("toString"), nonEnumerableProps = [ "constructor", "valueOf", "isPrototypeOf", "toString", "propertyIsEnumerable", "hasOwnProperty", "toLocaleString" ], hasArgsEnumBug = function() {
- return arguments.propertyIsEnumerable("length");
- }(), contains = function(list, item) {
- for (var idx = 0; idx < list.length; ) {
- if (list[idx] === item) return !0;
- idx += 1;
- }
- return !1;
- }, _keys = "function" != typeof Object.keys || hasArgsEnumBug ? function(obj) {
- if (Object(obj) !== obj) return [];
- var prop, nIdx, ks = [], checkArgsLength = hasArgsEnumBug && Object(__WEBPACK_IMPORTED_MODULE_2__internal_isArguments__.a)(obj);
- for (prop in obj) !Object(__WEBPACK_IMPORTED_MODULE_1__internal_has__.a)(prop, obj) || checkArgsLength && "length" === prop || (ks[ks.length] = prop);
- if (hasEnumBug) for (nIdx = nonEnumerableProps.length - 1; nIdx >= 0; ) prop = nonEnumerableProps[nIdx],
- Object(__WEBPACK_IMPORTED_MODULE_1__internal_has__.a)(prop, obj) && !contains(ks, prop) && (ks[ks.length] = prop),
- nIdx -= 1;
- return ks;
- } : function(obj) {
- return Object(obj) !== obj ? [] : Object.keys(obj);
- }, keys = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(_keys);
- __webpack_exports__.a = keys;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__internal_reduce__ = __webpack_require__(30), reduce = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(__WEBPACK_IMPORTED_MODULE_1__internal_reduce__.a);
- __webpack_exports__.a = reduce;
-}, function(module, exports, __webpack_require__) {
- var freeGlobal = __webpack_require__(365), freeSelf = "object" == typeof self && self && self.Object === Object && self, root = freeGlobal || freeSelf || Function("return this")();
- module.exports = root;
}, function(module, exports) {
function isObject(value) {
var type = typeof value;
@@ -1921,6 +1682,9 @@ var _publicBundleJs = []byte(`!function(modules) {
}
module.exports = isObject;
}, function(module, exports, __webpack_require__) {
+ var freeGlobal = __webpack_require__(242), freeSelf = "object" == typeof self && self && self.Object === Object && self, root = freeGlobal || freeSelf || Function("return this")();
+ module.exports = root;
+}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
@@ -1930,7 +1694,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.translateStyle = exports.AnimateGroup = exports.configBezier = exports.configSpring = void 0;
- var _Animate = __webpack_require__(383), _Animate2 = _interopRequireDefault(_Animate), _easing = __webpack_require__(395), _util = __webpack_require__(165), _AnimateGroup = __webpack_require__(986), _AnimateGroup2 = _interopRequireDefault(_AnimateGroup);
+ var _Animate = __webpack_require__(263), _Animate2 = _interopRequireDefault(_Animate), _easing = __webpack_require__(275), _util = __webpack_require__(123), _AnimateGroup = __webpack_require__(679), _AnimateGroup2 = _interopRequireDefault(_AnimateGroup);
exports.configSpring = _easing.configSpring, exports.configBezier = _easing.configBezier,
exports.AnimateGroup = _AnimateGroup2.default, exports.translateStyle = _util.translateStyle,
exports.default = _Animate2.default;
@@ -1938,17 +1702,12 @@ var _publicBundleJs = []byte(`!function(modules) {
function isEqual(value, other) {
return baseIsEqual(value, other);
}
- var baseIsEqual = __webpack_require__(240);
+ var baseIsEqual = __webpack_require__(178);
module.exports = isEqual;
}, function(module, exports) {
module.exports = function(it) {
return "object" == typeof it ? null !== it : "function" == typeof it;
};
-}, function(module, exports, __webpack_require__) {
- module.exports = {
- default: __webpack_require__(500),
- __esModule: !0
- };
}, function(module, exports) {
function isObjectLike(value) {
return null != value && "object" == typeof value;
@@ -1956,32 +1715,32 @@ var _publicBundleJs = []byte(`!function(modules) {
module.exports = isObjectLike;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__src_bisect__ = __webpack_require__(409);
+ var __WEBPACK_IMPORTED_MODULE_0__src_bisect__ = __webpack_require__(288);
__webpack_require__.d(__webpack_exports__, "b", function() {
return __WEBPACK_IMPORTED_MODULE_0__src_bisect__.a;
});
- var __WEBPACK_IMPORTED_MODULE_1__src_ascending__ = __webpack_require__(84);
+ var __WEBPACK_IMPORTED_MODULE_1__src_ascending__ = __webpack_require__(64);
__webpack_require__.d(__webpack_exports__, "a", function() {
return __WEBPACK_IMPORTED_MODULE_1__src_ascending__.a;
});
- var __WEBPACK_IMPORTED_MODULE_2__src_bisector__ = __webpack_require__(410);
+ var __WEBPACK_IMPORTED_MODULE_2__src_bisector__ = __webpack_require__(289);
__webpack_require__.d(__webpack_exports__, "c", function() {
return __WEBPACK_IMPORTED_MODULE_2__src_bisector__.a;
});
- var __WEBPACK_IMPORTED_MODULE_18__src_quantile__ = (__webpack_require__(1015), __webpack_require__(1016),
- __webpack_require__(412), __webpack_require__(414), __webpack_require__(1017), __webpack_require__(1020),
- __webpack_require__(1021), __webpack_require__(418), __webpack_require__(1022),
- __webpack_require__(1023), __webpack_require__(1024), __webpack_require__(1025),
- __webpack_require__(419), __webpack_require__(411), __webpack_require__(1026), __webpack_require__(248));
+ var __WEBPACK_IMPORTED_MODULE_18__src_quantile__ = (__webpack_require__(707), __webpack_require__(708),
+ __webpack_require__(291), __webpack_require__(293), __webpack_require__(709), __webpack_require__(712),
+ __webpack_require__(713), __webpack_require__(297), __webpack_require__(714), __webpack_require__(715),
+ __webpack_require__(716), __webpack_require__(717), __webpack_require__(298), __webpack_require__(290),
+ __webpack_require__(718), __webpack_require__(185));
__webpack_require__.d(__webpack_exports__, "d", function() {
return __WEBPACK_IMPORTED_MODULE_18__src_quantile__.a;
});
- var __WEBPACK_IMPORTED_MODULE_19__src_range__ = __webpack_require__(416);
+ var __WEBPACK_IMPORTED_MODULE_19__src_range__ = __webpack_require__(295);
__webpack_require__.d(__webpack_exports__, "e", function() {
return __WEBPACK_IMPORTED_MODULE_19__src_range__.a;
});
- var __WEBPACK_IMPORTED_MODULE_23__src_ticks__ = (__webpack_require__(1027), __webpack_require__(1028),
- __webpack_require__(1029), __webpack_require__(417));
+ var __WEBPACK_IMPORTED_MODULE_23__src_ticks__ = (__webpack_require__(719), __webpack_require__(720),
+ __webpack_require__(721), __webpack_require__(296));
__webpack_require__.d(__webpack_exports__, "h", function() {
return __WEBPACK_IMPORTED_MODULE_23__src_ticks__.a;
}), __webpack_require__.d(__webpack_exports__, "f", function() {
@@ -1989,7 +1748,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "g", function() {
return __WEBPACK_IMPORTED_MODULE_23__src_ticks__.c;
});
- __webpack_require__(420), __webpack_require__(413), __webpack_require__(1030);
+ __webpack_require__(299), __webpack_require__(292), __webpack_require__(722);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.d(__webpack_exports__, "d", function() {
@@ -2020,31 +1779,22 @@ var _publicBundleJs = []byte(`!function(modules) {
return arg;
}, module.exports = emptyFunction;
}, function(module, exports, __webpack_require__) {
- var dP = __webpack_require__(32), createDesc = __webpack_require__(91);
- module.exports = __webpack_require__(37) ? function(object, key, value) {
+ var dP = __webpack_require__(22), createDesc = __webpack_require__(71);
+ module.exports = __webpack_require__(25) ? function(object, key, value) {
return dP.f(object, key, createDesc(1, value));
} : function(object, key, value) {
return object[key] = value, object;
};
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- __webpack_exports__.a = Array.isArray || function(val) {
- return null != val && val.length >= 0 && "[object Array]" === Object.prototype.toString.call(val);
+}, function(module, exports, __webpack_require__) {
+ module.exports = {
+ default: __webpack_require__(378),
+ __esModule: !0
};
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _reduced(x) {
- return x && x["@@transducer/reduced"] ? x : {
- "@@transducer/value": x,
- "@@transducer/reduced": !0
- };
- }
- __webpack_exports__.a = _reduced;
}, function(module, exports, __webpack_require__) {
function baseGetTag(value) {
return null == value ? void 0 === value ? undefinedTag : nullTag : symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value);
}
- var Symbol = __webpack_require__(104), getRawTag = __webpack_require__(861), objectToString = __webpack_require__(862), nullTag = "[object Null]", undefinedTag = "[object Undefined]", symToStringTag = Symbol ? Symbol.toStringTag : void 0;
+ var Symbol = __webpack_require__(77), getRawTag = __webpack_require__(520), objectToString = __webpack_require__(521), nullTag = "[object Null]", undefinedTag = "[object Undefined]", symToStringTag = Symbol ? Symbol.toStringTag : void 0;
module.exports = baseGetTag;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -2070,7 +1820,7 @@ var _publicBundleJs = []byte(`!function(modules) {
className: __WEBPACK_IMPORTED_MODULE_5_classnames___default()("recharts-label", className)
}, attrs, positionAttrs), label);
}
- var __WEBPACK_IMPORTED_MODULE_0_lodash_isObject__ = __webpack_require__(47), __WEBPACK_IMPORTED_MODULE_0_lodash_isObject___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isObject__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil__ = __webpack_require__(28), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_3_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_3_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_react__), __WEBPACK_IMPORTED_MODULE_4_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_4_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_prop_types__), __WEBPACK_IMPORTED_MODULE_5_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_5_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_classnames__), __WEBPACK_IMPORTED_MODULE_6__Text__ = __webpack_require__(72), __WEBPACK_IMPORTED_MODULE_7__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_8__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_9__util_PolarUtils__ = __webpack_require__(35), _extends = Object.assign || function(target) {
+ var __WEBPACK_IMPORTED_MODULE_0_lodash_isObject__ = __webpack_require__(31), __WEBPACK_IMPORTED_MODULE_0_lodash_isObject___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isObject__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil__ = __webpack_require__(20), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_3_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_3_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_react__), __WEBPACK_IMPORTED_MODULE_4_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_4_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_prop_types__), __WEBPACK_IMPORTED_MODULE_5_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_5_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_classnames__), __WEBPACK_IMPORTED_MODULE_6__Text__ = __webpack_require__(55), __WEBPACK_IMPORTED_MODULE_7__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_8__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_9__util_PolarUtils__ = __webpack_require__(23), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -2282,7 +2032,7 @@ var _publicBundleJs = []byte(`!function(modules) {
__webpack_exports__.a = Label;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__src_color__ = __webpack_require__(251);
+ var __WEBPACK_IMPORTED_MODULE_0__src_color__ = __webpack_require__(188);
__webpack_require__.d(__webpack_exports__, "a", function() {
return __WEBPACK_IMPORTED_MODULE_0__src_color__.e;
}), __webpack_require__.d(__webpack_exports__, "f", function() {
@@ -2290,13 +2040,13 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "d", function() {
return __WEBPACK_IMPORTED_MODULE_0__src_color__.f;
});
- var __WEBPACK_IMPORTED_MODULE_1__src_lab__ = __webpack_require__(1038);
+ var __WEBPACK_IMPORTED_MODULE_1__src_lab__ = __webpack_require__(730);
__webpack_require__.d(__webpack_exports__, "e", function() {
return __WEBPACK_IMPORTED_MODULE_1__src_lab__.a;
}), __webpack_require__.d(__webpack_exports__, "c", function() {
return __WEBPACK_IMPORTED_MODULE_1__src_lab__.b;
});
- var __WEBPACK_IMPORTED_MODULE_2__src_cubehelix__ = __webpack_require__(1039);
+ var __WEBPACK_IMPORTED_MODULE_2__src_cubehelix__ = __webpack_require__(731);
__webpack_require__.d(__webpack_exports__, "b", function() {
return __WEBPACK_IMPORTED_MODULE_2__src_cubehelix__.a;
});
@@ -2332,7 +2082,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}));
})) : null;
}
- var __WEBPACK_IMPORTED_MODULE_0_lodash_isObject__ = __webpack_require__(47), __WEBPACK_IMPORTED_MODULE_0_lodash_isObject___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isObject__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil__ = __webpack_require__(28), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_3_lodash_last__ = __webpack_require__(1089), __WEBPACK_IMPORTED_MODULE_3_lodash_last___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_last__), __WEBPACK_IMPORTED_MODULE_4_lodash_isArray__ = __webpack_require__(16), __WEBPACK_IMPORTED_MODULE_4_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_5_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_5_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_react__), __WEBPACK_IMPORTED_MODULE_6_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_6_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_prop_types__), __WEBPACK_IMPORTED_MODULE_7__Label__ = __webpack_require__(60), __WEBPACK_IMPORTED_MODULE_8__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_9__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_10__util_ChartUtils__ = __webpack_require__(21), _extends = Object.assign || function(target) {
+ var __WEBPACK_IMPORTED_MODULE_0_lodash_isObject__ = __webpack_require__(31), __WEBPACK_IMPORTED_MODULE_0_lodash_isObject___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isObject__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil__ = __webpack_require__(20), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_3_lodash_last__ = __webpack_require__(781), __WEBPACK_IMPORTED_MODULE_3_lodash_last___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_last__), __WEBPACK_IMPORTED_MODULE_4_lodash_isArray__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_4_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_5_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_5_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_react__), __WEBPACK_IMPORTED_MODULE_6_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_6_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_prop_types__), __WEBPACK_IMPORTED_MODULE_7__Label__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_8__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_9__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_10__util_ChartUtils__ = __webpack_require__(16), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -2416,7 +2166,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var __WEBPACK_IMPORTED_MODULE_0_lodash_sortBy__ = __webpack_require__(402), __WEBPACK_IMPORTED_MODULE_0_lodash_sortBy___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_sortBy__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_lodash_get__ = __webpack_require__(152), __WEBPACK_IMPORTED_MODULE_2_lodash_get___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_get__), __WEBPACK_IMPORTED_MODULE_3_lodash_range__ = __webpack_require__(450), __WEBPACK_IMPORTED_MODULE_3_lodash_range___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_range__), __WEBPACK_IMPORTED_MODULE_4_lodash_throttle__ = __webpack_require__(1097), __WEBPACK_IMPORTED_MODULE_4_lodash_throttle___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_lodash_throttle__), __WEBPACK_IMPORTED_MODULE_5_lodash_isNil__ = __webpack_require__(28), __WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_6_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_6_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_react__), __WEBPACK_IMPORTED_MODULE_7_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_7_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_prop_types__), __WEBPACK_IMPORTED_MODULE_8_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_8_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_8_classnames__), __WEBPACK_IMPORTED_MODULE_9__container_Surface__ = __webpack_require__(103), __WEBPACK_IMPORTED_MODULE_10__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_11__component_Tooltip__ = __webpack_require__(164), __WEBPACK_IMPORTED_MODULE_12__component_Legend__ = __webpack_require__(233), __WEBPACK_IMPORTED_MODULE_13__shape_Curve__ = __webpack_require__(86), __WEBPACK_IMPORTED_MODULE_14__shape_Cross__ = __webpack_require__(444), __WEBPACK_IMPORTED_MODULE_15__shape_Sector__ = __webpack_require__(170), __WEBPACK_IMPORTED_MODULE_16__shape_Dot__ = __webpack_require__(74), __WEBPACK_IMPORTED_MODULE_17__shape_Rectangle__ = __webpack_require__(85), __WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_19__cartesian_CartesianAxis__ = __webpack_require__(451), __WEBPACK_IMPORTED_MODULE_20__cartesian_Brush__ = __webpack_require__(449), __WEBPACK_IMPORTED_MODULE_21__util_DOMUtils__ = __webpack_require__(247), __WEBPACK_IMPORTED_MODULE_22__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__ = __webpack_require__(21), __WEBPACK_IMPORTED_MODULE_24__util_PolarUtils__ = __webpack_require__(35), __WEBPACK_IMPORTED_MODULE_25__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_26__util_Events__ = __webpack_require__(1098), _extends = Object.assign || function(target) {
+ var __WEBPACK_IMPORTED_MODULE_0_lodash_sortBy__ = __webpack_require__(281), __WEBPACK_IMPORTED_MODULE_0_lodash_sortBy___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_sortBy__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_lodash_range__ = __webpack_require__(329), __WEBPACK_IMPORTED_MODULE_2_lodash_range___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_range__), __WEBPACK_IMPORTED_MODULE_3_lodash_throttle__ = __webpack_require__(790), __WEBPACK_IMPORTED_MODULE_3_lodash_throttle___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_throttle__), __WEBPACK_IMPORTED_MODULE_4_lodash_isNil__ = __webpack_require__(20), __WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_5_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_5_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_react__), __WEBPACK_IMPORTED_MODULE_6_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_6_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_prop_types__), __WEBPACK_IMPORTED_MODULE_7_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_7_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_classnames__), __WEBPACK_IMPORTED_MODULE_8__container_Surface__ = __webpack_require__(78), __WEBPACK_IMPORTED_MODULE_9__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_10__component_Tooltip__ = __webpack_require__(122), __WEBPACK_IMPORTED_MODULE_11__component_Legend__ = __webpack_require__(171), __WEBPACK_IMPORTED_MODULE_12__shape_Curve__ = __webpack_require__(66), __WEBPACK_IMPORTED_MODULE_13__shape_Cross__ = __webpack_require__(323), __WEBPACK_IMPORTED_MODULE_14__shape_Sector__ = __webpack_require__(128), __WEBPACK_IMPORTED_MODULE_15__shape_Dot__ = __webpack_require__(57), __WEBPACK_IMPORTED_MODULE_16__shape_Rectangle__ = __webpack_require__(65), __WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_18__cartesian_CartesianAxis__ = __webpack_require__(330), __WEBPACK_IMPORTED_MODULE_19__cartesian_Brush__ = __webpack_require__(328), __WEBPACK_IMPORTED_MODULE_20__util_DOMUtils__ = __webpack_require__(184), __WEBPACK_IMPORTED_MODULE_21__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__ = __webpack_require__(16), __WEBPACK_IMPORTED_MODULE_23__util_PolarUtils__ = __webpack_require__(23), __WEBPACK_IMPORTED_MODULE_24__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_25__util_Events__ = __webpack_require__(791), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -2454,22 +2204,22 @@ var _publicBundleJs = []byte(`!function(modules) {
props: props
}, defaultState, {
updateId: 0
- }))), _this.uniqueChartId = __WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(props.id) ? Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.j)("recharts") : props.id,
- props.throttleDelay && (_this.triggeredAfterMouseMove = __WEBPACK_IMPORTED_MODULE_4_lodash_throttle___default()(_this.triggeredAfterMouseMove, props.throttleDelay)),
+ }))), _this.uniqueChartId = __WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(props.id) ? Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.j)("recharts") : props.id,
+ props.throttleDelay && (_this.triggeredAfterMouseMove = __WEBPACK_IMPORTED_MODULE_3_lodash_throttle___default()(_this.triggeredAfterMouseMove, props.throttleDelay)),
_this;
}
return _inherits(CategoricalChartWrapper, _Component), _createClass(CategoricalChartWrapper, [ {
key: "componentDidMount",
value: function() {
- __WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(this.props.syncId) || this.addListener();
+ __WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(this.props.syncId) || this.addListener();
}
}, {
key: "componentWillReceiveProps",
value: function(nextProps) {
var _props = this.props, data = _props.data, children = _props.children, width = _props.width, height = _props.height, layout = _props.layout, stackOffset = _props.stackOffset, margin = _props.margin, updateId = this.state.updateId;
- if (nextProps.data === data && nextProps.width === width && nextProps.height === height && nextProps.layout === layout && nextProps.stackOffset === stackOffset && Object(__WEBPACK_IMPORTED_MODULE_25__util_PureRender__.b)(nextProps.margin, margin)) {
- if (!Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.m)(nextProps.children, children)) {
- var hasGlobalData = !__WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(nextProps.data), newUpdateId = hasGlobalData ? updateId : updateId + 1, _state = this.state, dataStartIndex = _state.dataStartIndex, dataEndIndex = _state.dataEndIndex, _defaultState = _extends({}, this.constructor.createDefaultState(nextProps), {
+ if (nextProps.data === data && nextProps.width === width && nextProps.height === height && nextProps.layout === layout && nextProps.stackOffset === stackOffset && Object(__WEBPACK_IMPORTED_MODULE_24__util_PureRender__.b)(nextProps.margin, margin)) {
+ if (!Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.m)(nextProps.children, children)) {
+ var hasGlobalData = !__WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(nextProps.data), newUpdateId = hasGlobalData ? updateId : updateId + 1, _state = this.state, dataStartIndex = _state.dataStartIndex, dataEndIndex = _state.dataEndIndex, _defaultState = _extends({}, this.constructor.createDefaultState(nextProps), {
dataEndIndex: dataEndIndex,
dataStartIndex: dataStartIndex
});
@@ -2491,19 +2241,19 @@ var _publicBundleJs = []byte(`!function(modules) {
updateId: updateId + 1
}))));
}
- __WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(this.props.syncId) && !__WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(nextProps.syncId) && this.addListener(),
- !__WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(this.props.syncId) && __WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(nextProps.syncId) && this.removeListener();
+ __WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(this.props.syncId) && !__WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(nextProps.syncId) && this.addListener(),
+ !__WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(this.props.syncId) && __WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(nextProps.syncId) && this.removeListener();
}
}, {
key: "componentWillUnmount",
value: function() {
- __WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(this.props.syncId) || this.removeListener(),
+ __WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(this.props.syncId) || this.removeListener(),
"function" == typeof this.triggeredAfterMouseMove.cancel && this.triggeredAfterMouseMove.cancel();
}
}, {
key: "getAxisMap",
value: function(props, _ref2) {
- var _ref2$axisType = _ref2.axisType, axisType = void 0 === _ref2$axisType ? "xAxis" : _ref2$axisType, AxisComp = _ref2.AxisComp, graphicalItems = _ref2.graphicalItems, stackGroups = _ref2.stackGroups, dataStartIndex = _ref2.dataStartIndex, dataEndIndex = _ref2.dataEndIndex, children = props.children, axisIdKey = axisType + "Id", axes = Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.h)(children, AxisComp), axisMap = {};
+ var _ref2$axisType = _ref2.axisType, axisType = void 0 === _ref2$axisType ? "xAxis" : _ref2$axisType, AxisComp = _ref2.AxisComp, graphicalItems = _ref2.graphicalItems, stackGroups = _ref2.stackGroups, dataStartIndex = _ref2.dataStartIndex, dataEndIndex = _ref2.dataEndIndex, children = props.children, axisIdKey = axisType + "Id", axes = Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.h)(children, AxisComp), axisMap = {};
return axes && axes.length ? axisMap = this.getAxisMapByAxes(props, {
axes: axes,
graphicalItems: graphicalItems,
@@ -2525,7 +2275,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, {
key: "getAxisMapByAxes",
value: function(props, _ref3) {
- var _this2 = this, axes = _ref3.axes, graphicalItems = _ref3.graphicalItems, axisType = _ref3.axisType, axisIdKey = _ref3.axisIdKey, stackGroups = _ref3.stackGroups, dataStartIndex = _ref3.dataStartIndex, dataEndIndex = _ref3.dataEndIndex, layout = props.layout, children = props.children, stackOffset = props.stackOffset, isCategorial = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.x)(layout, axisType);
+ var _this2 = this, axes = _ref3.axes, graphicalItems = _ref3.graphicalItems, axisType = _ref3.axisType, axisIdKey = _ref3.axisIdKey, stackGroups = _ref3.stackGroups, dataStartIndex = _ref3.dataStartIndex, dataEndIndex = _ref3.dataEndIndex, layout = props.layout, children = props.children, stackOffset = props.stackOffset, isCategorial = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.x)(layout, axisType);
return axes.reduce(function(result, child) {
var _child$props = child.props, type = _child$props.type, dataKey = _child$props.dataKey, allowDataOverflow = _child$props.allowDataOverflow, allowDuplicatedCategory = _child$props.allowDuplicatedCategory, scale = _child$props.scale, ticks = _child$props.ticks, axisId = child.props[axisIdKey], displayedData = _this2.constructor.getDisplayedData(props, {
graphicalItems: graphicalItems.filter(function(item) {
@@ -2537,28 +2287,28 @@ var _publicBundleJs = []byte(`!function(modules) {
if (!result[axisId]) {
var domain = void 0, duplicateDomain = void 0, categoricalDomain = void 0;
if (dataKey) {
- if (domain = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.n)(displayedData, dataKey, type),
+ if (domain = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.n)(displayedData, dataKey, type),
"category" === type && isCategorial) {
- var duplicate = Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.d)(domain);
- allowDuplicatedCategory && duplicate ? (duplicateDomain = domain, domain = __WEBPACK_IMPORTED_MODULE_3_lodash_range___default()(0, len)) : allowDuplicatedCategory || (domain = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.y)(child.props.domain, domain, child).reduce(function(finalDomain, entry) {
+ var duplicate = Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.d)(domain);
+ allowDuplicatedCategory && duplicate ? (duplicateDomain = domain, domain = __WEBPACK_IMPORTED_MODULE_2_lodash_range___default()(0, len)) : allowDuplicatedCategory || (domain = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.y)(child.props.domain, domain, child).reduce(function(finalDomain, entry) {
return finalDomain.indexOf(entry) >= 0 ? finalDomain : [].concat(_toConsumableArray(finalDomain), [ entry ]);
}, []));
} else if ("category" === type) domain = allowDuplicatedCategory ? domain.filter(function(entry) {
- return "" !== entry && !__WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(entry);
- }) : Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.y)(child.props.domain, domain, child).reduce(function(finalDomain, entry) {
- return finalDomain.indexOf(entry) >= 0 || "" === entry || __WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(entry) ? finalDomain : [].concat(_toConsumableArray(finalDomain), [ entry ]);
+ return "" !== entry && !__WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(entry);
+ }) : Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.y)(child.props.domain, domain, child).reduce(function(finalDomain, entry) {
+ return finalDomain.indexOf(entry) >= 0 || "" === entry || __WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(entry) ? finalDomain : [].concat(_toConsumableArray(finalDomain), [ entry ]);
}, []); else if ("number" === type) {
- var errorBarsDomain = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.z)(displayedData, graphicalItems.filter(function(item) {
+ var errorBarsDomain = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.z)(displayedData, graphicalItems.filter(function(item) {
return item.props[axisIdKey] === axisId && !item.props.hide;
}), dataKey, axisType);
errorBarsDomain && (domain = errorBarsDomain);
}
- !isCategorial || "number" !== type && "auto" === scale || (categoricalDomain = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.n)(displayedData, dataKey, "category"));
- } else domain = isCategorial ? __WEBPACK_IMPORTED_MODULE_3_lodash_range___default()(0, len) : stackGroups && stackGroups[axisId] && stackGroups[axisId].hasStack && "number" === type ? "expand" === stackOffset ? [ 0, 1 ] : Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.p)(stackGroups[axisId].stackGroups, dataStartIndex, dataEndIndex) : Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.o)(displayedData, graphicalItems.filter(function(item) {
+ !isCategorial || "number" !== type && "auto" === scale || (categoricalDomain = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.n)(displayedData, dataKey, "category"));
+ } else domain = isCategorial ? __WEBPACK_IMPORTED_MODULE_2_lodash_range___default()(0, len) : stackGroups && stackGroups[axisId] && stackGroups[axisId].hasStack && "number" === type ? "expand" === stackOffset ? [ 0, 1 ] : Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.p)(stackGroups[axisId].stackGroups, dataStartIndex, dataEndIndex) : Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.o)(displayedData, graphicalItems.filter(function(item) {
return item.props[axisIdKey] === axisId && !item.props.hide;
}), type, !0);
- return "number" === type && (domain = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.e)(children, domain, axisId, axisType, ticks),
- child.props.domain && (domain = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.B)(child.props.domain, domain, allowDataOverflow))),
+ return "number" === type && (domain = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.e)(children, domain, axisId, axisType, ticks),
+ child.props.domain && (domain = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.B)(child.props.domain, domain, allowDataOverflow))),
_extends({}, result, _defineProperty({}, axisId, _extends({}, child.props, {
axisType: axisType,
domain: domain,
@@ -2579,16 +2329,16 @@ var _publicBundleJs = []byte(`!function(modules) {
graphicalItems: graphicalItems,
dataStartIndex: dataStartIndex,
dataEndIndex: dataEndIndex
- }), len = displayedData.length, isCategorial = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.x)(layout, axisType), index = -1;
+ }), len = displayedData.length, isCategorial = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.x)(layout, axisType), index = -1;
return graphicalItems.reduce(function(result, child) {
var axisId = child.props[axisIdKey];
if (!result[axisId]) {
index++;
var domain = void 0;
- return isCategorial ? domain = __WEBPACK_IMPORTED_MODULE_3_lodash_range___default()(0, len) : stackGroups && stackGroups[axisId] && stackGroups[axisId].hasStack ? (domain = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.p)(stackGroups[axisId].stackGroups, dataStartIndex, dataEndIndex),
- domain = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.e)(children, domain, axisId, axisType)) : (domain = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.B)(Axis.defaultProps.domain, Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.o)(displayedData, graphicalItems.filter(function(item) {
+ return isCategorial ? domain = __WEBPACK_IMPORTED_MODULE_2_lodash_range___default()(0, len) : stackGroups && stackGroups[axisId] && stackGroups[axisId].hasStack ? (domain = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.p)(stackGroups[axisId].stackGroups, dataStartIndex, dataEndIndex),
+ domain = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.e)(children, domain, axisId, axisType)) : (domain = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.B)(Axis.defaultProps.domain, Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.o)(displayedData, graphicalItems.filter(function(item) {
return item.props[axisIdKey] === axisId && !item.props.hide;
- }), "number"), Axis.defaultProps.allowDataOverflow), domain = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.e)(children, domain, axisId, axisType)),
+ }), "number"), Axis.defaultProps.allowDataOverflow), domain = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.e)(children, domain, axisId, axisType)),
_extends({}, result, _defineProperty({}, axisId, _extends({
axisType: axisType
}, Axis.defaultProps, {
@@ -2606,9 +2356,9 @@ var _publicBundleJs = []byte(`!function(modules) {
}, {
key: "getActiveCoordinate",
value: function(tooltipTicks, activeIndex, rangeObj) {
- var layout = this.props.layout, entry = __WEBPACK_IMPORTED_MODULE_2_lodash_get___default()(tooltipTicks.filter(function(tick) {
+ var layout = this.props.layout, entry = tooltipTicks.find(function(tick) {
return tick && tick.index === activeIndex;
- }), "[0]");
+ });
if (entry) {
if ("horizontal" === layout) return {
x: entry.coordinate,
@@ -2620,13 +2370,13 @@ var _publicBundleJs = []byte(`!function(modules) {
};
if ("centric" === layout) {
var _angle = entry.coordinate, _radius = rangeObj.radius;
- return _extends({}, rangeObj, Object(__WEBPACK_IMPORTED_MODULE_24__util_PolarUtils__.e)(rangeObj.cx, rangeObj.cy, _radius, _angle), {
+ return _extends({}, rangeObj, Object(__WEBPACK_IMPORTED_MODULE_23__util_PolarUtils__.e)(rangeObj.cx, rangeObj.cy, _radius, _angle), {
angle: _angle,
radius: _radius
});
}
var radius = entry.coordinate, angle = rangeObj.angle;
- return _extends({}, rangeObj, Object(__WEBPACK_IMPORTED_MODULE_24__util_PolarUtils__.e)(rangeObj.cx, rangeObj.cy, radius, angle), {
+ return _extends({}, rangeObj, Object(__WEBPACK_IMPORTED_MODULE_23__util_PolarUtils__.e)(rangeObj.cx, rangeObj.cy, radius, angle), {
angle: angle,
radius: radius
});
@@ -2637,17 +2387,17 @@ var _publicBundleJs = []byte(`!function(modules) {
key: "getMouseInfo",
value: function(event) {
if (!this.container) return null;
- var containerOffset = Object(__WEBPACK_IMPORTED_MODULE_21__util_DOMUtils__.b)(this.container), e = Object(__WEBPACK_IMPORTED_MODULE_21__util_DOMUtils__.a)(event, containerOffset), rangeObj = this.inRange(e.chartX, e.chartY);
+ var containerOffset = Object(__WEBPACK_IMPORTED_MODULE_20__util_DOMUtils__.b)(this.container), e = Object(__WEBPACK_IMPORTED_MODULE_20__util_DOMUtils__.a)(event, containerOffset), rangeObj = this.inRange(e.chartX, e.chartY);
if (!rangeObj) return null;
var _state2 = this.state, xAxisMap = _state2.xAxisMap, yAxisMap = _state2.yAxisMap;
if ("axis" !== eventType && xAxisMap && yAxisMap) {
- var xScale = Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.b)(xAxisMap).scale, yScale = Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.b)(yAxisMap).scale, xValue = xScale && xScale.invert ? xScale.invert(e.chartX) : null, yValue = yScale && yScale.invert ? yScale.invert(e.chartY) : null;
+ var xScale = Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.b)(xAxisMap).scale, yScale = Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.b)(yAxisMap).scale, xValue = xScale && xScale.invert ? xScale.invert(e.chartX) : null, yValue = yScale && yScale.invert ? yScale.invert(e.chartY) : null;
return _extends({}, e, {
xValue: xValue,
yValue: yValue
});
}
- var _state3 = this.state, ticks = _state3.orderedTooltipTicks, axis = _state3.tooltipAxis, tooltipTicks = _state3.tooltipTicks, pos = this.calculateTooltipPos(rangeObj), activeIndex = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.b)(pos, ticks, tooltipTicks, axis);
+ var _state3 = this.state, ticks = _state3.orderedTooltipTicks, axis = _state3.tooltipAxis, tooltipTicks = _state3.tooltipTicks, pos = this.calculateTooltipPos(rangeObj), activeIndex = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.b)(pos, ticks, tooltipTicks, axis);
if (activeIndex >= 0 && tooltipTicks) {
var activeLabel = tooltipTicks[activeIndex] && tooltipTicks[activeIndex].value, activePayload = this.getTooltipContent(activeIndex, activeLabel), activeCoordinate = this.getActiveCoordinate(ticks, activeIndex, rangeObj);
return _extends({}, e, {
@@ -2666,14 +2416,14 @@ var _publicBundleJs = []byte(`!function(modules) {
return activeIndex < 0 || !graphicalItems || !graphicalItems.length || activeIndex >= displayedData.length ? null : graphicalItems.reduce(function(result, child) {
if (child.props.hide) return result;
var _child$props2 = child.props, dataKey = _child$props2.dataKey, name = _child$props2.name, unit = _child$props2.unit, formatter = _child$props2.formatter, data = _child$props2.data, payload = void 0;
- return payload = tooltipAxis.dataKey && !tooltipAxis.allowDuplicatedCategory ? Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.a)(data || displayedData, tooltipAxis.dataKey, activeLabel) : displayedData[activeIndex],
- payload ? [].concat(_toConsumableArray(result), [ _extends({}, Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.k)(child), {
+ return payload = tooltipAxis.dataKey && !tooltipAxis.allowDuplicatedCategory ? Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.a)(data || displayedData, tooltipAxis.dataKey, activeLabel) : displayedData[activeIndex],
+ payload ? [].concat(_toConsumableArray(result), [ _extends({}, Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.k)(child), {
dataKey: dataKey,
unit: unit,
formatter: formatter,
name: name || dataKey,
- color: Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.r)(child),
- value: Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.w)(payload, dataKey),
+ color: Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.r)(child),
+ value: Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.w)(payload, dataKey),
payload: payload
}) ]) : result;
}, []);
@@ -2681,7 +2431,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, {
key: "getFormatItems",
value: function(props, currentState) {
- var _this3 = this, graphicalItems = currentState.graphicalItems, stackGroups = currentState.stackGroups, offset = currentState.offset, updateId = currentState.updateId, dataStartIndex = currentState.dataStartIndex, dataEndIndex = currentState.dataEndIndex, barSize = props.barSize, layout = props.layout, barGap = props.barGap, barCategoryGap = props.barCategoryGap, globalMaxBarSize = props.maxBarSize, _getAxisNameByLayout = this.getAxisNameByLayout(layout), numericAxisName = _getAxisNameByLayout.numericAxisName, cateAxisName = _getAxisNameByLayout.cateAxisName, hasBar = this.constructor.hasBar(graphicalItems), sizeList = hasBar && Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.i)({
+ var _this3 = this, graphicalItems = currentState.graphicalItems, stackGroups = currentState.stackGroups, offset = currentState.offset, updateId = currentState.updateId, dataStartIndex = currentState.dataStartIndex, dataEndIndex = currentState.dataEndIndex, barSize = props.barSize, layout = props.layout, barGap = props.barGap, barCategoryGap = props.barCategoryGap, globalMaxBarSize = props.maxBarSize, _getAxisNameByLayout = this.getAxisNameByLayout(layout), numericAxisName = _getAxisNameByLayout.numericAxisName, cateAxisName = _getAxisNameByLayout.cateAxisName, hasBar = this.constructor.hasBar(graphicalItems), sizeList = hasBar && Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.i)({
barSize: barSize,
stackGroups: stackGroups
}), formatedItems = [];
@@ -2692,9 +2442,9 @@ var _publicBundleJs = []byte(`!function(modules) {
}, item), _item$props = item.props, dataKey = _item$props.dataKey, childMaxBarSize = _item$props.maxBarSize, numericAxisId = item.props[numericAxisName + "Id"], cateAxisId = item.props[cateAxisName + "Id"], axisObj = axisComponents.reduce(function(result, entry) {
var _extends4, axisMap = currentState[entry.axisType + "Map"], id = item.props[entry.axisType + "Id"], axis = axisMap && axisMap[id];
return _extends({}, result, (_extends4 = {}, _defineProperty(_extends4, entry.axisType, axis),
- _defineProperty(_extends4, entry.axisType + "Ticks", Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.u)(axis)),
+ _defineProperty(_extends4, entry.axisType + "Ticks", Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.u)(axis)),
_extends4));
- }, {}), cateAxis = axisObj[cateAxisName], cateTicks = axisObj[cateAxisName + "Ticks"], stackedData = stackGroups && stackGroups[numericAxisId] && stackGroups[numericAxisId].hasStack && Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.t)(item, stackGroups[numericAxisId].stackGroups), bandSize = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.g)(cateAxis, cateTicks), maxBarSize = __WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(childMaxBarSize) ? globalMaxBarSize : childMaxBarSize, barPosition = hasBar && Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.h)({
+ }, {}), cateAxis = axisObj[cateAxisName], cateTicks = axisObj[cateAxisName + "Ticks"], stackedData = stackGroups && stackGroups[numericAxisId] && stackGroups[numericAxisId].hasStack && Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.t)(item, stackGroups[numericAxisId].stackGroups), bandSize = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.g)(cateAxis, cateTicks), maxBarSize = __WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(childMaxBarSize) ? globalMaxBarSize : childMaxBarSize, barPosition = hasBar && Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.h)({
barGap: barGap,
barCategoryGap: barCategoryGap,
bandSize: bandSize,
@@ -2716,13 +2466,13 @@ var _publicBundleJs = []byte(`!function(modules) {
layout: layout,
dataStartIndex: dataStartIndex,
dataEndIndex: dataEndIndex,
- onItemMouseLeave: Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.d)(_this3.handleItemMouseLeave, null, item.props.onMouseLeave),
- onItemMouseEnter: Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.d)(_this3.handleItemMouseEnter, null, item.props.onMouseEnter)
+ onItemMouseLeave: Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.d)(_this3.handleItemMouseLeave, null, item.props.onMouseLeave),
+ onItemMouseEnter: Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.d)(_this3.handleItemMouseEnter, null, item.props.onMouseEnter)
})), (_extends5 = {
key: item.key || "item-" + index
}, _defineProperty(_extends5, numericAxisName, axisObj[numericAxisName]), _defineProperty(_extends5, cateAxisName, axisObj[cateAxisName]),
_defineProperty(_extends5, "animationId", updateId), _extends5)),
- childIndex: Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.o)(item, props.children),
+ childIndex: Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.o)(item, props.children),
item: item
});
}
@@ -2747,9 +2497,9 @@ var _publicBundleJs = []byte(`!function(modules) {
var layout = this.props.layout, _state6 = this.state, activeCoordinate = _state6.activeCoordinate, offset = _state6.offset, x1 = void 0, y1 = void 0, x2 = void 0, y2 = void 0;
if ("horizontal" === layout) x1 = activeCoordinate.x, x2 = x1, y1 = offset.top,
y2 = offset.top + offset.height; else if ("vertical" === layout) y1 = activeCoordinate.y,
- y2 = y1, x1 = offset.left, x2 = offset.left + offset.width; else if (!__WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(activeCoordinate.cx) || !__WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(activeCoordinate.cy)) {
+ y2 = y1, x1 = offset.left, x2 = offset.left + offset.width; else if (!__WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(activeCoordinate.cx) || !__WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(activeCoordinate.cy)) {
if ("centric" !== layout) {
- var _cx = activeCoordinate.cx, _cy = activeCoordinate.cy, radius = activeCoordinate.radius, startAngle = activeCoordinate.startAngle, endAngle = activeCoordinate.endAngle, startPoint = Object(__WEBPACK_IMPORTED_MODULE_24__util_PolarUtils__.e)(_cx, _cy, radius, startAngle), endPoint = Object(__WEBPACK_IMPORTED_MODULE_24__util_PolarUtils__.e)(_cx, _cy, radius, endAngle);
+ var _cx = activeCoordinate.cx, _cy = activeCoordinate.cy, radius = activeCoordinate.radius, startAngle = activeCoordinate.startAngle, endAngle = activeCoordinate.endAngle, startPoint = Object(__WEBPACK_IMPORTED_MODULE_23__util_PolarUtils__.e)(_cx, _cy, radius, startAngle), endPoint = Object(__WEBPACK_IMPORTED_MODULE_23__util_PolarUtils__.e)(_cx, _cy, radius, endAngle);
return {
points: [ startPoint, endPoint ],
cx: _cx,
@@ -2759,7 +2509,7 @@ var _publicBundleJs = []byte(`!function(modules) {
endAngle: endAngle
};
}
- var cx = activeCoordinate.cx, cy = activeCoordinate.cy, innerRadius = activeCoordinate.innerRadius, outerRadius = activeCoordinate.outerRadius, angle = activeCoordinate.angle, innerPoint = Object(__WEBPACK_IMPORTED_MODULE_24__util_PolarUtils__.e)(cx, cy, innerRadius, angle), outerPoint = Object(__WEBPACK_IMPORTED_MODULE_24__util_PolarUtils__.e)(cx, cy, outerRadius, angle);
+ var cx = activeCoordinate.cx, cy = activeCoordinate.cy, innerRadius = activeCoordinate.innerRadius, outerRadius = activeCoordinate.outerRadius, angle = activeCoordinate.angle, innerPoint = Object(__WEBPACK_IMPORTED_MODULE_23__util_PolarUtils__.e)(cx, cy, innerRadius, angle), outerPoint = Object(__WEBPACK_IMPORTED_MODULE_23__util_PolarUtils__.e)(cx, cy, outerRadius, angle);
x1 = innerPoint.x, y1 = innerPoint.y, x2 = outerPoint.x, y2 = outerPoint.y;
}
return [ {
@@ -2806,8 +2556,8 @@ var _publicBundleJs = []byte(`!function(modules) {
}
var _state7 = this.state, angleAxisMap = _state7.angleAxisMap, radiusAxisMap = _state7.radiusAxisMap;
if (angleAxisMap && radiusAxisMap) {
- var angleAxis = Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.b)(angleAxisMap);
- return Object(__WEBPACK_IMPORTED_MODULE_24__util_PolarUtils__.d)({
+ var angleAxis = Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.b)(angleAxisMap);
+ return Object(__WEBPACK_IMPORTED_MODULE_23__util_PolarUtils__.d)({
x: x,
y: y
}, angleAxis);
@@ -2817,22 +2567,22 @@ var _publicBundleJs = []byte(`!function(modules) {
}, {
key: "parseEventsOfWrapper",
value: function() {
- var children = this.props.children, tooltipItem = Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.i)(children, __WEBPACK_IMPORTED_MODULE_11__component_Tooltip__.a), tooltipEvents = tooltipItem && "axis" === eventType ? {
+ var children = this.props.children, tooltipItem = Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.i)(children, __WEBPACK_IMPORTED_MODULE_10__component_Tooltip__.a), tooltipEvents = tooltipItem && "axis" === eventType ? {
onMouseEnter: this.handleMouseEnter,
onMouseMove: this.handleMouseMove,
onMouseLeave: this.handleMouseLeave,
onTouchMove: this.handleTouchMove
- } : {}, outerEvents = Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.e)(this.props, this.handleOuterEvent);
+ } : {}, outerEvents = Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.e)(this.props, this.handleOuterEvent);
return _extends({}, outerEvents, tooltipEvents);
}
}, {
key: "updateStateOfAxisMapsOffsetAndStackGroups",
value: function(_ref5) {
var _this4 = this, props = _ref5.props, dataStartIndex = _ref5.dataStartIndex, dataEndIndex = _ref5.dataEndIndex, updateId = _ref5.updateId;
- if (!Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.q)({
+ if (!Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.q)({
props: props
})) return null;
- var children = props.children, layout = props.layout, stackOffset = props.stackOffset, data = props.data, reverseStackOrder = props.reverseStackOrder, _getAxisNameByLayout2 = this.getAxisNameByLayout(layout), numericAxisName = _getAxisNameByLayout2.numericAxisName, cateAxisName = _getAxisNameByLayout2.cateAxisName, graphicalItems = Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.h)(children, GraphicalChild), stackGroups = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.s)(data, graphicalItems, numericAxisName + "Id", cateAxisName + "Id", stackOffset, reverseStackOrder), axisObj = axisComponents.reduce(function(result, entry) {
+ var children = props.children, layout = props.layout, stackOffset = props.stackOffset, data = props.data, reverseStackOrder = props.reverseStackOrder, _getAxisNameByLayout2 = this.getAxisNameByLayout(layout), numericAxisName = _getAxisNameByLayout2.numericAxisName, cateAxisName = _getAxisNameByLayout2.cateAxisName, graphicalItems = Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.h)(children, GraphicalChild), stackGroups = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.s)(data, graphicalItems, numericAxisName + "Id", cateAxisName + "Id", stackOffset, reverseStackOrder), axisObj = axisComponents.reduce(function(result, entry) {
var name = entry.axisType + "Map";
return _extends({}, result, _defineProperty({}, name, _this4.getAxisMap(props, _extends({}, entry, {
graphicalItems: graphicalItems,
@@ -2865,19 +2615,19 @@ var _publicBundleJs = []byte(`!function(modules) {
}, {
key: "addListener",
value: function() {
- __WEBPACK_IMPORTED_MODULE_26__util_Events__.b.on(__WEBPACK_IMPORTED_MODULE_26__util_Events__.a, this.handleReceiveSyncEvent),
- __WEBPACK_IMPORTED_MODULE_26__util_Events__.b.setMaxListeners && __WEBPACK_IMPORTED_MODULE_26__util_Events__.b._maxListeners && __WEBPACK_IMPORTED_MODULE_26__util_Events__.b.setMaxListeners(__WEBPACK_IMPORTED_MODULE_26__util_Events__.b._maxListeners + 1);
+ __WEBPACK_IMPORTED_MODULE_25__util_Events__.b.on(__WEBPACK_IMPORTED_MODULE_25__util_Events__.a, this.handleReceiveSyncEvent),
+ __WEBPACK_IMPORTED_MODULE_25__util_Events__.b.setMaxListeners && __WEBPACK_IMPORTED_MODULE_25__util_Events__.b._maxListeners && __WEBPACK_IMPORTED_MODULE_25__util_Events__.b.setMaxListeners(__WEBPACK_IMPORTED_MODULE_25__util_Events__.b._maxListeners + 1);
}
}, {
key: "removeListener",
value: function() {
- __WEBPACK_IMPORTED_MODULE_26__util_Events__.b.removeListener(__WEBPACK_IMPORTED_MODULE_26__util_Events__.a, this.handleReceiveSyncEvent),
- __WEBPACK_IMPORTED_MODULE_26__util_Events__.b.setMaxListeners && __WEBPACK_IMPORTED_MODULE_26__util_Events__.b._maxListeners && __WEBPACK_IMPORTED_MODULE_26__util_Events__.b.setMaxListeners(__WEBPACK_IMPORTED_MODULE_26__util_Events__.b._maxListeners - 1);
+ __WEBPACK_IMPORTED_MODULE_25__util_Events__.b.removeListener(__WEBPACK_IMPORTED_MODULE_25__util_Events__.a, this.handleReceiveSyncEvent),
+ __WEBPACK_IMPORTED_MODULE_25__util_Events__.b.setMaxListeners && __WEBPACK_IMPORTED_MODULE_25__util_Events__.b._maxListeners && __WEBPACK_IMPORTED_MODULE_25__util_Events__.b.setMaxListeners(__WEBPACK_IMPORTED_MODULE_25__util_Events__.b._maxListeners - 1);
}
}, {
key: "calculateOffset",
value: function(_ref6) {
- var props = _ref6.props, graphicalItems = _ref6.graphicalItems, _ref6$xAxisMap = _ref6.xAxisMap, xAxisMap = void 0 === _ref6$xAxisMap ? {} : _ref6$xAxisMap, _ref6$yAxisMap = _ref6.yAxisMap, yAxisMap = void 0 === _ref6$yAxisMap ? {} : _ref6$yAxisMap, width = props.width, height = props.height, children = props.children, margin = props.margin || {}, brushItem = Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.i)(children, __WEBPACK_IMPORTED_MODULE_20__cartesian_Brush__.a), legendItem = Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.i)(children, __WEBPACK_IMPORTED_MODULE_12__component_Legend__.a), offsetH = Object.keys(yAxisMap).reduce(function(result, id) {
+ var props = _ref6.props, graphicalItems = _ref6.graphicalItems, _ref6$xAxisMap = _ref6.xAxisMap, xAxisMap = void 0 === _ref6$xAxisMap ? {} : _ref6$xAxisMap, _ref6$yAxisMap = _ref6.yAxisMap, yAxisMap = void 0 === _ref6$yAxisMap ? {} : _ref6$yAxisMap, width = props.width, height = props.height, children = props.children, margin = props.margin || {}, brushItem = Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.i)(children, __WEBPACK_IMPORTED_MODULE_19__cartesian_Brush__.a), legendItem = Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.i)(children, __WEBPACK_IMPORTED_MODULE_11__component_Legend__.a), offsetH = Object.keys(yAxisMap).reduce(function(result, id) {
var entry = yAxisMap[id], orientation = entry.orientation;
return entry.mirror || entry.hide ? result : _extends({}, result, _defineProperty({}, orientation, result[orientation] + entry.width));
}, {
@@ -2890,10 +2640,10 @@ var _publicBundleJs = []byte(`!function(modules) {
top: margin.top || 0,
bottom: margin.bottom || 0
}), offset = _extends({}, offsetV, offsetH), brushBottom = offset.bottom;
- if (brushItem && (offset.bottom += brushItem.props.height || __WEBPACK_IMPORTED_MODULE_20__cartesian_Brush__.a.defaultProps.height),
+ if (brushItem && (offset.bottom += brushItem.props.height || __WEBPACK_IMPORTED_MODULE_19__cartesian_Brush__.a.defaultProps.height),
legendItem && this.legendInstance) {
var legendBox = this.legendInstance.getBBox();
- offset = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.a)(offset, graphicalItems, props, legendBox);
+ offset = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.a)(offset, graphicalItems, props, legendBox);
}
return _extends({
brushBottom: brushBottom
@@ -2906,14 +2656,14 @@ var _publicBundleJs = []byte(`!function(modules) {
key: "triggerSyncEvent",
value: function(data) {
var syncId = this.props.syncId;
- __WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(syncId) || __WEBPACK_IMPORTED_MODULE_26__util_Events__.b.emit(__WEBPACK_IMPORTED_MODULE_26__util_Events__.a, syncId, this.uniqueChartId, data);
+ __WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(syncId) || __WEBPACK_IMPORTED_MODULE_25__util_Events__.b.emit(__WEBPACK_IMPORTED_MODULE_25__util_Events__.a, syncId, this.uniqueChartId, data);
}
}, {
key: "filterFormatItem",
value: function(item, displayName, childIndex) {
for (var formatedGraphicalItems = this.state.formatedGraphicalItems, i = 0, len = formatedGraphicalItems.length; i < len; i++) {
var entry = formatedGraphicalItems[i];
- if (entry.item === item || entry.props.key === item.key || displayName === Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.j)(entry.item.type) && childIndex === entry.childIndex) return entry;
+ if (entry.item === item || entry.props.key === item.key || displayName === Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.j)(entry.item.type) && childIndex === entry.childIndex) return entry;
}
return null;
}
@@ -2921,7 +2671,7 @@ var _publicBundleJs = []byte(`!function(modules) {
key: "renderAxis",
value: function(axisOptions, element, displayName, index) {
var _props2 = this.props, width = _props2.width, height = _props2.height;
- return __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_19__cartesian_CartesianAxis__.a, _extends({}, axisOptions, {
+ return __WEBPACK_IMPORTED_MODULE_5_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_18__cartesian_CartesianAxis__.a, _extends({}, axisOptions, {
className: "recharts-" + axisOptions.axisType + " " + axisOptions.axisType,
key: element.key || displayName + "-" + index,
viewBox: {
@@ -2936,7 +2686,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, {
key: "renderLegend",
value: function() {
- var _this5 = this, formatedGraphicalItems = this.state.formatedGraphicalItems, _props3 = this.props, children = _props3.children, width = _props3.width, height = _props3.height, margin = this.props.margin || {}, legendWidth = width - (margin.left || 0) - (margin.right || 0), legendHeight = height - (margin.top || 0) - (margin.bottom || 0), props = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.q)({
+ var _this5 = this, formatedGraphicalItems = this.state.formatedGraphicalItems, _props3 = this.props, children = _props3.children, width = _props3.width, height = _props3.height, margin = this.props.margin || {}, legendWidth = width - (margin.left || 0) - (margin.right || 0), legendHeight = height - (margin.top || 0) - (margin.bottom || 0), props = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.q)({
children: children,
formatedGraphicalItems: formatedGraphicalItems,
legendWidth: legendWidth,
@@ -2945,7 +2695,7 @@ var _publicBundleJs = []byte(`!function(modules) {
});
if (!props) return null;
var item = props.item, otherProps = _objectWithoutProperties(props, [ "item" ]);
- return Object(__WEBPACK_IMPORTED_MODULE_6_react__.cloneElement)(item, _extends({}, otherProps, {
+ return Object(__WEBPACK_IMPORTED_MODULE_5_react__.cloneElement)(item, _extends({}, otherProps, {
chartWidth: width,
chartHeight: height,
margin: margin,
@@ -2958,10 +2708,10 @@ var _publicBundleJs = []byte(`!function(modules) {
}, {
key: "renderTooltip",
value: function() {
- var children = this.props.children, tooltipItem = Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.i)(children, __WEBPACK_IMPORTED_MODULE_11__component_Tooltip__.a);
+ var children = this.props.children, tooltipItem = Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.i)(children, __WEBPACK_IMPORTED_MODULE_10__component_Tooltip__.a);
if (!tooltipItem) return null;
var _state8 = this.state, isTooltipActive = _state8.isTooltipActive, activeCoordinate = _state8.activeCoordinate, activePayload = _state8.activePayload, activeLabel = _state8.activeLabel, offset = _state8.offset;
- return Object(__WEBPACK_IMPORTED_MODULE_6_react__.cloneElement)(tooltipItem, {
+ return Object(__WEBPACK_IMPORTED_MODULE_5_react__.cloneElement)(tooltipItem, {
viewBox: _extends({}, offset, {
x: offset.left,
y: offset.top
@@ -2976,8 +2726,8 @@ var _publicBundleJs = []byte(`!function(modules) {
key: "renderActiveDot",
value: function(option, props) {
var dot = void 0;
- return dot = Object(__WEBPACK_IMPORTED_MODULE_6_react__.isValidElement)(option) ? Object(__WEBPACK_IMPORTED_MODULE_6_react__.cloneElement)(option, props) : __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default()(option) ? option(props) : __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_16__shape_Dot__.a, props),
- __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_10__container_Layer__.a, {
+ return dot = Object(__WEBPACK_IMPORTED_MODULE_5_react__.isValidElement)(option) ? Object(__WEBPACK_IMPORTED_MODULE_5_react__.cloneElement)(option, props) : __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default()(option) ? option(props) : __WEBPACK_IMPORTED_MODULE_5_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_15__shape_Dot__.a, props),
+ __WEBPACK_IMPORTED_MODULE_5_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_9__container_Layer__.a, {
className: "recharts-active-dot",
key: props.key
}, dot);
@@ -2991,13 +2741,13 @@ var _publicBundleJs = []byte(`!function(modules) {
cx: activePoint.x,
cy: activePoint.y,
r: 4,
- fill: Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.r)(item.item),
+ fill: Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.r)(item.item),
strokeWidth: 2,
stroke: "#fff",
payload: activePoint.payload,
value: activePoint.value,
key: key + "-activePoint-" + childIndex
- }, Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.k)(activeDot), Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.e)(activeDot));
+ }, Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.k)(activeDot), Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.e)(activeDot));
return result.push(this.renderActiveDot(activeDot, dotProps, childIndex)), basePoint ? result.push(this.renderActiveDot(activeDot, _extends({}, dotProps, {
cx: basePoint.x,
cy: basePoint.y,
@@ -3008,8 +2758,8 @@ var _publicBundleJs = []byte(`!function(modules) {
key: "render",
value: function() {
var _this6 = this;
- if (!Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.q)(this)) return null;
- var _props4 = this.props, children = _props4.children, className = _props4.className, width = _props4.width, height = _props4.height, style = _props4.style, compact = _props4.compact, others = _objectWithoutProperties(_props4, [ "children", "className", "width", "height", "style", "compact" ]), attrs = Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.k)(others), map = {
+ if (!Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.q)(this)) return null;
+ var _props4 = this.props, children = _props4.children, className = _props4.className, width = _props4.width, height = _props4.height, style = _props4.style, compact = _props4.compact, others = _objectWithoutProperties(_props4, [ "children", "className", "width", "height", "style", "compact" ]), attrs = Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.k)(others), map = {
CartesianGrid: {
handler: this.renderGrid,
once: !0
@@ -3069,13 +2819,13 @@ var _publicBundleJs = []byte(`!function(modules) {
handler: this.renderPolarAxis
}
};
- if (compact) return __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_9__container_Surface__.a, _extends({}, attrs, {
+ if (compact) return __WEBPACK_IMPORTED_MODULE_5_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_8__container_Surface__.a, _extends({}, attrs, {
width: width,
height: height
- }), Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.p)(children, map));
+ }), Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.p)(children, map));
var events = this.parseEventsOfWrapper();
- return __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement("div", _extends({
- className: __WEBPACK_IMPORTED_MODULE_8_classnames___default()("recharts-wrapper", className),
+ return __WEBPACK_IMPORTED_MODULE_5_react___default.a.createElement("div", _extends({
+ className: __WEBPACK_IMPORTED_MODULE_7_classnames___default()("recharts-wrapper", className),
style: _extends({}, style, {
position: "relative",
cursor: "default",
@@ -3086,43 +2836,43 @@ var _publicBundleJs = []byte(`!function(modules) {
ref: function(node) {
_this6.container = node;
}
- }), __WEBPACK_IMPORTED_MODULE_6_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_9__container_Surface__.a, _extends({}, attrs, {
+ }), __WEBPACK_IMPORTED_MODULE_5_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_8__container_Surface__.a, _extends({}, attrs, {
width: width,
height: height
- }), Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.p)(children, map)), this.renderLegend(), this.renderTooltip());
+ }), Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.p)(children, map)), this.renderLegend(), this.renderTooltip());
}
} ]), CategoricalChartWrapper;
- }(__WEBPACK_IMPORTED_MODULE_6_react__.Component), _class.displayName = chartName,
+ }(__WEBPACK_IMPORTED_MODULE_5_react__.Component), _class.displayName = chartName,
_class.propTypes = _extends({
- syncId: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.oneOfType([ __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.string, __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.number ]),
- compact: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.bool,
- width: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.number,
- height: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.number,
- data: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.arrayOf(__WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.object),
- layout: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.oneOf([ "horizontal", "vertical" ]),
- stackOffset: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.oneOf([ "sign", "expand", "none", "wiggle", "silhouette" ]),
- throttleDelay: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.number,
- margin: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.shape({
- top: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.number,
- right: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.number,
- bottom: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.number,
- left: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.number
+ syncId: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.oneOfType([ __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.string, __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.number ]),
+ compact: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.bool,
+ width: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.number,
+ height: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.number,
+ data: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.arrayOf(__WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.object),
+ layout: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.oneOf([ "horizontal", "vertical" ]),
+ stackOffset: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.oneOf([ "sign", "expand", "none", "wiggle", "silhouette" ]),
+ throttleDelay: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.number,
+ margin: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.shape({
+ top: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.number,
+ right: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.number,
+ bottom: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.number,
+ left: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.number
}),
- barCategoryGap: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.oneOfType([ __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.number, __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.string ]),
- barGap: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.oneOfType([ __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.number, __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.string ]),
- barSize: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.oneOfType([ __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.number, __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.string ]),
- maxBarSize: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.number,
- style: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.object,
- className: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.string,
- children: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.oneOfType([ __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.arrayOf(__WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.node), __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.node ]),
- onClick: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.func,
- onMouseLeave: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.func,
- onMouseEnter: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.func,
- onMouseMove: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.func,
- onMouseDown: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.func,
- onMouseUp: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.func,
- reverseStackOrder: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.bool,
- id: __WEBPACK_IMPORTED_MODULE_7_prop_types___default.a.string
+ barCategoryGap: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.oneOfType([ __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.number, __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.string ]),
+ barGap: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.oneOfType([ __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.number, __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.string ]),
+ barSize: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.oneOfType([ __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.number, __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.string ]),
+ maxBarSize: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.number,
+ style: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.object,
+ className: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.string,
+ children: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.oneOfType([ __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.arrayOf(__WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.node), __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.node ]),
+ onClick: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.func,
+ onMouseLeave: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.func,
+ onMouseEnter: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.func,
+ onMouseMove: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.func,
+ onMouseDown: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.func,
+ onMouseUp: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.func,
+ reverseStackOrder: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.bool,
+ id: __WEBPACK_IMPORTED_MODULE_6_prop_types___default.a.string
}, propTypes), _class.defaultProps = _extends({
layout: "horizontal",
stackOffset: "none",
@@ -3136,7 +2886,7 @@ var _publicBundleJs = []byte(`!function(modules) {
},
reverseStackOrder: !1
}, defaultProps), _class.createDefaultState = function(props) {
- var children = props.children, brushItem = Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.i)(children, __WEBPACK_IMPORTED_MODULE_20__cartesian_Brush__.a);
+ var children = props.children, brushItem = Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.i)(children, __WEBPACK_IMPORTED_MODULE_19__cartesian_Brush__.a);
return {
chartX: 0,
chartY: 0,
@@ -3147,7 +2897,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, _class.hasBar = function(graphicalItems) {
return !(!graphicalItems || !graphicalItems.length) && graphicalItems.some(function(item) {
- var name = Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.j)(item && item.type);
+ var name = Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.j)(item && item.type);
return name && name.indexOf("Bar") >= 0;
});
}, _class.getDisplayedData = function(props, _ref8, item) {
@@ -3158,7 +2908,7 @@ var _publicBundleJs = []byte(`!function(modules) {
if (itemsData && itemsData.length > 0) return itemsData;
if (item && item.props && item.props.data && item.props.data.length > 0) return item.props.data;
var data = props.data;
- return data && data.length && Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.g)(dataStartIndex) && Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.g)(dataEndIndex) ? data.slice(dataStartIndex, dataEndIndex + 1) : [];
+ return data && data.length && Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.g)(dataStartIndex) && Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.g)(dataEndIndex) ? data.slice(dataStartIndex, dataEndIndex + 1) : [];
}, _initialiseProps = function() {
var _this7 = this;
this.handleLegendBBoxUpdate = function(box) {
@@ -3175,7 +2925,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var _props5 = _this7.props, syncId = _props5.syncId, layout = _props5.layout, updateId = _this7.state.updateId;
if (syncId === cId && chartId !== _this7.uniqueChartId) {
var dataStartIndex = data.dataStartIndex, dataEndIndex = data.dataEndIndex;
- if (__WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(data.dataStartIndex) && __WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(data.dataEndIndex)) if (__WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(data.activeTooltipIndex)) _this7.setState(data); else {
+ if (__WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(data.dataStartIndex) && __WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(data.dataEndIndex)) if (__WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(data.activeTooltipIndex)) _this7.setState(data); else {
var chartX = data.chartX, chartY = data.chartY, activeTooltipIndex = data.activeTooltipIndex, _state10 = _this7.state, offset = _state10.offset, tooltipTicks = _state10.tooltipTicks;
if (!offset) return;
var viewBox = _extends({}, offset, {
@@ -3204,15 +2954,17 @@ var _publicBundleJs = []byte(`!function(modules) {
var startIndex = _ref9.startIndex, endIndex = _ref9.endIndex;
if (startIndex !== _this7.state.dataStartIndex || endIndex !== _this7.state.dataEndIndex) {
var updateId = _this7.state.updateId;
- _this7.setState(_extends({
- dataStartIndex: startIndex,
- dataEndIndex: endIndex
- }, _this7.updateStateOfAxisMapsOffsetAndStackGroups({
- props: _this7.props,
- dataStartIndex: startIndex,
- dataEndIndex: endIndex,
- updateId: updateId
- }))), _this7.triggerSyncEvent({
+ _this7.setState(function() {
+ return _extends({
+ dataStartIndex: startIndex,
+ dataEndIndex: endIndex
+ }, _this7.updateStateOfAxisMapsOffsetAndStackGroups({
+ props: _this7.props,
+ dataStartIndex: startIndex,
+ dataEndIndex: endIndex,
+ updateId: updateId
+ }));
+ }), _this7.triggerSyncEvent({
dataStartIndex: startIndex,
dataEndIndex: endIndex
});
@@ -3233,18 +2985,22 @@ var _publicBundleJs = []byte(`!function(modules) {
};
_this7.setState(nextState), _this7.triggerSyncEvent(nextState), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default()(onMouseMove) && onMouseMove(nextState, e);
}, this.handleItemMouseEnter = function(el) {
- _this7.setState({
- isTooltipActive: !0,
- activeItem: el,
- activePayload: el.tooltipPayload,
- activeCoordinate: el.tooltipPosition || {
- x: el.cx,
- y: el.cy
- }
+ _this7.setState(function() {
+ return {
+ isTooltipActive: !0,
+ activeItem: el,
+ activePayload: el.tooltipPayload,
+ activeCoordinate: el.tooltipPosition || {
+ x: el.cx,
+ y: el.cy
+ }
+ };
});
}, this.handleItemMouseLeave = function() {
- _this7.setState({
- isTooltipActive: !1
+ _this7.setState(function() {
+ return {
+ isTooltipActive: !1
+ };
});
}, this.handleMouseMove = function(e) {
e && __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default()(e.persist) && e.persist(),
@@ -3255,7 +3011,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
_this7.setState(nextState), _this7.triggerSyncEvent(nextState), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default()(onMouseLeave) && onMouseLeave(nextState, e);
}, this.handleOuterEvent = function(e) {
- var eventName = Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.l)(e);
+ var eventName = Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.l)(e);
if (eventName && __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default()(_this7.props[eventName])) {
var mouse = _this7.getMouseInfo(e);
(0, _this7.props[eventName])(mouse, e);
@@ -3279,8 +3035,8 @@ var _publicBundleJs = []byte(`!function(modules) {
null != e.changedTouches && e.changedTouches.length > 0 && _this7.handleMouseMove(e.changedTouches[0]);
}, this.verticalCoordinatesGenerator = function(_ref10) {
var xAxis = _ref10.xAxis, width = _ref10.width, height = _ref10.height, offset = _ref10.offset;
- return Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.m)(__WEBPACK_IMPORTED_MODULE_19__cartesian_CartesianAxis__.a.getTicks(_extends({}, __WEBPACK_IMPORTED_MODULE_19__cartesian_CartesianAxis__.a.defaultProps, xAxis, {
- ticks: Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.u)(xAxis, !0),
+ return Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.m)(__WEBPACK_IMPORTED_MODULE_18__cartesian_CartesianAxis__.a.getTicks(_extends({}, __WEBPACK_IMPORTED_MODULE_18__cartesian_CartesianAxis__.a.defaultProps, xAxis, {
+ ticks: Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.u)(xAxis, !0),
viewBox: {
x: 0,
y: 0,
@@ -3290,8 +3046,8 @@ var _publicBundleJs = []byte(`!function(modules) {
})), offset.left, offset.left + offset.width);
}, this.horizontalCoordinatesGenerator = function(_ref11) {
var yAxis = _ref11.yAxis, width = _ref11.width, height = _ref11.height, offset = _ref11.offset;
- return Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.m)(__WEBPACK_IMPORTED_MODULE_19__cartesian_CartesianAxis__.a.getTicks(_extends({}, __WEBPACK_IMPORTED_MODULE_19__cartesian_CartesianAxis__.a.defaultProps, yAxis, {
- ticks: Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.u)(yAxis, !0),
+ return Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.m)(__WEBPACK_IMPORTED_MODULE_18__cartesian_CartesianAxis__.a.getTicks(_extends({}, __WEBPACK_IMPORTED_MODULE_18__cartesian_CartesianAxis__.a.defaultProps, yAxis, {
+ ticks: Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.u)(yAxis, !0),
viewBox: {
x: 0,
y: 0,
@@ -3300,23 +3056,23 @@ var _publicBundleJs = []byte(`!function(modules) {
}
})), offset.top, offset.top + offset.height);
}, this.axesTicksGenerator = function(axis) {
- return Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.u)(axis, !0);
+ return Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.u)(axis, !0);
}, this.tooltipTicksGenerator = function(axisMap) {
- var axis = Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.b)(axisMap), tooltipTicks = Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.u)(axis, !1, !0);
+ var axis = Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.b)(axisMap), tooltipTicks = Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.u)(axis, !1, !0);
return {
tooltipTicks: tooltipTicks,
orderedTooltipTicks: __WEBPACK_IMPORTED_MODULE_0_lodash_sortBy___default()(tooltipTicks, function(o) {
return o.coordinate;
}),
tooltipAxis: axis,
- tooltipAxisBandSize: Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.g)(axis)
+ tooltipAxisBandSize: Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.g)(axis)
};
}, this.renderCursor = function(element) {
var _state11 = _this7.state, isTooltipActive = _state11.isTooltipActive, activeCoordinate = _state11.activeCoordinate, activePayload = _state11.activePayload, offset = _state11.offset;
if (!(element && element.props.cursor && isTooltipActive && activeCoordinate)) return null;
- var layout = _this7.props.layout, restProps = void 0, cursorComp = __WEBPACK_IMPORTED_MODULE_13__shape_Curve__.a;
- if ("ScatterChart" === chartName) restProps = activeCoordinate, cursorComp = __WEBPACK_IMPORTED_MODULE_14__shape_Cross__.a; else if ("BarChart" === chartName) restProps = _this7.getCursorRectangle(),
- cursorComp = __WEBPACK_IMPORTED_MODULE_17__shape_Rectangle__.a; else if ("radial" === layout) {
+ var layout = _this7.props.layout, restProps = void 0, cursorComp = __WEBPACK_IMPORTED_MODULE_12__shape_Curve__.a;
+ if ("ScatterChart" === chartName) restProps = activeCoordinate, cursorComp = __WEBPACK_IMPORTED_MODULE_13__shape_Cross__.a; else if ("BarChart" === chartName) restProps = _this7.getCursorRectangle(),
+ cursorComp = __WEBPACK_IMPORTED_MODULE_16__shape_Rectangle__.a; else if ("radial" === layout) {
var _getCursorPoints = _this7.getCursorPoints(), cx = _getCursorPoints.cx, cy = _getCursorPoints.cy, radius = _getCursorPoints.radius, startAngle = _getCursorPoints.startAngle, endAngle = _getCursorPoints.endAngle;
restProps = {
cx: cx,
@@ -3325,24 +3081,24 @@ var _publicBundleJs = []byte(`!function(modules) {
endAngle: endAngle,
innerRadius: radius,
outerRadius: radius
- }, cursorComp = __WEBPACK_IMPORTED_MODULE_15__shape_Sector__.a;
+ }, cursorComp = __WEBPACK_IMPORTED_MODULE_14__shape_Sector__.a;
} else restProps = {
points: _this7.getCursorPoints()
- }, cursorComp = __WEBPACK_IMPORTED_MODULE_13__shape_Curve__.a;
+ }, cursorComp = __WEBPACK_IMPORTED_MODULE_12__shape_Curve__.a;
var key = element.key || "_recharts-cursor", cursorProps = _extends({
stroke: "#ccc"
- }, offset, restProps, Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.k)(element.props.cursor), {
+ }, offset, restProps, Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.k)(element.props.cursor), {
payload: activePayload,
key: key,
className: "recharts-tooltip-cursor"
});
- return Object(__WEBPACK_IMPORTED_MODULE_6_react__.isValidElement)(element.props.cursor) ? Object(__WEBPACK_IMPORTED_MODULE_6_react__.cloneElement)(element.props.cursor, cursorProps) : Object(__WEBPACK_IMPORTED_MODULE_6_react__.createElement)(cursorComp, cursorProps);
+ return Object(__WEBPACK_IMPORTED_MODULE_5_react__.isValidElement)(element.props.cursor) ? Object(__WEBPACK_IMPORTED_MODULE_5_react__.cloneElement)(element.props.cursor, cursorProps) : Object(__WEBPACK_IMPORTED_MODULE_5_react__.createElement)(cursorComp, cursorProps);
}, this.renderPolarAxis = function(element, displayName, index) {
var axisType = element.type.axisType, axisMap = _this7.state[axisType + "Map"], axisOption = axisMap[element.props[axisType + "Id"]];
- return Object(__WEBPACK_IMPORTED_MODULE_6_react__.cloneElement)(element, _extends({}, axisOption, {
+ return Object(__WEBPACK_IMPORTED_MODULE_5_react__.cloneElement)(element, _extends({}, axisOption, {
className: axisType,
key: element.key || displayName + "-" + index,
- ticks: Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.u)(axisOption, !0)
+ ticks: Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.u)(axisOption, !0)
}));
}, this.renderXAxis = function(element, displayName, index) {
var xAxisMap = _this7.state.xAxisMap, axisObj = xAxisMap[element.props.xAxisId];
@@ -3351,13 +3107,13 @@ var _publicBundleJs = []byte(`!function(modules) {
var yAxisMap = _this7.state.yAxisMap, axisObj = yAxisMap[element.props.yAxisId];
return _this7.renderAxis(axisObj, element, displayName, index);
}, this.renderGrid = function(element) {
- var _state12 = _this7.state, xAxisMap = _state12.xAxisMap, yAxisMap = _state12.yAxisMap, offset = _state12.offset, _props6 = _this7.props, width = _props6.width, height = _props6.height, xAxis = Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.b)(xAxisMap), yAxis = Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.b)(yAxisMap), props = element.props || {};
- return Object(__WEBPACK_IMPORTED_MODULE_6_react__.cloneElement)(element, {
+ var _state12 = _this7.state, xAxisMap = _state12.xAxisMap, yAxisMap = _state12.yAxisMap, offset = _state12.offset, _props6 = _this7.props, width = _props6.width, height = _props6.height, xAxis = Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.b)(xAxisMap), yAxis = Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.b)(yAxisMap), props = element.props || {};
+ return Object(__WEBPACK_IMPORTED_MODULE_5_react__.cloneElement)(element, {
key: element.key || "grid",
- x: Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.g)(props.x) ? props.x : offset.left,
- y: Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.g)(props.y) ? props.y : offset.top,
- width: Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.g)(props.width) ? props.width : offset.width,
- height: Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.g)(props.height) ? props.height : offset.height,
+ x: Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.g)(props.x) ? props.x : offset.left,
+ y: Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.g)(props.y) ? props.y : offset.top,
+ width: Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.g)(props.width) ? props.width : offset.width,
+ height: Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.g)(props.height) ? props.height : offset.height,
xAxis: xAxis,
yAxis: yAxis,
offset: offset,
@@ -3367,12 +3123,12 @@ var _publicBundleJs = []byte(`!function(modules) {
horizontalCoordinatesGenerator: _this7.horizontalCoordinatesGenerator
});
}, this.renderPolarGrid = function(element) {
- var _state13 = _this7.state, radiusAxisMap = _state13.radiusAxisMap, angleAxisMap = _state13.angleAxisMap, radiusAxis = Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.b)(radiusAxisMap), angleAxis = Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.b)(angleAxisMap), cx = angleAxis.cx, cy = angleAxis.cy, innerRadius = angleAxis.innerRadius, outerRadius = angleAxis.outerRadius;
- return Object(__WEBPACK_IMPORTED_MODULE_6_react__.cloneElement)(element, {
- polarAngles: Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.u)(angleAxis, !0).map(function(entry) {
+ var _state13 = _this7.state, radiusAxisMap = _state13.radiusAxisMap, angleAxisMap = _state13.angleAxisMap, radiusAxis = Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.b)(radiusAxisMap), angleAxis = Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.b)(angleAxisMap), cx = angleAxis.cx, cy = angleAxis.cy, innerRadius = angleAxis.innerRadius, outerRadius = angleAxis.outerRadius;
+ return Object(__WEBPACK_IMPORTED_MODULE_5_react__.cloneElement)(element, {
+ polarAngles: Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.u)(angleAxis, !0).map(function(entry) {
return entry.coordinate;
}),
- polarRadius: Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.u)(radiusAxis, !0).map(function(entry) {
+ polarRadius: Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.u)(radiusAxis, !0).map(function(entry) {
return entry.coordinate;
}),
cx: cx,
@@ -3383,13 +3139,13 @@ var _publicBundleJs = []byte(`!function(modules) {
});
}, this.renderBrush = function(element) {
var _props7 = _this7.props, margin = _props7.margin, data = _props7.data, _state14 = _this7.state, offset = _state14.offset, dataStartIndex = _state14.dataStartIndex, dataEndIndex = _state14.dataEndIndex, updateId = _state14.updateId;
- return Object(__WEBPACK_IMPORTED_MODULE_6_react__.cloneElement)(element, {
+ return Object(__WEBPACK_IMPORTED_MODULE_5_react__.cloneElement)(element, {
key: element.key || "_recharts-brush",
- onChange: Object(__WEBPACK_IMPORTED_MODULE_23__util_ChartUtils__.d)(_this7.handleBrushChange, null, element.props.onChange),
+ onChange: Object(__WEBPACK_IMPORTED_MODULE_22__util_ChartUtils__.d)(_this7.handleBrushChange, null, element.props.onChange),
data: data,
- x: Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.g)(element.props.x) ? element.props.x : offset.left,
- y: Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.g)(element.props.y) ? element.props.y : offset.top + offset.height + offset.brushBottom - (margin.bottom || 0),
- width: Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.g)(element.props.width) ? element.props.width : offset.width,
+ x: Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.g)(element.props.x) ? element.props.x : offset.left,
+ y: Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.g)(element.props.y) ? element.props.y : offset.top + offset.height + offset.brushBottom - (margin.bottom || 0),
+ width: Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.g)(element.props.width) ? element.props.width : offset.width,
startIndex: dataStartIndex,
endIndex: dataEndIndex,
updateId: "brush-" + updateId
@@ -3397,7 +3153,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, this.renderReferenceElement = function(element, displayName, index) {
if (!element) return null;
var _state15 = _this7.state, xAxisMap = _state15.xAxisMap, yAxisMap = _state15.yAxisMap, offset = _state15.offset, _element$props = element.props, xAxisId = _element$props.xAxisId, yAxisId = _element$props.yAxisId;
- return Object(__WEBPACK_IMPORTED_MODULE_6_react__.cloneElement)(element, {
+ return Object(__WEBPACK_IMPORTED_MODULE_5_react__.cloneElement)(element, {
key: element.key || displayName + "-" + index,
xAxis: xAxisMap[xAxisId],
yAxis: yAxisMap[yAxisId],
@@ -3411,12 +3167,12 @@ var _publicBundleJs = []byte(`!function(modules) {
}, this.renderGraphicChild = function(element, displayName, index) {
var item = _this7.filterFormatItem(element, displayName, index);
if (!item) return null;
- var graphicalItem = Object(__WEBPACK_IMPORTED_MODULE_6_react__.cloneElement)(element, item.props), _state16 = _this7.state, isTooltipActive = _state16.isTooltipActive, tooltipAxis = _state16.tooltipAxis, activeTooltipIndex = _state16.activeTooltipIndex, activeLabel = _state16.activeLabel, children = _this7.props.children, tooltipItem = Object(__WEBPACK_IMPORTED_MODULE_18__util_ReactUtils__.i)(children, __WEBPACK_IMPORTED_MODULE_11__component_Tooltip__.a), _item$props2 = item.props, points = _item$props2.points, isRange = _item$props2.isRange, baseLine = _item$props2.baseLine, _item$item$props2 = item.item.props, activeDot = _item$item$props2.activeDot;
+ var graphicalItem = Object(__WEBPACK_IMPORTED_MODULE_5_react__.cloneElement)(element, item.props), _state16 = _this7.state, isTooltipActive = _state16.isTooltipActive, tooltipAxis = _state16.tooltipAxis, activeTooltipIndex = _state16.activeTooltipIndex, activeLabel = _state16.activeLabel, children = _this7.props.children, tooltipItem = Object(__WEBPACK_IMPORTED_MODULE_17__util_ReactUtils__.i)(children, __WEBPACK_IMPORTED_MODULE_10__component_Tooltip__.a), _item$props2 = item.props, points = _item$props2.points, isRange = _item$props2.isRange, baseLine = _item$props2.baseLine, _item$item$props2 = item.item.props, activeDot = _item$item$props2.activeDot;
if (!_item$item$props2.hide && isTooltipActive && tooltipItem && activeDot && activeTooltipIndex >= 0) {
var activePoint = void 0, basePoint = void 0;
- if (tooltipAxis.dataKey && !tooltipAxis.allowDuplicatedCategory ? (activePoint = Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.a)(points, "payload." + tooltipAxis.dataKey, activeLabel),
- basePoint = isRange && baseLine && Object(__WEBPACK_IMPORTED_MODULE_22__util_DataUtils__.a)(baseLine, "payload." + tooltipAxis.dataKey, activeLabel)) : (activePoint = points[activeTooltipIndex],
- basePoint = isRange && baseLine && baseLine[activeTooltipIndex]), !__WEBPACK_IMPORTED_MODULE_5_lodash_isNil___default()(activePoint)) return [ graphicalItem ].concat(_toConsumableArray(_this7.renderActivePoints({
+ if (tooltipAxis.dataKey && !tooltipAxis.allowDuplicatedCategory ? (activePoint = Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.a)(points, "payload." + tooltipAxis.dataKey, activeLabel),
+ basePoint = isRange && baseLine && Object(__WEBPACK_IMPORTED_MODULE_21__util_DataUtils__.a)(baseLine, "payload." + tooltipAxis.dataKey, activeLabel)) : (activePoint = points[activeTooltipIndex],
+ basePoint = isRange && baseLine && baseLine[activeTooltipIndex]), !__WEBPACK_IMPORTED_MODULE_4_lodash_isNil___default()(activePoint)) return [ graphicalItem ].concat(_toConsumableArray(_this7.renderActivePoints({
item: item,
activePoint: activePoint,
basePoint: basePoint,
@@ -3430,7 +3186,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
__webpack_exports__.a = generateCategoricalChart;
}, function(module, exports, __webpack_require__) {
- var aFunction = __webpack_require__(269);
+ var aFunction = __webpack_require__(206);
module.exports = function(fn, that, length) {
if (aFunction(fn), void 0 === that) return fn;
switch (length) {
@@ -3454,7 +3210,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
};
}, function(module, exports, __webpack_require__) {
- var isObject = __webpack_require__(50);
+ var isObject = __webpack_require__(35);
module.exports = function(it) {
if (!isObject(it)) throw TypeError(it + " is not an object!");
return it;
@@ -3527,17 +3283,17 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _typeof2 = __webpack_require__(126), _typeof3 = _interopRequireDefault(_typeof2), _keys = __webpack_require__(51), _keys2 = _interopRequireDefault(_keys);
+ var _typeof2 = __webpack_require__(100), _typeof3 = _interopRequireDefault(_typeof2), _keys = __webpack_require__(41), _keys2 = _interopRequireDefault(_keys);
exports.capitalizeFirstLetter = capitalizeFirstLetter, exports.contains = contains,
exports.findIndex = findIndex, exports.find = find, exports.createChainedFunction = createChainedFunction;
- var _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning);
- }).call(exports, __webpack_require__(3));
+ var _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning);
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
function getNative(object, key) {
var value = getValue(object, key);
return baseIsNative(value) ? value : void 0;
}
- var baseIsNative = __webpack_require__(869), getValue = __webpack_require__(872);
+ var baseIsNative = __webpack_require__(562), getValue = __webpack_require__(565);
module.exports = getNative;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -3571,7 +3327,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isNil__ = __webpack_require__(28), __WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3_reduce_css_calc__ = __webpack_require__(994), __WEBPACK_IMPORTED_MODULE_3_reduce_css_calc___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_reduce_css_calc__), __WEBPACK_IMPORTED_MODULE_4_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_4_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_classnames__), __WEBPACK_IMPORTED_MODULE_5__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_6__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_7__util_DOMUtils__ = __webpack_require__(247), _extends = Object.assign || function(target) {
+ var _class, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isNil__ = __webpack_require__(20), __WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3_reduce_css_calc__ = __webpack_require__(686), __WEBPACK_IMPORTED_MODULE_3_reduce_css_calc___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_reduce_css_calc__), __WEBPACK_IMPORTED_MODULE_4_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_4_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_classnames__), __WEBPACK_IMPORTED_MODULE_5__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_6__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_7__util_DOMUtils__ = __webpack_require__(184), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -3749,7 +3505,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_4__util_ReactUtils__ = __webpack_require__(7), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_4__util_ReactUtils__ = __webpack_require__(4), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -3791,12 +3547,12 @@ var _publicBundleJs = []byte(`!function(modules) {
}, _class = _temp)) || _class;
__webpack_exports__.a = Dot;
}, function(module, exports, __webpack_require__) {
- var IObject = __webpack_require__(177), defined = __webpack_require__(179);
+ var IObject = __webpack_require__(135), defined = __webpack_require__(137);
module.exports = function(it) {
return IObject(defined(it));
};
}, function(module, exports, __webpack_require__) {
- var defined = __webpack_require__(179);
+ var defined = __webpack_require__(137);
module.exports = function(it) {
return Object(defined(it));
};
@@ -3835,7 +3591,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), _toCss = __webpack_require__(195), _toCss2 = _interopRequireDefault(_toCss), _toCssValue = __webpack_require__(196), _toCssValue2 = _interopRequireDefault(_toCssValue), StyleRule = function() {
+ }(), _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), _toCss = __webpack_require__(153), _toCss2 = _interopRequireDefault(_toCss), _toCssValue = __webpack_require__(105), _toCssValue2 = _interopRequireDefault(_toCssValue), StyleRule = function() {
function StyleRule(key, style, options) {
_classCallCheck(this, StyleRule), this.type = "style", this.isProcessed = !1;
var sheet = options.sheet, Renderer = options.Renderer, selector = options.selector;
@@ -3897,42 +3653,69 @@ var _publicBundleJs = []byte(`!function(modules) {
} ]), StyleRule;
}();
exports.default = StyleRule;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), always = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(val) {
- return function() {
- return val;
- };
- });
- __webpack_exports__.a = always;
-}, function(module, __webpack_exports__, __webpack_require__) {
+}, function(module, exports, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), max = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- return b > a ? b : a;
+ Object.defineProperty(exports, "__esModule", {
+ value: !0
});
- __webpack_exports__.a = max;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), path = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(paths, obj) {
- for (var val = obj, idx = 0; idx < paths.length; ) {
- if (null == val) return;
- val = val[paths[idx]], idx += 1;
+ var _extends = Object.assign || function(target) {
+ for (var i = 1; i < arguments.length; i++) {
+ var source = arguments[i];
+ for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
}
- return val;
- });
- __webpack_exports__.a = path;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _contains(a, list) {
- return Object(__WEBPACK_IMPORTED_MODULE_0__indexOf__.a)(list, a, 0) >= 0;
- }
- __webpack_exports__.a = _contains;
- var __WEBPACK_IMPORTED_MODULE_0__indexOf__ = __webpack_require__(316);
+ return target;
+ }, menuSkeletons = [ {
+ id: "home",
+ menu: {
+ title: "Home",
+ icon: "home"
+ }
+ }, {
+ id: "chain",
+ menu: {
+ title: "Chain",
+ icon: "link"
+ }
+ }, {
+ id: "txpool",
+ menu: {
+ title: "TxPool",
+ icon: "credit-card"
+ }
+ }, {
+ id: "network",
+ menu: {
+ title: "Network",
+ icon: "globe"
+ }
+ }, {
+ id: "system",
+ menu: {
+ title: "System",
+ icon: "tachometer"
+ }
+ }, {
+ id: "logs",
+ menu: {
+ title: "Logs",
+ icon: "list"
+ }
+ } ];
+ exports.MENU = new Map(menuSkeletons.map(function(_ref) {
+ var id = _ref.id, menu = _ref.menu;
+ return [ id, _extends({
+ id: id
+ }, menu) ];
+ })), exports.DURATION = 200, exports.styles = {
+ light: {
+ color: "rgba(255, 255, 255, 0.54)"
+ }
+ };
}, function(module, exports, __webpack_require__) {
function isSymbol(value) {
return "symbol" == typeof value || isObjectLike(value) && baseGetTag(value) == symbolTag;
}
- var baseGetTag = __webpack_require__(59), isObjectLike = __webpack_require__(52), symbolTag = "[object Symbol]";
+ var baseGetTag = __webpack_require__(42), isObjectLike = __webpack_require__(36), symbolTag = "[object Symbol]";
module.exports = isSymbol;
}, function(module, exports) {
function identity(value) {
@@ -3964,7 +3747,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), __WEBPACK_IMPORTED_MODULE_3_react_smooth__ = __webpack_require__(48), __WEBPACK_IMPORTED_MODULE_3_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_react_smooth__), __WEBPACK_IMPORTED_MODULE_4__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_5__util_ReactUtils__ = __webpack_require__(7), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), __WEBPACK_IMPORTED_MODULE_3_react_smooth__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_3_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_react_smooth__), __WEBPACK_IMPORTED_MODULE_4__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_5__util_ReactUtils__ = __webpack_require__(4), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -4009,12 +3792,12 @@ var _publicBundleJs = []byte(`!function(modules) {
return _inherits(Rectangle, _Component), _createClass(Rectangle, [ {
key: "componentDidMount",
value: function() {
- if (this.node && this.node.getTotalLength) {
+ if (this.node && this.node.getTotalLength) try {
var totalLength = this.node.getTotalLength();
totalLength && this.setState({
totalLength: totalLength
});
- }
+ } catch (err) {}
}
}, {
key: "render",
@@ -4109,7 +3892,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isArray__ = __webpack_require__(16), __WEBPACK_IMPORTED_MODULE_0_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_2_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_react__), __WEBPACK_IMPORTED_MODULE_3_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_3_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_prop_types__), __WEBPACK_IMPORTED_MODULE_4_d3_shape__ = __webpack_require__(235), __WEBPACK_IMPORTED_MODULE_5_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_5_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_classnames__), __WEBPACK_IMPORTED_MODULE_6__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_7__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_8__util_DataUtils__ = __webpack_require__(12), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isArray__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_0_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_react__), __WEBPACK_IMPORTED_MODULE_3_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_3_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_prop_types__), __WEBPACK_IMPORTED_MODULE_4_d3_shape__ = __webpack_require__(173), __WEBPACK_IMPORTED_MODULE_5_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_5_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_classnames__), __WEBPACK_IMPORTED_MODULE_6__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_7__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_8__util_DataUtils__ = __webpack_require__(9), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -4223,8 +4006,8 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = (__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__),
- __webpack_require__(2)), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_3__util_ReactUtils__ = __webpack_require__(7), _createClass = function() {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = (__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__),
+ __webpack_require__(1)), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_3__util_ReactUtils__ = __webpack_require__(4), _createClass = function() {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
@@ -4318,8 +4101,8 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = (__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__),
- __webpack_require__(2)), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2__util_PureRender__ = __webpack_require__(8), _createClass = function() {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = (__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__),
+ __webpack_require__(1)), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2__util_PureRender__ = __webpack_require__(5), _createClass = function() {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
@@ -4446,7 +4229,7 @@ var _publicBundleJs = []byte(`!function(modules) {
"production" !== process.env.NODE_ENV && (validateFormat = function(format) {
if (void 0 === format) throw new Error("invariant requires an error message argument");
}), module.exports = invariant;
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports) {
module.exports = function(bitmap, value) {
return {
@@ -4457,7 +4240,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
};
}, function(module, exports, __webpack_require__) {
- var $keys = __webpack_require__(272), enumBugKeys = __webpack_require__(183);
+ var $keys = __webpack_require__(209), enumBugKeys = __webpack_require__(141);
module.exports = Object.keys || function(O) {
return $keys(O, enumBugKeys);
};
@@ -4475,7 +4258,8 @@ var _publicBundleJs = []byte(`!function(modules) {
return "@media (min-width:" + ("number" == typeof values[key] ? values[key] : key) + unit + ")";
}
function down(key) {
- return "@media (max-width:" + (("number" == typeof values[key] ? values[key] : key) - step / 100) + unit + ")";
+ var endIndex = keys.indexOf(key) + 1, upperbound = values[keys[endIndex]];
+ return endIndex === keys.length ? up("xs") : "@media (max-width:" + (("number" == typeof upperbound && endIndex > 0 ? upperbound : key) - step / 100) + unit + ")";
}
function between(start, end) {
var endIndex = keys.indexOf(end) + 1;
@@ -4508,13 +4292,13 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.keys = void 0;
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
exports.default = createBreakpoints;
var keys = exports.keys = [ "xs", "sm", "md", "lg", "xl" ];
}, function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = !0;
- var _getDisplayName = __webpack_require__(289), _getDisplayName2 = function(obj) {
+ var _getDisplayName = __webpack_require__(226), _getDisplayName2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -4553,7 +4337,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _createRule = __webpack_require__(131), _createRule2 = _interopRequireDefault(_createRule), _linkRule = __webpack_require__(294), _linkRule2 = _interopRequireDefault(_linkRule), _StyleRule = __webpack_require__(77), _StyleRule2 = _interopRequireDefault(_StyleRule), _escape = __webpack_require__(546), _escape2 = _interopRequireDefault(_escape), RuleList = function() {
+ }(), _createRule = __webpack_require__(106), _createRule2 = _interopRequireDefault(_createRule), _linkRule = __webpack_require__(231), _linkRule2 = _interopRequireDefault(_linkRule), _StyleRule = __webpack_require__(60), _StyleRule2 = _interopRequireDefault(_StyleRule), _escape = __webpack_require__(424), _escape2 = _interopRequireDefault(_escape), RuleList = function() {
function RuleList(options) {
_classCallCheck(this, RuleList), this.map = {}, this.raw = {}, this.index = [],
this.options = options, this.classes = options.classes;
@@ -4639,53 +4423,9 @@ var _publicBundleJs = []byte(`!function(modules) {
} ]), RuleList;
}();
exports.default = RuleList;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__map__ = __webpack_require__(27), __WEBPACK_IMPORTED_MODULE_2__prop__ = __webpack_require__(201), pluck = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(p, list) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__map__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__prop__.a)(p), list);
- });
- __webpack_exports__.a = pluck;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _isString(x) {
- return "[object String]" === Object.prototype.toString.call(x);
- }
- __webpack_exports__.a = _isString;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _checkForMethod(methodname, fn) {
- return function() {
- var length = arguments.length;
- if (0 === length) return fn();
- var obj = arguments[length - 1];
- return Object(__WEBPACK_IMPORTED_MODULE_0__isArray__.a)(obj) || "function" != typeof obj[methodname] ? fn.apply(this, arguments) : obj[methodname].apply(obj, Array.prototype.slice.call(arguments, 0, length - 1));
- };
- }
- __webpack_exports__.a = _checkForMethod;
- var __WEBPACK_IMPORTED_MODULE_0__isArray__ = __webpack_require__(57);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__internal_toString__ = __webpack_require__(604), toString = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(val) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__internal_toString__.a)(val, []);
- });
- __webpack_exports__.a = toString;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_isString__ = __webpack_require__(98), nth = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(offset, list) {
- var idx = offset < 0 ? list.length + offset : offset;
- return Object(__WEBPACK_IMPORTED_MODULE_1__internal_isString__.a)(list) ? list.charAt(idx) : list[idx];
- });
- __webpack_exports__.a = nth;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_isFunction__ = __webpack_require__(140), __WEBPACK_IMPORTED_MODULE_2__curryN__ = __webpack_require__(23), __WEBPACK_IMPORTED_MODULE_3__toString__ = __webpack_require__(100), invoker = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(arity, method) {
- return Object(__WEBPACK_IMPORTED_MODULE_2__curryN__.a)(arity + 1, function() {
- var target = arguments[arity];
- if (null != target && Object(__WEBPACK_IMPORTED_MODULE_1__internal_isFunction__.a)(target[method])) return target[method].apply(target, Array.prototype.slice.call(arguments, 0, arity));
- throw new TypeError(Object(__WEBPACK_IMPORTED_MODULE_3__toString__.a)(target) + ' does not have a method named "' + method + '"');
- });
- });
- __webpack_exports__.a = invoker;
+}, function(module, exports, __webpack_require__) {
+ var root = __webpack_require__(32), Symbol = root.Symbol;
+ module.exports = Symbol;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
function _objectWithoutProperties(obj, keys) {
@@ -4709,7 +4449,7 @@ var _publicBundleJs = []byte(`!function(modules) {
version: "1.1"
}), children);
}
- var __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), __WEBPACK_IMPORTED_MODULE_3__util_ReactUtils__ = __webpack_require__(7), _extends = Object.assign || function(target) {
+ var __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), __WEBPACK_IMPORTED_MODULE_3__util_ReactUtils__ = __webpack_require__(4), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -4729,12 +4469,9 @@ var _publicBundleJs = []byte(`!function(modules) {
children: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.oneOfType([ __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.arrayOf(__WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.node), __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.node ])
};
Surface.propTypes = propTypes, __webpack_exports__.a = Surface;
-}, function(module, exports, __webpack_require__) {
- var root = __webpack_require__(46), Symbol = root.Symbol;
- module.exports = Symbol;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__src_path__ = __webpack_require__(891);
+ var __WEBPACK_IMPORTED_MODULE_0__src_path__ = __webpack_require__(584);
__webpack_require__.d(__webpack_exports__, "a", function() {
return __WEBPACK_IMPORTED_MODULE_0__src_path__.a;
});
@@ -4786,21 +4523,21 @@ var _publicBundleJs = []byte(`!function(modules) {
function isArrayLike(value) {
return null != value && isLength(value.length) && !isFunction(value);
}
- var isFunction = __webpack_require__(11), isLength = __webpack_require__(244);
+ var isFunction = __webpack_require__(8), isLength = __webpack_require__(182);
module.exports = isArrayLike;
}, function(module, exports, __webpack_require__) {
function baseIteratee(value) {
return "function" == typeof value ? value : null == value ? identity : "object" == typeof value ? isArray(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value) : property(value);
}
- var baseMatches = __webpack_require__(976), baseMatchesProperty = __webpack_require__(979), identity = __webpack_require__(83), isArray = __webpack_require__(16), property = __webpack_require__(983);
+ var baseMatches = __webpack_require__(669), baseMatchesProperty = __webpack_require__(672), identity = __webpack_require__(63), isArray = __webpack_require__(12), property = __webpack_require__(676);
module.exports = baseIteratee;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
function Cell() {
return null;
}
- var __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1__util_ReactUtils__ = (__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__),
- __webpack_require__(7)), _extends = Object.assign || function(target) {
+ var __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__util_ReactUtils__ = (__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__),
+ __webpack_require__(4)), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -4843,29 +4580,29 @@ var _publicBundleJs = []byte(`!function(modules) {
}, linearish(scale);
}
__webpack_exports__.b = linearish, __webpack_exports__.a = linear;
- var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(53), __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__ = __webpack_require__(114), __WEBPACK_IMPORTED_MODULE_2__continuous__ = __webpack_require__(168), __WEBPACK_IMPORTED_MODULE_3__tickFormat__ = __webpack_require__(1050);
+ var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(37), __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__ = __webpack_require__(88), __WEBPACK_IMPORTED_MODULE_2__continuous__ = __webpack_require__(126), __WEBPACK_IMPORTED_MODULE_3__tickFormat__ = __webpack_require__(742);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__src_value__ = __webpack_require__(250);
+ var __WEBPACK_IMPORTED_MODULE_0__src_value__ = __webpack_require__(187);
__webpack_require__.d(__webpack_exports__, "a", function() {
return __WEBPACK_IMPORTED_MODULE_0__src_value__.a;
});
- var __WEBPACK_IMPORTED_MODULE_5__src_number__ = (__webpack_require__(426), __webpack_require__(253),
- __webpack_require__(424), __webpack_require__(427), __webpack_require__(167));
+ var __WEBPACK_IMPORTED_MODULE_5__src_number__ = (__webpack_require__(305), __webpack_require__(190),
+ __webpack_require__(303), __webpack_require__(306), __webpack_require__(125));
__webpack_require__.d(__webpack_exports__, "c", function() {
return __WEBPACK_IMPORTED_MODULE_5__src_number__.a;
});
- var __WEBPACK_IMPORTED_MODULE_7__src_round__ = (__webpack_require__(428), __webpack_require__(1040));
+ var __WEBPACK_IMPORTED_MODULE_7__src_round__ = (__webpack_require__(307), __webpack_require__(732));
__webpack_require__.d(__webpack_exports__, "d", function() {
return __WEBPACK_IMPORTED_MODULE_7__src_round__.a;
});
- var __WEBPACK_IMPORTED_MODULE_15__src_cubehelix__ = (__webpack_require__(429), __webpack_require__(1041),
- __webpack_require__(1044), __webpack_require__(423), __webpack_require__(1045),
- __webpack_require__(1046), __webpack_require__(1047), __webpack_require__(1048));
+ var __WEBPACK_IMPORTED_MODULE_15__src_cubehelix__ = (__webpack_require__(308), __webpack_require__(733),
+ __webpack_require__(736), __webpack_require__(302), __webpack_require__(737), __webpack_require__(738),
+ __webpack_require__(739), __webpack_require__(740));
__webpack_require__.d(__webpack_exports__, "b", function() {
return __WEBPACK_IMPORTED_MODULE_15__src_cubehelix__.a;
});
- __webpack_require__(1049);
+ __webpack_require__(741);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
function linear(a, d) {
@@ -4892,7 +4629,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return d ? linear(a, d) : Object(__WEBPACK_IMPORTED_MODULE_0__constant__.a)(isNaN(a) ? b : a);
}
__webpack_exports__.c = hue, __webpack_exports__.b = gamma, __webpack_exports__.a = nogamma;
- var __WEBPACK_IMPORTED_MODULE_0__constant__ = __webpack_require__(425);
+ var __WEBPACK_IMPORTED_MODULE_0__constant__ = __webpack_require__(304);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_exports__.a = function(s) {
@@ -4925,7 +4662,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_3__util_ReactUtils__ = __webpack_require__(7), _extends = Object.assign || function(target) {
+ var _class, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_3__util_ReactUtils__ = __webpack_require__(4), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -5036,7 +4773,7 @@ var _publicBundleJs = []byte(`!function(modules) {
__webpack_require__.d(__webpack_exports__, "a", function() {
return formatAxisMap;
});
- var __WEBPACK_IMPORTED_MODULE_0__ChartUtils__ = __webpack_require__(21), _extends = Object.assign || function(target) {
+ var __WEBPACK_IMPORTED_MODULE_0__ChartUtils__ = __webpack_require__(16), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -5083,11 +4820,11 @@ var _publicBundleJs = []byte(`!function(modules) {
(function(process) {
var emptyObject = {};
"production" !== process.env.NODE_ENV && Object.freeze(emptyObject), module.exports = emptyObject;
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
- var emptyFunction = __webpack_require__(55), warning = emptyFunction;
+ var emptyFunction = __webpack_require__(39), warning = emptyFunction;
if ("production" !== process.env.NODE_ENV) {
var printWarning = function(format) {
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) args[_key - 1] = arguments[_key];
@@ -5100,7 +4837,7 @@ var _publicBundleJs = []byte(`!function(modules) {
} catch (x) {}
};
warning = function(condition, format) {
- if (void 0 === format) throw new Error("` + "`" + `warning(condition, format, ...args)` + "`" + ` requires a warning message argument");
+ if (void 0 === format) throw new Error("` + "`")) + (`warning(condition, format, ...args)` + ("`" + ` requires a warning message argument");
if (0 !== format.indexOf("Failed Composite propType: ") && !condition) {
for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) args[_key2 - 2] = arguments[_key2];
printWarning.apply(void 0, [ format ].concat(args));
@@ -5108,7 +4845,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}
module.exports = warning;
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -5122,8 +4859,8 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}
}
- "production" === process.env.NODE_ENV ? (checkDCE(), module.exports = __webpack_require__(456)) : module.exports = __webpack_require__(459);
- }).call(exports, __webpack_require__(3));
+ "production" === process.env.NODE_ENV ? (checkDCE(), module.exports = __webpack_require__(334)) : module.exports = __webpack_require__(337);
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
function is(x, y) {
@@ -5140,7 +4877,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var hasOwnProperty = Object.prototype.hasOwnProperty;
module.exports = shallowEqual;
}, function(module, exports, __webpack_require__) {
- var toInteger = __webpack_require__(180), min = Math.min;
+ var toInteger = __webpack_require__(138), min = Math.min;
module.exports = function(it) {
return it > 0 ? min(toInteger(it), 9007199254740991) : 0;
};
@@ -5159,7 +4896,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}
exports.__esModule = !0;
- var _iterator = __webpack_require__(474), _iterator2 = _interopRequireDefault(_iterator), _symbol = __webpack_require__(482), _symbol2 = _interopRequireDefault(_symbol), _typeof = "function" == typeof _symbol2.default && "symbol" == typeof _iterator2.default ? function(obj) {
+ var _iterator = __webpack_require__(352), _iterator2 = _interopRequireDefault(_iterator), _symbol = __webpack_require__(360), _symbol2 = _interopRequireDefault(_symbol), _typeof = "function" == typeof _symbol2.default && "symbol" == typeof _iterator2.default ? function(obj) {
return typeof obj;
} : function(obj) {
return obj && "function" == typeof _symbol2.default && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : typeof obj;
@@ -5170,9 +4907,9 @@ var _publicBundleJs = []byte(`!function(modules) {
return obj && "function" == typeof _symbol2.default && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : void 0 === obj ? "undefined" : _typeof(obj);
};
}, function(module, exports, __webpack_require__) {
- var anObject = __webpack_require__(65), dPs = __webpack_require__(478), enumBugKeys = __webpack_require__(183), IE_PROTO = __webpack_require__(181)("IE_PROTO"), Empty = function() {}, createDict = function() {
- var iframeDocument, iframe = __webpack_require__(271)("iframe"), i = enumBugKeys.length;
- for (iframe.style.display = "none", __webpack_require__(479).appendChild(iframe),
+ var anObject = __webpack_require__(48), dPs = __webpack_require__(356), enumBugKeys = __webpack_require__(141), IE_PROTO = __webpack_require__(139)("IE_PROTO"), Empty = function() {}, createDict = function() {
+ var iframeDocument, iframe = __webpack_require__(208)("iframe"), i = enumBugKeys.length;
+ for (iframe.style.display = "none", __webpack_require__(357).appendChild(iframe),
iframe.src = "javascript:", iframeDocument = iframe.contentWindow.document, iframeDocument.open(),
iframeDocument.write("<script>document.F=Object<\/script>"), iframeDocument.close(),
createDict = iframeDocument.F; i--; ) delete createDict.prototype[enumBugKeys[i]];
@@ -5184,7 +4921,7 @@ var _publicBundleJs = []byte(`!function(modules) {
result[IE_PROTO] = O) : result = createDict(), void 0 === Properties ? result : dPs(result, Properties);
};
}, function(module, exports, __webpack_require__) {
- var def = __webpack_require__(32).f, has = __webpack_require__(67), TAG = __webpack_require__(29)("toStringTag");
+ var def = __webpack_require__(22).f, has = __webpack_require__(50), TAG = __webpack_require__(21)("toStringTag");
module.exports = function(it, tag, stat) {
it && !has(it = stat ? it : it.prototype, TAG) && def(it, TAG, {
configurable: !0,
@@ -5244,7 +4981,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var deepmerge_1 = deepmerge;
__webpack_exports__.default = deepmerge_1;
}, function(module, exports, __webpack_require__) {
- var ctx = __webpack_require__(64), call = __webpack_require__(284), isArrayIter = __webpack_require__(285), anObject = __webpack_require__(65), toLength = __webpack_require__(123), getIterFn = __webpack_require__(286), BREAK = {}, RETURN = {}, exports = module.exports = function(iterable, entries, fn, that, ITERATOR) {
+ var ctx = __webpack_require__(47), call = __webpack_require__(221), isArrayIter = __webpack_require__(222), anObject = __webpack_require__(48), toLength = __webpack_require__(97), getIterFn = __webpack_require__(223), BREAK = {}, RETURN = {}, exports = module.exports = function(iterable, entries, fn, that, ITERATOR) {
var length, step, iterator, result, iterFn = ITERATOR ? function() {
return iterable;
} : getIterFn(iterable), f = ctx(fn, that, entries ? 2 : 1), index = 0;
@@ -5256,6 +4993,25 @@ var _publicBundleJs = []byte(`!function(modules) {
exports.BREAK = BREAK, exports.RETURN = RETURN;
}, function(module, exports, __webpack_require__) {
"use strict";
+ function toCssValue(value) {
+ var ignoreImportant = arguments.length > 1 && void 0 !== arguments[1] && arguments[1];
+ if (!Array.isArray(value)) return value;
+ var cssValue = "";
+ if (Array.isArray(value[0])) for (var i = 0; i < value.length && "!important" !== value[i]; i++) cssValue && (cssValue += ", "),
+ cssValue += join(value[i], " "); else cssValue = join(value, ", ");
+ return ignoreImportant || "!important" !== value[value.length - 1] || (cssValue += " !important"),
+ cssValue;
+ }
+ Object.defineProperty(exports, "__esModule", {
+ value: !0
+ }), exports.default = toCssValue;
+ var join = function(value, by) {
+ for (var result = "", i = 0; i < value.length && "!important" !== value[i]; i++) result && (result += by),
+ result += value[i];
+ return result;
+ };
+}, function(module, exports, __webpack_require__) {
+ "use strict";
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
@@ -5270,7 +5026,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.default = createRule;
- var _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), _StyleRule = __webpack_require__(77), _StyleRule2 = _interopRequireDefault(_StyleRule), _cloneStyle = __webpack_require__(542), _cloneStyle2 = _interopRequireDefault(_cloneStyle);
+ var _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), _StyleRule = __webpack_require__(60), _StyleRule2 = _interopRequireDefault(_StyleRule), _cloneStyle = __webpack_require__(420), _cloneStyle2 = _interopRequireDefault(_cloneStyle);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", {
@@ -5284,192 +5040,6 @@ var _publicBundleJs = []byte(`!function(modules) {
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
}, isBrowser = "object" === ("undefined" == typeof window ? "undefined" : _typeof(window)) && "object" === ("undefined" == typeof document ? "undefined" : _typeof(document)) && 9 === document.nodeType;
__webpack_exports__.default = isBrowser;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _isPlaceholder(a) {
- return null != a && "object" == typeof a && !0 === a["@@functional/placeholder"];
- }
- __webpack_exports__.a = _isPlaceholder;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), add = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- return Number(a) + Number(b);
- });
- __webpack_exports__.a = add;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _curryN(length, received, fn) {
- return function() {
- for (var combined = [], argsIdx = 0, left = length, combinedIdx = 0; combinedIdx < received.length || argsIdx < arguments.length; ) {
- var result;
- combinedIdx < received.length && (!Object(__WEBPACK_IMPORTED_MODULE_1__isPlaceholder__.a)(received[combinedIdx]) || argsIdx >= arguments.length) ? result = received[combinedIdx] : (result = arguments[argsIdx],
- argsIdx += 1), combined[combinedIdx] = result, Object(__WEBPACK_IMPORTED_MODULE_1__isPlaceholder__.a)(result) || (left -= 1),
- combinedIdx += 1;
- }
- return left <= 0 ? fn.apply(this, combined) : Object(__WEBPACK_IMPORTED_MODULE_0__arity__.a)(left, _curryN(length, combined, fn));
- };
- }
- __webpack_exports__.a = _curryN;
- var __WEBPACK_IMPORTED_MODULE_0__arity__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_1__isPlaceholder__ = __webpack_require__(133);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _map(fn, functor) {
- for (var idx = 0, len = functor.length, result = Array(len); idx < len; ) result[idx] = fn(functor[idx]),
- idx += 1;
- return result;
- }
- __webpack_exports__.a = _map;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__isArray__ = __webpack_require__(57), __WEBPACK_IMPORTED_MODULE_2__isString__ = __webpack_require__(98), _isArrayLike = Object(__WEBPACK_IMPORTED_MODULE_0__curry1__.a)(function(x) {
- return !!Object(__WEBPACK_IMPORTED_MODULE_1__isArray__.a)(x) || !!x && ("object" == typeof x && (!Object(__WEBPACK_IMPORTED_MODULE_2__isString__.a)(x) && (1 === x.nodeType ? !!x.length : 0 === x.length || x.length > 0 && (x.hasOwnProperty(0) && x.hasOwnProperty(x.length - 1)))));
- });
- __webpack_exports__.a = _isArrayLike;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), assoc = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(prop, val, obj) {
- var result = {};
- for (var p in obj) result[p] = obj[p];
- return result[prop] = val, result;
- });
- __webpack_exports__.a = assoc;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), nAry = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(n, fn) {
- switch (n) {
- case 0:
- return function() {
- return fn.call(this);
- };
-
- case 1:
- return function(a0) {
- return fn.call(this, a0);
- };
-
- case 2:
- return function(a0, a1) {
- return fn.call(this, a0, a1);
- };
-
- case 3:
- return function(a0, a1, a2) {
- return fn.call(this, a0, a1, a2);
- };
-
- case 4:
- return function(a0, a1, a2, a3) {
- return fn.call(this, a0, a1, a2, a3);
- };
-
- case 5:
- return function(a0, a1, a2, a3, a4) {
- return fn.call(this, a0, a1, a2, a3, a4);
- };
-
- case 6:
- return function(a0, a1, a2, a3, a4, a5) {
- return fn.call(this, a0, a1, a2, a3, a4, a5);
- };
-
- case 7:
- return function(a0, a1, a2, a3, a4, a5, a6) {
- return fn.call(this, a0, a1, a2, a3, a4, a5, a6);
- };
-
- case 8:
- return function(a0, a1, a2, a3, a4, a5, a6, a7) {
- return fn.call(this, a0, a1, a2, a3, a4, a5, a6, a7);
- };
-
- case 9:
- return function(a0, a1, a2, a3, a4, a5, a6, a7, a8) {
- return fn.call(this, a0, a1, a2, a3, a4, a5, a6, a7, a8);
- };
-
- case 10:
- return function(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
- return fn.call(this, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
- };
-
- default:
- throw new Error("First argument to nAry must be a non-negative integer no greater than ten");
- }
- });
- __webpack_exports__.a = nAry;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _isFunction(x) {
- return "[object Function]" === Object.prototype.toString.call(x);
- }
- __webpack_exports__.a = _isFunction;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__liftN__ = __webpack_require__(308), lift = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(fn) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__liftN__.a)(fn.length, fn);
- });
- __webpack_exports__.a = lift;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__internal_isString__ = __webpack_require__(98), reverse = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(list) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__internal_isString__.a)(list) ? list.split("").reverse().join("") : Array.prototype.slice.call(list, 0).reverse();
- });
- __webpack_exports__.a = reverse;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _containsWith(pred, x, list) {
- for (var idx = 0, len = list.length; idx < len; ) {
- if (pred(x, list[idx])) return !0;
- idx += 1;
- }
- return !1;
- }
- __webpack_exports__.a = _containsWith;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_complement__ = __webpack_require__(318), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2__filter__ = __webpack_require__(210), reject = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(function(pred, filterable) {
- return Object(__WEBPACK_IMPORTED_MODULE_2__filter__.a)(Object(__WEBPACK_IMPORTED_MODULE_0__internal_complement__.a)(pred), filterable);
- });
- __webpack_exports__.a = reject;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curryN__ = __webpack_require__(135), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_has__ = __webpack_require__(26), __WEBPACK_IMPORTED_MODULE_3__internal_reduce__ = __webpack_require__(30), __WEBPACK_IMPORTED_MODULE_4__internal_xreduceBy__ = __webpack_require__(615), reduceBy = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curryN__.a)(4, [], Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([], __WEBPACK_IMPORTED_MODULE_4__internal_xreduceBy__.a, function(valueFn, valueAcc, keyFn, list) {
- return Object(__WEBPACK_IMPORTED_MODULE_3__internal_reduce__.a)(function(acc, elt) {
- var key = keyFn(elt);
- return acc[key] = valueFn(Object(__WEBPACK_IMPORTED_MODULE_2__internal_has__.a)(key, acc) ? acc[key] : valueAcc, elt),
- acc;
- }, {}, list);
- }));
- __webpack_exports__.a = reduceBy;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__curryN__ = __webpack_require__(23), flip = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(fn) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__curryN__.a)(fn.length, function(a, b) {
- var args = Array.prototype.slice.call(arguments, 0);
- return args[0] = b, args[1] = a, fn.apply(this, args);
- });
- });
- __webpack_exports__.a = flip;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__map__ = __webpack_require__(27), lens = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(getter, setter) {
- return function(toFunctorFn) {
- return function(target) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__map__.a)(function(focus) {
- return setter(focus, target);
- }, toFunctorFn(getter(target)));
- };
- };
- });
- __webpack_exports__.a = lens;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__internal_isObject__ = __webpack_require__(212), __WEBPACK_IMPORTED_MODULE_2__mergeWithKey__ = __webpack_require__(219), mergeDeepWithKey = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function mergeDeepWithKey(fn, lObj, rObj) {
- return Object(__WEBPACK_IMPORTED_MODULE_2__mergeWithKey__.a)(function(k, lVal, rVal) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__internal_isObject__.a)(lVal) && Object(__WEBPACK_IMPORTED_MODULE_1__internal_isObject__.a)(rVal) ? mergeDeepWithKey(fn, lVal, rVal) : fn(k, lVal, rVal);
- }, lObj, rObj);
- });
- __webpack_exports__.a = mergeDeepWithKey;
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -5503,12 +5073,12 @@ var _publicBundleJs = []byte(`!function(modules) {
}
function noop() {}
exports.__esModule = !0, exports.EXITING = exports.ENTERED = exports.ENTERING = exports.EXITED = exports.UNMOUNTED = void 0;
- var _propTypes = __webpack_require__(2), PropTypes = function(obj) {
+ var _propTypes = __webpack_require__(1), PropTypes = function(obj) {
if (obj && obj.__esModule) return obj;
var newObj = {};
if (null != obj) for (var key in obj) Object.prototype.hasOwnProperty.call(obj, key) && (newObj[key] = obj[key]);
return newObj.default = obj, newObj;
- }(_propTypes), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _reactDom = __webpack_require__(121), _reactDom2 = _interopRequireDefault(_reactDom), _PropTypes = __webpack_require__(781), UNMOUNTED = exports.UNMOUNTED = "unmounted", EXITED = exports.EXITED = "exited", ENTERING = exports.ENTERING = "entering", ENTERED = exports.ENTERED = "entered", EXITING = exports.EXITING = "exiting", Transition = function(_React$Component) {
+ }(_propTypes), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _reactDom = __webpack_require__(95), _reactDom2 = _interopRequireDefault(_reactDom), _PropTypes = __webpack_require__(460), UNMOUNTED = exports.UNMOUNTED = "unmounted", EXITED = exports.EXITED = "exited", ENTERING = exports.ENTERING = "entering", ENTERED = exports.ENTERED = "entered", EXITING = exports.EXITING = "exiting", Transition = function(_React$Component) {
function Transition(props, context) {
_classCallCheck(this, Transition);
var _this = _possibleConstructorReturn(this, _React$Component.call(this, props, context)), parentGroup = context.transitionGroup, appear = parentGroup && !parentGroup.isMounting ? props.enter : props.appear, initialStatus = void 0;
@@ -5654,94 +5224,24 @@ var _publicBundleJs = []byte(`!function(modules) {
onExited: noop
}, Transition.UNMOUNTED = 0, Transition.EXITED = 1, Transition.ENTERING = 2, Transition.ENTERED = 3,
Transition.EXITING = 4, exports.default = Transition;
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
- function _toConsumableArray(arr) {
- if (Array.isArray(arr)) {
- for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
- return arr2;
- }
- return Array.from(arr);
+ function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
}
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _extends = Object.assign || function(target) {
- for (var i = 1; i < arguments.length; i++) {
- var source = arguments[i];
- for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
- }
- return target;
- }, menuSkeletons = [ {
- id: "home",
- menu: {
- title: "Home",
- icon: "home"
- }
- }, {
- id: "chain",
- menu: {
- title: "Chain",
- icon: "link"
- }
- }, {
- id: "txpool",
- menu: {
- title: "TxPool",
- icon: "credit-card"
- }
- }, {
- id: "network",
- menu: {
- title: "Network",
- icon: "globe"
- }
- }, {
- id: "system",
- menu: {
- title: "System",
- icon: "tachometer"
- }
- }, {
- id: "logs",
- menu: {
- title: "Logs",
- icon: "list"
- }
- } ], sampleSkeletons = (exports.MENU = new Map(menuSkeletons.map(function(_ref) {
- var id = _ref.id, menu = _ref.menu;
- return [ id, _extends({
- id: id
- }, menu) ];
- })), [ {
- id: "memory",
- sample: {
- limit: 200
- }
- }, {
- id: "traffic",
- sample: {
- limit: 200
- }
- }, {
- id: "logs",
- sample: {
- limit: 200
+ var _Typography = __webpack_require__(480);
+ Object.defineProperty(exports, "default", {
+ enumerable: !0,
+ get: function() {
+ return _interopRequireDefault(_Typography).default;
}
- } ]);
- exports.SAMPLE = new Map(sampleSkeletons.map(function(_ref2) {
- var id = _ref2.id, sample = _ref2.sample;
- return [ id, _extends({
- id: id
- }, sample) ];
- })), exports.DURATION = 200, exports.LENS = new Map([ "content" ].concat(_toConsumableArray(menuSkeletons.map(function(_ref3) {
- return _ref3.id;
- })), _toConsumableArray(sampleSkeletons.map(function(_ref4) {
- return _ref4.id;
- }))).map(function(lens) {
- return [ lens, lens ];
- }));
+ });
}, function(module, exports) {
module.exports = function(exec) {
try {
@@ -5751,14 +5251,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
};
}, function(module, exports, __webpack_require__) {
- function get(object, path, defaultValue) {
- var result = null == object ? void 0 : baseGet(object, path);
- return void 0 === result ? defaultValue : result;
- }
- var baseGet = __webpack_require__(366);
- module.exports = get;
-}, function(module, exports, __webpack_require__) {
- var getNative = __webpack_require__(70), nativeCreate = getNative(Object, "create");
+ var getNative = __webpack_require__(53), nativeCreate = getNative(Object, "create");
module.exports = nativeCreate;
}, function(module, exports, __webpack_require__) {
function ListCache(entries) {
@@ -5768,7 +5261,7 @@ var _publicBundleJs = []byte(`!function(modules) {
this.set(entry[0], entry[1]);
}
}
- var listCacheClear = __webpack_require__(877), listCacheDelete = __webpack_require__(878), listCacheGet = __webpack_require__(879), listCacheHas = __webpack_require__(880), listCacheSet = __webpack_require__(881);
+ var listCacheClear = __webpack_require__(570), listCacheDelete = __webpack_require__(571), listCacheGet = __webpack_require__(572), listCacheHas = __webpack_require__(573), listCacheSet = __webpack_require__(574);
ListCache.prototype.clear = listCacheClear, ListCache.prototype.delete = listCacheDelete,
ListCache.prototype.get = listCacheGet, ListCache.prototype.has = listCacheHas,
ListCache.prototype.set = listCacheSet, module.exports = ListCache;
@@ -5777,14 +5270,14 @@ var _publicBundleJs = []byte(`!function(modules) {
for (var length = array.length; length--; ) if (eq(array[length][0], key)) return length;
return -1;
}
- var eq = __webpack_require__(230);
+ var eq = __webpack_require__(168);
module.exports = assocIndexOf;
}, function(module, exports, __webpack_require__) {
function getMapData(map, key) {
var data = map.__data__;
return isKeyable(key) ? data["string" == typeof key ? "string" : "hash"] : data.map;
}
- var isKeyable = __webpack_require__(883);
+ var isKeyable = __webpack_require__(576);
module.exports = getMapData;
}, function(module, exports) {
function arrayMap(array, iteratee) {
@@ -5798,13 +5291,13 @@ var _publicBundleJs = []byte(`!function(modules) {
var result = value + "";
return "0" == result && 1 / value == -INFINITY ? "-0" : result;
}
- var isSymbol = __webpack_require__(82), INFINITY = 1 / 0;
+ var isSymbol = __webpack_require__(62), INFINITY = 1 / 0;
module.exports = toKey;
}, function(module, exports, __webpack_require__) {
function isNaN(value) {
return isNumber(value) && value != +value;
}
- var isNumber = __webpack_require__(232);
+ var isNumber = __webpack_require__(170);
module.exports = isNaN;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -5972,8 +5465,8 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isNil__ = __webpack_require__(28), __WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_2_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_react__), __WEBPACK_IMPORTED_MODULE_3_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_3_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_prop_types__), __WEBPACK_IMPORTED_MODULE_4_react_smooth__ = __webpack_require__(48), __WEBPACK_IMPORTED_MODULE_5__DefaultTooltipContent__ = (__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react_smooth__),
- __webpack_require__(988)), __WEBPACK_IMPORTED_MODULE_6__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_7__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_8__util_PureRender__ = __webpack_require__(8), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isNil__ = __webpack_require__(20), __WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_react__), __WEBPACK_IMPORTED_MODULE_3_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_3_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_prop_types__), __WEBPACK_IMPORTED_MODULE_4_react_smooth__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_5__DefaultTooltipContent__ = (__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react_smooth__),
+ __webpack_require__(681)), __WEBPACK_IMPORTED_MODULE_6__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_7__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_8__util_PureRender__ = __webpack_require__(5), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -6025,7 +5518,8 @@ var _publicBundleJs = []byte(`!function(modules) {
animationDuration: __WEBPACK_IMPORTED_MODULE_3_prop_types___default.a.number,
animationEasing: __WEBPACK_IMPORTED_MODULE_3_prop_types___default.a.oneOf([ "ease", "ease-in", "ease-out", "ease-in-out", "linear" ]),
itemSorter: __WEBPACK_IMPORTED_MODULE_3_prop_types___default.a.func,
- filterNull: __WEBPACK_IMPORTED_MODULE_3_prop_types___default.a.bool
+ filterNull: __WEBPACK_IMPORTED_MODULE_3_prop_types___default.a.bool,
+ useTranslate3d: __WEBPACK_IMPORTED_MODULE_3_prop_types___default.a.bool
}, defaultProps = {
active: !1,
offset: 10,
@@ -6051,7 +5545,8 @@ var _publicBundleJs = []byte(`!function(modules) {
itemSorter: function() {
return -1;
},
- filterNull: !0
+ filterNull: !0,
+ useTranslate3d: !1
}, renderContent = function(content, props) {
return __WEBPACK_IMPORTED_MODULE_2_react___default.a.isValidElement(content) ? __WEBPACK_IMPORTED_MODULE_2_react___default.a.cloneElement(content, props) : __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default()(content) ? content(props) : __WEBPACK_IMPORTED_MODULE_2_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_5__DefaultTooltipContent__.a, props);
}, Tooltip = Object(__WEBPACK_IMPORTED_MODULE_8__util_PureRender__.a)((_temp2 = _class2 = function(_Component) {
@@ -6108,7 +5603,7 @@ var _publicBundleJs = []byte(`!function(modules) {
translateY = position && Object(__WEBPACK_IMPORTED_MODULE_7__util_DataUtils__.g)(position.y) ? position.y : Math.max(coordinate.y + boxHeight + offset > viewBox.y + viewBox.height ? coordinate.y - boxHeight - offset : coordinate.y + offset, viewBox.y)) : outerStyle.visibility = "hidden";
}
return outerStyle = _extends({}, outerStyle, Object(__WEBPACK_IMPORTED_MODULE_4_react_smooth__.translateStyle)({
- transform: "translate(" + translateX + "px, " + translateY + "px)"
+ transform: this.props.useTranslate3d ? "translate3d(" + translateX + "px, " + translateY + "px, 0)" : "translate(" + translateX + "px, " + translateY + "px)"
})), isAnimationActive && active && (outerStyle = _extends({}, outerStyle, Object(__WEBPACK_IMPORTED_MODULE_4_react_smooth__.translateStyle)({
transition: "transform " + animationDuration + "ms " + animationEasing
}))), __WEBPACK_IMPORTED_MODULE_2_react___default.a.createElement("div", {
@@ -6139,7 +5634,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.warn = exports.getTransitionVal = exports.compose = exports.translateStyle = exports.mapObject = exports.debugf = exports.debug = exports.log = exports.generatePrefixStyle = exports.getDashCase = exports.identity = exports.getIntersectionKeys = void 0;
- var _intersection2 = __webpack_require__(952), _intersection3 = function(obj) {
+ var _intersection2 = __webpack_require__(645), _intersection3 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -6210,7 +5705,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}));
}
};
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
function baseExtremum(array, iteratee, comparator) {
for (var index = -1, length = array.length; ++index < length; ) {
@@ -6219,7 +5714,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return result;
}
- var isSymbol = __webpack_require__(82);
+ var isSymbol = __webpack_require__(62);
module.exports = baseExtremum;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -6297,10 +5792,10 @@ var _publicBundleJs = []byte(`!function(modules) {
}, rescale();
}
__webpack_exports__.c = deinterpolateLinear, __webpack_exports__.a = copy, __webpack_exports__.b = continuous;
- var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(53), __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__ = __webpack_require__(114), __WEBPACK_IMPORTED_MODULE_2__array__ = __webpack_require__(73), __WEBPACK_IMPORTED_MODULE_3__constant__ = __webpack_require__(254), __WEBPACK_IMPORTED_MODULE_4__number__ = __webpack_require__(430), unit = [ 0, 1 ];
+ var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(37), __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__ = __webpack_require__(88), __WEBPACK_IMPORTED_MODULE_2__array__ = __webpack_require__(56), __WEBPACK_IMPORTED_MODULE_3__constant__ = __webpack_require__(191), __WEBPACK_IMPORTED_MODULE_4__number__ = __webpack_require__(309), unit = [ 0, 1 ];
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__formatDecimal__ = __webpack_require__(255);
+ var __WEBPACK_IMPORTED_MODULE_0__formatDecimal__ = __webpack_require__(192);
__webpack_exports__.a = function(x) {
return x = Object(__WEBPACK_IMPORTED_MODULE_0__formatDecimal__.a)(Math.abs(x)),
x ? x[1] : NaN;
@@ -6325,7 +5820,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_4__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_5__util_PolarUtils__ = __webpack_require__(35), __WEBPACK_IMPORTED_MODULE_6__util_DataUtils__ = __webpack_require__(12), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_4__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_5__util_PolarUtils__ = __webpack_require__(23), __WEBPACK_IMPORTED_MODULE_6__util_DataUtils__ = __webpack_require__(9), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -6483,7 +5978,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_lodash_minBy__ = __webpack_require__(1091), __WEBPACK_IMPORTED_MODULE_1_lodash_minBy___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_minBy__), __WEBPACK_IMPORTED_MODULE_2_lodash_maxBy__ = __webpack_require__(445), __WEBPACK_IMPORTED_MODULE_2_lodash_maxBy___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_maxBy__), __WEBPACK_IMPORTED_MODULE_3_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_3_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_react__), __WEBPACK_IMPORTED_MODULE_4_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_4_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_prop_types__), __WEBPACK_IMPORTED_MODULE_5__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_6__component_Text__ = __webpack_require__(72), __WEBPACK_IMPORTED_MODULE_7__component_Label__ = __webpack_require__(60), __WEBPACK_IMPORTED_MODULE_8__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_9__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_10__util_PolarUtils__ = __webpack_require__(35), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_lodash_minBy__ = __webpack_require__(783), __WEBPACK_IMPORTED_MODULE_1_lodash_minBy___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_minBy__), __WEBPACK_IMPORTED_MODULE_2_lodash_maxBy__ = __webpack_require__(324), __WEBPACK_IMPORTED_MODULE_2_lodash_maxBy___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_maxBy__), __WEBPACK_IMPORTED_MODULE_3_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_3_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_react__), __WEBPACK_IMPORTED_MODULE_4_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_4_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_prop_types__), __WEBPACK_IMPORTED_MODULE_5__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_6__component_Text__ = __webpack_require__(55), __WEBPACK_IMPORTED_MODULE_7__component_Label__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_8__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_9__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_10__util_PolarUtils__ = __webpack_require__(23), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -6662,7 +6157,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_4__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_5__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_6__shape_Dot__ = __webpack_require__(74), __WEBPACK_IMPORTED_MODULE_7__shape_Polygon__ = __webpack_require__(258), __WEBPACK_IMPORTED_MODULE_8__component_Text__ = __webpack_require__(72), __WEBPACK_IMPORTED_MODULE_9__util_PolarUtils__ = __webpack_require__(35), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_4__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_5__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_6__shape_Dot__ = __webpack_require__(57), __WEBPACK_IMPORTED_MODULE_7__shape_Polygon__ = __webpack_require__(195), __WEBPACK_IMPORTED_MODULE_8__component_Text__ = __webpack_require__(55), __WEBPACK_IMPORTED_MODULE_9__util_PolarUtils__ = __webpack_require__(23), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -6824,8 +6319,8 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = (__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__),
- __webpack_require__(2)), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2__util_PureRender__ = __webpack_require__(8), _createClass = function() {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = (__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__),
+ __webpack_require__(1)), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2__util_PureRender__ = __webpack_require__(5), _createClass = function() {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
@@ -6870,12 +6365,12 @@ var _publicBundleJs = []byte(`!function(modules) {
if ("production" !== process.env.NODE_ENV) for (var typeSpecName in typeSpecs) if (typeSpecs.hasOwnProperty(typeSpecName)) {
var error;
try {
- invariant("function" == typeof typeSpecs[typeSpecName], "%s: %s type ` + "`" + `%s` + "`" + ` is invalid; it must be a function, usually from the ` + "`" + `prop-types` + "`" + ` package, but received ` + "`" + `%s` + "`" + `.", componentName || "React class", location, typeSpecName, typeof typeSpecs[typeSpecName]),
+ invariant("function" == typeof typeSpecs[typeSpecName], "%s: %s type `))) + (("`" + (`%s` + "`")) + (` is invalid; it must be a function, usually from the ` + ("`" + `prop-types`))))) + (((("`" + (` package, but received ` + "`")) + (`%s` + ("`" + `.", componentName || "React class", location, typeSpecName, typeof typeSpecs[typeSpecName]),
error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);
} catch (ex) {
error = ex;
}
- if (warning(!error || error instanceof Error, "%s: type specification of %s ` + "`" + `%s` + "`" + ` is invalid; the type checker function must return ` + "`" + `null` + "`" + ` or an ` + "`" + `Error` + "`" + ` but returned a %s. You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument).", componentName || "React class", location, typeSpecName, typeof error),
+ if (warning(!error || error instanceof Error, "%s: type specification of %s `))) + (("`" + (`%s` + "`")) + (` is invalid; the type checker function must return ` + ("`" + `null`)))) + ((("`" + (` or an ` + "`")) + (`Error` + ("`" + ` but returned a %s. You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument).", componentName || "React class", location, typeSpecName, typeof error),
error instanceof Error && !(error.message in loggedTypeFailures)) {
loggedTypeFailures[error.message] = !0;
var stack = getStack ? getStack() : "";
@@ -6883,14 +6378,14 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}
}
- if ("production" !== process.env.NODE_ENV) var invariant = __webpack_require__(90), warning = __webpack_require__(120), ReactPropTypesSecret = __webpack_require__(175), loggedTypeFailures = {};
+ if ("production" !== process.env.NODE_ENV) var invariant = __webpack_require__(70), warning = __webpack_require__(94), ReactPropTypesSecret = __webpack_require__(133), loggedTypeFailures = {};
module.exports = checkPropTypes;
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
module.exports = "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";
}, function(module, exports, __webpack_require__) {
- var isObject = __webpack_require__(50);
+ var isObject = __webpack_require__(35);
module.exports = function(it, S) {
if (!isObject(it)) return it;
var fn, val;
@@ -6900,7 +6395,7 @@ var _publicBundleJs = []byte(`!function(modules) {
throw TypeError("Can't convert object to primitive value");
};
}, function(module, exports, __webpack_require__) {
- var cof = __webpack_require__(178);
+ var cof = __webpack_require__(136);
module.exports = Object("z").propertyIsEnumerable(0) ? Object : function(it) {
return "String" == cof(it) ? it.split("") : Object(it);
};
@@ -6920,12 +6415,12 @@ var _publicBundleJs = []byte(`!function(modules) {
return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);
};
}, function(module, exports, __webpack_require__) {
- var shared = __webpack_require__(182)("keys"), uid = __webpack_require__(124);
+ var shared = __webpack_require__(140)("keys"), uid = __webpack_require__(98);
module.exports = function(key) {
return shared[key] || (shared[key] = uid(key));
};
}, function(module, exports, __webpack_require__) {
- var global = __webpack_require__(36), store = global["__core-js_shared__"] || (global["__core-js_shared__"] = {});
+ var global = __webpack_require__(24), store = global["__core-js_shared__"] || (global["__core-js_shared__"] = {});
module.exports = function(key) {
return store[key] || (store[key] = {});
};
@@ -6935,13 +6430,13 @@ var _publicBundleJs = []byte(`!function(modules) {
exports.f = Object.getOwnPropertySymbols;
}, function(module, exports, __webpack_require__) {
module.exports = {
- default: __webpack_require__(470),
+ default: __webpack_require__(348),
__esModule: !0
};
}, function(module, exports, __webpack_require__) {
"use strict";
- var $at = __webpack_require__(476)(!0);
- __webpack_require__(187)(String, "String", function(iterated) {
+ var $at = __webpack_require__(354)(!0);
+ __webpack_require__(145)(String, "String", function(iterated) {
this._t = String(iterated), this._i = 0;
}, function() {
var point, O = this._t, index = this._i;
@@ -6955,7 +6450,7 @@ var _publicBundleJs = []byte(`!function(modules) {
});
}, function(module, exports, __webpack_require__) {
"use strict";
- var LIBRARY = __webpack_require__(188), $export = __webpack_require__(25), redefine = __webpack_require__(275), hide = __webpack_require__(56), has = __webpack_require__(67), Iterators = __webpack_require__(93), $iterCreate = __webpack_require__(477), setToStringTag = __webpack_require__(128), getPrototypeOf = __webpack_require__(273), ITERATOR = __webpack_require__(29)("iterator"), BUGGY = !([].keys && "next" in [].keys()), returnThis = function() {
+ var LIBRARY = __webpack_require__(146), $export = __webpack_require__(19), redefine = __webpack_require__(212), hide = __webpack_require__(40), has = __webpack_require__(50), Iterators = __webpack_require__(73), $iterCreate = __webpack_require__(355), setToStringTag = __webpack_require__(102), getPrototypeOf = __webpack_require__(210), ITERATOR = __webpack_require__(21)("iterator"), BUGGY = !([].keys && "next" in [].keys()), returnThis = function() {
return this;
};
module.exports = function(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {
@@ -6988,11 +6483,11 @@ var _publicBundleJs = []byte(`!function(modules) {
}, function(module, exports) {
module.exports = !0;
}, function(module, exports, __webpack_require__) {
- exports.f = __webpack_require__(29);
+ exports.f = __webpack_require__(21);
}, function(module, exports, __webpack_require__) {
- var META = __webpack_require__(124)("meta"), isObject = __webpack_require__(50), has = __webpack_require__(67), setDesc = __webpack_require__(32).f, id = 0, isExtensible = Object.isExtensible || function() {
+ var META = __webpack_require__(98)("meta"), isObject = __webpack_require__(35), has = __webpack_require__(50), setDesc = __webpack_require__(22).f, id = 0, isExtensible = Object.isExtensible || function() {
return !0;
- }, FREEZE = !__webpack_require__(66)(function() {
+ }, FREEZE = !__webpack_require__(49)(function() {
return isExtensible(Object.preventExtensions({}));
}), setMeta = function(it) {
setDesc(it, META, {
@@ -7027,7 +6522,7 @@ var _publicBundleJs = []byte(`!function(modules) {
onFreeze: onFreeze
};
}, function(module, exports, __webpack_require__) {
- var global = __webpack_require__(36), core = __webpack_require__(22), LIBRARY = __webpack_require__(188), wksExt = __webpack_require__(189), defineProperty = __webpack_require__(32).f;
+ var global = __webpack_require__(24), core = __webpack_require__(17), LIBRARY = __webpack_require__(146), wksExt = __webpack_require__(147), defineProperty = __webpack_require__(22).f;
module.exports = function(name) {
var $Symbol = core.Symbol || (core.Symbol = LIBRARY ? {} : global.Symbol || {});
"_" == name.charAt(0) || name in $Symbol || defineProperty($Symbol, name, {
@@ -7044,7 +6539,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.CHANNEL = void 0;
- var _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), CHANNEL = exports.CHANNEL = "__THEMING__", themeListener = {
+ var _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), CHANNEL = exports.CHANNEL = "__THEMING__", themeListener = {
contextTypes: (0, _defineProperty3.default)({}, CHANNEL, _propTypes2.default.object),
initial: function(context) {
return context[CHANNEL] ? context[CHANNEL].getState() : null;
@@ -7087,9 +6582,9 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _deepmerge = __webpack_require__(129), _deepmerge2 = _interopRequireDefault(_deepmerge), _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), _createTypography = __webpack_require__(502), _createTypography2 = _interopRequireDefault(_createTypography), _createBreakpoints = __webpack_require__(94), _createBreakpoints2 = _interopRequireDefault(_createBreakpoints), _createPalette = __webpack_require__(503), _createPalette2 = _interopRequireDefault(_createPalette), _createMixins = __webpack_require__(510), _createMixins2 = _interopRequireDefault(_createMixins), _shadows = __webpack_require__(511), _shadows2 = _interopRequireDefault(_shadows), _transitions = __webpack_require__(512), _transitions2 = _interopRequireDefault(_transitions), _zIndex = __webpack_require__(516), _zIndex2 = _interopRequireDefault(_zIndex), _spacing = __webpack_require__(517), _spacing2 = _interopRequireDefault(_spacing);
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _deepmerge = __webpack_require__(103), _deepmerge2 = _interopRequireDefault(_deepmerge), _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), _createTypography = __webpack_require__(380), _createTypography2 = _interopRequireDefault(_createTypography), _createBreakpoints = __webpack_require__(74), _createBreakpoints2 = _interopRequireDefault(_createBreakpoints), _createPalette = __webpack_require__(381), _createPalette2 = _interopRequireDefault(_createPalette), _createMixins = __webpack_require__(388), _createMixins2 = _interopRequireDefault(_createMixins), _shadows = __webpack_require__(389), _shadows2 = _interopRequireDefault(_shadows), _transitions = __webpack_require__(390), _transitions2 = _interopRequireDefault(_transitions), _zIndex = __webpack_require__(394), _zIndex2 = _interopRequireDefault(_zIndex), _spacing = __webpack_require__(395), _spacing2 = _interopRequireDefault(_spacing);
exports.default = createMuiTheme;
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
var REACT_STATICS = {
@@ -7161,30 +6656,11 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.default = toCss;
- var _toCssValue = __webpack_require__(196), _toCssValue2 = function(obj) {
+ var _toCssValue = __webpack_require__(105), _toCssValue2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}(_toCssValue);
-}, function(module, exports, __webpack_require__) {
- "use strict";
- function toCssValue(value) {
- var ignoreImportant = arguments.length > 1 && void 0 !== arguments[1] && arguments[1];
- if (!Array.isArray(value)) return value;
- var cssValue = "";
- if (Array.isArray(value[0])) for (var i = 0; i < value.length && "!important" !== value[i]; i++) cssValue && (cssValue += ", "),
- cssValue += join(value[i], " "); else cssValue = join(value, ", ");
- return ignoreImportant || "!important" !== value[value.length - 1] || (cssValue += " !important"),
- cssValue;
- }
- Object.defineProperty(exports, "__esModule", {
- value: !0
- }), exports.default = toCssValue;
- var join = function(value, by) {
- for (var result = "", i = 0; i < value.length && "!important" !== value[i]; i++) result && (result += by),
- result += value[i];
- return result;
- };
}, function(module, exports) {
module.exports = function(module) {
return module.webpackPolyfill || (module.deprecate = function() {}, module.paths = [],
@@ -7205,7 +6681,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _SheetsRegistry = __webpack_require__(292), _SheetsRegistry2 = function(obj) {
+ var _SheetsRegistry = __webpack_require__(229), _SheetsRegistry2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -7216,7 +6692,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _isInBrowser = __webpack_require__(132), _isInBrowser2 = function(obj) {
+ var _isInBrowser = __webpack_require__(107), _isInBrowser2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -7237,148 +6713,55 @@ var _publicBundleJs = []byte(`!function(modules) {
js: js,
css: css
};
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _isTransformer(obj) {
- return "function" == typeof obj["@@transducer/step"];
- }
- __webpack_exports__.a = _isTransformer;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__path__ = __webpack_require__(80), prop = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(p, obj) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__path__.a)([ p ], obj);
- });
- __webpack_exports__.a = prop;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_concat__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2__internal_reduce__ = __webpack_require__(30), __WEBPACK_IMPORTED_MODULE_3__map__ = __webpack_require__(27), ap = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(function(applyF, applyX) {
- return "function" == typeof applyX["fantasy-land/ap"] ? applyX["fantasy-land/ap"](applyF) : "function" == typeof applyF.ap ? applyF.ap(applyX) : "function" == typeof applyF ? function(x) {
- return applyF(x)(applyX(x));
- } : Object(__WEBPACK_IMPORTED_MODULE_2__internal_reduce__.a)(function(acc, f) {
- return Object(__WEBPACK_IMPORTED_MODULE_0__internal_concat__.a)(acc, Object(__WEBPACK_IMPORTED_MODULE_3__map__.a)(f, applyX));
- }, [], applyF);
- });
- __webpack_exports__.a = ap;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- __webpack_exports__.a = Number.isInteger || function(n) {
- return n << 0 === n;
- };
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__curryN__ = __webpack_require__(23), curry = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(fn) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__curryN__.a)(fn.length, fn);
- });
- __webpack_exports__.a = curry;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_makeFlat__ = __webpack_require__(309), __WEBPACK_IMPORTED_MODULE_3__internal_xchain__ = __webpack_require__(594), __WEBPACK_IMPORTED_MODULE_4__map__ = __webpack_require__(27), chain = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([ "fantasy-land/chain", "chain" ], __WEBPACK_IMPORTED_MODULE_3__internal_xchain__.a, function(fn, monad) {
- return "function" == typeof monad ? function(x) {
- return fn(monad(x))(x);
- } : Object(__WEBPACK_IMPORTED_MODULE_2__internal_makeFlat__.a)(!1)(Object(__WEBPACK_IMPORTED_MODULE_4__map__.a)(fn, monad));
- }));
- __webpack_exports__.a = chain;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), type = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(val) {
- return null === val ? "Null" : void 0 === val ? "Undefined" : Object.prototype.toString.call(val).slice(8, -1);
- });
- __webpack_exports__.a = type;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function compose() {
- if (0 === arguments.length) throw new Error("compose requires at least one argument");
- return __WEBPACK_IMPORTED_MODULE_0__pipe__.a.apply(this, Object(__WEBPACK_IMPORTED_MODULE_1__reverse__.a)(arguments));
- }
- __webpack_exports__.a = compose;
- var __WEBPACK_IMPORTED_MODULE_0__pipe__ = __webpack_require__(313), __WEBPACK_IMPORTED_MODULE_1__reverse__ = __webpack_require__(142);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_checkForMethod__ = __webpack_require__(99), __WEBPACK_IMPORTED_MODULE_1__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_2__slice__ = __webpack_require__(34), tail = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry1__.a)(Object(__WEBPACK_IMPORTED_MODULE_0__internal_checkForMethod__.a)("tail", Object(__WEBPACK_IMPORTED_MODULE_2__slice__.a)(1, 1 / 0)));
- __webpack_exports__.a = tail;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_isArray__ = __webpack_require__(57), __WEBPACK_IMPORTED_MODULE_2__internal_isFunction__ = __webpack_require__(140), __WEBPACK_IMPORTED_MODULE_3__internal_isString__ = __webpack_require__(98), __WEBPACK_IMPORTED_MODULE_4__toString__ = __webpack_require__(100), concat = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- if (Object(__WEBPACK_IMPORTED_MODULE_1__internal_isArray__.a)(a)) {
- if (Object(__WEBPACK_IMPORTED_MODULE_1__internal_isArray__.a)(b)) return a.concat(b);
- throw new TypeError(Object(__WEBPACK_IMPORTED_MODULE_4__toString__.a)(b) + " is not an array");
+}, function(module, exports, __webpack_require__) {
+ function debounce(func, wait, options) {
+ function invokeFunc(time) {
+ var args = lastArgs, thisArg = lastThis;
+ return lastArgs = lastThis = void 0, lastInvokeTime = time, result = func.apply(thisArg, args);
}
- if (Object(__WEBPACK_IMPORTED_MODULE_3__internal_isString__.a)(a)) {
- if (Object(__WEBPACK_IMPORTED_MODULE_3__internal_isString__.a)(b)) return a + b;
- throw new TypeError(Object(__WEBPACK_IMPORTED_MODULE_4__toString__.a)(b) + " is not a string");
+ function leadingEdge(time) {
+ return lastInvokeTime = time, timerId = setTimeout(timerExpired, wait), leading ? invokeFunc(time) : result;
}
- if (null != a && Object(__WEBPACK_IMPORTED_MODULE_2__internal_isFunction__.a)(a["fantasy-land/concat"])) return a["fantasy-land/concat"](b);
- if (null != a && Object(__WEBPACK_IMPORTED_MODULE_2__internal_isFunction__.a)(a.concat)) return a.concat(b);
- throw new TypeError(Object(__WEBPACK_IMPORTED_MODULE_4__toString__.a)(a) + ' does not have a method named "concat" or "fantasy-land/concat"');
- });
- __webpack_exports__.a = concat;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_filter__ = __webpack_require__(211), __WEBPACK_IMPORTED_MODULE_3__internal_isObject__ = __webpack_require__(212), __WEBPACK_IMPORTED_MODULE_4__internal_reduce__ = __webpack_require__(30), __WEBPACK_IMPORTED_MODULE_5__internal_xfilter__ = __webpack_require__(610), __WEBPACK_IMPORTED_MODULE_6__keys__ = __webpack_require__(44), filter = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([ "filter" ], __WEBPACK_IMPORTED_MODULE_5__internal_xfilter__.a, function(pred, filterable) {
- return Object(__WEBPACK_IMPORTED_MODULE_3__internal_isObject__.a)(filterable) ? Object(__WEBPACK_IMPORTED_MODULE_4__internal_reduce__.a)(function(acc, key) {
- return pred(filterable[key]) && (acc[key] = filterable[key]), acc;
- }, {}, Object(__WEBPACK_IMPORTED_MODULE_6__keys__.a)(filterable)) : Object(__WEBPACK_IMPORTED_MODULE_2__internal_filter__.a)(pred, filterable);
- }));
- __webpack_exports__.a = filter;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _filter(fn, list) {
- for (var idx = 0, len = list.length, result = []; idx < len; ) fn(list[idx]) && (result[result.length] = list[idx]),
- idx += 1;
- return result;
- }
- __webpack_exports__.a = _filter;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _isObject(x) {
- return "[object Object]" === Object.prototype.toString.call(x);
- }
- __webpack_exports__.a = _isObject;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__adjust__ = __webpack_require__(297), __WEBPACK_IMPORTED_MODULE_2__always__ = __webpack_require__(78), update = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(idx, x, list) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__adjust__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__always__.a)(x), idx, list);
- });
- __webpack_exports__.a = update;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_xtake__ = __webpack_require__(623), __WEBPACK_IMPORTED_MODULE_3__slice__ = __webpack_require__(34), take = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([ "take" ], __WEBPACK_IMPORTED_MODULE_2__internal_xtake__.a, function(n, xs) {
- return Object(__WEBPACK_IMPORTED_MODULE_3__slice__.a)(0, n < 0 ? 1 / 0 : n, xs);
- }));
- __webpack_exports__.a = take;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__internal_identity__ = __webpack_require__(216), identity = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(__WEBPACK_IMPORTED_MODULE_1__internal_identity__.a);
- __webpack_exports__.a = identity;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _identity(x) {
- return x;
+ function remainingWait(time) {
+ var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, result = wait - timeSinceLastCall;
+ return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
+ }
+ function shouldInvoke(time) {
+ var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime;
+ return void 0 === lastCallTime || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
+ }
+ function timerExpired() {
+ var time = now();
+ if (shouldInvoke(time)) return trailingEdge(time);
+ timerId = setTimeout(timerExpired, remainingWait(time));
+ }
+ function trailingEdge(time) {
+ return timerId = void 0, trailing && lastArgs ? invokeFunc(time) : (lastArgs = lastThis = void 0,
+ result);
+ }
+ function cancel() {
+ void 0 !== timerId && clearTimeout(timerId), lastInvokeTime = 0, lastArgs = lastCallTime = lastThis = timerId = void 0;
+ }
+ function flush() {
+ return void 0 === timerId ? result : trailingEdge(now());
+ }
+ function debounced() {
+ var time = now(), isInvoking = shouldInvoke(time);
+ if (lastArgs = arguments, lastThis = this, lastCallTime = time, isInvoking) {
+ if (void 0 === timerId) return leadingEdge(lastCallTime);
+ if (maxing) return timerId = setTimeout(timerExpired, wait), invokeFunc(lastCallTime);
+ }
+ return void 0 === timerId && (timerId = setTimeout(timerExpired, wait)), result;
+ }
+ var lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = !1, maxing = !1, trailing = !0;
+ if ("function" != typeof func) throw new TypeError(FUNC_ERROR_TEXT);
+ return wait = toNumber(wait) || 0, isObject(options) && (leading = !!options.leading,
+ maxing = "maxWait" in options, maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait,
+ trailing = "trailing" in options ? !!options.trailing : trailing), debounced.cancel = cancel,
+ debounced.flush = flush, debounced;
}
- __webpack_exports__.a = _identity;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__identity__ = __webpack_require__(215), __WEBPACK_IMPORTED_MODULE_1__uniqBy__ = __webpack_require__(333), uniq = Object(__WEBPACK_IMPORTED_MODULE_1__uniqBy__.a)(__WEBPACK_IMPORTED_MODULE_0__identity__.a);
- __webpack_exports__.a = uniq;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__objectAssign__ = __webpack_require__(668);
- __webpack_exports__.a = "function" == typeof Object.assign ? Object.assign : __WEBPACK_IMPORTED_MODULE_0__objectAssign__.a;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__internal_has__ = __webpack_require__(26), mergeWithKey = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(fn, l, r) {
- var k, result = {};
- for (k in l) Object(__WEBPACK_IMPORTED_MODULE_1__internal_has__.a)(k, l) && (result[k] = Object(__WEBPACK_IMPORTED_MODULE_1__internal_has__.a)(k, r) ? fn(k, l[k], r[k]) : l[k]);
- for (k in r) Object(__WEBPACK_IMPORTED_MODULE_1__internal_has__.a)(k, r) && !Object(__WEBPACK_IMPORTED_MODULE_1__internal_has__.a)(k, result) && (result[k] = r[k]);
- return result;
- });
- __webpack_exports__.a = mergeWithKey;
-}, function(module, exports, __webpack_require__) {
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: !0
- }), exports.default = !("undefined" == typeof window || !window.document || !window.document.createElement),
- module.exports = exports.default;
+ var isObject = __webpack_require__(31), now = __webpack_require__(519), toNumber = __webpack_require__(243), FUNC_ERROR_TEXT = "Expected a function", nativeMax = Math.max, nativeMin = Math.min;
+ module.exports = debounce;
}, function(module, exports) {
var global = module.exports = "undefined" != typeof window && window.Math == Math ? window : "undefined" != typeof self && self.Math == Math ? self : Function("return this")();
"number" == typeof __g && (__g = global);
@@ -7392,7 +6775,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return "object" == typeof it ? null !== it : "function" == typeof it;
};
}, function(module, exports, __webpack_require__) {
- module.exports = !__webpack_require__(151)(function() {
+ module.exports = !__webpack_require__(110)(function() {
return 7 != Object.defineProperty({}, "a", {
get: function() {
return 7;
@@ -7412,15 +6795,22 @@ var _publicBundleJs = []byte(`!function(modules) {
function isString(value) {
return "string" == typeof value || !isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag;
}
- var baseGetTag = __webpack_require__(59), isArray = __webpack_require__(16), isObjectLike = __webpack_require__(52), stringTag = "[object String]";
+ var baseGetTag = __webpack_require__(42), isArray = __webpack_require__(12), isObjectLike = __webpack_require__(36), stringTag = "[object String]";
module.exports = isString;
}, function(module, exports, __webpack_require__) {
+ function get(object, path, defaultValue) {
+ var result = null == object ? void 0 : baseGet(object, path);
+ return void 0 === result ? defaultValue : result;
+ }
+ var baseGet = __webpack_require__(246);
+ module.exports = get;
+}, function(module, exports, __webpack_require__) {
function isKey(value, object) {
if (isArray(value)) return !1;
var type = typeof value;
return !("number" != type && "symbol" != type && "boolean" != type && null != value && !isSymbol(value)) || (reIsPlainProp.test(value) || !reIsDeepProp.test(value) || null != object && value in Object(object));
}
- var isArray = __webpack_require__(16), isSymbol = __webpack_require__(82), reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/;
+ var isArray = __webpack_require__(12), isSymbol = __webpack_require__(62), reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/;
module.exports = isKey;
}, function(module, exports, __webpack_require__) {
function MapCache(entries) {
@@ -7430,7 +6820,7 @@ var _publicBundleJs = []byte(`!function(modules) {
this.set(entry[0], entry[1]);
}
}
- var mapCacheClear = __webpack_require__(866), mapCacheDelete = __webpack_require__(882), mapCacheGet = __webpack_require__(884), mapCacheHas = __webpack_require__(885), mapCacheSet = __webpack_require__(886);
+ var mapCacheClear = __webpack_require__(559), mapCacheDelete = __webpack_require__(575), mapCacheGet = __webpack_require__(577), mapCacheHas = __webpack_require__(578), mapCacheSet = __webpack_require__(579);
MapCache.prototype.clear = mapCacheClear, MapCache.prototype.delete = mapCacheDelete,
MapCache.prototype.get = mapCacheGet, MapCache.prototype.has = mapCacheHas, MapCache.prototype.set = mapCacheSet,
module.exports = MapCache;
@@ -7440,13 +6830,13 @@ var _publicBundleJs = []byte(`!function(modules) {
}
module.exports = eq;
}, function(module, exports, __webpack_require__) {
- var getNative = __webpack_require__(70), root = __webpack_require__(46), Map = getNative(root, "Map");
+ var getNative = __webpack_require__(53), root = __webpack_require__(32), Map = getNative(root, "Map");
module.exports = Map;
}, function(module, exports, __webpack_require__) {
function isNumber(value) {
return "number" == typeof value || isObjectLike(value) && baseGetTag(value) == numberTag;
}
- var baseGetTag = __webpack_require__(59), isObjectLike = __webpack_require__(52), numberTag = "[object Number]";
+ var baseGetTag = __webpack_require__(42), isObjectLike = __webpack_require__(36), numberTag = "[object Number]";
module.exports = isNumber;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -7468,7 +6858,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_4__DefaultLegendContent__ = __webpack_require__(889), __WEBPACK_IMPORTED_MODULE_5__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_6__util_ReactUtils__ = __webpack_require__(7), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_4__DefaultLegendContent__ = __webpack_require__(582), __WEBPACK_IMPORTED_MODULE_5__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_6__util_ReactUtils__ = __webpack_require__(4), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -7652,7 +7042,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_d3_shape__ = __webpack_require__(235), __WEBPACK_IMPORTED_MODULE_3_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_3_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_classnames__), __WEBPACK_IMPORTED_MODULE_4__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_5__util_ReactUtils__ = __webpack_require__(7), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_d3_shape__ = __webpack_require__(173), __WEBPACK_IMPORTED_MODULE_3_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_3_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_classnames__), __WEBPACK_IMPORTED_MODULE_4__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_5__util_ReactUtils__ = __webpack_require__(4), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -7743,80 +7133,80 @@ var _publicBundleJs = []byte(`!function(modules) {
__webpack_exports__.a = Symbols;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_1__src_area__ = (__webpack_require__(890), __webpack_require__(369));
+ var __WEBPACK_IMPORTED_MODULE_1__src_area__ = (__webpack_require__(583), __webpack_require__(249));
__webpack_require__.d(__webpack_exports__, "a", function() {
return __WEBPACK_IMPORTED_MODULE_1__src_area__.a;
});
- var __WEBPACK_IMPORTED_MODULE_2__src_line__ = __webpack_require__(236);
+ var __WEBPACK_IMPORTED_MODULE_2__src_line__ = __webpack_require__(174);
__webpack_require__.d(__webpack_exports__, "m", function() {
return __WEBPACK_IMPORTED_MODULE_2__src_line__.a;
});
- var __WEBPACK_IMPORTED_MODULE_8__src_symbol__ = (__webpack_require__(892), __webpack_require__(895),
- __webpack_require__(371), __webpack_require__(372), __webpack_require__(896), __webpack_require__(897));
+ var __WEBPACK_IMPORTED_MODULE_8__src_symbol__ = (__webpack_require__(585), __webpack_require__(588),
+ __webpack_require__(251), __webpack_require__(252), __webpack_require__(589), __webpack_require__(590));
__webpack_require__.d(__webpack_exports__, "t", function() {
return __WEBPACK_IMPORTED_MODULE_8__src_symbol__.a;
});
- var __WEBPACK_IMPORTED_MODULE_9__src_symbol_circle__ = __webpack_require__(374);
+ var __WEBPACK_IMPORTED_MODULE_9__src_symbol_circle__ = __webpack_require__(254);
__webpack_require__.d(__webpack_exports__, "u", function() {
return __WEBPACK_IMPORTED_MODULE_9__src_symbol_circle__.a;
});
- var __WEBPACK_IMPORTED_MODULE_10__src_symbol_cross__ = __webpack_require__(375);
+ var __WEBPACK_IMPORTED_MODULE_10__src_symbol_cross__ = __webpack_require__(255);
__webpack_require__.d(__webpack_exports__, "v", function() {
return __WEBPACK_IMPORTED_MODULE_10__src_symbol_cross__.a;
});
- var __WEBPACK_IMPORTED_MODULE_11__src_symbol_diamond__ = __webpack_require__(376);
+ var __WEBPACK_IMPORTED_MODULE_11__src_symbol_diamond__ = __webpack_require__(256);
__webpack_require__.d(__webpack_exports__, "w", function() {
return __WEBPACK_IMPORTED_MODULE_11__src_symbol_diamond__.a;
});
- var __WEBPACK_IMPORTED_MODULE_12__src_symbol_square__ = __webpack_require__(378);
+ var __WEBPACK_IMPORTED_MODULE_12__src_symbol_square__ = __webpack_require__(258);
__webpack_require__.d(__webpack_exports__, "x", function() {
return __WEBPACK_IMPORTED_MODULE_12__src_symbol_square__.a;
});
- var __WEBPACK_IMPORTED_MODULE_13__src_symbol_star__ = __webpack_require__(377);
+ var __WEBPACK_IMPORTED_MODULE_13__src_symbol_star__ = __webpack_require__(257);
__webpack_require__.d(__webpack_exports__, "y", function() {
return __WEBPACK_IMPORTED_MODULE_13__src_symbol_star__.a;
});
- var __WEBPACK_IMPORTED_MODULE_14__src_symbol_triangle__ = __webpack_require__(379);
+ var __WEBPACK_IMPORTED_MODULE_14__src_symbol_triangle__ = __webpack_require__(259);
__webpack_require__.d(__webpack_exports__, "z", function() {
return __WEBPACK_IMPORTED_MODULE_14__src_symbol_triangle__.a;
});
- var __WEBPACK_IMPORTED_MODULE_15__src_symbol_wye__ = __webpack_require__(380);
+ var __WEBPACK_IMPORTED_MODULE_15__src_symbol_wye__ = __webpack_require__(260);
__webpack_require__.d(__webpack_exports__, "A", function() {
return __WEBPACK_IMPORTED_MODULE_15__src_symbol_wye__.a;
});
- var __WEBPACK_IMPORTED_MODULE_16__src_curve_basisClosed__ = __webpack_require__(898);
+ var __WEBPACK_IMPORTED_MODULE_16__src_curve_basisClosed__ = __webpack_require__(591);
__webpack_require__.d(__webpack_exports__, "c", function() {
return __WEBPACK_IMPORTED_MODULE_16__src_curve_basisClosed__.a;
});
- var __WEBPACK_IMPORTED_MODULE_17__src_curve_basisOpen__ = __webpack_require__(899);
+ var __WEBPACK_IMPORTED_MODULE_17__src_curve_basisOpen__ = __webpack_require__(592);
__webpack_require__.d(__webpack_exports__, "d", function() {
return __WEBPACK_IMPORTED_MODULE_17__src_curve_basisOpen__.a;
});
- var __WEBPACK_IMPORTED_MODULE_18__src_curve_basis__ = __webpack_require__(162);
+ var __WEBPACK_IMPORTED_MODULE_18__src_curve_basis__ = __webpack_require__(120);
__webpack_require__.d(__webpack_exports__, "b", function() {
return __WEBPACK_IMPORTED_MODULE_18__src_curve_basis__.b;
});
- var __WEBPACK_IMPORTED_MODULE_26__src_curve_linearClosed__ = (__webpack_require__(900),
- __webpack_require__(381), __webpack_require__(382), __webpack_require__(163), __webpack_require__(901),
- __webpack_require__(902), __webpack_require__(238), __webpack_require__(903));
+ var __WEBPACK_IMPORTED_MODULE_26__src_curve_linearClosed__ = (__webpack_require__(593),
+ __webpack_require__(261), __webpack_require__(262), __webpack_require__(121), __webpack_require__(594),
+ __webpack_require__(595), __webpack_require__(176), __webpack_require__(596));
__webpack_require__.d(__webpack_exports__, "f", function() {
return __WEBPACK_IMPORTED_MODULE_26__src_curve_linearClosed__.a;
});
- var __WEBPACK_IMPORTED_MODULE_27__src_curve_linear__ = __webpack_require__(160);
+ var __WEBPACK_IMPORTED_MODULE_27__src_curve_linear__ = __webpack_require__(118);
__webpack_require__.d(__webpack_exports__, "e", function() {
return __WEBPACK_IMPORTED_MODULE_27__src_curve_linear__.a;
});
- var __WEBPACK_IMPORTED_MODULE_28__src_curve_monotone__ = __webpack_require__(904);
+ var __WEBPACK_IMPORTED_MODULE_28__src_curve_monotone__ = __webpack_require__(597);
__webpack_require__.d(__webpack_exports__, "g", function() {
return __WEBPACK_IMPORTED_MODULE_28__src_curve_monotone__.a;
}), __webpack_require__.d(__webpack_exports__, "h", function() {
return __WEBPACK_IMPORTED_MODULE_28__src_curve_monotone__.b;
});
- var __WEBPACK_IMPORTED_MODULE_29__src_curve_natural__ = __webpack_require__(905);
+ var __WEBPACK_IMPORTED_MODULE_29__src_curve_natural__ = __webpack_require__(598);
__webpack_require__.d(__webpack_exports__, "i", function() {
return __WEBPACK_IMPORTED_MODULE_29__src_curve_natural__.a;
});
- var __WEBPACK_IMPORTED_MODULE_30__src_curve_step__ = __webpack_require__(906);
+ var __WEBPACK_IMPORTED_MODULE_30__src_curve_step__ = __webpack_require__(599);
__webpack_require__.d(__webpack_exports__, "j", function() {
return __WEBPACK_IMPORTED_MODULE_30__src_curve_step__.a;
}), __webpack_require__.d(__webpack_exports__, "k", function() {
@@ -7824,36 +7214,36 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "l", function() {
return __WEBPACK_IMPORTED_MODULE_30__src_curve_step__.c;
});
- var __WEBPACK_IMPORTED_MODULE_31__src_stack__ = __webpack_require__(907);
+ var __WEBPACK_IMPORTED_MODULE_31__src_stack__ = __webpack_require__(600);
__webpack_require__.d(__webpack_exports__, "n", function() {
return __WEBPACK_IMPORTED_MODULE_31__src_stack__.a;
});
- var __WEBPACK_IMPORTED_MODULE_32__src_offset_expand__ = __webpack_require__(908);
+ var __WEBPACK_IMPORTED_MODULE_32__src_offset_expand__ = __webpack_require__(601);
__webpack_require__.d(__webpack_exports__, "o", function() {
return __WEBPACK_IMPORTED_MODULE_32__src_offset_expand__.a;
});
- var __WEBPACK_IMPORTED_MODULE_34__src_offset_none__ = (__webpack_require__(909),
- __webpack_require__(107));
+ var __WEBPACK_IMPORTED_MODULE_34__src_offset_none__ = (__webpack_require__(602),
+ __webpack_require__(81));
__webpack_require__.d(__webpack_exports__, "p", function() {
return __WEBPACK_IMPORTED_MODULE_34__src_offset_none__.a;
});
- var __WEBPACK_IMPORTED_MODULE_35__src_offset_silhouette__ = __webpack_require__(910);
+ var __WEBPACK_IMPORTED_MODULE_35__src_offset_silhouette__ = __webpack_require__(603);
__webpack_require__.d(__webpack_exports__, "q", function() {
return __WEBPACK_IMPORTED_MODULE_35__src_offset_silhouette__.a;
});
- var __WEBPACK_IMPORTED_MODULE_36__src_offset_wiggle__ = __webpack_require__(911);
+ var __WEBPACK_IMPORTED_MODULE_36__src_offset_wiggle__ = __webpack_require__(604);
__webpack_require__.d(__webpack_exports__, "r", function() {
return __WEBPACK_IMPORTED_MODULE_36__src_offset_wiggle__.a;
});
- var __WEBPACK_IMPORTED_MODULE_40__src_order_none__ = (__webpack_require__(239),
- __webpack_require__(912), __webpack_require__(913), __webpack_require__(108));
+ var __WEBPACK_IMPORTED_MODULE_40__src_order_none__ = (__webpack_require__(177),
+ __webpack_require__(605), __webpack_require__(606), __webpack_require__(82));
__webpack_require__.d(__webpack_exports__, "s", function() {
return __WEBPACK_IMPORTED_MODULE_40__src_order_none__.a;
});
- __webpack_require__(914);
+ __webpack_require__(607);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0_d3_path__ = __webpack_require__(105), __WEBPACK_IMPORTED_MODULE_1__constant__ = __webpack_require__(71), __WEBPACK_IMPORTED_MODULE_2__curve_linear__ = __webpack_require__(160), __WEBPACK_IMPORTED_MODULE_3__point__ = __webpack_require__(237);
+ var __WEBPACK_IMPORTED_MODULE_0_d3_path__ = __webpack_require__(79), __WEBPACK_IMPORTED_MODULE_1__constant__ = __webpack_require__(54), __WEBPACK_IMPORTED_MODULE_2__curve_linear__ = __webpack_require__(118), __WEBPACK_IMPORTED_MODULE_3__point__ = __webpack_require__(175);
__webpack_exports__.a = function() {
function line(data) {
var i, d, buffer, n = data.length, defined0 = !1;
@@ -7907,7 +7297,7 @@ var _publicBundleJs = []byte(`!function(modules) {
this._context = context, this._alpha = alpha;
}
__webpack_exports__.a = point;
- var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(106), __WEBPACK_IMPORTED_MODULE_1__cardinal__ = __webpack_require__(163);
+ var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(80), __WEBPACK_IMPORTED_MODULE_1__cardinal__ = __webpack_require__(121);
CatmullRom.prototype = {
areaStart: function() {
this._line = 0;
@@ -7970,7 +7360,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return s;
}
__webpack_exports__.b = sum;
- var __WEBPACK_IMPORTED_MODULE_0__none__ = __webpack_require__(108);
+ var __WEBPACK_IMPORTED_MODULE_0__none__ = __webpack_require__(82);
__webpack_exports__.a = function(series) {
var sums = series.map(sum);
return Object(__WEBPACK_IMPORTED_MODULE_0__none__.a)(series).sort(function(a, b) {
@@ -7981,16 +7371,16 @@ var _publicBundleJs = []byte(`!function(modules) {
function baseIsEqual(value, other, bitmask, customizer, stack) {
return value === other || (null == value || null == other || !isObjectLike(value) && !isObjectLike(other) ? value !== value && other !== other : baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack));
}
- var baseIsEqualDeep = __webpack_require__(915), isObjectLike = __webpack_require__(52);
+ var baseIsEqualDeep = __webpack_require__(608), isObjectLike = __webpack_require__(36);
module.exports = baseIsEqual;
}, function(module, exports, __webpack_require__) {
function keys(object) {
return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
}
- var arrayLikeKeys = __webpack_require__(933), baseKeys = __webpack_require__(939), isArrayLike = __webpack_require__(109);
+ var arrayLikeKeys = __webpack_require__(626), baseKeys = __webpack_require__(632), isArrayLike = __webpack_require__(83);
module.exports = keys;
}, function(module, exports, __webpack_require__) {
- var baseIsArguments = __webpack_require__(935), isObjectLike = __webpack_require__(52), objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty, propertyIsEnumerable = objectProto.propertyIsEnumerable, isArguments = baseIsArguments(function() {
+ var baseIsArguments = __webpack_require__(628), isObjectLike = __webpack_require__(36), objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty, propertyIsEnumerable = objectProto.propertyIsEnumerable, isArguments = baseIsArguments(function() {
return arguments;
}()) ? baseIsArguments : function(value) {
return isObjectLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee");
@@ -8015,55 +7405,6 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}
module.exports = baseUnary;
-}, function(module, exports, __webpack_require__) {
- function debounce(func, wait, options) {
- function invokeFunc(time) {
- var args = lastArgs, thisArg = lastThis;
- return lastArgs = lastThis = void 0, lastInvokeTime = time, result = func.apply(thisArg, args);
- }
- function leadingEdge(time) {
- return lastInvokeTime = time, timerId = setTimeout(timerExpired, wait), leading ? invokeFunc(time) : result;
- }
- function remainingWait(time) {
- var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, result = wait - timeSinceLastCall;
- return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
- }
- function shouldInvoke(time) {
- var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime;
- return void 0 === lastCallTime || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
- }
- function timerExpired() {
- var time = now();
- if (shouldInvoke(time)) return trailingEdge(time);
- timerId = setTimeout(timerExpired, remainingWait(time));
- }
- function trailingEdge(time) {
- return timerId = void 0, trailing && lastArgs ? invokeFunc(time) : (lastArgs = lastThis = void 0,
- result);
- }
- function cancel() {
- void 0 !== timerId && clearTimeout(timerId), lastInvokeTime = 0, lastArgs = lastCallTime = lastThis = timerId = void 0;
- }
- function flush() {
- return void 0 === timerId ? result : trailingEdge(now());
- }
- function debounced() {
- var time = now(), isInvoking = shouldInvoke(time);
- if (lastArgs = arguments, lastThis = this, lastCallTime = time, isInvoking) {
- if (void 0 === timerId) return leadingEdge(lastCallTime);
- if (maxing) return timerId = setTimeout(timerExpired, wait), invokeFunc(lastCallTime);
- }
- return void 0 === timerId && (timerId = setTimeout(timerExpired, wait)), result;
- }
- var lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = !1, maxing = !1, trailing = !0;
- if ("function" != typeof func) throw new TypeError(FUNC_ERROR_TEXT);
- return wait = toNumber(wait) || 0, isObject(options) && (leading = !!options.leading,
- maxing = "maxWait" in options, maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait,
- trailing = "trailing" in options ? !!options.trailing : trailing), debounced.cancel = cancel,
- debounced.flush = flush, debounced;
- }
- var isObject = __webpack_require__(47), now = __webpack_require__(990), toNumber = __webpack_require__(400), FUNC_ERROR_TEXT = "Expected a function", nativeMax = Math.max, nativeMin = Math.min;
- module.exports = debounce;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
function _toConsumableArray(arr) {
@@ -8088,7 +7429,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "a", function() {
return calculateChartCoordinate;
});
- var __WEBPACK_IMPORTED_MODULE_0__ReactUtils__ = __webpack_require__(7), _extends = Object.assign || function(target) {
+ var __WEBPACK_IMPORTED_MODULE_0__ReactUtils__ = __webpack_require__(4), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -8152,7 +7493,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__number__ = __webpack_require__(112);
+ var __WEBPACK_IMPORTED_MODULE_0__number__ = __webpack_require__(86);
__webpack_exports__.a = function(values, p, valueof) {
if (null == valueof && (valueof = __WEBPACK_IMPORTED_MODULE_0__number__.a), n = values.length) {
if ((p = +p) <= 0 || n < 2) return +valueof(values[0], 0, values);
@@ -8229,7 +7570,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, __webpack_exports__.a = map;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(61), __WEBPACK_IMPORTED_MODULE_1__rgb__ = __webpack_require__(423), __WEBPACK_IMPORTED_MODULE_2__array__ = __webpack_require__(426), __WEBPACK_IMPORTED_MODULE_3__date__ = __webpack_require__(427), __WEBPACK_IMPORTED_MODULE_4__number__ = __webpack_require__(167), __WEBPACK_IMPORTED_MODULE_5__object__ = __webpack_require__(428), __WEBPACK_IMPORTED_MODULE_6__string__ = __webpack_require__(429), __WEBPACK_IMPORTED_MODULE_7__constant__ = __webpack_require__(425);
+ var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(44), __WEBPACK_IMPORTED_MODULE_1__rgb__ = __webpack_require__(302), __WEBPACK_IMPORTED_MODULE_2__array__ = __webpack_require__(305), __WEBPACK_IMPORTED_MODULE_3__date__ = __webpack_require__(306), __WEBPACK_IMPORTED_MODULE_4__number__ = __webpack_require__(125), __WEBPACK_IMPORTED_MODULE_5__object__ = __webpack_require__(307), __WEBPACK_IMPORTED_MODULE_6__string__ = __webpack_require__(308), __WEBPACK_IMPORTED_MODULE_7__constant__ = __webpack_require__(304);
__webpack_exports__.a = function(a, b) {
var c, t = typeof b;
return null == b || "boolean" === t ? Object(__WEBPACK_IMPORTED_MODULE_7__constant__.a)(b) : ("number" === t ? __WEBPACK_IMPORTED_MODULE_4__number__.a : "string" === t ? (c = Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__.a)(b)) ? (b = c,
@@ -8287,7 +7628,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return brighter;
}), __webpack_exports__.e = color, __webpack_exports__.h = rgbConvert, __webpack_exports__.g = rgb,
__webpack_exports__.b = Rgb, __webpack_exports__.f = hsl;
- var __WEBPACK_IMPORTED_MODULE_0__define__ = __webpack_require__(252), darker = .7, brighter = 1 / darker, reI = "\\s*([+-]?\\d+)\\s*", reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*", reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*", reHex3 = /^#([0-9a-f]{3})$/, reHex6 = /^#([0-9a-f]{6})$/, reRgbInteger = new RegExp("^rgb\\(" + [ reI, reI, reI ] + "\\)$"), reRgbPercent = new RegExp("^rgb\\(" + [ reP, reP, reP ] + "\\)$"), reRgbaInteger = new RegExp("^rgba\\(" + [ reI, reI, reI, reN ] + "\\)$"), reRgbaPercent = new RegExp("^rgba\\(" + [ reP, reP, reP, reN ] + "\\)$"), reHslPercent = new RegExp("^hsl\\(" + [ reN, reP, reP ] + "\\)$"), reHslaPercent = new RegExp("^hsla\\(" + [ reN, reP, reP, reN ] + "\\)$"), named = {
+ var __WEBPACK_IMPORTED_MODULE_0__define__ = __webpack_require__(189), darker = .7, brighter = 1 / darker, reI = "\\s*([+-]?\\d+)\\s*", reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*", reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*", reHex3 = /^#([0-9a-f]{3})$/, reHex6 = /^#([0-9a-f]{6})$/, reRgbInteger = new RegExp("^rgb\\(" + [ reI, reI, reI ] + "\\)$"), reRgbPercent = new RegExp("^rgb\\(" + [ reP, reP, reP ] + "\\)$"), reRgbaInteger = new RegExp("^rgba\\(" + [ reI, reI, reI, reN ] + "\\)$"), reRgbaPercent = new RegExp("^rgba\\(" + [ reP, reP, reP, reN ] + "\\)$"), reHslPercent = new RegExp("^hsl\\(" + [ reN, reP, reP ] + "\\)$"), reHslaPercent = new RegExp("^hsla\\(" + [ reN, reP, reP, reN ] + "\\)$"), named = {
aliceblue: 15792383,
antiquewhite: 16444375,
aqua: 65535,
@@ -8515,31 +7856,31 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_1__src_millisecond__ = (__webpack_require__(24), __webpack_require__(1065));
+ var __WEBPACK_IMPORTED_MODULE_1__src_millisecond__ = (__webpack_require__(18), __webpack_require__(757));
__webpack_require__.d(__webpack_exports__, "c", function() {
return __WEBPACK_IMPORTED_MODULE_1__src_millisecond__.a;
}), __webpack_require__.d(__webpack_exports__, "n", function() {
return __WEBPACK_IMPORTED_MODULE_1__src_millisecond__.a;
});
- var __WEBPACK_IMPORTED_MODULE_2__src_second__ = __webpack_require__(1066);
+ var __WEBPACK_IMPORTED_MODULE_2__src_second__ = __webpack_require__(758);
__webpack_require__.d(__webpack_exports__, "g", function() {
return __WEBPACK_IMPORTED_MODULE_2__src_second__.a;
}), __webpack_require__.d(__webpack_exports__, "r", function() {
return __WEBPACK_IMPORTED_MODULE_2__src_second__.a;
});
- var __WEBPACK_IMPORTED_MODULE_3__src_minute__ = __webpack_require__(1067);
+ var __WEBPACK_IMPORTED_MODULE_3__src_minute__ = __webpack_require__(759);
__webpack_require__.d(__webpack_exports__, "d", function() {
return __WEBPACK_IMPORTED_MODULE_3__src_minute__.a;
});
- var __WEBPACK_IMPORTED_MODULE_4__src_hour__ = __webpack_require__(1068);
+ var __WEBPACK_IMPORTED_MODULE_4__src_hour__ = __webpack_require__(760);
__webpack_require__.d(__webpack_exports__, "b", function() {
return __WEBPACK_IMPORTED_MODULE_4__src_hour__.a;
});
- var __WEBPACK_IMPORTED_MODULE_5__src_day__ = __webpack_require__(1069);
+ var __WEBPACK_IMPORTED_MODULE_5__src_day__ = __webpack_require__(761);
__webpack_require__.d(__webpack_exports__, "a", function() {
return __WEBPACK_IMPORTED_MODULE_5__src_day__.a;
});
- var __WEBPACK_IMPORTED_MODULE_6__src_week__ = __webpack_require__(1070);
+ var __WEBPACK_IMPORTED_MODULE_6__src_week__ = __webpack_require__(762);
__webpack_require__.d(__webpack_exports__, "j", function() {
return __WEBPACK_IMPORTED_MODULE_6__src_week__.b;
}), __webpack_require__.d(__webpack_exports__, "h", function() {
@@ -8549,27 +7890,27 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "i", function() {
return __WEBPACK_IMPORTED_MODULE_6__src_week__.c;
});
- var __WEBPACK_IMPORTED_MODULE_7__src_month__ = __webpack_require__(1071);
+ var __WEBPACK_IMPORTED_MODULE_7__src_month__ = __webpack_require__(763);
__webpack_require__.d(__webpack_exports__, "f", function() {
return __WEBPACK_IMPORTED_MODULE_7__src_month__.a;
});
- var __WEBPACK_IMPORTED_MODULE_8__src_year__ = __webpack_require__(1072);
+ var __WEBPACK_IMPORTED_MODULE_8__src_year__ = __webpack_require__(764);
__webpack_require__.d(__webpack_exports__, "k", function() {
return __WEBPACK_IMPORTED_MODULE_8__src_year__.a;
});
- var __WEBPACK_IMPORTED_MODULE_9__src_utcMinute__ = __webpack_require__(1073);
+ var __WEBPACK_IMPORTED_MODULE_9__src_utcMinute__ = __webpack_require__(765);
__webpack_require__.d(__webpack_exports__, "o", function() {
return __WEBPACK_IMPORTED_MODULE_9__src_utcMinute__.a;
});
- var __WEBPACK_IMPORTED_MODULE_10__src_utcHour__ = __webpack_require__(1074);
+ var __WEBPACK_IMPORTED_MODULE_10__src_utcHour__ = __webpack_require__(766);
__webpack_require__.d(__webpack_exports__, "m", function() {
return __WEBPACK_IMPORTED_MODULE_10__src_utcHour__.a;
});
- var __WEBPACK_IMPORTED_MODULE_11__src_utcDay__ = __webpack_require__(1075);
+ var __WEBPACK_IMPORTED_MODULE_11__src_utcDay__ = __webpack_require__(767);
__webpack_require__.d(__webpack_exports__, "l", function() {
return __WEBPACK_IMPORTED_MODULE_11__src_utcDay__.a;
});
- var __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__ = __webpack_require__(1076);
+ var __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__ = __webpack_require__(768);
__webpack_require__.d(__webpack_exports__, "u", function() {
return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__.b;
}), __webpack_require__.d(__webpack_exports__, "s", function() {
@@ -8579,11 +7920,11 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "t", function() {
return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__.c;
});
- var __WEBPACK_IMPORTED_MODULE_13__src_utcMonth__ = __webpack_require__(1077);
+ var __WEBPACK_IMPORTED_MODULE_13__src_utcMonth__ = __webpack_require__(769);
__webpack_require__.d(__webpack_exports__, "q", function() {
return __WEBPACK_IMPORTED_MODULE_13__src_utcMonth__.a;
});
- var __WEBPACK_IMPORTED_MODULE_14__src_utcYear__ = __webpack_require__(1078);
+ var __WEBPACK_IMPORTED_MODULE_14__src_utcYear__ = __webpack_require__(770);
__webpack_require__.d(__webpack_exports__, "v", function() {
return __WEBPACK_IMPORTED_MODULE_14__src_utcYear__.a;
});
@@ -8596,7 +7937,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "c", function() {
return utcParse;
});
- var locale, timeFormat, timeParse, utcFormat, utcParse, __WEBPACK_IMPORTED_MODULE_0__locale__ = __webpack_require__(439);
+ var locale, timeFormat, timeParse, utcFormat, utcParse, __WEBPACK_IMPORTED_MODULE_0__locale__ = __webpack_require__(318);
!function(definition) {
locale = Object(__WEBPACK_IMPORTED_MODULE_0__locale__.a)(definition), timeFormat = locale.format,
timeParse = locale.parse, utcFormat = locale.utcFormat, utcParse = locale.utcParse;
@@ -8630,7 +7971,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_4__util_ReactUtils__ = __webpack_require__(7), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_4__util_ReactUtils__ = __webpack_require__(4), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -8710,7 +8051,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__ = __webpack_require__(49), __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil__ = __webpack_require__(28), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_3_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_3_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_react__), __WEBPACK_IMPORTED_MODULE_4_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_4_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_prop_types__), __WEBPACK_IMPORTED_MODULE_5_react_smooth__ = __webpack_require__(48), __WEBPACK_IMPORTED_MODULE_5_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_react_smooth__), __WEBPACK_IMPORTED_MODULE_6_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_6_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_classnames__), __WEBPACK_IMPORTED_MODULE_7__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_8__shape_Curve__ = __webpack_require__(86), __WEBPACK_IMPORTED_MODULE_9__shape_Dot__ = __webpack_require__(74), __WEBPACK_IMPORTED_MODULE_10__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_11__component_LabelList__ = __webpack_require__(62), __WEBPACK_IMPORTED_MODULE_12__ErrorBar__ = __webpack_require__(117), __WEBPACK_IMPORTED_MODULE_13__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_14__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_15__util_ChartUtils__ = __webpack_require__(21), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__ = __webpack_require__(34), __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil__ = __webpack_require__(20), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_3_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_3_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_react__), __WEBPACK_IMPORTED_MODULE_4_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_4_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_prop_types__), __WEBPACK_IMPORTED_MODULE_5_react_smooth__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_5_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_react_smooth__), __WEBPACK_IMPORTED_MODULE_6_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_6_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_classnames__), __WEBPACK_IMPORTED_MODULE_7__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_8__shape_Curve__ = __webpack_require__(66), __WEBPACK_IMPORTED_MODULE_9__shape_Dot__ = __webpack_require__(57), __WEBPACK_IMPORTED_MODULE_10__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_11__component_LabelList__ = __webpack_require__(45), __WEBPACK_IMPORTED_MODULE_12__ErrorBar__ = __webpack_require__(91), __WEBPACK_IMPORTED_MODULE_13__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_14__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_15__util_ChartUtils__ = __webpack_require__(16), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -8774,7 +8115,11 @@ var _publicBundleJs = []byte(`!function(modules) {
key: "getTotalLength",
value: function() {
var curveDom = this.mainCurve;
- return curveDom && curveDom.getTotalLength && curveDom.getTotalLength() || 0;
+ try {
+ return curveDom && curveDom.getTotalLength && curveDom.getTotalLength() || 0;
+ } catch (err) {
+ return 0;
+ }
}
}, {
key: "getStrokeDasharray",
@@ -9052,7 +8397,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__ = __webpack_require__(49), __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_1_lodash_isNaN__ = __webpack_require__(159), __WEBPACK_IMPORTED_MODULE_1_lodash_isNaN___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isNaN__), __WEBPACK_IMPORTED_MODULE_2_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_2_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_3_lodash_isNil__ = __webpack_require__(28), __WEBPACK_IMPORTED_MODULE_3_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_4_lodash_isArray__ = __webpack_require__(16), __WEBPACK_IMPORTED_MODULE_4_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_5_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_5_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_react__), __WEBPACK_IMPORTED_MODULE_6_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_6_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_prop_types__), __WEBPACK_IMPORTED_MODULE_7_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_7_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_classnames__), __WEBPACK_IMPORTED_MODULE_8_react_smooth__ = __webpack_require__(48), __WEBPACK_IMPORTED_MODULE_8_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_8_react_smooth__), __WEBPACK_IMPORTED_MODULE_9__shape_Curve__ = __webpack_require__(86), __WEBPACK_IMPORTED_MODULE_10__shape_Dot__ = __webpack_require__(74), __WEBPACK_IMPORTED_MODULE_11__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_12__component_LabelList__ = __webpack_require__(62), __WEBPACK_IMPORTED_MODULE_13__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_14__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_15__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_16__util_ChartUtils__ = __webpack_require__(21), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__ = __webpack_require__(34), __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_1_lodash_isNaN__ = __webpack_require__(117), __WEBPACK_IMPORTED_MODULE_1_lodash_isNaN___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isNaN__), __WEBPACK_IMPORTED_MODULE_2_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_2_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_3_lodash_isNil__ = __webpack_require__(20), __WEBPACK_IMPORTED_MODULE_3_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_4_lodash_isArray__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_4_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_5_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_5_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_react__), __WEBPACK_IMPORTED_MODULE_6_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_6_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_prop_types__), __WEBPACK_IMPORTED_MODULE_7_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_7_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_classnames__), __WEBPACK_IMPORTED_MODULE_8_react_smooth__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_8_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_8_react_smooth__), __WEBPACK_IMPORTED_MODULE_9__shape_Curve__ = __webpack_require__(66), __WEBPACK_IMPORTED_MODULE_10__shape_Dot__ = __webpack_require__(57), __WEBPACK_IMPORTED_MODULE_11__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_12__component_LabelList__ = __webpack_require__(45), __WEBPACK_IMPORTED_MODULE_13__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_14__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_15__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_16__util_ChartUtils__ = __webpack_require__(16), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -9397,7 +8742,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isNil__ = __webpack_require__(28), __WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_1_lodash_isEqual__ = __webpack_require__(49), __WEBPACK_IMPORTED_MODULE_1_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_2_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_2_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_3_lodash_isArray__ = __webpack_require__(16), __WEBPACK_IMPORTED_MODULE_3_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_4_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_4_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react__), __WEBPACK_IMPORTED_MODULE_5_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_5_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_prop_types__), __WEBPACK_IMPORTED_MODULE_6_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_6_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_classnames__), __WEBPACK_IMPORTED_MODULE_7_react_smooth__ = __webpack_require__(48), __WEBPACK_IMPORTED_MODULE_7_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_react_smooth__), __WEBPACK_IMPORTED_MODULE_8__shape_Rectangle__ = __webpack_require__(85), __WEBPACK_IMPORTED_MODULE_9__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_10__ErrorBar__ = __webpack_require__(117), __WEBPACK_IMPORTED_MODULE_11__component_Cell__ = __webpack_require__(111), __WEBPACK_IMPORTED_MODULE_12__component_LabelList__ = __webpack_require__(62), __WEBPACK_IMPORTED_MODULE_13__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_14__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_15__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_16__util_ChartUtils__ = __webpack_require__(21), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isNil__ = __webpack_require__(20), __WEBPACK_IMPORTED_MODULE_0_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_1_lodash_isEqual__ = __webpack_require__(34), __WEBPACK_IMPORTED_MODULE_1_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_2_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_2_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_3_lodash_isArray__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_3_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_4_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_4_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react__), __WEBPACK_IMPORTED_MODULE_5_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_5_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_prop_types__), __WEBPACK_IMPORTED_MODULE_6_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_6_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_classnames__), __WEBPACK_IMPORTED_MODULE_7_react_smooth__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_7_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_react_smooth__), __WEBPACK_IMPORTED_MODULE_8__shape_Rectangle__ = __webpack_require__(65), __WEBPACK_IMPORTED_MODULE_9__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_10__ErrorBar__ = __webpack_require__(91), __WEBPACK_IMPORTED_MODULE_11__component_Cell__ = __webpack_require__(85), __WEBPACK_IMPORTED_MODULE_12__component_LabelList__ = __webpack_require__(45), __WEBPACK_IMPORTED_MODULE_13__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_14__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_15__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_16__util_ChartUtils__ = __webpack_require__(16), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -9708,7 +9053,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__ = __webpack_require__(49), __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil__ = __webpack_require__(28), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_3_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_3_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_react__), __WEBPACK_IMPORTED_MODULE_4_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_4_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_prop_types__), __WEBPACK_IMPORTED_MODULE_5_react_smooth__ = __webpack_require__(48), __WEBPACK_IMPORTED_MODULE_5_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_react_smooth__), __WEBPACK_IMPORTED_MODULE_6_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_6_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_classnames__), __WEBPACK_IMPORTED_MODULE_7__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_8__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_9__component_LabelList__ = __webpack_require__(62), __WEBPACK_IMPORTED_MODULE_10__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_11__ZAxis__ = __webpack_require__(173), __WEBPACK_IMPORTED_MODULE_12__shape_Curve__ = __webpack_require__(86), __WEBPACK_IMPORTED_MODULE_13__shape_Symbols__ = __webpack_require__(234), __WEBPACK_IMPORTED_MODULE_14__ErrorBar__ = __webpack_require__(117), __WEBPACK_IMPORTED_MODULE_15__component_Cell__ = __webpack_require__(111), __WEBPACK_IMPORTED_MODULE_16__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_17__util_ChartUtils__ = __webpack_require__(21), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__ = __webpack_require__(34), __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil__ = __webpack_require__(20), __WEBPACK_IMPORTED_MODULE_2_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_3_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_3_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_react__), __WEBPACK_IMPORTED_MODULE_4_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_4_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_prop_types__), __WEBPACK_IMPORTED_MODULE_5_react_smooth__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_5_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_react_smooth__), __WEBPACK_IMPORTED_MODULE_6_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_6_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_classnames__), __WEBPACK_IMPORTED_MODULE_7__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_8__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_9__component_LabelList__ = __webpack_require__(45), __WEBPACK_IMPORTED_MODULE_10__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_11__ZAxis__ = __webpack_require__(131), __WEBPACK_IMPORTED_MODULE_12__shape_Curve__ = __webpack_require__(66), __WEBPACK_IMPORTED_MODULE_13__shape_Symbols__ = __webpack_require__(172), __WEBPACK_IMPORTED_MODULE_14__ErrorBar__ = __webpack_require__(91), __WEBPACK_IMPORTED_MODULE_15__component_Cell__ = __webpack_require__(85), __WEBPACK_IMPORTED_MODULE_16__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_17__util_ChartUtils__ = __webpack_require__(16), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -10018,7 +9363,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
- var emptyFunction = __webpack_require__(55), EventListener = {
+ var emptyFunction = __webpack_require__(39), EventListener = {
listen: function(target, eventType, callback) {
return target.addEventListener ? (target.addEventListener(eventType, callback, !1),
{
@@ -10045,7 +9390,7 @@ var _publicBundleJs = []byte(`!function(modules) {
registerDefault: function() {}
};
module.exports = EventListener;
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
function getActiveElement(doc) {
@@ -10062,7 +9407,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function containsNode(outerNode, innerNode) {
return !(!outerNode || !innerNode) && (outerNode === innerNode || !isTextNode(outerNode) && (isTextNode(innerNode) ? containsNode(outerNode, innerNode.parentNode) : "contains" in outerNode ? outerNode.contains(innerNode) : !!outerNode.compareDocumentPosition && !!(16 & outerNode.compareDocumentPosition(innerNode))));
}
- var isTextNode = __webpack_require__(457);
+ var isTextNode = __webpack_require__(335);
module.exports = containsNode;
}, function(module, exports, __webpack_require__) {
"use strict";
@@ -10074,7 +9419,7 @@ var _publicBundleJs = []byte(`!function(modules) {
module.exports = focusNode;
}, function(module, exports, __webpack_require__) {
module.exports = {
- default: __webpack_require__(465),
+ default: __webpack_require__(343),
__esModule: !0
};
}, function(module, exports) {
@@ -10083,20 +9428,20 @@ var _publicBundleJs = []byte(`!function(modules) {
return it;
};
}, function(module, exports, __webpack_require__) {
- module.exports = !__webpack_require__(37) && !__webpack_require__(66)(function() {
- return 7 != Object.defineProperty(__webpack_require__(271)("div"), "a", {
+ module.exports = !__webpack_require__(25) && !__webpack_require__(49)(function() {
+ return 7 != Object.defineProperty(__webpack_require__(208)("div"), "a", {
get: function() {
return 7;
}
}).a;
});
}, function(module, exports, __webpack_require__) {
- var isObject = __webpack_require__(50), document = __webpack_require__(36).document, is = isObject(document) && isObject(document.createElement);
+ var isObject = __webpack_require__(35), document = __webpack_require__(24).document, is = isObject(document) && isObject(document.createElement);
module.exports = function(it) {
return is ? document.createElement(it) : {};
};
}, function(module, exports, __webpack_require__) {
- var has = __webpack_require__(67), toIObject = __webpack_require__(75), arrayIndexOf = __webpack_require__(468)(!1), IE_PROTO = __webpack_require__(181)("IE_PROTO");
+ var has = __webpack_require__(50), toIObject = __webpack_require__(58), arrayIndexOf = __webpack_require__(346)(!1), IE_PROTO = __webpack_require__(139)("IE_PROTO");
module.exports = function(object, names) {
var key, O = toIObject(object), i = 0, result = [];
for (key in O) key != IE_PROTO && has(O, key) && result.push(key);
@@ -10104,12 +9449,12 @@ var _publicBundleJs = []byte(`!function(modules) {
return result;
};
}, function(module, exports, __webpack_require__) {
- var has = __webpack_require__(67), toObject = __webpack_require__(76), IE_PROTO = __webpack_require__(181)("IE_PROTO"), ObjectProto = Object.prototype;
+ var has = __webpack_require__(50), toObject = __webpack_require__(59), IE_PROTO = __webpack_require__(139)("IE_PROTO"), ObjectProto = Object.prototype;
module.exports = Object.getPrototypeOf || function(O) {
return O = toObject(O), has(O, IE_PROTO) ? O[IE_PROTO] : "function" == typeof O.constructor && O instanceof O.constructor ? O.constructor.prototype : O instanceof Object ? ObjectProto : null;
};
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(25), core = __webpack_require__(22), fails = __webpack_require__(66);
+ var $export = __webpack_require__(19), core = __webpack_require__(17), fails = __webpack_require__(49);
module.exports = function(KEY, exec) {
var fn = (core.Object || {})[KEY] || Object[KEY], exp = {};
exp[KEY] = exec(fn), $export($export.S + $export.F * fails(function() {
@@ -10117,10 +9462,10 @@ var _publicBundleJs = []byte(`!function(modules) {
}), "Object", exp);
};
}, function(module, exports, __webpack_require__) {
- module.exports = __webpack_require__(56);
+ module.exports = __webpack_require__(40);
}, function(module, exports, __webpack_require__) {
- __webpack_require__(480);
- for (var global = __webpack_require__(36), hide = __webpack_require__(56), Iterators = __webpack_require__(93), TO_STRING_TAG = __webpack_require__(29)("toStringTag"), DOMIterables = "CSSRuleList,CSSStyleDeclaration,CSSValueList,ClientRectList,DOMRectList,DOMStringList,DOMTokenList,DataTransferItemList,FileList,HTMLAllCollection,HTMLCollection,HTMLFormElement,HTMLSelectElement,MediaList,MimeTypeArray,NamedNodeMap,NodeList,PaintRequestList,Plugin,PluginArray,SVGLengthList,SVGNumberList,SVGPathSegList,SVGPointList,SVGStringList,SVGTransformList,SourceBufferList,StyleSheetList,TextTrackCueList,TextTrackList,TouchList".split(","), i = 0; i < DOMIterables.length; i++) {
+ __webpack_require__(358);
+ for (var global = __webpack_require__(24), hide = __webpack_require__(40), Iterators = __webpack_require__(73), TO_STRING_TAG = __webpack_require__(21)("toStringTag"), DOMIterables = "CSSRuleList,CSSStyleDeclaration,CSSValueList,ClientRectList,DOMRectList,DOMStringList,DOMTokenList,DataTransferItemList,FileList,HTMLAllCollection,HTMLCollection,HTMLFormElement,HTMLSelectElement,MediaList,MimeTypeArray,NamedNodeMap,NodeList,PaintRequestList,Plugin,PluginArray,SVGLengthList,SVGNumberList,SVGPathSegList,SVGPointList,SVGStringList,SVGTransformList,SourceBufferList,StyleSheetList,TextTrackCueList,TextTrackList,TouchList".split(","), i = 0; i < DOMIterables.length; i++) {
var NAME = DOMIterables[i], Collection = global[NAME], proto = Collection && Collection.prototype;
proto && !proto[TO_STRING_TAG] && hide(proto, TO_STRING_TAG, NAME), Iterators[NAME] = Iterators.Array;
}
@@ -10132,25 +9477,25 @@ var _publicBundleJs = []byte(`!function(modules) {
};
};
}, function(module, exports, __webpack_require__) {
- var cof = __webpack_require__(178);
+ var cof = __webpack_require__(136);
module.exports = Array.isArray || function(arg) {
return "Array" == cof(arg);
};
}, function(module, exports, __webpack_require__) {
- var $keys = __webpack_require__(272), hiddenKeys = __webpack_require__(183).concat("length", "prototype");
+ var $keys = __webpack_require__(209), hiddenKeys = __webpack_require__(141).concat("length", "prototype");
exports.f = Object.getOwnPropertyNames || function(O) {
return $keys(O, hiddenKeys);
};
}, function(module, exports, __webpack_require__) {
- var pIE = __webpack_require__(125), createDesc = __webpack_require__(91), toIObject = __webpack_require__(75), toPrimitive = __webpack_require__(176), has = __webpack_require__(67), IE8_DOM_DEFINE = __webpack_require__(270), gOPD = Object.getOwnPropertyDescriptor;
- exports.f = __webpack_require__(37) ? gOPD : function(O, P) {
+ var pIE = __webpack_require__(99), createDesc = __webpack_require__(71), toIObject = __webpack_require__(58), toPrimitive = __webpack_require__(134), has = __webpack_require__(50), IE8_DOM_DEFINE = __webpack_require__(207), gOPD = Object.getOwnPropertyDescriptor;
+ exports.f = __webpack_require__(25) ? gOPD : function(O, P) {
if (O = toIObject(O), P = toPrimitive(P, !0), IE8_DOM_DEFINE) try {
return gOPD(O, P);
} catch (e) {}
if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]);
};
}, function(module, exports) {}, function(module, exports, __webpack_require__) {
- var hide = __webpack_require__(56);
+ var hide = __webpack_require__(40);
module.exports = function(target, src, safe) {
for (var key in src) safe && target[key] ? target[key] = src[key] : hide(target, key, src[key]);
return target;
@@ -10161,7 +9506,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return it;
};
}, function(module, exports, __webpack_require__) {
- var anObject = __webpack_require__(65);
+ var anObject = __webpack_require__(48);
module.exports = function(iterator, fn, value, entries) {
try {
return entries ? fn(anObject(value)[0], value[1]) : fn(value);
@@ -10171,17 +9516,17 @@ var _publicBundleJs = []byte(`!function(modules) {
}
};
}, function(module, exports, __webpack_require__) {
- var Iterators = __webpack_require__(93), ITERATOR = __webpack_require__(29)("iterator"), ArrayProto = Array.prototype;
+ var Iterators = __webpack_require__(73), ITERATOR = __webpack_require__(21)("iterator"), ArrayProto = Array.prototype;
module.exports = function(it) {
return void 0 !== it && (Iterators.Array === it || ArrayProto[ITERATOR] === it);
};
}, function(module, exports, __webpack_require__) {
- var classof = __webpack_require__(287), ITERATOR = __webpack_require__(29)("iterator"), Iterators = __webpack_require__(93);
- module.exports = __webpack_require__(22).getIteratorMethod = function(it) {
+ var classof = __webpack_require__(224), ITERATOR = __webpack_require__(21)("iterator"), Iterators = __webpack_require__(73);
+ module.exports = __webpack_require__(17).getIteratorMethod = function(it) {
if (void 0 != it) return it[ITERATOR] || it["@@iterator"] || Iterators[classof(it)];
};
}, function(module, exports, __webpack_require__) {
- var cof = __webpack_require__(178), TAG = __webpack_require__(29)("toStringTag"), ARG = "Arguments" == cof(function() {
+ var cof = __webpack_require__(136), TAG = __webpack_require__(21)("toStringTag"), ARG = "Arguments" == cof(function() {
return arguments;
}()), tryGet = function(it, key) {
try {
@@ -10193,7 +9538,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return void 0 === it ? "Undefined" : null === it ? "Null" : "string" == typeof (T = tryGet(O = Object(it), TAG)) ? T : ARG ? cof(O) : "Object" == (B = cof(O)) && "function" == typeof O.callee ? "Arguments" : B;
};
}, function(module, exports, __webpack_require__) {
- var isObject = __webpack_require__(50);
+ var isObject = __webpack_require__(35);
module.exports = function(it, TYPE) {
if (!isObject(it) || it._t !== TYPE) throw TypeError("Incompatible receiver, " + TYPE + " required!");
return it;
@@ -10222,50 +9567,57 @@ var _publicBundleJs = []byte(`!function(modules) {
}
Object.defineProperty(exports, "__esModule", {
value: !0
- }), exports.create = exports.createGenerateClassName = exports.sheets = exports.RuleList = exports.SheetsManager = exports.SheetsRegistry = exports.getDynamicStyles = void 0;
- var _getDynamicStyles = __webpack_require__(540);
+ }), exports.create = exports.createGenerateClassName = exports.sheets = exports.RuleList = exports.SheetsManager = exports.SheetsRegistry = exports.toCssValue = exports.getDynamicStyles = void 0;
+ var _getDynamicStyles = __webpack_require__(418);
Object.defineProperty(exports, "getDynamicStyles", {
enumerable: !0,
get: function() {
return _interopRequireDefault(_getDynamicStyles).default;
}
});
- var _SheetsRegistry = __webpack_require__(292);
+ var _toCssValue = __webpack_require__(105);
+ Object.defineProperty(exports, "toCssValue", {
+ enumerable: !0,
+ get: function() {
+ return _interopRequireDefault(_toCssValue).default;
+ }
+ });
+ var _SheetsRegistry = __webpack_require__(229);
Object.defineProperty(exports, "SheetsRegistry", {
enumerable: !0,
get: function() {
return _interopRequireDefault(_SheetsRegistry).default;
}
});
- var _SheetsManager = __webpack_require__(541);
+ var _SheetsManager = __webpack_require__(419);
Object.defineProperty(exports, "SheetsManager", {
enumerable: !0,
get: function() {
return _interopRequireDefault(_SheetsManager).default;
}
});
- var _RuleList = __webpack_require__(96);
+ var _RuleList = __webpack_require__(76);
Object.defineProperty(exports, "RuleList", {
enumerable: !0,
get: function() {
return _interopRequireDefault(_RuleList).default;
}
});
- var _sheets = __webpack_require__(198);
+ var _sheets = __webpack_require__(155);
Object.defineProperty(exports, "sheets", {
enumerable: !0,
get: function() {
return _interopRequireDefault(_sheets).default;
}
});
- var _createGenerateClassName = __webpack_require__(295);
+ var _createGenerateClassName = __webpack_require__(232);
Object.defineProperty(exports, "createGenerateClassName", {
enumerable: !0,
get: function() {
return _interopRequireDefault(_createGenerateClassName).default;
}
});
- var _Jss = __webpack_require__(548), _Jss2 = _interopRequireDefault(_Jss), create = exports.create = function(options) {
+ var _Jss = __webpack_require__(426), _Jss2 = _interopRequireDefault(_Jss), create = exports.create = function(options) {
return new _Jss2.default(options);
};
exports.default = create();
@@ -10335,7 +9687,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _symbolObservable = __webpack_require__(543), _symbolObservable2 = function(obj) {
+ var _symbolObservable = __webpack_require__(421), _symbolObservable2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -10362,8 +9714,8 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), _StyleSheet = __webpack_require__(296), _moduleId = (_interopRequireDefault(_StyleSheet),
- __webpack_require__(547)), _moduleId2 = _interopRequireDefault(_moduleId), env = process.env.NODE_ENV;
+ var _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), _StyleSheet = __webpack_require__(233), _moduleId = (_interopRequireDefault(_StyleSheet),
+ __webpack_require__(425)), _moduleId2 = _interopRequireDefault(_moduleId), env = process.env.NODE_ENV;
exports.default = function() {
var ruleCounter = 0, defaultPrefix = "production" === env ? "c" : "";
return function(rule, sheet) {
@@ -10373,7 +9725,7 @@ var _publicBundleJs = []byte(`!function(modules) {
"production" === env ? "" + prefix + _moduleId2.default + jssId + ruleCounter : prefix + rule.key + "-" + _moduleId2.default + (jssId && "-" + jssId) + "-" + ruleCounter;
};
};
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -10405,7 +9757,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _linkRule = __webpack_require__(294), _linkRule2 = _interopRequireDefault(_linkRule), _RuleList = __webpack_require__(96), _RuleList2 = _interopRequireDefault(_RuleList), StyleSheet = function() {
+ }(), _linkRule = __webpack_require__(231), _linkRule2 = _interopRequireDefault(_linkRule), _RuleList = __webpack_require__(76), _RuleList2 = _interopRequireDefault(_RuleList), StyleSheet = function() {
function StyleSheet(styles, options) {
_classCallCheck(this, StyleSheet), this.attached = !1, this.deployed = !1, this.linked = !1,
this.classes = {}, this.options = _extends({}, options, {
@@ -10490,568 +9842,6 @@ var _publicBundleJs = []byte(`!function(modules) {
} ]), StyleSheet;
}();
exports.default = StyleSheet;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_concat__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_1__internal_curry3__ = __webpack_require__(5), adjust = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry3__.a)(function(fn, idx, list) {
- if (idx >= list.length || idx < -list.length) return list;
- var start = idx < 0 ? list.length : 0, _idx = start + idx, _list = Object(__WEBPACK_IMPORTED_MODULE_0__internal_concat__.a)(list);
- return _list[_idx] = fn(list[_idx]), _list;
- });
- __webpack_exports__.a = adjust;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _xwrap(fn) {
- return new XWrap(fn);
- }
- __webpack_exports__.a = _xwrap;
- var XWrap = function() {
- function XWrap(fn) {
- this.f = fn;
- }
- return XWrap.prototype["@@transducer/init"] = function() {
- throw new Error("init not implemented on XWrap");
- }, XWrap.prototype["@@transducer/result"] = function(acc) {
- return acc;
- }, XWrap.prototype["@@transducer/step"] = function(acc, x) {
- return this.f(acc, x);
- }, XWrap;
- }();
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_arity__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), bind = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(function(fn, thisObj) {
- return Object(__WEBPACK_IMPORTED_MODULE_0__internal_arity__.a)(fn.length, function() {
- return fn.apply(thisObj, arguments);
- });
- });
- __webpack_exports__.a = bind;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__has__ = __webpack_require__(26), toString = Object.prototype.toString, _isArguments = function() {
- return "[object Arguments]" === toString.call(arguments) ? function(x) {
- return "[object Arguments]" === toString.call(x);
- } : function(x) {
- return Object(__WEBPACK_IMPORTED_MODULE_0__has__.a)("callee", x);
- };
- };
- __webpack_exports__.a = _isArguments;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), and = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- return a && b;
- });
- __webpack_exports__.a = and;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_xany__ = __webpack_require__(303), any = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([ "any" ], __WEBPACK_IMPORTED_MODULE_2__internal_xany__.a, function(fn, list) {
- for (var idx = 0; idx < list.length; ) {
- if (fn(list[idx])) return !0;
- idx += 1;
- }
- return !1;
- }));
- __webpack_exports__.a = any;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__reduced__ = __webpack_require__(58), __WEBPACK_IMPORTED_MODULE_2__xfBase__ = __webpack_require__(19), XAny = function() {
- function XAny(f, xf) {
- this.xf = xf, this.f = f, this.any = !1;
- }
- return XAny.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_2__xfBase__.a.init,
- XAny.prototype["@@transducer/result"] = function(result) {
- return this.any || (result = this.xf["@@transducer/step"](result, !1)), this.xf["@@transducer/result"](result);
- }, XAny.prototype["@@transducer/step"] = function(result, input) {
- return this.f(input) && (this.any = !0, result = Object(__WEBPACK_IMPORTED_MODULE_1__reduced__.a)(this.xf["@@transducer/step"](result, !0))),
- result;
- }, XAny;
- }(), _xany = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(f, xf) {
- return new XAny(f, xf);
- });
- __webpack_exports__.a = _xany;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), apply = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(fn, args) {
- return fn.apply(this, args);
- });
- __webpack_exports__.a = apply;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__keys__ = __webpack_require__(44), values = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(obj) {
- for (var props = Object(__WEBPACK_IMPORTED_MODULE_1__keys__.a)(obj), len = props.length, vals = [], idx = 0; idx < len; ) vals[idx] = obj[props[idx]],
- idx += 1;
- return vals;
- });
- __webpack_exports__.a = values;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__internal_has__ = __webpack_require__(26), __WEBPACK_IMPORTED_MODULE_2__internal_isArray__ = __webpack_require__(57), __WEBPACK_IMPORTED_MODULE_3__internal_isInteger__ = __webpack_require__(203), __WEBPACK_IMPORTED_MODULE_4__assoc__ = __webpack_require__(138), __WEBPACK_IMPORTED_MODULE_5__isNil__ = __webpack_require__(307), assocPath = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function assocPath(path, val, obj) {
- if (0 === path.length) return val;
- var idx = path[0];
- if (path.length > 1) {
- var nextObj = !Object(__WEBPACK_IMPORTED_MODULE_5__isNil__.a)(obj) && Object(__WEBPACK_IMPORTED_MODULE_1__internal_has__.a)(idx, obj) ? obj[idx] : Object(__WEBPACK_IMPORTED_MODULE_3__internal_isInteger__.a)(path[1]) ? [] : {};
- val = assocPath(Array.prototype.slice.call(path, 1), val, nextObj);
- }
- if (Object(__WEBPACK_IMPORTED_MODULE_3__internal_isInteger__.a)(idx) && Object(__WEBPACK_IMPORTED_MODULE_2__internal_isArray__.a)(obj)) {
- var arr = [].concat(obj);
- return arr[idx] = val, arr;
- }
- return Object(__WEBPACK_IMPORTED_MODULE_4__assoc__.a)(idx, val, obj);
- });
- __webpack_exports__.a = assocPath;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), isNil = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(x) {
- return null == x;
- });
- __webpack_exports__.a = isNil;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_reduce__ = __webpack_require__(30), __WEBPACK_IMPORTED_MODULE_2__ap__ = __webpack_require__(202), __WEBPACK_IMPORTED_MODULE_3__curryN__ = __webpack_require__(23), __WEBPACK_IMPORTED_MODULE_4__map__ = __webpack_require__(27), liftN = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(arity, fn) {
- var lifted = Object(__WEBPACK_IMPORTED_MODULE_3__curryN__.a)(arity, fn);
- return Object(__WEBPACK_IMPORTED_MODULE_3__curryN__.a)(arity, function() {
- return Object(__WEBPACK_IMPORTED_MODULE_1__internal_reduce__.a)(__WEBPACK_IMPORTED_MODULE_2__ap__.a, Object(__WEBPACK_IMPORTED_MODULE_4__map__.a)(lifted, arguments[0]), Array.prototype.slice.call(arguments, 1));
- });
- });
- __webpack_exports__.a = liftN;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _makeFlat(recursive) {
- return function flatt(list) {
- for (var value, jlen, j, result = [], idx = 0, ilen = list.length; idx < ilen; ) {
- if (Object(__WEBPACK_IMPORTED_MODULE_0__isArrayLike__.a)(list[idx])) for (value = recursive ? flatt(list[idx]) : list[idx],
- j = 0, jlen = value.length; j < jlen; ) result[result.length] = value[j], j += 1; else result[result.length] = list[idx];
- idx += 1;
- }
- return result;
- };
- }
- __webpack_exports__.a = _makeFlat;
- var __WEBPACK_IMPORTED_MODULE_0__isArrayLike__ = __webpack_require__(137);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _clone(value, refFrom, refTo, deep) {
- var copy = function(copiedValue) {
- for (var len = refFrom.length, idx = 0; idx < len; ) {
- if (value === refFrom[idx]) return refTo[idx];
- idx += 1;
- }
- refFrom[idx + 1] = value, refTo[idx + 1] = copiedValue;
- for (var key in value) copiedValue[key] = deep ? _clone(value[key], refFrom, refTo, !0) : value[key];
- return copiedValue;
- };
- switch (Object(__WEBPACK_IMPORTED_MODULE_1__type__.a)(value)) {
- case "Object":
- return copy({});
-
- case "Array":
- return copy([]);
-
- case "Date":
- return new Date(value.valueOf());
-
- case "RegExp":
- return Object(__WEBPACK_IMPORTED_MODULE_0__cloneRegExp__.a)(value);
-
- default:
- return value;
- }
- }
- __webpack_exports__.a = _clone;
- var __WEBPACK_IMPORTED_MODULE_0__cloneRegExp__ = __webpack_require__(311), __WEBPACK_IMPORTED_MODULE_1__type__ = __webpack_require__(206);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _cloneRegExp(pattern) {
- return new RegExp(pattern.source, (pattern.global ? "g" : "") + (pattern.ignoreCase ? "i" : "") + (pattern.multiline ? "m" : "") + (pattern.sticky ? "y" : "") + (pattern.unicode ? "u" : ""));
- }
- __webpack_exports__.a = _cloneRegExp;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), not = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(a) {
- return !a;
- });
- __webpack_exports__.a = not;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function pipe() {
- if (0 === arguments.length) throw new Error("pipe requires at least one argument");
- return Object(__WEBPACK_IMPORTED_MODULE_0__internal_arity__.a)(arguments[0].length, Object(__WEBPACK_IMPORTED_MODULE_2__reduce__.a)(__WEBPACK_IMPORTED_MODULE_1__internal_pipe__.a, arguments[0], Object(__WEBPACK_IMPORTED_MODULE_3__tail__.a)(arguments)));
- }
- __webpack_exports__.a = pipe;
- var __WEBPACK_IMPORTED_MODULE_0__internal_arity__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_1__internal_pipe__ = __webpack_require__(601), __WEBPACK_IMPORTED_MODULE_2__reduce__ = __webpack_require__(45), __WEBPACK_IMPORTED_MODULE_3__tail__ = __webpack_require__(208);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function composeK() {
- if (0 === arguments.length) throw new Error("composeK requires at least one argument");
- var init = Array.prototype.slice.call(arguments), last = init.pop();
- return Object(__WEBPACK_IMPORTED_MODULE_1__compose__.a)(__WEBPACK_IMPORTED_MODULE_1__compose__.a.apply(this, Object(__WEBPACK_IMPORTED_MODULE_2__map__.a)(__WEBPACK_IMPORTED_MODULE_0__chain__.a, init)), last);
- }
- __webpack_exports__.a = composeK;
- var __WEBPACK_IMPORTED_MODULE_0__chain__ = __webpack_require__(205), __WEBPACK_IMPORTED_MODULE_1__compose__ = __webpack_require__(207), __WEBPACK_IMPORTED_MODULE_2__map__ = __webpack_require__(27);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function pipeP() {
- if (0 === arguments.length) throw new Error("pipeP requires at least one argument");
- return Object(__WEBPACK_IMPORTED_MODULE_0__internal_arity__.a)(arguments[0].length, Object(__WEBPACK_IMPORTED_MODULE_2__reduce__.a)(__WEBPACK_IMPORTED_MODULE_1__internal_pipeP__.a, arguments[0], Object(__WEBPACK_IMPORTED_MODULE_3__tail__.a)(arguments)));
- }
- __webpack_exports__.a = pipeP;
- var __WEBPACK_IMPORTED_MODULE_0__internal_arity__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_1__internal_pipeP__ = __webpack_require__(603), __WEBPACK_IMPORTED_MODULE_2__reduce__ = __webpack_require__(45), __WEBPACK_IMPORTED_MODULE_3__tail__ = __webpack_require__(208);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _indexOf(list, a, idx) {
- var inf, item;
- if ("function" == typeof list.indexOf) switch (typeof a) {
- case "number":
- if (0 === a) {
- for (inf = 1 / a; idx < list.length; ) {
- if (0 === (item = list[idx]) && 1 / item === inf) return idx;
- idx += 1;
- }
- return -1;
- }
- if (a !== a) {
- for (;idx < list.length; ) {
- if ("number" == typeof (item = list[idx]) && item !== item) return idx;
- idx += 1;
- }
- return -1;
- }
- return list.indexOf(a, idx);
-
- case "string":
- case "boolean":
- case "function":
- case "undefined":
- return list.indexOf(a, idx);
-
- case "object":
- if (null === a) return list.indexOf(a, idx);
- }
- for (;idx < list.length; ) {
- if (Object(__WEBPACK_IMPORTED_MODULE_0__equals__.a)(list[idx], a)) return idx;
- idx += 1;
- }
- return -1;
- }
- __webpack_exports__.a = _indexOf;
- var __WEBPACK_IMPORTED_MODULE_0__equals__ = __webpack_require__(31);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), identical = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- return a === b ? 0 !== a || 1 / a == 1 / b : a !== a && b !== b;
- });
- __webpack_exports__.a = identical;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _complement(f) {
- return function() {
- return !f.apply(this, arguments);
- };
- }
- __webpack_exports__.a = _complement;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__curry__ = __webpack_require__(204), __WEBPACK_IMPORTED_MODULE_2__nAry__ = __webpack_require__(139), constructN = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(n, Fn) {
- if (n > 10) throw new Error("Constructor with greater than ten arguments");
- return 0 === n ? function() {
- return new Fn();
- } : Object(__WEBPACK_IMPORTED_MODULE_1__curry__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__nAry__.a)(n, function($0, $1, $2, $3, $4, $5, $6, $7, $8, $9) {
- switch (arguments.length) {
- case 1:
- return new Fn($0);
-
- case 2:
- return new Fn($0, $1);
-
- case 3:
- return new Fn($0, $1, $2);
-
- case 4:
- return new Fn($0, $1, $2, $3);
-
- case 5:
- return new Fn($0, $1, $2, $3, $4);
-
- case 6:
- return new Fn($0, $1, $2, $3, $4, $5);
-
- case 7:
- return new Fn($0, $1, $2, $3, $4, $5, $6);
-
- case 8:
- return new Fn($0, $1, $2, $3, $4, $5, $6, $7);
-
- case 9:
- return new Fn($0, $1, $2, $3, $4, $5, $6, $7, $8);
-
- case 10:
- return new Fn($0, $1, $2, $3, $4, $5, $6, $7, $8, $9);
- }
- }));
- });
- __webpack_exports__.a = constructN;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_map__ = __webpack_require__(136), __WEBPACK_IMPORTED_MODULE_2__curryN__ = __webpack_require__(23), __WEBPACK_IMPORTED_MODULE_3__max__ = __webpack_require__(79), __WEBPACK_IMPORTED_MODULE_4__pluck__ = __webpack_require__(97), __WEBPACK_IMPORTED_MODULE_5__reduce__ = __webpack_require__(45), converge = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(after, fns) {
- return Object(__WEBPACK_IMPORTED_MODULE_2__curryN__.a)(Object(__WEBPACK_IMPORTED_MODULE_5__reduce__.a)(__WEBPACK_IMPORTED_MODULE_3__max__.a, 0, Object(__WEBPACK_IMPORTED_MODULE_4__pluck__.a)("length", fns)), function() {
- var args = arguments, context = this;
- return after.apply(context, Object(__WEBPACK_IMPORTED_MODULE_1__internal_map__.a)(function(fn) {
- return fn.apply(context, args);
- }, fns));
- });
- });
- __webpack_exports__.a = converge;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), defaultTo = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(d, v) {
- return null == v || v !== v ? d : v;
- });
- __webpack_exports__.a = defaultTo;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_contains__ = __webpack_require__(81), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), difference = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(function(first, second) {
- for (var out = [], idx = 0, firstLen = first.length; idx < firstLen; ) Object(__WEBPACK_IMPORTED_MODULE_0__internal_contains__.a)(first[idx], second) || Object(__WEBPACK_IMPORTED_MODULE_0__internal_contains__.a)(first[idx], out) || (out[out.length] = first[idx]),
- idx += 1;
- return out;
- });
- __webpack_exports__.a = difference;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_containsWith__ = __webpack_require__(143), __WEBPACK_IMPORTED_MODULE_1__internal_curry3__ = __webpack_require__(5), differenceWith = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry3__.a)(function(pred, first, second) {
- for (var out = [], idx = 0, firstLen = first.length; idx < firstLen; ) Object(__WEBPACK_IMPORTED_MODULE_0__internal_containsWith__.a)(pred, first[idx], second) || Object(__WEBPACK_IMPORTED_MODULE_0__internal_containsWith__.a)(pred, first[idx], out) || out.push(first[idx]),
- idx += 1;
- return out;
- });
- __webpack_exports__.a = differenceWith;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), dissoc = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(prop, obj) {
- var result = {};
- for (var p in obj) result[p] = obj[p];
- return delete result[prop], result;
- });
- __webpack_exports__.a = dissoc;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), remove = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(start, count, list) {
- var result = Array.prototype.slice.call(list, 0);
- return result.splice(start, count), result;
- });
- __webpack_exports__.a = remove;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_xdrop__ = __webpack_require__(620), __WEBPACK_IMPORTED_MODULE_3__slice__ = __webpack_require__(34), drop = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([ "drop" ], __WEBPACK_IMPORTED_MODULE_2__internal_xdrop__.a, function(n, xs) {
- return Object(__WEBPACK_IMPORTED_MODULE_3__slice__.a)(Math.max(0, n), 1 / 0, xs);
- }));
- __webpack_exports__.a = drop;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__xfBase__ = __webpack_require__(19), XDropRepeatsWith = function() {
- function XDropRepeatsWith(pred, xf) {
- this.xf = xf, this.pred = pred, this.lastValue = void 0, this.seenFirstValue = !1;
- }
- return XDropRepeatsWith.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_1__xfBase__.a.init,
- XDropRepeatsWith.prototype["@@transducer/result"] = __WEBPACK_IMPORTED_MODULE_1__xfBase__.a.result,
- XDropRepeatsWith.prototype["@@transducer/step"] = function(result, input) {
- var sameAsLast = !1;
- return this.seenFirstValue ? this.pred(this.lastValue, input) && (sameAsLast = !0) : this.seenFirstValue = !0,
- this.lastValue = input, sameAsLast ? result : this.xf["@@transducer/step"](result, input);
- }, XDropRepeatsWith;
- }(), _xdropRepeatsWith = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(pred, xf) {
- return new XDropRepeatsWith(pred, xf);
- });
- __webpack_exports__.a = _xdropRepeatsWith;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_xdropRepeatsWith__ = __webpack_require__(327), __WEBPACK_IMPORTED_MODULE_3__last__ = __webpack_require__(329), dropRepeatsWith = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([], __WEBPACK_IMPORTED_MODULE_2__internal_xdropRepeatsWith__.a, function(pred, list) {
- var result = [], idx = 1, len = list.length;
- if (0 !== len) for (result[0] = list[0]; idx < len; ) pred(Object(__WEBPACK_IMPORTED_MODULE_3__last__.a)(result), list[idx]) || (result[result.length] = list[idx]),
- idx += 1;
- return result;
- }));
- __webpack_exports__.a = dropRepeatsWith;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__nth__ = __webpack_require__(101), last = Object(__WEBPACK_IMPORTED_MODULE_0__nth__.a)(-1);
- __webpack_exports__.a = last;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), or = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- return a || b;
- });
- __webpack_exports__.a = or;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__internal_isArguments__ = __webpack_require__(300), __WEBPACK_IMPORTED_MODULE_2__internal_isArray__ = __webpack_require__(57), __WEBPACK_IMPORTED_MODULE_3__internal_isObject__ = __webpack_require__(212), __WEBPACK_IMPORTED_MODULE_4__internal_isString__ = __webpack_require__(98), empty = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(x) {
- return null != x && "function" == typeof x["fantasy-land/empty"] ? x["fantasy-land/empty"]() : null != x && null != x.constructor && "function" == typeof x.constructor["fantasy-land/empty"] ? x.constructor["fantasy-land/empty"]() : null != x && "function" == typeof x.empty ? x.empty() : null != x && null != x.constructor && "function" == typeof x.constructor.empty ? x.constructor.empty() : Object(__WEBPACK_IMPORTED_MODULE_2__internal_isArray__.a)(x) ? [] : Object(__WEBPACK_IMPORTED_MODULE_4__internal_isString__.a)(x) ? "" : Object(__WEBPACK_IMPORTED_MODULE_3__internal_isObject__.a)(x) ? {} : Object(__WEBPACK_IMPORTED_MODULE_1__internal_isArguments__.a)(x) ? function() {
- return arguments;
- }() : void 0;
- });
- __webpack_exports__.a = empty;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__drop__ = __webpack_require__(326), takeLast = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(n, xs) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__drop__.a)(n >= 0 ? xs.length - n : 0, xs);
- });
- __webpack_exports__.a = takeLast;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_Set__ = __webpack_require__(664), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), uniqBy = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(function(fn, list) {
- for (var appliedItem, item, set = new __WEBPACK_IMPORTED_MODULE_0__internal_Set__.a(), result = [], idx = 0; idx < list.length; ) item = list[idx],
- appliedItem = fn(item), set.add(appliedItem) && result.push(item), idx += 1;
- return result;
- });
- __webpack_exports__.a = uniqBy;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), objOf = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(key, val) {
- var obj = {};
- return obj[key] = val, obj;
- });
- __webpack_exports__.a = objOf;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), is = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(Ctor, val) {
- return null != val && val.constructor === Ctor || val instanceof Ctor;
- });
- __webpack_exports__.a = is;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__converge__ = __webpack_require__(320), juxt = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(fns) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__converge__.a)(function() {
- return Array.prototype.slice.call(arguments, 0);
- }, fns);
- });
- __webpack_exports__.a = juxt;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__internal_isNumber__ = __webpack_require__(338), length = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(list) {
- return null != list && Object(__WEBPACK_IMPORTED_MODULE_1__internal_isNumber__.a)(list.length) ? list.length : NaN;
- });
- __webpack_exports__.a = length;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _isNumber(x) {
- return "[object Number]" === Object.prototype.toString.call(x);
- }
- __webpack_exports__.a = _isNumber;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__sum__ = __webpack_require__(340), mean = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(list) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__sum__.a)(list) / list.length;
- });
- __webpack_exports__.a = mean;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__add__ = __webpack_require__(134), __WEBPACK_IMPORTED_MODULE_1__reduce__ = __webpack_require__(45), sum = Object(__WEBPACK_IMPORTED_MODULE_1__reduce__.a)(__WEBPACK_IMPORTED_MODULE_0__add__.a, 0);
- __webpack_exports__.a = sum;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_arity__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2__internal_has__ = __webpack_require__(26), memoizeWith = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(function(mFn, fn) {
- var cache = {};
- return Object(__WEBPACK_IMPORTED_MODULE_0__internal_arity__.a)(fn.length, function() {
- var key = mFn.apply(this, arguments);
- return Object(__WEBPACK_IMPORTED_MODULE_2__internal_has__.a)(key, cache) || (cache[key] = fn.apply(this, arguments)),
- cache[key];
- });
- });
- __webpack_exports__.a = memoizeWith;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), multiply = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- return a * b;
- });
- __webpack_exports__.a = multiply;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), Identity = function(x) {
- return {
- value: x,
- map: function(f) {
- return Identity(f(x));
- }
- };
- }, over = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(lens, f, x) {
- return lens(function(y) {
- return Identity(f(y));
- })(x).value;
- });
- __webpack_exports__.a = over;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _createPartialApplicator(concat) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__curry2__.a)(function(fn, args) {
- return Object(__WEBPACK_IMPORTED_MODULE_0__arity__.a)(Math.max(0, fn.length - args.length), function() {
- return fn.apply(this, concat(args, arguments));
- });
- });
- }
- __webpack_exports__.a = _createPartialApplicator;
- var __WEBPACK_IMPORTED_MODULE_0__arity__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_1__curry2__ = __webpack_require__(0);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), pickAll = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(names, obj) {
- for (var result = {}, idx = 0, len = names.length; idx < len; ) {
- var name = names[idx];
- result[name] = obj[name], idx += 1;
- }
- return result;
- });
- __webpack_exports__.a = pickAll;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_concat__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), prepend = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(function(el, list) {
- return Object(__WEBPACK_IMPORTED_MODULE_0__internal_concat__.a)([ el ], list);
- });
- __webpack_exports__.a = prepend;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__curryN__ = __webpack_require__(23), useWith = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(fn, transformers) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__curryN__.a)(transformers.length, function() {
- for (var args = [], idx = 0; idx < transformers.length; ) args.push(transformers[idx].call(this, arguments[idx])),
- idx += 1;
- return fn.apply(this, args.concat(Array.prototype.slice.call(arguments, transformers.length)));
- });
- });
- __webpack_exports__.a = useWith;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), reduceRight = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(fn, acc, list) {
- for (var idx = list.length - 1; idx >= 0; ) acc = fn(list[idx], acc), idx -= 1;
- return acc;
- });
- __webpack_exports__.a = reduceRight;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), times = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(fn, n) {
- var list, len = Number(n), idx = 0;
- if (len < 0 || isNaN(len)) throw new RangeError("n must be a non-negative number");
- for (list = new Array(len); idx < len; ) list[idx] = fn(idx), idx += 1;
- return list;
- });
- __webpack_exports__.a = times;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__ap__ = __webpack_require__(202), __WEBPACK_IMPORTED_MODULE_2__map__ = __webpack_require__(27), __WEBPACK_IMPORTED_MODULE_3__prepend__ = __webpack_require__(346), __WEBPACK_IMPORTED_MODULE_4__reduceRight__ = __webpack_require__(348), sequence = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(of, traversable) {
- return "function" == typeof traversable.sequence ? traversable.sequence(of) : Object(__WEBPACK_IMPORTED_MODULE_4__reduceRight__.a)(function(x, acc) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__ap__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__map__.a)(__WEBPACK_IMPORTED_MODULE_3__prepend__.a, x), acc);
- }, of([]), traversable);
- });
- __webpack_exports__.a = sequence;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_containsWith__ = __webpack_require__(143), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), uniqWith = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(function(pred, list) {
- for (var item, idx = 0, len = list.length, result = []; idx < len; ) item = list[idx],
- Object(__WEBPACK_IMPORTED_MODULE_0__internal_containsWith__.a)(pred, item, result) || (result[result.length] = item),
- idx += 1;
- return result;
- });
- __webpack_exports__.a = uniqWith;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_has__ = __webpack_require__(26), where = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(spec, testObj) {
- for (var prop in spec) if (Object(__WEBPACK_IMPORTED_MODULE_1__internal_has__.a)(prop, spec) && !spec[prop](testObj[prop])) return !1;
- return !0;
- });
- __webpack_exports__.a = where;
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -11062,7 +9852,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _ButtonBase = __webpack_require__(784);
+ var _ButtonBase = __webpack_require__(463);
Object.defineProperty(exports, "default", {
enumerable: !0,
get: function() {
@@ -11120,7 +9910,7 @@ var _publicBundleJs = []byte(`!function(modules) {
"-": 189,
".": 190,
"/": 191,
- "` + "`" + `": 192,
+ "`))) + (("`" + (`": 192,
"[": 219,
"\\": 220,
"]": 221,
@@ -11191,7 +9981,7 @@ var _publicBundleJs = []byte(`!function(modules) {
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
}
return target;
- }, _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _ChildMapping = __webpack_require__(797), values = Object.values || function(obj) {
+ }, _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _ChildMapping = __webpack_require__(475), values = Object.values || function(obj) {
return Object.keys(obj).map(function(k) {
return obj[k];
});
@@ -11283,7 +10073,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, TransitionGroup.propTypes = "production" !== process.env.NODE_ENV ? propTypes : {},
TransitionGroup.defaultProps = defaultProps, exports.default = TransitionGroup,
module.exports = exports.default;
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -11294,7 +10084,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _Icon = __webpack_require__(800);
+ var _Icon = __webpack_require__(478);
Object.defineProperty(exports, "default", {
enumerable: !0,
get: function() {
@@ -11320,7 +10110,7 @@ var _publicBundleJs = []byte(`!function(modules) {
value: !0
}), exports.cloneChildrenWithClassName = cloneChildrenWithClassName, exports.isMuiElement = isMuiElement,
exports.isMuiComponent = isMuiComponent;
- var _react = __webpack_require__(1);
+ var _react = __webpack_require__(0);
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -11331,7 +10121,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _SvgIcon = __webpack_require__(801);
+ var _SvgIcon = __webpack_require__(479);
Object.defineProperty(exports, "default", {
enumerable: !0,
get: function() {
@@ -11340,6 +10130,17 @@ var _publicBundleJs = []byte(`!function(modules) {
});
}, function(module, exports, __webpack_require__) {
"use strict";
+ exports.__esModule = !0;
+ var _setStatic = __webpack_require__(484), _setStatic2 = function(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
+ }(_setStatic), setDisplayName = function(displayName) {
+ return (0, _setStatic2.default)("displayName", displayName);
+ };
+ exports.default = setDisplayName;
+}, function(module, exports, __webpack_require__) {
+ "use strict";
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
@@ -11348,273 +10149,36 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _Typography = __webpack_require__(802);
+ var _Grid = __webpack_require__(509);
Object.defineProperty(exports, "default", {
enumerable: !0,
get: function() {
- return _interopRequireDefault(_Typography).default;
+ return _interopRequireDefault(_Grid).default;
}
});
}, function(module, exports, __webpack_require__) {
- "use strict";
- exports.__esModule = !0;
- var _setStatic = __webpack_require__(806), _setStatic2 = function(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
- };
- }(_setStatic), setDisplayName = function(displayName) {
- return (0, _setStatic2.default)("displayName", displayName);
- };
- exports.default = setDisplayName;
+ (function(global) {
+ var freeGlobal = "object" == typeof global && global && global.Object === Object && global;
+ module.exports = freeGlobal;
+ }).call(exports, __webpack_require__(51));
}, function(module, exports, __webpack_require__) {
- "use strict";
- (function(process) {
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
- };
- }
- function getDefaultTheme() {
- return defaultTheme || (defaultTheme = (0, _createMuiTheme2.default)());
+ function toNumber(value) {
+ if ("number" == typeof value) return value;
+ if (isSymbol(value)) return NAN;
+ if (isObject(value)) {
+ var other = "function" == typeof value.valueOf ? value.valueOf() : value;
+ value = isObject(other) ? other + "" : other;
}
- Object.defineProperty(exports, "__esModule", {
- value: !0
- });
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _getPrototypeOf = __webpack_require__(38), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(39), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(40), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(41), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(42), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _wrapDisplayName = __webpack_require__(95), _wrapDisplayName2 = _interopRequireDefault(_wrapDisplayName), _hoistNonReactStatics = __webpack_require__(194), _hoistNonReactStatics2 = _interopRequireDefault(_hoistNonReactStatics), _createMuiTheme = __webpack_require__(193), _createMuiTheme2 = _interopRequireDefault(_createMuiTheme), _themeListener = __webpack_require__(192), _themeListener2 = _interopRequireDefault(_themeListener), defaultTheme = void 0, withTheme = function() {
- return function(Component) {
- var WithTheme = function(_React$Component) {
- function WithTheme(props, context) {
- (0, _classCallCheck3.default)(this, WithTheme);
- var _this = (0, _possibleConstructorReturn3.default)(this, (WithTheme.__proto__ || (0,
- _getPrototypeOf2.default)(WithTheme)).call(this, props, context));
- return _this.state = {}, _this.unsubscribeId = null, _this.state = {
- theme: _themeListener2.default.initial(context) || getDefaultTheme()
- }, _this;
- }
- return (0, _inherits3.default)(WithTheme, _React$Component), (0, _createClass3.default)(WithTheme, [ {
- key: "componentDidMount",
- value: function() {
- var _this2 = this;
- this.unsubscribeId = _themeListener2.default.subscribe(this.context, function(theme) {
- _this2.setState({
- theme: theme
- });
- });
- }
- }, {
- key: "componentWillUnmount",
- value: function() {
- null !== this.unsubscribeId && _themeListener2.default.unsubscribe(this.context, this.unsubscribeId);
- }
- }, {
- key: "render",
- value: function() {
- return _react2.default.createElement(Component, (0, _extends3.default)({
- theme: this.state.theme
- }, this.props));
- }
- } ]), WithTheme;
- }(_react2.default.Component);
- return WithTheme.contextTypes = _themeListener2.default.contextTypes, "production" !== process.env.NODE_ENV && (WithTheme.displayName = (0,
- _wrapDisplayName2.default)(Component, "withTheme")), (0, _hoistNonReactStatics2.default)(WithTheme, Component),
- "production" !== process.env.NODE_ENV && (WithTheme.Naked = Component), WithTheme;
- };
- };
- exports.default = withTheme;
- }).call(exports, __webpack_require__(3));
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- Object.defineProperty(__webpack_exports__, "__esModule", {
- value: !0
- });
- var __WEBPACK_IMPORTED_MODULE_1__container_Surface__ = (__webpack_require__(830),
- __webpack_require__(103));
- __webpack_require__.d(__webpack_exports__, "Surface", function() {
- return __WEBPACK_IMPORTED_MODULE_1__container_Surface__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_2__container_Layer__ = __webpack_require__(18);
- __webpack_require__.d(__webpack_exports__, "Layer", function() {
- return __WEBPACK_IMPORTED_MODULE_2__container_Layer__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_3__component_Legend__ = __webpack_require__(233);
- __webpack_require__.d(__webpack_exports__, "Legend", function() {
- return __WEBPACK_IMPORTED_MODULE_3__component_Legend__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_4__component_Tooltip__ = __webpack_require__(164);
- __webpack_require__.d(__webpack_exports__, "Tooltip", function() {
- return __WEBPACK_IMPORTED_MODULE_4__component_Tooltip__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_5__component_ResponsiveContainer__ = __webpack_require__(989);
- __webpack_require__.d(__webpack_exports__, "ResponsiveContainer", function() {
- return __WEBPACK_IMPORTED_MODULE_5__component_ResponsiveContainer__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_6__component_Cell__ = __webpack_require__(111);
- __webpack_require__.d(__webpack_exports__, "Cell", function() {
- return __WEBPACK_IMPORTED_MODULE_6__component_Cell__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_7__component_Text__ = __webpack_require__(72);
- __webpack_require__.d(__webpack_exports__, "Text", function() {
- return __WEBPACK_IMPORTED_MODULE_7__component_Text__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_8__component_Label__ = __webpack_require__(60);
- __webpack_require__.d(__webpack_exports__, "Label", function() {
- return __WEBPACK_IMPORTED_MODULE_8__component_Label__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_9__component_LabelList__ = __webpack_require__(62);
- __webpack_require__.d(__webpack_exports__, "LabelList", function() {
- return __WEBPACK_IMPORTED_MODULE_9__component_LabelList__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_10__shape_Sector__ = __webpack_require__(170);
- __webpack_require__.d(__webpack_exports__, "Sector", function() {
- return __WEBPACK_IMPORTED_MODULE_10__shape_Sector__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_11__shape_Curve__ = __webpack_require__(86);
- __webpack_require__.d(__webpack_exports__, "Curve", function() {
- return __WEBPACK_IMPORTED_MODULE_11__shape_Curve__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_12__shape_Rectangle__ = __webpack_require__(85);
- __webpack_require__.d(__webpack_exports__, "Rectangle", function() {
- return __WEBPACK_IMPORTED_MODULE_12__shape_Rectangle__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_13__shape_Polygon__ = __webpack_require__(258);
- __webpack_require__.d(__webpack_exports__, "Polygon", function() {
- return __WEBPACK_IMPORTED_MODULE_13__shape_Polygon__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_14__shape_Dot__ = __webpack_require__(74);
- __webpack_require__.d(__webpack_exports__, "Dot", function() {
- return __WEBPACK_IMPORTED_MODULE_14__shape_Dot__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_15__shape_Cross__ = __webpack_require__(444);
- __webpack_require__.d(__webpack_exports__, "Cross", function() {
- return __WEBPACK_IMPORTED_MODULE_15__shape_Cross__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_16__shape_Symbols__ = __webpack_require__(234);
- __webpack_require__.d(__webpack_exports__, "Symbols", function() {
- return __WEBPACK_IMPORTED_MODULE_16__shape_Symbols__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_17__polar_PolarGrid__ = __webpack_require__(1090);
- __webpack_require__.d(__webpack_exports__, "PolarGrid", function() {
- return __WEBPACK_IMPORTED_MODULE_17__polar_PolarGrid__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_18__polar_PolarRadiusAxis__ = __webpack_require__(171);
- __webpack_require__.d(__webpack_exports__, "PolarRadiusAxis", function() {
- return __WEBPACK_IMPORTED_MODULE_18__polar_PolarRadiusAxis__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_19__polar_PolarAngleAxis__ = __webpack_require__(172);
- __webpack_require__.d(__webpack_exports__, "PolarAngleAxis", function() {
- return __WEBPACK_IMPORTED_MODULE_19__polar_PolarAngleAxis__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_20__polar_Pie__ = __webpack_require__(446);
- __webpack_require__.d(__webpack_exports__, "Pie", function() {
- return __WEBPACK_IMPORTED_MODULE_20__polar_Pie__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_21__polar_Radar__ = __webpack_require__(447);
- __webpack_require__.d(__webpack_exports__, "Radar", function() {
- return __WEBPACK_IMPORTED_MODULE_21__polar_Radar__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_22__polar_RadialBar__ = __webpack_require__(448);
- __webpack_require__.d(__webpack_exports__, "RadialBar", function() {
- return __WEBPACK_IMPORTED_MODULE_22__polar_RadialBar__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_23__cartesian_Brush__ = __webpack_require__(449);
- __webpack_require__.d(__webpack_exports__, "Brush", function() {
- return __WEBPACK_IMPORTED_MODULE_23__cartesian_Brush__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_24__cartesian_ReferenceLine__ = __webpack_require__(442);
- __webpack_require__.d(__webpack_exports__, "ReferenceLine", function() {
- return __WEBPACK_IMPORTED_MODULE_24__cartesian_ReferenceLine__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_25__cartesian_ReferenceDot__ = __webpack_require__(441);
- __webpack_require__.d(__webpack_exports__, "ReferenceDot", function() {
- return __WEBPACK_IMPORTED_MODULE_25__cartesian_ReferenceDot__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_26__cartesian_ReferenceArea__ = __webpack_require__(443);
- __webpack_require__.d(__webpack_exports__, "ReferenceArea", function() {
- return __WEBPACK_IMPORTED_MODULE_26__cartesian_ReferenceArea__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_27__cartesian_CartesianAxis__ = __webpack_require__(451);
- __webpack_require__.d(__webpack_exports__, "CartesianAxis", function() {
- return __WEBPACK_IMPORTED_MODULE_27__cartesian_CartesianAxis__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_28__cartesian_CartesianGrid__ = __webpack_require__(1095);
- __webpack_require__.d(__webpack_exports__, "CartesianGrid", function() {
- return __WEBPACK_IMPORTED_MODULE_28__cartesian_CartesianGrid__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_29__cartesian_Line__ = __webpack_require__(259);
- __webpack_require__.d(__webpack_exports__, "Line", function() {
- return __WEBPACK_IMPORTED_MODULE_29__cartesian_Line__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_30__cartesian_Area__ = __webpack_require__(260);
- __webpack_require__.d(__webpack_exports__, "Area", function() {
- return __WEBPACK_IMPORTED_MODULE_30__cartesian_Area__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_31__cartesian_Bar__ = __webpack_require__(261);
- __webpack_require__.d(__webpack_exports__, "Bar", function() {
- return __WEBPACK_IMPORTED_MODULE_31__cartesian_Bar__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_32__cartesian_Scatter__ = __webpack_require__(262);
- __webpack_require__.d(__webpack_exports__, "Scatter", function() {
- return __WEBPACK_IMPORTED_MODULE_32__cartesian_Scatter__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_33__cartesian_XAxis__ = __webpack_require__(87);
- __webpack_require__.d(__webpack_exports__, "XAxis", function() {
- return __WEBPACK_IMPORTED_MODULE_33__cartesian_XAxis__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_34__cartesian_YAxis__ = __webpack_require__(88);
- __webpack_require__.d(__webpack_exports__, "YAxis", function() {
- return __WEBPACK_IMPORTED_MODULE_34__cartesian_YAxis__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_35__cartesian_ZAxis__ = __webpack_require__(173);
- __webpack_require__.d(__webpack_exports__, "ZAxis", function() {
- return __WEBPACK_IMPORTED_MODULE_35__cartesian_ZAxis__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_36__cartesian_ErrorBar__ = __webpack_require__(117);
- __webpack_require__.d(__webpack_exports__, "ErrorBar", function() {
- return __WEBPACK_IMPORTED_MODULE_36__cartesian_ErrorBar__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_37__chart_LineChart__ = __webpack_require__(1096);
- __webpack_require__.d(__webpack_exports__, "LineChart", function() {
- return __WEBPACK_IMPORTED_MODULE_37__chart_LineChart__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_38__chart_BarChart__ = __webpack_require__(1100);
- __webpack_require__.d(__webpack_exports__, "BarChart", function() {
- return __WEBPACK_IMPORTED_MODULE_38__chart_BarChart__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_39__chart_PieChart__ = __webpack_require__(1101);
- __webpack_require__.d(__webpack_exports__, "PieChart", function() {
- return __WEBPACK_IMPORTED_MODULE_39__chart_PieChart__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_40__chart_Treemap__ = __webpack_require__(1102);
- __webpack_require__.d(__webpack_exports__, "Treemap", function() {
- return __WEBPACK_IMPORTED_MODULE_40__chart_Treemap__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_41__chart_Sankey__ = __webpack_require__(1103);
- __webpack_require__.d(__webpack_exports__, "Sankey", function() {
- return __WEBPACK_IMPORTED_MODULE_41__chart_Sankey__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_42__chart_RadarChart__ = __webpack_require__(1106);
- __webpack_require__.d(__webpack_exports__, "RadarChart", function() {
- return __WEBPACK_IMPORTED_MODULE_42__chart_RadarChart__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_43__chart_ScatterChart__ = __webpack_require__(1107);
- __webpack_require__.d(__webpack_exports__, "ScatterChart", function() {
- return __WEBPACK_IMPORTED_MODULE_43__chart_ScatterChart__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_44__chart_AreaChart__ = __webpack_require__(1108);
- __webpack_require__.d(__webpack_exports__, "AreaChart", function() {
- return __WEBPACK_IMPORTED_MODULE_44__chart_AreaChart__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_45__chart_RadialBarChart__ = __webpack_require__(1109);
- __webpack_require__.d(__webpack_exports__, "RadialBarChart", function() {
- return __WEBPACK_IMPORTED_MODULE_45__chart_RadialBarChart__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_46__chart_ComposedChart__ = __webpack_require__(1110);
- __webpack_require__.d(__webpack_exports__, "ComposedChart", function() {
- return __WEBPACK_IMPORTED_MODULE_46__chart_ComposedChart__.a;
- });
+ if ("string" != typeof value) return 0 === value ? value : +value;
+ value = value.replace(reTrim, "");
+ var isBinary = reIsBinary.test(value);
+ return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
+ }
+ var isObject = __webpack_require__(31), isSymbol = __webpack_require__(62), NAN = NaN, reTrim = /^\s+|\s+$/g, reIsBadHex = /^[-+]0x[0-9a-f]+$/i, reIsBinary = /^0b[01]+$/i, reIsOctal = /^0o[0-7]+$/i, freeParseInt = parseInt;
+ module.exports = toNumber;
}, function(module, exports, __webpack_require__) {
- var dP = __webpack_require__(833), createDesc = __webpack_require__(838);
- module.exports = __webpack_require__(224) ? function(object, key, value) {
+ var dP = __webpack_require__(528), createDesc = __webpack_require__(533);
+ module.exports = __webpack_require__(161) ? function(object, key, value) {
return dP.f(object, key, createDesc(1, value));
} : function(object, key, value) {
return object[key] = value, object;
@@ -11624,23 +10188,18 @@ var _publicBundleJs = []byte(`!function(modules) {
return (x = +x) > -1e-8 && x < 1e-8 ? x - x * x / 2 : Math.log(1 + x);
};
}, function(module, exports, __webpack_require__) {
- (function(global) {
- var freeGlobal = "object" == typeof global && global && global.Object === Object && global;
- module.exports = freeGlobal;
- }).call(exports, __webpack_require__(68));
-}, function(module, exports, __webpack_require__) {
function baseGet(object, path) {
path = castPath(path, object);
for (var index = 0, length = path.length; null != object && index < length; ) object = object[toKey(path[index++])];
return index && index == length ? object : void 0;
}
- var castPath = __webpack_require__(367), toKey = __webpack_require__(158);
+ var castPath = __webpack_require__(247), toKey = __webpack_require__(116);
module.exports = baseGet;
}, function(module, exports, __webpack_require__) {
function castPath(value, object) {
return isArray(value) ? value : isKey(value, object) ? [ value ] : stringToPath(toString(value));
}
- var isArray = __webpack_require__(16), isKey = __webpack_require__(228), stringToPath = __webpack_require__(863), toString = __webpack_require__(887);
+ var isArray = __webpack_require__(12), isKey = __webpack_require__(166), stringToPath = __webpack_require__(556), toString = __webpack_require__(580);
module.exports = castPath;
}, function(module, exports) {
function toSource(func) {
@@ -11658,7 +10217,7 @@ var _publicBundleJs = []byte(`!function(modules) {
module.exports = toSource;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0_d3_path__ = __webpack_require__(105), __WEBPACK_IMPORTED_MODULE_1__constant__ = __webpack_require__(71), __WEBPACK_IMPORTED_MODULE_2__curve_linear__ = __webpack_require__(160), __WEBPACK_IMPORTED_MODULE_3__line__ = __webpack_require__(236), __WEBPACK_IMPORTED_MODULE_4__point__ = __webpack_require__(237);
+ var __WEBPACK_IMPORTED_MODULE_0_d3_path__ = __webpack_require__(79), __WEBPACK_IMPORTED_MODULE_1__constant__ = __webpack_require__(54), __WEBPACK_IMPORTED_MODULE_2__curve_linear__ = __webpack_require__(118), __WEBPACK_IMPORTED_MODULE_3__line__ = __webpack_require__(174), __WEBPACK_IMPORTED_MODULE_4__point__ = __webpack_require__(175);
__webpack_exports__.a = function() {
function area(data) {
var i, j, k, d, buffer, n = data.length, defined0 = !1, x0z = new Array(n), y0z = new Array(n);
@@ -11726,7 +10285,7 @@ var _publicBundleJs = []byte(`!function(modules) {
__webpack_require__.d(__webpack_exports__, "a", function() {
return curveRadialLinear;
}), __webpack_exports__.b = curveRadial;
- var __WEBPACK_IMPORTED_MODULE_0__linear__ = __webpack_require__(160), curveRadialLinear = curveRadial(__WEBPACK_IMPORTED_MODULE_0__linear__.a);
+ var __WEBPACK_IMPORTED_MODULE_0__linear__ = __webpack_require__(118), curveRadialLinear = curveRadial(__WEBPACK_IMPORTED_MODULE_0__linear__.a);
Radial.prototype = {
areaStart: function() {
this._curve.areaStart();
@@ -11753,8 +10312,8 @@ var _publicBundleJs = []byte(`!function(modules) {
}, l;
}
__webpack_exports__.a = lineRadial;
- var __WEBPACK_IMPORTED_MODULE_0__curve_radial__ = __webpack_require__(370);
- __webpack_require__(236);
+ var __WEBPACK_IMPORTED_MODULE_0__curve_radial__ = __webpack_require__(250);
+ __webpack_require__(174);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_exports__.a = function(x, y) {
@@ -11768,7 +10327,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var slice = Array.prototype.slice;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(106);
+ var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(80);
__webpack_exports__.a = {
draw: function(context, size) {
var r = Math.sqrt(size / __WEBPACK_IMPORTED_MODULE_0__math__.j);
@@ -11798,7 +10357,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(106), kr = Math.sin(__WEBPACK_IMPORTED_MODULE_0__math__.j / 10) / Math.sin(7 * __WEBPACK_IMPORTED_MODULE_0__math__.j / 10), kx = Math.sin(__WEBPACK_IMPORTED_MODULE_0__math__.m / 10) * kr, ky = -Math.cos(__WEBPACK_IMPORTED_MODULE_0__math__.m / 10) * kr;
+ var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(80), kr = Math.sin(__WEBPACK_IMPORTED_MODULE_0__math__.j / 10) / Math.sin(7 * __WEBPACK_IMPORTED_MODULE_0__math__.j / 10), kx = Math.sin(__WEBPACK_IMPORTED_MODULE_0__math__.m / 10) * kr, ky = -Math.cos(__WEBPACK_IMPORTED_MODULE_0__math__.m / 10) * kr;
__webpack_exports__.a = {
draw: function(context, size) {
var r = Math.sqrt(.8908130915292852 * size), x = kx * r, y = ky * r;
@@ -11846,7 +10405,7 @@ var _publicBundleJs = []byte(`!function(modules) {
this._context = context, this._k = (1 - tension) / 6;
}
__webpack_exports__.a = CardinalClosed;
- var __WEBPACK_IMPORTED_MODULE_0__noop__ = __webpack_require__(161), __WEBPACK_IMPORTED_MODULE_1__cardinal__ = __webpack_require__(163);
+ var __WEBPACK_IMPORTED_MODULE_0__noop__ = __webpack_require__(119), __WEBPACK_IMPORTED_MODULE_1__cardinal__ = __webpack_require__(121);
CardinalClosed.prototype = {
areaStart: __WEBPACK_IMPORTED_MODULE_0__noop__.a,
areaEnd: __WEBPACK_IMPORTED_MODULE_0__noop__.a,
@@ -11903,7 +10462,7 @@ var _publicBundleJs = []byte(`!function(modules) {
this._context = context, this._k = (1 - tension) / 6;
}
__webpack_exports__.a = CardinalOpen;
- var __WEBPACK_IMPORTED_MODULE_0__cardinal__ = __webpack_require__(163);
+ var __WEBPACK_IMPORTED_MODULE_0__cardinal__ = __webpack_require__(121);
CardinalOpen.prototype = {
areaStart: function() {
this._line = 0;
@@ -11998,7 +10557,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _class, _class2, _temp, _isEqual2 = __webpack_require__(49), _isEqual3 = _interopRequireDefault(_isEqual2), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, _isEqual2 = __webpack_require__(34), _isEqual3 = _interopRequireDefault(_isEqual2), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -12016,7 +10575,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _AnimateManager = __webpack_require__(947), _AnimateManager2 = _interopRequireDefault(_AnimateManager), _PureRender = __webpack_require__(950), _PureRender2 = _interopRequireDefault(_PureRender), _easing = __webpack_require__(395), _configUpdate = __webpack_require__(969), _configUpdate2 = _interopRequireDefault(_configUpdate), _util = __webpack_require__(165), Animate = (0,
+ }(), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _AnimateManager = __webpack_require__(640), _AnimateManager2 = _interopRequireDefault(_AnimateManager), _PureRender = __webpack_require__(643), _PureRender2 = _interopRequireDefault(_PureRender), _easing = __webpack_require__(275), _configUpdate = __webpack_require__(662), _configUpdate2 = _interopRequireDefault(_configUpdate), _util = __webpack_require__(123), Animate = (0,
_PureRender2.default)((_temp = _class2 = function(_Component) {
function Animate(props, context) {
_classCallCheck(this, Animate);
@@ -12194,7 +10753,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var data = this.__data__ = new ListCache(entries);
this.size = data.size;
}
- var ListCache = __webpack_require__(154), stackClear = __webpack_require__(916), stackDelete = __webpack_require__(917), stackGet = __webpack_require__(918), stackHas = __webpack_require__(919), stackSet = __webpack_require__(920);
+ var ListCache = __webpack_require__(112), stackClear = __webpack_require__(609), stackDelete = __webpack_require__(610), stackGet = __webpack_require__(611), stackHas = __webpack_require__(612), stackSet = __webpack_require__(613);
Stack.prototype.clear = stackClear, Stack.prototype.delete = stackDelete, Stack.prototype.get = stackGet,
Stack.prototype.has = stackHas, Stack.prototype.set = stackSet, module.exports = Stack;
}, function(module, exports, __webpack_require__) {
@@ -12226,14 +10785,14 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return stack.delete(array), stack.delete(other), result;
}
- var SetCache = __webpack_require__(386), arraySome = __webpack_require__(923), cacheHas = __webpack_require__(387), COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2;
+ var SetCache = __webpack_require__(266), arraySome = __webpack_require__(616), cacheHas = __webpack_require__(267), COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2;
module.exports = equalArrays;
}, function(module, exports, __webpack_require__) {
function SetCache(values) {
var index = -1, length = null == values ? 0 : values.length;
for (this.__data__ = new MapCache(); ++index < length; ) this.add(values[index]);
}
- var MapCache = __webpack_require__(229), setCacheAdd = __webpack_require__(921), setCacheHas = __webpack_require__(922);
+ var MapCache = __webpack_require__(167), setCacheAdd = __webpack_require__(614), setCacheHas = __webpack_require__(615);
SetCache.prototype.add = SetCache.prototype.push = setCacheAdd, SetCache.prototype.has = setCacheHas,
module.exports = SetCache;
}, function(module, exports) {
@@ -12258,11 +10817,11 @@ var _publicBundleJs = []byte(`!function(modules) {
module.exports = arrayFilter;
}, function(module, exports, __webpack_require__) {
(function(module) {
- var root = __webpack_require__(46), stubFalse = __webpack_require__(936), freeExports = "object" == typeof exports && exports && !exports.nodeType && exports, freeModule = freeExports && "object" == typeof module && module && !module.nodeType && module, moduleExports = freeModule && freeModule.exports === freeExports, Buffer = moduleExports ? root.Buffer : void 0, nativeIsBuffer = Buffer ? Buffer.isBuffer : void 0, isBuffer = nativeIsBuffer || stubFalse;
+ var root = __webpack_require__(32), stubFalse = __webpack_require__(629), freeExports = "object" == typeof exports && exports && !exports.nodeType && exports, freeModule = freeExports && "object" == typeof module && module && !module.nodeType && module, moduleExports = freeModule && freeModule.exports === freeExports, Buffer = moduleExports ? root.Buffer : void 0, nativeIsBuffer = Buffer ? Buffer.isBuffer : void 0, isBuffer = nativeIsBuffer || stubFalse;
module.exports = isBuffer;
- }).call(exports, __webpack_require__(197)(module));
+ }).call(exports, __webpack_require__(154)(module));
}, function(module, exports, __webpack_require__) {
- var baseIsTypedArray = __webpack_require__(937), baseUnary = __webpack_require__(245), nodeUtil = __webpack_require__(938), nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray, isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
+ var baseIsTypedArray = __webpack_require__(630), baseUnary = __webpack_require__(183), nodeUtil = __webpack_require__(631), nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray, isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
module.exports = isTypedArray;
}, function(module, exports) {
function overArg(func, transform) {
@@ -12273,7 +10832,7 @@ var _publicBundleJs = []byte(`!function(modules) {
module.exports = overArg;
}, function(module, exports, __webpack_require__) {
(function(global) {
- for (var now = __webpack_require__(949), root = "undefined" == typeof window ? global : window, vendors = [ "moz", "webkit" ], suffix = "AnimationFrame", raf = root["request" + suffix], caf = root["cancel" + suffix] || root["cancelRequest" + suffix], i = 0; !raf && i < vendors.length; i++) raf = root[vendors[i] + "Request" + suffix],
+ for (var now = __webpack_require__(642), root = "undefined" == typeof window ? global : window, vendors = [ "moz", "webkit" ], suffix = "AnimationFrame", raf = root["request" + suffix], caf = root["cancel" + suffix] || root["cancelRequest" + suffix], i = 0; !raf && i < vendors.length; i++) raf = root[vendors[i] + "Request" + suffix],
caf = root[vendors[i] + "Cancel" + suffix] || root[vendors[i] + "CancelRequest" + suffix];
if (!raf || !caf) {
var last = 0, id = 0, queue = [];
@@ -12308,7 +10867,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, module.exports.polyfill = function(object) {
object || (object = root), object.requestAnimationFrame = raf, object.cancelAnimationFrame = caf;
};
- }).call(exports, __webpack_require__(68));
+ }).call(exports, __webpack_require__(51));
}, function(module, exports, __webpack_require__) {
function isPlainObject(value) {
if (!isObjectLike(value) || baseGetTag(value) != objectTag) return !1;
@@ -12317,7 +10876,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var Ctor = hasOwnProperty.call(proto, "constructor") && proto.constructor;
return "function" == typeof Ctor && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString;
}
- var baseGetTag = __webpack_require__(59), getPrototype = __webpack_require__(951), isObjectLike = __webpack_require__(52), objectTag = "[object Object]", funcProto = Function.prototype, objectProto = Object.prototype, funcToString = funcProto.toString, hasOwnProperty = objectProto.hasOwnProperty, objectCtorString = funcToString.call(Object);
+ var baseGetTag = __webpack_require__(42), getPrototype = __webpack_require__(644), isObjectLike = __webpack_require__(36), objectTag = "[object Object]", funcProto = Function.prototype, objectProto = Object.prototype, funcToString = funcProto.toString, hasOwnProperty = objectProto.hasOwnProperty, objectCtorString = funcToString.call(Object);
module.exports = isPlainObject;
}, function(module, exports, __webpack_require__) {
"use strict";
@@ -12331,7 +10890,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.configEasing = exports.configSpring = exports.configBezier = void 0;
- var _util = __webpack_require__(165), cubicBezierFactor = function(c1, c2) {
+ var _util = __webpack_require__(123), cubicBezierFactor = function(c1, c2) {
return [ 0, 3 * c1, 3 * c2 - 6 * c1, 3 * c1 - 3 * c2 + 1 ];
}, multyTime = function(params, t) {
return params.map(function(param, i) {
@@ -12423,16 +10982,16 @@ var _publicBundleJs = []byte(`!function(modules) {
function baseRest(func, start) {
return setToString(overRest(func, start, identity), func + "");
}
- var identity = __webpack_require__(83), overRest = __webpack_require__(960), setToString = __webpack_require__(962);
+ var identity = __webpack_require__(63), overRest = __webpack_require__(653), setToString = __webpack_require__(655);
module.exports = baseRest;
}, function(module, exports, __webpack_require__) {
- var baseForOwn = __webpack_require__(972), createBaseEach = __webpack_require__(975), baseEach = createBaseEach(baseForOwn);
+ var baseForOwn = __webpack_require__(665), createBaseEach = __webpack_require__(668), baseEach = createBaseEach(baseForOwn);
module.exports = baseEach;
}, function(module, exports, __webpack_require__) {
function isStrictComparable(value) {
return value === value && !isObject(value);
}
- var isObject = __webpack_require__(47);
+ var isObject = __webpack_require__(31);
module.exports = isStrictComparable;
}, function(module, exports) {
function matchesStrictComparable(key, srcValue) {
@@ -12441,21 +11000,6 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}
module.exports = matchesStrictComparable;
-}, function(module, exports, __webpack_require__) {
- function toNumber(value) {
- if ("number" == typeof value) return value;
- if (isSymbol(value)) return NAN;
- if (isObject(value)) {
- var other = "function" == typeof value.valueOf ? value.valueOf() : value;
- value = isObject(other) ? other + "" : other;
- }
- if ("string" != typeof value) return 0 === value ? value : +value;
- value = value.replace(reTrim, "");
- var isBinary = reIsBinary.test(value);
- return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
- }
- var isObject = __webpack_require__(47), isSymbol = __webpack_require__(82), NAN = NaN, reTrim = /^\s+|\s+$/g, reIsBadHex = /^[-+]0x[0-9a-f]+$/i, reIsBinary = /^0b[01]+$/i, reIsOctal = /^0o[0-7]+$/i, freeParseInt = parseInt;
- module.exports = toNumber;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
(function(process) {
@@ -12471,9 +11015,9 @@ var _publicBundleJs = []byte(`!function(modules) {
}));
}
};
- }).call(__webpack_exports__, __webpack_require__(3));
+ }).call(__webpack_exports__, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
- var baseFlatten = __webpack_require__(1003), baseOrderBy = __webpack_require__(1005), baseRest = __webpack_require__(396), isIterateeCall = __webpack_require__(403), sortBy = baseRest(function(collection, iteratees) {
+ var baseFlatten = __webpack_require__(695), baseOrderBy = __webpack_require__(697), baseRest = __webpack_require__(276), isIterateeCall = __webpack_require__(282), sortBy = baseRest(function(collection, iteratees) {
if (null == collection) return [];
var length = iteratees.length;
return length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1]) ? iteratees = [] : length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2]) && (iteratees = [ iteratees[0] ]),
@@ -12486,7 +11030,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var type = typeof index;
return !!("number" == type ? isArrayLike(object) && isIndex(index, object.length) : "string" == type && index in object) && eq(object[index], value);
}
- var eq = __webpack_require__(230), isArrayLike = __webpack_require__(109), isIndex = __webpack_require__(243), isObject = __webpack_require__(47);
+ var eq = __webpack_require__(168), isArrayLike = __webpack_require__(83), isIndex = __webpack_require__(181), isObject = __webpack_require__(31);
module.exports = isIterateeCall;
}, function(module, exports) {
function baseGt(value, other) {
@@ -12497,7 +11041,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function min(array) {
return array && array.length ? baseExtremum(array, identity, baseLt) : void 0;
}
- var baseExtremum = __webpack_require__(166), baseLt = __webpack_require__(406), identity = __webpack_require__(83);
+ var baseExtremum = __webpack_require__(124), baseLt = __webpack_require__(285), identity = __webpack_require__(63);
module.exports = min;
}, function(module, exports) {
function baseLt(value, other) {
@@ -12575,77 +11119,77 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(__webpack_exports__, "__esModule", {
value: !0
});
- var __WEBPACK_IMPORTED_MODULE_0__src_band__ = __webpack_require__(1014);
+ var __WEBPACK_IMPORTED_MODULE_0__src_band__ = __webpack_require__(706);
__webpack_require__.d(__webpack_exports__, "scaleBand", function() {
return __WEBPACK_IMPORTED_MODULE_0__src_band__.a;
}), __webpack_require__.d(__webpack_exports__, "scalePoint", function() {
return __WEBPACK_IMPORTED_MODULE_0__src_band__.b;
});
- var __WEBPACK_IMPORTED_MODULE_1__src_identity__ = __webpack_require__(1037);
+ var __WEBPACK_IMPORTED_MODULE_1__src_identity__ = __webpack_require__(729);
__webpack_require__.d(__webpack_exports__, "scaleIdentity", function() {
return __WEBPACK_IMPORTED_MODULE_1__src_identity__.a;
});
- var __WEBPACK_IMPORTED_MODULE_2__src_linear__ = __webpack_require__(113);
+ var __WEBPACK_IMPORTED_MODULE_2__src_linear__ = __webpack_require__(87);
__webpack_require__.d(__webpack_exports__, "scaleLinear", function() {
return __WEBPACK_IMPORTED_MODULE_2__src_linear__.a;
});
- var __WEBPACK_IMPORTED_MODULE_3__src_log__ = __webpack_require__(1060);
+ var __WEBPACK_IMPORTED_MODULE_3__src_log__ = __webpack_require__(752);
__webpack_require__.d(__webpack_exports__, "scaleLog", function() {
return __WEBPACK_IMPORTED_MODULE_3__src_log__.a;
});
- var __WEBPACK_IMPORTED_MODULE_4__src_ordinal__ = __webpack_require__(421);
+ var __WEBPACK_IMPORTED_MODULE_4__src_ordinal__ = __webpack_require__(300);
__webpack_require__.d(__webpack_exports__, "scaleOrdinal", function() {
return __WEBPACK_IMPORTED_MODULE_4__src_ordinal__.a;
}), __webpack_require__.d(__webpack_exports__, "scaleImplicit", function() {
return __WEBPACK_IMPORTED_MODULE_4__src_ordinal__.b;
});
- var __WEBPACK_IMPORTED_MODULE_5__src_pow__ = __webpack_require__(1061);
+ var __WEBPACK_IMPORTED_MODULE_5__src_pow__ = __webpack_require__(753);
__webpack_require__.d(__webpack_exports__, "scalePow", function() {
return __WEBPACK_IMPORTED_MODULE_5__src_pow__.a;
}), __webpack_require__.d(__webpack_exports__, "scaleSqrt", function() {
return __WEBPACK_IMPORTED_MODULE_5__src_pow__.b;
});
- var __WEBPACK_IMPORTED_MODULE_6__src_quantile__ = __webpack_require__(1062);
+ var __WEBPACK_IMPORTED_MODULE_6__src_quantile__ = __webpack_require__(754);
__webpack_require__.d(__webpack_exports__, "scaleQuantile", function() {
return __WEBPACK_IMPORTED_MODULE_6__src_quantile__.a;
});
- var __WEBPACK_IMPORTED_MODULE_7__src_quantize__ = __webpack_require__(1063);
+ var __WEBPACK_IMPORTED_MODULE_7__src_quantize__ = __webpack_require__(755);
__webpack_require__.d(__webpack_exports__, "scaleQuantize", function() {
return __WEBPACK_IMPORTED_MODULE_7__src_quantize__.a;
});
- var __WEBPACK_IMPORTED_MODULE_8__src_threshold__ = __webpack_require__(1064);
+ var __WEBPACK_IMPORTED_MODULE_8__src_threshold__ = __webpack_require__(756);
__webpack_require__.d(__webpack_exports__, "scaleThreshold", function() {
return __WEBPACK_IMPORTED_MODULE_8__src_threshold__.a;
});
- var __WEBPACK_IMPORTED_MODULE_9__src_time__ = __webpack_require__(437);
+ var __WEBPACK_IMPORTED_MODULE_9__src_time__ = __webpack_require__(316);
__webpack_require__.d(__webpack_exports__, "scaleTime", function() {
return __WEBPACK_IMPORTED_MODULE_9__src_time__.b;
});
- var __WEBPACK_IMPORTED_MODULE_10__src_utcTime__ = __webpack_require__(1080);
+ var __WEBPACK_IMPORTED_MODULE_10__src_utcTime__ = __webpack_require__(772);
__webpack_require__.d(__webpack_exports__, "scaleUtc", function() {
return __WEBPACK_IMPORTED_MODULE_10__src_utcTime__.a;
});
- var __WEBPACK_IMPORTED_MODULE_11__src_category10__ = __webpack_require__(1081);
+ var __WEBPACK_IMPORTED_MODULE_11__src_category10__ = __webpack_require__(773);
__webpack_require__.d(__webpack_exports__, "schemeCategory10", function() {
return __WEBPACK_IMPORTED_MODULE_11__src_category10__.a;
});
- var __WEBPACK_IMPORTED_MODULE_12__src_category20b__ = __webpack_require__(1082);
+ var __WEBPACK_IMPORTED_MODULE_12__src_category20b__ = __webpack_require__(774);
__webpack_require__.d(__webpack_exports__, "schemeCategory20b", function() {
return __WEBPACK_IMPORTED_MODULE_12__src_category20b__.a;
});
- var __WEBPACK_IMPORTED_MODULE_13__src_category20c__ = __webpack_require__(1083);
+ var __WEBPACK_IMPORTED_MODULE_13__src_category20c__ = __webpack_require__(775);
__webpack_require__.d(__webpack_exports__, "schemeCategory20c", function() {
return __WEBPACK_IMPORTED_MODULE_13__src_category20c__.a;
});
- var __WEBPACK_IMPORTED_MODULE_14__src_category20__ = __webpack_require__(1084);
+ var __WEBPACK_IMPORTED_MODULE_14__src_category20__ = __webpack_require__(776);
__webpack_require__.d(__webpack_exports__, "schemeCategory20", function() {
return __WEBPACK_IMPORTED_MODULE_14__src_category20__.a;
});
- var __WEBPACK_IMPORTED_MODULE_15__src_cubehelix__ = __webpack_require__(1085);
+ var __WEBPACK_IMPORTED_MODULE_15__src_cubehelix__ = __webpack_require__(777);
__webpack_require__.d(__webpack_exports__, "interpolateCubehelixDefault", function() {
return __WEBPACK_IMPORTED_MODULE_15__src_cubehelix__.a;
});
- var __WEBPACK_IMPORTED_MODULE_16__src_rainbow__ = __webpack_require__(1086);
+ var __WEBPACK_IMPORTED_MODULE_16__src_rainbow__ = __webpack_require__(778);
__webpack_require__.d(__webpack_exports__, "interpolateRainbow", function() {
return __WEBPACK_IMPORTED_MODULE_16__src_rainbow__.b;
}), __webpack_require__.d(__webpack_exports__, "interpolateWarm", function() {
@@ -12653,7 +11197,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "interpolateCool", function() {
return __WEBPACK_IMPORTED_MODULE_16__src_rainbow__.a;
});
- var __WEBPACK_IMPORTED_MODULE_17__src_viridis__ = __webpack_require__(1087);
+ var __WEBPACK_IMPORTED_MODULE_17__src_viridis__ = __webpack_require__(779);
__webpack_require__.d(__webpack_exports__, "interpolateViridis", function() {
return __WEBPACK_IMPORTED_MODULE_17__src_viridis__.a;
}), __webpack_require__.d(__webpack_exports__, "interpolateMagma", function() {
@@ -12663,13 +11207,13 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "interpolatePlasma", function() {
return __WEBPACK_IMPORTED_MODULE_17__src_viridis__.d;
});
- var __WEBPACK_IMPORTED_MODULE_18__src_sequential__ = __webpack_require__(1088);
+ var __WEBPACK_IMPORTED_MODULE_18__src_sequential__ = __webpack_require__(780);
__webpack_require__.d(__webpack_exports__, "scaleSequential", function() {
return __WEBPACK_IMPORTED_MODULE_18__src_sequential__.a;
});
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__ascending__ = __webpack_require__(84), __WEBPACK_IMPORTED_MODULE_1__bisector__ = __webpack_require__(410), ascendingBisect = Object(__WEBPACK_IMPORTED_MODULE_1__bisector__.a)(__WEBPACK_IMPORTED_MODULE_0__ascending__.a), bisectRight = ascendingBisect.right;
+ var __WEBPACK_IMPORTED_MODULE_0__ascending__ = __webpack_require__(64), __WEBPACK_IMPORTED_MODULE_1__bisector__ = __webpack_require__(289), ascendingBisect = Object(__WEBPACK_IMPORTED_MODULE_1__bisector__.a)(__WEBPACK_IMPORTED_MODULE_0__ascending__.a), bisectRight = ascendingBisect.right;
ascendingBisect.left;
__webpack_exports__.a = bisectRight;
}, function(module, __webpack_exports__, __webpack_require__) {
@@ -12679,7 +11223,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return Object(__WEBPACK_IMPORTED_MODULE_0__ascending__.a)(f(d), x);
};
}
- var __WEBPACK_IMPORTED_MODULE_0__ascending__ = __webpack_require__(84);
+ var __WEBPACK_IMPORTED_MODULE_0__ascending__ = __webpack_require__(64);
__webpack_exports__.a = function(compare) {
return 1 === compare.length && (compare = ascendingComparator(compare)), {
left: function(a, x, lo, hi) {
@@ -12706,14 +11250,14 @@ var _publicBundleJs = []byte(`!function(modules) {
__webpack_exports__.a = pair;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__variance__ = __webpack_require__(413);
+ var __WEBPACK_IMPORTED_MODULE_0__variance__ = __webpack_require__(292);
__webpack_exports__.a = function(array, f) {
var v = Object(__WEBPACK_IMPORTED_MODULE_0__variance__.a)(array, f);
return v ? Math.sqrt(v) : v;
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__number__ = __webpack_require__(112);
+ var __WEBPACK_IMPORTED_MODULE_0__number__ = __webpack_require__(86);
__webpack_exports__.a = function(values, valueof) {
var value, delta, n = values.length, m = 0, i = -1, mean = 0, sum = 0;
if (null == valueof) for (;++i < n; ) isNaN(value = Object(__WEBPACK_IMPORTED_MODULE_0__number__.a)(values[i])) || (delta = value - mean,
@@ -12789,7 +11333,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function length(d) {
return d.length;
}
- var __WEBPACK_IMPORTED_MODULE_0__min__ = __webpack_require__(419);
+ var __WEBPACK_IMPORTED_MODULE_0__min__ = __webpack_require__(298);
__webpack_exports__.a = function(matrix) {
if (!(n = matrix.length)) return [];
for (var i = -1, m = Object(__WEBPACK_IMPORTED_MODULE_0__min__.a)(matrix, length), transpose = new Array(m); ++i < m; ) for (var n, j = -1, row = transpose[i] = new Array(n); ++j < n; ) row[j] = matrix[j][i];
@@ -12825,7 +11369,7 @@ var _publicBundleJs = []byte(`!function(modules) {
__webpack_require__.d(__webpack_exports__, "b", function() {
return implicit;
}), __webpack_exports__.a = ordinal;
- var __WEBPACK_IMPORTED_MODULE_0_d3_collection__ = __webpack_require__(1031), __WEBPACK_IMPORTED_MODULE_1__array__ = __webpack_require__(73), implicit = {
+ var __WEBPACK_IMPORTED_MODULE_0_d3_collection__ = __webpack_require__(723), __WEBPACK_IMPORTED_MODULE_1__array__ = __webpack_require__(56), implicit = {
name: "implicit"
};
}, function(module, __webpack_exports__, __webpack_require__) {
@@ -12848,7 +11392,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
};
}
- var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(61), __WEBPACK_IMPORTED_MODULE_1__basis__ = __webpack_require__(253), __WEBPACK_IMPORTED_MODULE_2__basisClosed__ = __webpack_require__(424), __WEBPACK_IMPORTED_MODULE_3__color__ = __webpack_require__(115);
+ var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(44), __WEBPACK_IMPORTED_MODULE_1__basis__ = __webpack_require__(190), __WEBPACK_IMPORTED_MODULE_2__basisClosed__ = __webpack_require__(303), __WEBPACK_IMPORTED_MODULE_3__color__ = __webpack_require__(89);
__webpack_exports__.a = function rgbGamma(y) {
function rgb(start, end) {
var r = color((start = Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__.f)(start)).r, (end = Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__.f)(end)).r), g = color(start.g, end.g), b = color(start.b, end.b), opacity = Object(__WEBPACK_IMPORTED_MODULE_3__color__.a)(start.opacity, end.opacity);
@@ -12863,7 +11407,7 @@ var _publicBundleJs = []byte(`!function(modules) {
rgbSpline(__WEBPACK_IMPORTED_MODULE_1__basis__.b), rgbSpline(__WEBPACK_IMPORTED_MODULE_2__basisClosed__.a);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__basis__ = __webpack_require__(253);
+ var __WEBPACK_IMPORTED_MODULE_0__basis__ = __webpack_require__(190);
__webpack_exports__.a = function(values) {
var n = values.length;
return function(t) {
@@ -12880,7 +11424,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__value__ = __webpack_require__(250);
+ var __WEBPACK_IMPORTED_MODULE_0__value__ = __webpack_require__(187);
__webpack_exports__.a = function(a, b) {
var i, nb = b ? b.length : 0, na = a ? Math.min(nb, a.length) : 0, x = new Array(na), c = new Array(nb);
for (i = 0; i < na; ++i) x[i] = Object(__WEBPACK_IMPORTED_MODULE_0__value__.a)(a[i], b[i]);
@@ -12900,7 +11444,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__value__ = __webpack_require__(250);
+ var __WEBPACK_IMPORTED_MODULE_0__value__ = __webpack_require__(187);
__webpack_exports__.a = function(a, b) {
var k, i = {}, c = {};
null !== a && "object" == typeof a || (a = {}), null !== b && "object" == typeof b || (b = {});
@@ -12922,7 +11466,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return b(t) + "";
};
}
- var __WEBPACK_IMPORTED_MODULE_0__number__ = __webpack_require__(167), reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, reB = new RegExp(reA.source, "g");
+ var __WEBPACK_IMPORTED_MODULE_0__number__ = __webpack_require__(125), reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, reB = new RegExp(reA.source, "g");
__webpack_exports__.a = function(a, b) {
var am, bm, bs, bi = reA.lastIndex = reB.lastIndex = 0, i = -1, s = [], q = [];
for (a += "", b += ""; (am = reA.exec(a)) && (bm = reB.exec(b)); ) (bs = bm.index) > bi && (bs = b.slice(bi, bs),
@@ -12944,32 +11488,32 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__ = __webpack_require__(1051);
+ var __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__ = __webpack_require__(743);
__webpack_require__.d(__webpack_exports__, "a", function() {
return __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__.a;
}), __webpack_require__.d(__webpack_exports__, "b", function() {
return __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__.b;
});
- var __WEBPACK_IMPORTED_MODULE_2__src_formatSpecifier__ = (__webpack_require__(432),
- __webpack_require__(433));
+ var __WEBPACK_IMPORTED_MODULE_2__src_formatSpecifier__ = (__webpack_require__(311),
+ __webpack_require__(312));
__webpack_require__.d(__webpack_exports__, "c", function() {
return __WEBPACK_IMPORTED_MODULE_2__src_formatSpecifier__.a;
});
- var __WEBPACK_IMPORTED_MODULE_3__src_precisionFixed__ = __webpack_require__(1057);
+ var __WEBPACK_IMPORTED_MODULE_3__src_precisionFixed__ = __webpack_require__(749);
__webpack_require__.d(__webpack_exports__, "d", function() {
return __WEBPACK_IMPORTED_MODULE_3__src_precisionFixed__.a;
});
- var __WEBPACK_IMPORTED_MODULE_4__src_precisionPrefix__ = __webpack_require__(1058);
+ var __WEBPACK_IMPORTED_MODULE_4__src_precisionPrefix__ = __webpack_require__(750);
__webpack_require__.d(__webpack_exports__, "e", function() {
return __WEBPACK_IMPORTED_MODULE_4__src_precisionPrefix__.a;
});
- var __WEBPACK_IMPORTED_MODULE_5__src_precisionRound__ = __webpack_require__(1059);
+ var __WEBPACK_IMPORTED_MODULE_5__src_precisionRound__ = __webpack_require__(751);
__webpack_require__.d(__webpack_exports__, "f", function() {
return __WEBPACK_IMPORTED_MODULE_5__src_precisionRound__.a;
});
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__exponent__ = __webpack_require__(169), __WEBPACK_IMPORTED_MODULE_1__formatGroup__ = __webpack_require__(1052), __WEBPACK_IMPORTED_MODULE_2__formatNumerals__ = __webpack_require__(1053), __WEBPACK_IMPORTED_MODULE_3__formatSpecifier__ = __webpack_require__(433), __WEBPACK_IMPORTED_MODULE_4__formatTypes__ = __webpack_require__(434), __WEBPACK_IMPORTED_MODULE_5__formatPrefixAuto__ = __webpack_require__(435), __WEBPACK_IMPORTED_MODULE_6__identity__ = __webpack_require__(1056), prefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ];
+ var __WEBPACK_IMPORTED_MODULE_0__exponent__ = __webpack_require__(127), __WEBPACK_IMPORTED_MODULE_1__formatGroup__ = __webpack_require__(744), __WEBPACK_IMPORTED_MODULE_2__formatNumerals__ = __webpack_require__(745), __WEBPACK_IMPORTED_MODULE_3__formatSpecifier__ = __webpack_require__(312), __WEBPACK_IMPORTED_MODULE_4__formatTypes__ = __webpack_require__(313), __WEBPACK_IMPORTED_MODULE_5__formatPrefixAuto__ = __webpack_require__(314), __WEBPACK_IMPORTED_MODULE_6__identity__ = __webpack_require__(748), prefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ];
__webpack_exports__.a = function(locale) {
function newFormat(specifier) {
function format(value) {
@@ -12979,7 +11523,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var valueNegative = value < 0;
if (value = formatType(Math.abs(value), precision), valueNegative && 0 == +value && (valueNegative = !1),
valuePrefix = (valueNegative ? "(" === sign ? sign : "-" : "-" === sign || "(" === sign ? "" : sign) + valuePrefix,
- valueSuffix = valueSuffix + ("s" === type ? prefixes[8 + __WEBPACK_IMPORTED_MODULE_5__formatPrefixAuto__.b / 3] : "") + (valueNegative && "(" === sign ? ")" : ""),
+ valueSuffix = ("s" === type ? prefixes[8 + __WEBPACK_IMPORTED_MODULE_5__formatPrefixAuto__.b / 3] : "") + valueSuffix + (valueNegative && "(" === sign ? ")" : ""),
maybeSuffix) for (i = -1, n = value.length; ++i < n; ) if (48 > (c = value.charCodeAt(i)) || c > 57) {
valueSuffix = (46 === c ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix,
value = value.slice(0, i);
@@ -13041,13 +11585,13 @@ var _publicBundleJs = []byte(`!function(modules) {
this.width = width, this.comma = comma, this.precision = precision, this.type = type;
}
__webpack_exports__.a = formatSpecifier;
- var __WEBPACK_IMPORTED_MODULE_0__formatTypes__ = __webpack_require__(434), re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;
+ var __WEBPACK_IMPORTED_MODULE_0__formatTypes__ = __webpack_require__(313), re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;
formatSpecifier.prototype = FormatSpecifier.prototype, FormatSpecifier.prototype.toString = function() {
return this.fill + this.align + this.sign + this.symbol + (this.zero ? "0" : "") + (null == this.width ? "" : Math.max(1, 0 | this.width)) + (this.comma ? "," : "") + (null == this.precision ? "" : "." + Math.max(0, 0 | this.precision)) + this.type;
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__formatDefault__ = __webpack_require__(1054), __WEBPACK_IMPORTED_MODULE_1__formatPrefixAuto__ = __webpack_require__(435), __WEBPACK_IMPORTED_MODULE_2__formatRounded__ = __webpack_require__(1055);
+ var __WEBPACK_IMPORTED_MODULE_0__formatDefault__ = __webpack_require__(746), __WEBPACK_IMPORTED_MODULE_1__formatPrefixAuto__ = __webpack_require__(314), __WEBPACK_IMPORTED_MODULE_2__formatRounded__ = __webpack_require__(747);
__webpack_exports__.a = {
"": __WEBPACK_IMPORTED_MODULE_0__formatDefault__.a,
"%": function(x, p) {
@@ -13091,7 +11635,7 @@ var _publicBundleJs = []byte(`!function(modules) {
__webpack_require__.d(__webpack_exports__, "b", function() {
return prefixExponent;
});
- var prefixExponent, __WEBPACK_IMPORTED_MODULE_0__formatDecimal__ = __webpack_require__(255);
+ var prefixExponent, __WEBPACK_IMPORTED_MODULE_0__formatDecimal__ = __webpack_require__(192);
__webpack_exports__.a = function(x, p) {
var d = Object(__WEBPACK_IMPORTED_MODULE_0__formatDecimal__.a)(x, p);
if (!d) return x + "";
@@ -13149,19 +11693,19 @@ var _publicBundleJs = []byte(`!function(modules) {
}, scale;
}
__webpack_exports__.a = calendar;
- var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(53), __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__ = __webpack_require__(114), __WEBPACK_IMPORTED_MODULE_2_d3_time__ = __webpack_require__(256), __WEBPACK_IMPORTED_MODULE_3_d3_time_format__ = __webpack_require__(438), __WEBPACK_IMPORTED_MODULE_4__array__ = __webpack_require__(73), __WEBPACK_IMPORTED_MODULE_5__continuous__ = __webpack_require__(168), __WEBPACK_IMPORTED_MODULE_6__nice__ = __webpack_require__(436), durationSecond = 1e3, durationMinute = 60 * durationSecond, durationHour = 60 * durationMinute, durationDay = 24 * durationHour, durationWeek = 7 * durationDay, durationMonth = 30 * durationDay, durationYear = 365 * durationDay;
+ var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(37), __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__ = __webpack_require__(88), __WEBPACK_IMPORTED_MODULE_2_d3_time__ = __webpack_require__(193), __WEBPACK_IMPORTED_MODULE_3_d3_time_format__ = __webpack_require__(317), __WEBPACK_IMPORTED_MODULE_4__array__ = __webpack_require__(56), __WEBPACK_IMPORTED_MODULE_5__continuous__ = __webpack_require__(126), __WEBPACK_IMPORTED_MODULE_6__nice__ = __webpack_require__(315), durationSecond = 1e3, durationMinute = 60 * durationSecond, durationHour = 60 * durationMinute, durationDay = 24 * durationHour, durationWeek = 7 * durationDay, durationMonth = 30 * durationDay, durationYear = 365 * durationDay;
__webpack_exports__.b = function() {
return calendar(__WEBPACK_IMPORTED_MODULE_2_d3_time__.k, __WEBPACK_IMPORTED_MODULE_2_d3_time__.f, __WEBPACK_IMPORTED_MODULE_2_d3_time__.j, __WEBPACK_IMPORTED_MODULE_2_d3_time__.a, __WEBPACK_IMPORTED_MODULE_2_d3_time__.b, __WEBPACK_IMPORTED_MODULE_2_d3_time__.d, __WEBPACK_IMPORTED_MODULE_2_d3_time__.g, __WEBPACK_IMPORTED_MODULE_2_d3_time__.c, __WEBPACK_IMPORTED_MODULE_3_d3_time_format__.a).domain([ new Date(2e3, 0, 1), new Date(2e3, 0, 2) ]);
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__ = __webpack_require__(257);
+ var __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__ = __webpack_require__(194);
__webpack_require__.d(__webpack_exports__, "a", function() {
return __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__.a;
}), __webpack_require__.d(__webpack_exports__, "b", function() {
return __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__.b;
});
- __webpack_require__(439), __webpack_require__(440), __webpack_require__(1079);
+ __webpack_require__(318), __webpack_require__(319), __webpack_require__(771);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
function localDate(d) {
@@ -13617,7 +12161,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return Math.floor(+d / 1e3);
}
__webpack_exports__.a = formatLocale;
- var __WEBPACK_IMPORTED_MODULE_0_d3_time__ = __webpack_require__(256), pads = {
+ var __WEBPACK_IMPORTED_MODULE_0_d3_time__ = __webpack_require__(193), pads = {
"-": "",
_: " ",
"0": "0"
@@ -13630,7 +12174,7 @@ var _publicBundleJs = []byte(`!function(modules) {
__webpack_require__.d(__webpack_exports__, "a", function() {
return isoSpecifier;
});
- var __WEBPACK_IMPORTED_MODULE_0__defaultLocale__ = __webpack_require__(257), isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ";
+ var __WEBPACK_IMPORTED_MODULE_0__defaultLocale__ = __webpack_require__(194), isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ";
Date.prototype.toISOString || Object(__WEBPACK_IMPORTED_MODULE_0__defaultLocale__.b)(isoSpecifier);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -13652,7 +12196,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_3_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_classnames__), __WEBPACK_IMPORTED_MODULE_4__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_5__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_6__shape_Dot__ = __webpack_require__(74), __WEBPACK_IMPORTED_MODULE_7__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_8__component_Label__ = __webpack_require__(60), __WEBPACK_IMPORTED_MODULE_9__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_10__util_ChartUtils__ = __webpack_require__(21), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_3_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_classnames__), __WEBPACK_IMPORTED_MODULE_4__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_5__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_6__shape_Dot__ = __webpack_require__(57), __WEBPACK_IMPORTED_MODULE_7__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_8__component_Label__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_9__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_10__util_ChartUtils__ = __webpack_require__(16), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -13759,7 +12303,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_3_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_classnames__), __WEBPACK_IMPORTED_MODULE_4__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_5__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_6__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_7__component_Label__ = __webpack_require__(60), __WEBPACK_IMPORTED_MODULE_8__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_9__util_ChartUtils__ = __webpack_require__(21), _slicedToArray = function() {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_3_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_classnames__), __WEBPACK_IMPORTED_MODULE_4__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_5__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_6__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_7__component_Label__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_8__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_9__util_ChartUtils__ = __webpack_require__(16), _slicedToArray = function() {
function sliceIterator(arr, i) {
var _arr = [], _n = !0, _d = !1, _e = void 0;
try {
@@ -13916,7 +12460,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_3_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_classnames__), __WEBPACK_IMPORTED_MODULE_4__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_5__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_6__component_Label__ = __webpack_require__(60), __WEBPACK_IMPORTED_MODULE_7__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_8__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_9__util_ChartUtils__ = __webpack_require__(21), __WEBPACK_IMPORTED_MODULE_10__shape_Rectangle__ = __webpack_require__(85), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_3_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_classnames__), __WEBPACK_IMPORTED_MODULE_4__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_5__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_6__component_Label__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_7__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_8__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_9__util_ChartUtils__ = __webpack_require__(16), __WEBPACK_IMPORTED_MODULE_10__shape_Rectangle__ = __webpack_require__(65), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -14023,7 +12567,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_4__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_5__util_ReactUtils__ = __webpack_require__(7), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_4__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_5__util_ReactUtils__ = __webpack_require__(4), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -14082,7 +12626,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function maxBy(array, iteratee) {
return array && array.length ? baseExtremum(array, baseIteratee(iteratee, 2), baseGt) : void 0;
}
- var baseExtremum = __webpack_require__(166), baseGt = __webpack_require__(404), baseIteratee = __webpack_require__(110);
+ var baseExtremum = __webpack_require__(124), baseGt = __webpack_require__(283), baseIteratee = __webpack_require__(84);
module.exports = maxBy;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -14104,7 +12648,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__ = __webpack_require__(49), __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_1_lodash_isPlainObject__ = __webpack_require__(394), __WEBPACK_IMPORTED_MODULE_1_lodash_isPlainObject___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isPlainObject__), __WEBPACK_IMPORTED_MODULE_2_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_2_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_3_lodash_isNil__ = __webpack_require__(28), __WEBPACK_IMPORTED_MODULE_3_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_4_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_4_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react__), __WEBPACK_IMPORTED_MODULE_5_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_5_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_prop_types__), __WEBPACK_IMPORTED_MODULE_6_react_smooth__ = __webpack_require__(48), __WEBPACK_IMPORTED_MODULE_6_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_react_smooth__), __WEBPACK_IMPORTED_MODULE_7_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_7_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_classnames__), __WEBPACK_IMPORTED_MODULE_8__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_9__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_10__shape_Sector__ = __webpack_require__(170), __WEBPACK_IMPORTED_MODULE_11__shape_Curve__ = __webpack_require__(86), __WEBPACK_IMPORTED_MODULE_12__component_Text__ = __webpack_require__(72), __WEBPACK_IMPORTED_MODULE_13__component_Label__ = __webpack_require__(60), __WEBPACK_IMPORTED_MODULE_14__component_LabelList__ = __webpack_require__(62), __WEBPACK_IMPORTED_MODULE_15__component_Cell__ = __webpack_require__(111), __WEBPACK_IMPORTED_MODULE_16__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_17__util_PolarUtils__ = __webpack_require__(35), __WEBPACK_IMPORTED_MODULE_18__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_19__util_ChartUtils__ = __webpack_require__(21), __WEBPACK_IMPORTED_MODULE_20__util_LogUtils__ = __webpack_require__(401), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__ = __webpack_require__(34), __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_1_lodash_isPlainObject__ = __webpack_require__(274), __WEBPACK_IMPORTED_MODULE_1_lodash_isPlainObject___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isPlainObject__), __WEBPACK_IMPORTED_MODULE_2_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_2_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_3_lodash_isNil__ = __webpack_require__(20), __WEBPACK_IMPORTED_MODULE_3_lodash_isNil___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_isNil__), __WEBPACK_IMPORTED_MODULE_4_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_4_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react__), __WEBPACK_IMPORTED_MODULE_5_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_5_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_prop_types__), __WEBPACK_IMPORTED_MODULE_6_react_smooth__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_6_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_react_smooth__), __WEBPACK_IMPORTED_MODULE_7_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_7_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_classnames__), __WEBPACK_IMPORTED_MODULE_8__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_9__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_10__shape_Sector__ = __webpack_require__(128), __WEBPACK_IMPORTED_MODULE_11__shape_Curve__ = __webpack_require__(66), __WEBPACK_IMPORTED_MODULE_12__component_Text__ = __webpack_require__(55), __WEBPACK_IMPORTED_MODULE_13__component_Label__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_14__component_LabelList__ = __webpack_require__(45), __WEBPACK_IMPORTED_MODULE_15__component_Cell__ = __webpack_require__(85), __WEBPACK_IMPORTED_MODULE_16__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_17__util_PolarUtils__ = __webpack_require__(23), __WEBPACK_IMPORTED_MODULE_18__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_19__util_ChartUtils__ = __webpack_require__(16), __WEBPACK_IMPORTED_MODULE_20__util_LogUtils__ = __webpack_require__(280), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -14422,7 +12966,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__ = __webpack_require__(49), __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_2_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_react__), __WEBPACK_IMPORTED_MODULE_3_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_3_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_prop_types__), __WEBPACK_IMPORTED_MODULE_4_react_smooth__ = __webpack_require__(48), __WEBPACK_IMPORTED_MODULE_4_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react_smooth__), __WEBPACK_IMPORTED_MODULE_5_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_5_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_classnames__), __WEBPACK_IMPORTED_MODULE_6__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_7__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_8__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_9__util_PolarUtils__ = __webpack_require__(35), __WEBPACK_IMPORTED_MODULE_10__util_ChartUtils__ = __webpack_require__(21), __WEBPACK_IMPORTED_MODULE_11__shape_Polygon__ = __webpack_require__(258), __WEBPACK_IMPORTED_MODULE_12__shape_Dot__ = __webpack_require__(74), __WEBPACK_IMPORTED_MODULE_13__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_14__component_LabelList__ = __webpack_require__(62), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__ = __webpack_require__(34), __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_react__), __WEBPACK_IMPORTED_MODULE_3_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_3_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_prop_types__), __WEBPACK_IMPORTED_MODULE_4_react_smooth__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_4_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react_smooth__), __WEBPACK_IMPORTED_MODULE_5_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_5_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_classnames__), __WEBPACK_IMPORTED_MODULE_6__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_7__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_8__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_9__util_PolarUtils__ = __webpack_require__(23), __WEBPACK_IMPORTED_MODULE_10__util_ChartUtils__ = __webpack_require__(16), __WEBPACK_IMPORTED_MODULE_11__shape_Polygon__ = __webpack_require__(195), __WEBPACK_IMPORTED_MODULE_12__shape_Dot__ = __webpack_require__(57), __WEBPACK_IMPORTED_MODULE_13__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_14__component_LabelList__ = __webpack_require__(45), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -14656,7 +13200,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__ = __webpack_require__(49), __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_lodash_isArray__ = __webpack_require__(16), __WEBPACK_IMPORTED_MODULE_2_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_3_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_3_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_react__), __WEBPACK_IMPORTED_MODULE_4_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_4_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_prop_types__), __WEBPACK_IMPORTED_MODULE_5_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_5_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_classnames__), __WEBPACK_IMPORTED_MODULE_6_react_smooth__ = __webpack_require__(48), __WEBPACK_IMPORTED_MODULE_6_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_react_smooth__), __WEBPACK_IMPORTED_MODULE_7__shape_Sector__ = __webpack_require__(170), __WEBPACK_IMPORTED_MODULE_8__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_9__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_10__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_11__component_LabelList__ = __webpack_require__(62), __WEBPACK_IMPORTED_MODULE_12__component_Cell__ = __webpack_require__(111), __WEBPACK_IMPORTED_MODULE_13__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_14__util_ChartUtils__ = __webpack_require__(21), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__ = __webpack_require__(34), __WEBPACK_IMPORTED_MODULE_0_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isEqual__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_lodash_isArray__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_2_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_3_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_3_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_react__), __WEBPACK_IMPORTED_MODULE_4_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_4_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_prop_types__), __WEBPACK_IMPORTED_MODULE_5_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_5_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_classnames__), __WEBPACK_IMPORTED_MODULE_6_react_smooth__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_6_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_react_smooth__), __WEBPACK_IMPORTED_MODULE_7__shape_Sector__ = __webpack_require__(128), __WEBPACK_IMPORTED_MODULE_8__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_9__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_10__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_11__component_LabelList__ = __webpack_require__(45), __WEBPACK_IMPORTED_MODULE_12__component_Cell__ = __webpack_require__(85), __WEBPACK_IMPORTED_MODULE_13__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_14__util_ChartUtils__ = __webpack_require__(16), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -14940,7 +13484,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_range__ = __webpack_require__(450), __WEBPACK_IMPORTED_MODULE_0_lodash_range___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_range__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_2_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_react__), __WEBPACK_IMPORTED_MODULE_3_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_3_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_prop_types__), __WEBPACK_IMPORTED_MODULE_4_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_4_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_classnames__), __WEBPACK_IMPORTED_MODULE_5_d3_scale__ = __webpack_require__(408), __WEBPACK_IMPORTED_MODULE_6__util_ChartUtils__ = __webpack_require__(21), __WEBPACK_IMPORTED_MODULE_7__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_8__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_9__component_Text__ = __webpack_require__(72), __WEBPACK_IMPORTED_MODULE_10__util_DataUtils__ = __webpack_require__(12), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_range__ = __webpack_require__(329), __WEBPACK_IMPORTED_MODULE_0_lodash_range___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_range__), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_1_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_2_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_react__), __WEBPACK_IMPORTED_MODULE_3_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_3_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_prop_types__), __WEBPACK_IMPORTED_MODULE_4_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_4_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_classnames__), __WEBPACK_IMPORTED_MODULE_5_d3_scale__ = __webpack_require__(287), __WEBPACK_IMPORTED_MODULE_6__util_ChartUtils__ = __webpack_require__(16), __WEBPACK_IMPORTED_MODULE_7__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_8__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_9__component_Text__ = __webpack_require__(55), __WEBPACK_IMPORTED_MODULE_10__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_11__util_CssPrefixUtils__ = __webpack_require__(787), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -15204,14 +13748,15 @@ var _publicBundleJs = []byte(`!function(modules) {
value: function() {
var _props10 = this.props, data = _props10.data, className = _props10.className, children = _props10.children, x = _props10.x, y = _props10.y, width = _props10.width, height = _props10.height, _state4 = this.state, startX = _state4.startX, endX = _state4.endX, isTextActive = _state4.isTextActive, isSlideMoving = _state4.isSlideMoving, isTravellerMoving = _state4.isTravellerMoving;
if (!data || !data.length || !Object(__WEBPACK_IMPORTED_MODULE_10__util_DataUtils__.g)(x) || !Object(__WEBPACK_IMPORTED_MODULE_10__util_DataUtils__.g)(y) || !Object(__WEBPACK_IMPORTED_MODULE_10__util_DataUtils__.g)(width) || !Object(__WEBPACK_IMPORTED_MODULE_10__util_DataUtils__.g)(height) || width <= 0 || height <= 0) return null;
- var layerClass = __WEBPACK_IMPORTED_MODULE_4_classnames___default()("recharts-brush", className), isPanoramic = 1 === __WEBPACK_IMPORTED_MODULE_2_react___default.a.Children.count(children);
+ var layerClass = __WEBPACK_IMPORTED_MODULE_4_classnames___default()("recharts-brush", className), isPanoramic = 1 === __WEBPACK_IMPORTED_MODULE_2_react___default.a.Children.count(children), style = Object(__WEBPACK_IMPORTED_MODULE_11__util_CssPrefixUtils__.a)("userSelect", "none");
return __WEBPACK_IMPORTED_MODULE_2_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_8__container_Layer__.a, {
className: layerClass,
onMouseMove: this.handleDrag,
onMouseLeave: this.handleLeaveWrapper,
onMouseUp: this.handleDragEnd,
onTouchEnd: this.handleDragEnd,
- onTouchMove: this.handleTouchMove
+ onTouchMove: this.handleTouchMove,
+ style: style
}, this.renderBackground(), isPanoramic && this.renderPanorama(), this.renderSlide(startX, endX), this.renderTraveller(startX, "startX"), this.renderTraveller(endX, "endX"), (isTextActive || isSlideMoving || isTravellerMoving) && this.renderText());
}
} ]), Brush;
@@ -15253,7 +13798,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, _class = _temp)) || _class;
__webpack_exports__.a = Brush;
}, function(module, exports, __webpack_require__) {
- var createRange = __webpack_require__(1092), range = createRange();
+ var createRange = __webpack_require__(784), range = createRange();
module.exports = range;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -15280,7 +13825,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_3_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_classnames__), __WEBPACK_IMPORTED_MODULE_4__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_5__util_DOMUtils__ = __webpack_require__(247), __WEBPACK_IMPORTED_MODULE_6__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_7__component_Text__ = __webpack_require__(72), __WEBPACK_IMPORTED_MODULE_8__component_Label__ = __webpack_require__(60), __WEBPACK_IMPORTED_MODULE_9__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_10__util_DataUtils__ = __webpack_require__(12), _extends = Object.assign || function(target) {
+ var _class, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_3_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_classnames__), __WEBPACK_IMPORTED_MODULE_4__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_5__util_DOMUtils__ = __webpack_require__(184), __WEBPACK_IMPORTED_MODULE_6__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_7__component_Text__ = __webpack_require__(55), __WEBPACK_IMPORTED_MODULE_8__component_Label__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_9__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_10__util_DataUtils__ = __webpack_require__(9), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -15432,7 +13977,8 @@ var _publicBundleJs = []byte(`!function(modules) {
fill: stroke
}, customTickProps, tickCoord, {
index: i,
- payload: entry
+ payload: entry,
+ visibleTicksCount: finalTicks.length
});
return __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement(__WEBPACK_IMPORTED_MODULE_6__container_Layer__.a, _extends({
className: "recharts-cartesian-axis-tick",
@@ -15602,67 +14148,12 @@ var _publicBundleJs = []byte(`!function(modules) {
__webpack_exports__.a = CartesianAxis;
}, function(module, exports, __webpack_require__) {
"use strict";
- (function(process) {
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
- };
- }
- function HiddenJs(props) {
- var children = props.children, only = (props.lgDown, props.lgUp, props.mdDown, props.mdUp,
- props.only), width = (props.smDown, props.smUp, props.width), other = (props.xlDown,
- props.xlUp, props.xsDown, props.xsUp, (0, _objectWithoutProperties3.default)(props, [ "children", "lgDown", "lgUp", "mdDown", "mdUp", "only", "smDown", "smUp", "width", "xlDown", "xlUp", "xsDown", "xsUp" ]));
- "production" !== process.env.NODE_ENV && (0, _warning2.default)(0 === (0, _keys2.default)(other).length, "Material-UI: unsupported properties received " + (0,
- _stringify2.default)(other) + " by ` + "`" + `<Hidden />` + "`" + `.");
- var visible = !0;
- if (only) if (Array.isArray(only)) for (var i = 0; i < only.length; i += 1) {
- var breakpoint = only[i];
- if (width === breakpoint) {
- visible = !1;
- break;
- }
- } else only && width === only && (visible = !1);
- if (visible) for (var _i = 0; _i < _createBreakpoints.keys.length; _i += 1) {
- var _breakpoint = _createBreakpoints.keys[_i], breakpointUp = props[_breakpoint + "Up"], breakpointDown = props[_breakpoint + "Down"];
- if (breakpointUp && (0, _withWidth.isWidthUp)(_breakpoint, width) || breakpointDown && (0,
- _withWidth.isWidthDown)(_breakpoint, width)) {
- visible = !1;
- break;
- }
- }
- return visible ? children : null;
- }
- Object.defineProperty(exports, "__esModule", {
- value: !0
- });
- var _stringify = __webpack_require__(1117), _stringify2 = _interopRequireDefault(_stringify), _keys = __webpack_require__(51), _keys2 = _interopRequireDefault(_keys), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), _createBreakpoints = __webpack_require__(94), _withWidth = __webpack_require__(1119), _withWidth2 = _interopRequireDefault(_withWidth);
- HiddenJs.propTypes = {
- children: _propTypes2.default.node,
- className: _propTypes2.default.string,
- implementation: _propTypes2.default.oneOf([ "js", "css" ]),
- initialWidth: _propTypes2.default.number,
- lgDown: _propTypes2.default.bool,
- lgUp: _propTypes2.default.bool,
- mdDown: _propTypes2.default.bool,
- mdUp: _propTypes2.default.bool,
- only: _propTypes2.default.oneOfType([ _propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ]), _propTypes2.default.arrayOf(_propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ])) ]),
- smDown: _propTypes2.default.bool,
- smUp: _propTypes2.default.bool,
- width: _propTypes2.default.string.isRequired,
- xlDown: _propTypes2.default.bool,
- xlUp: _propTypes2.default.bool,
- xsDown: _propTypes2.default.bool,
- xsUp: _propTypes2.default.bool
- }, exports.default = (0, _withWidth2.default)()(HiddenJs);
- }).call(exports, __webpack_require__(3));
-}, function(module, exports, __webpack_require__) {
- "use strict";
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
- var _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _reactDom = __webpack_require__(121), _MuiThemeProvider = __webpack_require__(464), _MuiThemeProvider2 = _interopRequireDefault(_MuiThemeProvider), _createMuiTheme = __webpack_require__(193), _createMuiTheme2 = _interopRequireDefault(_createMuiTheme), _Dashboard = __webpack_require__(518), _Dashboard2 = _interopRequireDefault(_Dashboard), theme = (0,
+ var _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _reactDom = __webpack_require__(95), _MuiThemeProvider = __webpack_require__(342), _MuiThemeProvider2 = _interopRequireDefault(_MuiThemeProvider), _createMuiTheme = __webpack_require__(151), _createMuiTheme2 = _interopRequireDefault(_createMuiTheme), _Dashboard = __webpack_require__(396), _Dashboard2 = _interopRequireDefault(_Dashboard), theme = (0,
_createMuiTheme2.default)({
palette: {
type: "dark"
@@ -15789,7 +14280,7 @@ var _publicBundleJs = []byte(`!function(modules) {
null != e && (g = ("" + e).replace(L, "$&/") + "/"), b = N(b, g, c, d), null == a || P(a, "", S, b),
O(b);
}
- var m = __webpack_require__(89), n = __webpack_require__(119), p = __webpack_require__(55), q = "function" == typeof Symbol && Symbol.for, r = q ? Symbol.for("react.element") : 60103, t = q ? Symbol.for("react.call") : 60104, u = q ? Symbol.for("react.return") : 60105, v = q ? Symbol.for("react.portal") : 60106, w = q ? Symbol.for("react.fragment") : 60107, x = "function" == typeof Symbol && Symbol.iterator, z = {
+ var m = __webpack_require__(69), n = __webpack_require__(93), p = __webpack_require__(39), q = "function" == typeof Symbol && Symbol.for, r = q ? Symbol.for("react.element") : 60103, t = q ? Symbol.for("react.call") : 60104, u = q ? Symbol.for("react.return") : 60105, v = q ? Symbol.for("react.portal") : 60106, w = q ? Symbol.for("react.fragment") : 60107, x = "function" == typeof Symbol && Symbol.iterator, z = {
isMounted: function() {
return !1;
},
@@ -15918,7 +14409,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
function defineKeyPropWarningGetter(props, displayName) {
var warnAboutAccessingKey = function() {
- specialPropKeyWarningShown || (specialPropKeyWarningShown = !0, warning(!1, "%s: ` + "`" + `key` + "`" + ` is not a prop. Trying to access it will result in ` + "`" + `undefined` + "`" + ` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://fb.me/react-special-props)", displayName));
+ specialPropKeyWarningShown || (specialPropKeyWarningShown = !0, warning(!1, "%s: ` + "`")) + (`key` + ("`" + ` is not a prop. Trying to access it will result in `)))))) + ((((("`" + `undefined`) + ("`" + (` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://fb.me/react-special-props)", displayName));
};
warnAboutAccessingKey.isReactWarning = !0, Object.defineProperty(props, "key", {
get: warnAboutAccessingKey,
@@ -15927,7 +14418,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
function defineRefPropWarningGetter(props, displayName) {
var warnAboutAccessingRef = function() {
- specialPropRefWarningShown || (specialPropRefWarningShown = !0, warning(!1, "%s: ` + "`" + `ref` + "`" + ` is not a prop. Trying to access it will result in ` + "`" + `undefined` + "`" + ` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://fb.me/react-special-props)", displayName));
+ specialPropRefWarningShown || (specialPropRefWarningShown = !0, warning(!1, "%s: ` + "`"))) + ((`ref` + ("`" + ` is not a prop. Trying to access it will result in `)) + ("`" + (`undefined` + "`")))) + (((` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://fb.me/react-special-props)", displayName));
};
warnAboutAccessingRef.isReactWarning = !0, Object.defineProperty(props, "ref", {
get: warnAboutAccessingRef,
@@ -16097,7 +14588,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function getDeclarationErrorAddendum() {
if (ReactCurrentOwner.current) {
var name = getComponentName(ReactCurrentOwner.current);
- if (name) return "\n\nCheck the render method of ` + "`" + `" + name + "` + "`" + `.";
+ if (name) return "\n\nCheck the render method of ` + ("`" + `" + name + "`)) + ("`" + (`.";
}
return "";
}
@@ -16144,8 +14635,8 @@ var _publicBundleJs = []byte(`!function(modules) {
var name = componentClass.displayName || componentClass.name, propTypes = componentClass.propTypes;
propTypes ? (currentlyValidatingElement = element, checkPropTypes(propTypes, element.props, "prop", name, getStackAddendum),
currentlyValidatingElement = null) : void 0 === componentClass.PropTypes || propTypesMisspellWarningShown || (propTypesMisspellWarningShown = !0,
- warning(!1, "Component %s declared ` + "`" + `PropTypes` + "`" + ` instead of ` + "`" + `propTypes` + "`" + `. Did you misspell the property assignment?", name || "Unknown")),
- "function" == typeof componentClass.getDefaultProps && warning(componentClass.getDefaultProps.isReactClassApproved, "getDefaultProps is only used on classic React.createClass definitions. Use a static property named ` + "`" + `defaultProps` + "`" + ` instead.");
+ warning(!1, "Component %s declared ` + "`"))) + ((`PropTypes` + ("`" + ` instead of `)) + ("`" + (`propTypes` + "`"))))) + ((((`. Did you misspell the property assignment?", name || "Unknown")),
+ "function" == typeof componentClass.getDefaultProps && warning(componentClass.getDefaultProps.isReactClassApproved, "getDefaultProps is only used on classic React.createClass definitions. Use a static property named ` + ("`" + `defaultProps`)) + ("`" + (` instead.");
}
}
function validateFragmentProps(fragment) {
@@ -16155,7 +14646,7 @@ var _publicBundleJs = []byte(`!function(modules) {
for (var _step, _iterator = Object.keys(fragment.props)[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = !0) {
var key = _step.value;
if (!VALID_FRAGMENT_PROPS.has(key)) {
- warning(!1, "Invalid prop ` + "`" + `%s` + "`" + ` supplied to ` + "`" + `React.Fragment` + "`" + `. React.Fragment can only have ` + "`" + `key` + "`" + ` and ` + "`" + `children` + "`" + ` props.%s", key, getStackAddendum());
+ warning(!1, "Invalid prop ` + "`"))) + ((`%s` + ("`" + ` supplied to `)) + ("`" + (`React.Fragment` + "`")))) + (((`. React.Fragment can only have ` + ("`" + `key`)) + ("`" + (` and ` + "`"))) + ((`children` + ("`" + ` props.%s", key, getStackAddendum());
break;
}
}
@@ -16168,7 +14659,7 @@ var _publicBundleJs = []byte(`!function(modules) {
if (_didIteratorError) throw _iteratorError;
}
}
- null !== fragment.ref && warning(!1, "Invalid attribute ` + "`" + `ref` + "`" + ` supplied to ` + "`" + `React.Fragment` + "`" + `.%s", getStackAddendum()),
+ null !== fragment.ref && warning(!1, "Invalid attribute `)) + ("`" + (`ref` + "`"))))))) + ((((((` supplied to ` + "`") + (`React.Fragment` + ("`" + `.%s", getStackAddendum()),
currentlyValidatingElement = null;
}
function createElementWithValidation(type, props, children) {
@@ -16202,7 +14693,7 @@ var _publicBundleJs = []byte(`!function(modules) {
for (var newElement = cloneElement.apply(this, arguments), i = 2; i < arguments.length; i++) validateChildKeys(arguments[i], newElement.type);
return validatePropTypes(newElement), newElement;
}
- var _assign = __webpack_require__(89), emptyObject = __webpack_require__(119), invariant = __webpack_require__(90), warning = __webpack_require__(120), emptyFunction = __webpack_require__(55), checkPropTypes = __webpack_require__(174), hasSymbol = "function" == typeof Symbol && Symbol.for, REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for("react.element") : 60103, REACT_CALL_TYPE = hasSymbol ? Symbol.for("react.call") : 60104, REACT_RETURN_TYPE = hasSymbol ? Symbol.for("react.return") : 60105, REACT_PORTAL_TYPE = hasSymbol ? Symbol.for("react.portal") : 60106, REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for("react.fragment") : 60107, MAYBE_ITERATOR_SYMBOL = "function" == typeof Symbol && Symbol.iterator, FAUX_ITERATOR_SYMBOL = "@@iterator", lowPriorityWarning = function() {}, printWarning = function(format) {
+ var _assign = __webpack_require__(69), emptyObject = __webpack_require__(93), invariant = __webpack_require__(70), warning = __webpack_require__(94), emptyFunction = __webpack_require__(39), checkPropTypes = __webpack_require__(132), hasSymbol = "function" == typeof Symbol && Symbol.for, REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for("react.element") : 60103, REACT_CALL_TYPE = hasSymbol ? Symbol.for("react.call") : 60104, REACT_RETURN_TYPE = hasSymbol ? Symbol.for("react.return") : 60105, REACT_PORTAL_TYPE = hasSymbol ? Symbol.for("react.portal") : 60106, REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for("react.fragment") : 60107, MAYBE_ITERATOR_SYMBOL = "function" == typeof Symbol && Symbol.iterator, FAUX_ITERATOR_SYMBOL = "@@iterator", lowPriorityWarning = function() {}, printWarning = function(format) {
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) args[_key - 1] = arguments[_key];
var argIndex = 0, message = "Warning: " + format.replace(/%s/g, function() {
return args[argIndex++];
@@ -16213,7 +14704,7 @@ var _publicBundleJs = []byte(`!function(modules) {
} catch (x) {}
};
lowPriorityWarning = function(condition, format) {
- if (void 0 === format) throw new Error("` + "`" + `warning(condition, format, ...args)` + "`" + ` requires a warning message argument");
+ if (void 0 === format) throw new Error("`))) + (("`" + (`warning(condition, format, ...args)` + "`")) + (` requires a warning message argument");
if (!condition) {
for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) args[_key2 - 2] = arguments[_key2];
printWarning.apply(void 0, [ format ].concat(args));
@@ -16338,7 +14829,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), React$3 = React$2 && React || React$2, react = React$3.default ? React$3.default : React$3;
module.exports = react;
}();
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
function E(a) {
@@ -19014,7 +17505,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function Rg(a, b) {
this._reactRootContainer = Z.createContainer(a, b);
}
- var aa = __webpack_require__(1), l = __webpack_require__(263), B = __webpack_require__(89), C = __webpack_require__(55), ba = __webpack_require__(264), da = __webpack_require__(265), ea = __webpack_require__(122), fa = __webpack_require__(266), ia = __webpack_require__(267), D = __webpack_require__(119);
+ var aa = __webpack_require__(0), l = __webpack_require__(200), B = __webpack_require__(69), C = __webpack_require__(39), ba = __webpack_require__(201), da = __webpack_require__(202), ea = __webpack_require__(96), fa = __webpack_require__(203), ia = __webpack_require__(204), D = __webpack_require__(93);
aa || E("227");
var oa = {
children: !0,
@@ -20243,7 +18734,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function isTextNode(object) {
return isNode(object) && 3 == object.nodeType;
}
- var isNode = __webpack_require__(458);
+ var isNode = __webpack_require__(336);
module.exports = isTextNode;
}, function(module, exports, __webpack_require__) {
"use strict";
@@ -20293,17 +18784,17 @@ var _publicBundleJs = []byte(`!function(modules) {
function recomputePluginOrdering() {
if (eventPluginOrder) for (var pluginName in namesToPlugins) {
var pluginModule = namesToPlugins[pluginName], pluginIndex = eventPluginOrder.indexOf(pluginName);
- if (pluginIndex > -1 || invariant(!1, "EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, ` + "`" + `%s` + "`" + `.", pluginName),
+ if (pluginIndex > -1 || invariant(!1, "EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, ` + ("`" + `%s`)))) + ((("`" + (`.", pluginName),
!plugins[pluginIndex]) {
- pluginModule.extractEvents || invariant(!1, "EventPluginRegistry: Event plugins must implement an ` + "`" + `extractEvents` + "`" + ` method, but ` + "`" + `%s` + "`" + ` does not.", pluginName),
+ pluginModule.extractEvents || invariant(!1, "EventPluginRegistry: Event plugins must implement an ` + "`")) + (`extractEvents` + ("`" + ` method, but `))) + (("`" + (`%s` + "`")) + (` does not.", pluginName),
plugins[pluginIndex] = pluginModule;
var publishedEvents = pluginModule.eventTypes;
- for (var eventName in publishedEvents) publishEventForPlugin(publishedEvents[eventName], pluginModule, eventName) || invariant(!1, "EventPluginRegistry: Failed to publish event ` + "`" + `%s` + "`" + ` for plugin ` + "`" + `%s` + "`" + `.", eventName, pluginName);
+ for (var eventName in publishedEvents) publishEventForPlugin(publishedEvents[eventName], pluginModule, eventName) || invariant(!1, "EventPluginRegistry: Failed to publish event ` + ("`" + `%s`))))) + (((("`" + (` for plugin ` + "`")) + (`%s` + ("`" + `.", eventName, pluginName);
}
}
}
function publishEventForPlugin(dispatchConfig, pluginModule, eventName) {
- eventNameDispatchConfigs.hasOwnProperty(eventName) && invariant(!1, "EventPluginHub: More than one plugin attempted to publish the same event name, ` + "`" + `%s` + "`" + `.", eventName),
+ eventNameDispatchConfigs.hasOwnProperty(eventName) && invariant(!1, "EventPluginHub: More than one plugin attempted to publish the same event name, `))) + (("`" + (`%s` + "`")) + (`.", eventName),
eventNameDispatchConfigs[eventName] = dispatchConfig;
var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;
if (phasedRegistrationNames) {
@@ -20317,7 +18808,7 @@ var _publicBundleJs = []byte(`!function(modules) {
!0);
}
function publishRegistrationName(registrationName, pluginModule, eventName) {
- registrationNameModules[registrationName] && invariant(!1, "EventPluginHub: More than one plugin attempted to publish the same registration name, ` + "`" + `%s` + "`" + `.", registrationName),
+ registrationNameModules[registrationName] && invariant(!1, "EventPluginHub: More than one plugin attempted to publish the same registration name, ` + ("`" + `%s`)))) + ((("`" + (`.", registrationName),
registrationNameModules[registrationName] = pluginModule, registrationNameDependencies[registrationName] = pluginModule.eventTypes[eventName].dependencies;
var lowerCasedName = registrationName.toLowerCase();
possibleRegistrationNames[lowerCasedName] = registrationName, "onDoubleClick" === registrationName && (possibleRegistrationNames.ondblclick = registrationName);
@@ -20330,7 +18821,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var isOrderingDirty = !1;
for (var pluginName in injectedNamesToPlugins) if (injectedNamesToPlugins.hasOwnProperty(pluginName)) {
var pluginModule = injectedNamesToPlugins[pluginName];
- namesToPlugins.hasOwnProperty(pluginName) && namesToPlugins[pluginName] === pluginModule || (namesToPlugins[pluginName] && invariant(!1, "EventPluginRegistry: Cannot inject two different event plugins using the same name, ` + "`" + `%s` + "`" + `.", pluginName),
+ namesToPlugins.hasOwnProperty(pluginName) && namesToPlugins[pluginName] === pluginModule || (namesToPlugins[pluginName] && invariant(!1, "EventPluginRegistry: Cannot inject two different event plugins using the same name, ` + "`")) + (`%s` + ("`" + `.", pluginName),
namesToPlugins[pluginName] = pluginModule, isOrderingDirty = !0);
}
isOrderingDirty && recomputePluginOrdering();
@@ -20378,7 +18869,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var listener, stateNode = inst.stateNode;
if (!stateNode) return null;
var props = getFiberCurrentPropsFromNode(stateNode);
- return props ? (listener = props[registrationName], shouldPreventMouseEvent(registrationName, inst.type, props) ? null : (listener && "function" != typeof listener && invariant(!1, "Expected ` + "`" + `%s` + "`" + ` listener to be a function, instead got a value of ` + "`" + `%s` + "`" + ` type.", registrationName, typeof listener),
+ return props ? (listener = props[registrationName], shouldPreventMouseEvent(registrationName, inst.type, props) ? null : (listener && "function" != typeof listener && invariant(!1, "Expected `))) + (("`" + (`%s` + "`")) + (` listener to be a function, instead got a value of ` + ("`" + `%s`)))))) + ((((("`" + (` type.", registrationName, typeof listener),
listener)) : null;
}
function extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
@@ -20558,7 +19049,7 @@ var _publicBundleJs = []byte(`!function(modules) {
getVal;
}
function warn(action, result) {
- warning(!1, "This synthetic event is reused for performance reasons. If you're seeing this, you're %s ` + "`" + `%s` + "`" + ` on a released/nullified synthetic event. %s. If you must keep the original synthetic event around, use event.persist(). See https://fb.me/react-event-pooling for more information.", action, propName, result);
+ warning(!1, "This synthetic event is reused for performance reasons. If you're seeing this, you're %s ` + "`")) + (`%s` + ("`" + ` on a released/nullified synthetic event. %s. If you must keep the original synthetic event around, use event.persist(). See https://fb.me/react-event-pooling for more information.", action, propName, result);
}
var isFunction = "function" == typeof getVal;
return {
@@ -21570,7 +20061,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var info = "";
(void 0 === type || "object" == typeof type && null !== type && 0 === Object.keys(type).length) && (info += " You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.");
var ownerName = owner ? getComponentName(owner) : null;
- ownerName && (info += "\n\nCheck the render method of ` + "`" + `" + ownerName + "` + "`" + `."), invariant(!1, "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s", null == type ? type : typeof type, info);
+ ownerName && (info += "\n\nCheck the render method of `))) + (("`" + (`" + ownerName + "` + "`")) + (`."), invariant(!1, "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s", null == type ? type : typeof type, info);
}
return fiber._debugSource = element._source, fiber._debugOwner = element._owner,
fiber.expirationTime = expirationTime, fiber;
@@ -21971,7 +20462,7 @@ var _publicBundleJs = []byte(`!function(modules) {
knownKeys.add(key);
break;
}
- warning(!1, "Encountered two children with the same key, ` + "`" + `%s` + "`" + `. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.%s", key, getCurrentFiberStackAddendum$1());
+ warning(!1, "Encountered two children with the same key, ` + ("`" + `%s`)))) + ((("`" + (`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.%s", key, getCurrentFiberStackAddendum$1());
}
return knownKeys;
}
@@ -22206,7 +20697,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
function isAttributeNameSafe(attributeName) {
return !!validatedAttributeNameCache.hasOwnProperty(attributeName) || !illegalAttributeNameCache.hasOwnProperty(attributeName) && (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName) ? (validatedAttributeNameCache[attributeName] = !0,
- !0) : (illegalAttributeNameCache[attributeName] = !0, warning(!1, "Invalid attribute name: ` + "`" + `%s` + "`" + `", attributeName),
+ !0) : (illegalAttributeNameCache[attributeName] = !0, warning(!1, "Invalid attribute name: ` + "`")) + (`%s` + ("`" + `", attributeName),
!1));
}
function shouldIgnoreValue(propertyInfo, value) {
@@ -22346,7 +20837,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var otherNode = group[i];
if (otherNode !== rootNode && otherNode.form === rootNode.form) {
var otherProps = getFiberCurrentPropsFromNode$1(otherNode);
- otherProps || invariant(!1, "ReactDOMInput: Mixing React and non-React radio inputs with the same ` + "`" + `name` + "`" + ` is not supported."),
+ otherProps || invariant(!1, "ReactDOMInput: Mixing React and non-React radio inputs with the same `))) + (("`" + (`name` + "`")) + (` is not supported."),
updateValueIfChanged(otherNode), updateWrapper(otherNode, otherProps);
}
}
@@ -22359,7 +20850,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), content;
}
function validateProps(element, props) {
- warning(null == props.selected, "Use the ` + "`" + `defaultValue` + "`" + ` or ` + "`" + `value` + "`" + ` props on <select> instead of setting ` + "`" + `selected` + "`" + ` on <option>.");
+ warning(null == props.selected, "Use the ` + ("`" + `defaultValue`))))) + (((("`" + (` or ` + "`")) + (`value` + ("`" + ` props on <select> instead of setting `))) + (("`" + (`selected` + "`")) + (` on <option>.");
}
function postMountWrapper$1(element, props) {
null != props.value && element.setAttribute("value", props.value);
@@ -22372,7 +20863,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
function getDeclarationErrorAddendum() {
var ownerName = getCurrentFiberOwnerName$3();
- return ownerName ? "\n\nCheck the render method of ` + "`" + `" + ownerName + "` + "`" + `." : "";
+ return ownerName ? "\n\nCheck the render method of ` + ("`" + `" + ownerName + "`)))) + ((("`" + (`." : "";
}
function checkSelectPropTypes(props) {
ReactControlledValuePropTypes.checkPropTypes("select", props, getCurrentFiberStackAddendum$4);
@@ -22380,7 +20871,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var propName = valuePropNames[i];
if (null != props[propName]) {
var isArray = Array.isArray(props[propName]);
- props.multiple && !isArray ? warning(!1, "The ` + "`" + `%s` + "`" + ` prop supplied to <select> must be an array if ` + "`" + `multiple` + "`" + ` is true.%s", propName, getDeclarationErrorAddendum()) : !props.multiple && isArray && warning(!1, "The ` + "`" + `%s` + "`" + ` prop supplied to <select> must be a scalar value if ` + "`" + `multiple` + "`" + ` is false.%s", propName, getDeclarationErrorAddendum());
+ props.multiple && !isArray ? warning(!1, "The ` + "`")) + (`%s` + ("`" + ` prop supplied to <select> must be an array if `))) + (("`" + (`multiple` + "`")) + (` is true.%s", propName, getDeclarationErrorAddendum()) : !props.multiple && isArray && warning(!1, "The ` + ("`" + `%s`)))))))) + ((((((("`" + ` prop supplied to <select> must be a scalar value if `) + ("`" + (`multiple` + "`"))) + ((` is false.%s", propName, getDeclarationErrorAddendum());
}
}
}
@@ -22435,7 +20926,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
function getHostProps$3(element, props) {
var node = element;
- return null != props.dangerouslySetInnerHTML && invariant(!1, "` + "`" + `dangerouslySetInnerHTML` + "`" + ` does not make sense on <textarea>."),
+ return null != props.dangerouslySetInnerHTML && invariant(!1, "` + ("`" + `dangerouslySetInnerHTML`)) + ("`" + (` does not make sense on <textarea>."),
_assign({}, props, {
value: void 0,
defaultValue: void 0,
@@ -22450,8 +20941,8 @@ var _publicBundleJs = []byte(`!function(modules) {
var initialValue = props.value;
if (null == initialValue) {
var defaultValue = props.defaultValue, children = props.children;
- null != children && (warning(!1, "Use the ` + "`" + `defaultValue` + "`" + ` or ` + "`" + `value` + "`" + ` props instead of setting children on <textarea>."),
- null != defaultValue && invariant(!1, "If you supply ` + "`" + `defaultValue` + "`" + ` on a <textarea>, do not pass children."),
+ null != children && (warning(!1, "Use the ` + "`")))) + (((`defaultValue` + ("`" + ` or `)) + ("`" + (`value` + "`"))) + ((` props instead of setting children on <textarea>."),
+ null != defaultValue && invariant(!1, "If you supply ` + ("`" + `defaultValue`)) + ("`" + (` on a <textarea>, do not pass children."),
Array.isArray(children) && (children.length <= 1 || invariant(!1, "<textarea> can only have at most one child."),
children = children[0]), defaultValue = "" + children), null == defaultValue && (defaultValue = ""),
initialValue = defaultValue;
@@ -22518,11 +21009,11 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}
function assertValidProps(tag, props, getStack) {
- props && (voidElementTags[tag] && (null != props.children || null != props.dangerouslySetInnerHTML) && invariant(!1, "%s is a void element tag and must neither have ` + "`" + `children` + "`" + ` nor use ` + "`" + `dangerouslySetInnerHTML` + "`" + `.%s", tag, getStack()),
- null != props.dangerouslySetInnerHTML && (null != props.children && invariant(!1, "Can only set one of ` + "`" + `children` + "`" + ` or ` + "`" + `props.dangerouslySetInnerHTML` + "`" + `."),
- "object" == typeof props.dangerouslySetInnerHTML && HTML$1 in props.dangerouslySetInnerHTML || invariant(!1, "` + "`" + `props.dangerouslySetInnerHTML` + "`" + ` must be in the form ` + "`" + `{__html: ...}` + "`" + `. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information.")),
- warning(props.suppressContentEditableWarning || !props.contentEditable || null == props.children, "A component is ` + "`" + `contentEditable` + "`" + ` and contains ` + "`" + `children` + "`" + ` managed by React. It is now your responsibility to guarantee that none of those nodes are unexpectedly modified or duplicated. This is probably not intentional.%s", getStack()),
- null != props.style && "object" != typeof props.style && invariant(!1, "The ` + "`" + `style` + "`" + ` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + 'em'}} when using JSX.%s", getStack()));
+ props && (voidElementTags[tag] && (null != props.children || null != props.dangerouslySetInnerHTML) && invariant(!1, "%s is a void element tag and must neither have ` + "`"))))) + ((((`children` + ("`" + ` nor use `)) + ("`" + (`dangerouslySetInnerHTML` + "`"))) + ((`.%s", tag, getStack()),
+ null != props.dangerouslySetInnerHTML && (null != props.children && invariant(!1, "Can only set one of ` + ("`" + `children`)) + ("`" + (` or ` + "`")))) + (((`props.dangerouslySetInnerHTML` + ("`" + `."),
+ "object" == typeof props.dangerouslySetInnerHTML && HTML$1 in props.dangerouslySetInnerHTML || invariant(!1, "`)) + ("`" + (`props.dangerouslySetInnerHTML` + "`"))) + ((` must be in the form ` + ("`" + `{__html: ...}`)) + ("`" + (`. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information.")),
+ warning(props.suppressContentEditableWarning || !props.contentEditable || null == props.children, "A component is ` + "`")))))) + (((((`contentEditable` + ("`" + ` and contains `)) + ("`" + (`children` + "`"))) + ((` managed by React. It is now your responsibility to guarantee that none of those nodes are unexpectedly modified or duplicated. This is probably not intentional.%s", getStack()),
+ null != props.style && "object" != typeof props.style && invariant(!1, "The ` + ("`" + `style`)) + ("`" + (` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + 'em'}} when using JSX.%s", getStack()));
}
function isCustomComponent(tagName, props) {
if (-1 === tagName.indexOf("-")) return "string" == typeof props.is;
@@ -22549,15 +21040,15 @@ var _publicBundleJs = []byte(`!function(modules) {
if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) return !0;
if (rARIACamel.test(name)) {
var ariaName = "aria-" + name.slice(4).toLowerCase(), correctName = ariaProperties.hasOwnProperty(ariaName) ? ariaName : null;
- if (null == correctName) return warning(!1, "Invalid ARIA attribute ` + "`" + `%s` + "`" + `. ARIA attributes follow the pattern aria-* and must be lowercase.%s", name, getStackAddendum()),
+ if (null == correctName) return warning(!1, "Invalid ARIA attribute ` + "`")))) + (((`%s` + ("`" + `. ARIA attributes follow the pattern aria-* and must be lowercase.%s", name, getStackAddendum()),
warnedProperties[name] = !0, !0;
- if (name !== correctName) return warning(!1, "Invalid ARIA attribute ` + "`" + `%s` + "`" + `. Did you mean ` + "`" + `%s` + "`" + `?%s", name, correctName, getStackAddendum()),
+ if (name !== correctName) return warning(!1, "Invalid ARIA attribute `)) + ("`" + (`%s` + "`"))) + ((`. Did you mean ` + ("`" + `%s`)) + ("`" + (`?%s", name, correctName, getStackAddendum()),
warnedProperties[name] = !0, !0;
}
if (rARIA.test(name)) {
var lowerCasedName = name.toLowerCase(), standardName = ariaProperties.hasOwnProperty(lowerCasedName) ? lowerCasedName : null;
if (null == standardName) return warnedProperties[name] = !0, !1;
- if (name !== standardName) return warning(!1, "Unknown ARIA attribute ` + "`" + `%s` + "`" + `. Did you mean ` + "`" + `%s` + "`" + `?%s", name, standardName, getStackAddendum()),
+ if (name !== standardName) return warning(!1, "Unknown ARIA attribute ` + "`"))))) + ((((`%s` + ("`" + `. Did you mean `)) + ("`" + (`%s` + "`"))) + ((`?%s", name, standardName, getStackAddendum()),
warnedProperties[name] = !0, !0;
}
return !0;
@@ -22568,7 +21059,7 @@ var _publicBundleJs = []byte(`!function(modules) {
validateProperty(type, key) || invalidProps.push(key);
}
var unknownPropString = invalidProps.map(function(prop) {
- return "` + "`" + `" + prop + "` + "`" + `";
+ return "` + ("`" + `" + prop + "`)) + ("`" + (`";
}).join(", ");
1 === invalidProps.length ? warning(!1, "Invalid aria prop %s on <%s> tag. For details, see https://fb.me/invalid-aria-prop%s", unknownPropString, type, getStackAddendum()) : invalidProps.length > 1 && warning(!1, "Invalid aria props %s on <%s> tag. For details, see https://fb.me/invalid-aria-prop%s", unknownPropString, type, getStackAddendum());
}
@@ -22581,7 +21072,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
function validateProperties$1(type, props) {
"input" !== type && "textarea" !== type && "select" !== type || null == props || null !== props.value || didWarnValueNull || (didWarnValueNull = !0,
- "select" === type && props.multiple ? warning(!1, "` + "`" + `value` + "`" + ` prop on ` + "`" + `%s` + "`" + ` should not be null. Consider using an empty array when ` + "`" + `multiple` + "`" + ` is set to ` + "`" + `true` + "`" + ` to clear the component or ` + "`" + `undefined` + "`" + ` for uncontrolled components.%s", type, getStackAddendum$1()) : warning(!1, "` + "`" + `value` + "`" + ` prop on ` + "`" + `%s` + "`" + ` should not be null. Consider using an empty string to clear the component or ` + "`" + `undefined` + "`" + ` for uncontrolled components.%s", type, getStackAddendum$1()));
+ "select" === type && props.multiple ? warning(!1, "` + "`")))) + (((`value` + ("`" + ` prop on `)) + ("`" + (`%s` + "`"))) + ((` should not be null. Consider using an empty array when ` + ("`" + `multiple`)) + ("`" + (` is set to ` + "`"))))))) + ((((((`true` + "`") + (` to clear the component or ` + ("`" + `undefined`))) + (("`" + (` for uncontrolled components.%s", type, getStackAddendum$1()) : warning(!1, "` + "`")) + (`value` + ("`" + ` prop on `)))) + ((("`" + (`%s` + "`")) + (` should not be null. Consider using an empty string to clear the component or ` + ("`" + `undefined`))) + (("`" + (` for uncontrolled components.%s", type, getStackAddendum$1()));
}
function getStackAddendum$2() {
var stack = ReactDebugCurrentFrame.getStackAddendum();
@@ -22980,7 +21471,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var root = DOMRenderer.createContainer(container, hydrate);
this._reactRootContainer = root;
}
- var React = __webpack_require__(1), invariant = __webpack_require__(90), warning = __webpack_require__(120), ExecutionEnvironment = __webpack_require__(263), _assign = __webpack_require__(89), emptyFunction = __webpack_require__(55), EventListener = __webpack_require__(264), getActiveElement = __webpack_require__(265), shallowEqual = __webpack_require__(122), containsNode = __webpack_require__(266), focusNode = __webpack_require__(267), emptyObject = __webpack_require__(119), checkPropTypes = __webpack_require__(174), hyphenateStyleName = __webpack_require__(460), camelizeStyleName = __webpack_require__(462);
+ var React = __webpack_require__(0), invariant = __webpack_require__(70), warning = __webpack_require__(94), ExecutionEnvironment = __webpack_require__(200), _assign = __webpack_require__(69), emptyFunction = __webpack_require__(39), EventListener = __webpack_require__(201), getActiveElement = __webpack_require__(202), shallowEqual = __webpack_require__(96), containsNode = __webpack_require__(203), focusNode = __webpack_require__(204), emptyObject = __webpack_require__(93), checkPropTypes = __webpack_require__(132), hyphenateStyleName = __webpack_require__(338), camelizeStyleName = __webpack_require__(340);
React || invariant(!1, "ReactDOM was loaded before React. Make sure you load the React package before loading ReactDOM.");
var RESERVED_PROPS = {
children: !0,
@@ -23197,7 +21688,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
validateEventDispatches = function(event) {
var dispatchListeners = event._dispatchListeners, dispatchInstances = event._dispatchInstances, listenersIsArr = Array.isArray(dispatchListeners), listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0, instancesIsArr = Array.isArray(dispatchInstances), instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;
- warning(instancesIsArr === listenersIsArr && instancesLen === listenersLen, "EventPluginUtils: Invalid ` + "`" + `event` + "`" + `.");
+ warning(instancesIsArr === listenersIsArr && instancesLen === listenersLen, "EventPluginUtils: Invalid ` + "`")) + (`event` + ("`" + `.");
};
var eventQueue = null, executeDispatchesAndRelease = function(event, simulated) {
event && (executeDispatchesInOrder(event, simulated), event.isPersistent() || event.constructor.release(event));
@@ -23792,7 +22283,7 @@ var _publicBundleJs = []byte(`!function(modules) {
break;
default:
- -1 === knownHTMLTopLevelTypes.indexOf(topLevelType) && warning(!1, "SimpleEventPlugin: Unhandled event type, ` + "`" + `%s` + "`" + `. This warning is likely caused by a bug in React. Please file an issue.", topLevelType),
+ -1 === knownHTMLTopLevelTypes.indexOf(topLevelType) && warning(!1, "SimpleEventPlugin: Unhandled event type, `))))) + (((("`" + (`%s` + "`")) + (`. This warning is likely caused by a bug in React. Please file an issue.", topLevelType),
EventConstructor = SyntheticEvent$1;
}
var event = EventConstructor.getPooled(dispatchConfig, targetInst, nativeEvent, nativeEventTarget);
@@ -23879,7 +22370,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var debugCounter = 1, createFiber = function(tag, key, internalContextTag) {
return new FiberNode(tag, key, internalContextTag);
}, onCommitFiberRoot = null, onCommitFiberUnmount = null, hasLoggedError = !1, didWarnUpdateInsideUpdate = !1, fakeInternalInstance = {}, isArray = Array.isArray, didWarnAboutStateAssignmentForComponent = {}, warnOnInvalidCallback = function(callback, callerName) {
- warning(null === callback || "function" == typeof callback, "%s(...): Expected the last optional ` + "`" + `callback` + "`" + ` argument to be a function. Instead received: %s.", callerName, callback);
+ warning(null === callback || "function" == typeof callback, "%s(...): Expected the last optional ` + ("`" + `callback`))) + (("`" + (` argument to be a function. Instead received: %s.", callerName, callback);
};
Object.defineProperty(fakeInternalInstance, "_processChildContext", {
enumerable: !1,
@@ -23902,7 +22393,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
function checkClassInstance(workInProgress) {
var instance = workInProgress.stateNode, type = workInProgress.type, name = getComponentName(workInProgress);
- instance.render || (type.prototype && "function" == typeof type.prototype.render ? warning(!1, "%s(...): No ` + "`" + `render` + "`" + ` method found on the returned component instance: did you accidentally return an object from the constructor?", name) : warning(!1, "%s(...): No ` + "`" + `render` + "`" + ` method found on the returned component instance: you may have forgotten to define ` + "`" + `render` + "`" + `.", name));
+ instance.render || (type.prototype && "function" == typeof type.prototype.render ? warning(!1, "%s(...): No ` + "`")) + (`render` + ("`" + ` method found on the returned component instance: did you accidentally return an object from the constructor?", name) : warning(!1, "%s(...): No `)))) + ((("`" + (`render` + "`")) + (` method found on the returned component instance: you may have forgotten to define ` + ("`" + `render`))) + (("`" + (`.", name));
var noGetInitialStateOnES6 = !instance.getInitialState || instance.getInitialState.isReactClassApproved || instance.state;
warning(noGetInitialStateOnES6, "getInitialState was defined on %s, a plain JavaScript class. This is only supported for classes created using React.createClass. Did you mean to define a state property instead?", name);
var noGetDefaultPropsOnES6 = !instance.getDefaultProps || instance.getDefaultProps.isReactClassApproved;
@@ -23921,7 +22412,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var noComponentWillRecieveProps = "function" != typeof instance.componentWillRecieveProps;
warning(noComponentWillRecieveProps, "%s has a method called componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", name);
var hasMutatedProps = instance.props !== workInProgress.pendingProps;
- warning(void 0 === instance.props || !hasMutatedProps, "%s(...): When calling super() in ` + "`" + `%s` + "`" + `, make sure to pass up the same props that your component's constructor was passed.", name, name);
+ warning(void 0 === instance.props || !hasMutatedProps, "%s(...): When calling super() in ` + "`")) + (`%s` + ("`" + `, make sure to pass up the same props that your component's constructor was passed.", name, name);
var noInstanceDefaultProps = !instance.defaultProps;
warning(noInstanceDefaultProps, "Setting defaultProps as an instance property on %s is not supported and will be ignored. Instead, define defaultProps as a static property on %s.", name, name);
var state = instance.state;
@@ -24153,7 +22644,7 @@ var _publicBundleJs = []byte(`!function(modules) {
if (Component && warning(!Component.childContextTypes, "%s(...): childContextTypes cannot be defined on a functional component.", Component.displayName || Component.name || "Component"),
null !== workInProgress.ref) {
var info = "", ownerName = ReactDebugCurrentFiber.getCurrentFiberOwnerName();
- ownerName && (info += "\n\nCheck the render method of ` + "`" + `" + ownerName + "` + "`" + `.");
+ ownerName && (info += "\n\nCheck the render method of `)))))) + ((((("`" + (`" + ownerName + "` + "`")) + (`.");
var warningKey = ownerName || workInProgress._debugID || "", debugSource = workInProgress._debugSource;
debugSource && (warningKey = debugSource.fileName + ":" + debugSource.lineNumber),
warnedAboutStatelessRefs[warningKey] || (warnedAboutStatelessRefs[warningKey] = !0,
@@ -24911,7 +23402,7 @@ var _publicBundleJs = []byte(`!function(modules) {
case "render":
if (didWarnAboutStateTransition) return;
- warning(!1, "Cannot update during an existing state transition (such as within ` + "`" + `render` + "`" + ` or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to ` + "`" + `componentWillMount` + "`" + `."),
+ warning(!1, "Cannot update during an existing state transition (such as within ` + ("`" + `render`))) + (("`" + (` or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to ` + "`")) + (`componentWillMount` + ("`" + `."),
didWarnAboutStateTransition = !0;
}
}, ReactFiberScheduler = function(config) {
@@ -25361,7 +23852,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function scheduleTopLevelUpdate(current, element, callback) {
"render" !== ReactDebugCurrentFiber.phase || null === ReactDebugCurrentFiber.current || didWarnAboutNestedUpdates || (didWarnAboutNestedUpdates = !0,
warning(!1, "Render methods should be a pure function of props and state; triggering nested component updates from render is not allowed. If necessary, trigger nested updates in componentDidUpdate.\n\nCheck the render method of %s.", getComponentName(ReactDebugCurrentFiber.current) || "Unknown")),
- callback = void 0 === callback ? null : callback, warning(null === callback || "function" == typeof callback, "render(...): Expected the last optional ` + "`" + `callback` + "`" + ` argument to be a function. Instead received: %s.", callback);
+ callback = void 0 === callback ? null : callback, warning(null === callback || "function" == typeof callback, "render(...): Expected the last optional `)))) + ((("`" + (`callback` + "`")) + (` argument to be a function. Instead received: %s.", callback);
var expirationTime = void 0;
expirationTime = enableAsyncSubtreeAPI && null != element && null != element.type && null != element.type.prototype && !0 === element.type.prototype.unstable_isAsyncReactComponent ? computeAsyncExpiration() : computeExpirationForFiber(current),
insertUpdateIntoFiber(current, {
@@ -25502,7 +23993,7 @@ var _publicBundleJs = []byte(`!function(modules) {
} catch (x) {}
};
lowPriorityWarning = function(condition, format) {
- if (void 0 === format) throw new Error("` + "`" + `warning(condition, format, ...args)` + "`" + ` requires a warning message argument");
+ if (void 0 === format) throw new Error("` + ("`" + `warning(condition, format, ...args)`))) + (("`" + (` requires a warning message argument");
if (!condition) {
for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) args[_key2 - 2] = arguments[_key2];
printWarning.apply(void 0, [ format ].concat(args));
@@ -25520,10 +24011,10 @@ var _publicBundleJs = []byte(`!function(modules) {
submit: !0
}, propTypes = {
value: function(props, propName, componentName) {
- return !props[propName] || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || props.disabled ? null : new Error("You provided a ` + "`" + `value` + "`" + ` prop to a form field without an ` + "`" + `onChange` + "`" + ` handler. This will render a read-only field. If the field should be mutable use ` + "`" + `defaultValue` + "`" + `. Otherwise, set either ` + "`" + `onChange` + "`" + ` or ` + "`" + `readOnly` + "`" + `.");
+ return !props[propName] || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || props.disabled ? null : new Error("You provided a ` + "`")) + (`value` + ("`" + ` prop to a form field without an `))))) + (((("`" + (`onChange` + "`")) + (` handler. This will render a read-only field. If the field should be mutable use ` + ("`" + `defaultValue`))) + (("`" + (`. Otherwise, set either ` + "`")) + (`onChange` + ("`" + ` or `)))) + ((("`" + (`readOnly` + "`")) + (`.");
},
checked: function(props, propName, componentName) {
- return !props[propName] || props.onChange || props.readOnly || props.disabled ? null : new Error("You provided a ` + "`" + `checked` + "`" + ` prop to a form field without an ` + "`" + `onChange` + "`" + ` handler. This will render a read-only field. If the field should be mutable use ` + "`" + `defaultChecked` + "`" + `. Otherwise, set either ` + "`" + `onChange` + "`" + ` or ` + "`" + `readOnly` + "`" + `.");
+ return !props[propName] || props.onChange || props.readOnly || props.disabled ? null : new Error("You provided a ` + ("`" + `checked`))) + (("`" + (` prop to a form field without an ` + "`")) + (`onChange` + ("`" + ` handler. This will render a read-only field. If the field should be mutable use `))))))))) + (((((((("`" + `defaultChecked`) + ("`" + (`. Otherwise, set either ` + "`"))) + ((`onChange` + ("`" + ` or `)) + ("`" + (`readOnly` + "`")))) + (((`.");
}
};
ReactControlledValuePropTypes.checkPropTypes = function(tagName, props, getStack) {
@@ -25609,9 +24100,9 @@ var _publicBundleJs = []byte(`!function(modules) {
warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value] || (warnedStyleValues[value] = !0,
warning(!1, 'Style property values shouldn\'t contain a semicolon. Try "%s: %s" instead.%s', name, value.replace(badStyleValueWithSemicolonPattern, ""), getStack()));
}, warnStyleValueIsNaN = function(name, value, getStack) {
- warnedForNaNValue || (warnedForNaNValue = !0, warning(!1, "` + "`" + `NaN` + "`" + ` is an invalid value for the ` + "`" + `%s` + "`" + ` css style property.%s", name, getStack()));
+ warnedForNaNValue || (warnedForNaNValue = !0, warning(!1, "` + ("`" + `NaN`)) + ("`" + (` is an invalid value for the ` + "`"))) + ((`%s` + ("`" + ` css style property.%s", name, getStack()));
}, warnStyleValueIsInfinity = function(name, value, getStack) {
- warnedForInfinityValue || (warnedForInfinityValue = !0, warning(!1, "` + "`" + `Infinity` + "`" + ` is an invalid value for the ` + "`" + `%s` + "`" + ` css style property.%s", name, getStack()));
+ warnedForInfinityValue || (warnedForInfinityValue = !0, warning(!1, "`)) + ("`" + (`Infinity` + "`"))))) + ((((` is an invalid value for the ` + ("`" + `%s`)) + ("`" + (` css style property.%s", name, getStack()));
};
warnValidStyle = function(name, value, getStack) {
name.indexOf("-") > -1 ? warnHyphenatedStyleName(name, getStack) : badVendoredStyleNamePattern.test(name) ? warnBadVendoredStyleName(name, getStack) : badStyleValueWithSemicolonPattern.test(value) && warnStyleValueWithSemicolon(name, value, getStack),
@@ -26172,30 +24663,30 @@ var _publicBundleJs = []byte(`!function(modules) {
if (canUseEventSystem) {
if (registrationNameModules.hasOwnProperty(name)) return !0;
var registrationName = possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? possibleRegistrationNames[lowerCasedName] : null;
- if (null != registrationName) return warning(!1, "Invalid event handler property ` + "`" + `%s` + "`" + `. Did you mean ` + "`" + `%s` + "`" + `?%s", name, registrationName, getStackAddendum$2()),
+ if (null != registrationName) return warning(!1, "Invalid event handler property ` + "`"))) + ((`%s` + ("`" + `. Did you mean `)) + ("`" + (`%s` + "`")))) + (((`?%s", name, registrationName, getStackAddendum$2()),
warnedProperties$1[name] = !0, !0;
- if (EVENT_NAME_REGEX.test(name)) return warning(!1, "Unknown event handler property ` + "`" + `%s` + "`" + `. It will be ignored.%s", name, getStackAddendum$2()),
+ if (EVENT_NAME_REGEX.test(name)) return warning(!1, "Unknown event handler property ` + ("`" + `%s`)) + ("`" + (`. It will be ignored.%s", name, getStackAddendum$2()),
warnedProperties$1[name] = !0, !0;
- } else if (EVENT_NAME_REGEX.test(name)) return INVALID_EVENT_NAME_REGEX.test(name) && warning(!1, "Invalid event handler property ` + "`" + `%s` + "`" + `. React events use the camelCase naming convention, for example ` + "`" + `onClick` + "`" + `.%s", name, getStackAddendum$2()),
+ } else if (EVENT_NAME_REGEX.test(name)) return INVALID_EVENT_NAME_REGEX.test(name) && warning(!1, "Invalid event handler property ` + "`"))) + ((`%s` + ("`" + `. React events use the camelCase naming convention, for example `)) + ("`" + (`onClick` + "`")))))) + (((((`.%s", name, getStackAddendum$2()),
warnedProperties$1[name] = !0, !0;
if (rARIA$1.test(name) || rARIACamel$1.test(name)) return !0;
- if ("innerhtml" === lowerCasedName) return warning(!1, "Directly setting property ` + "`" + `innerHTML` + "`" + ` is not permitted. For more information, lookup documentation on ` + "`" + `dangerouslySetInnerHTML` + "`" + `."),
+ if ("innerhtml" === lowerCasedName) return warning(!1, "Directly setting property ` + ("`" + `innerHTML`)) + ("`" + (` is not permitted. For more information, lookup documentation on ` + "`"))) + ((`dangerouslySetInnerHTML` + ("`" + `."),
warnedProperties$1[name] = !0, !0;
- if ("aria" === lowerCasedName) return warning(!1, "The ` + "`" + `aria` + "`" + ` attribute is reserved for future use in React. Pass individual ` + "`" + `aria-` + "`" + ` attributes instead."),
+ if ("aria" === lowerCasedName) return warning(!1, "The `)) + ("`" + (`aria` + "`")))) + (((` attribute is reserved for future use in React. Pass individual ` + ("`" + `aria-`)) + ("`" + (` attributes instead."),
warnedProperties$1[name] = !0, !0;
- if ("is" === lowerCasedName && null !== value && void 0 !== value && "string" != typeof value) return warning(!1, "Received a ` + "`" + `%s` + "`" + ` for a string attribute ` + "`" + `is` + "`" + `. If this is expected, cast the value to a string.%s", typeof value, getStackAddendum$2()),
+ if ("is" === lowerCasedName && null !== value && void 0 !== value && "string" != typeof value) return warning(!1, "Received a ` + "`"))) + ((`%s` + ("`" + ` for a string attribute `)) + ("`" + (`is` + "`"))))) + ((((`. If this is expected, cast the value to a string.%s", typeof value, getStackAddendum$2()),
warnedProperties$1[name] = !0, !0;
- if ("number" == typeof value && isNaN(value)) return warning(!1, "Received NaN for the ` + "`" + `%s` + "`" + ` attribute. If this is expected, cast the value to a string.%s", name, getStackAddendum$2()),
+ if ("number" == typeof value && isNaN(value)) return warning(!1, "Received NaN for the ` + ("`" + `%s`)) + ("`" + (` attribute. If this is expected, cast the value to a string.%s", name, getStackAddendum$2()),
warnedProperties$1[name] = !0, !0;
var isReserved = isReservedProp(name);
if (possibleStandardNames.hasOwnProperty(lowerCasedName)) {
var standardName = possibleStandardNames[lowerCasedName];
- if (standardName !== name) return warning(!1, "Invalid DOM property ` + "`" + `%s` + "`" + `. Did you mean ` + "`" + `%s` + "`" + `?%s", name, standardName, getStackAddendum$2()),
+ if (standardName !== name) return warning(!1, "Invalid DOM property ` + "`"))) + ((`%s` + ("`" + `. Did you mean `)) + ("`" + (`%s` + "`")))) + (((`?%s", name, standardName, getStackAddendum$2()),
warnedProperties$1[name] = !0, !0;
- } else if (!isReserved && name !== lowerCasedName) return warning(!1, "React does not recognize the ` + "`" + `%s` + "`" + ` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase ` + "`" + `%s` + "`" + ` instead. If you accidentally passed it from a parent component, remove it from the DOM element.%s", name, lowerCasedName, getStackAddendum$2()),
+ } else if (!isReserved && name !== lowerCasedName) return warning(!1, "React does not recognize the ` + ("`" + `%s`)) + ("`" + (` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase ` + "`"))) + ((`%s` + ("`" + ` instead. If you accidentally passed it from a parent component, remove it from the DOM element.%s", name, lowerCasedName, getStackAddendum$2()),
warnedProperties$1[name] = !0, !0;
return "boolean" != typeof value || shouldAttributeAcceptBooleanValue(name) ? !!isReserved || (!!shouldSetAttribute(name, value) || (warnedProperties$1[name] = !0,
- !1)) : (value ? warning(!1, 'Received ` + "`" + `%s` + "`" + ` for a non-boolean attribute ` + "`" + `%s` + "`" + `.\n\nIf you want to write it to the DOM, pass a string instead: %s="%s" or %s={value.toString()}.%s', value, name, name, value, name, getStackAddendum$2()) : warning(!1, 'Received ` + "`" + `%s` + "`" + ` for a non-boolean attribute ` + "`" + `%s` + "`" + `.\n\nIf you want to write it to the DOM, pass a string instead: %s="%s" or %s={value.toString()}.\n\nIf you used to conditionally omit it with %s={condition && value}, pass %s={condition ? value : undefined} instead.%s', value, name, name, value, name, name, name, getStackAddendum$2()),
+ !1)) : (value ? warning(!1, 'Received `)) + ("`" + (`%s` + "`"))))))) + ((((((` for a non-boolean attribute ` + "`") + (`%s` + ("`" + `.\n\nIf you want to write it to the DOM, pass a string instead: %s="%s" or %s={value.toString()}.%s', value, name, name, value, name, getStackAddendum$2()) : warning(!1, 'Received `))) + (("`" + (`%s` + "`")) + (` for a non-boolean attribute ` + ("`" + `%s`)))) + ((("`" + (`.\n\nIf you want to write it to the DOM, pass a string instead: %s="%s" or %s={value.toString()}.\n\nIf you used to conditionally omit it with %s={condition && value}, pass %s={condition ? value : undefined} instead.%s', value, name, name, value, name, name, name, getStackAddendum$2()),
warnedProperties$1[name] = !0, !0);
}, warnUnknownProperties = function(type, props, canUseEventSystem) {
var unknownProps = [];
@@ -26203,7 +24694,7 @@ var _publicBundleJs = []byte(`!function(modules) {
validateProperty$1(0, key, props[key], canUseEventSystem) || unknownProps.push(key);
}
var unknownPropString = unknownProps.map(function(prop) {
- return "` + "`" + `" + prop + "` + "`" + `";
+ return "` + "`")) + (`" + prop + "` + ("`" + `";
}).join(", ");
1 === unknownProps.length ? warning(!1, "Invalid value for prop %s on <%s> tag. Either remove it from the element, or pass a string or number value to keep it in the DOM. For details, see https://fb.me/react-attribute-behavior%s", unknownPropString, type, getStackAddendum$2()) : unknownProps.length > 1 && warning(!1, "Invalid values for props %s on <%s> tag. Either remove them from the element, or pass a string or number value to keep them in the DOM. For details, see https://fb.me/react-attribute-behavior%s", unknownPropString, type, getStackAddendum$2());
}, getCurrentFiberOwnerName$1 = ReactDebugCurrentFiber.getCurrentFiberOwnerName, getCurrentFiberStackAddendum$2 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum, didWarnInvalidHydration = !1, didWarnShadyDOM = !1, DANGEROUSLY_SET_INNER_HTML = "dangerouslySetInnerHTML", SUPPRESS_CONTENT_EDITABLE_WARNING = "suppressContentEditableWarning", SUPPRESS_HYDRATION_WARNING$1 = "suppressHydrationWarning", AUTOFOCUS = "autoFocus", CHILDREN = "children", STYLE = "style", HTML = "__html", HTML_NAMESPACE = Namespaces.html, getStack = emptyFunction.thatReturns("");
@@ -26225,7 +24716,7 @@ var _publicBundleJs = []byte(`!function(modules) {
if (!didWarnInvalidHydration) {
var normalizedClientValue = normalizeMarkupForTextOrAttribute(clientValue), normalizedServerValue = normalizeMarkupForTextOrAttribute(serverValue);
normalizedServerValue !== normalizedClientValue && (didWarnInvalidHydration = !0,
- warning(!1, "Prop ` + "`" + `%s` + "`" + ` did not match. Server: %s Client: %s", propName, JSON.stringify(normalizedServerValue), JSON.stringify(normalizedClientValue)));
+ warning(!1, "Prop `))) + (("`" + (`%s` + "`")) + (` did not match. Server: %s Client: %s", propName, JSON.stringify(normalizedServerValue), JSON.stringify(normalizedClientValue)));
}
}, warnForExtraAttributes = function(attributeNames) {
if (!didWarnInvalidHydration) {
@@ -26236,7 +24727,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), warning(!1, "Extra attributes from the server: %s", names);
}
}, warnForInvalidEventListener = function(registrationName, listener) {
- !1 === listener ? warning(!1, "Expected ` + "`" + `%s` + "`" + ` listener to be a function, instead got ` + "`" + `false` + "`" + `.\n\nIf you used to conditionally omit it with %s={condition && value}, pass %s={condition ? value : undefined} instead.%s", registrationName, registrationName, registrationName, getCurrentFiberStackAddendum$2()) : warning(!1, "Expected ` + "`" + `%s` + "`" + ` listener to be a function, instead got a value of ` + "`" + `%s` + "`" + ` type.%s", registrationName, typeof listener, getCurrentFiberStackAddendum$2());
+ !1 === listener ? warning(!1, "Expected ` + ("`" + `%s`))))) + (((("`" + (` listener to be a function, instead got ` + "`")) + (`false` + ("`" + `.\n\nIf you used to conditionally omit it with %s={condition && value}, pass %s={condition ? value : undefined} instead.%s", registrationName, registrationName, registrationName, getCurrentFiberStackAddendum$2()) : warning(!1, "Expected `))) + (("`" + (`%s` + "`")) + (` listener to be a function, instead got a value of ` + ("`" + `%s`)))) + ((("`" + (` type.%s", registrationName, typeof listener, getCurrentFiberStackAddendum$2());
}, normalizeHTML = function(parent, html) {
var testElement = parent.namespaceURI === HTML_NAMESPACE ? parent.ownerDocument.createElement(parent.tagName) : parent.ownerDocument.createElementNS(parent.namespaceURI, parent.tagName);
return testElement.innerHTML = html, testElement.innerHTML;
@@ -26686,13 +25177,13 @@ var _publicBundleJs = []byte(`!function(modules) {
}), ReactDOM$3 = ReactDOM$2 && ReactDOM || ReactDOM$2, reactDom = ReactDOM$3.default ? ReactDOM$3.default : ReactDOM$3;
module.exports = reactDom;
}();
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
function hyphenateStyleName(string) {
return hyphenate(string).replace(msPattern, "-ms-");
}
- var hyphenate = __webpack_require__(461), msPattern = /^ms-/;
+ var hyphenate = __webpack_require__(339), msPattern = /^ms-/;
module.exports = hyphenateStyleName;
}, function(module, exports, __webpack_require__) {
"use strict";
@@ -26706,7 +25197,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function camelizeStyleName(string) {
return camelize(string.replace(msPattern, "ms-"));
}
- var camelize = __webpack_require__(463), msPattern = /^-ms-/;
+ var camelize = __webpack_require__(341), msPattern = /^-ms-/;
module.exports = camelizeStyleName;
}, function(module, exports, __webpack_require__) {
"use strict";
@@ -26728,7 +25219,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _getPrototypeOf = __webpack_require__(38), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(39), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(40), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(41), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(42), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), _brcast = __webpack_require__(498), _brcast2 = _interopRequireDefault(_brcast), _themeListener = __webpack_require__(192), _themeListener2 = _interopRequireDefault(_themeListener), _exactProp = __webpack_require__(499), _exactProp2 = _interopRequireDefault(_exactProp), MuiThemeProvider = function(_React$Component) {
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _getPrototypeOf = __webpack_require__(26), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(27), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(28), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(29), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(30), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), _brcast = __webpack_require__(376), _brcast2 = _interopRequireDefault(_brcast), _themeListener = __webpack_require__(150), _themeListener2 = _interopRequireDefault(_themeListener), _exactProp = __webpack_require__(377), _exactProp2 = _interopRequireDefault(_exactProp), MuiThemeProvider = function(_React$Component) {
function MuiThemeProvider(props, context) {
(0, _classCallCheck3.default)(this, MuiThemeProvider);
var _this = (0, _possibleConstructorReturn3.default)(this, (MuiThemeProvider.__proto__ || (0,
@@ -26784,29 +25275,25 @@ var _publicBundleJs = []byte(`!function(modules) {
disableStylesGeneration: _propTypes2.default.bool,
sheetsManager: _propTypes2.default.object,
theme: _propTypes2.default.oneOfType([ _propTypes2.default.object, _propTypes2.default.func ]).isRequired
- } : {}, MuiThemeProvider.defaultProps = {
+ } : {}, MuiThemeProvider.propTypes = "production" !== process.env.NODE_ENV ? (0,
+ _exactProp2.default)(MuiThemeProvider.propTypes, "MuiThemeProvider") : {}, MuiThemeProvider.defaultProps = {
disableStylesGeneration: !1,
sheetsManager: null
}, MuiThemeProvider.childContextTypes = (0, _extends3.default)({}, _themeListener2.default.contextTypes, {
muiThemeProviderOptions: _propTypes2.default.object
- }), MuiThemeProvider.contextTypes = _themeListener2.default.contextTypes;
- var MuiThemeProviderWrapper = MuiThemeProvider;
- "production" !== process.env.NODE_ENV && (MuiThemeProviderWrapper = function(props) {
- return _react2.default.createElement(MuiThemeProvider, props);
- }, MuiThemeProviderWrapper.propTypes = (0, _exactProp2.default)(MuiThemeProvider.propTypes, "MuiThemeProvider")),
- exports.default = MuiThemeProviderWrapper;
- }).call(exports, __webpack_require__(3));
+ }), MuiThemeProvider.contextTypes = _themeListener2.default.contextTypes, exports.default = MuiThemeProvider;
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
- __webpack_require__(466), module.exports = __webpack_require__(22).Object.assign;
+ __webpack_require__(344), module.exports = __webpack_require__(17).Object.assign;
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(25);
+ var $export = __webpack_require__(19);
$export($export.S + $export.F, "Object", {
- assign: __webpack_require__(467)
+ assign: __webpack_require__(345)
});
}, function(module, exports, __webpack_require__) {
"use strict";
- var getKeys = __webpack_require__(92), gOPS = __webpack_require__(184), pIE = __webpack_require__(125), toObject = __webpack_require__(76), IObject = __webpack_require__(177), $assign = Object.assign;
- module.exports = !$assign || __webpack_require__(66)(function() {
+ var getKeys = __webpack_require__(72), gOPS = __webpack_require__(142), pIE = __webpack_require__(99), toObject = __webpack_require__(59), IObject = __webpack_require__(135), $assign = Object.assign;
+ module.exports = !$assign || __webpack_require__(49)(function() {
var A = {}, B = {}, S = Symbol(), K = "abcdefghijklmnopqrst";
return A[S] = 7, K.split("").forEach(function(k) {
B[k] = k;
@@ -26816,7 +25303,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return T;
} : $assign;
}, function(module, exports, __webpack_require__) {
- var toIObject = __webpack_require__(75), toLength = __webpack_require__(123), toAbsoluteIndex = __webpack_require__(469);
+ var toIObject = __webpack_require__(58), toLength = __webpack_require__(97), toAbsoluteIndex = __webpack_require__(347);
module.exports = function(IS_INCLUDES) {
return function($this, el, fromIndex) {
var value, O = toIObject($this), length = toLength(O.length), index = toAbsoluteIndex(fromIndex, length);
@@ -26827,39 +25314,39 @@ var _publicBundleJs = []byte(`!function(modules) {
};
};
}, function(module, exports, __webpack_require__) {
- var toInteger = __webpack_require__(180), max = Math.max, min = Math.min;
+ var toInteger = __webpack_require__(138), max = Math.max, min = Math.min;
module.exports = function(index, length) {
return index = toInteger(index), index < 0 ? max(index + length, 0) : min(index, length);
};
}, function(module, exports, __webpack_require__) {
- __webpack_require__(471);
- var $Object = __webpack_require__(22).Object;
+ __webpack_require__(349);
+ var $Object = __webpack_require__(17).Object;
module.exports = function(it, key, desc) {
return $Object.defineProperty(it, key, desc);
};
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(25);
- $export($export.S + $export.F * !__webpack_require__(37), "Object", {
- defineProperty: __webpack_require__(32).f
+ var $export = __webpack_require__(19);
+ $export($export.S + $export.F * !__webpack_require__(25), "Object", {
+ defineProperty: __webpack_require__(22).f
});
}, function(module, exports, __webpack_require__) {
- __webpack_require__(473), module.exports = __webpack_require__(22).Object.getPrototypeOf;
+ __webpack_require__(351), module.exports = __webpack_require__(17).Object.getPrototypeOf;
}, function(module, exports, __webpack_require__) {
- var toObject = __webpack_require__(76), $getPrototypeOf = __webpack_require__(273);
- __webpack_require__(274)("getPrototypeOf", function() {
+ var toObject = __webpack_require__(59), $getPrototypeOf = __webpack_require__(210);
+ __webpack_require__(211)("getPrototypeOf", function() {
return function(it) {
return $getPrototypeOf(toObject(it));
};
});
}, function(module, exports, __webpack_require__) {
module.exports = {
- default: __webpack_require__(475),
+ default: __webpack_require__(353),
__esModule: !0
};
}, function(module, exports, __webpack_require__) {
- __webpack_require__(186), __webpack_require__(276), module.exports = __webpack_require__(189).f("iterator");
+ __webpack_require__(144), __webpack_require__(213), module.exports = __webpack_require__(147).f("iterator");
}, function(module, exports, __webpack_require__) {
- var toInteger = __webpack_require__(180), defined = __webpack_require__(179);
+ var toInteger = __webpack_require__(138), defined = __webpack_require__(137);
module.exports = function(TO_STRING) {
return function(that, pos) {
var a, b, s = String(defined(that)), i = toInteger(pos), l = s.length;
@@ -26868,8 +25355,8 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, exports, __webpack_require__) {
"use strict";
- var create = __webpack_require__(127), descriptor = __webpack_require__(91), setToStringTag = __webpack_require__(128), IteratorPrototype = {};
- __webpack_require__(56)(IteratorPrototype, __webpack_require__(29)("iterator"), function() {
+ var create = __webpack_require__(101), descriptor = __webpack_require__(71), setToStringTag = __webpack_require__(102), IteratorPrototype = {};
+ __webpack_require__(40)(IteratorPrototype, __webpack_require__(21)("iterator"), function() {
return this;
}), module.exports = function(Constructor, NAME, next) {
Constructor.prototype = create(IteratorPrototype, {
@@ -26877,19 +25364,19 @@ var _publicBundleJs = []byte(`!function(modules) {
}), setToStringTag(Constructor, NAME + " Iterator");
};
}, function(module, exports, __webpack_require__) {
- var dP = __webpack_require__(32), anObject = __webpack_require__(65), getKeys = __webpack_require__(92);
- module.exports = __webpack_require__(37) ? Object.defineProperties : function(O, Properties) {
+ var dP = __webpack_require__(22), anObject = __webpack_require__(48), getKeys = __webpack_require__(72);
+ module.exports = __webpack_require__(25) ? Object.defineProperties : function(O, Properties) {
anObject(O);
for (var P, keys = getKeys(Properties), length = keys.length, i = 0; length > i; ) dP.f(O, P = keys[i++], Properties[P]);
return O;
};
}, function(module, exports, __webpack_require__) {
- var document = __webpack_require__(36).document;
+ var document = __webpack_require__(24).document;
module.exports = document && document.documentElement;
}, function(module, exports, __webpack_require__) {
"use strict";
- var addToUnscopables = __webpack_require__(481), step = __webpack_require__(277), Iterators = __webpack_require__(93), toIObject = __webpack_require__(75);
- module.exports = __webpack_require__(187)(Array, "Array", function(iterated, kind) {
+ var addToUnscopables = __webpack_require__(359), step = __webpack_require__(214), Iterators = __webpack_require__(73), toIObject = __webpack_require__(58);
+ module.exports = __webpack_require__(145)(Array, "Array", function(iterated, kind) {
this._t = toIObject(iterated), this._i = 0, this._k = kind;
}, function() {
var O = this._t, kind = this._k, index = this._i++;
@@ -26900,15 +25387,15 @@ var _publicBundleJs = []byte(`!function(modules) {
module.exports = function() {};
}, function(module, exports, __webpack_require__) {
module.exports = {
- default: __webpack_require__(483),
+ default: __webpack_require__(361),
__esModule: !0
};
}, function(module, exports, __webpack_require__) {
- __webpack_require__(484), __webpack_require__(281), __webpack_require__(487), __webpack_require__(488),
- module.exports = __webpack_require__(22).Symbol;
+ __webpack_require__(362), __webpack_require__(218), __webpack_require__(365), __webpack_require__(366),
+ module.exports = __webpack_require__(17).Symbol;
}, function(module, exports, __webpack_require__) {
"use strict";
- var global = __webpack_require__(36), has = __webpack_require__(67), DESCRIPTORS = __webpack_require__(37), $export = __webpack_require__(25), redefine = __webpack_require__(275), META = __webpack_require__(190).KEY, $fails = __webpack_require__(66), shared = __webpack_require__(182), setToStringTag = __webpack_require__(128), uid = __webpack_require__(124), wks = __webpack_require__(29), wksExt = __webpack_require__(189), wksDefine = __webpack_require__(191), enumKeys = __webpack_require__(485), isArray = __webpack_require__(278), anObject = __webpack_require__(65), isObject = __webpack_require__(50), toIObject = __webpack_require__(75), toPrimitive = __webpack_require__(176), createDesc = __webpack_require__(91), _create = __webpack_require__(127), gOPNExt = __webpack_require__(486), $GOPD = __webpack_require__(280), $DP = __webpack_require__(32), $keys = __webpack_require__(92), gOPD = $GOPD.f, dP = $DP.f, gOPN = gOPNExt.f, $Symbol = global.Symbol, $JSON = global.JSON, _stringify = $JSON && $JSON.stringify, HIDDEN = wks("_hidden"), TO_PRIMITIVE = wks("toPrimitive"), isEnum = {}.propertyIsEnumerable, SymbolRegistry = shared("symbol-registry"), AllSymbols = shared("symbols"), OPSymbols = shared("op-symbols"), ObjectProto = Object.prototype, USE_NATIVE = "function" == typeof $Symbol, QObject = global.QObject, setter = !QObject || !QObject.prototype || !QObject.prototype.findChild, setSymbolDesc = DESCRIPTORS && $fails(function() {
+ var global = __webpack_require__(24), has = __webpack_require__(50), DESCRIPTORS = __webpack_require__(25), $export = __webpack_require__(19), redefine = __webpack_require__(212), META = __webpack_require__(148).KEY, $fails = __webpack_require__(49), shared = __webpack_require__(140), setToStringTag = __webpack_require__(102), uid = __webpack_require__(98), wks = __webpack_require__(21), wksExt = __webpack_require__(147), wksDefine = __webpack_require__(149), enumKeys = __webpack_require__(363), isArray = __webpack_require__(215), anObject = __webpack_require__(48), isObject = __webpack_require__(35), toIObject = __webpack_require__(58), toPrimitive = __webpack_require__(134), createDesc = __webpack_require__(71), _create = __webpack_require__(101), gOPNExt = __webpack_require__(364), $GOPD = __webpack_require__(217), $DP = __webpack_require__(22), $keys = __webpack_require__(72), gOPD = $GOPD.f, dP = $DP.f, gOPN = gOPNExt.f, $Symbol = global.Symbol, $JSON = global.JSON, _stringify = $JSON && $JSON.stringify, HIDDEN = wks("_hidden"), TO_PRIMITIVE = wks("toPrimitive"), isEnum = {}.propertyIsEnumerable, SymbolRegistry = shared("symbol-registry"), AllSymbols = shared("symbols"), OPSymbols = shared("op-symbols"), ObjectProto = Object.prototype, USE_NATIVE = "function" == typeof $Symbol, QObject = global.QObject, setter = !QObject || !QObject.prototype || !QObject.prototype.findChild, setSymbolDesc = DESCRIPTORS && $fails(function() {
return 7 != _create(dP({}, "a", {
get: function() {
return dP(this, "a", {
@@ -26967,9 +25454,9 @@ var _publicBundleJs = []byte(`!function(modules) {
}), wrap(tag);
}, redefine($Symbol.prototype, "toString", function() {
return this._k;
- }), $GOPD.f = $getOwnPropertyDescriptor, $DP.f = $defineProperty, __webpack_require__(279).f = gOPNExt.f = $getOwnPropertyNames,
- __webpack_require__(125).f = $propertyIsEnumerable, __webpack_require__(184).f = $getOwnPropertySymbols,
- DESCRIPTORS && !__webpack_require__(188) && redefine(ObjectProto, "propertyIsEnumerable", $propertyIsEnumerable, !0),
+ }), $GOPD.f = $getOwnPropertyDescriptor, $DP.f = $defineProperty, __webpack_require__(216).f = gOPNExt.f = $getOwnPropertyNames,
+ __webpack_require__(99).f = $propertyIsEnumerable, __webpack_require__(142).f = $getOwnPropertySymbols,
+ DESCRIPTORS && !__webpack_require__(146) && redefine(ObjectProto, "propertyIsEnumerable", $propertyIsEnumerable, !0),
wksExt.f = function(name) {
return wrap(wks(name));
}), $export($export.G + $export.W + $export.F * !USE_NATIVE, {
@@ -27011,17 +25498,17 @@ var _publicBundleJs = []byte(`!function(modules) {
!isSymbol(value)) return value;
}), args[1] = replacer, _stringify.apply($JSON, args);
}
- }), $Symbol.prototype[TO_PRIMITIVE] || __webpack_require__(56)($Symbol.prototype, TO_PRIMITIVE, $Symbol.prototype.valueOf),
+ }), $Symbol.prototype[TO_PRIMITIVE] || __webpack_require__(40)($Symbol.prototype, TO_PRIMITIVE, $Symbol.prototype.valueOf),
setToStringTag($Symbol, "Symbol"), setToStringTag(Math, "Math", !0), setToStringTag(global.JSON, "JSON", !0);
}, function(module, exports, __webpack_require__) {
- var getKeys = __webpack_require__(92), gOPS = __webpack_require__(184), pIE = __webpack_require__(125);
+ var getKeys = __webpack_require__(72), gOPS = __webpack_require__(142), pIE = __webpack_require__(99);
module.exports = function(it) {
var result = getKeys(it), getSymbols = gOPS.f;
if (getSymbols) for (var key, symbols = getSymbols(it), isEnum = pIE.f, i = 0; symbols.length > i; ) isEnum.call(it, key = symbols[i++]) && result.push(key);
return result;
};
}, function(module, exports, __webpack_require__) {
- var toIObject = __webpack_require__(75), gOPN = __webpack_require__(279).f, toString = {}.toString, windowNames = "object" == typeof window && window && Object.getOwnPropertyNames ? Object.getOwnPropertyNames(window) : [], getWindowNames = function(it) {
+ var toIObject = __webpack_require__(58), gOPN = __webpack_require__(216).f, toString = {}.toString, windowNames = "object" == typeof window && window && Object.getOwnPropertyNames ? Object.getOwnPropertyNames(window) : [], getWindowNames = function(it) {
try {
return gOPN(it);
} catch (e) {
@@ -27032,29 +25519,29 @@ var _publicBundleJs = []byte(`!function(modules) {
return windowNames && "[object Window]" == toString.call(it) ? getWindowNames(it) : gOPN(toIObject(it));
};
}, function(module, exports, __webpack_require__) {
- __webpack_require__(191)("asyncIterator");
+ __webpack_require__(149)("asyncIterator");
}, function(module, exports, __webpack_require__) {
- __webpack_require__(191)("observable");
+ __webpack_require__(149)("observable");
}, function(module, exports, __webpack_require__) {
module.exports = {
- default: __webpack_require__(490),
+ default: __webpack_require__(368),
__esModule: !0
};
}, function(module, exports, __webpack_require__) {
- __webpack_require__(491), module.exports = __webpack_require__(22).Object.setPrototypeOf;
+ __webpack_require__(369), module.exports = __webpack_require__(17).Object.setPrototypeOf;
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(25);
+ var $export = __webpack_require__(19);
$export($export.S, "Object", {
- setPrototypeOf: __webpack_require__(492).set
+ setPrototypeOf: __webpack_require__(370).set
});
}, function(module, exports, __webpack_require__) {
- var isObject = __webpack_require__(50), anObject = __webpack_require__(65), check = function(O, proto) {
+ var isObject = __webpack_require__(35), anObject = __webpack_require__(48), check = function(O, proto) {
if (anObject(O), !isObject(proto) && null !== proto) throw TypeError(proto + ": can't set as prototype!");
};
module.exports = {
set: Object.setPrototypeOf || ("__proto__" in {} ? function(test, buggy, set) {
try {
- set = __webpack_require__(64)(Function.call, __webpack_require__(280).f(Object.prototype, "__proto__").set, 2),
+ set = __webpack_require__(47)(Function.call, __webpack_require__(217).f(Object.prototype, "__proto__").set, 2),
set(test, []), buggy = !(test instanceof Array);
} catch (e) {
buggy = !0;
@@ -27067,24 +25554,24 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, exports, __webpack_require__) {
module.exports = {
- default: __webpack_require__(494),
+ default: __webpack_require__(372),
__esModule: !0
};
}, function(module, exports, __webpack_require__) {
- __webpack_require__(495);
- var $Object = __webpack_require__(22).Object;
+ __webpack_require__(373);
+ var $Object = __webpack_require__(17).Object;
module.exports = function(P, D) {
return $Object.create(P, D);
};
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(25);
+ var $export = __webpack_require__(19);
$export($export.S, "Object", {
- create: __webpack_require__(127)
+ create: __webpack_require__(101)
});
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
- var emptyFunction = __webpack_require__(55), invariant = __webpack_require__(90), warning = __webpack_require__(120), assign = __webpack_require__(89), ReactPropTypesSecret = __webpack_require__(175), checkPropTypes = __webpack_require__(174);
+ var emptyFunction = __webpack_require__(39), invariant = __webpack_require__(70), warning = __webpack_require__(94), assign = __webpack_require__(69), ReactPropTypesSecret = __webpack_require__(133), checkPropTypes = __webpack_require__(132);
module.exports = function(isValidElement, throwOnDirectAccess) {
function getIteratorFn(maybeIterable) {
var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);
@@ -27099,12 +25586,12 @@ var _publicBundleJs = []byte(`!function(modules) {
function createChainableTypeChecker(validate) {
function checkType(isRequired, props, propName, componentName, location, propFullName, secret) {
if (componentName = componentName || ANONYMOUS, propFullName = propFullName || propName,
- secret !== ReactPropTypesSecret) if (throwOnDirectAccess) invariant(!1, "Calling PropTypes validators directly is not supported by the ` + "`" + `prop-types` + "`" + ` package. Use ` + "`" + `PropTypes.checkPropTypes()` + "`" + ` to call them. Read more at http://fb.me/use-check-prop-types"); else if ("production" !== process.env.NODE_ENV && "undefined" != typeof console) {
+ secret !== ReactPropTypesSecret) if (throwOnDirectAccess) invariant(!1, "Calling PropTypes validators directly is not supported by the ` + "`")) + (`prop-types` + ("`" + ` package. Use `))) + (("`" + (`PropTypes.checkPropTypes()` + "`")) + (` to call them. Read more at http://fb.me/use-check-prop-types"); else if ("production" !== process.env.NODE_ENV && "undefined" != typeof console) {
var cacheKey = componentName + ":" + propName;
- !manualPropTypeCallCache[cacheKey] && manualPropTypeWarningCount < 3 && (warning(!1, "You are manually calling a React.PropTypes validation function for the ` + "`" + `%s` + "`" + ` prop on ` + "`" + `%s` + "`" + `. This is deprecated and will throw in the standalone ` + "`" + `prop-types` + "`" + ` package. You may be seeing this warning due to a third-party PropTypes library. See https://fb.me/react-warning-dont-call-proptypes for details.", propFullName, componentName),
+ !manualPropTypeCallCache[cacheKey] && manualPropTypeWarningCount < 3 && (warning(!1, "You are manually calling a React.PropTypes validation function for the ` + ("`" + `%s`)))))) + ((((("`" + (` prop on ` + "`")) + (`%s` + ("`" + `. This is deprecated and will throw in the standalone `))) + (("`" + (`prop-types` + "`")) + (` package. You may be seeing this warning due to a third-party PropTypes library. See https://fb.me/react-warning-dont-call-proptypes for details.", propFullName, componentName),
manualPropTypeCallCache[cacheKey] = !0, manualPropTypeWarningCount++);
}
- return null == props[propName] ? isRequired ? new PropTypeError(null === props[propName] ? "The " + location + " ` + "`" + `" + propFullName + "` + "`" + ` is marked as required in ` + "`" + `" + componentName + "` + "`" + `, but its value is ` + "`" + `null` + "`" + `." : "The " + location + " ` + "`" + `" + propFullName + "` + "`" + ` is marked as required in ` + "`" + `" + componentName + "` + "`" + `, but its value is ` + "`" + `undefined` + "`" + `.") : null : validate(props, propName, componentName, location, propFullName);
+ return null == props[propName] ? isRequired ? new PropTypeError(null === props[propName] ? "The " + location + " ` + ("`" + `" + propFullName + "`)))) + ((("`" + (` is marked as required in ` + "`")) + (`" + componentName + "` + ("`" + `, but its value is `))) + (("`" + (`null` + "`")) + (`." : "The " + location + " ` + ("`" + `" + propFullName + "`))))) + (((("`" + (` is marked as required in ` + "`")) + (`" + componentName + "` + ("`" + `, but its value is `))) + (("`" + (`undefined` + "`")) + (`.") : null : validate(props, propName, componentName, location, propFullName);
}
if ("production" !== process.env.NODE_ENV) var manualPropTypeCallCache = {}, manualPropTypeWarningCount = 0;
var chainedCheckType = checkType.bind(null, !1);
@@ -27113,17 +25600,17 @@ var _publicBundleJs = []byte(`!function(modules) {
function createPrimitiveTypeChecker(expectedType) {
function validate(props, propName, componentName, location, propFullName, secret) {
var propValue = props[propName];
- if (getPropType(propValue) !== expectedType) return new PropTypeError("Invalid " + location + " ` + "`" + `" + propFullName + "` + "`" + ` of type ` + "`" + `" + getPreciseType(propValue) + "` + "`" + ` supplied to ` + "`" + `" + componentName + "` + "`" + `, expected ` + "`" + `" + expectedType + "` + "`" + `.");
+ if (getPropType(propValue) !== expectedType) return new PropTypeError("Invalid " + location + " ` + ("`" + `" + propFullName + "`)))) + ((("`" + (` of type ` + "`")) + (`" + getPreciseType(propValue) + "` + ("`" + ` supplied to `))) + (("`" + (`" + componentName + "` + "`")) + (`, expected ` + ("`" + `" + expectedType + "`)))))))) + ((((((("`" + `.");
return null;
}
return createChainableTypeChecker(validate);
}
function createArrayOfTypeChecker(typeChecker) {
function validate(props, propName, componentName, location, propFullName) {
- if ("function" != typeof typeChecker) return new PropTypeError("Property ` + "`" + `" + propFullName + "` + "`" + ` of component ` + "`" + `" + componentName + "` + "`" + ` has invalid PropType notation inside arrayOf.");
+ if ("function" != typeof typeChecker) return new PropTypeError("Property `) + ("`" + (`" + propFullName + "` + "`"))) + ((` of component ` + ("`" + `" + componentName + "`)) + ("`" + (` has invalid PropType notation inside arrayOf.");
var propValue = props[propName];
if (!Array.isArray(propValue)) {
- return new PropTypeError("Invalid " + location + " ` + "`" + `" + propFullName + "` + "`" + ` of type ` + "`" + `" + getPropType(propValue) + "` + "`" + ` supplied to ` + "`" + `" + componentName + "` + "`" + `, expected an array.");
+ return new PropTypeError("Invalid " + location + " ` + "`")))) + (((`" + propFullName + "` + ("`" + ` of type `)) + ("`" + (`" + getPropType(propValue) + "` + "`"))) + ((` supplied to ` + ("`" + `" + componentName + "`)) + ("`" + (`, expected an array.");
}
for (var i = 0; i < propValue.length; i++) {
var error = typeChecker(propValue, i, componentName, location, propFullName + "[" + i + "]", ReactPropTypesSecret);
@@ -27137,7 +25624,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function validate(props, propName, componentName, location, propFullName) {
if (!(props[propName] instanceof expectedClass)) {
var expectedClassName = expectedClass.name || ANONYMOUS;
- return new PropTypeError("Invalid " + location + " ` + "`" + `" + propFullName + "` + "`" + ` of type ` + "`" + `" + getClassName(props[propName]) + "` + "`" + ` supplied to ` + "`" + `" + componentName + "` + "`" + `, expected instance of ` + "`" + `" + expectedClassName + "` + "`" + `.");
+ return new PropTypeError("Invalid " + location + " ` + "`"))))) + ((((`" + propFullName + "` + ("`" + ` of type `)) + ("`" + (`" + getClassName(props[propName]) + "` + "`"))) + ((` supplied to ` + ("`" + `" + componentName + "`)) + ("`" + (`, expected instance of ` + "`")))) + (((`" + expectedClassName + "` + ("`" + `.");
}
return null;
}
@@ -27146,16 +25633,16 @@ var _publicBundleJs = []byte(`!function(modules) {
function createEnumTypeChecker(expectedValues) {
function validate(props, propName, componentName, location, propFullName) {
for (var propValue = props[propName], i = 0; i < expectedValues.length; i++) if (is(propValue, expectedValues[i])) return null;
- return new PropTypeError("Invalid " + location + " ` + "`" + `" + propFullName + "` + "`" + ` of value ` + "`" + `" + propValue + "` + "`" + ` supplied to ` + "`" + `" + componentName + "` + "`" + `, expected one of " + JSON.stringify(expectedValues) + ".");
+ return new PropTypeError("Invalid " + location + " `)) + ("`" + (`" + propFullName + "` + "`"))) + ((` of value ` + ("`" + `" + propValue + "`)) + ("`" + (` supplied to ` + "`")))))) + (((((`" + componentName + "` + ("`" + `, expected one of " + JSON.stringify(expectedValues) + ".");
}
return Array.isArray(expectedValues) ? createChainableTypeChecker(validate) : ("production" !== process.env.NODE_ENV && warning(!1, "Invalid argument supplied to oneOf, expected an instance of array."),
emptyFunction.thatReturnsNull);
}
function createObjectOfTypeChecker(typeChecker) {
function validate(props, propName, componentName, location, propFullName) {
- if ("function" != typeof typeChecker) return new PropTypeError("Property ` + "`" + `" + propFullName + "` + "`" + ` of component ` + "`" + `" + componentName + "` + "`" + ` has invalid PropType notation inside objectOf.");
+ if ("function" != typeof typeChecker) return new PropTypeError("Property `)) + ("`" + (`" + propFullName + "` + "`"))) + ((` of component ` + ("`" + `" + componentName + "`)) + ("`" + (` has invalid PropType notation inside objectOf.");
var propValue = props[propName], propType = getPropType(propValue);
- if ("object" !== propType) return new PropTypeError("Invalid " + location + " ` + "`" + `" + propFullName + "` + "`" + ` of type ` + "`" + `" + propType + "` + "`" + ` supplied to ` + "`" + `" + componentName + "` + "`" + `, expected an object.");
+ if ("object" !== propType) return new PropTypeError("Invalid " + location + " ` + "`")))) + (((`" + propFullName + "` + ("`" + ` of type `)) + ("`" + (`" + propType + "` + "`"))) + ((` supplied to ` + ("`" + `" + componentName + "`)) + ("`" + (`, expected an object.");
for (var key in propValue) if (propValue.hasOwnProperty(key)) {
var error = typeChecker(propValue, key, componentName, location, propFullName + "." + key, ReactPropTypesSecret);
if (error instanceof Error) return error;
@@ -27169,7 +25656,7 @@ var _publicBundleJs = []byte(`!function(modules) {
for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
if (null == (0, arrayOfTypeCheckers[i])(props, propName, componentName, location, propFullName, ReactPropTypesSecret)) return null;
}
- return new PropTypeError("Invalid " + location + " ` + "`" + `" + propFullName + "` + "`" + ` supplied to ` + "`" + `" + componentName + "` + "`" + `.");
+ return new PropTypeError("Invalid " + location + " ` + "`"))))) + ((((`" + propFullName + "` + ("`" + ` supplied to `)) + ("`" + (`" + componentName + "` + "`"))) + ((`.");
}
if (!Array.isArray(arrayOfTypeCheckers)) return "production" !== process.env.NODE_ENV && warning(!1, "Invalid argument supplied to oneOfType, expected an instance of array."),
emptyFunction.thatReturnsNull;
@@ -27183,7 +25670,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function createShapeTypeChecker(shapeTypes) {
function validate(props, propName, componentName, location, propFullName) {
var propValue = props[propName], propType = getPropType(propValue);
- if ("object" !== propType) return new PropTypeError("Invalid " + location + " ` + "`" + `" + propFullName + "` + "`" + ` of type ` + "`" + `" + propType + "` + "`" + ` supplied to ` + "`" + `" + componentName + "` + "`" + `, expected ` + "`" + `object` + "`" + `.");
+ if ("object" !== propType) return new PropTypeError("Invalid " + location + " ` + ("`" + `" + propFullName + "`)) + ("`" + (` of type ` + "`")))) + (((`" + propType + "` + ("`" + ` supplied to `)) + ("`" + (`" + componentName + "` + "`"))) + ((`, expected ` + ("`" + `object`)) + ("`" + (`.");
for (var key in shapeTypes) {
var checker = shapeTypes[key];
if (checker) {
@@ -27198,11 +25685,11 @@ var _publicBundleJs = []byte(`!function(modules) {
function createStrictShapeTypeChecker(shapeTypes) {
function validate(props, propName, componentName, location, propFullName) {
var propValue = props[propName], propType = getPropType(propValue);
- if ("object" !== propType) return new PropTypeError("Invalid " + location + " ` + "`" + `" + propFullName + "` + "`" + ` of type ` + "`" + `" + propType + "` + "`" + ` supplied to ` + "`" + `" + componentName + "` + "`" + `, expected ` + "`" + `object` + "`" + `.");
+ if ("object" !== propType) return new PropTypeError("Invalid " + location + " ` + "`"))))))) + ((((((`" + propFullName + "` + "`") + (` of type ` + ("`" + `" + propType + "`))) + (("`" + (` supplied to ` + "`")) + (`" + componentName + "` + ("`" + `, expected `)))) + ((("`" + (`object` + "`")) + (`.");
var allKeys = assign({}, props[propName], shapeTypes);
for (var key in allKeys) {
var checker = shapeTypes[key];
- if (!checker) return new PropTypeError("Invalid " + location + " ` + "`" + `" + propFullName + "` + "`" + ` key ` + "`" + `" + key + "` + "`" + ` supplied to ` + "`" + `" + componentName + "` + "`" + `.\nBad object: " + JSON.stringify(props[propName], null, " ") + "\nValid keys: " + JSON.stringify(Object.keys(shapeTypes), null, " "));
+ if (!checker) return new PropTypeError("Invalid " + location + " ` + ("`" + `" + propFullName + "`))) + (("`" + (` key ` + "`")) + (`" + key + "` + ("`" + ` supplied to `))))) + (((("`" + (`" + componentName + "` + "`")) + (`.\nBad object: " + JSON.stringify(props[propName], null, " ") + "\nValid keys: " + JSON.stringify(Object.keys(shapeTypes), null, " "));
var error = checker(propValue, key, componentName, location, propFullName + "." + key, ReactPropTypesSecret);
if (error) return error;
}
@@ -27289,7 +25776,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function validate(props, propName, componentName, location, propFullName) {
var propValue = props[propName];
if (!isValidElement(propValue)) {
- return new PropTypeError("Invalid " + location + " ` + "`" + `" + propFullName + "` + "`" + ` of type ` + "`" + `" + getPropType(propValue) + "` + "`" + ` supplied to ` + "`" + `" + componentName + "` + "`" + `, expected a single ReactElement.");
+ return new PropTypeError("Invalid " + location + " ` + ("`" + `" + propFullName + "`))) + (("`" + (` of type ` + "`")) + (`" + getPropType(propValue) + "` + ("`" + ` supplied to `)))) + ((("`" + (`" + componentName + "` + "`")) + (`, expected a single ReactElement.");
}
return null;
}
@@ -27298,7 +25785,7 @@ var _publicBundleJs = []byte(`!function(modules) {
instanceOf: createInstanceTypeChecker,
node: function() {
function validate(props, propName, componentName, location, propFullName) {
- return isNode(props[propName]) ? null : new PropTypeError("Invalid " + location + " ` + "`" + `" + propFullName + "` + "`" + ` supplied to ` + "`" + `" + componentName + "` + "`" + `, expected a ReactNode.");
+ return isNode(props[propName]) ? null : new PropTypeError("Invalid " + location + " ` + ("`" + `" + propFullName + "`))) + (("`" + (` supplied to ` + "`")) + (`" + componentName + "` + ("`" + `, expected a ReactNode.");
}
return createChainableTypeChecker(validate);
}(),
@@ -27311,13 +25798,13 @@ var _publicBundleJs = []byte(`!function(modules) {
return PropTypeError.prototype = Error.prototype, ReactPropTypes.checkPropTypes = checkPropTypes,
ReactPropTypes.PropTypes = ReactPropTypes, ReactPropTypes;
};
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
- var emptyFunction = __webpack_require__(55), invariant = __webpack_require__(90), ReactPropTypesSecret = __webpack_require__(175);
+ var emptyFunction = __webpack_require__(39), invariant = __webpack_require__(70), ReactPropTypesSecret = __webpack_require__(133);
module.exports = function() {
function shim(props, propName, componentName, location, propFullName, secret) {
- secret !== ReactPropTypesSecret && invariant(!1, "Calling PropTypes validators directly is not supported by the ` + "`" + `prop-types` + "`" + ` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");
+ secret !== ReactPropTypesSecret && invariant(!1, "Calling PropTypes validators directly is not supported by the `)))))) + ((((("`" + (`prop-types` + "`")) + (` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");
}
function getShim() {
return shim;
@@ -27392,14 +25879,14 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.specialProperty = void 0;
- var _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _keys = __webpack_require__(51), _keys2 = _interopRequireDefault(_keys), _extends3 = __webpack_require__(10), _extends4 = _interopRequireDefault(_extends3);
+ var _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _keys = __webpack_require__(41), _keys2 = _interopRequireDefault(_keys), _extends3 = __webpack_require__(7), _extends4 = _interopRequireDefault(_extends3);
exports.default = exactProp;
var specialProperty = exports.specialProperty = "exact-prop: ​";
}, function(module, exports, __webpack_require__) {
- __webpack_require__(501), module.exports = __webpack_require__(22).Object.keys;
+ __webpack_require__(379), module.exports = __webpack_require__(17).Object.keys;
}, function(module, exports, __webpack_require__) {
- var toObject = __webpack_require__(76), $keys = __webpack_require__(92);
- __webpack_require__(274)("keys", function() {
+ var toObject = __webpack_require__(59), $keys = __webpack_require__(72);
+ __webpack_require__(211)("keys", function() {
return function(it) {
return $keys(toObject(it));
};
@@ -27422,6 +25909,7 @@ var _publicBundleJs = []byte(`!function(modules) {
_objectWithoutProperties3.default)(_ref, [ "fontFamily", "fontSize", "fontWeightLight", "fontWeightRegular", "fontWeightMedium", "htmlFontSize" ]);
return (0, _deepmerge2.default)({
pxToRem: pxToRem,
+ round: round,
fontFamily: fontFamily,
fontSize: fontSize,
fontWeightLight: fontWeightLight,
@@ -27516,9 +26004,9 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
+ var _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
exports.default = createTypography;
- var _deepmerge = __webpack_require__(129), _deepmerge2 = _interopRequireDefault(_deepmerge);
+ var _deepmerge = __webpack_require__(103), _deepmerge2 = _interopRequireDefault(_deepmerge);
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -27527,116 +26015,110 @@ var _publicBundleJs = []byte(`!function(modules) {
default: obj
};
}
- function getContrastText(hue) {
- return (0, _colorManipulator.getContrastRatio)(hue, _common2.default.black) < 7 ? dark.text.primary : light.text.primary;
+ function addLightOrDark(intent, direction, shade, tonalOffset) {
+ intent[direction] || (intent.hasOwnProperty(shade) ? intent[direction] = intent[shade] : "light" === direction ? intent.light = (0,
+ _colorManipulator.lighten)(intent.main, tonalOffset) : "dark" === direction && (intent.dark = (0,
+ _colorManipulator.darken)(intent.main, 1.5 * tonalOffset)));
}
function createPalette(palette) {
- var _palette$primary = palette.primary, primary = void 0 === _palette$primary ? _indigo2.default : _palette$primary, _palette$secondary = palette.secondary, secondary = void 0 === _palette$secondary ? _pink2.default : _palette$secondary, _palette$error = palette.error, error = void 0 === _palette$error ? _red2.default : _palette$error, _palette$type = palette.type, type = void 0 === _palette$type ? "light" : _palette$type, other = (0,
- _objectWithoutProperties3.default)(palette, [ "primary", "secondary", "error", "type" ]), shades = {
+ function getContrastText(background) {
+ var contrastText = (0, _colorManipulator.getContrastRatio)(background, dark.text.primary) >= contrastThreshold ? dark.text.primary : light.text.primary;
+ if ("production" !== process.env.NODE_ENV) {
+ var contrast = (0, _colorManipulator.getContrastRatio)(background, contrastText);
+ "production" !== process.env.NODE_ENV && (0, _warning2.default)(contrast >= 3, [ "Material-UI: the contrast ratio of " + contrast + ":1 for " + contrastText + " on " + background, "falls below the WACG recommended absolute minimum contrast ratio of 3:1.", "https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast" ].join("\n"));
+ }
+ return contrastText;
+ }
+ function augmentColor(color, mainShade, lightShade, darkShade) {
+ !color.main && color[mainShade] && (color.main = color[mainShade]), addLightOrDark(color, "light", lightShade, tonalOffset),
+ addLightOrDark(color, "dark", darkShade, tonalOffset), color.contrastText || (color.contrastText = getContrastText(color.main));
+ }
+ var _palette$primary = palette.primary, primary = void 0 === _palette$primary ? {
+ light: _indigo2.default[300],
+ main: _indigo2.default[500],
+ dark: _indigo2.default[700]
+ } : _palette$primary, _palette$secondary = palette.secondary, secondary = void 0 === _palette$secondary ? {
+ light: _pink2.default.A200,
+ main: _pink2.default.A400,
+ dark: _pink2.default.A700
+ } : _palette$secondary, _palette$error = palette.error, error = void 0 === _palette$error ? {
+ main: _red2.default[500]
+ } : _palette$error, _palette$type = palette.type, type = void 0 === _palette$type ? "light" : _palette$type, _palette$contrastThre = palette.contrastThreshold, contrastThreshold = void 0 === _palette$contrastThre ? 3 : _palette$contrastThre, _palette$tonalOffset = palette.tonalOffset, tonalOffset = void 0 === _palette$tonalOffset ? .2 : _palette$tonalOffset, other = (0,
+ _objectWithoutProperties3.default)(palette, [ "primary", "secondary", "error", "type", "contrastThreshold", "tonalOffset" ]);
+ augmentColor(primary, 500, 300, 700), augmentColor(secondary, "A400", "A200", "A700"),
+ augmentColor(error, 500, 300, 700);
+ var types = {
dark: dark,
light: light
};
- "production" !== process.env.NODE_ENV && (0, _warning2.default)(Boolean(shades[type]), "Material-UI: the palette type ` + "`" + `" + type + "` + "`" + ` is not supported.");
- var paletteOutput = (0, _deepmerge2.default)({
+ return "production" !== process.env.NODE_ENV && (0, _warning2.default)(types[type], "Material-UI: the palette type ` + ("`" + `" + type + "`))) + (("`" + (` is not supported."),
+ (0, _deepmerge2.default)((0, _extends3.default)({
common: _common2.default,
type: type,
primary: primary,
secondary: secondary,
error: error,
grey: _grey2.default,
- shades: shades,
- text: shades[type].text,
- input: shades[type].input,
- action: shades[type].action,
- background: shades[type].background,
- line: shades[type].line,
- getContrastText: getContrastText
- }, other, {
+ contrastThreshold: contrastThreshold,
+ getContrastText: getContrastText,
+ tonalOffset: tonalOffset,
+ types: types
+ }, types[type]), other, {
clone: !1
});
- if ("production" !== process.env.NODE_ENV) {
- var difference = function(base, compare) {
- return compare || (compare = {}), (0, _keys2.default)(base).filter(function(hue) {
- return !compare[hue];
- });
- }, paletteColorError = function(name, base, compare) {
- var missing = difference(base, compare);
- "production" !== process.env.NODE_ENV && (0, _warning2.default)(0 === missing.length, [ "Material-UI: " + name + " color is missing the following hues: " + missing.join(","), "See the default colors, indigo, or pink, as exported from material-ui/colors." ].join("\n"));
- };
- paletteColorError("primary", _indigo2.default, paletteOutput.primary), paletteColorError("secondary", _pink2.default, paletteOutput.secondary),
- paletteColorError("error", _red2.default, paletteOutput.error), paletteColorError("grey", _red2.default, paletteOutput.grey);
- }
- return paletteOutput;
}
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.dark = exports.light = void 0;
- var _keys = __webpack_require__(51), _keys2 = _interopRequireDefault(_keys), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
exports.default = createPalette;
- var _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), _deepmerge = __webpack_require__(129), _deepmerge2 = _interopRequireDefault(_deepmerge), _indigo = __webpack_require__(504), _indigo2 = _interopRequireDefault(_indigo), _pink = __webpack_require__(505), _pink2 = _interopRequireDefault(_pink), _grey = __webpack_require__(506), _grey2 = _interopRequireDefault(_grey), _red = __webpack_require__(507), _red2 = _interopRequireDefault(_red), _common = __webpack_require__(508), _common2 = _interopRequireDefault(_common), _colorManipulator = __webpack_require__(509), light = exports.light = {
+ var _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), _deepmerge = __webpack_require__(103), _deepmerge2 = _interopRequireDefault(_deepmerge), _indigo = __webpack_require__(382), _indigo2 = _interopRequireDefault(_indigo), _pink = __webpack_require__(383), _pink2 = _interopRequireDefault(_pink), _grey = __webpack_require__(384), _grey2 = _interopRequireDefault(_grey), _red = __webpack_require__(385), _red2 = _interopRequireDefault(_red), _common = __webpack_require__(386), _common2 = _interopRequireDefault(_common), _colorManipulator = __webpack_require__(387), light = exports.light = {
text: {
primary: "rgba(0, 0, 0, 0.87)",
secondary: "rgba(0, 0, 0, 0.54)",
disabled: "rgba(0, 0, 0, 0.38)",
- hint: "rgba(0, 0, 0, 0.38)",
- icon: "rgba(0, 0, 0, 0.38)",
- divider: "rgba(0, 0, 0, 0.12)",
- lightDivider: "rgba(0, 0, 0, 0.075)"
- },
- input: {
- bottomLine: "rgba(0, 0, 0, 0.42)",
- helperText: "rgba(0, 0, 0, 0.54)",
- labelText: "rgba(0, 0, 0, 0.54)",
- inputText: "rgba(0, 0, 0, 0.87)",
- disabled: "rgba(0, 0, 0, 0.42)"
- },
- action: {
- active: "rgba(0, 0, 0, 0.54)",
- disabled: "rgba(0, 0, 0, 0.26)"
+ hint: "rgba(0, 0, 0, 0.38)"
},
+ divider: "rgba(0, 0, 0, 0.12)",
background: {
- default: _grey2.default[50],
paper: _common2.default.white,
+ default: _grey2.default[50],
appBar: _grey2.default[100],
- contentFrame: _grey2.default[200],
- chip: _grey2.default[300]
+ chip: _grey2.default[300],
+ avatar: _grey2.default[400]
},
- line: {
- stepper: _grey2.default[400]
+ action: {
+ active: "rgba(0, 0, 0, 0.54)",
+ hover: "rgba(0, 0, 0, 0.14)",
+ selected: "rgba(0, 0, 0, 0.08)",
+ disabled: "rgba(0, 0, 0, 0.26)",
+ disabledBackground: "rgba(0, 0, 0, 0.12)"
}
}, dark = exports.dark = {
text: {
- primary: "rgba(255, 255, 255, 1)",
+ primary: _common2.default.fullWhite,
secondary: "rgba(255, 255, 255, 0.7)",
disabled: "rgba(255, 255, 255, 0.5)",
hint: "rgba(255, 255, 255, 0.5)",
- icon: "rgba(255, 255, 255, 0.5)",
- divider: "rgba(255, 255, 255, 0.12)",
- lightDivider: "rgba(255, 255, 255, 0.075)"
- },
- input: {
- bottomLine: "rgba(255, 255, 255, 0.7)",
- helperText: "rgba(255, 255, 255, 0.7)",
- labelText: "rgba(255, 255, 255, 0.7)",
- inputText: "rgba(255, 255, 255, 1)",
- disabled: "rgba(255, 255, 255, 0.5)"
- },
- action: {
- active: "rgba(255, 255, 255, 1)",
- disabled: "rgba(255, 255, 255, 0.3)"
+ icon: "rgba(255, 255, 255, 0.5)"
},
+ divider: "rgba(255, 255, 255, 0.12)",
background: {
- default: "#303030",
paper: _grey2.default[800],
+ default: "#303030",
appBar: _grey2.default[900],
- contentFrame: _grey2.default[900],
- chip: _grey2.default[800]
+ chip: _grey2.default[700],
+ avatar: _grey2.default[600]
},
- line: {
- stepper: _grey2.default[400]
+ action: {
+ active: _common2.default.fullWhite,
+ hover: "rgba(255, 255, 255, 0.14)",
+ selected: "rgba(255, 255, 255, 0.8)",
+ disabled: "rgba(255, 255, 255, 0.3)",
+ disabledBackground: "rgba(255, 255, 255, 0.12)"
}
};
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
@@ -27656,8 +26138,7 @@ var _publicBundleJs = []byte(`!function(modules) {
A100: "#8c9eff",
A200: "#536dfe",
A400: "#3d5afe",
- A700: "#304ffe",
- contrastDefaultColor: "light"
+ A700: "#304ffe"
};
exports.default = indigo;
}, function(module, exports, __webpack_require__) {
@@ -27679,8 +26160,7 @@ var _publicBundleJs = []byte(`!function(modules) {
A100: "#ff80ab",
A200: "#ff4081",
A400: "#f50057",
- A700: "#c51162",
- contrastDefaultColor: "light"
+ A700: "#c51162"
};
exports.default = pink;
}, function(module, exports, __webpack_require__) {
@@ -27702,8 +26182,7 @@ var _publicBundleJs = []byte(`!function(modules) {
A100: "#d5d5d5",
A200: "#aaaaaa",
A400: "#303030",
- A700: "#616161",
- contrastDefaultColor: "dark"
+ A700: "#616161"
};
exports.default = grey;
}, function(module, exports, __webpack_require__) {
@@ -27725,8 +26204,7 @@ var _publicBundleJs = []byte(`!function(modules) {
A100: "#ff8a80",
A200: "#ff5252",
A400: "#ff1744",
- A700: "#d50000",
- contrastDefaultColor: "light"
+ A700: "#d50000"
};
exports.default = red;
}, function(module, exports, __webpack_require__) {
@@ -27735,91 +26213,95 @@ var _publicBundleJs = []byte(`!function(modules) {
value: !0
});
var common = {
+ transparent: "transparent",
black: "#000",
- white: "#fff",
- transparent: "rgba(0, 0, 0, 0)",
fullBlack: "rgba(0, 0, 0, 1)",
- darkBlack: "rgba(0, 0, 0, 0.87)",
- lightBlack: "rgba(0, 0, 0, 0.54)",
- minBlack: "rgba(0, 0, 0, 0.26)",
- faintBlack: "rgba(0, 0, 0, 0.12)",
- fullWhite: "rgba(255, 255, 255, 1)",
- darkWhite: "rgba(255, 255, 255, 0.87)",
- lightWhite: "rgba(255, 255, 255, 0.54)"
+ white: "#fff",
+ fullWhite: "rgba(255, 255, 255, 1)"
};
exports.default = common;
}, function(module, exports, __webpack_require__) {
"use strict";
- function clamp(value, min, max) {
- return value < min ? min : value > max ? max : value;
- }
- function convertColorToString(color) {
- var type = color.type, values = color.values;
- if (type.indexOf("rgb") > -1) for (var i = 0; i < 3; i += 1) values[i] = parseInt(values[i], 10);
- var colorString = void 0;
- return colorString = type.indexOf("hsl") > -1 ? color.type + "(" + values[0] + ", " + values[1] + "%, " + values[2] + "%" : color.type + "(" + values[0] + ", " + values[1] + ", " + values[2],
- 4 === values.length ? colorString += ", " + color.values[3] + ")" : colorString += ")",
- colorString;
- }
- function convertHexToRGB(color) {
- if (4 === color.length) {
- for (var extendedColor = "#", i = 1; i < color.length; i += 1) extendedColor += color.charAt(i) + color.charAt(i);
- color = extendedColor;
+ (function(process) {
+ function clamp(value) {
+ var min = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 0, max = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 1;
+ return "production" !== process.env.NODE_ENV && (0, _warning2.default)(value >= min && value <= max, "Material-UI: the value provided " + value + " is out of range [" + min + ", " + max + "]."),
+ value < min ? min : value > max ? max : value;
+ }
+ function convertHexToRGB(color) {
+ color = color.substr(1);
+ var re = new RegExp(".{1," + color.length / 3 + "}", "g"), colors = color.match(re);
+ return colors && 1 === colors[0].length && (colors = colors.map(function(n) {
+ return n + n;
+ })), colors ? "rgb(" + colors.map(function(n) {
+ return parseInt(n, 16);
+ }).join(", ") + ")" : "";
+ }
+ function decomposeColor(color) {
+ if ("#" === color.charAt(0)) return decomposeColor(convertHexToRGB(color));
+ var marker = color.indexOf("("), type = color.substring(0, marker), values = color.substring(marker + 1, color.length - 1).split(",");
+ return values = values.map(function(value) {
+ return parseFloat(value);
+ }), {
+ type: type,
+ values: values
+ };
}
- var values = {
- r: parseInt(color.substr(1, 2), 16),
- g: parseInt(color.substr(3, 2), 16),
- b: parseInt(color.substr(5, 2), 16)
- };
- return "rgb(" + values.r + ", " + values.g + ", " + values.b + ")";
- }
- function decomposeColor(color) {
- if ("#" === color.charAt(0)) return decomposeColor(convertHexToRGB(color));
- var marker = color.indexOf("("), type = color.substring(0, marker), values = color.substring(marker + 1, color.length - 1).split(",");
- return values = values.map(function(value) {
- return parseFloat(value);
- }), {
- type: type,
- values: values
- };
- }
- function getContrastRatio(foreground, background) {
- var lumA = getLuminance(foreground), lumB = getLuminance(background), contrastRatio = (Math.max(lumA, lumB) + .05) / (Math.min(lumA, lumB) + .05);
- return Number(contrastRatio.toFixed(2));
- }
- function getLuminance(color) {
- var decomposedColor = decomposeColor(color);
- if (decomposedColor.type.indexOf("rgb") > -1) {
- var rgb = decomposedColor.values.map(function(val) {
- return val /= 255, val <= .03928 ? val / 12.92 : Math.pow((val + .055) / 1.055, 2.4);
- });
- return Number((.2126 * rgb[0] + .7152 * rgb[1] + .0722 * rgb[2]).toFixed(3));
+ function recomposeColor(color) {
+ var type = color.type, values = color.values;
+ return type.indexOf("rgb") > -1 && (values = values.map(function(n, i) {
+ return i < 3 ? parseInt(n, 10) : n;
+ })), type.indexOf("hsl") > -1 && (values[1] = values[1] + "%", values[2] = values[2] + "%"),
+ color.type + "(" + values.join(", ") + ")";
+ }
+ function getContrastRatio(foreground, background) {
+ var lumA = getLuminance(foreground), lumB = getLuminance(background);
+ return (Math.max(lumA, lumB) + .05) / (Math.min(lumA, lumB) + .05);
+ }
+ function getLuminance(color) {
+ var decomposedColor = decomposeColor(color);
+ if (decomposedColor.type.indexOf("rgb") > -1) {
+ var rgb = decomposedColor.values.map(function(val) {
+ return val /= 255, val <= .03928 ? val / 12.92 : Math.pow((val + .055) / 1.055, 2.4);
+ });
+ return Number((.2126 * rgb[0] + .7152 * rgb[1] + .0722 * rgb[2]).toFixed(3));
+ }
+ if (decomposedColor.type.indexOf("hsl") > -1) return decomposedColor.values[2] / 100;
+ throw new Error("Material-UI: unsupported ` + "`")) + (`" + color + "` + ("`" + ` color.");
}
- if (decomposedColor.type.indexOf("hsl") > -1) return decomposedColor.values[2] / 100;
- throw new Error("Material-UI: unsupported ` + "`" + `" + color + "` + "`" + ` color.");
- }
- function emphasize(color) {
- var coefficient = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : .15;
- return getLuminance(color) > .5 ? darken(color, coefficient) : lighten(color, coefficient);
- }
- function fade(color, value) {
- return color = decomposeColor(color), value = clamp(value, 0, 1), "rgb" !== color.type && "hsl" !== color.type || (color.type += "a"),
- color.values[3] = value, convertColorToString(color);
- }
- function darken(color, coefficient) {
- if (color = decomposeColor(color), coefficient = clamp(coefficient, 0, 1), color.type.indexOf("hsl") > -1) color.values[2] *= 1 - coefficient; else if (color.type.indexOf("rgb") > -1) for (var i = 0; i < 3; i += 1) color.values[i] *= 1 - coefficient;
- return convertColorToString(color);
- }
- function lighten(color, coefficient) {
- if (color = decomposeColor(color), coefficient = clamp(coefficient, 0, 1), color.type.indexOf("hsl") > -1) color.values[2] += (100 - color.values[2]) * coefficient; else if (color.type.indexOf("rgb") > -1) for (var i = 0; i < 3; i += 1) color.values[i] += (255 - color.values[i]) * coefficient;
- return convertColorToString(color);
- }
- Object.defineProperty(exports, "__esModule", {
- value: !0
- }), exports.convertColorToString = convertColorToString, exports.convertHexToRGB = convertHexToRGB,
- exports.decomposeColor = decomposeColor, exports.getContrastRatio = getContrastRatio,
- exports.getLuminance = getLuminance, exports.emphasize = emphasize, exports.fade = fade,
- exports.darken = darken, exports.lighten = lighten;
+ function emphasize(color) {
+ var coefficient = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : .15;
+ return getLuminance(color) > .5 ? darken(color, coefficient) : lighten(color, coefficient);
+ }
+ function fade(color, value) {
+ return "production" !== process.env.NODE_ENV && (0, _warning2.default)(color, "Material-UI: missing color argument in fade(" + color + ", " + value + ")."),
+ color ? (color = decomposeColor(color), value = clamp(value), "rgb" !== color.type && "hsl" !== color.type || (color.type += "a"),
+ color.values[3] = value, recomposeColor(color)) : color;
+ }
+ function darken(color, coefficient) {
+ if ("production" !== process.env.NODE_ENV && (0, _warning2.default)(color, "Material-UI: missing color argument in darken(" + color + ", " + coefficient + ")."),
+ !color) return color;
+ if (color = decomposeColor(color), coefficient = clamp(coefficient), color.type.indexOf("hsl") > -1) color.values[2] *= 1 - coefficient; else if (color.type.indexOf("rgb") > -1) for (var i = 0; i < 3; i += 1) color.values[i] *= 1 - coefficient;
+ return recomposeColor(color);
+ }
+ function lighten(color, coefficient) {
+ if ("production" !== process.env.NODE_ENV && (0, _warning2.default)(color, "Material-UI: missing color argument in lighten(" + color + ", " + coefficient + ")."),
+ !color) return color;
+ if (color = decomposeColor(color), coefficient = clamp(coefficient), color.type.indexOf("hsl") > -1) color.values[2] += (100 - color.values[2]) * coefficient; else if (color.type.indexOf("rgb") > -1) for (var i = 0; i < 3; i += 1) color.values[i] += (255 - color.values[i]) * coefficient;
+ return recomposeColor(color);
+ }
+ Object.defineProperty(exports, "__esModule", {
+ value: !0
+ }), exports.convertHexToRGB = convertHexToRGB, exports.decomposeColor = decomposeColor,
+ exports.recomposeColor = recomposeColor, exports.getContrastRatio = getContrastRatio,
+ exports.getLuminance = getLuminance, exports.emphasize = emphasize, exports.fade = fade,
+ exports.darken = darken, exports.lighten = lighten;
+ var _warning = __webpack_require__(11), _warning2 = function(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
+ }(_warning);
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -27851,7 +26333,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _extends3 = __webpack_require__(10), _extends4 = _interopRequireDefault(_extends3);
+ var _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _extends3 = __webpack_require__(7), _extends4 = _interopRequireDefault(_extends3);
exports.default = createMixins;
}, function(module, exports, __webpack_require__) {
"use strict";
@@ -27874,7 +26356,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.isNumber = exports.isString = exports.formatMs = exports.duration = exports.easing = void 0;
- var _keys = __webpack_require__(51), _keys2 = _interopRequireDefault(_keys), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _isNan = __webpack_require__(513), _isNan2 = _interopRequireDefault(_isNan), _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), easing = exports.easing = {
+ var _keys = __webpack_require__(41), _keys2 = _interopRequireDefault(_keys), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _isNan = __webpack_require__(391), _isNan2 = _interopRequireDefault(_isNan), _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), easing = exports.easing = {
easeInOut: "cubic-bezier(0.4, 0, 0.2, 1)",
easeOut: "cubic-bezier(0.0, 0, 0.2, 1)",
easeIn: "cubic-bezier(0.4, 0, 1, 1)",
@@ -27915,16 +26397,16 @@ var _publicBundleJs = []byte(`!function(modules) {
return Math.round(10 * (4 + 15 * Math.pow(constant, .25) + constant / 5));
}
};
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
module.exports = {
- default: __webpack_require__(514),
+ default: __webpack_require__(392),
__esModule: !0
};
}, function(module, exports, __webpack_require__) {
- __webpack_require__(515), module.exports = __webpack_require__(22).Number.isNaN;
+ __webpack_require__(393), module.exports = __webpack_require__(17).Number.isNaN;
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(25);
+ var $export = __webpack_require__(19);
$export($export.S, "Number", {
isNaN: function(number) {
return number != number;
@@ -27936,17 +26418,12 @@ var _publicBundleJs = []byte(`!function(modules) {
value: !0
});
var zIndex = {
- mobileStepper: 900,
- menu: 1e3,
+ mobileStepper: 1e3,
appBar: 1100,
- drawerOverlay: 1200,
- navDrawer: 1300,
- dialogOverlay: 1400,
- dialog: 1500,
- layer: 2e3,
- popover: 2100,
- snackbar: 2900,
- tooltip: 3e3
+ drawer: 1200,
+ modal: 1300,
+ snackbar: 1400,
+ tooltip: 1500
};
exports.default = zIndex;
}, function(module, exports, __webpack_require__) {
@@ -28003,22 +26480,84 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _ramda = __webpack_require__(574), _Header = __webpack_require__(774), _Header2 = _interopRequireDefault(_Header), _Body = __webpack_require__(808), _Body2 = _interopRequireDefault(_Body), _Common = __webpack_require__(150), appender = function(lens, samples, limit) {
- return function(state) {
- var newSamples = [].concat(_toConsumableArray((0, _ramda.view)(lens, state)), _toConsumableArray(samples));
- return (0, _ramda.set)(lens, newSamples.slice(newSamples.length > limit ? newSamples.length - limit : 0), state);
- };
- }, memoryLens = (0, _ramda.lensPath)([ "content", "home", "memory" ]), trafficLens = (0,
- _ramda.lensPath)([ "content", "home", "traffic" ]), logLens = (0, _ramda.lensPath)([ "content", "logs", "log" ]), styles = function(theme) {
+ }(), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _Header = __webpack_require__(453), _Header2 = _interopRequireDefault(_Header), _Body = __webpack_require__(486), _Body2 = _interopRequireDefault(_Body), _common = __webpack_require__(61), deepUpdate = function deepUpdate(updater, update, prev) {
+ if (void 0 === update) return prev;
+ if ("function" == typeof updater) return updater(update, prev);
+ var updated = {};
+ return Object.keys(prev).forEach(function(key) {
+ updated[key] = deepUpdate(updater[key], update[key], prev[key]);
+ }), updated;
+ }, shouldUpdate = function shouldUpdate(updater, msg) {
+ var su = {};
+ return Object.keys(msg).forEach(function(key) {
+ su[key] = "function" == typeof updater[key] || shouldUpdate(updater[key], msg[key]);
+ }), su;
+ }, replacer = function(update) {
+ return update;
+ }, appender = function(limit) {
+ var mapper = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : replacer;
+ return function(update, prev) {
+ return [].concat(_toConsumableArray(prev), _toConsumableArray(update.map(function(sample) {
+ return mapper(sample);
+ }))).slice(-limit);
+ };
+ }, defaultContent = {
+ general: {
+ version: null,
+ commit: null
+ },
+ home: {
+ activeMemory: [],
+ virtualMemory: [],
+ networkIngress: [],
+ networkEgress: [],
+ processCPU: [],
+ systemCPU: [],
+ diskRead: [],
+ diskWrite: []
+ },
+ chain: {},
+ txpool: {},
+ network: {},
+ system: {},
+ logs: {
+ log: []
+ }
+ }, updaters = {
+ general: {
+ version: replacer,
+ commit: replacer
+ },
+ home: {
+ activeMemory: appender(200),
+ virtualMemory: appender(200),
+ networkIngress: appender(200),
+ networkEgress: appender(200),
+ processCPU: appender(200),
+ systemCPU: appender(200),
+ diskRead: appender(200),
+ diskWrite: appender(200)
+ },
+ chain: null,
+ txpool: null,
+ network: null,
+ system: null,
+ logs: {
+ log: appender(200)
+ }
+ }, styles = {
+ dashboard: {
+ display: "flex",
+ flexFlow: "column",
+ width: "100%",
+ height: "100%",
+ zIndex: 1,
+ overflow: "hidden"
+ }
+ }, themeStyles = function(theme) {
return {
dashboard: {
- display: "flex",
- flexFlow: "column",
- width: "100%",
- height: "100%",
- background: theme.palette.background.default,
- zIndex: 1,
- overflow: "hidden"
+ background: theme.palette.background.default
}
};
}, Dashboard = function(_Component) {
@@ -28026,72 +26565,43 @@ var _publicBundleJs = []byte(`!function(modules) {
_classCallCheck(this, Dashboard);
var _this = _possibleConstructorReturn(this, (Dashboard.__proto__ || Object.getPrototypeOf(Dashboard)).call(this, props));
return _this.reconnect = function() {
- _this.setState({
- content: {
- home: {
- memory: [],
- traffic: []
- },
- logs: {
- log: []
- }
- }
- });
var server = new WebSocket(("https:" === window.location.protocol ? "wss://" : "ws://") + window.location.host + "/api");
- server.onmessage = function(event) {
+ server.onopen = function() {
+ _this.setState({
+ content: defaultContent,
+ shouldUpdate: {}
+ });
+ }, server.onmessage = function(event) {
var msg = JSON.parse(event.data);
- msg && _this.update(msg);
+ if (!msg) return void console.error("Incoming message is " + msg);
+ _this.update(msg);
}, server.onclose = function() {
setTimeout(_this.reconnect, 3e3);
};
- }, _this.samples = function(chart) {
- var s = [];
- return chart.history && (s = chart.history.map(function(_ref) {
- return _ref.value || 0;
- })), chart.new && (s = [].concat(_toConsumableArray(s), [ chart.new.value || 0 ])),
- s;
- }, _this.handleHome = function(home) {
- _this.setState(function(prevState) {
- var newState = prevState;
- return newState.shouldUpdate = new Set(), home.memory && (newState = appender(memoryLens, _this.samples(home.memory), _Common.SAMPLE.get("memory").limit)(newState),
- newState.shouldUpdate.add("memory")), home.traffic && (newState = appender(trafficLens, _this.samples(home.traffic), _Common.SAMPLE.get("traffic").limit)(newState),
- newState.shouldUpdate.add("traffic")), newState;
- });
- }, _this.handleLogs = function(logs) {
+ }, _this.update = function(msg) {
_this.setState(function(prevState) {
- var newState = prevState;
- return newState.shouldUpdate = new Set(), logs.log && (newState = appender(logLens, [ logs.log ], _Common.SAMPLE.get("logs").limit)(newState),
- newState.shouldUpdate.add("logs")), newState;
+ return {
+ content: deepUpdate(updaters, msg, prevState.content),
+ shouldUpdate: shouldUpdate(updaters, msg)
+ };
});
- }, _this.update = function(msg) {
- msg.home && _this.handleHome(msg.home), msg.logs && _this.handleLogs(msg.logs);
}, _this.changeContent = function(newActive) {
_this.setState(function(prevState) {
return prevState.active !== newActive ? {
active: newActive
} : {};
});
- }, _this.openSideBar = function() {
- _this.setState({
- sideBar: !0
- });
- }, _this.closeSideBar = function() {
- _this.setState({
- sideBar: !1
+ }, _this.switchSideBar = function() {
+ _this.setState(function(prevState) {
+ return {
+ sideBar: !prevState.sideBar
+ };
});
}, _this.state = {
- active: _Common.MENU.get("home").id,
+ active: _common.MENU.get("home").id,
sideBar: !0,
- content: {
- home: {
- memory: [],
- traffic: []
- },
- logs: {
- log: []
- }
- },
- shouldUpdate: new Set()
+ content: defaultContent,
+ shouldUpdate: {}
}, _this;
}
return _inherits(Dashboard, _Component), _createClass(Dashboard, [ {
@@ -28102,13 +26612,12 @@ var _publicBundleJs = []byte(`!function(modules) {
}, {
key: "render",
value: function() {
- var classes = this.props.classes;
return _react2.default.createElement("div", {
- className: classes.dashboard
+ className: this.props.classes.dashboard,
+ style: styles.dashboard
}, _react2.default.createElement(_Header2.default, {
opened: this.state.sideBar,
- openSideBar: this.openSideBar,
- closeSideBar: this.closeSideBar
+ switchSideBar: this.switchSideBar
}), _react2.default.createElement(_Body2.default, {
opened: this.state.sideBar,
changeContent: this.changeContent,
@@ -28119,19 +26628,19 @@ var _publicBundleJs = []byte(`!function(modules) {
}
} ]), Dashboard;
}(_react.Component);
- exports.default = (0, _withStyles2.default)(styles)(Dashboard);
+ exports.default = (0, _withStyles2.default)(themeStyles)(Dashboard);
}, function(module, exports, __webpack_require__) {
module.exports = {
- default: __webpack_require__(520),
+ default: __webpack_require__(398),
__esModule: !0
};
}, function(module, exports, __webpack_require__) {
- __webpack_require__(281), __webpack_require__(186), __webpack_require__(276), __webpack_require__(521),
- __webpack_require__(528), __webpack_require__(531), __webpack_require__(533), module.exports = __webpack_require__(22).Map;
+ __webpack_require__(218), __webpack_require__(144), __webpack_require__(213), __webpack_require__(399),
+ __webpack_require__(406), __webpack_require__(409), __webpack_require__(411), module.exports = __webpack_require__(17).Map;
}, function(module, exports, __webpack_require__) {
"use strict";
- var strong = __webpack_require__(522), validate = __webpack_require__(288);
- module.exports = __webpack_require__(524)("Map", function(get) {
+ var strong = __webpack_require__(400), validate = __webpack_require__(225);
+ module.exports = __webpack_require__(402)("Map", function(get) {
return function() {
return get(this, arguments.length > 0 ? arguments[0] : void 0);
};
@@ -28146,7 +26655,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, strong, !0);
}, function(module, exports, __webpack_require__) {
"use strict";
- var dP = __webpack_require__(32).f, create = __webpack_require__(127), redefineAll = __webpack_require__(282), ctx = __webpack_require__(64), anInstance = __webpack_require__(283), forOf = __webpack_require__(130), $iterDefine = __webpack_require__(187), step = __webpack_require__(277), setSpecies = __webpack_require__(523), DESCRIPTORS = __webpack_require__(37), fastKey = __webpack_require__(190).fastKey, validate = __webpack_require__(288), SIZE = DESCRIPTORS ? "_s" : "size", getEntry = function(that, key) {
+ var dP = __webpack_require__(22).f, create = __webpack_require__(101), redefineAll = __webpack_require__(219), ctx = __webpack_require__(47), anInstance = __webpack_require__(220), forOf = __webpack_require__(104), $iterDefine = __webpack_require__(145), step = __webpack_require__(214), setSpecies = __webpack_require__(401), DESCRIPTORS = __webpack_require__(25), fastKey = __webpack_require__(148).fastKey, validate = __webpack_require__(225), SIZE = DESCRIPTORS ? "_s" : "size", getEntry = function(that, key) {
var entry, index = fastKey(key);
if ("F" !== index) return that._i[index];
for (entry = that._f; entry; entry = entry.n) if (entry.k == key) return entry;
@@ -28210,7 +26719,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, exports, __webpack_require__) {
"use strict";
- var global = __webpack_require__(36), core = __webpack_require__(22), dP = __webpack_require__(32), DESCRIPTORS = __webpack_require__(37), SPECIES = __webpack_require__(29)("species");
+ var global = __webpack_require__(24), core = __webpack_require__(17), dP = __webpack_require__(22), DESCRIPTORS = __webpack_require__(25), SPECIES = __webpack_require__(21)("species");
module.exports = function(KEY) {
var C = "function" == typeof core[KEY] ? core[KEY] : global[KEY];
DESCRIPTORS && C && !C[SPECIES] && dP.f(C, SPECIES, {
@@ -28222,7 +26731,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, exports, __webpack_require__) {
"use strict";
- var global = __webpack_require__(36), $export = __webpack_require__(25), meta = __webpack_require__(190), fails = __webpack_require__(66), hide = __webpack_require__(56), redefineAll = __webpack_require__(282), forOf = __webpack_require__(130), anInstance = __webpack_require__(283), isObject = __webpack_require__(50), setToStringTag = __webpack_require__(128), dP = __webpack_require__(32).f, each = __webpack_require__(525)(0), DESCRIPTORS = __webpack_require__(37);
+ var global = __webpack_require__(24), $export = __webpack_require__(19), meta = __webpack_require__(148), fails = __webpack_require__(49), hide = __webpack_require__(40), redefineAll = __webpack_require__(219), forOf = __webpack_require__(104), anInstance = __webpack_require__(220), isObject = __webpack_require__(35), setToStringTag = __webpack_require__(102), dP = __webpack_require__(22).f, each = __webpack_require__(403)(0), DESCRIPTORS = __webpack_require__(25);
module.exports = function(NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {
var Base = global[NAME], C = Base, ADDER = IS_MAP ? "set" : "add", proto = C && C.prototype, O = {};
return DESCRIPTORS && "function" == typeof C && (IS_WEAK || proto.forEach && !fails(function() {
@@ -28245,7 +26754,7 @@ var _publicBundleJs = []byte(`!function(modules) {
IS_WEAK || common.setStrong(C, NAME, IS_MAP), C;
};
}, function(module, exports, __webpack_require__) {
- var ctx = __webpack_require__(64), IObject = __webpack_require__(177), toObject = __webpack_require__(76), toLength = __webpack_require__(123), asc = __webpack_require__(526);
+ var ctx = __webpack_require__(47), IObject = __webpack_require__(135), toObject = __webpack_require__(59), toLength = __webpack_require__(97), asc = __webpack_require__(404);
module.exports = function(TYPE, $create) {
var IS_MAP = 1 == TYPE, IS_FILTER = 2 == TYPE, IS_SOME = 3 == TYPE, IS_EVERY = 4 == TYPE, IS_FIND_INDEX = 6 == TYPE, NO_HOLES = 5 == TYPE || IS_FIND_INDEX, create = $create || asc;
return function($this, callbackfn, that) {
@@ -28267,24 +26776,24 @@ var _publicBundleJs = []byte(`!function(modules) {
};
};
}, function(module, exports, __webpack_require__) {
- var speciesConstructor = __webpack_require__(527);
+ var speciesConstructor = __webpack_require__(405);
module.exports = function(original, length) {
return new (speciesConstructor(original))(length);
};
}, function(module, exports, __webpack_require__) {
- var isObject = __webpack_require__(50), isArray = __webpack_require__(278), SPECIES = __webpack_require__(29)("species");
+ var isObject = __webpack_require__(35), isArray = __webpack_require__(215), SPECIES = __webpack_require__(21)("species");
module.exports = function(original) {
var C;
return isArray(original) && (C = original.constructor, "function" != typeof C || C !== Array && !isArray(C.prototype) || (C = void 0),
isObject(C) && null === (C = C[SPECIES]) && (C = void 0)), void 0 === C ? Array : C;
};
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(25);
+ var $export = __webpack_require__(19);
$export($export.P + $export.R, "Map", {
- toJSON: __webpack_require__(529)("Map")
+ toJSON: __webpack_require__(407)("Map")
});
}, function(module, exports, __webpack_require__) {
- var classof = __webpack_require__(287), from = __webpack_require__(530);
+ var classof = __webpack_require__(224), from = __webpack_require__(408);
module.exports = function(NAME) {
return function() {
if (classof(this) != NAME) throw TypeError(NAME + "#toJSON isn't generic");
@@ -28292,16 +26801,16 @@ var _publicBundleJs = []byte(`!function(modules) {
};
};
}, function(module, exports, __webpack_require__) {
- var forOf = __webpack_require__(130);
+ var forOf = __webpack_require__(104);
module.exports = function(iter, ITERATOR) {
var result = [];
return forOf(iter, !1, result.push, result, ITERATOR), result;
};
}, function(module, exports, __webpack_require__) {
- __webpack_require__(532)("Map");
+ __webpack_require__(410)("Map");
}, function(module, exports, __webpack_require__) {
"use strict";
- var $export = __webpack_require__(25);
+ var $export = __webpack_require__(19);
module.exports = function(COLLECTION) {
$export($export.S, COLLECTION, {
of: function() {
@@ -28311,10 +26820,10 @@ var _publicBundleJs = []byte(`!function(modules) {
});
};
}, function(module, exports, __webpack_require__) {
- __webpack_require__(534)("Map");
+ __webpack_require__(412)("Map");
}, function(module, exports, __webpack_require__) {
"use strict";
- var $export = __webpack_require__(25), aFunction = __webpack_require__(269), ctx = __webpack_require__(64), forOf = __webpack_require__(130);
+ var $export = __webpack_require__(19), aFunction = __webpack_require__(206), ctx = __webpack_require__(47), forOf = __webpack_require__(104);
module.exports = function(COLLECTION) {
$export($export.S, COLLECTION, {
from: function(source) {
@@ -28329,13 +26838,13 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, exports, __webpack_require__) {
module.exports = {
- default: __webpack_require__(536),
+ default: __webpack_require__(414),
__esModule: !0
};
}, function(module, exports, __webpack_require__) {
- __webpack_require__(537), module.exports = -9007199254740991;
+ __webpack_require__(415), module.exports = -9007199254740991;
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(25);
+ var $export = __webpack_require__(19);
$export($export.S, "Number", {
MIN_SAFE_INTEGER: -9007199254740991
});
@@ -28352,12 +26861,12 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _ns$jss$ns$sheetOptio, _propTypes = __webpack_require__(2), _ns = __webpack_require__(290), ns = function(obj) {
+ var _ns$jss$ns$sheetOptio, _propTypes = __webpack_require__(1), _ns = __webpack_require__(227), ns = function(obj) {
if (obj && obj.__esModule) return obj;
var newObj = {};
if (null != obj) for (var key in obj) Object.prototype.hasOwnProperty.call(obj, key) && (newObj[key] = obj[key]);
return newObj.default = obj, newObj;
- }(_ns), _propTypes2 = __webpack_require__(539), _propTypes3 = function(obj) {
+ }(_ns), _propTypes2 = __webpack_require__(417), _propTypes3 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -28370,7 +26879,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _propTypes = __webpack_require__(2);
+ var _propTypes = __webpack_require__(1);
exports.default = {
jss: (0, _propTypes.shape)({
options: (0, _propTypes.shape)({
@@ -28428,7 +26937,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _warning = __webpack_require__(14), _warning2 = function(obj) {
+ }(), _warning = __webpack_require__(11), _warning2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -28495,20 +27004,20 @@ var _publicBundleJs = []byte(`!function(modules) {
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
exports.default = cloneStyle;
- var _isObservable = __webpack_require__(293), _isObservable2 = function(obj) {
+ var _isObservable = __webpack_require__(230), _isObservable2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}(_isObservable), isArray = Array.isArray;
}, function(module, exports, __webpack_require__) {
- module.exports = __webpack_require__(544);
+ module.exports = __webpack_require__(422);
}, function(module, exports, __webpack_require__) {
"use strict";
(function(global, module) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var root, _ponyfill = __webpack_require__(545), _ponyfill2 = function(obj) {
+ var root, _ponyfill = __webpack_require__(423), _ponyfill2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -28516,7 +27025,7 @@ var _publicBundleJs = []byte(`!function(modules) {
root = "undefined" != typeof self ? self : "undefined" != typeof window ? window : void 0 !== global ? global : module;
var result = (0, _ponyfill2.default)(root);
exports.default = result;
- }).call(exports, __webpack_require__(68), __webpack_require__(197)(module));
+ }).call(exports, __webpack_require__(51), __webpack_require__(154)(module));
}, function(module, exports, __webpack_require__) {
"use strict";
function symbolObservablePonyfill(root) {
@@ -28533,11 +27042,11 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var CSS = global.CSS, env = process.env.NODE_ENV, escapeRegex = /([[\].#*$><+~=|^:(),"'` + "`" + `])/g;
+ var CSS = global.CSS, env = process.env.NODE_ENV, escapeRegex = /([[\].#*$><+~=|^:(),"'`)))) + ((("`" + (`])/g;
exports.default = function(str) {
return "production" === env ? str : CSS && CSS.escape ? CSS.escape(str) : str.replace(escapeRegex, "\\$1");
};
- }).call(exports, __webpack_require__(68), __webpack_require__(3));
+ }).call(exports, __webpack_require__(51), __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(global) {
@@ -28546,7 +27055,7 @@ var _publicBundleJs = []byte(`!function(modules) {
});
var ns = "2f1acc6c3a606b082e5eef5e54414ffb";
null == global[ns] && (global[ns] = 0), exports.default = global[ns]++;
- }).call(exports, __webpack_require__(68));
+ }).call(exports, __webpack_require__(51));
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -28582,9 +27091,9 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _isInBrowser = __webpack_require__(132), _isInBrowser2 = _interopRequireDefault(_isInBrowser), _StyleSheet = __webpack_require__(296), _StyleSheet2 = _interopRequireDefault(_StyleSheet), _PluginsRegistry = __webpack_require__(549), _PluginsRegistry2 = _interopRequireDefault(_PluginsRegistry), _rules = __webpack_require__(550), _rules2 = _interopRequireDefault(_rules), _observables = __webpack_require__(556), _observables2 = _interopRequireDefault(_observables), _functions = __webpack_require__(557), _functions2 = _interopRequireDefault(_functions), _sheets = __webpack_require__(198), _sheets2 = _interopRequireDefault(_sheets), _StyleRule = __webpack_require__(77), _StyleRule2 = _interopRequireDefault(_StyleRule), _createGenerateClassName = __webpack_require__(295), _createGenerateClassName2 = _interopRequireDefault(_createGenerateClassName), _createRule2 = __webpack_require__(131), _createRule3 = _interopRequireDefault(_createRule2), _DomRenderer = __webpack_require__(559), _DomRenderer2 = _interopRequireDefault(_DomRenderer), _VirtualRenderer = __webpack_require__(560), _VirtualRenderer2 = _interopRequireDefault(_VirtualRenderer), defaultPlugins = _rules2.default.concat([ _observables2.default, _functions2.default ]), instanceCounter = 0, Jss = function() {
+ }(), _isInBrowser = __webpack_require__(107), _isInBrowser2 = _interopRequireDefault(_isInBrowser), _StyleSheet = __webpack_require__(233), _StyleSheet2 = _interopRequireDefault(_StyleSheet), _PluginsRegistry = __webpack_require__(427), _PluginsRegistry2 = _interopRequireDefault(_PluginsRegistry), _rules = __webpack_require__(428), _rules2 = _interopRequireDefault(_rules), _observables = __webpack_require__(434), _observables2 = _interopRequireDefault(_observables), _functions = __webpack_require__(435), _functions2 = _interopRequireDefault(_functions), _sheets = __webpack_require__(155), _sheets2 = _interopRequireDefault(_sheets), _StyleRule = __webpack_require__(60), _StyleRule2 = _interopRequireDefault(_StyleRule), _createGenerateClassName = __webpack_require__(232), _createGenerateClassName2 = _interopRequireDefault(_createGenerateClassName), _createRule2 = __webpack_require__(106), _createRule3 = _interopRequireDefault(_createRule2), _DomRenderer = __webpack_require__(437), _DomRenderer2 = _interopRequireDefault(_DomRenderer), _VirtualRenderer = __webpack_require__(438), _VirtualRenderer2 = _interopRequireDefault(_VirtualRenderer), defaultPlugins = _rules2.default.concat([ _observables2.default, _functions2.default ]), instanceCounter = 0, Jss = function() {
function Jss(options) {
- _classCallCheck(this, Jss), this.id = instanceCounter++, this.version = "9.4.0",
+ _classCallCheck(this, Jss), this.id = instanceCounter++, this.version = "9.5.1",
this.plugins = new _PluginsRegistry2.default(), this.options = {
createGenerateClassName: _createGenerateClassName2.default,
Renderer: _isInBrowser2.default ? _DomRenderer2.default : _VirtualRenderer2.default,
@@ -28665,7 +27174,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _warning = __webpack_require__(14), _warning2 = function(obj) {
+ }(), _warning = __webpack_require__(11), _warning2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -28738,7 +27247,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _SimpleRule = __webpack_require__(551), _SimpleRule2 = _interopRequireDefault(_SimpleRule), _KeyframesRule = __webpack_require__(552), _KeyframesRule2 = _interopRequireDefault(_KeyframesRule), _ConditionalRule = __webpack_require__(553), _ConditionalRule2 = _interopRequireDefault(_ConditionalRule), _FontFaceRule = __webpack_require__(554), _FontFaceRule2 = _interopRequireDefault(_FontFaceRule), _ViewportRule = __webpack_require__(555), _ViewportRule2 = _interopRequireDefault(_ViewportRule), classes = {
+ var _SimpleRule = __webpack_require__(429), _SimpleRule2 = _interopRequireDefault(_SimpleRule), _KeyframesRule = __webpack_require__(430), _KeyframesRule2 = _interopRequireDefault(_KeyframesRule), _ConditionalRule = __webpack_require__(431), _ConditionalRule2 = _interopRequireDefault(_ConditionalRule), _FontFaceRule = __webpack_require__(432), _FontFaceRule2 = _interopRequireDefault(_FontFaceRule), _ViewportRule = __webpack_require__(433), _ViewportRule2 = _interopRequireDefault(_ViewportRule), classes = {
"@charset": _SimpleRule2.default,
"@import": _SimpleRule2.default,
"@namespace": _SimpleRule2.default,
@@ -28821,7 +27330,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _RuleList = __webpack_require__(96), _RuleList2 = function(obj) {
+ }(), _RuleList = __webpack_require__(76), _RuleList2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -28874,7 +27383,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _RuleList = __webpack_require__(96), _RuleList2 = function(obj) {
+ }(), _RuleList = __webpack_require__(76), _RuleList2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -28934,7 +27443,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _toCss = __webpack_require__(195), _toCss2 = function(obj) {
+ }(), _toCss = __webpack_require__(153), _toCss2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -28976,7 +27485,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _toCss = __webpack_require__(195), _toCss2 = function(obj) {
+ }(), _toCss = __webpack_require__(153), _toCss2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -29003,7 +27512,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _StyleRule = __webpack_require__(77), _StyleRule2 = _interopRequireDefault(_StyleRule), _createRule = __webpack_require__(131), _createRule2 = _interopRequireDefault(_createRule), _isObservable = __webpack_require__(293), _isObservable2 = _interopRequireDefault(_isObservable);
+ var _StyleRule = __webpack_require__(60), _StyleRule2 = _interopRequireDefault(_StyleRule), _createRule = __webpack_require__(106), _createRule2 = _interopRequireDefault(_createRule), _isObservable = __webpack_require__(230), _isObservable2 = _interopRequireDefault(_isObservable);
exports.default = {
onCreateRule: function(name, decl, options) {
if (!(0, _isObservable2.default)(decl)) return null;
@@ -29039,7 +27548,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _RuleList = __webpack_require__(96), _RuleList2 = _interopRequireDefault(_RuleList), _StyleRule = __webpack_require__(77), _StyleRule2 = _interopRequireDefault(_StyleRule), _kebabCase = __webpack_require__(558), _kebabCase2 = _interopRequireDefault(_kebabCase), _createRule = __webpack_require__(131), _createRule2 = _interopRequireDefault(_createRule), now = Date.now(), fnValuesNs = "fnValues" + now, fnStyleNs = "fnStyle" + ++now;
+ var _RuleList = __webpack_require__(76), _RuleList2 = _interopRequireDefault(_RuleList), _StyleRule = __webpack_require__(60), _StyleRule2 = _interopRequireDefault(_StyleRule), _kebabCase = __webpack_require__(436), _kebabCase2 = _interopRequireDefault(_kebabCase), _createRule = __webpack_require__(106), _createRule2 = _interopRequireDefault(_createRule), now = Date.now(), fnValuesNs = "fnValues" + now, fnStyleNs = "fnStyle" + ++now;
exports.default = {
onCreateRule: function(name, decl, options) {
if ("function" != typeof decl) return null;
@@ -29174,7 +27683,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), _sheets = __webpack_require__(198), _sheets2 = _interopRequireDefault(_sheets), _StyleRule = __webpack_require__(77), _StyleRule2 = _interopRequireDefault(_StyleRule), _toCssValue = __webpack_require__(196), _toCssValue2 = _interopRequireDefault(_toCssValue), CSSRuleTypes = {
+ }(), _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), _sheets = __webpack_require__(155), _sheets2 = _interopRequireDefault(_sheets), _StyleRule = __webpack_require__(60), _StyleRule2 = _interopRequireDefault(_StyleRule), _toCssValue = __webpack_require__(105), _toCssValue2 = _interopRequireDefault(_toCssValue), CSSRuleTypes = {
STYLE_RULE: 1,
KEYFRAMES_RULE: 7
}, getKey = function() {
@@ -29286,7 +27795,7 @@ var _publicBundleJs = []byte(`!function(modules) {
} ]), DomRenderer;
}();
exports.default = DomRenderer;
- }).call(exports, __webpack_require__(68));
+ }).call(exports, __webpack_require__(51));
}, function(module, exports, __webpack_require__) {
"use strict";
function _classCallCheck(instance, Constructor) {
@@ -29368,6 +27877,24 @@ var _publicBundleJs = []byte(`!function(modules) {
exports.default = VirtualRenderer;
}, function(module, exports, __webpack_require__) {
"use strict";
+ function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
+ }
+ function jssPreset() {
+ return {
+ plugins: [ (0, _jssGlobal2.default)(), (0, _jssNested2.default)(), (0, _jssCamelCase2.default)(), (0,
+ _jssDefaultUnit2.default)(), (0, _jssVendorPrefixer2.default)(), (0, _jssPropsSort2.default)() ]
+ };
+ }
+ Object.defineProperty(exports, "__esModule", {
+ value: !0
+ });
+ var _jssGlobal = __webpack_require__(440), _jssGlobal2 = _interopRequireDefault(_jssGlobal), _jssNested = __webpack_require__(441), _jssNested2 = _interopRequireDefault(_jssNested), _jssCamelCase = __webpack_require__(442), _jssCamelCase2 = _interopRequireDefault(_jssCamelCase), _jssDefaultUnit = __webpack_require__(443), _jssDefaultUnit2 = _interopRequireDefault(_jssDefaultUnit), _jssVendorPrefixer = __webpack_require__(445), _jssVendorPrefixer2 = _interopRequireDefault(_jssVendorPrefixer), _jssPropsSort = __webpack_require__(450), _jssPropsSort2 = _interopRequireDefault(_jssPropsSort);
+ exports.default = jssPreset;
+}, function(module, exports, __webpack_require__) {
+ "use strict";
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
}
@@ -29433,7 +27960,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}();
exports.default = jssGlobal;
- var _jss = __webpack_require__(291), propKey = "@global", prefixKey = "@global ", GlobalContainerRule = function() {
+ var _jss = __webpack_require__(228), propKey = "@global", prefixKey = "@global ", GlobalContainerRule = function() {
function GlobalContainerRule(key, styles, options) {
_classCallCheck(this, GlobalContainerRule), this.type = "global", this.key = key,
this.options = options, this.rules = new _jss.RuleList(_extends({}, options, {
@@ -29547,7 +28074,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return target;
};
exports.default = jssNested;
- var _warning = __webpack_require__(14), _warning2 = function(obj) {
+ var _warning = __webpack_require__(11), _warning2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -29633,7 +28160,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
exports.default = defaultUnit;
- var _defaultUnits = __webpack_require__(565), _defaultUnits2 = function(obj) {
+ var _defaultUnits = __webpack_require__(444), _defaultUnits2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -29776,7 +28303,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.default = jssVendorPrefixer;
- var _cssVendor = __webpack_require__(567), vendor = function(obj) {
+ var _cssVendor = __webpack_require__(446), vendor = function(obj) {
if (obj && obj.__esModule) return obj;
var newObj = {};
if (null != obj) for (var key in obj) Object.prototype.hasOwnProperty.call(obj, key) && (newObj[key] = obj[key]);
@@ -29792,7 +28319,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.supportedValue = exports.supportedProperty = exports.prefix = void 0;
- var _prefix = __webpack_require__(199), _prefix2 = _interopRequireDefault(_prefix), _supportedProperty = __webpack_require__(568), _supportedProperty2 = _interopRequireDefault(_supportedProperty), _supportedValue = __webpack_require__(570), _supportedValue2 = _interopRequireDefault(_supportedValue);
+ var _prefix = __webpack_require__(156), _prefix2 = _interopRequireDefault(_prefix), _supportedProperty = __webpack_require__(447), _supportedProperty2 = _interopRequireDefault(_supportedProperty), _supportedValue = __webpack_require__(449), _supportedValue2 = _interopRequireDefault(_supportedValue);
exports.default = {
prefix: _prefix2.default,
supportedProperty: _supportedProperty2.default,
@@ -29814,7 +28341,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.default = supportedProperty;
- var _isInBrowser = __webpack_require__(132), _isInBrowser2 = _interopRequireDefault(_isInBrowser), _prefix = __webpack_require__(199), _prefix2 = _interopRequireDefault(_prefix), _camelize = __webpack_require__(569), _camelize2 = _interopRequireDefault(_camelize), el = void 0, cache = {};
+ var _isInBrowser = __webpack_require__(107), _isInBrowser2 = _interopRequireDefault(_isInBrowser), _prefix = __webpack_require__(156), _prefix2 = _interopRequireDefault(_prefix), _camelize = __webpack_require__(448), _camelize2 = _interopRequireDefault(_camelize), el = void 0, cache = {};
if (_isInBrowser2.default) {
el = document.createElement("p");
var computed = window.getComputedStyle(document.documentElement, "");
@@ -29856,7 +28383,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.default = supportedValue;
- var _isInBrowser = __webpack_require__(132), _isInBrowser2 = _interopRequireDefault(_isInBrowser), _prefix = __webpack_require__(199), _prefix2 = _interopRequireDefault(_prefix), cache = {}, el = void 0;
+ var _isInBrowser = __webpack_require__(107), _isInBrowser2 = _interopRequireDefault(_isInBrowser), _prefix = __webpack_require__(156), _prefix2 = _interopRequireDefault(_prefix), cache = {}, el = void 0;
_isInBrowser2.default && (el = document.createElement("p"));
}, function(module, exports, __webpack_require__) {
"use strict";
@@ -29881,14 +28408,22 @@ var _publicBundleJs = []byte(`!function(modules) {
"use strict";
(function(process) {
function createGenerateClassName() {
- var ruleCounter = 0;
- return "production" === process.env.NODE_ENV && "undefined" != typeof window && (generatorCounter += 1) > 2 && console.error([ "Material-UI: we have detected more than needed creation of the class name generator.", "You should only use one class name generator on the client side.", "If you do otherwise, you take the risk to have conflicting class names in production." ].join("\n")),
+ var options = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, _options$dangerouslyU = options.dangerouslyUseGlobalCSS, dangerouslyUseGlobalCSS = void 0 !== _options$dangerouslyU && _options$dangerouslyU, _options$productionPr = options.productionPrefix, productionPrefix = void 0 === _options$productionPr ? "jss" : _options$productionPr, escapeRegex = /([[\].#*$><+~=|^:(),"'` + "`")) + (`\s])/g, ruleCounter = 0;
+ return "production" === process.env.NODE_ENV && "undefined" != typeof window && "jss" === productionPrefix && (generatorCounter += 1) > 2 && console.error([ "Material-UI: we have detected more than needed creation of the class name generator.", "You should only use one class name generator on the client side.", "If you do otherwise, you take the risk to have conflicting class names in production." ].join("\n")),
function(rule, styleSheet) {
if (ruleCounter += 1, "production" !== process.env.NODE_ENV && (0, _warning2.default)(ruleCounter < 1e10, [ "Material-UI: you might have a memory leak.", "The ruleCounter is not supposed to grow that much." ].join("")),
- "production" === process.env.NODE_ENV) return "c" + ruleCounter;
- if (styleSheet && styleSheet.options.meta) {
- var meta = styleSheet.options.meta;
- return (meta = meta.replace(new RegExp(/[!"#$%&'()*+,.\/:; <=>?@[\\\]^` + "`" + `{|}~]/g), "-")) + "-" + rule.key + "-" + ruleCounter;
+ dangerouslyUseGlobalCSS) {
+ if (styleSheet && styleSheet.options.classNamePrefix) {
+ var prefix = styleSheet.options.classNamePrefix;
+ if (prefix = prefix.replace(escapeRegex, "-"), prefix.match(/^Mui/)) return prefix + "-" + rule.key;
+ if ("production" !== process.env.NODE_ENV) return prefix + "-" + rule.key + "-" + ruleCounter;
+ }
+ return "production" === process.env.NODE_ENV ? "" + productionPrefix + ruleCounter : rule.key + "-" + ruleCounter;
+ }
+ if ("production" === process.env.NODE_ENV) return "" + productionPrefix + ruleCounter;
+ if (styleSheet && styleSheet.options.classNamePrefix) {
+ var _prefix = styleSheet.options.classNamePrefix;
+ return (_prefix = _prefix.replace(escapeRegex, "-")) + "-" + rule.key + "-" + ruleCounter;
}
return rule.key + "-" + ruleCounter;
};
@@ -29896,12 +28431,12 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.default = createGenerateClassName;
- var _warning = __webpack_require__(14), _warning2 = function(obj) {
+ var _warning = __webpack_require__(11), _warning2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}(_warning), generatorCounter = 0;
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -29912,2793 +28447,27 @@ var _publicBundleJs = []byte(`!function(modules) {
}
function getStylesCreator(stylesOrCreator) {
function create(theme, name) {
- var styles = "function" == typeof stylesOrCreator ? stylesOrCreator(theme) : stylesOrCreator;
+ var styles = themingEnabled ? stylesOrCreator(theme) : stylesOrCreator;
if (!theme.overrides || !name || !theme.overrides[name]) return styles;
var overrides = theme.overrides[name], stylesWithOverrides = (0, _extends3.default)({}, styles);
return (0, _keys2.default)(overrides).forEach(function(key) {
- "production" !== process.env.NODE_ENV && (0, _warning2.default)(stylesWithOverrides[key], [ "Material-UI: you are trying to override a style that does not exist.", "Fix the ` + "`" + `" + key + "` + "`" + ` key of ` + "`" + `theme.overrides." + name + "` + "`" + `." ].join("\n")),
+ "production" !== process.env.NODE_ENV && (0, _warning2.default)(stylesWithOverrides[key], [ "Material-UI: you are trying to override a style that does not exist.", "Fix the ` + ("`" + `" + key + "`))) + (("`" + (` key of ` + "`")) + (`theme.overrides." + name + "` + ("`" + `." ].join("\n")),
stylesWithOverrides[key] = (0, _deepmerge2.default)(stylesWithOverrides[key], overrides[key]);
}), stylesWithOverrides;
}
+ var themingEnabled = "function" == typeof stylesOrCreator;
return {
create: create,
- options: {
- index: void 0
- },
- themingEnabled: "function" == typeof stylesOrCreator
+ options: {},
+ themingEnabled: themingEnabled
};
}
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _keys = __webpack_require__(51), _keys2 = _interopRequireDefault(_keys), _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), _deepmerge = __webpack_require__(129), _deepmerge2 = _interopRequireDefault(_deepmerge);
+ var _keys = __webpack_require__(41), _keys2 = _interopRequireDefault(_keys), _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), _deepmerge = __webpack_require__(103), _deepmerge2 = _interopRequireDefault(_deepmerge);
exports.default = getStylesCreator;
- }).call(exports, __webpack_require__(3));
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- Object.defineProperty(__webpack_exports__, "__esModule", {
- value: !0
- });
- var __WEBPACK_IMPORTED_MODULE_0__F__ = __webpack_require__(575);
- __webpack_require__.d(__webpack_exports__, "F", function() {
- return __WEBPACK_IMPORTED_MODULE_0__F__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_1__T__ = __webpack_require__(576);
- __webpack_require__.d(__webpack_exports__, "T", function() {
- return __WEBPACK_IMPORTED_MODULE_1__T__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_2____ = __webpack_require__(577);
- __webpack_require__.d(__webpack_exports__, "__", function() {
- return __WEBPACK_IMPORTED_MODULE_2____.a;
- });
- var __WEBPACK_IMPORTED_MODULE_3__add__ = __webpack_require__(134);
- __webpack_require__.d(__webpack_exports__, "add", function() {
- return __WEBPACK_IMPORTED_MODULE_3__add__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_4__addIndex__ = __webpack_require__(578);
- __webpack_require__.d(__webpack_exports__, "addIndex", function() {
- return __WEBPACK_IMPORTED_MODULE_4__addIndex__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_5__adjust__ = __webpack_require__(297);
- __webpack_require__.d(__webpack_exports__, "adjust", function() {
- return __WEBPACK_IMPORTED_MODULE_5__adjust__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_6__all__ = __webpack_require__(579);
- __webpack_require__.d(__webpack_exports__, "all", function() {
- return __WEBPACK_IMPORTED_MODULE_6__all__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_7__allPass__ = __webpack_require__(581);
- __webpack_require__.d(__webpack_exports__, "allPass", function() {
- return __WEBPACK_IMPORTED_MODULE_7__allPass__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_8__always__ = __webpack_require__(78);
- __webpack_require__.d(__webpack_exports__, "always", function() {
- return __WEBPACK_IMPORTED_MODULE_8__always__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_9__and__ = __webpack_require__(301);
- __webpack_require__.d(__webpack_exports__, "and", function() {
- return __WEBPACK_IMPORTED_MODULE_9__and__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_10__any__ = __webpack_require__(302);
- __webpack_require__.d(__webpack_exports__, "any", function() {
- return __WEBPACK_IMPORTED_MODULE_10__any__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_11__anyPass__ = __webpack_require__(583);
- __webpack_require__.d(__webpack_exports__, "anyPass", function() {
- return __WEBPACK_IMPORTED_MODULE_11__anyPass__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_12__ap__ = __webpack_require__(202);
- __webpack_require__.d(__webpack_exports__, "ap", function() {
- return __WEBPACK_IMPORTED_MODULE_12__ap__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_13__aperture__ = __webpack_require__(584);
- __webpack_require__.d(__webpack_exports__, "aperture", function() {
- return __WEBPACK_IMPORTED_MODULE_13__aperture__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_14__append__ = __webpack_require__(587);
- __webpack_require__.d(__webpack_exports__, "append", function() {
- return __WEBPACK_IMPORTED_MODULE_14__append__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_15__apply__ = __webpack_require__(304);
- __webpack_require__.d(__webpack_exports__, "apply", function() {
- return __WEBPACK_IMPORTED_MODULE_15__apply__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_16__applySpec__ = __webpack_require__(588);
- __webpack_require__.d(__webpack_exports__, "applySpec", function() {
- return __WEBPACK_IMPORTED_MODULE_16__applySpec__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_17__applyTo__ = __webpack_require__(589);
- __webpack_require__.d(__webpack_exports__, "applyTo", function() {
- return __WEBPACK_IMPORTED_MODULE_17__applyTo__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_18__ascend__ = __webpack_require__(590);
- __webpack_require__.d(__webpack_exports__, "ascend", function() {
- return __WEBPACK_IMPORTED_MODULE_18__ascend__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_19__assoc__ = __webpack_require__(138);
- __webpack_require__.d(__webpack_exports__, "assoc", function() {
- return __WEBPACK_IMPORTED_MODULE_19__assoc__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_20__assocPath__ = __webpack_require__(306);
- __webpack_require__.d(__webpack_exports__, "assocPath", function() {
- return __WEBPACK_IMPORTED_MODULE_20__assocPath__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_21__binary__ = __webpack_require__(591);
- __webpack_require__.d(__webpack_exports__, "binary", function() {
- return __WEBPACK_IMPORTED_MODULE_21__binary__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_22__bind__ = __webpack_require__(299);
- __webpack_require__.d(__webpack_exports__, "bind", function() {
- return __WEBPACK_IMPORTED_MODULE_22__bind__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_23__both__ = __webpack_require__(592);
- __webpack_require__.d(__webpack_exports__, "both", function() {
- return __WEBPACK_IMPORTED_MODULE_23__both__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_24__call__ = __webpack_require__(593);
- __webpack_require__.d(__webpack_exports__, "call", function() {
- return __WEBPACK_IMPORTED_MODULE_24__call__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_25__chain__ = __webpack_require__(205);
- __webpack_require__.d(__webpack_exports__, "chain", function() {
- return __WEBPACK_IMPORTED_MODULE_25__chain__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_26__clamp__ = __webpack_require__(597);
- __webpack_require__.d(__webpack_exports__, "clamp", function() {
- return __WEBPACK_IMPORTED_MODULE_26__clamp__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_27__clone__ = __webpack_require__(598);
- __webpack_require__.d(__webpack_exports__, "clone", function() {
- return __WEBPACK_IMPORTED_MODULE_27__clone__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_28__comparator__ = __webpack_require__(599);
- __webpack_require__.d(__webpack_exports__, "comparator", function() {
- return __WEBPACK_IMPORTED_MODULE_28__comparator__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_29__complement__ = __webpack_require__(600);
- __webpack_require__.d(__webpack_exports__, "complement", function() {
- return __WEBPACK_IMPORTED_MODULE_29__complement__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_30__compose__ = __webpack_require__(207);
- __webpack_require__.d(__webpack_exports__, "compose", function() {
- return __WEBPACK_IMPORTED_MODULE_30__compose__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_31__composeK__ = __webpack_require__(314);
- __webpack_require__.d(__webpack_exports__, "composeK", function() {
- return __WEBPACK_IMPORTED_MODULE_31__composeK__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_32__composeP__ = __webpack_require__(602);
- __webpack_require__.d(__webpack_exports__, "composeP", function() {
- return __WEBPACK_IMPORTED_MODULE_32__composeP__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_33__concat__ = __webpack_require__(209);
- __webpack_require__.d(__webpack_exports__, "concat", function() {
- return __WEBPACK_IMPORTED_MODULE_33__concat__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_34__cond__ = __webpack_require__(611);
- __webpack_require__.d(__webpack_exports__, "cond", function() {
- return __WEBPACK_IMPORTED_MODULE_34__cond__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_35__construct__ = __webpack_require__(612);
- __webpack_require__.d(__webpack_exports__, "construct", function() {
- return __WEBPACK_IMPORTED_MODULE_35__construct__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_36__constructN__ = __webpack_require__(319);
- __webpack_require__.d(__webpack_exports__, "constructN", function() {
- return __WEBPACK_IMPORTED_MODULE_36__constructN__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_37__contains__ = __webpack_require__(613);
- __webpack_require__.d(__webpack_exports__, "contains", function() {
- return __WEBPACK_IMPORTED_MODULE_37__contains__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_38__converge__ = __webpack_require__(320);
- __webpack_require__.d(__webpack_exports__, "converge", function() {
- return __WEBPACK_IMPORTED_MODULE_38__converge__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_39__countBy__ = __webpack_require__(614);
- __webpack_require__.d(__webpack_exports__, "countBy", function() {
- return __WEBPACK_IMPORTED_MODULE_39__countBy__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_40__curry__ = __webpack_require__(204);
- __webpack_require__.d(__webpack_exports__, "curry", function() {
- return __WEBPACK_IMPORTED_MODULE_40__curry__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_41__curryN__ = __webpack_require__(23);
- __webpack_require__.d(__webpack_exports__, "curryN", function() {
- return __WEBPACK_IMPORTED_MODULE_41__curryN__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_42__dec__ = __webpack_require__(616);
- __webpack_require__.d(__webpack_exports__, "dec", function() {
- return __WEBPACK_IMPORTED_MODULE_42__dec__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_43__defaultTo__ = __webpack_require__(321);
- __webpack_require__.d(__webpack_exports__, "defaultTo", function() {
- return __WEBPACK_IMPORTED_MODULE_43__defaultTo__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_44__descend__ = __webpack_require__(617);
- __webpack_require__.d(__webpack_exports__, "descend", function() {
- return __WEBPACK_IMPORTED_MODULE_44__descend__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_45__difference__ = __webpack_require__(322);
- __webpack_require__.d(__webpack_exports__, "difference", function() {
- return __WEBPACK_IMPORTED_MODULE_45__difference__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_46__differenceWith__ = __webpack_require__(323);
- __webpack_require__.d(__webpack_exports__, "differenceWith", function() {
- return __WEBPACK_IMPORTED_MODULE_46__differenceWith__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_47__dissoc__ = __webpack_require__(324);
- __webpack_require__.d(__webpack_exports__, "dissoc", function() {
- return __WEBPACK_IMPORTED_MODULE_47__dissoc__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_48__dissocPath__ = __webpack_require__(618);
- __webpack_require__.d(__webpack_exports__, "dissocPath", function() {
- return __WEBPACK_IMPORTED_MODULE_48__dissocPath__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_49__divide__ = __webpack_require__(619);
- __webpack_require__.d(__webpack_exports__, "divide", function() {
- return __WEBPACK_IMPORTED_MODULE_49__divide__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_50__drop__ = __webpack_require__(326);
- __webpack_require__.d(__webpack_exports__, "drop", function() {
- return __WEBPACK_IMPORTED_MODULE_50__drop__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_51__dropLast__ = __webpack_require__(621);
- __webpack_require__.d(__webpack_exports__, "dropLast", function() {
- return __WEBPACK_IMPORTED_MODULE_51__dropLast__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_52__dropLastWhile__ = __webpack_require__(625);
- __webpack_require__.d(__webpack_exports__, "dropLastWhile", function() {
- return __WEBPACK_IMPORTED_MODULE_52__dropLastWhile__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_53__dropRepeats__ = __webpack_require__(628);
- __webpack_require__.d(__webpack_exports__, "dropRepeats", function() {
- return __WEBPACK_IMPORTED_MODULE_53__dropRepeats__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_54__dropRepeatsWith__ = __webpack_require__(328);
- __webpack_require__.d(__webpack_exports__, "dropRepeatsWith", function() {
- return __WEBPACK_IMPORTED_MODULE_54__dropRepeatsWith__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_55__dropWhile__ = __webpack_require__(629);
- __webpack_require__.d(__webpack_exports__, "dropWhile", function() {
- return __WEBPACK_IMPORTED_MODULE_55__dropWhile__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_56__either__ = __webpack_require__(631);
- __webpack_require__.d(__webpack_exports__, "either", function() {
- return __WEBPACK_IMPORTED_MODULE_56__either__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_57__empty__ = __webpack_require__(331);
- __webpack_require__.d(__webpack_exports__, "empty", function() {
- return __WEBPACK_IMPORTED_MODULE_57__empty__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_58__endsWith__ = __webpack_require__(632);
- __webpack_require__.d(__webpack_exports__, "endsWith", function() {
- return __WEBPACK_IMPORTED_MODULE_58__endsWith__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_59__eqBy__ = __webpack_require__(633);
- __webpack_require__.d(__webpack_exports__, "eqBy", function() {
- return __WEBPACK_IMPORTED_MODULE_59__eqBy__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_60__eqProps__ = __webpack_require__(634);
- __webpack_require__.d(__webpack_exports__, "eqProps", function() {
- return __WEBPACK_IMPORTED_MODULE_60__eqProps__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_61__equals__ = __webpack_require__(31);
- __webpack_require__.d(__webpack_exports__, "equals", function() {
- return __WEBPACK_IMPORTED_MODULE_61__equals__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_62__evolve__ = __webpack_require__(635);
- __webpack_require__.d(__webpack_exports__, "evolve", function() {
- return __WEBPACK_IMPORTED_MODULE_62__evolve__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_63__filter__ = __webpack_require__(210);
- __webpack_require__.d(__webpack_exports__, "filter", function() {
- return __WEBPACK_IMPORTED_MODULE_63__filter__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_64__find__ = __webpack_require__(636);
- __webpack_require__.d(__webpack_exports__, "find", function() {
- return __WEBPACK_IMPORTED_MODULE_64__find__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_65__findIndex__ = __webpack_require__(638);
- __webpack_require__.d(__webpack_exports__, "findIndex", function() {
- return __WEBPACK_IMPORTED_MODULE_65__findIndex__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_66__findLast__ = __webpack_require__(640);
- __webpack_require__.d(__webpack_exports__, "findLast", function() {
- return __WEBPACK_IMPORTED_MODULE_66__findLast__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_67__findLastIndex__ = __webpack_require__(642);
- __webpack_require__.d(__webpack_exports__, "findLastIndex", function() {
- return __WEBPACK_IMPORTED_MODULE_67__findLastIndex__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_68__flatten__ = __webpack_require__(644);
- __webpack_require__.d(__webpack_exports__, "flatten", function() {
- return __WEBPACK_IMPORTED_MODULE_68__flatten__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_69__flip__ = __webpack_require__(146);
- __webpack_require__.d(__webpack_exports__, "flip", function() {
- return __WEBPACK_IMPORTED_MODULE_69__flip__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_70__forEach__ = __webpack_require__(645);
- __webpack_require__.d(__webpack_exports__, "forEach", function() {
- return __WEBPACK_IMPORTED_MODULE_70__forEach__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_71__forEachObjIndexed__ = __webpack_require__(646);
- __webpack_require__.d(__webpack_exports__, "forEachObjIndexed", function() {
- return __WEBPACK_IMPORTED_MODULE_71__forEachObjIndexed__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_72__fromPairs__ = __webpack_require__(647);
- __webpack_require__.d(__webpack_exports__, "fromPairs", function() {
- return __WEBPACK_IMPORTED_MODULE_72__fromPairs__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_73__groupBy__ = __webpack_require__(648);
- __webpack_require__.d(__webpack_exports__, "groupBy", function() {
- return __WEBPACK_IMPORTED_MODULE_73__groupBy__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_74__groupWith__ = __webpack_require__(649);
- __webpack_require__.d(__webpack_exports__, "groupWith", function() {
- return __WEBPACK_IMPORTED_MODULE_74__groupWith__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_75__gt__ = __webpack_require__(650);
- __webpack_require__.d(__webpack_exports__, "gt", function() {
- return __WEBPACK_IMPORTED_MODULE_75__gt__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_76__gte__ = __webpack_require__(651);
- __webpack_require__.d(__webpack_exports__, "gte", function() {
- return __WEBPACK_IMPORTED_MODULE_76__gte__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_77__has__ = __webpack_require__(652);
- __webpack_require__.d(__webpack_exports__, "has", function() {
- return __WEBPACK_IMPORTED_MODULE_77__has__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_78__hasIn__ = __webpack_require__(653);
- __webpack_require__.d(__webpack_exports__, "hasIn", function() {
- return __WEBPACK_IMPORTED_MODULE_78__hasIn__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_79__head__ = __webpack_require__(654);
- __webpack_require__.d(__webpack_exports__, "head", function() {
- return __WEBPACK_IMPORTED_MODULE_79__head__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_80__identical__ = __webpack_require__(317);
- __webpack_require__.d(__webpack_exports__, "identical", function() {
- return __WEBPACK_IMPORTED_MODULE_80__identical__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_81__identity__ = __webpack_require__(215);
- __webpack_require__.d(__webpack_exports__, "identity", function() {
- return __WEBPACK_IMPORTED_MODULE_81__identity__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_82__ifElse__ = __webpack_require__(655);
- __webpack_require__.d(__webpack_exports__, "ifElse", function() {
- return __WEBPACK_IMPORTED_MODULE_82__ifElse__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_83__inc__ = __webpack_require__(656);
- __webpack_require__.d(__webpack_exports__, "inc", function() {
- return __WEBPACK_IMPORTED_MODULE_83__inc__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_84__indexBy__ = __webpack_require__(657);
- __webpack_require__.d(__webpack_exports__, "indexBy", function() {
- return __WEBPACK_IMPORTED_MODULE_84__indexBy__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_85__indexOf__ = __webpack_require__(658);
- __webpack_require__.d(__webpack_exports__, "indexOf", function() {
- return __WEBPACK_IMPORTED_MODULE_85__indexOf__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_86__init__ = __webpack_require__(659);
- __webpack_require__.d(__webpack_exports__, "init", function() {
- return __WEBPACK_IMPORTED_MODULE_86__init__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_87__innerJoin__ = __webpack_require__(660);
- __webpack_require__.d(__webpack_exports__, "innerJoin", function() {
- return __WEBPACK_IMPORTED_MODULE_87__innerJoin__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_88__insert__ = __webpack_require__(661);
- __webpack_require__.d(__webpack_exports__, "insert", function() {
- return __WEBPACK_IMPORTED_MODULE_88__insert__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_89__insertAll__ = __webpack_require__(662);
- __webpack_require__.d(__webpack_exports__, "insertAll", function() {
- return __WEBPACK_IMPORTED_MODULE_89__insertAll__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_90__intersection__ = __webpack_require__(663);
- __webpack_require__.d(__webpack_exports__, "intersection", function() {
- return __WEBPACK_IMPORTED_MODULE_90__intersection__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_91__intersperse__ = __webpack_require__(665);
- __webpack_require__.d(__webpack_exports__, "intersperse", function() {
- return __WEBPACK_IMPORTED_MODULE_91__intersperse__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_92__into__ = __webpack_require__(666);
- __webpack_require__.d(__webpack_exports__, "into", function() {
- return __WEBPACK_IMPORTED_MODULE_92__into__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_93__invert__ = __webpack_require__(669);
- __webpack_require__.d(__webpack_exports__, "invert", function() {
- return __WEBPACK_IMPORTED_MODULE_93__invert__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_94__invertObj__ = __webpack_require__(670);
- __webpack_require__.d(__webpack_exports__, "invertObj", function() {
- return __WEBPACK_IMPORTED_MODULE_94__invertObj__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_95__invoker__ = __webpack_require__(102);
- __webpack_require__.d(__webpack_exports__, "invoker", function() {
- return __WEBPACK_IMPORTED_MODULE_95__invoker__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_96__is__ = __webpack_require__(335);
- __webpack_require__.d(__webpack_exports__, "is", function() {
- return __WEBPACK_IMPORTED_MODULE_96__is__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_97__isEmpty__ = __webpack_require__(671);
- __webpack_require__.d(__webpack_exports__, "isEmpty", function() {
- return __WEBPACK_IMPORTED_MODULE_97__isEmpty__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_98__isNil__ = __webpack_require__(307);
- __webpack_require__.d(__webpack_exports__, "isNil", function() {
- return __WEBPACK_IMPORTED_MODULE_98__isNil__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_99__join__ = __webpack_require__(672);
- __webpack_require__.d(__webpack_exports__, "join", function() {
- return __WEBPACK_IMPORTED_MODULE_99__join__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_100__juxt__ = __webpack_require__(336);
- __webpack_require__.d(__webpack_exports__, "juxt", function() {
- return __WEBPACK_IMPORTED_MODULE_100__juxt__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_101__keys__ = __webpack_require__(44);
- __webpack_require__.d(__webpack_exports__, "keys", function() {
- return __WEBPACK_IMPORTED_MODULE_101__keys__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_102__keysIn__ = __webpack_require__(673);
- __webpack_require__.d(__webpack_exports__, "keysIn", function() {
- return __WEBPACK_IMPORTED_MODULE_102__keysIn__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_103__last__ = __webpack_require__(329);
- __webpack_require__.d(__webpack_exports__, "last", function() {
- return __WEBPACK_IMPORTED_MODULE_103__last__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_104__lastIndexOf__ = __webpack_require__(674);
- __webpack_require__.d(__webpack_exports__, "lastIndexOf", function() {
- return __WEBPACK_IMPORTED_MODULE_104__lastIndexOf__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_105__length__ = __webpack_require__(337);
- __webpack_require__.d(__webpack_exports__, "length", function() {
- return __WEBPACK_IMPORTED_MODULE_105__length__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_106__lens__ = __webpack_require__(147);
- __webpack_require__.d(__webpack_exports__, "lens", function() {
- return __WEBPACK_IMPORTED_MODULE_106__lens__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_107__lensIndex__ = __webpack_require__(675);
- __webpack_require__.d(__webpack_exports__, "lensIndex", function() {
- return __WEBPACK_IMPORTED_MODULE_107__lensIndex__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_108__lensPath__ = __webpack_require__(676);
- __webpack_require__.d(__webpack_exports__, "lensPath", function() {
- return __WEBPACK_IMPORTED_MODULE_108__lensPath__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_109__lensProp__ = __webpack_require__(677);
- __webpack_require__.d(__webpack_exports__, "lensProp", function() {
- return __WEBPACK_IMPORTED_MODULE_109__lensProp__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_110__lift__ = __webpack_require__(141);
- __webpack_require__.d(__webpack_exports__, "lift", function() {
- return __WEBPACK_IMPORTED_MODULE_110__lift__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_111__liftN__ = __webpack_require__(308);
- __webpack_require__.d(__webpack_exports__, "liftN", function() {
- return __WEBPACK_IMPORTED_MODULE_111__liftN__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_112__lt__ = __webpack_require__(678);
- __webpack_require__.d(__webpack_exports__, "lt", function() {
- return __WEBPACK_IMPORTED_MODULE_112__lt__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_113__lte__ = __webpack_require__(679);
- __webpack_require__.d(__webpack_exports__, "lte", function() {
- return __WEBPACK_IMPORTED_MODULE_113__lte__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_114__map__ = __webpack_require__(27);
- __webpack_require__.d(__webpack_exports__, "map", function() {
- return __WEBPACK_IMPORTED_MODULE_114__map__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_115__mapAccum__ = __webpack_require__(680);
- __webpack_require__.d(__webpack_exports__, "mapAccum", function() {
- return __WEBPACK_IMPORTED_MODULE_115__mapAccum__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_116__mapAccumRight__ = __webpack_require__(681);
- __webpack_require__.d(__webpack_exports__, "mapAccumRight", function() {
- return __WEBPACK_IMPORTED_MODULE_116__mapAccumRight__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_117__mapObjIndexed__ = __webpack_require__(682);
- __webpack_require__.d(__webpack_exports__, "mapObjIndexed", function() {
- return __WEBPACK_IMPORTED_MODULE_117__mapObjIndexed__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_118__match__ = __webpack_require__(683);
- __webpack_require__.d(__webpack_exports__, "match", function() {
- return __WEBPACK_IMPORTED_MODULE_118__match__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_119__mathMod__ = __webpack_require__(684);
- __webpack_require__.d(__webpack_exports__, "mathMod", function() {
- return __WEBPACK_IMPORTED_MODULE_119__mathMod__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_120__max__ = __webpack_require__(79);
- __webpack_require__.d(__webpack_exports__, "max", function() {
- return __WEBPACK_IMPORTED_MODULE_120__max__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_121__maxBy__ = __webpack_require__(685);
- __webpack_require__.d(__webpack_exports__, "maxBy", function() {
- return __WEBPACK_IMPORTED_MODULE_121__maxBy__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_122__mean__ = __webpack_require__(339);
- __webpack_require__.d(__webpack_exports__, "mean", function() {
- return __WEBPACK_IMPORTED_MODULE_122__mean__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_123__median__ = __webpack_require__(686);
- __webpack_require__.d(__webpack_exports__, "median", function() {
- return __WEBPACK_IMPORTED_MODULE_123__median__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_124__memoize__ = __webpack_require__(687);
- __webpack_require__.d(__webpack_exports__, "memoize", function() {
- return __WEBPACK_IMPORTED_MODULE_124__memoize__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_125__memoizeWith__ = __webpack_require__(341);
- __webpack_require__.d(__webpack_exports__, "memoizeWith", function() {
- return __WEBPACK_IMPORTED_MODULE_125__memoizeWith__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_126__merge__ = __webpack_require__(688);
- __webpack_require__.d(__webpack_exports__, "merge", function() {
- return __WEBPACK_IMPORTED_MODULE_126__merge__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_127__mergeAll__ = __webpack_require__(689);
- __webpack_require__.d(__webpack_exports__, "mergeAll", function() {
- return __WEBPACK_IMPORTED_MODULE_127__mergeAll__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_128__mergeDeepLeft__ = __webpack_require__(690);
- __webpack_require__.d(__webpack_exports__, "mergeDeepLeft", function() {
- return __WEBPACK_IMPORTED_MODULE_128__mergeDeepLeft__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_129__mergeDeepRight__ = __webpack_require__(691);
- __webpack_require__.d(__webpack_exports__, "mergeDeepRight", function() {
- return __WEBPACK_IMPORTED_MODULE_129__mergeDeepRight__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_130__mergeDeepWith__ = __webpack_require__(692);
- __webpack_require__.d(__webpack_exports__, "mergeDeepWith", function() {
- return __WEBPACK_IMPORTED_MODULE_130__mergeDeepWith__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_131__mergeDeepWithKey__ = __webpack_require__(148);
- __webpack_require__.d(__webpack_exports__, "mergeDeepWithKey", function() {
- return __WEBPACK_IMPORTED_MODULE_131__mergeDeepWithKey__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_132__mergeWith__ = __webpack_require__(693);
- __webpack_require__.d(__webpack_exports__, "mergeWith", function() {
- return __WEBPACK_IMPORTED_MODULE_132__mergeWith__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_133__mergeWithKey__ = __webpack_require__(219);
- __webpack_require__.d(__webpack_exports__, "mergeWithKey", function() {
- return __WEBPACK_IMPORTED_MODULE_133__mergeWithKey__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_134__min__ = __webpack_require__(694);
- __webpack_require__.d(__webpack_exports__, "min", function() {
- return __WEBPACK_IMPORTED_MODULE_134__min__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_135__minBy__ = __webpack_require__(695);
- __webpack_require__.d(__webpack_exports__, "minBy", function() {
- return __WEBPACK_IMPORTED_MODULE_135__minBy__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_136__modulo__ = __webpack_require__(696);
- __webpack_require__.d(__webpack_exports__, "modulo", function() {
- return __WEBPACK_IMPORTED_MODULE_136__modulo__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_137__multiply__ = __webpack_require__(342);
- __webpack_require__.d(__webpack_exports__, "multiply", function() {
- return __WEBPACK_IMPORTED_MODULE_137__multiply__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_138__nAry__ = __webpack_require__(139);
- __webpack_require__.d(__webpack_exports__, "nAry", function() {
- return __WEBPACK_IMPORTED_MODULE_138__nAry__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_139__negate__ = __webpack_require__(697);
- __webpack_require__.d(__webpack_exports__, "negate", function() {
- return __WEBPACK_IMPORTED_MODULE_139__negate__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_140__none__ = __webpack_require__(698);
- __webpack_require__.d(__webpack_exports__, "none", function() {
- return __WEBPACK_IMPORTED_MODULE_140__none__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_141__not__ = __webpack_require__(312);
- __webpack_require__.d(__webpack_exports__, "not", function() {
- return __WEBPACK_IMPORTED_MODULE_141__not__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_142__nth__ = __webpack_require__(101);
- __webpack_require__.d(__webpack_exports__, "nth", function() {
- return __WEBPACK_IMPORTED_MODULE_142__nth__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_143__nthArg__ = __webpack_require__(699);
- __webpack_require__.d(__webpack_exports__, "nthArg", function() {
- return __WEBPACK_IMPORTED_MODULE_143__nthArg__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_144__o__ = __webpack_require__(700);
- __webpack_require__.d(__webpack_exports__, "o", function() {
- return __WEBPACK_IMPORTED_MODULE_144__o__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_145__objOf__ = __webpack_require__(334);
- __webpack_require__.d(__webpack_exports__, "objOf", function() {
- return __WEBPACK_IMPORTED_MODULE_145__objOf__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_146__of__ = __webpack_require__(701);
- __webpack_require__.d(__webpack_exports__, "of", function() {
- return __WEBPACK_IMPORTED_MODULE_146__of__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_147__omit__ = __webpack_require__(703);
- __webpack_require__.d(__webpack_exports__, "omit", function() {
- return __WEBPACK_IMPORTED_MODULE_147__omit__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_148__once__ = __webpack_require__(704);
- __webpack_require__.d(__webpack_exports__, "once", function() {
- return __WEBPACK_IMPORTED_MODULE_148__once__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_149__or__ = __webpack_require__(330);
- __webpack_require__.d(__webpack_exports__, "or", function() {
- return __WEBPACK_IMPORTED_MODULE_149__or__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_150__over__ = __webpack_require__(343);
- __webpack_require__.d(__webpack_exports__, "over", function() {
- return __WEBPACK_IMPORTED_MODULE_150__over__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_151__pair__ = __webpack_require__(705);
- __webpack_require__.d(__webpack_exports__, "pair", function() {
- return __WEBPACK_IMPORTED_MODULE_151__pair__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_152__partial__ = __webpack_require__(706);
- __webpack_require__.d(__webpack_exports__, "partial", function() {
- return __WEBPACK_IMPORTED_MODULE_152__partial__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_153__partialRight__ = __webpack_require__(707);
- __webpack_require__.d(__webpack_exports__, "partialRight", function() {
- return __WEBPACK_IMPORTED_MODULE_153__partialRight__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_154__partition__ = __webpack_require__(708);
- __webpack_require__.d(__webpack_exports__, "partition", function() {
- return __WEBPACK_IMPORTED_MODULE_154__partition__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_155__path__ = __webpack_require__(80);
- __webpack_require__.d(__webpack_exports__, "path", function() {
- return __WEBPACK_IMPORTED_MODULE_155__path__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_156__pathEq__ = __webpack_require__(709);
- __webpack_require__.d(__webpack_exports__, "pathEq", function() {
- return __WEBPACK_IMPORTED_MODULE_156__pathEq__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_157__pathOr__ = __webpack_require__(710);
- __webpack_require__.d(__webpack_exports__, "pathOr", function() {
- return __WEBPACK_IMPORTED_MODULE_157__pathOr__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_158__pathSatisfies__ = __webpack_require__(711);
- __webpack_require__.d(__webpack_exports__, "pathSatisfies", function() {
- return __WEBPACK_IMPORTED_MODULE_158__pathSatisfies__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_159__pick__ = __webpack_require__(712);
- __webpack_require__.d(__webpack_exports__, "pick", function() {
- return __WEBPACK_IMPORTED_MODULE_159__pick__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_160__pickAll__ = __webpack_require__(345);
- __webpack_require__.d(__webpack_exports__, "pickAll", function() {
- return __WEBPACK_IMPORTED_MODULE_160__pickAll__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_161__pickBy__ = __webpack_require__(713);
- __webpack_require__.d(__webpack_exports__, "pickBy", function() {
- return __WEBPACK_IMPORTED_MODULE_161__pickBy__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_162__pipe__ = __webpack_require__(313);
- __webpack_require__.d(__webpack_exports__, "pipe", function() {
- return __WEBPACK_IMPORTED_MODULE_162__pipe__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_163__pipeK__ = __webpack_require__(714);
- __webpack_require__.d(__webpack_exports__, "pipeK", function() {
- return __WEBPACK_IMPORTED_MODULE_163__pipeK__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_164__pipeP__ = __webpack_require__(315);
- __webpack_require__.d(__webpack_exports__, "pipeP", function() {
- return __WEBPACK_IMPORTED_MODULE_164__pipeP__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_165__pluck__ = __webpack_require__(97);
- __webpack_require__.d(__webpack_exports__, "pluck", function() {
- return __WEBPACK_IMPORTED_MODULE_165__pluck__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_166__prepend__ = __webpack_require__(346);
- __webpack_require__.d(__webpack_exports__, "prepend", function() {
- return __WEBPACK_IMPORTED_MODULE_166__prepend__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_167__product__ = __webpack_require__(715);
- __webpack_require__.d(__webpack_exports__, "product", function() {
- return __WEBPACK_IMPORTED_MODULE_167__product__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_168__project__ = __webpack_require__(716);
- __webpack_require__.d(__webpack_exports__, "project", function() {
- return __WEBPACK_IMPORTED_MODULE_168__project__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_169__prop__ = __webpack_require__(201);
- __webpack_require__.d(__webpack_exports__, "prop", function() {
- return __WEBPACK_IMPORTED_MODULE_169__prop__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_170__propEq__ = __webpack_require__(717);
- __webpack_require__.d(__webpack_exports__, "propEq", function() {
- return __WEBPACK_IMPORTED_MODULE_170__propEq__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_171__propIs__ = __webpack_require__(718);
- __webpack_require__.d(__webpack_exports__, "propIs", function() {
- return __WEBPACK_IMPORTED_MODULE_171__propIs__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_172__propOr__ = __webpack_require__(719);
- __webpack_require__.d(__webpack_exports__, "propOr", function() {
- return __WEBPACK_IMPORTED_MODULE_172__propOr__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_173__propSatisfies__ = __webpack_require__(720);
- __webpack_require__.d(__webpack_exports__, "propSatisfies", function() {
- return __WEBPACK_IMPORTED_MODULE_173__propSatisfies__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_174__props__ = __webpack_require__(721);
- __webpack_require__.d(__webpack_exports__, "props", function() {
- return __WEBPACK_IMPORTED_MODULE_174__props__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_175__range__ = __webpack_require__(722);
- __webpack_require__.d(__webpack_exports__, "range", function() {
- return __WEBPACK_IMPORTED_MODULE_175__range__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_176__reduce__ = __webpack_require__(45);
- __webpack_require__.d(__webpack_exports__, "reduce", function() {
- return __WEBPACK_IMPORTED_MODULE_176__reduce__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_177__reduceBy__ = __webpack_require__(145);
- __webpack_require__.d(__webpack_exports__, "reduceBy", function() {
- return __WEBPACK_IMPORTED_MODULE_177__reduceBy__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_178__reduceRight__ = __webpack_require__(348);
- __webpack_require__.d(__webpack_exports__, "reduceRight", function() {
- return __WEBPACK_IMPORTED_MODULE_178__reduceRight__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_179__reduceWhile__ = __webpack_require__(723);
- __webpack_require__.d(__webpack_exports__, "reduceWhile", function() {
- return __WEBPACK_IMPORTED_MODULE_179__reduceWhile__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_180__reduced__ = __webpack_require__(724);
- __webpack_require__.d(__webpack_exports__, "reduced", function() {
- return __WEBPACK_IMPORTED_MODULE_180__reduced__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_181__reject__ = __webpack_require__(144);
- __webpack_require__.d(__webpack_exports__, "reject", function() {
- return __WEBPACK_IMPORTED_MODULE_181__reject__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_182__remove__ = __webpack_require__(325);
- __webpack_require__.d(__webpack_exports__, "remove", function() {
- return __WEBPACK_IMPORTED_MODULE_182__remove__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_183__repeat__ = __webpack_require__(725);
- __webpack_require__.d(__webpack_exports__, "repeat", function() {
- return __WEBPACK_IMPORTED_MODULE_183__repeat__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_184__replace__ = __webpack_require__(726);
- __webpack_require__.d(__webpack_exports__, "replace", function() {
- return __WEBPACK_IMPORTED_MODULE_184__replace__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_185__reverse__ = __webpack_require__(142);
- __webpack_require__.d(__webpack_exports__, "reverse", function() {
- return __WEBPACK_IMPORTED_MODULE_185__reverse__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_186__scan__ = __webpack_require__(727);
- __webpack_require__.d(__webpack_exports__, "scan", function() {
- return __WEBPACK_IMPORTED_MODULE_186__scan__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_187__sequence__ = __webpack_require__(350);
- __webpack_require__.d(__webpack_exports__, "sequence", function() {
- return __WEBPACK_IMPORTED_MODULE_187__sequence__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_188__set__ = __webpack_require__(728);
- __webpack_require__.d(__webpack_exports__, "set", function() {
- return __WEBPACK_IMPORTED_MODULE_188__set__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_189__slice__ = __webpack_require__(34);
- __webpack_require__.d(__webpack_exports__, "slice", function() {
- return __WEBPACK_IMPORTED_MODULE_189__slice__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_190__sort__ = __webpack_require__(729);
- __webpack_require__.d(__webpack_exports__, "sort", function() {
- return __WEBPACK_IMPORTED_MODULE_190__sort__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_191__sortBy__ = __webpack_require__(730);
- __webpack_require__.d(__webpack_exports__, "sortBy", function() {
- return __WEBPACK_IMPORTED_MODULE_191__sortBy__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_192__sortWith__ = __webpack_require__(731);
- __webpack_require__.d(__webpack_exports__, "sortWith", function() {
- return __WEBPACK_IMPORTED_MODULE_192__sortWith__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_193__split__ = __webpack_require__(732);
- __webpack_require__.d(__webpack_exports__, "split", function() {
- return __WEBPACK_IMPORTED_MODULE_193__split__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_194__splitAt__ = __webpack_require__(733);
- __webpack_require__.d(__webpack_exports__, "splitAt", function() {
- return __WEBPACK_IMPORTED_MODULE_194__splitAt__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_195__splitEvery__ = __webpack_require__(734);
- __webpack_require__.d(__webpack_exports__, "splitEvery", function() {
- return __WEBPACK_IMPORTED_MODULE_195__splitEvery__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_196__splitWhen__ = __webpack_require__(735);
- __webpack_require__.d(__webpack_exports__, "splitWhen", function() {
- return __WEBPACK_IMPORTED_MODULE_196__splitWhen__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_197__startsWith__ = __webpack_require__(736);
- __webpack_require__.d(__webpack_exports__, "startsWith", function() {
- return __WEBPACK_IMPORTED_MODULE_197__startsWith__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_198__subtract__ = __webpack_require__(737);
- __webpack_require__.d(__webpack_exports__, "subtract", function() {
- return __WEBPACK_IMPORTED_MODULE_198__subtract__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_199__sum__ = __webpack_require__(340);
- __webpack_require__.d(__webpack_exports__, "sum", function() {
- return __WEBPACK_IMPORTED_MODULE_199__sum__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_200__symmetricDifference__ = __webpack_require__(738);
- __webpack_require__.d(__webpack_exports__, "symmetricDifference", function() {
- return __WEBPACK_IMPORTED_MODULE_200__symmetricDifference__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_201__symmetricDifferenceWith__ = __webpack_require__(739);
- __webpack_require__.d(__webpack_exports__, "symmetricDifferenceWith", function() {
- return __WEBPACK_IMPORTED_MODULE_201__symmetricDifferenceWith__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_202__tail__ = __webpack_require__(208);
- __webpack_require__.d(__webpack_exports__, "tail", function() {
- return __WEBPACK_IMPORTED_MODULE_202__tail__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_203__take__ = __webpack_require__(214);
- __webpack_require__.d(__webpack_exports__, "take", function() {
- return __WEBPACK_IMPORTED_MODULE_203__take__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_204__takeLast__ = __webpack_require__(332);
- __webpack_require__.d(__webpack_exports__, "takeLast", function() {
- return __WEBPACK_IMPORTED_MODULE_204__takeLast__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_205__takeLastWhile__ = __webpack_require__(740);
- __webpack_require__.d(__webpack_exports__, "takeLastWhile", function() {
- return __WEBPACK_IMPORTED_MODULE_205__takeLastWhile__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_206__takeWhile__ = __webpack_require__(741);
- __webpack_require__.d(__webpack_exports__, "takeWhile", function() {
- return __WEBPACK_IMPORTED_MODULE_206__takeWhile__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_207__tap__ = __webpack_require__(743);
- __webpack_require__.d(__webpack_exports__, "tap", function() {
- return __WEBPACK_IMPORTED_MODULE_207__tap__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_208__test__ = __webpack_require__(745);
- __webpack_require__.d(__webpack_exports__, "test", function() {
- return __WEBPACK_IMPORTED_MODULE_208__test__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_209__times__ = __webpack_require__(349);
- __webpack_require__.d(__webpack_exports__, "times", function() {
- return __WEBPACK_IMPORTED_MODULE_209__times__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_210__toLower__ = __webpack_require__(747);
- __webpack_require__.d(__webpack_exports__, "toLower", function() {
- return __WEBPACK_IMPORTED_MODULE_210__toLower__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_211__toPairs__ = __webpack_require__(748);
- __webpack_require__.d(__webpack_exports__, "toPairs", function() {
- return __WEBPACK_IMPORTED_MODULE_211__toPairs__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_212__toPairsIn__ = __webpack_require__(749);
- __webpack_require__.d(__webpack_exports__, "toPairsIn", function() {
- return __WEBPACK_IMPORTED_MODULE_212__toPairsIn__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_213__toString__ = __webpack_require__(100);
- __webpack_require__.d(__webpack_exports__, "toString", function() {
- return __WEBPACK_IMPORTED_MODULE_213__toString__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_214__toUpper__ = __webpack_require__(750);
- __webpack_require__.d(__webpack_exports__, "toUpper", function() {
- return __WEBPACK_IMPORTED_MODULE_214__toUpper__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_215__transduce__ = __webpack_require__(751);
- __webpack_require__.d(__webpack_exports__, "transduce", function() {
- return __WEBPACK_IMPORTED_MODULE_215__transduce__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_216__transpose__ = __webpack_require__(752);
- __webpack_require__.d(__webpack_exports__, "transpose", function() {
- return __WEBPACK_IMPORTED_MODULE_216__transpose__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_217__traverse__ = __webpack_require__(753);
- __webpack_require__.d(__webpack_exports__, "traverse", function() {
- return __WEBPACK_IMPORTED_MODULE_217__traverse__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_218__trim__ = __webpack_require__(754);
- __webpack_require__.d(__webpack_exports__, "trim", function() {
- return __WEBPACK_IMPORTED_MODULE_218__trim__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_219__tryCatch__ = __webpack_require__(755);
- __webpack_require__.d(__webpack_exports__, "tryCatch", function() {
- return __WEBPACK_IMPORTED_MODULE_219__tryCatch__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_220__type__ = __webpack_require__(206);
- __webpack_require__.d(__webpack_exports__, "type", function() {
- return __WEBPACK_IMPORTED_MODULE_220__type__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_221__unapply__ = __webpack_require__(756);
- __webpack_require__.d(__webpack_exports__, "unapply", function() {
- return __WEBPACK_IMPORTED_MODULE_221__unapply__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_222__unary__ = __webpack_require__(757);
- __webpack_require__.d(__webpack_exports__, "unary", function() {
- return __WEBPACK_IMPORTED_MODULE_222__unary__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_223__uncurryN__ = __webpack_require__(758);
- __webpack_require__.d(__webpack_exports__, "uncurryN", function() {
- return __WEBPACK_IMPORTED_MODULE_223__uncurryN__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_224__unfold__ = __webpack_require__(759);
- __webpack_require__.d(__webpack_exports__, "unfold", function() {
- return __WEBPACK_IMPORTED_MODULE_224__unfold__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_225__union__ = __webpack_require__(760);
- __webpack_require__.d(__webpack_exports__, "union", function() {
- return __WEBPACK_IMPORTED_MODULE_225__union__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_226__unionWith__ = __webpack_require__(761);
- __webpack_require__.d(__webpack_exports__, "unionWith", function() {
- return __WEBPACK_IMPORTED_MODULE_226__unionWith__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_227__uniq__ = __webpack_require__(217);
- __webpack_require__.d(__webpack_exports__, "uniq", function() {
- return __WEBPACK_IMPORTED_MODULE_227__uniq__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_228__uniqBy__ = __webpack_require__(333);
- __webpack_require__.d(__webpack_exports__, "uniqBy", function() {
- return __WEBPACK_IMPORTED_MODULE_228__uniqBy__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_229__uniqWith__ = __webpack_require__(351);
- __webpack_require__.d(__webpack_exports__, "uniqWith", function() {
- return __WEBPACK_IMPORTED_MODULE_229__uniqWith__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_230__unless__ = __webpack_require__(762);
- __webpack_require__.d(__webpack_exports__, "unless", function() {
- return __WEBPACK_IMPORTED_MODULE_230__unless__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_231__unnest__ = __webpack_require__(763);
- __webpack_require__.d(__webpack_exports__, "unnest", function() {
- return __WEBPACK_IMPORTED_MODULE_231__unnest__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_232__until__ = __webpack_require__(764);
- __webpack_require__.d(__webpack_exports__, "until", function() {
- return __WEBPACK_IMPORTED_MODULE_232__until__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_233__update__ = __webpack_require__(213);
- __webpack_require__.d(__webpack_exports__, "update", function() {
- return __WEBPACK_IMPORTED_MODULE_233__update__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_234__useWith__ = __webpack_require__(347);
- __webpack_require__.d(__webpack_exports__, "useWith", function() {
- return __WEBPACK_IMPORTED_MODULE_234__useWith__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_235__values__ = __webpack_require__(305);
- __webpack_require__.d(__webpack_exports__, "values", function() {
- return __WEBPACK_IMPORTED_MODULE_235__values__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_236__valuesIn__ = __webpack_require__(765);
- __webpack_require__.d(__webpack_exports__, "valuesIn", function() {
- return __WEBPACK_IMPORTED_MODULE_236__valuesIn__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_237__view__ = __webpack_require__(766);
- __webpack_require__.d(__webpack_exports__, "view", function() {
- return __WEBPACK_IMPORTED_MODULE_237__view__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_238__when__ = __webpack_require__(767);
- __webpack_require__.d(__webpack_exports__, "when", function() {
- return __WEBPACK_IMPORTED_MODULE_238__when__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_239__where__ = __webpack_require__(352);
- __webpack_require__.d(__webpack_exports__, "where", function() {
- return __WEBPACK_IMPORTED_MODULE_239__where__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_240__whereEq__ = __webpack_require__(768);
- __webpack_require__.d(__webpack_exports__, "whereEq", function() {
- return __WEBPACK_IMPORTED_MODULE_240__whereEq__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_241__without__ = __webpack_require__(769);
- __webpack_require__.d(__webpack_exports__, "without", function() {
- return __WEBPACK_IMPORTED_MODULE_241__without__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_242__xprod__ = __webpack_require__(770);
- __webpack_require__.d(__webpack_exports__, "xprod", function() {
- return __WEBPACK_IMPORTED_MODULE_242__xprod__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_243__zip__ = __webpack_require__(771);
- __webpack_require__.d(__webpack_exports__, "zip", function() {
- return __WEBPACK_IMPORTED_MODULE_243__zip__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_244__zipObj__ = __webpack_require__(772);
- __webpack_require__.d(__webpack_exports__, "zipObj", function() {
- return __WEBPACK_IMPORTED_MODULE_244__zipObj__.a;
- });
- var __WEBPACK_IMPORTED_MODULE_245__zipWith__ = __webpack_require__(773);
- __webpack_require__.d(__webpack_exports__, "zipWith", function() {
- return __WEBPACK_IMPORTED_MODULE_245__zipWith__.a;
- });
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__always__ = __webpack_require__(78), F = Object(__WEBPACK_IMPORTED_MODULE_0__always__.a)(!1);
- __webpack_exports__.a = F;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__always__ = __webpack_require__(78), T = Object(__WEBPACK_IMPORTED_MODULE_0__always__.a)(!0);
- __webpack_exports__.a = T;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- __webpack_exports__.a = {
- "@@functional/placeholder": !0
- };
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_concat__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_1__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_2__curryN__ = __webpack_require__(23), addIndex = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry1__.a)(function(fn) {
- return Object(__WEBPACK_IMPORTED_MODULE_2__curryN__.a)(fn.length, function() {
- var idx = 0, origFn = arguments[0], list = arguments[arguments.length - 1], args = Array.prototype.slice.call(arguments, 0);
- return args[0] = function() {
- var result = origFn.apply(this, Object(__WEBPACK_IMPORTED_MODULE_0__internal_concat__.a)(arguments, [ idx, list ]));
- return idx += 1, result;
- }, fn.apply(this, args);
- });
- });
- __webpack_exports__.a = addIndex;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_xall__ = __webpack_require__(580), all = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([ "all" ], __WEBPACK_IMPORTED_MODULE_2__internal_xall__.a, function(fn, list) {
- for (var idx = 0; idx < list.length; ) {
- if (!fn(list[idx])) return !1;
- idx += 1;
- }
- return !0;
- }));
- __webpack_exports__.a = all;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__reduced__ = __webpack_require__(58), __WEBPACK_IMPORTED_MODULE_2__xfBase__ = __webpack_require__(19), XAll = function() {
- function XAll(f, xf) {
- this.xf = xf, this.f = f, this.all = !0;
- }
- return XAll.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_2__xfBase__.a.init,
- XAll.prototype["@@transducer/result"] = function(result) {
- return this.all && (result = this.xf["@@transducer/step"](result, !0)), this.xf["@@transducer/result"](result);
- }, XAll.prototype["@@transducer/step"] = function(result, input) {
- return this.f(input) || (this.all = !1, result = Object(__WEBPACK_IMPORTED_MODULE_1__reduced__.a)(this.xf["@@transducer/step"](result, !1))),
- result;
- }, XAll;
- }(), _xall = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(f, xf) {
- return new XAll(f, xf);
- });
- __webpack_exports__.a = _xall;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__curryN__ = __webpack_require__(23), __WEBPACK_IMPORTED_MODULE_2__max__ = __webpack_require__(79), __WEBPACK_IMPORTED_MODULE_3__pluck__ = __webpack_require__(97), __WEBPACK_IMPORTED_MODULE_4__reduce__ = __webpack_require__(45), allPass = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(preds) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__curryN__.a)(Object(__WEBPACK_IMPORTED_MODULE_4__reduce__.a)(__WEBPACK_IMPORTED_MODULE_2__max__.a, 0, Object(__WEBPACK_IMPORTED_MODULE_3__pluck__.a)("length", preds)), function() {
- for (var idx = 0, len = preds.length; idx < len; ) {
- if (!preds[idx].apply(this, arguments)) return !1;
- idx += 1;
- }
- return !0;
- });
- });
- __webpack_exports__.a = allPass;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__xfBase__ = __webpack_require__(19), XMap = function() {
- function XMap(f, xf) {
- this.xf = xf, this.f = f;
- }
- return XMap.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_1__xfBase__.a.init,
- XMap.prototype["@@transducer/result"] = __WEBPACK_IMPORTED_MODULE_1__xfBase__.a.result,
- XMap.prototype["@@transducer/step"] = function(result, input) {
- return this.xf["@@transducer/step"](result, this.f(input));
- }, XMap;
- }(), _xmap = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(f, xf) {
- return new XMap(f, xf);
- });
- __webpack_exports__.a = _xmap;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__curryN__ = __webpack_require__(23), __WEBPACK_IMPORTED_MODULE_2__max__ = __webpack_require__(79), __WEBPACK_IMPORTED_MODULE_3__pluck__ = __webpack_require__(97), __WEBPACK_IMPORTED_MODULE_4__reduce__ = __webpack_require__(45), anyPass = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(preds) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__curryN__.a)(Object(__WEBPACK_IMPORTED_MODULE_4__reduce__.a)(__WEBPACK_IMPORTED_MODULE_2__max__.a, 0, Object(__WEBPACK_IMPORTED_MODULE_3__pluck__.a)("length", preds)), function() {
- for (var idx = 0, len = preds.length; idx < len; ) {
- if (preds[idx].apply(this, arguments)) return !0;
- idx += 1;
- }
- return !1;
- });
- });
- __webpack_exports__.a = anyPass;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_aperture__ = __webpack_require__(585), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_3__internal_xaperture__ = __webpack_require__(586), aperture = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__internal_dispatchable__.a)([], __WEBPACK_IMPORTED_MODULE_3__internal_xaperture__.a, __WEBPACK_IMPORTED_MODULE_0__internal_aperture__.a));
- __webpack_exports__.a = aperture;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _aperture(n, list) {
- for (var idx = 0, limit = list.length - (n - 1), acc = new Array(limit >= 0 ? limit : 0); idx < limit; ) acc[idx] = Array.prototype.slice.call(list, idx, idx + n),
- idx += 1;
- return acc;
- }
- __webpack_exports__.a = _aperture;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__concat__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_1__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2__xfBase__ = __webpack_require__(19), XAperture = function() {
- function XAperture(n, xf) {
- this.xf = xf, this.pos = 0, this.full = !1, this.acc = new Array(n);
- }
- return XAperture.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_2__xfBase__.a.init,
- XAperture.prototype["@@transducer/result"] = function(result) {
- return this.acc = null, this.xf["@@transducer/result"](result);
- }, XAperture.prototype["@@transducer/step"] = function(result, input) {
- return this.store(input), this.full ? this.xf["@@transducer/step"](result, this.getCopy()) : result;
- }, XAperture.prototype.store = function(input) {
- this.acc[this.pos] = input, this.pos += 1, this.pos === this.acc.length && (this.pos = 0,
- this.full = !0);
- }, XAperture.prototype.getCopy = function() {
- return Object(__WEBPACK_IMPORTED_MODULE_0__concat__.a)(Array.prototype.slice.call(this.acc, this.pos), Array.prototype.slice.call(this.acc, 0, this.pos));
- }, XAperture;
- }(), _xaperture = Object(__WEBPACK_IMPORTED_MODULE_1__curry2__.a)(function(n, xf) {
- return new XAperture(n, xf);
- });
- __webpack_exports__.a = _xaperture;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_concat__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), append = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(function(el, list) {
- return Object(__WEBPACK_IMPORTED_MODULE_0__internal_concat__.a)(list, [ el ]);
- });
- __webpack_exports__.a = append;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__apply__ = __webpack_require__(304), __WEBPACK_IMPORTED_MODULE_2__curryN__ = __webpack_require__(23), __WEBPACK_IMPORTED_MODULE_3__map__ = __webpack_require__(27), __WEBPACK_IMPORTED_MODULE_4__max__ = __webpack_require__(79), __WEBPACK_IMPORTED_MODULE_5__pluck__ = __webpack_require__(97), __WEBPACK_IMPORTED_MODULE_6__reduce__ = __webpack_require__(45), __WEBPACK_IMPORTED_MODULE_7__values__ = __webpack_require__(305), applySpec = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function applySpec(spec) {
- return spec = Object(__WEBPACK_IMPORTED_MODULE_3__map__.a)(function(v) {
- return "function" == typeof v ? v : applySpec(v);
- }, spec), Object(__WEBPACK_IMPORTED_MODULE_2__curryN__.a)(Object(__WEBPACK_IMPORTED_MODULE_6__reduce__.a)(__WEBPACK_IMPORTED_MODULE_4__max__.a, 0, Object(__WEBPACK_IMPORTED_MODULE_5__pluck__.a)("length", Object(__WEBPACK_IMPORTED_MODULE_7__values__.a)(spec))), function() {
- var args = arguments;
- return Object(__WEBPACK_IMPORTED_MODULE_3__map__.a)(function(f) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__apply__.a)(f, args);
- }, spec);
- });
- });
- __webpack_exports__.a = applySpec;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), applyTo = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(x, f) {
- return f(x);
- });
- __webpack_exports__.a = applyTo;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), ascend = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(fn, a, b) {
- var aa = fn(a), bb = fn(b);
- return aa < bb ? -1 : aa > bb ? 1 : 0;
- });
- __webpack_exports__.a = ascend;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__nAry__ = __webpack_require__(139), binary = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(fn) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__nAry__.a)(2, fn);
- });
- __webpack_exports__.a = binary;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_isFunction__ = __webpack_require__(140), __WEBPACK_IMPORTED_MODULE_2__and__ = __webpack_require__(301), __WEBPACK_IMPORTED_MODULE_3__lift__ = __webpack_require__(141), both = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(f, g) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__internal_isFunction__.a)(f) ? function() {
- return f.apply(this, arguments) && g.apply(this, arguments);
- } : Object(__WEBPACK_IMPORTED_MODULE_3__lift__.a)(__WEBPACK_IMPORTED_MODULE_2__and__.a)(f, g);
- });
- __webpack_exports__.a = both;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry__ = __webpack_require__(204), call = Object(__WEBPACK_IMPORTED_MODULE_0__curry__.a)(function(fn) {
- return fn.apply(this, Array.prototype.slice.call(arguments, 1));
- });
- __webpack_exports__.a = call;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__flatCat__ = __webpack_require__(595), __WEBPACK_IMPORTED_MODULE_2__map__ = __webpack_require__(27), _xchain = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(f, xf) {
- return Object(__WEBPACK_IMPORTED_MODULE_2__map__.a)(f, Object(__WEBPACK_IMPORTED_MODULE_1__flatCat__.a)(xf));
- });
- __webpack_exports__.a = _xchain;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__forceReduced__ = __webpack_require__(596), __WEBPACK_IMPORTED_MODULE_1__isArrayLike__ = __webpack_require__(137), __WEBPACK_IMPORTED_MODULE_2__reduce__ = __webpack_require__(30), __WEBPACK_IMPORTED_MODULE_3__xfBase__ = __webpack_require__(19), preservingReduced = function(xf) {
- return {
- "@@transducer/init": __WEBPACK_IMPORTED_MODULE_3__xfBase__.a.init,
- "@@transducer/result": function(result) {
- return xf["@@transducer/result"](result);
- },
- "@@transducer/step": function(result, input) {
- var ret = xf["@@transducer/step"](result, input);
- return ret["@@transducer/reduced"] ? Object(__WEBPACK_IMPORTED_MODULE_0__forceReduced__.a)(ret) : ret;
- }
- };
- }, _flatCat = function(xf) {
- var rxf = preservingReduced(xf);
- return {
- "@@transducer/init": __WEBPACK_IMPORTED_MODULE_3__xfBase__.a.init,
- "@@transducer/result": function(result) {
- return rxf["@@transducer/result"](result);
- },
- "@@transducer/step": function(result, input) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__isArrayLike__.a)(input) ? Object(__WEBPACK_IMPORTED_MODULE_2__reduce__.a)(rxf, result, input) : Object(__WEBPACK_IMPORTED_MODULE_2__reduce__.a)(rxf, result, [ input ]);
- }
- };
- };
- __webpack_exports__.a = _flatCat;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _forceReduced(x) {
- return {
- "@@transducer/value": x,
- "@@transducer/reduced": !0
- };
- }
- __webpack_exports__.a = _forceReduced;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), clamp = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(min, max, value) {
- if (min > max) throw new Error("min must not be greater than max in clamp(min, max, value)");
- return value < min ? min : value > max ? max : value;
- });
- __webpack_exports__.a = clamp;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_clone__ = __webpack_require__(310), __WEBPACK_IMPORTED_MODULE_1__internal_curry1__ = __webpack_require__(4), clone = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry1__.a)(function(value) {
- return null != value && "function" == typeof value.clone ? value.clone() : Object(__WEBPACK_IMPORTED_MODULE_0__internal_clone__.a)(value, [], [], !0);
- });
- __webpack_exports__.a = clone;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), comparator = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(pred) {
- return function(a, b) {
- return pred(a, b) ? -1 : pred(b, a) ? 1 : 0;
- };
- });
- __webpack_exports__.a = comparator;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__lift__ = __webpack_require__(141), __WEBPACK_IMPORTED_MODULE_1__not__ = __webpack_require__(312), complement = Object(__WEBPACK_IMPORTED_MODULE_0__lift__.a)(__WEBPACK_IMPORTED_MODULE_1__not__.a);
- __webpack_exports__.a = complement;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _pipe(f, g) {
- return function() {
- return g.call(this, f.apply(this, arguments));
- };
- }
- __webpack_exports__.a = _pipe;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function composeP() {
- if (0 === arguments.length) throw new Error("composeP requires at least one argument");
- return __WEBPACK_IMPORTED_MODULE_0__pipeP__.a.apply(this, Object(__WEBPACK_IMPORTED_MODULE_1__reverse__.a)(arguments));
- }
- __webpack_exports__.a = composeP;
- var __WEBPACK_IMPORTED_MODULE_0__pipeP__ = __webpack_require__(315), __WEBPACK_IMPORTED_MODULE_1__reverse__ = __webpack_require__(142);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _pipeP(f, g) {
- return function() {
- var ctx = this;
- return f.apply(ctx, arguments).then(function(x) {
- return g.call(ctx, x);
- });
- };
- }
- __webpack_exports__.a = _pipeP;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _toString(x, seen) {
- var recur = function(y) {
- var xs = seen.concat([ x ]);
- return Object(__WEBPACK_IMPORTED_MODULE_0__contains__.a)(y, xs) ? "<Circular>" : _toString(y, xs);
- }, mapPairs = function(obj, keys) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__map__.a)(function(k) {
- return Object(__WEBPACK_IMPORTED_MODULE_2__quote__.a)(k) + ": " + recur(obj[k]);
- }, keys.slice().sort());
- };
- switch (Object.prototype.toString.call(x)) {
- case "[object Arguments]":
- return "(function() { return arguments; }(" + Object(__WEBPACK_IMPORTED_MODULE_1__map__.a)(recur, x).join(", ") + "))";
-
- case "[object Array]":
- return "[" + Object(__WEBPACK_IMPORTED_MODULE_1__map__.a)(recur, x).concat(mapPairs(x, Object(__WEBPACK_IMPORTED_MODULE_5__reject__.a)(function(k) {
- return /^\d+$/.test(k);
- }, Object(__WEBPACK_IMPORTED_MODULE_4__keys__.a)(x)))).join(", ") + "]";
-
- case "[object Boolean]":
- return "object" == typeof x ? "new Boolean(" + recur(x.valueOf()) + ")" : x.toString();
-
- case "[object Date]":
- return "new Date(" + (isNaN(x.valueOf()) ? recur(NaN) : Object(__WEBPACK_IMPORTED_MODULE_2__quote__.a)(Object(__WEBPACK_IMPORTED_MODULE_3__toISOString__.a)(x))) + ")";
-
- case "[object Null]":
- return "null";
-
- case "[object Number]":
- return "object" == typeof x ? "new Number(" + recur(x.valueOf()) + ")" : 1 / x == -1 / 0 ? "-0" : x.toString(10);
-
- case "[object String]":
- return "object" == typeof x ? "new String(" + recur(x.valueOf()) + ")" : Object(__WEBPACK_IMPORTED_MODULE_2__quote__.a)(x);
-
- case "[object Undefined]":
- return "undefined";
-
- default:
- if ("function" == typeof x.toString) {
- var repr = x.toString();
- if ("[object Object]" !== repr) return repr;
- }
- return "{" + mapPairs(x, Object(__WEBPACK_IMPORTED_MODULE_4__keys__.a)(x)).join(", ") + "}";
- }
- }
- __webpack_exports__.a = _toString;
- var __WEBPACK_IMPORTED_MODULE_0__contains__ = __webpack_require__(81), __WEBPACK_IMPORTED_MODULE_1__map__ = __webpack_require__(136), __WEBPACK_IMPORTED_MODULE_2__quote__ = __webpack_require__(608), __WEBPACK_IMPORTED_MODULE_3__toISOString__ = __webpack_require__(609), __WEBPACK_IMPORTED_MODULE_4__keys__ = __webpack_require__(44), __WEBPACK_IMPORTED_MODULE_5__reject__ = __webpack_require__(144);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _uniqContentEquals(aIterator, bIterator, stackA, stackB) {
- function eq(_a, _b) {
- return _equals(_a, _b, stackA.slice(), stackB.slice());
- }
- var a = Object(__WEBPACK_IMPORTED_MODULE_0__arrayFromIterator__.a)(aIterator), b = Object(__WEBPACK_IMPORTED_MODULE_0__arrayFromIterator__.a)(bIterator);
- return !Object(__WEBPACK_IMPORTED_MODULE_1__containsWith__.a)(function(b, aItem) {
- return !Object(__WEBPACK_IMPORTED_MODULE_1__containsWith__.a)(eq, aItem, b);
- }, b, a);
- }
- function _equals(a, b, stackA, stackB) {
- if (Object(__WEBPACK_IMPORTED_MODULE_4__identical__.a)(a, b)) return !0;
- var typeA = Object(__WEBPACK_IMPORTED_MODULE_6__type__.a)(a);
- if (typeA !== Object(__WEBPACK_IMPORTED_MODULE_6__type__.a)(b)) return !1;
- if (null == a || null == b) return !1;
- if ("function" == typeof a["fantasy-land/equals"] || "function" == typeof b["fantasy-land/equals"]) return "function" == typeof a["fantasy-land/equals"] && a["fantasy-land/equals"](b) && "function" == typeof b["fantasy-land/equals"] && b["fantasy-land/equals"](a);
- if ("function" == typeof a.equals || "function" == typeof b.equals) return "function" == typeof a.equals && a.equals(b) && "function" == typeof b.equals && b.equals(a);
- switch (typeA) {
- case "Arguments":
- case "Array":
- case "Object":
- if ("function" == typeof a.constructor && "Promise" === Object(__WEBPACK_IMPORTED_MODULE_2__functionName__.a)(a.constructor)) return a === b;
- break;
-
- case "Boolean":
- case "Number":
- case "String":
- if (typeof a != typeof b || !Object(__WEBPACK_IMPORTED_MODULE_4__identical__.a)(a.valueOf(), b.valueOf())) return !1;
- break;
-
- case "Date":
- if (!Object(__WEBPACK_IMPORTED_MODULE_4__identical__.a)(a.valueOf(), b.valueOf())) return !1;
- break;
-
- case "Error":
- return a.name === b.name && a.message === b.message;
-
- case "RegExp":
- if (a.source !== b.source || a.global !== b.global || a.ignoreCase !== b.ignoreCase || a.multiline !== b.multiline || a.sticky !== b.sticky || a.unicode !== b.unicode) return !1;
- }
- for (var idx = stackA.length - 1; idx >= 0; ) {
- if (stackA[idx] === a) return stackB[idx] === b;
- idx -= 1;
- }
- switch (typeA) {
- case "Map":
- return a.size === b.size && _uniqContentEquals(a.entries(), b.entries(), stackA.concat([ a ]), stackB.concat([ b ]));
-
- case "Set":
- return a.size === b.size && _uniqContentEquals(a.values(), b.values(), stackA.concat([ a ]), stackB.concat([ b ]));
-
- case "Arguments":
- case "Array":
- case "Object":
- case "Boolean":
- case "Number":
- case "String":
- case "Date":
- case "Error":
- case "RegExp":
- case "Int8Array":
- case "Uint8Array":
- case "Uint8ClampedArray":
- case "Int16Array":
- case "Uint16Array":
- case "Int32Array":
- case "Uint32Array":
- case "Float32Array":
- case "Float64Array":
- case "ArrayBuffer":
- break;
-
- default:
- return !1;
- }
- var keysA = Object(__WEBPACK_IMPORTED_MODULE_5__keys__.a)(a);
- if (keysA.length !== Object(__WEBPACK_IMPORTED_MODULE_5__keys__.a)(b).length) return !1;
- var extendedStackA = stackA.concat([ a ]), extendedStackB = stackB.concat([ b ]);
- for (idx = keysA.length - 1; idx >= 0; ) {
- var key = keysA[idx];
- if (!Object(__WEBPACK_IMPORTED_MODULE_3__has__.a)(key, b) || !_equals(b[key], a[key], extendedStackA, extendedStackB)) return !1;
- idx -= 1;
- }
- return !0;
- }
- __webpack_exports__.a = _equals;
- var __WEBPACK_IMPORTED_MODULE_0__arrayFromIterator__ = __webpack_require__(606), __WEBPACK_IMPORTED_MODULE_1__containsWith__ = __webpack_require__(143), __WEBPACK_IMPORTED_MODULE_2__functionName__ = __webpack_require__(607), __WEBPACK_IMPORTED_MODULE_3__has__ = __webpack_require__(26), __WEBPACK_IMPORTED_MODULE_4__identical__ = __webpack_require__(317), __WEBPACK_IMPORTED_MODULE_5__keys__ = __webpack_require__(44), __WEBPACK_IMPORTED_MODULE_6__type__ = __webpack_require__(206);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _arrayFromIterator(iter) {
- for (var next, list = []; !(next = iter.next()).done; ) list.push(next.value);
- return list;
- }
- __webpack_exports__.a = _arrayFromIterator;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _functionName(f) {
- var match = String(f).match(/^function (\w*)/);
- return null == match ? "" : match[1];
- }
- __webpack_exports__.a = _functionName;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _quote(s) {
- return '"' + s.replace(/\\/g, "\\\\").replace(/[\b]/g, "\\b").replace(/\f/g, "\\f").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t").replace(/\v/g, "\\v").replace(/\0/g, "\\0").replace(/"/g, '\\"') + '"';
- }
- __webpack_exports__.a = _quote;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var pad = function(n) {
- return (n < 10 ? "0" : "") + n;
- }, _toISOString = "function" == typeof Date.prototype.toISOString ? function(d) {
- return d.toISOString();
- } : function(d) {
- return d.getUTCFullYear() + "-" + pad(d.getUTCMonth() + 1) + "-" + pad(d.getUTCDate()) + "T" + pad(d.getUTCHours()) + ":" + pad(d.getUTCMinutes()) + ":" + pad(d.getUTCSeconds()) + "." + (d.getUTCMilliseconds() / 1e3).toFixed(3).slice(2, 5) + "Z";
- };
- __webpack_exports__.a = _toISOString;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__xfBase__ = __webpack_require__(19), XFilter = function() {
- function XFilter(f, xf) {
- this.xf = xf, this.f = f;
- }
- return XFilter.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_1__xfBase__.a.init,
- XFilter.prototype["@@transducer/result"] = __WEBPACK_IMPORTED_MODULE_1__xfBase__.a.result,
- XFilter.prototype["@@transducer/step"] = function(result, input) {
- return this.f(input) ? this.xf["@@transducer/step"](result, input) : result;
- }, XFilter;
- }(), _xfilter = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(f, xf) {
- return new XFilter(f, xf);
- });
- __webpack_exports__.a = _xfilter;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_arity__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_1__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_2__map__ = __webpack_require__(27), __WEBPACK_IMPORTED_MODULE_3__max__ = __webpack_require__(79), __WEBPACK_IMPORTED_MODULE_4__reduce__ = __webpack_require__(45), cond = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry1__.a)(function(pairs) {
- var arity = Object(__WEBPACK_IMPORTED_MODULE_4__reduce__.a)(__WEBPACK_IMPORTED_MODULE_3__max__.a, 0, Object(__WEBPACK_IMPORTED_MODULE_2__map__.a)(function(pair) {
- return pair[0].length;
- }, pairs));
- return Object(__WEBPACK_IMPORTED_MODULE_0__internal_arity__.a)(arity, function() {
- for (var idx = 0; idx < pairs.length; ) {
- if (pairs[idx][0].apply(this, arguments)) return pairs[idx][1].apply(this, arguments);
- idx += 1;
- }
- });
- });
- __webpack_exports__.a = cond;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__constructN__ = __webpack_require__(319), construct = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(Fn) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__constructN__.a)(Fn.length, Fn);
- });
- __webpack_exports__.a = construct;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_contains__ = __webpack_require__(81), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), contains = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(__WEBPACK_IMPORTED_MODULE_0__internal_contains__.a);
- __webpack_exports__.a = contains;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__reduceBy__ = __webpack_require__(145), countBy = Object(__WEBPACK_IMPORTED_MODULE_0__reduceBy__.a)(function(acc, elem) {
- return acc + 1;
- }, 0);
- __webpack_exports__.a = countBy;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curryN__ = __webpack_require__(135), __WEBPACK_IMPORTED_MODULE_1__has__ = __webpack_require__(26), __WEBPACK_IMPORTED_MODULE_2__xfBase__ = __webpack_require__(19), XReduceBy = function() {
- function XReduceBy(valueFn, valueAcc, keyFn, xf) {
- this.valueFn = valueFn, this.valueAcc = valueAcc, this.keyFn = keyFn, this.xf = xf,
- this.inputs = {};
- }
- return XReduceBy.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_2__xfBase__.a.init,
- XReduceBy.prototype["@@transducer/result"] = function(result) {
- var key;
- for (key in this.inputs) if (Object(__WEBPACK_IMPORTED_MODULE_1__has__.a)(key, this.inputs) && (result = this.xf["@@transducer/step"](result, this.inputs[key]),
- result["@@transducer/reduced"])) {
- result = result["@@transducer/value"];
- break;
- }
- return this.inputs = null, this.xf["@@transducer/result"](result);
- }, XReduceBy.prototype["@@transducer/step"] = function(result, input) {
- var key = this.keyFn(input);
- return this.inputs[key] = this.inputs[key] || [ key, this.valueAcc ], this.inputs[key][1] = this.valueFn(this.inputs[key][1], input),
- result;
- }, XReduceBy;
- }(), _xreduceBy = Object(__WEBPACK_IMPORTED_MODULE_0__curryN__.a)(4, [], function(valueFn, valueAcc, keyFn, xf) {
- return new XReduceBy(valueFn, valueAcc, keyFn, xf);
- });
- __webpack_exports__.a = _xreduceBy;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__add__ = __webpack_require__(134), dec = Object(__WEBPACK_IMPORTED_MODULE_0__add__.a)(-1);
- __webpack_exports__.a = dec;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), descend = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(fn, a, b) {
- var aa = fn(a), bb = fn(b);
- return aa > bb ? -1 : aa < bb ? 1 : 0;
- });
- __webpack_exports__.a = descend;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_isInteger__ = __webpack_require__(203), __WEBPACK_IMPORTED_MODULE_2__assoc__ = __webpack_require__(138), __WEBPACK_IMPORTED_MODULE_3__dissoc__ = __webpack_require__(324), __WEBPACK_IMPORTED_MODULE_4__remove__ = __webpack_require__(325), __WEBPACK_IMPORTED_MODULE_5__update__ = __webpack_require__(213), dissocPath = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function dissocPath(path, obj) {
- switch (path.length) {
- case 0:
- return obj;
-
- case 1:
- return Object(__WEBPACK_IMPORTED_MODULE_1__internal_isInteger__.a)(path[0]) ? Object(__WEBPACK_IMPORTED_MODULE_4__remove__.a)(path[0], 1, obj) : Object(__WEBPACK_IMPORTED_MODULE_3__dissoc__.a)(path[0], obj);
-
- default:
- var head = path[0], tail = Array.prototype.slice.call(path, 1);
- return null == obj[head] ? obj : Object(__WEBPACK_IMPORTED_MODULE_1__internal_isInteger__.a)(path[0]) ? Object(__WEBPACK_IMPORTED_MODULE_5__update__.a)(head, dissocPath(tail, obj[head]), obj) : Object(__WEBPACK_IMPORTED_MODULE_2__assoc__.a)(head, dissocPath(tail, obj[head]), obj);
- }
- });
- __webpack_exports__.a = dissocPath;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), divide = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- return a / b;
- });
- __webpack_exports__.a = divide;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__xfBase__ = __webpack_require__(19), XDrop = function() {
- function XDrop(n, xf) {
- this.xf = xf, this.n = n;
- }
- return XDrop.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_1__xfBase__.a.init,
- XDrop.prototype["@@transducer/result"] = __WEBPACK_IMPORTED_MODULE_1__xfBase__.a.result,
- XDrop.prototype["@@transducer/step"] = function(result, input) {
- return this.n > 0 ? (this.n -= 1, result) : this.xf["@@transducer/step"](result, input);
- }, XDrop;
- }(), _xdrop = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(n, xf) {
- return new XDrop(n, xf);
- });
- __webpack_exports__.a = _xdrop;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_dropLast__ = __webpack_require__(622), __WEBPACK_IMPORTED_MODULE_3__internal_xdropLast__ = __webpack_require__(624), dropLast = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([], __WEBPACK_IMPORTED_MODULE_3__internal_xdropLast__.a, __WEBPACK_IMPORTED_MODULE_2__internal_dropLast__.a));
- __webpack_exports__.a = dropLast;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function dropLast(n, xs) {
- return Object(__WEBPACK_IMPORTED_MODULE_0__take__.a)(n < xs.length ? xs.length - n : 0, xs);
- }
- __webpack_exports__.a = dropLast;
- var __WEBPACK_IMPORTED_MODULE_0__take__ = __webpack_require__(214);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__reduced__ = __webpack_require__(58), __WEBPACK_IMPORTED_MODULE_2__xfBase__ = __webpack_require__(19), XTake = function() {
- function XTake(n, xf) {
- this.xf = xf, this.n = n, this.i = 0;
- }
- return XTake.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_2__xfBase__.a.init,
- XTake.prototype["@@transducer/result"] = __WEBPACK_IMPORTED_MODULE_2__xfBase__.a.result,
- XTake.prototype["@@transducer/step"] = function(result, input) {
- this.i += 1;
- var ret = 0 === this.n ? result : this.xf["@@transducer/step"](result, input);
- return this.n >= 0 && this.i >= this.n ? Object(__WEBPACK_IMPORTED_MODULE_1__reduced__.a)(ret) : ret;
- }, XTake;
- }(), _xtake = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(n, xf) {
- return new XTake(n, xf);
- });
- __webpack_exports__.a = _xtake;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__xfBase__ = __webpack_require__(19), XDropLast = function() {
- function XDropLast(n, xf) {
- this.xf = xf, this.pos = 0, this.full = !1, this.acc = new Array(n);
- }
- return XDropLast.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_1__xfBase__.a.init,
- XDropLast.prototype["@@transducer/result"] = function(result) {
- return this.acc = null, this.xf["@@transducer/result"](result);
- }, XDropLast.prototype["@@transducer/step"] = function(result, input) {
- return this.full && (result = this.xf["@@transducer/step"](result, this.acc[this.pos])),
- this.store(input), result;
- }, XDropLast.prototype.store = function(input) {
- this.acc[this.pos] = input, this.pos += 1, this.pos === this.acc.length && (this.pos = 0,
- this.full = !0);
- }, XDropLast;
- }(), _xdropLast = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(n, xf) {
- return new XDropLast(n, xf);
- });
- __webpack_exports__.a = _xdropLast;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_dropLastWhile__ = __webpack_require__(626), __WEBPACK_IMPORTED_MODULE_3__internal_xdropLastWhile__ = __webpack_require__(627), dropLastWhile = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([], __WEBPACK_IMPORTED_MODULE_3__internal_xdropLastWhile__.a, __WEBPACK_IMPORTED_MODULE_2__internal_dropLastWhile__.a));
- __webpack_exports__.a = dropLastWhile;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function dropLastWhile(pred, xs) {
- for (var idx = xs.length - 1; idx >= 0 && pred(xs[idx]); ) idx -= 1;
- return Object(__WEBPACK_IMPORTED_MODULE_0__slice__.a)(0, idx + 1, xs);
- }
- __webpack_exports__.a = dropLastWhile;
- var __WEBPACK_IMPORTED_MODULE_0__slice__ = __webpack_require__(34);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__reduce__ = __webpack_require__(30), __WEBPACK_IMPORTED_MODULE_2__xfBase__ = __webpack_require__(19), XDropLastWhile = function() {
- function XDropLastWhile(fn, xf) {
- this.f = fn, this.retained = [], this.xf = xf;
- }
- return XDropLastWhile.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_2__xfBase__.a.init,
- XDropLastWhile.prototype["@@transducer/result"] = function(result) {
- return this.retained = null, this.xf["@@transducer/result"](result);
- }, XDropLastWhile.prototype["@@transducer/step"] = function(result, input) {
- return this.f(input) ? this.retain(result, input) : this.flush(result, input);
- }, XDropLastWhile.prototype.flush = function(result, input) {
- return result = Object(__WEBPACK_IMPORTED_MODULE_1__reduce__.a)(this.xf["@@transducer/step"], result, this.retained),
- this.retained = [], this.xf["@@transducer/step"](result, input);
- }, XDropLastWhile.prototype.retain = function(result, input) {
- return this.retained.push(input), result;
- }, XDropLastWhile;
- }(), _xdropLastWhile = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(fn, xf) {
- return new XDropLastWhile(fn, xf);
- });
- __webpack_exports__.a = _xdropLastWhile;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_xdropRepeatsWith__ = __webpack_require__(327), __WEBPACK_IMPORTED_MODULE_3__dropRepeatsWith__ = __webpack_require__(328), __WEBPACK_IMPORTED_MODULE_4__equals__ = __webpack_require__(31), dropRepeats = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([], Object(__WEBPACK_IMPORTED_MODULE_2__internal_xdropRepeatsWith__.a)(__WEBPACK_IMPORTED_MODULE_4__equals__.a), Object(__WEBPACK_IMPORTED_MODULE_3__dropRepeatsWith__.a)(__WEBPACK_IMPORTED_MODULE_4__equals__.a)));
- __webpack_exports__.a = dropRepeats;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_xdropWhile__ = __webpack_require__(630), __WEBPACK_IMPORTED_MODULE_3__slice__ = __webpack_require__(34), dropWhile = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([ "dropWhile" ], __WEBPACK_IMPORTED_MODULE_2__internal_xdropWhile__.a, function(pred, xs) {
- for (var idx = 0, len = xs.length; idx < len && pred(xs[idx]); ) idx += 1;
- return Object(__WEBPACK_IMPORTED_MODULE_3__slice__.a)(idx, 1 / 0, xs);
- }));
- __webpack_exports__.a = dropWhile;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__xfBase__ = __webpack_require__(19), XDropWhile = function() {
- function XDropWhile(f, xf) {
- this.xf = xf, this.f = f;
- }
- return XDropWhile.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_1__xfBase__.a.init,
- XDropWhile.prototype["@@transducer/result"] = __WEBPACK_IMPORTED_MODULE_1__xfBase__.a.result,
- XDropWhile.prototype["@@transducer/step"] = function(result, input) {
- if (this.f) {
- if (this.f(input)) return result;
- this.f = null;
- }
- return this.xf["@@transducer/step"](result, input);
- }, XDropWhile;
- }(), _xdropWhile = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(f, xf) {
- return new XDropWhile(f, xf);
- });
- __webpack_exports__.a = _xdropWhile;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_isFunction__ = __webpack_require__(140), __WEBPACK_IMPORTED_MODULE_2__lift__ = __webpack_require__(141), __WEBPACK_IMPORTED_MODULE_3__or__ = __webpack_require__(330), either = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(f, g) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__internal_isFunction__.a)(f) ? function() {
- return f.apply(this, arguments) || g.apply(this, arguments);
- } : Object(__WEBPACK_IMPORTED_MODULE_2__lift__.a)(__WEBPACK_IMPORTED_MODULE_3__or__.a)(f, g);
- });
- __webpack_exports__.a = either;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__equals__ = __webpack_require__(31), __WEBPACK_IMPORTED_MODULE_2__takeLast__ = __webpack_require__(332), endsWith = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(suffix, list) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__equals__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__takeLast__.a)(suffix.length, list), suffix);
- });
- __webpack_exports__.a = endsWith;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__equals__ = __webpack_require__(31), eqBy = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(f, x, y) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__equals__.a)(f(x), f(y));
- });
- __webpack_exports__.a = eqBy;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__equals__ = __webpack_require__(31), eqProps = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(prop, obj1, obj2) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__equals__.a)(obj1[prop], obj2[prop]);
- });
- __webpack_exports__.a = eqProps;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), evolve = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function evolve(transformations, object) {
- var transformation, key, type, result = {};
- for (key in object) transformation = transformations[key], type = typeof transformation,
- result[key] = "function" === type ? transformation(object[key]) : transformation && "object" === type ? evolve(transformation, object[key]) : object[key];
- return result;
- });
- __webpack_exports__.a = evolve;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_xfind__ = __webpack_require__(637), find = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([ "find" ], __WEBPACK_IMPORTED_MODULE_2__internal_xfind__.a, function(fn, list) {
- for (var idx = 0, len = list.length; idx < len; ) {
- if (fn(list[idx])) return list[idx];
- idx += 1;
- }
- }));
- __webpack_exports__.a = find;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__reduced__ = __webpack_require__(58), __WEBPACK_IMPORTED_MODULE_2__xfBase__ = __webpack_require__(19), XFind = function() {
- function XFind(f, xf) {
- this.xf = xf, this.f = f, this.found = !1;
- }
- return XFind.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_2__xfBase__.a.init,
- XFind.prototype["@@transducer/result"] = function(result) {
- return this.found || (result = this.xf["@@transducer/step"](result, void 0)), this.xf["@@transducer/result"](result);
- }, XFind.prototype["@@transducer/step"] = function(result, input) {
- return this.f(input) && (this.found = !0, result = Object(__WEBPACK_IMPORTED_MODULE_1__reduced__.a)(this.xf["@@transducer/step"](result, input))),
- result;
- }, XFind;
- }(), _xfind = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(f, xf) {
- return new XFind(f, xf);
- });
- __webpack_exports__.a = _xfind;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_xfindIndex__ = __webpack_require__(639), findIndex = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([], __WEBPACK_IMPORTED_MODULE_2__internal_xfindIndex__.a, function(fn, list) {
- for (var idx = 0, len = list.length; idx < len; ) {
- if (fn(list[idx])) return idx;
- idx += 1;
- }
- return -1;
- }));
- __webpack_exports__.a = findIndex;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__reduced__ = __webpack_require__(58), __WEBPACK_IMPORTED_MODULE_2__xfBase__ = __webpack_require__(19), XFindIndex = function() {
- function XFindIndex(f, xf) {
- this.xf = xf, this.f = f, this.idx = -1, this.found = !1;
- }
- return XFindIndex.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_2__xfBase__.a.init,
- XFindIndex.prototype["@@transducer/result"] = function(result) {
- return this.found || (result = this.xf["@@transducer/step"](result, -1)), this.xf["@@transducer/result"](result);
- }, XFindIndex.prototype["@@transducer/step"] = function(result, input) {
- return this.idx += 1, this.f(input) && (this.found = !0, result = Object(__WEBPACK_IMPORTED_MODULE_1__reduced__.a)(this.xf["@@transducer/step"](result, this.idx))),
- result;
- }, XFindIndex;
- }(), _xfindIndex = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(f, xf) {
- return new XFindIndex(f, xf);
- });
- __webpack_exports__.a = _xfindIndex;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_xfindLast__ = __webpack_require__(641), findLast = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([], __WEBPACK_IMPORTED_MODULE_2__internal_xfindLast__.a, function(fn, list) {
- for (var idx = list.length - 1; idx >= 0; ) {
- if (fn(list[idx])) return list[idx];
- idx -= 1;
- }
- }));
- __webpack_exports__.a = findLast;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__xfBase__ = __webpack_require__(19), XFindLast = function() {
- function XFindLast(f, xf) {
- this.xf = xf, this.f = f;
- }
- return XFindLast.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_1__xfBase__.a.init,
- XFindLast.prototype["@@transducer/result"] = function(result) {
- return this.xf["@@transducer/result"](this.xf["@@transducer/step"](result, this.last));
- }, XFindLast.prototype["@@transducer/step"] = function(result, input) {
- return this.f(input) && (this.last = input), result;
- }, XFindLast;
- }(), _xfindLast = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(f, xf) {
- return new XFindLast(f, xf);
- });
- __webpack_exports__.a = _xfindLast;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_xfindLastIndex__ = __webpack_require__(643), findLastIndex = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([], __WEBPACK_IMPORTED_MODULE_2__internal_xfindLastIndex__.a, function(fn, list) {
- for (var idx = list.length - 1; idx >= 0; ) {
- if (fn(list[idx])) return idx;
- idx -= 1;
- }
- return -1;
- }));
- __webpack_exports__.a = findLastIndex;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__xfBase__ = __webpack_require__(19), XFindLastIndex = function() {
- function XFindLastIndex(f, xf) {
- this.xf = xf, this.f = f, this.idx = -1, this.lastIdx = -1;
- }
- return XFindLastIndex.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_1__xfBase__.a.init,
- XFindLastIndex.prototype["@@transducer/result"] = function(result) {
- return this.xf["@@transducer/result"](this.xf["@@transducer/step"](result, this.lastIdx));
- }, XFindLastIndex.prototype["@@transducer/step"] = function(result, input) {
- return this.idx += 1, this.f(input) && (this.lastIdx = this.idx), result;
- }, XFindLastIndex;
- }(), _xfindLastIndex = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(f, xf) {
- return new XFindLastIndex(f, xf);
- });
- __webpack_exports__.a = _xfindLastIndex;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__internal_makeFlat__ = __webpack_require__(309), flatten = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_makeFlat__.a)(!0));
- __webpack_exports__.a = flatten;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_checkForMethod__ = __webpack_require__(99), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), forEach = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_0__internal_checkForMethod__.a)("forEach", function(fn, list) {
- for (var len = list.length, idx = 0; idx < len; ) fn(list[idx]), idx += 1;
- return list;
- }));
- __webpack_exports__.a = forEach;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__keys__ = __webpack_require__(44), forEachObjIndexed = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(fn, obj) {
- for (var keyList = Object(__WEBPACK_IMPORTED_MODULE_1__keys__.a)(obj), idx = 0; idx < keyList.length; ) {
- var key = keyList[idx];
- fn(obj[key], key, obj), idx += 1;
- }
- return obj;
- });
- __webpack_exports__.a = forEachObjIndexed;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), fromPairs = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(pairs) {
- for (var result = {}, idx = 0; idx < pairs.length; ) result[pairs[idx][0]] = pairs[idx][1],
- idx += 1;
- return result;
- });
- __webpack_exports__.a = fromPairs;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_checkForMethod__ = __webpack_require__(99), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2__reduceBy__ = __webpack_require__(145), groupBy = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_0__internal_checkForMethod__.a)("groupBy", Object(__WEBPACK_IMPORTED_MODULE_2__reduceBy__.a)(function(acc, item) {
- return null == acc && (acc = []), acc.push(item), acc;
- }, null)));
- __webpack_exports__.a = groupBy;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), groupWith = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(fn, list) {
- for (var res = [], idx = 0, len = list.length; idx < len; ) {
- for (var nextidx = idx + 1; nextidx < len && fn(list[nextidx - 1], list[nextidx]); ) nextidx += 1;
- res.push(list.slice(idx, nextidx)), idx = nextidx;
- }
- return res;
- });
- __webpack_exports__.a = groupWith;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), gt = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- return a > b;
- });
- __webpack_exports__.a = gt;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), gte = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- return a >= b;
- });
- __webpack_exports__.a = gte;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_has__ = __webpack_require__(26), has = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(__WEBPACK_IMPORTED_MODULE_1__internal_has__.a);
- __webpack_exports__.a = has;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), hasIn = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(prop, obj) {
- return prop in obj;
- });
- __webpack_exports__.a = hasIn;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__nth__ = __webpack_require__(101), head = Object(__WEBPACK_IMPORTED_MODULE_0__nth__.a)(0);
- __webpack_exports__.a = head;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__curryN__ = __webpack_require__(23), ifElse = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(condition, onTrue, onFalse) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__curryN__.a)(Math.max(condition.length, onTrue.length, onFalse.length), function() {
- return condition.apply(this, arguments) ? onTrue.apply(this, arguments) : onFalse.apply(this, arguments);
- });
- });
- __webpack_exports__.a = ifElse;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__add__ = __webpack_require__(134), inc = Object(__WEBPACK_IMPORTED_MODULE_0__add__.a)(1);
- __webpack_exports__.a = inc;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__reduceBy__ = __webpack_require__(145), indexBy = Object(__WEBPACK_IMPORTED_MODULE_0__reduceBy__.a)(function(acc, elem) {
- return elem;
- }, null);
- __webpack_exports__.a = indexBy;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_indexOf__ = __webpack_require__(316), __WEBPACK_IMPORTED_MODULE_2__internal_isArray__ = __webpack_require__(57), indexOf = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(target, xs) {
- return "function" != typeof xs.indexOf || Object(__WEBPACK_IMPORTED_MODULE_2__internal_isArray__.a)(xs) ? Object(__WEBPACK_IMPORTED_MODULE_1__internal_indexOf__.a)(xs, target, 0) : xs.indexOf(target);
- });
- __webpack_exports__.a = indexOf;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__slice__ = __webpack_require__(34), init = Object(__WEBPACK_IMPORTED_MODULE_0__slice__.a)(0, -1);
- __webpack_exports__.a = init;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_containsWith__ = __webpack_require__(143), __WEBPACK_IMPORTED_MODULE_1__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_2__internal_filter__ = __webpack_require__(211), innerJoin = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry3__.a)(function(pred, xs, ys) {
- return Object(__WEBPACK_IMPORTED_MODULE_2__internal_filter__.a)(function(x) {
- return Object(__WEBPACK_IMPORTED_MODULE_0__internal_containsWith__.a)(pred, x, ys);
- }, xs);
- });
- __webpack_exports__.a = innerJoin;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), insert = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(idx, elt, list) {
- idx = idx < list.length && idx >= 0 ? idx : list.length;
- var result = Array.prototype.slice.call(list, 0);
- return result.splice(idx, 0, elt), result;
- });
- __webpack_exports__.a = insert;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), insertAll = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(idx, elts, list) {
- return idx = idx < list.length && idx >= 0 ? idx : list.length, [].concat(Array.prototype.slice.call(list, 0, idx), elts, Array.prototype.slice.call(list, idx));
- });
- __webpack_exports__.a = insertAll;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_contains__ = __webpack_require__(81), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2__internal_filter__ = __webpack_require__(211), __WEBPACK_IMPORTED_MODULE_3__flip__ = __webpack_require__(146), __WEBPACK_IMPORTED_MODULE_4__uniq__ = __webpack_require__(217), intersection = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(function(list1, list2) {
- var lookupList, filteredList;
- return list1.length > list2.length ? (lookupList = list1, filteredList = list2) : (lookupList = list2,
- filteredList = list1), Object(__WEBPACK_IMPORTED_MODULE_4__uniq__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__internal_filter__.a)(Object(__WEBPACK_IMPORTED_MODULE_3__flip__.a)(__WEBPACK_IMPORTED_MODULE_0__internal_contains__.a)(lookupList), filteredList));
- });
- __webpack_exports__.a = intersection;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function hasOrAdd(item, shouldAdd, set) {
- var prevSize, type = typeof item;
- switch (type) {
- case "string":
- case "number":
- return 0 === item && 1 / item == -1 / 0 ? !!set._items["-0"] || (shouldAdd && (set._items["-0"] = !0),
- !1) : null !== set._nativeSet ? shouldAdd ? (prevSize = set._nativeSet.size, set._nativeSet.add(item),
- set._nativeSet.size === prevSize) : set._nativeSet.has(item) : type in set._items ? item in set._items[type] || (shouldAdd && (set._items[type][item] = !0),
- !1) : (shouldAdd && (set._items[type] = {}, set._items[type][item] = !0), !1);
-
- case "boolean":
- if (type in set._items) {
- var bIdx = item ? 1 : 0;
- return !!set._items[type][bIdx] || (shouldAdd && (set._items[type][bIdx] = !0),
- !1);
- }
- return shouldAdd && (set._items[type] = item ? [ !1, !0 ] : [ !0, !1 ]), !1;
-
- case "function":
- return null !== set._nativeSet ? shouldAdd ? (prevSize = set._nativeSet.size, set._nativeSet.add(item),
- set._nativeSet.size === prevSize) : set._nativeSet.has(item) : type in set._items ? !!Object(__WEBPACK_IMPORTED_MODULE_0__contains__.a)(item, set._items[type]) || (shouldAdd && set._items[type].push(item),
- !1) : (shouldAdd && (set._items[type] = [ item ]), !1);
-
- case "undefined":
- return !!set._items[type] || (shouldAdd && (set._items[type] = !0), !1);
-
- case "object":
- if (null === item) return !!set._items.null || (shouldAdd && (set._items.null = !0),
- !1);
-
- default:
- return type = Object.prototype.toString.call(item), type in set._items ? !!Object(__WEBPACK_IMPORTED_MODULE_0__contains__.a)(item, set._items[type]) || (shouldAdd && set._items[type].push(item),
- !1) : (shouldAdd && (set._items[type] = [ item ]), !1);
- }
- }
- var __WEBPACK_IMPORTED_MODULE_0__contains__ = __webpack_require__(81), _Set = function() {
- function _Set() {
- this._nativeSet = "function" == typeof Set ? new Set() : null, this._items = {};
- }
- return _Set.prototype.add = function(item) {
- return !hasOrAdd(item, !0, this);
- }, _Set.prototype.has = function(item) {
- return hasOrAdd(item, !1, this);
- }, _Set;
- }();
- __webpack_exports__.a = _Set;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_checkForMethod__ = __webpack_require__(99), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), intersperse = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_0__internal_checkForMethod__.a)("intersperse", function(separator, list) {
- for (var out = [], idx = 0, length = list.length; idx < length; ) idx === length - 1 ? out.push(list[idx]) : out.push(list[idx], separator),
- idx += 1;
- return out;
- }));
- __webpack_exports__.a = intersperse;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_clone__ = __webpack_require__(310), __WEBPACK_IMPORTED_MODULE_1__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_2__internal_isTransformer__ = __webpack_require__(200), __WEBPACK_IMPORTED_MODULE_3__internal_reduce__ = __webpack_require__(30), __WEBPACK_IMPORTED_MODULE_4__internal_stepCat__ = __webpack_require__(667), into = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry3__.a)(function(acc, xf, list) {
- return Object(__WEBPACK_IMPORTED_MODULE_2__internal_isTransformer__.a)(acc) ? Object(__WEBPACK_IMPORTED_MODULE_3__internal_reduce__.a)(xf(acc), acc["@@transducer/init"](), list) : Object(__WEBPACK_IMPORTED_MODULE_3__internal_reduce__.a)(xf(Object(__WEBPACK_IMPORTED_MODULE_4__internal_stepCat__.a)(acc)), Object(__WEBPACK_IMPORTED_MODULE_0__internal_clone__.a)(acc, [], [], !1), list);
- });
- __webpack_exports__.a = into;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _stepCat(obj) {
- if (Object(__WEBPACK_IMPORTED_MODULE_3__isTransformer__.a)(obj)) return obj;
- if (Object(__WEBPACK_IMPORTED_MODULE_2__isArrayLike__.a)(obj)) return _stepCatArray;
- if ("string" == typeof obj) return _stepCatString;
- if ("object" == typeof obj) return _stepCatObject;
- throw new Error("Cannot create transformer for " + obj);
- }
- __webpack_exports__.a = _stepCat;
- var __WEBPACK_IMPORTED_MODULE_0__assign__ = __webpack_require__(218), __WEBPACK_IMPORTED_MODULE_1__identity__ = __webpack_require__(216), __WEBPACK_IMPORTED_MODULE_2__isArrayLike__ = __webpack_require__(137), __WEBPACK_IMPORTED_MODULE_3__isTransformer__ = __webpack_require__(200), __WEBPACK_IMPORTED_MODULE_4__objOf__ = __webpack_require__(334), _stepCatArray = {
- "@@transducer/init": Array,
- "@@transducer/step": function(xs, x) {
- return xs.push(x), xs;
- },
- "@@transducer/result": __WEBPACK_IMPORTED_MODULE_1__identity__.a
- }, _stepCatString = {
- "@@transducer/init": String,
- "@@transducer/step": function(a, b) {
- return a + b;
- },
- "@@transducer/result": __WEBPACK_IMPORTED_MODULE_1__identity__.a
- }, _stepCatObject = {
- "@@transducer/init": Object,
- "@@transducer/step": function(result, input) {
- return Object(__WEBPACK_IMPORTED_MODULE_0__assign__.a)(result, Object(__WEBPACK_IMPORTED_MODULE_2__isArrayLike__.a)(input) ? Object(__WEBPACK_IMPORTED_MODULE_4__objOf__.a)(input[0], input[1]) : input);
- },
- "@@transducer/result": __WEBPACK_IMPORTED_MODULE_1__identity__.a
- };
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _objectAssign(target) {
- if (null == target) throw new TypeError("Cannot convert undefined or null to object");
- for (var output = Object(target), idx = 1, length = arguments.length; idx < length; ) {
- var source = arguments[idx];
- if (null != source) for (var nextKey in source) Object(__WEBPACK_IMPORTED_MODULE_0__has__.a)(nextKey, source) && (output[nextKey] = source[nextKey]);
- idx += 1;
- }
- return output;
- }
- __webpack_exports__.a = _objectAssign;
- var __WEBPACK_IMPORTED_MODULE_0__has__ = __webpack_require__(26);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__internal_has__ = __webpack_require__(26), __WEBPACK_IMPORTED_MODULE_2__keys__ = __webpack_require__(44), invert = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(obj) {
- for (var props = Object(__WEBPACK_IMPORTED_MODULE_2__keys__.a)(obj), len = props.length, idx = 0, out = {}; idx < len; ) {
- var key = props[idx], val = obj[key], list = Object(__WEBPACK_IMPORTED_MODULE_1__internal_has__.a)(val, out) ? out[val] : out[val] = [];
- list[list.length] = key, idx += 1;
- }
- return out;
- });
- __webpack_exports__.a = invert;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__keys__ = __webpack_require__(44), invertObj = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(obj) {
- for (var props = Object(__WEBPACK_IMPORTED_MODULE_1__keys__.a)(obj), len = props.length, idx = 0, out = {}; idx < len; ) {
- var key = props[idx];
- out[obj[key]] = key, idx += 1;
- }
- return out;
- });
- __webpack_exports__.a = invertObj;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__empty__ = __webpack_require__(331), __WEBPACK_IMPORTED_MODULE_2__equals__ = __webpack_require__(31), isEmpty = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(x) {
- return null != x && Object(__WEBPACK_IMPORTED_MODULE_2__equals__.a)(x, Object(__WEBPACK_IMPORTED_MODULE_1__empty__.a)(x));
- });
- __webpack_exports__.a = isEmpty;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__invoker__ = __webpack_require__(102), join = Object(__WEBPACK_IMPORTED_MODULE_0__invoker__.a)(1, "join");
- __webpack_exports__.a = join;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), keysIn = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(obj) {
- var prop, ks = [];
- for (prop in obj) ks[ks.length] = prop;
- return ks;
- });
- __webpack_exports__.a = keysIn;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_isArray__ = __webpack_require__(57), __WEBPACK_IMPORTED_MODULE_2__equals__ = __webpack_require__(31), lastIndexOf = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(target, xs) {
- if ("function" != typeof xs.lastIndexOf || Object(__WEBPACK_IMPORTED_MODULE_1__internal_isArray__.a)(xs)) {
- for (var idx = xs.length - 1; idx >= 0; ) {
- if (Object(__WEBPACK_IMPORTED_MODULE_2__equals__.a)(xs[idx], target)) return idx;
- idx -= 1;
- }
- return -1;
- }
- return xs.lastIndexOf(target);
- });
- __webpack_exports__.a = lastIndexOf;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__lens__ = __webpack_require__(147), __WEBPACK_IMPORTED_MODULE_2__nth__ = __webpack_require__(101), __WEBPACK_IMPORTED_MODULE_3__update__ = __webpack_require__(213), lensIndex = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(n) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__lens__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__nth__.a)(n), Object(__WEBPACK_IMPORTED_MODULE_3__update__.a)(n));
- });
- __webpack_exports__.a = lensIndex;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__assocPath__ = __webpack_require__(306), __WEBPACK_IMPORTED_MODULE_2__lens__ = __webpack_require__(147), __WEBPACK_IMPORTED_MODULE_3__path__ = __webpack_require__(80), lensPath = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(p) {
- return Object(__WEBPACK_IMPORTED_MODULE_2__lens__.a)(Object(__WEBPACK_IMPORTED_MODULE_3__path__.a)(p), Object(__WEBPACK_IMPORTED_MODULE_1__assocPath__.a)(p));
- });
- __webpack_exports__.a = lensPath;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__assoc__ = __webpack_require__(138), __WEBPACK_IMPORTED_MODULE_2__lens__ = __webpack_require__(147), __WEBPACK_IMPORTED_MODULE_3__prop__ = __webpack_require__(201), lensProp = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(k) {
- return Object(__WEBPACK_IMPORTED_MODULE_2__lens__.a)(Object(__WEBPACK_IMPORTED_MODULE_3__prop__.a)(k), Object(__WEBPACK_IMPORTED_MODULE_1__assoc__.a)(k));
- });
- __webpack_exports__.a = lensProp;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), lt = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- return a < b;
- });
- __webpack_exports__.a = lt;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), lte = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- return a <= b;
- });
- __webpack_exports__.a = lte;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), mapAccum = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(fn, acc, list) {
- for (var idx = 0, len = list.length, result = [], tuple = [ acc ]; idx < len; ) tuple = fn(tuple[0], list[idx]),
- result[idx] = tuple[1], idx += 1;
- return [ tuple[0], result ];
- });
- __webpack_exports__.a = mapAccum;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), mapAccumRight = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(fn, acc, list) {
- for (var idx = list.length - 1, result = [], tuple = [ acc ]; idx >= 0; ) tuple = fn(list[idx], tuple[0]),
- result[idx] = tuple[1], idx -= 1;
- return [ result, tuple[0] ];
- });
- __webpack_exports__.a = mapAccumRight;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_reduce__ = __webpack_require__(30), __WEBPACK_IMPORTED_MODULE_2__keys__ = __webpack_require__(44), mapObjIndexed = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(fn, obj) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__internal_reduce__.a)(function(acc, key) {
- return acc[key] = fn(obj[key], key, obj), acc;
- }, {}, Object(__WEBPACK_IMPORTED_MODULE_2__keys__.a)(obj));
- });
- __webpack_exports__.a = mapObjIndexed;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), match = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(rx, str) {
- return str.match(rx) || [];
- });
- __webpack_exports__.a = match;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_isInteger__ = __webpack_require__(203), mathMod = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(m, p) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__internal_isInteger__.a)(m) ? !Object(__WEBPACK_IMPORTED_MODULE_1__internal_isInteger__.a)(p) || p < 1 ? NaN : (m % p + p) % p : NaN;
- });
- __webpack_exports__.a = mathMod;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), maxBy = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(f, a, b) {
- return f(b) > f(a) ? b : a;
- });
- __webpack_exports__.a = maxBy;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__mean__ = __webpack_require__(339), median = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(list) {
- var len = list.length;
- if (0 === len) return NaN;
- var width = 2 - len % 2, idx = (len - width) / 2;
- return Object(__WEBPACK_IMPORTED_MODULE_1__mean__.a)(Array.prototype.slice.call(list, 0).sort(function(a, b) {
- return a < b ? -1 : a > b ? 1 : 0;
- }).slice(idx, idx + width));
- });
- __webpack_exports__.a = median;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__memoizeWith__ = __webpack_require__(341), __WEBPACK_IMPORTED_MODULE_1__toString__ = __webpack_require__(100), memoize = Object(__WEBPACK_IMPORTED_MODULE_0__memoizeWith__.a)(function() {
- return Object(__WEBPACK_IMPORTED_MODULE_1__toString__.a)(arguments);
- });
- __webpack_exports__.a = memoize;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_assign__ = __webpack_require__(218), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), merge = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(function(l, r) {
- return Object(__WEBPACK_IMPORTED_MODULE_0__internal_assign__.a)({}, l, r);
- });
- __webpack_exports__.a = merge;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_assign__ = __webpack_require__(218), __WEBPACK_IMPORTED_MODULE_1__internal_curry1__ = __webpack_require__(4), mergeAll = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry1__.a)(function(list) {
- return __WEBPACK_IMPORTED_MODULE_0__internal_assign__.a.apply(null, [ {} ].concat(list));
- });
- __webpack_exports__.a = mergeAll;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__mergeDeepWithKey__ = __webpack_require__(148), mergeDeepLeft = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(lObj, rObj) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__mergeDeepWithKey__.a)(function(k, lVal, rVal) {
- return lVal;
- }, lObj, rObj);
- });
- __webpack_exports__.a = mergeDeepLeft;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__mergeDeepWithKey__ = __webpack_require__(148), mergeDeepRight = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(lObj, rObj) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__mergeDeepWithKey__.a)(function(k, lVal, rVal) {
- return rVal;
- }, lObj, rObj);
- });
- __webpack_exports__.a = mergeDeepRight;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__mergeDeepWithKey__ = __webpack_require__(148), mergeDeepWith = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(fn, lObj, rObj) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__mergeDeepWithKey__.a)(function(k, lVal, rVal) {
- return fn(lVal, rVal);
- }, lObj, rObj);
- });
- __webpack_exports__.a = mergeDeepWith;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__mergeWithKey__ = __webpack_require__(219), mergeWith = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(fn, l, r) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__mergeWithKey__.a)(function(_, _l, _r) {
- return fn(_l, _r);
- }, l, r);
- });
- __webpack_exports__.a = mergeWith;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), min = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- return b < a ? b : a;
- });
- __webpack_exports__.a = min;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), minBy = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(f, a, b) {
- return f(b) < f(a) ? b : a;
- });
- __webpack_exports__.a = minBy;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), modulo = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- return a % b;
- });
- __webpack_exports__.a = modulo;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), negate = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(n) {
- return -n;
- });
- __webpack_exports__.a = negate;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_complement__ = __webpack_require__(318), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_3__internal_xany__ = __webpack_require__(303), __WEBPACK_IMPORTED_MODULE_4__any__ = __webpack_require__(302), none = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_0__internal_complement__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__internal_dispatchable__.a)([ "any" ], __WEBPACK_IMPORTED_MODULE_3__internal_xany__.a, __WEBPACK_IMPORTED_MODULE_4__any__.a)));
- __webpack_exports__.a = none;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__curryN__ = __webpack_require__(23), __WEBPACK_IMPORTED_MODULE_2__nth__ = __webpack_require__(101), nthArg = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(n) {
- var arity = n < 0 ? 1 : n + 1;
- return Object(__WEBPACK_IMPORTED_MODULE_1__curryN__.a)(arity, function() {
- return Object(__WEBPACK_IMPORTED_MODULE_2__nth__.a)(n, arguments);
- });
- });
- __webpack_exports__.a = nthArg;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), o = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(f, g, x) {
- return f(g(x));
- });
- __webpack_exports__.a = o;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__internal_of__ = __webpack_require__(702), of = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(__WEBPACK_IMPORTED_MODULE_1__internal_of__.a);
- __webpack_exports__.a = of;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _of(x) {
- return [ x ];
- }
- __webpack_exports__.a = _of;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), omit = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(names, obj) {
- for (var result = {}, index = {}, idx = 0, len = names.length; idx < len; ) index[names[idx]] = 1,
- idx += 1;
- for (var prop in obj) index.hasOwnProperty(prop) || (result[prop] = obj[prop]);
- return result;
- });
- __webpack_exports__.a = omit;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_arity__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_1__internal_curry1__ = __webpack_require__(4), once = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry1__.a)(function(fn) {
- var result, called = !1;
- return Object(__WEBPACK_IMPORTED_MODULE_0__internal_arity__.a)(fn.length, function() {
- return called ? result : (called = !0, result = fn.apply(this, arguments));
- });
- });
- __webpack_exports__.a = once;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), pair = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(fst, snd) {
- return [ fst, snd ];
- });
- __webpack_exports__.a = pair;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_concat__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_1__internal_createPartialApplicator__ = __webpack_require__(344), partial = Object(__WEBPACK_IMPORTED_MODULE_1__internal_createPartialApplicator__.a)(__WEBPACK_IMPORTED_MODULE_0__internal_concat__.a);
- __webpack_exports__.a = partial;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_concat__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_1__internal_createPartialApplicator__ = __webpack_require__(344), __WEBPACK_IMPORTED_MODULE_2__flip__ = __webpack_require__(146), partialRight = Object(__WEBPACK_IMPORTED_MODULE_1__internal_createPartialApplicator__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__flip__.a)(__WEBPACK_IMPORTED_MODULE_0__internal_concat__.a));
- __webpack_exports__.a = partialRight;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__filter__ = __webpack_require__(210), __WEBPACK_IMPORTED_MODULE_1__juxt__ = __webpack_require__(336), __WEBPACK_IMPORTED_MODULE_2__reject__ = __webpack_require__(144), partition = Object(__WEBPACK_IMPORTED_MODULE_1__juxt__.a)([ __WEBPACK_IMPORTED_MODULE_0__filter__.a, __WEBPACK_IMPORTED_MODULE_2__reject__.a ]);
- __webpack_exports__.a = partition;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__equals__ = __webpack_require__(31), __WEBPACK_IMPORTED_MODULE_2__path__ = __webpack_require__(80), pathEq = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(_path, val, obj) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__equals__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__path__.a)(_path, obj), val);
- });
- __webpack_exports__.a = pathEq;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__defaultTo__ = __webpack_require__(321), __WEBPACK_IMPORTED_MODULE_2__path__ = __webpack_require__(80), pathOr = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(d, p, obj) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__defaultTo__.a)(d, Object(__WEBPACK_IMPORTED_MODULE_2__path__.a)(p, obj));
- });
- __webpack_exports__.a = pathOr;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__path__ = __webpack_require__(80), pathSatisfies = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(pred, propPath, obj) {
- return propPath.length > 0 && pred(Object(__WEBPACK_IMPORTED_MODULE_1__path__.a)(propPath, obj));
- });
- __webpack_exports__.a = pathSatisfies;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), pick = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(names, obj) {
- for (var result = {}, idx = 0; idx < names.length; ) names[idx] in obj && (result[names[idx]] = obj[names[idx]]),
- idx += 1;
- return result;
- });
- __webpack_exports__.a = pick;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), pickBy = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(test, obj) {
- var result = {};
- for (var prop in obj) test(obj[prop], prop, obj) && (result[prop] = obj[prop]);
- return result;
- });
- __webpack_exports__.a = pickBy;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function pipeK() {
- if (0 === arguments.length) throw new Error("pipeK requires at least one argument");
- return __WEBPACK_IMPORTED_MODULE_0__composeK__.a.apply(this, Object(__WEBPACK_IMPORTED_MODULE_1__reverse__.a)(arguments));
- }
- __webpack_exports__.a = pipeK;
- var __WEBPACK_IMPORTED_MODULE_0__composeK__ = __webpack_require__(314), __WEBPACK_IMPORTED_MODULE_1__reverse__ = __webpack_require__(142);
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__multiply__ = __webpack_require__(342), __WEBPACK_IMPORTED_MODULE_1__reduce__ = __webpack_require__(45), product = Object(__WEBPACK_IMPORTED_MODULE_1__reduce__.a)(__WEBPACK_IMPORTED_MODULE_0__multiply__.a, 1);
- __webpack_exports__.a = product;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_map__ = __webpack_require__(136), __WEBPACK_IMPORTED_MODULE_1__identity__ = __webpack_require__(215), __WEBPACK_IMPORTED_MODULE_2__pickAll__ = __webpack_require__(345), __WEBPACK_IMPORTED_MODULE_3__useWith__ = __webpack_require__(347), project = Object(__WEBPACK_IMPORTED_MODULE_3__useWith__.a)(__WEBPACK_IMPORTED_MODULE_0__internal_map__.a, [ __WEBPACK_IMPORTED_MODULE_2__pickAll__.a, __WEBPACK_IMPORTED_MODULE_1__identity__.a ]);
- __webpack_exports__.a = project;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__equals__ = __webpack_require__(31), propEq = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(name, val, obj) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__equals__.a)(val, obj[name]);
- });
- __webpack_exports__.a = propEq;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__is__ = __webpack_require__(335), propIs = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(type, name, obj) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__is__.a)(type, obj[name]);
- });
- __webpack_exports__.a = propIs;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__internal_has__ = __webpack_require__(26), propOr = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(val, p, obj) {
- return null != obj && Object(__WEBPACK_IMPORTED_MODULE_1__internal_has__.a)(p, obj) ? obj[p] : val;
- });
- __webpack_exports__.a = propOr;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), propSatisfies = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(pred, name, obj) {
- return pred(obj[name]);
- });
- __webpack_exports__.a = propSatisfies;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), props = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(ps, obj) {
- for (var len = ps.length, out = [], idx = 0; idx < len; ) out[idx] = obj[ps[idx]],
- idx += 1;
- return out;
- });
- __webpack_exports__.a = props;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_isNumber__ = __webpack_require__(338), range = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(from, to) {
- if (!Object(__WEBPACK_IMPORTED_MODULE_1__internal_isNumber__.a)(from) || !Object(__WEBPACK_IMPORTED_MODULE_1__internal_isNumber__.a)(to)) throw new TypeError("Both arguments to range must be numbers");
- for (var result = [], n = from; n < to; ) result.push(n), n += 1;
- return result;
- });
- __webpack_exports__.a = range;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curryN__ = __webpack_require__(135), __WEBPACK_IMPORTED_MODULE_1__internal_reduce__ = __webpack_require__(30), __WEBPACK_IMPORTED_MODULE_2__internal_reduced__ = __webpack_require__(58), reduceWhile = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curryN__.a)(4, [], function(pred, fn, a, list) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__internal_reduce__.a)(function(acc, x) {
- return pred(acc, x) ? fn(acc, x) : Object(__WEBPACK_IMPORTED_MODULE_2__internal_reduced__.a)(acc);
- }, a, list);
- });
- __webpack_exports__.a = reduceWhile;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__internal_reduced__ = __webpack_require__(58), reduced = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(__WEBPACK_IMPORTED_MODULE_1__internal_reduced__.a);
- __webpack_exports__.a = reduced;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__always__ = __webpack_require__(78), __WEBPACK_IMPORTED_MODULE_2__times__ = __webpack_require__(349), repeat = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(value, n) {
- return Object(__WEBPACK_IMPORTED_MODULE_2__times__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__always__.a)(value), n);
- });
- __webpack_exports__.a = repeat;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), replace = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(regex, replacement, str) {
- return str.replace(regex, replacement);
- });
- __webpack_exports__.a = replace;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), scan = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(fn, acc, list) {
- for (var idx = 0, len = list.length, result = [ acc ]; idx < len; ) acc = fn(acc, list[idx]),
- result[idx + 1] = acc, idx += 1;
- return result;
- });
- __webpack_exports__.a = scan;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__always__ = __webpack_require__(78), __WEBPACK_IMPORTED_MODULE_2__over__ = __webpack_require__(343), set = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(lens, v, x) {
- return Object(__WEBPACK_IMPORTED_MODULE_2__over__.a)(lens, Object(__WEBPACK_IMPORTED_MODULE_1__always__.a)(v), x);
- });
- __webpack_exports__.a = set;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), sort = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(comparator, list) {
- return Array.prototype.slice.call(list, 0).sort(comparator);
- });
- __webpack_exports__.a = sort;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), sortBy = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(fn, list) {
- return Array.prototype.slice.call(list, 0).sort(function(a, b) {
- var aa = fn(a), bb = fn(b);
- return aa < bb ? -1 : aa > bb ? 1 : 0;
- });
- });
- __webpack_exports__.a = sortBy;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), sortWith = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(fns, list) {
- return Array.prototype.slice.call(list, 0).sort(function(a, b) {
- for (var result = 0, i = 0; 0 === result && i < fns.length; ) result = fns[i](a, b),
- i += 1;
- return result;
- });
- });
- __webpack_exports__.a = sortWith;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__invoker__ = __webpack_require__(102), split = Object(__WEBPACK_IMPORTED_MODULE_0__invoker__.a)(1, "split");
- __webpack_exports__.a = split;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__length__ = __webpack_require__(337), __WEBPACK_IMPORTED_MODULE_2__slice__ = __webpack_require__(34), splitAt = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(index, array) {
- return [ Object(__WEBPACK_IMPORTED_MODULE_2__slice__.a)(0, index, array), Object(__WEBPACK_IMPORTED_MODULE_2__slice__.a)(index, Object(__WEBPACK_IMPORTED_MODULE_1__length__.a)(array), array) ];
- });
- __webpack_exports__.a = splitAt;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__slice__ = __webpack_require__(34), splitEvery = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(n, list) {
- if (n <= 0) throw new Error("First argument to splitEvery must be a positive integer");
- for (var result = [], idx = 0; idx < list.length; ) result.push(Object(__WEBPACK_IMPORTED_MODULE_1__slice__.a)(idx, idx += n, list));
- return result;
- });
- __webpack_exports__.a = splitEvery;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), splitWhen = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(pred, list) {
- for (var idx = 0, len = list.length, prefix = []; idx < len && !pred(list[idx]); ) prefix.push(list[idx]),
- idx += 1;
- return [ prefix, Array.prototype.slice.call(list, idx) ];
- });
- __webpack_exports__.a = splitWhen;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__equals__ = __webpack_require__(31), __WEBPACK_IMPORTED_MODULE_2__take__ = __webpack_require__(214), startsWith = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(prefix, list) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__equals__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__take__.a)(prefix.length, list), prefix);
- });
- __webpack_exports__.a = startsWith;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), subtract = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- return Number(a) - Number(b);
- });
- __webpack_exports__.a = subtract;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__concat__ = __webpack_require__(209), __WEBPACK_IMPORTED_MODULE_2__difference__ = __webpack_require__(322), symmetricDifference = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(list1, list2) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__concat__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__difference__.a)(list1, list2), Object(__WEBPACK_IMPORTED_MODULE_2__difference__.a)(list2, list1));
- });
- __webpack_exports__.a = symmetricDifference;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__concat__ = __webpack_require__(209), __WEBPACK_IMPORTED_MODULE_2__differenceWith__ = __webpack_require__(323), symmetricDifferenceWith = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(pred, list1, list2) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__concat__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__differenceWith__.a)(pred, list1, list2), Object(__WEBPACK_IMPORTED_MODULE_2__differenceWith__.a)(pred, list2, list1));
- });
- __webpack_exports__.a = symmetricDifferenceWith;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__slice__ = __webpack_require__(34), takeLastWhile = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(fn, xs) {
- for (var idx = xs.length - 1; idx >= 0 && fn(xs[idx]); ) idx -= 1;
- return Object(__WEBPACK_IMPORTED_MODULE_1__slice__.a)(idx + 1, 1 / 0, xs);
- });
- __webpack_exports__.a = takeLastWhile;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_xtakeWhile__ = __webpack_require__(742), __WEBPACK_IMPORTED_MODULE_3__slice__ = __webpack_require__(34), takeWhile = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([ "takeWhile" ], __WEBPACK_IMPORTED_MODULE_2__internal_xtakeWhile__.a, function(fn, xs) {
- for (var idx = 0, len = xs.length; idx < len && fn(xs[idx]); ) idx += 1;
- return Object(__WEBPACK_IMPORTED_MODULE_3__slice__.a)(0, idx, xs);
- }));
- __webpack_exports__.a = takeWhile;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__reduced__ = __webpack_require__(58), __WEBPACK_IMPORTED_MODULE_2__xfBase__ = __webpack_require__(19), XTakeWhile = function() {
- function XTakeWhile(f, xf) {
- this.xf = xf, this.f = f;
- }
- return XTakeWhile.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_2__xfBase__.a.init,
- XTakeWhile.prototype["@@transducer/result"] = __WEBPACK_IMPORTED_MODULE_2__xfBase__.a.result,
- XTakeWhile.prototype["@@transducer/step"] = function(result, input) {
- return this.f(input) ? this.xf["@@transducer/step"](result, input) : Object(__WEBPACK_IMPORTED_MODULE_1__reduced__.a)(result);
- }, XTakeWhile;
- }(), _xtakeWhile = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(f, xf) {
- return new XTakeWhile(f, xf);
- });
- __webpack_exports__.a = _xtakeWhile;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__ = __webpack_require__(15), __WEBPACK_IMPORTED_MODULE_2__internal_xtap__ = __webpack_require__(744), tap = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_1__internal_dispatchable__.a)([], __WEBPACK_IMPORTED_MODULE_2__internal_xtap__.a, function(fn, x) {
- return fn(x), x;
- }));
- __webpack_exports__.a = tap;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__xfBase__ = __webpack_require__(19), XTap = function() {
- function XTap(f, xf) {
- this.xf = xf, this.f = f;
- }
- return XTap.prototype["@@transducer/init"] = __WEBPACK_IMPORTED_MODULE_1__xfBase__.a.init,
- XTap.prototype["@@transducer/result"] = __WEBPACK_IMPORTED_MODULE_1__xfBase__.a.result,
- XTap.prototype["@@transducer/step"] = function(result, input) {
- return this.f(input), this.xf["@@transducer/step"](result, input);
- }, XTap;
- }(), _xtap = Object(__WEBPACK_IMPORTED_MODULE_0__curry2__.a)(function(f, xf) {
- return new XTap(f, xf);
- });
- __webpack_exports__.a = _xtap;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_cloneRegExp__ = __webpack_require__(311), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2__internal_isRegExp__ = __webpack_require__(746), __WEBPACK_IMPORTED_MODULE_3__toString__ = __webpack_require__(100), test = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(function(pattern, str) {
- if (!Object(__WEBPACK_IMPORTED_MODULE_2__internal_isRegExp__.a)(pattern)) throw new TypeError("‘test’ requires a value of type RegExp as its first argument; received " + Object(__WEBPACK_IMPORTED_MODULE_3__toString__.a)(pattern));
- return Object(__WEBPACK_IMPORTED_MODULE_0__internal_cloneRegExp__.a)(pattern).test(str);
- });
- __webpack_exports__.a = test;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- function _isRegExp(x) {
- return "[object RegExp]" === Object.prototype.toString.call(x);
- }
- __webpack_exports__.a = _isRegExp;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__invoker__ = __webpack_require__(102), toLower = Object(__WEBPACK_IMPORTED_MODULE_0__invoker__.a)(0, "toLowerCase");
- __webpack_exports__.a = toLower;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__internal_has__ = __webpack_require__(26), toPairs = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(obj) {
- var pairs = [];
- for (var prop in obj) Object(__WEBPACK_IMPORTED_MODULE_1__internal_has__.a)(prop, obj) && (pairs[pairs.length] = [ prop, obj[prop] ]);
- return pairs;
- });
- __webpack_exports__.a = toPairs;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), toPairsIn = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(obj) {
- var pairs = [];
- for (var prop in obj) pairs[pairs.length] = [ prop, obj[prop] ];
- return pairs;
- });
- __webpack_exports__.a = toPairsIn;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__invoker__ = __webpack_require__(102), toUpper = Object(__WEBPACK_IMPORTED_MODULE_0__invoker__.a)(0, "toUpperCase");
- __webpack_exports__.a = toUpper;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_reduce__ = __webpack_require__(30), __WEBPACK_IMPORTED_MODULE_1__internal_xwrap__ = __webpack_require__(298), __WEBPACK_IMPORTED_MODULE_2__curryN__ = __webpack_require__(23), transduce = Object(__WEBPACK_IMPORTED_MODULE_2__curryN__.a)(4, function(xf, fn, acc, list) {
- return Object(__WEBPACK_IMPORTED_MODULE_0__internal_reduce__.a)(xf("function" == typeof fn ? Object(__WEBPACK_IMPORTED_MODULE_1__internal_xwrap__.a)(fn) : fn), acc, list);
- });
- __webpack_exports__.a = transduce;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), transpose = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(outerlist) {
- for (var i = 0, result = []; i < outerlist.length; ) {
- for (var innerlist = outerlist[i], j = 0; j < innerlist.length; ) void 0 === result[j] && (result[j] = []),
- result[j].push(innerlist[j]), j += 1;
- i += 1;
- }
- return result;
- });
- __webpack_exports__.a = transpose;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_1__map__ = __webpack_require__(27), __WEBPACK_IMPORTED_MODULE_2__sequence__ = __webpack_require__(350), traverse = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(of, f, traversable) {
- return "function" == typeof traversable["fantasy-land/traverse"] ? traversable["fantasy-land/traverse"](f, of) : Object(__WEBPACK_IMPORTED_MODULE_2__sequence__.a)(of, Object(__WEBPACK_IMPORTED_MODULE_1__map__.a)(f, traversable));
- });
- __webpack_exports__.a = traverse;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), ws = "\t\n\v\f\r   ᠎              \u2028\u2029\ufeff", zeroWidth = "​", hasProtoTrim = "function" == typeof String.prototype.trim, _trim = hasProtoTrim && !ws.trim() && zeroWidth.trim() ? function(str) {
- return str.trim();
- } : function(str) {
- var beginRx = new RegExp("^[" + ws + "][" + ws + "]*"), endRx = new RegExp("[" + ws + "][" + ws + "]*$");
- return str.replace(beginRx, "").replace(endRx, "");
- }, trim = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(_trim);
- __webpack_exports__.a = trim;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_arity__ = __webpack_require__(43), __WEBPACK_IMPORTED_MODULE_1__internal_concat__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_2__internal_curry2__ = __webpack_require__(0), tryCatch = Object(__WEBPACK_IMPORTED_MODULE_2__internal_curry2__.a)(function(tryer, catcher) {
- return Object(__WEBPACK_IMPORTED_MODULE_0__internal_arity__.a)(tryer.length, function() {
- try {
- return tryer.apply(this, arguments);
- } catch (e) {
- return catcher.apply(this, Object(__WEBPACK_IMPORTED_MODULE_1__internal_concat__.a)([ e ], arguments));
- }
- });
- });
- __webpack_exports__.a = tryCatch;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), unapply = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(fn) {
- return function() {
- return fn(Array.prototype.slice.call(arguments, 0));
- };
- });
- __webpack_exports__.a = unapply;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_1__nAry__ = __webpack_require__(139), unary = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(fn) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__nAry__.a)(1, fn);
- });
- __webpack_exports__.a = unary;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__curryN__ = __webpack_require__(23), uncurryN = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(depth, fn) {
- return Object(__WEBPACK_IMPORTED_MODULE_1__curryN__.a)(depth, function() {
- for (var endIdx, currentDepth = 1, value = fn, idx = 0; currentDepth <= depth && "function" == typeof value; ) endIdx = currentDepth === depth ? arguments.length : idx + value.length,
- value = value.apply(this, Array.prototype.slice.call(arguments, idx, endIdx)), currentDepth += 1,
- idx = endIdx;
- return value;
- });
- });
- __webpack_exports__.a = uncurryN;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), unfold = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(fn, seed) {
- for (var pair = fn(seed), result = []; pair && pair.length; ) result[result.length] = pair[0],
- pair = fn(pair[1]);
- return result;
- });
- __webpack_exports__.a = unfold;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_concat__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2__compose__ = __webpack_require__(207), __WEBPACK_IMPORTED_MODULE_3__uniq__ = __webpack_require__(217), union = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__compose__.a)(__WEBPACK_IMPORTED_MODULE_3__uniq__.a, __WEBPACK_IMPORTED_MODULE_0__internal_concat__.a));
- __webpack_exports__.a = union;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_concat__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_1__internal_curry3__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_2__uniqWith__ = __webpack_require__(351), unionWith = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry3__.a)(function(pred, list1, list2) {
- return Object(__WEBPACK_IMPORTED_MODULE_2__uniqWith__.a)(pred, Object(__WEBPACK_IMPORTED_MODULE_0__internal_concat__.a)(list1, list2));
- });
- __webpack_exports__.a = unionWith;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), unless = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(pred, whenFalseFn, x) {
- return pred(x) ? x : whenFalseFn(x);
- });
- __webpack_exports__.a = unless;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_identity__ = __webpack_require__(216), __WEBPACK_IMPORTED_MODULE_1__chain__ = __webpack_require__(205), unnest = Object(__WEBPACK_IMPORTED_MODULE_1__chain__.a)(__WEBPACK_IMPORTED_MODULE_0__internal_identity__.a);
- __webpack_exports__.a = unnest;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), until = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(pred, fn, init) {
- for (var val = init; !pred(val); ) val = fn(val);
- return val;
- });
- __webpack_exports__.a = until;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry1__ = __webpack_require__(4), valuesIn = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry1__.a)(function(obj) {
- var prop, vs = [];
- for (prop in obj) vs[vs.length] = obj[prop];
- return vs;
- });
- __webpack_exports__.a = valuesIn;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), Const = function(x) {
- return {
- value: x,
- "fantasy-land/map": function() {
- return this;
- }
- };
- }, view = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(lens, x) {
- return lens(Const)(x).value;
- });
- __webpack_exports__.a = view;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), when = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(pred, whenTrueFn, x) {
- return pred(x) ? whenTrueFn(x) : x;
- });
- __webpack_exports__.a = when;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1__equals__ = __webpack_require__(31), __WEBPACK_IMPORTED_MODULE_2__map__ = __webpack_require__(27), __WEBPACK_IMPORTED_MODULE_3__where__ = __webpack_require__(352), whereEq = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(spec, testObj) {
- return Object(__WEBPACK_IMPORTED_MODULE_3__where__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__map__.a)(__WEBPACK_IMPORTED_MODULE_1__equals__.a, spec), testObj);
- });
- __webpack_exports__.a = whereEq;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_contains__ = __webpack_require__(81), __WEBPACK_IMPORTED_MODULE_1__internal_curry2__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2__flip__ = __webpack_require__(146), __WEBPACK_IMPORTED_MODULE_3__reject__ = __webpack_require__(144), without = Object(__WEBPACK_IMPORTED_MODULE_1__internal_curry2__.a)(function(xs, list) {
- return Object(__WEBPACK_IMPORTED_MODULE_3__reject__.a)(Object(__WEBPACK_IMPORTED_MODULE_2__flip__.a)(__WEBPACK_IMPORTED_MODULE_0__internal_contains__.a)(xs), list);
- });
- __webpack_exports__.a = without;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), xprod = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- for (var j, idx = 0, ilen = a.length, jlen = b.length, result = []; idx < ilen; ) {
- for (j = 0; j < jlen; ) result[result.length] = [ a[idx], b[j] ], j += 1;
- idx += 1;
- }
- return result;
- });
- __webpack_exports__.a = xprod;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), zip = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(a, b) {
- for (var rv = [], idx = 0, len = Math.min(a.length, b.length); idx < len; ) rv[idx] = [ a[idx], b[idx] ],
- idx += 1;
- return rv;
- });
- __webpack_exports__.a = zip;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry2__ = __webpack_require__(0), zipObj = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry2__.a)(function(keys, values) {
- for (var idx = 0, len = Math.min(keys.length, values.length), out = {}; idx < len; ) out[keys[idx]] = values[idx],
- idx += 1;
- return out;
- });
- __webpack_exports__.a = zipObj;
-}, function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- var __WEBPACK_IMPORTED_MODULE_0__internal_curry3__ = __webpack_require__(5), zipWith = Object(__WEBPACK_IMPORTED_MODULE_0__internal_curry3__.a)(function(fn, a, b) {
- for (var rv = [], idx = 0, len = Math.min(a.length, b.length); idx < len; ) rv[idx] = fn(a[idx], b[idx]),
- idx += 1;
- return rv;
- });
- __webpack_exports__.a = zipWith;
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -32745,13 +28514,18 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _AppBar = __webpack_require__(775), _AppBar2 = _interopRequireDefault(_AppBar), _Toolbar = __webpack_require__(779), _Toolbar2 = _interopRequireDefault(_Toolbar), _Transition = __webpack_require__(149), _Transition2 = _interopRequireDefault(_Transition), _IconButton = __webpack_require__(782), _IconButton2 = _interopRequireDefault(_IconButton), _Typography = __webpack_require__(359), _Typography2 = _interopRequireDefault(_Typography), _ChevronLeft = __webpack_require__(803), _ChevronLeft2 = _interopRequireDefault(_ChevronLeft), _Common = __webpack_require__(150), arrowDefault = {
- transition: "transform " + _Common.DURATION + "ms"
- }, arrowTransition = {
- entered: {
- transform: "rotate(180deg)"
+ }(), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _AppBar = __webpack_require__(454), _AppBar2 = _interopRequireDefault(_AppBar), _Toolbar = __webpack_require__(458), _Toolbar2 = _interopRequireDefault(_Toolbar), _Transition = __webpack_require__(108), _Transition2 = _interopRequireDefault(_Transition), _IconButton = __webpack_require__(461), _IconButton2 = _interopRequireDefault(_IconButton), _Typography = __webpack_require__(109), _Typography2 = _interopRequireDefault(_Typography), _ChevronLeft = __webpack_require__(481), _ChevronLeft2 = _interopRequireDefault(_ChevronLeft), _common = __webpack_require__(61), styles = {
+ arrow: {
+ default: {
+ transition: "transform " + _common.DURATION + "ms"
+ },
+ transition: {
+ entered: {
+ transform: "rotate(180deg)"
+ }
+ }
}
- }, styles = function(theme) {
+ }, themeStyles = function(theme) {
return {
header: {
backgroundColor: theme.palette.background.appBar,
@@ -32762,7 +28536,7 @@ var _publicBundleJs = []byte(`!function(modules) {
paddingLeft: theme.spacing.unit,
paddingRight: theme.spacing.unit
},
- mainText: {
+ title: {
paddingLeft: theme.spacing.unit
}
};
@@ -32772,13 +28546,11 @@ var _publicBundleJs = []byte(`!function(modules) {
_classCallCheck(this, Header);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) args[_key] = arguments[_key];
return _temp = _this = _possibleConstructorReturn(this, (_ref = Header.__proto__ || Object.getPrototypeOf(Header)).call.apply(_ref, [ this ].concat(args))),
- _this.changeSideBar = function() {
- _this.props.opened ? _this.props.closeSideBar() : _this.props.openSideBar();
- }, _this.arrowButton = function(transitionState) {
+ _this.arrow = function(transitionState) {
return _react2.default.createElement(_IconButton2.default, {
- onClick: _this.changeSideBar
+ onClick: _this.props.switchSideBar
}, _react2.default.createElement(_ChevronLeft2.default, {
- style: _extends({}, arrowDefault, arrowTransition[transitionState])
+ style: _extends({}, styles.arrow.default, styles.arrow.transition[transitionState])
}));
}, _ret = _temp, _possibleConstructorReturn(_this, _ret);
}
@@ -32800,18 +28572,18 @@ var _publicBundleJs = []byte(`!function(modules) {
mountOnEnter: !0,
in: opened,
timeout: {
- enter: _Common.DURATION
+ enter: _common.DURATION
}
- }, this.arrowButton), _react2.default.createElement(_Typography2.default, {
+ }, this.arrow), _react2.default.createElement(_Typography2.default, {
type: "title",
color: "inherit",
noWrap: !0,
- className: classes.mainText
+ className: classes.title
}, "Go Ethereum Dashboard")));
}
} ]), Header;
}(_react.Component);
- exports.default = (0, _withStyles2.default)(styles)(Header);
+ exports.default = (0, _withStyles2.default)(themeStyles)(Header);
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -32822,7 +28594,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _AppBar = __webpack_require__(776);
+ var _AppBar = __webpack_require__(455);
Object.defineProperty(exports, "default", {
enumerable: !0,
get: function() {
@@ -32853,7 +28625,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = void 0;
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _helpers = __webpack_require__(69), _Paper = __webpack_require__(777), _Paper2 = _interopRequireDefault(_Paper), styles = exports.styles = function(theme) {
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _helpers = __webpack_require__(52), _Paper = __webpack_require__(456), _Paper2 = _interopRequireDefault(_Paper), styles = exports.styles = function(theme) {
return {
root: {
display: "flex",
@@ -32884,12 +28656,12 @@ var _publicBundleJs = []byte(`!function(modules) {
color: theme.palette.getContrastText(theme.palette.background.appBar)
},
colorPrimary: {
- backgroundColor: theme.palette.primary[500],
- color: theme.palette.getContrastText(theme.palette.primary[500])
+ backgroundColor: theme.palette.primary.main,
+ color: theme.palette.primary.contrastText
},
- colorAccent: {
- backgroundColor: theme.palette.secondary.A200,
- color: theme.palette.getContrastText(theme.palette.secondary.A200)
+ colorSecondary: {
+ backgroundColor: theme.palette.secondary.main,
+ color: theme.palette.secondary.contrastText
}
};
};
@@ -32897,7 +28669,7 @@ var _publicBundleJs = []byte(`!function(modules) {
children: _propTypes2.default.node.isRequired,
classes: _propTypes2.default.object.isRequired,
className: _propTypes2.default.string,
- color: _propTypes2.default.oneOf([ "inherit", "primary", "accent", "default" ]),
+ color: _propTypes2.default.oneOf([ "inherit", "primary", "secondary", "default" ]),
position: _propTypes2.default.oneOf([ "static", "fixed", "absolute" ])
} : {}, AppBar.defaultProps = {
color: "primary",
@@ -32905,7 +28677,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, exports.default = (0, _withStyles2.default)(styles, {
name: "MuiAppBar"
})(AppBar);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -32916,7 +28688,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _Paper = __webpack_require__(778);
+ var _Paper = __webpack_require__(457);
Object.defineProperty(exports, "default", {
enumerable: !0,
get: function() {
@@ -32932,19 +28704,19 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}
function Paper(props) {
- var classes = props.classes, classNameProp = props.className, ComponentProp = props.component, square = props.square, elevation = props.elevation, other = (0,
+ var classes = props.classes, classNameProp = props.className, Component = props.component, square = props.square, elevation = props.elevation, other = (0,
_objectWithoutProperties3.default)(props, [ "classes", "className", "component", "square", "elevation" ]);
- "production" !== process.env.NODE_ENV && (0, _warning2.default)(elevation >= 0 && elevation < 25, "Material-UI: this elevation ` + "`" + `" + elevation + "` + "`" + ` is not implemented.");
+ "production" !== process.env.NODE_ENV && (0, _warning2.default)(elevation >= 0 && elevation < 25, "Material-UI: this elevation `))))) + (((("`" + (`" + elevation + "` + "`")) + (` is not implemented.");
var className = (0, _classnames2.default)(classes.root, classes["shadow" + (elevation >= 0 ? elevation : 0)], (0,
_defineProperty3.default)({}, classes.rounded, !square), classNameProp);
- return _react2.default.createElement(ComponentProp, (0, _extends3.default)({
+ return _react2.default.createElement(Component, (0, _extends3.default)({
className: className
}, other));
}
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = void 0;
- var _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), styles = exports.styles = function(theme) {
+ var _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), styles = exports.styles = function(theme) {
var shadows = {};
return theme.shadows.forEach(function(shadow, index) {
shadows["shadow" + index] = {
@@ -32973,7 +28745,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, exports.default = (0, _withStyles2.default)(styles, {
name: "MuiPaper"
})(Paper);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -32984,7 +28756,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _Toolbar = __webpack_require__(780);
+ var _Toolbar = __webpack_require__(459);
Object.defineProperty(exports, "default", {
enumerable: !0,
get: function() {
@@ -33010,7 +28782,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = void 0;
- var _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), styles = exports.styles = function(theme) {
+ var _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), styles = exports.styles = function(theme) {
return {
root: (0, _extends3.default)({
position: "relative",
@@ -33021,7 +28793,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
};
Toolbar.propTypes = "production" !== process.env.NODE_ENV ? {
- children: _propTypes2.default.node.isRequired,
+ children: _propTypes2.default.node,
classes: _propTypes2.default.object.isRequired,
className: _propTypes2.default.string,
disableGutters: _propTypes2.default.bool
@@ -33030,7 +28802,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, exports.default = (0, _withStyles2.default)(styles, {
name: "MuiToolbar"
})(Toolbar);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
function transitionTimeout(transitionType) {
@@ -33045,7 +28817,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
exports.__esModule = !0, exports.classNamesShape = exports.timeoutsShape = void 0,
exports.transitionTimeout = transitionTimeout;
- var _propTypes = __webpack_require__(2), _propTypes2 = function(obj) {
+ var _propTypes = __webpack_require__(1), _propTypes2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -33073,7 +28845,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _IconButton = __webpack_require__(783);
+ var _IconButton = __webpack_require__(462);
Object.defineProperty(exports, "default", {
enumerable: !0,
get: function() {
@@ -33096,7 +28868,7 @@ var _publicBundleJs = []byte(`!function(modules) {
_helpers.capitalizeFirstLetter)(color)], "default" !== color), (0, _defineProperty3.default)(_classNames, classes.disabled, disabled),
_classNames), className),
centerRipple: !0,
- keyboardFocusedClassName: classes.keyboardFocused,
+ focusRipple: !0,
disabled: disabled,
rootRef: buttonRef,
ref: rootRef
@@ -33113,8 +28885,8 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = void 0;
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _ButtonBase = __webpack_require__(353), _ButtonBase2 = _interopRequireDefault(_ButtonBase), _helpers = __webpack_require__(69), _Icon = __webpack_require__(356), _Icon2 = _interopRequireDefault(_Icon), _reactHelpers = __webpack_require__(357);
- __webpack_require__(358);
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _ButtonBase = __webpack_require__(234), _ButtonBase2 = _interopRequireDefault(_ButtonBase), _helpers = __webpack_require__(52), _Icon = __webpack_require__(237), _Icon2 = _interopRequireDefault(_Icon), _reactHelpers = __webpack_require__(238);
+ __webpack_require__(239);
var styles = exports.styles = function(theme) {
return {
root: {
@@ -33130,17 +28902,14 @@ var _publicBundleJs = []byte(`!function(modules) {
duration: theme.transitions.duration.shortest
})
},
- colorAccent: {
- color: theme.palette.secondary.A200
- },
- colorContrast: {
- color: theme.palette.getContrastText(theme.palette.primary[500])
+ colorInherit: {
+ color: "inherit"
},
colorPrimary: {
- color: theme.palette.primary[500]
+ color: theme.palette.primary.main
},
- colorInherit: {
- color: "inherit"
+ colorSecondary: {
+ color: theme.palette.secondary.main
},
disabled: {
color: theme.palette.action.disabled
@@ -33154,9 +28923,6 @@ var _publicBundleJs = []byte(`!function(modules) {
icon: {
width: "1em",
height: "1em"
- },
- keyboardFocused: {
- backgroundColor: theme.palette.text.divider
}
};
};
@@ -33165,7 +28931,7 @@ var _publicBundleJs = []byte(`!function(modules) {
children: _propTypes2.default.node,
classes: _propTypes2.default.object.isRequired,
className: _propTypes2.default.string,
- color: _propTypes2.default.oneOf([ "default", "inherit", "primary", "contrast", "accent" ]),
+ color: _propTypes2.default.oneOf([ "default", "inherit", "primary", "secondary" ]),
disabled: _propTypes2.default.bool,
disableRipple: _propTypes2.default.bool,
rootRef: _propTypes2.default.func
@@ -33176,7 +28942,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, exports.default = (0, _withStyles2.default)(styles, {
name: "MuiIconButton"
})(IconButton);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -33188,7 +28954,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = void 0;
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _getPrototypeOf = __webpack_require__(38), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(39), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(40), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(41), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(42), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _reactDom = __webpack_require__(121), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _keycode = __webpack_require__(354), _keycode2 = _interopRequireDefault(_keycode), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _keyboardFocus = __webpack_require__(785), _TouchRipple = __webpack_require__(790), _TouchRipple2 = _interopRequireDefault(_TouchRipple), _createRippleHandler = __webpack_require__(799), _createRippleHandler2 = _interopRequireDefault(_createRippleHandler), styles = exports.styles = function(theme) {
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _getPrototypeOf = __webpack_require__(26), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(27), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(28), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(29), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(30), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _reactDom = __webpack_require__(95), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _keycode = __webpack_require__(235), _keycode2 = _interopRequireDefault(_keycode), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _keyboardFocus = __webpack_require__(464), _TouchRipple = __webpack_require__(468), _TouchRipple2 = _interopRequireDefault(_TouchRipple), _createRippleHandler = __webpack_require__(477), _createRippleHandler2 = _interopRequireDefault(_createRippleHandler), styles = exports.styles = function(theme) {
return {
root: {
display: "inline-flex",
@@ -33200,8 +28966,10 @@ var _publicBundleJs = []byte(`!function(modules) {
outline: "none",
border: 0,
borderRadius: 0,
+ padding: 0,
cursor: "pointer",
userSelect: "none",
+ verticalAlign: "middle",
appearance: "none",
textDecoration: "none",
color: "inherit",
@@ -33258,12 +29026,10 @@ var _publicBundleJs = []byte(`!function(modules) {
keyboardFocused: !1
});
}), _this.handleFocus = function(event) {
- if (!_this.props.disabled) {
- _this.button || (_this.button = event.currentTarget), event.persist();
- var keyboardFocusCallback = _this.onKeyboardFocusHandler.bind(_this, event);
- (0, _keyboardFocus.detectKeyboardFocus)(_this, _this.button, keyboardFocusCallback),
- _this.props.onFocus && _this.props.onFocus(event);
- }
+ _this.props.disabled || (_this.button || (_this.button = event.currentTarget), event.persist(),
+ (0, _keyboardFocus.detectKeyboardFocus)(_this, _this.button, function() {
+ _this.onKeyboardFocusHandler(event);
+ }), _this.props.onFocus && _this.props.onFocus(event));
}, _ret = _temp, (0, _possibleConstructorReturn3.default)(_this, _ret);
}
return (0, _inherits3.default)(ButtonBase, _React$Component), (0, _createClass3.default)(ButtonBase, [ {
@@ -33300,8 +29066,9 @@ var _publicBundleJs = []byte(`!function(modules) {
(0, _defineProperty3.default)(_classNames, keyboardFocusedClassName || "", this.state.keyboardFocused),
_classNames), classNameProp), buttonProps = {}, ComponentProp = component;
return ComponentProp || (ComponentProp = other.href ? "a" : "button"), "button" === ComponentProp && (buttonProps.type = type || "button"),
- "a" !== ComponentProp && (buttonProps.role = buttonProps.role || "button", buttonProps.disabled = disabled),
- _react2.default.createElement(ComponentProp, (0, _extends3.default)({
+ "a" !== ComponentProp && (buttonProps.role = "button" === buttonProps.type ? void 0 : "button",
+ buttonProps.disabled = disabled), _react2.default.createElement(ComponentProp, (0,
+ _extends3.default)({
onBlur: this.handleBlur,
onFocus: this.handleFocus,
onKeyDown: this.handleKeyDown,
@@ -33314,9 +29081,9 @@ var _publicBundleJs = []byte(`!function(modules) {
onTouchStart: this.handleTouchStart,
tabIndex: disabled ? -1 : tabIndex,
className: className
- }, buttonProps, other, {
+ }, buttonProps, {
ref: rootRef
- }), children, disableRipple || disabled ? null : _react2.default.createElement(_TouchRipple2.default, {
+ }, other), children, disableRipple || disabled ? null : _react2.default.createElement(_TouchRipple2.default, {
innerRef: function(node) {
_this2.ripple = node;
},
@@ -33360,7 +29127,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, exports.default = (0, _withStyles2.default)(styles, {
name: "MuiButtonBase"
})(ButtonBase);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -33392,11 +29159,11 @@ var _publicBundleJs = []byte(`!function(modules) {
value: !0
}), exports.focusKeyPressed = focusKeyPressed, exports.detectKeyboardFocus = detectKeyboardFocus,
exports.listenForFocusKeys = listenForFocusKeys;
- var _keycode = __webpack_require__(354), _keycode2 = _interopRequireDefault(_keycode), _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), _contains = __webpack_require__(786), _contains2 = _interopRequireDefault(_contains), _addEventListener = __webpack_require__(787), _addEventListener2 = _interopRequireDefault(_addEventListener), internal = {
+ var _keycode = __webpack_require__(235), _keycode2 = _interopRequireDefault(_keycode), _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), _contains = __webpack_require__(465), _contains2 = _interopRequireDefault(_contains), _addEventListener = __webpack_require__(467), _addEventListener2 = _interopRequireDefault(_addEventListener), internal = {
listening: !1,
focusKeyPressed: !1
}, FOCUS_KEYS = [ "tab", "enter", "space", "esc", "up", "down", "left", "right" ];
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
function fallback(context, node) {
@@ -33408,7 +29175,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _inDOM = __webpack_require__(220), _inDOM2 = function(obj) {
+ var _inDOM = __webpack_require__(466), _inDOM2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -33420,58 +29187,21 @@ var _publicBundleJs = []byte(`!function(modules) {
}(), module.exports = exports.default;
}, function(module, exports, __webpack_require__) {
"use strict";
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
- };
- }
- Object.defineProperty(exports, "__esModule", {
- value: !0
- }), exports.default = function(node, event, handler, capture) {
- return (0, _on2.default)(node, event, handler, capture), {
- remove: function() {
- (0, _off2.default)(node, event, handler, capture);
- }
- };
- };
- var _on = __webpack_require__(788), _on2 = _interopRequireDefault(_on), _off = __webpack_require__(789), _off2 = _interopRequireDefault(_off);
-}, function(module, exports, __webpack_require__) {
- "use strict";
Object.defineProperty(exports, "__esModule", {
value: !0
- });
- var _inDOM = __webpack_require__(220), _inDOM2 = function(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
- };
- }(_inDOM), on = function() {};
- _inDOM2.default && (on = function() {
- return document.addEventListener ? function(node, eventName, handler, capture) {
- return node.addEventListener(eventName, handler, capture || !1);
- } : document.attachEvent ? function(node, eventName, handler) {
- return node.attachEvent("on" + eventName, function(e) {
- e = e || window.event, e.target = e.target || e.srcElement, e.currentTarget = node,
- handler.call(node, e);
- });
- } : void 0;
- }()), exports.default = on, module.exports = exports.default;
+ }), exports.default = !("undefined" == typeof window || !window.document || !window.document.createElement),
+ module.exports = exports.default;
}, function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: !0
- });
- var _inDOM = __webpack_require__(220), _inDOM2 = function(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
+ }), exports.default = function(node, event, handler, capture) {
+ return node.addEventListener(event, handler, capture), {
+ remove: function() {
+ node.removeEventListener(event, handler, capture);
+ }
};
- }(_inDOM), off = function() {};
- _inDOM2.default && (off = function() {
- return document.addEventListener ? function(node, eventName, handler, capture) {
- return node.removeEventListener(eventName, handler, capture || !1);
- } : document.attachEvent ? function(node, eventName, handler) {
- return node.detachEvent("on" + eventName, handler);
- } : void 0;
- }()), exports.default = off, module.exports = exports.default;
+ };
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -33483,7 +29213,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = exports.DELAY_RIPPLE = void 0;
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _toConsumableArray2 = __webpack_require__(791), _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2), _getPrototypeOf = __webpack_require__(38), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(39), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(40), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(41), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(42), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _reactDom = __webpack_require__(121), _reactDom2 = _interopRequireDefault(_reactDom), _TransitionGroup = __webpack_require__(355), _TransitionGroup2 = _interopRequireDefault(_TransitionGroup), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _Ripple = __webpack_require__(798), _Ripple2 = _interopRequireDefault(_Ripple), DURATION = 550, DELAY_RIPPLE = exports.DELAY_RIPPLE = 80, styles = exports.styles = function(theme) {
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _toConsumableArray2 = __webpack_require__(469), _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2), _getPrototypeOf = __webpack_require__(26), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(27), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(28), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(29), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(30), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _reactDom = __webpack_require__(95), _reactDom2 = _interopRequireDefault(_reactDom), _TransitionGroup = __webpack_require__(236), _TransitionGroup2 = _interopRequireDefault(_TransitionGroup), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _Ripple = __webpack_require__(476), _Ripple2 = _interopRequireDefault(_Ripple), DURATION = 550, DELAY_RIPPLE = exports.DELAY_RIPPLE = 80, styles = exports.styles = function(theme) {
return {
root: {
display: "block",
@@ -33511,10 +29241,7 @@ var _publicBundleJs = []byte(`!function(modules) {
display: "block",
width: "100%",
height: "100%",
- animation: "mui-ripple-pulsate 1500ms " + theme.transitions.easing.easeInOut + " 200ms infinite",
- rippleVisible: {
- opacity: .2
- }
+ animation: "mui-ripple-pulsate 2500ms " + theme.transitions.easing.easeInOut + " 200ms infinite"
},
"@keyframes mui-ripple-enter": {
"0%": {
@@ -33537,7 +29264,7 @@ var _publicBundleJs = []byte(`!function(modules) {
transform: "scale(1)"
},
"50%": {
- transform: "scale(0.9)"
+ transform: "scale(0.92)"
},
"100%": {
transform: "scale(1)"
@@ -33671,11 +29398,11 @@ var _publicBundleJs = []byte(`!function(modules) {
flip: !1,
name: "MuiTouchRipple"
})(TouchRipple);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = !0;
- var _from = __webpack_require__(792), _from2 = function(obj) {
+ var _from = __webpack_require__(470), _from2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -33689,15 +29416,15 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, exports, __webpack_require__) {
module.exports = {
- default: __webpack_require__(793),
+ default: __webpack_require__(471),
__esModule: !0
};
}, function(module, exports, __webpack_require__) {
- __webpack_require__(186), __webpack_require__(794), module.exports = __webpack_require__(22).Array.from;
+ __webpack_require__(144), __webpack_require__(472), module.exports = __webpack_require__(17).Array.from;
}, function(module, exports, __webpack_require__) {
"use strict";
- var ctx = __webpack_require__(64), $export = __webpack_require__(25), toObject = __webpack_require__(76), call = __webpack_require__(284), isArrayIter = __webpack_require__(285), toLength = __webpack_require__(123), createProperty = __webpack_require__(795), getIterFn = __webpack_require__(286);
- $export($export.S + $export.F * !__webpack_require__(796)(function(iter) {
+ var ctx = __webpack_require__(47), $export = __webpack_require__(19), toObject = __webpack_require__(59), call = __webpack_require__(221), isArrayIter = __webpack_require__(222), toLength = __webpack_require__(97), createProperty = __webpack_require__(473), getIterFn = __webpack_require__(223);
+ $export($export.S + $export.F * !__webpack_require__(474)(function(iter) {
Array.from(iter);
}), "Array", {
from: function(arrayLike) {
@@ -33710,12 +29437,12 @@ var _publicBundleJs = []byte(`!function(modules) {
});
}, function(module, exports, __webpack_require__) {
"use strict";
- var $defineProperty = __webpack_require__(32), createDesc = __webpack_require__(91);
+ var $defineProperty = __webpack_require__(22), createDesc = __webpack_require__(71);
module.exports = function(object, index, value) {
index in object ? $defineProperty.f(object, index, createDesc(0, value)) : object[index] = value;
};
}, function(module, exports, __webpack_require__) {
- var ITERATOR = __webpack_require__(29)("iterator"), SAFE_CLOSING = !1;
+ var ITERATOR = __webpack_require__(21)("iterator"), SAFE_CLOSING = !1;
try {
var riter = [ 7 ][ITERATOR]();
riter.return = function() {
@@ -33771,7 +29498,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return childMapping;
}
exports.__esModule = !0, exports.getChildMapping = getChildMapping, exports.mergeChildMappings = mergeChildMappings;
- var _react = __webpack_require__(1);
+ var _react = __webpack_require__(0);
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -33783,7 +29510,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _getPrototypeOf = __webpack_require__(38), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(39), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(40), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(41), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(42), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _Transition = __webpack_require__(149), _Transition2 = _interopRequireDefault(_Transition), Ripple = function(_React$Component) {
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _getPrototypeOf = __webpack_require__(26), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(27), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(28), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(29), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(30), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _Transition = __webpack_require__(108), _Transition2 = _interopRequireDefault(_Transition), Ripple = function(_React$Component) {
function Ripple() {
var _ref, _temp, _this, _ret;
(0, _classCallCheck3.default)(this, Ripple);
@@ -33838,7 +29565,7 @@ var _publicBundleJs = []byte(`!function(modules) {
} : {}, Ripple.defaultProps = {
pulsate: !1
}, exports.default = Ripple;
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
function createRippleHandler(instance, eventName, action, cb) {
@@ -33872,28 +29599,25 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = void 0;
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _helpers = __webpack_require__(69), styles = exports.styles = function(theme) {
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _helpers = __webpack_require__(52), styles = exports.styles = function(theme) {
return {
root: {
userSelect: "none"
},
- colorAccent: {
- color: theme.palette.secondary.A200
+ colorPrimary: {
+ color: theme.palette.primary.main
+ },
+ colorSecondary: {
+ color: theme.palette.secondary.main
},
colorAction: {
color: theme.palette.action.active
},
- colorContrast: {
- color: theme.palette.getContrastText(theme.palette.primary[500])
- },
colorDisabled: {
color: theme.palette.action.disabled
},
colorError: {
- color: theme.palette.error[500]
- },
- colorPrimary: {
- color: theme.palette.primary[500]
+ color: theme.palette.error.main
}
};
};
@@ -33901,13 +29625,13 @@ var _publicBundleJs = []byte(`!function(modules) {
children: _propTypes2.default.node,
classes: _propTypes2.default.object.isRequired,
className: _propTypes2.default.string,
- color: _propTypes2.default.oneOf([ "inherit", "accent", "action", "contrast", "disabled", "error", "primary" ])
+ color: _propTypes2.default.oneOf([ "inherit", "secondary", "action", "disabled", "error", "primary" ])
} : {}, Icon.defaultProps = {
color: "inherit"
}, Icon.muiName = "Icon", exports.default = (0, _withStyles2.default)(styles, {
name: "MuiIcon"
})(Icon);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -33917,21 +29641,22 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}
function SvgIcon(props) {
- var children = props.children, classes = props.classes, classNameProp = props.className, color = props.color, titleAccess = props.titleAccess, viewBox = props.viewBox, other = (0,
- _objectWithoutProperties3.default)(props, [ "children", "classes", "className", "color", "titleAccess", "viewBox" ]), className = (0,
+ var children = props.children, classes = props.classes, classNameProp = props.className, color = props.color, nativeColor = props.nativeColor, titleAccess = props.titleAccess, viewBox = props.viewBox, other = (0,
+ _objectWithoutProperties3.default)(props, [ "children", "classes", "className", "color", "nativeColor", "titleAccess", "viewBox" ]), className = (0,
_classnames2.default)(classes.root, (0, _defineProperty3.default)({}, classes["color" + (0,
_helpers.capitalizeFirstLetter)(color)], "inherit" !== color), classNameProp);
return _react2.default.createElement("svg", (0, _extends3.default)({
className: className,
focusable: "false",
viewBox: viewBox,
+ color: nativeColor,
"aria-hidden": titleAccess ? "false" : "true"
}, other), titleAccess ? _react2.default.createElement("title", null, titleAccess) : null, children);
}
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = void 0;
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _helpers = __webpack_require__(69), styles = exports.styles = function(theme) {
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _helpers = __webpack_require__(52), styles = exports.styles = function(theme) {
return {
root: {
display: "inline-block",
@@ -33944,23 +29669,20 @@ var _publicBundleJs = []byte(`!function(modules) {
duration: theme.transitions.duration.shorter
})
},
- colorAccent: {
- color: theme.palette.secondary.A200
+ colorPrimary: {
+ color: theme.palette.primary.main
+ },
+ colorSecondary: {
+ color: theme.palette.secondary.main
},
colorAction: {
color: theme.palette.action.active
},
- colorContrast: {
- color: theme.palette.getContrastText(theme.palette.primary[500])
- },
colorDisabled: {
color: theme.palette.action.disabled
},
colorError: {
- color: theme.palette.error[500]
- },
- colorPrimary: {
- color: theme.palette.primary[500]
+ color: theme.palette.error.main
}
};
};
@@ -33968,7 +29690,8 @@ var _publicBundleJs = []byte(`!function(modules) {
children: _propTypes2.default.node.isRequired,
classes: _propTypes2.default.object.isRequired,
className: _propTypes2.default.string,
- color: _propTypes2.default.oneOf([ "inherit", "accent", "action", "contrast", "disabled", "error", "primary" ]),
+ color: _propTypes2.default.oneOf([ "action", "disabled", "error", "inherit", "primary", "secondary" ]),
+ nativeColor: _propTypes2.default.string,
titleAccess: _propTypes2.default.string,
viewBox: _propTypes2.default.string
} : {}, SvgIcon.defaultProps = {
@@ -33977,7 +29700,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, SvgIcon.muiName = "SvgIcon", exports.default = (0, _withStyles2.default)(styles, {
name: "MuiSvgIcon"
})(SvgIcon);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -34001,7 +29724,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = void 0;
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _helpers = __webpack_require__(69), styles = exports.styles = function(theme) {
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _helpers = __webpack_require__(52), styles = exports.styles = function(theme) {
return {
root: {
display: "block",
@@ -34045,25 +29768,25 @@ var _publicBundleJs = []byte(`!function(modules) {
color: "inherit"
},
colorPrimary: {
- color: theme.palette.primary[500]
+ color: theme.palette.primary.main
},
colorSecondary: {
- color: theme.palette.text.secondary
+ color: theme.palette.secondary.main
},
- colorAccent: {
- color: theme.palette.secondary.A400
+ colorTextSecondary: {
+ color: theme.palette.text.secondary
},
colorError: {
- color: theme.palette.error.A400
+ color: theme.palette.error.main
}
};
};
Typography.propTypes = "production" !== process.env.NODE_ENV ? {
align: _propTypes2.default.oneOf([ "inherit", "left", "center", "right", "justify" ]),
- children: _propTypes2.default.node.isRequired,
+ children: _propTypes2.default.node,
classes: _propTypes2.default.object.isRequired,
className: _propTypes2.default.string,
- color: _propTypes2.default.oneOf([ "inherit", "primary", "secondary", "accent", "error", "default" ]),
+ color: _propTypes2.default.oneOf([ "inherit", "primary", "textSecondary", "secondary", "error", "default" ]),
component: _propTypes2.default.oneOfType([ _propTypes2.default.string, _propTypes2.default.func ]),
gutterBottom: _propTypes2.default.bool,
headlineMapping: _propTypes2.default.object,
@@ -34091,7 +29814,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, exports.default = (0, _withStyles2.default)(styles, {
name: "MuiTypography"
})(Typography);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(global) {
@@ -34103,14 +29826,14 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _pure = __webpack_require__(804), _pure2 = _interopRequireDefault(_pure), _SvgIcon = __webpack_require__(358), _SvgIcon2 = _interopRequireDefault(_SvgIcon), SvgIconCustom = global.__MUI_SvgIcon__ || _SvgIcon2.default, _ref = _react2.default.createElement("path", {
+ var _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _pure = __webpack_require__(482), _pure2 = _interopRequireDefault(_pure), _SvgIcon = __webpack_require__(239), _SvgIcon2 = _interopRequireDefault(_SvgIcon), SvgIconCustom = global.__MUI_SvgIcon__ || _SvgIcon2.default, _ref = _react2.default.createElement("path", {
d: "M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"
}), ChevronLeft = function(props) {
return _react2.default.createElement(SvgIconCustom, props, _ref);
};
ChevronLeft = (0, _pure2.default)(ChevronLeft), ChevronLeft.muiName = "SvgIcon",
exports.default = ChevronLeft;
- }).call(exports, __webpack_require__(68));
+ }).call(exports, __webpack_require__(51));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -34120,7 +29843,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}
exports.__esModule = !0;
- var _shouldUpdate = __webpack_require__(805), _shouldUpdate2 = _interopRequireDefault(_shouldUpdate), _shallowEqual = __webpack_require__(807), _shallowEqual2 = _interopRequireDefault(_shallowEqual), _setDisplayName = __webpack_require__(360), _setDisplayName2 = _interopRequireDefault(_setDisplayName), _wrapDisplayName = __webpack_require__(95), _wrapDisplayName2 = _interopRequireDefault(_wrapDisplayName), pure = function(BaseComponent) {
+ var _shouldUpdate = __webpack_require__(483), _shouldUpdate2 = _interopRequireDefault(_shouldUpdate), _shallowEqual = __webpack_require__(485), _shallowEqual2 = _interopRequireDefault(_shallowEqual), _setDisplayName = __webpack_require__(240), _setDisplayName2 = _interopRequireDefault(_setDisplayName), _wrapDisplayName = __webpack_require__(75), _wrapDisplayName2 = _interopRequireDefault(_wrapDisplayName), pure = function(BaseComponent) {
var hoc = (0, _shouldUpdate2.default)(function(props, nextProps) {
return !(0, _shallowEqual2.default)(props, nextProps);
});
@@ -34128,7 +29851,7 @@ var _publicBundleJs = []byte(`!function(modules) {
_wrapDisplayName2.default)(BaseComponent, "pure"))(hoc(BaseComponent)) : hoc(BaseComponent);
};
exports.default = pure;
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -34156,7 +29879,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
exports.__esModule = !0;
- var _react = __webpack_require__(1), _setDisplayName = __webpack_require__(360), _setDisplayName2 = _interopRequireDefault(_setDisplayName), _wrapDisplayName = __webpack_require__(95), _wrapDisplayName2 = _interopRequireDefault(_wrapDisplayName), shouldUpdate = function(test) {
+ var _react = __webpack_require__(0), _setDisplayName = __webpack_require__(240), _setDisplayName2 = _interopRequireDefault(_setDisplayName), _wrapDisplayName = __webpack_require__(75), _wrapDisplayName2 = _interopRequireDefault(_wrapDisplayName), shouldUpdate = function(test) {
return function(BaseComponent) {
var factory = (0, _react.createFactory)(BaseComponent), ShouldUpdate = function(_Component) {
function ShouldUpdate() {
@@ -34173,7 +29896,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
};
exports.default = shouldUpdate;
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = !0;
@@ -34186,7 +29909,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = !0;
- var _shallowEqual = __webpack_require__(122), _shallowEqual2 = function(obj) {
+ var _shallowEqual = __webpack_require__(96), _shallowEqual2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -34232,14 +29955,12 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _SideBar = __webpack_require__(809), _SideBar2 = _interopRequireDefault(_SideBar), _Main = __webpack_require__(828), _Main2 = _interopRequireDefault(_Main), styles = function() {
- return {
- body: {
- display: "flex",
- width: "100%",
- height: "100%"
- }
- };
+ }(), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _SideBar = __webpack_require__(487), _SideBar2 = _interopRequireDefault(_SideBar), _Main = __webpack_require__(507), _Main2 = _interopRequireDefault(_Main), styles = {
+ body: {
+ display: "flex",
+ width: "100%",
+ height: "100%"
+ }
}, Body = function(_Component) {
function Body() {
return _classCallCheck(this, Body), _possibleConstructorReturn(this, (Body.__proto__ || Object.getPrototypeOf(Body)).apply(this, arguments));
@@ -34247,9 +29968,8 @@ var _publicBundleJs = []byte(`!function(modules) {
return _inherits(Body, _Component), _createClass(Body, [ {
key: "render",
value: function() {
- var classes = this.props.classes;
return _react2.default.createElement("div", {
- className: classes.body
+ style: styles.body
}, _react2.default.createElement(_SideBar2.default, {
opened: this.props.opened,
changeContent: this.props.changeContent
@@ -34261,7 +29981,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
} ]), Body;
}(_react.Component);
- exports.default = (0, _withStyles2.default)(styles)(Body);
+ exports.default = Body;
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -34308,13 +30028,18 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _List = __webpack_require__(810), _List2 = _interopRequireDefault(_List), _Icon = __webpack_require__(356), _Icon2 = _interopRequireDefault(_Icon), _Transition = __webpack_require__(149), _Transition2 = _interopRequireDefault(_Transition), _reactFa = __webpack_require__(818), _Common = __webpack_require__(150), menuDefault = {
- transition: "margin-left " + _Common.DURATION + "ms"
- }, menuTransition = {
- entered: {
- marginLeft: -200
+ }(), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _List = __webpack_require__(488), _List2 = _interopRequireDefault(_List), _Icon = __webpack_require__(237), _Icon2 = _interopRequireDefault(_Icon), _Transition = __webpack_require__(108), _Transition2 = _interopRequireDefault(_Transition), _reactFa = __webpack_require__(496), _common = __webpack_require__(61), styles = {
+ menu: {
+ default: {
+ transition: "margin-left " + _common.DURATION + "ms"
+ },
+ transition: {
+ entered: {
+ marginLeft: -200
+ }
+ }
}
- }, styles = function(theme) {
+ }, themeStyles = function(theme) {
return {
list: {
background: theme.palette.background.appBar
@@ -34327,16 +30052,22 @@ var _publicBundleJs = []byte(`!function(modules) {
}
};
}, SideBar = function(_Component) {
- function SideBar(props) {
+ function SideBar() {
+ var _ref, _temp, _this, _ret;
_classCallCheck(this, SideBar);
- var _this = _possibleConstructorReturn(this, (SideBar.__proto__ || Object.getPrototypeOf(SideBar)).call(this, props));
- return _this.menuItems = function(transitionState) {
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) args[_key] = arguments[_key];
+ return _temp = _this = _possibleConstructorReturn(this, (_ref = SideBar.__proto__ || Object.getPrototypeOf(SideBar)).call.apply(_ref, [ this ].concat(args))),
+ _this.clickOn = function(menu) {
+ return function(event) {
+ event.preventDefault(), _this.props.changeContent(menu);
+ };
+ }, _this.menuItems = function(transitionState) {
var classes = _this.props.classes, children = [];
- return _Common.MENU.forEach(function(menu) {
+ return _common.MENU.forEach(function(menu) {
children.push(_react2.default.createElement(_List.ListItem, {
button: !0,
key: menu.id,
- onClick: _this.clickOn[menu.id],
+ onClick: _this.clickOn(menu.id),
className: classes.listItem
}, _react2.default.createElement(_List.ListItemIcon, null, _react2.default.createElement(_Icon2.default, {
className: classes.icon
@@ -34344,21 +30075,16 @@ var _publicBundleJs = []byte(`!function(modules) {
name: menu.icon
}))), _react2.default.createElement(_List.ListItemText, {
primary: menu.title,
- style: _extends({}, menuDefault, menuTransition[transitionState], {
+ style: _extends({}, styles.menu.default, styles.menu.transition[transitionState], {
padding: 0
})
})));
}), children;
}, _this.menu = function(transitionState) {
- var classes = _this.props.classes;
return _react2.default.createElement("div", {
- className: classes.list
+ className: _this.props.classes.list
}, _react2.default.createElement(_List2.default, null, _this.menuItems(transitionState)));
- }, _this.clickOn = {}, _Common.MENU.forEach(function(menu) {
- _this.clickOn[menu.id] = function(event) {
- event.preventDefault(), props.changeContent(menu.id);
- };
- }), _this;
+ }, _ret = _temp, _possibleConstructorReturn(_this, _ret);
}
return _inherits(SideBar, _Component), _createClass(SideBar, [ {
key: "shouldComponentUpdate",
@@ -34372,13 +30098,13 @@ var _publicBundleJs = []byte(`!function(modules) {
mountOnEnter: !0,
in: this.props.opened,
timeout: {
- enter: _Common.DURATION
+ enter: _common.DURATION
}
}, this.menu);
}
} ]), SideBar;
}(_react.Component);
- exports.default = (0, _withStyles2.default)(styles)(SideBar);
+ exports.default = (0, _withStyles2.default)(themeStyles)(SideBar);
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -34389,49 +30115,49 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _List = __webpack_require__(811);
+ var _List = __webpack_require__(489);
Object.defineProperty(exports, "default", {
enumerable: !0,
get: function() {
return _interopRequireDefault(_List).default;
}
});
- var _ListItem = __webpack_require__(812);
+ var _ListItem = __webpack_require__(490);
Object.defineProperty(exports, "ListItem", {
enumerable: !0,
get: function() {
return _interopRequireDefault(_ListItem).default;
}
});
- var _ListItemAvatar = __webpack_require__(813);
+ var _ListItemAvatar = __webpack_require__(491);
Object.defineProperty(exports, "ListItemAvatar", {
enumerable: !0,
get: function() {
return _interopRequireDefault(_ListItemAvatar).default;
}
});
- var _ListItemText = __webpack_require__(814);
+ var _ListItemText = __webpack_require__(492);
Object.defineProperty(exports, "ListItemText", {
enumerable: !0,
get: function() {
return _interopRequireDefault(_ListItemText).default;
}
});
- var _ListItemIcon = __webpack_require__(815);
+ var _ListItemIcon = __webpack_require__(493);
Object.defineProperty(exports, "ListItemIcon", {
enumerable: !0,
get: function() {
return _interopRequireDefault(_ListItemIcon).default;
}
});
- var _ListItemSecondaryAction = __webpack_require__(816);
+ var _ListItemSecondaryAction = __webpack_require__(494);
Object.defineProperty(exports, "ListItemSecondaryAction", {
enumerable: !0,
get: function() {
return _interopRequireDefault(_ListItemSecondaryAction).default;
}
});
- var _ListSubheader = __webpack_require__(817);
+ var _ListSubheader = __webpack_require__(495);
Object.defineProperty(exports, "ListSubheader", {
enumerable: !0,
get: function() {
@@ -34449,7 +30175,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = void 0;
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _getPrototypeOf = __webpack_require__(38), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(39), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(40), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(41), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(42), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), styles = exports.styles = function(theme) {
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _getPrototypeOf = __webpack_require__(26), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(27), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(28), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(29), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(30), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), styles = exports.styles = function(theme) {
return {
root: {
flex: "1 1 auto",
@@ -34485,16 +30211,14 @@ var _publicBundleJs = []byte(`!function(modules) {
}, {
key: "render",
value: function() {
- var _classNames, _props = this.props, classes = _props.classes, classNameProp = _props.className, ComponentProp = _props.component, disablePadding = _props.disablePadding, children = _props.children, dense = _props.dense, subheader = _props.subheader, rootRef = _props.rootRef, other = (0,
- _objectWithoutProperties3.default)(_props, [ "classes", "className", "component", "disablePadding", "children", "dense", "subheader", "rootRef" ]), className = (0,
+ var _classNames, _props = this.props, children = _props.children, classes = _props.classes, classNameProp = _props.className, Component = _props.component, dense = _props.dense, disablePadding = _props.disablePadding, subheader = _props.subheader, other = (0,
+ _objectWithoutProperties3.default)(_props, [ "children", "classes", "className", "component", "dense", "disablePadding", "subheader" ]), className = (0,
_classnames2.default)(classes.root, (_classNames = {}, (0, _defineProperty3.default)(_classNames, classes.dense, dense && !disablePadding),
(0, _defineProperty3.default)(_classNames, classes.padding, !disablePadding), (0,
_defineProperty3.default)(_classNames, classes.subheader, subheader), _classNames), classNameProp);
- return _react2.default.createElement(ComponentProp, (0, _extends3.default)({
+ return _react2.default.createElement(Component, (0, _extends3.default)({
className: className
- }, other, {
- ref: rootRef
- }), subheader, children);
+ }, other), subheader, children);
}
} ]), List;
}(_react2.default.Component);
@@ -34505,7 +30229,6 @@ var _publicBundleJs = []byte(`!function(modules) {
component: _propTypes2.default.oneOfType([ _propTypes2.default.string, _propTypes2.default.func ]),
dense: _propTypes2.default.bool,
disablePadding: _propTypes2.default.bool,
- rootRef: _propTypes2.default.func,
subheader: _propTypes2.default.node
} : {}, List.defaultProps = {
component: "ul",
@@ -34516,7 +30239,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, exports.default = (0, _withStyles2.default)(styles, {
name: "MuiList"
})(List);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -34528,7 +30251,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = void 0;
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _getPrototypeOf = __webpack_require__(38), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(39), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(40), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(41), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(42), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _ButtonBase = __webpack_require__(353), _ButtonBase2 = _interopRequireDefault(_ButtonBase), _reactHelpers = __webpack_require__(357), styles = exports.styles = function(theme) {
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _getPrototypeOf = __webpack_require__(26), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(27), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(28), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(29), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(30), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _ButtonBase = __webpack_require__(234), _ButtonBase2 = _interopRequireDefault(_ButtonBase), _reactHelpers = __webpack_require__(238), styles = exports.styles = function(theme) {
return {
root: {
display: "flex",
@@ -34541,7 +30264,7 @@ var _publicBundleJs = []byte(`!function(modules) {
position: "relative"
},
keyboardFocused: {
- background: theme.palette.text.divider
+ backgroundColor: theme.palette.action.hover
},
default: {
paddingTop: 12,
@@ -34555,7 +30278,7 @@ var _publicBundleJs = []byte(`!function(modules) {
opacity: .5
},
divider: {
- borderBottom: "1px solid " + theme.palette.text.lightDivider
+ borderBottom: "1px solid " + theme.palette.divider
},
gutters: {
paddingLeft: 2 * theme.spacing.unit,
@@ -34567,7 +30290,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}),
"&:hover": {
textDecoration: "none",
- backgroundColor: theme.palette.text.divider,
+ backgroundColor: theme.palette.action.hover,
"@media (hover: none)": {
backgroundColor: "transparent"
},
@@ -34638,7 +30361,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, exports.default = (0, _withStyles2.default)(styles, {
name: "MuiListItem"
})(ListItem);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -34660,7 +30383,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = void 0;
- var _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), styles = exports.styles = function(theme) {
+ var _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), styles = exports.styles = function(theme) {
return {
root: {
width: 36,
@@ -34684,7 +30407,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, ListItemAvatar.muiName = "ListItemAvatar", exports.default = (0, _withStyles2.default)(styles, {
name: "MuiListItemAvatar"
})(ListItemAvatar);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -34702,20 +30425,21 @@ var _publicBundleJs = []byte(`!function(modules) {
className: className
}, other), primary && (disableTypography ? primary : _react2.default.createElement(_Typography2.default, {
type: "subheading",
- className: (0, _classnames2.default)(classes.text, (0, _defineProperty3.default)({}, classes.textDense, dense))
+ className: (0, _classnames2.default)(classes.primary, (0, _defineProperty3.default)({}, classes.textDense, dense))
}, primary)), secondary && (disableTypography ? secondary : _react2.default.createElement(_Typography2.default, {
- color: "secondary",
type: "body1",
- className: (0, _classnames2.default)(classes.text, (0, _defineProperty3.default)({}, classes.textDense, dense))
+ className: (0, _classnames2.default)(classes.secondary, (0, _defineProperty3.default)({}, classes.textDense, dense)),
+ color: "textSecondary"
}, secondary)));
}
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = void 0;
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _Typography = __webpack_require__(359), _Typography2 = _interopRequireDefault(_Typography), styles = exports.styles = function(theme) {
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _Typography = __webpack_require__(109), _Typography2 = _interopRequireDefault(_Typography), styles = exports.styles = function(theme) {
return {
root: {
flex: "1 1 auto",
+ minWidth: 0,
padding: "0 16px",
"&:first-child": {
paddingLeft: 0
@@ -34729,10 +30453,17 @@ var _publicBundleJs = []byte(`!function(modules) {
dense: {
fontSize: theme.typography.pxToRem(13)
},
- text: {},
- textDense: {
- fontSize: "inherit"
- }
+ primary: {
+ "&$textDense": {
+ fontSize: "inherit"
+ }
+ },
+ secondary: {
+ "&$textDense": {
+ fontSize: "inherit"
+ }
+ },
+ textDense: {}
};
};
ListItemText.propTypes = "production" !== process.env.NODE_ENV ? {
@@ -34752,7 +30483,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, exports.default = (0, _withStyles2.default)(styles, {
name: "MuiListItemText"
})(ListItemText);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -34771,7 +30502,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = void 0;
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), styles = exports.styles = function(theme) {
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), styles = exports.styles = function(theme) {
return {
root: {
height: 24,
@@ -34789,7 +30520,7 @@ var _publicBundleJs = []byte(`!function(modules) {
} : {}, exports.default = (0, _withStyles2.default)(styles, {
name: "MuiListItemIcon"
})(ListItemIcon);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -34808,7 +30539,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = void 0;
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), styles = exports.styles = function(theme) {
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), styles = exports.styles = function(theme) {
return {
root: {
position: "absolute",
@@ -34826,7 +30557,7 @@ var _publicBundleJs = []byte(`!function(modules) {
_withStyles2.default)(styles, {
name: "MuiListItemSecondaryAction"
})(ListItemSecondaryAction);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
(function(process) {
@@ -34836,19 +30567,19 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}
function ListSubheader(props) {
- var _classNames, children = props.children, classes = props.classes, classNameProp = props.className, color = props.color, ComponentProp = props.component, disableSticky = props.disableSticky, inset = props.inset, other = (0,
- _objectWithoutProperties3.default)(props, [ "children", "classes", "className", "color", "component", "disableSticky", "inset" ]), className = (0,
+ var _classNames, classes = props.classes, classNameProp = props.className, color = props.color, Component = props.component, disableSticky = props.disableSticky, inset = props.inset, other = (0,
+ _objectWithoutProperties3.default)(props, [ "classes", "className", "color", "component", "disableSticky", "inset" ]), className = (0,
_classnames2.default)(classes.root, (_classNames = {}, (0, _defineProperty3.default)(_classNames, classes["color" + (0,
_helpers.capitalizeFirstLetter)(color)], "default" !== color), (0, _defineProperty3.default)(_classNames, classes.inset, inset),
(0, _defineProperty3.default)(_classNames, classes.sticky, !disableSticky), _classNames), classNameProp);
- return _react2.default.createElement(ComponentProp, (0, _extends3.default)({
+ return _react2.default.createElement(Component, (0, _extends3.default)({
className: className
- }, other), children);
+ }, other));
}
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.styles = void 0;
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _helpers = __webpack_require__(69), styles = exports.styles = function(theme) {
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _helpers = __webpack_require__(52), styles = exports.styles = function(theme) {
return {
root: {
boxSizing: "border-box",
@@ -34862,7 +30593,7 @@ var _publicBundleJs = []byte(`!function(modules) {
fontSize: theme.typography.pxToRem(theme.typography.fontSize)
},
colorPrimary: {
- color: theme.palette.primary[500]
+ color: theme.palette.primary.main
},
colorInherit: {
color: "inherit"
@@ -34894,7 +30625,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, ListSubheader.muiName = "ListSubheader", exports.default = (0, _withStyles2.default)(styles, {
name: "MuiListSubheader"
})(ListSubheader);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -34904,20 +30635,26 @@ var _publicBundleJs = []byte(`!function(modules) {
}
Object.defineProperty(exports, "__esModule", {
value: !0
- }), exports.IconStack = exports.Icon = exports.default = void 0, __webpack_require__(819);
- var _Icon = __webpack_require__(826), _Icon2 = _interopRequireDefault(_Icon), _IconStack = __webpack_require__(827), _IconStack2 = _interopRequireDefault(_IconStack);
+ }), exports.IconStack = exports.Icon = exports.default = void 0, __webpack_require__(497);
+ var _Icon = __webpack_require__(505), _Icon2 = _interopRequireDefault(_Icon), _IconStack = __webpack_require__(506), _IconStack2 = _interopRequireDefault(_IconStack);
exports.default = _Icon2.default, exports.Icon = _Icon2.default, exports.IconStack = _IconStack2.default;
}, function(module, exports, __webpack_require__) {
- var content = __webpack_require__(820);
+ var content = __webpack_require__(498);
"string" == typeof content && (content = [ [ module.i, content, "" ] ]);
var options = {
hmr: !0
};
options.transform = void 0;
- __webpack_require__(824)(content, options);
+ __webpack_require__(503)(content, options);
content.locals && (module.exports = content.locals);
}, function(module, exports, __webpack_require__) {
- exports = module.exports = __webpack_require__(821)(void 0), exports.push([ module.i, "/*!\n * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome\n * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)\n */\n/* FONT PATH\n * -------------------------- */\n@font-face {\n font-family: 'FontAwesome';\n \n src: url(" + __webpack_require__(822) + ") format('woff2'), url(" + __webpack_require__(823) + ') format(\'woff\');\n font-weight: normal;\n font-style: normal;\n}\n.fa {\n display: inline-block;\n font: normal normal normal 14px/1 FontAwesome;\n font-size: inherit;\n text-rendering: auto;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n/* makes the font 33% larger relative to the icon container */\n.fa-lg {\n font-size: 1.33333333em;\n line-height: 0.75em;\n vertical-align: -15%;\n}\n.fa-2x {\n font-size: 2em;\n}\n.fa-3x {\n font-size: 3em;\n}\n.fa-4x {\n font-size: 4em;\n}\n.fa-5x {\n font-size: 5em;\n}\n.fa-fw {\n width: 1.28571429em;\n text-align: center;\n}\n.fa-ul {\n padding-left: 0;\n margin-left: 2.14285714em;\n list-style-type: none;\n}\n.fa-ul > li {\n position: relative;\n}\n.fa-li {\n position: absolute;\n left: -2.14285714em;\n width: 2.14285714em;\n top: 0.14285714em;\n text-align: center;\n}\n.fa-li.fa-lg {\n left: -1.85714286em;\n}\n.fa-border {\n padding: .2em .25em .15em;\n border: solid 0.08em #eeeeee;\n border-radius: .1em;\n}\n.fa-pull-left {\n float: left;\n}\n.fa-pull-right {\n float: right;\n}\n.fa.fa-pull-left {\n margin-right: .3em;\n}\n.fa.fa-pull-right {\n margin-left: .3em;\n}\n/* Deprecated as of 4.4.0 */\n.pull-right {\n float: right;\n}\n.pull-left {\n float: left;\n}\n.fa.pull-left {\n margin-right: .3em;\n}\n.fa.pull-right {\n margin-left: .3em;\n}\n.fa-spin {\n -webkit-animation: fa-spin 2s infinite linear;\n animation: fa-spin 2s infinite linear;\n}\n.fa-pulse {\n -webkit-animation: fa-spin 1s infinite steps(8);\n animation: fa-spin 1s infinite steps(8);\n}\n@-webkit-keyframes fa-spin {\n 0% {\n -webkit-transform: rotate(0deg);\n transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(359deg);\n transform: rotate(359deg);\n }\n}\n@keyframes fa-spin {\n 0% {\n -webkit-transform: rotate(0deg);\n transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(359deg);\n transform: rotate(359deg);\n }\n}\n.fa-rotate-90 {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";\n -webkit-transform: rotate(90deg);\n -ms-transform: rotate(90deg);\n transform: rotate(90deg);\n}\n.fa-rotate-180 {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";\n -webkit-transform: rotate(180deg);\n -ms-transform: rotate(180deg);\n transform: rotate(180deg);\n}\n.fa-rotate-270 {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";\n -webkit-transform: rotate(270deg);\n -ms-transform: rotate(270deg);\n transform: rotate(270deg);\n}\n.fa-flip-horizontal {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";\n -webkit-transform: scale(-1, 1);\n -ms-transform: scale(-1, 1);\n transform: scale(-1, 1);\n}\n.fa-flip-vertical {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";\n -webkit-transform: scale(1, -1);\n -ms-transform: scale(1, -1);\n transform: scale(1, -1);\n}\n:root .fa-rotate-90,\n:root .fa-rotate-180,\n:root .fa-rotate-270,\n:root .fa-flip-horizontal,\n:root .fa-flip-vertical {\n filter: none;\n}\n.fa-stack {\n position: relative;\n display: inline-block;\n width: 2em;\n height: 2em;\n line-height: 2em;\n vertical-align: middle;\n}\n.fa-stack-1x,\n.fa-stack-2x {\n position: absolute;\n left: 0;\n width: 100%;\n text-align: center;\n}\n.fa-stack-1x {\n line-height: inherit;\n}\n.fa-stack-2x {\n font-size: 2em;\n}\n.fa-inverse {\n color: #ffffff;\n}\n/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen\n readers do not read off random characters that represent icons */\n.fa-glass:before {\n content: "\\F000";\n}\n.fa-music:before {\n content: "\\F001";\n}\n.fa-search:before {\n content: "\\F002";\n}\n.fa-envelope-o:before {\n content: "\\F003";\n}\n.fa-heart:before {\n content: "\\F004";\n}\n.fa-star:before {\n content: "\\F005";\n}\n.fa-star-o:before {\n content: "\\F006";\n}\n.fa-user:before {\n content: "\\F007";\n}\n.fa-film:before {\n content: "\\F008";\n}\n.fa-th-large:before {\n content: "\\F009";\n}\n.fa-th:before {\n content: "\\F00A";\n}\n.fa-th-list:before {\n content: "\\F00B";\n}\n.fa-check:before {\n content: "\\F00C";\n}\n.fa-remove:before,\n.fa-close:before,\n.fa-times:before {\n content: "\\F00D";\n}\n.fa-search-plus:before {\n content: "\\F00E";\n}\n.fa-search-minus:before {\n content: "\\F010";\n}\n.fa-power-off:before {\n content: "\\F011";\n}\n.fa-signal:before {\n content: "\\F012";\n}\n.fa-gear:before,\n.fa-cog:before {\n content: "\\F013";\n}\n.fa-trash-o:before {\n content: "\\F014";\n}\n.fa-home:before {\n content: "\\F015";\n}\n.fa-file-o:before {\n content: "\\F016";\n}\n.fa-clock-o:before {\n content: "\\F017";\n}\n.fa-road:before {\n content: "\\F018";\n}\n.fa-download:before {\n content: "\\F019";\n}\n.fa-arrow-circle-o-down:before {\n content: "\\F01A";\n}\n.fa-arrow-circle-o-up:before {\n content: "\\F01B";\n}\n.fa-inbox:before {\n content: "\\F01C";\n}\n.fa-play-circle-o:before {\n content: "\\F01D";\n}\n.fa-rotate-right:before,\n.fa-repeat:before {\n content: "\\F01E";\n}\n.fa-refresh:before {\n content: "\\F021";\n}\n.fa-list-alt:before {\n content: "\\F022";\n}\n.fa-lock:before {\n content: "\\F023";\n}\n.fa-flag:before {\n content: "\\F024";\n}\n.fa-headphones:before {\n content: "\\F025";\n}\n.fa-volume-off:before {\n content: "\\F026";\n}\n.fa-volume-down:before {\n content: "\\F027";\n}\n.fa-volume-up:before {\n content: "\\F028";\n}\n.fa-qrcode:before {\n content: "\\F029";\n}\n.fa-barcode:before {\n content: "\\F02A";\n}\n.fa-tag:before {\n content: "\\F02B";\n}\n.fa-tags:before {\n content: "\\F02C";\n}\n.fa-book:before {\n content: "\\F02D";\n}\n.fa-bookmark:before {\n content: "\\F02E";\n}\n.fa-print:before {\n content: "\\F02F";\n}\n.fa-camera:before {\n content: "\\F030";\n}\n.fa-font:before {\n content: "\\F031";\n}\n.fa-bold:before {\n content: "\\F032";\n}\n.fa-italic:before {\n content: "\\F033";\n}\n.fa-text-height:before {\n content: "\\F034";\n}\n.fa-text-width:before {\n content: "\\F035";\n}\n.fa-align-left:before {\n content: "\\F036";\n}\n.fa-align-center:before {\n content: "\\F037";\n}\n.fa-align-right:before {\n content: "\\F038";\n}\n.fa-align-justify:before {\n content: "\\F039";\n}\n.fa-list:before {\n content: "\\F03A";\n}\n.fa-dedent:before,\n.fa-outdent:before {\n content: "\\F03B";\n}\n.fa-indent:before {\n content: "\\F03C";\n}\n.fa-video-camera:before {\n content: "\\F03D";\n}\n.fa-photo:before,\n.fa-image:before,\n.fa-picture-o:before {\n content: "\\F03E";\n}\n.fa-pencil:before {\n content: "\\F040";\n}\n.fa-map-marker:before {\n content: "\\F041";\n}\n.fa-adjust:before {\n content: "\\F042";\n}\n.fa-tint:before {\n content: "\\F043";\n}\n.fa-edit:before,\n.fa-pencil-square-o:before {\n content: "\\F044";\n}\n.fa-share-square-o:before {\n content: "\\F045";\n}\n.fa-check-square-o:before {\n content: "\\F046";\n}\n.fa-arrows:before {\n content: "\\F047";\n}\n.fa-step-backward:before {\n content: "\\F048";\n}\n.fa-fast-backward:before {\n content: "\\F049";\n}\n.fa-backward:before {\n content: "\\F04A";\n}\n.fa-play:before {\n content: "\\F04B";\n}\n.fa-pause:before {\n content: "\\F04C";\n}\n.fa-stop:before {\n content: "\\F04D";\n}\n.fa-forward:before {\n content: "\\F04E";\n}\n.fa-fast-forward:before {\n content: "\\F050";\n}\n.fa-step-forward:before {\n content: "\\F051";\n}\n.fa-eject:before {\n content: "\\F052";\n}\n.fa-chevron-left:before {\n content: "\\F053";\n}\n.fa-chevron-right:before {\n content: "\\F054";\n}\n.fa-plus-circle:before {\n content: "\\F055";\n}\n.fa-minus-circle:before {\n content: "\\F056";\n}\n.fa-times-circle:before {\n content: "\\F057";\n}\n.fa-check-circle:before {\n content: "\\F058";\n}\n.fa-question-circle:before {\n content: "\\F059";\n}\n.fa-info-circle:before {\n content: "\\F05A";\n}\n.fa-crosshairs:before {\n content: "\\F05B";\n}\n.fa-times-circle-o:before {\n content: "\\F05C";\n}\n.fa-check-circle-o:before {\n content: "\\F05D";\n}\n.fa-ban:before {\n content: "\\F05E";\n}\n.fa-arrow-left:before {\n content: "\\F060";\n}\n.fa-arrow-right:before {\n content: "\\F061";\n}\n.fa-arrow-up:before {\n content: "\\F062";\n}\n.fa-arrow-down:before {\n content: "\\F063";\n}\n.fa-mail-forward:before,\n.fa-share:before {\n content: "\\F064";\n}\n.fa-expand:before {\n content: "\\F065";\n}\n.fa-compress:before {\n content: "\\F066";\n}\n.fa-plus:before {\n content: "\\F067";\n}\n.fa-minus:before {\n content: "\\F068";\n}\n.fa-asterisk:before {\n content: "\\F069";\n}\n.fa-exclamation-circle:before {\n content: "\\F06A";\n}\n.fa-gift:before {\n content: "\\F06B";\n}\n.fa-leaf:before {\n content: "\\F06C";\n}\n.fa-fire:before {\n content: "\\F06D";\n}\n.fa-eye:before {\n content: "\\F06E";\n}\n.fa-eye-slash:before {\n content: "\\F070";\n}\n.fa-warning:before,\n.fa-exclamation-triangle:before {\n content: "\\F071";\n}\n.fa-plane:before {\n content: "\\F072";\n}\n.fa-calendar:before {\n content: "\\F073";\n}\n.fa-random:before {\n content: "\\F074";\n}\n.fa-comment:before {\n content: "\\F075";\n}\n.fa-magnet:before {\n content: "\\F076";\n}\n.fa-chevron-up:before {\n content: "\\F077";\n}\n.fa-chevron-down:before {\n content: "\\F078";\n}\n.fa-retweet:before {\n content: "\\F079";\n}\n.fa-shopping-cart:before {\n content: "\\F07A";\n}\n.fa-folder:before {\n content: "\\F07B";\n}\n.fa-folder-open:before {\n content: "\\F07C";\n}\n.fa-arrows-v:before {\n content: "\\F07D";\n}\n.fa-arrows-h:before {\n content: "\\F07E";\n}\n.fa-bar-chart-o:before,\n.fa-bar-chart:before {\n content: "\\F080";\n}\n.fa-twitter-square:before {\n content: "\\F081";\n}\n.fa-facebook-square:before {\n content: "\\F082";\n}\n.fa-camera-retro:before {\n content: "\\F083";\n}\n.fa-key:before {\n content: "\\F084";\n}\n.fa-gears:before,\n.fa-cogs:before {\n content: "\\F085";\n}\n.fa-comments:before {\n content: "\\F086";\n}\n.fa-thumbs-o-up:before {\n content: "\\F087";\n}\n.fa-thumbs-o-down:before {\n content: "\\F088";\n}\n.fa-star-half:before {\n content: "\\F089";\n}\n.fa-heart-o:before {\n content: "\\F08A";\n}\n.fa-sign-out:before {\n content: "\\F08B";\n}\n.fa-linkedin-square:before {\n content: "\\F08C";\n}\n.fa-thumb-tack:before {\n content: "\\F08D";\n}\n.fa-external-link:before {\n content: "\\F08E";\n}\n.fa-sign-in:before {\n content: "\\F090";\n}\n.fa-trophy:before {\n content: "\\F091";\n}\n.fa-github-square:before {\n content: "\\F092";\n}\n.fa-upload:before {\n content: "\\F093";\n}\n.fa-lemon-o:before {\n content: "\\F094";\n}\n.fa-phone:before {\n content: "\\F095";\n}\n.fa-square-o:before {\n content: "\\F096";\n}\n.fa-bookmark-o:before {\n content: "\\F097";\n}\n.fa-phone-square:before {\n content: "\\F098";\n}\n.fa-twitter:before {\n content: "\\F099";\n}\n.fa-facebook-f:before,\n.fa-facebook:before {\n content: "\\F09A";\n}\n.fa-github:before {\n content: "\\F09B";\n}\n.fa-unlock:before {\n content: "\\F09C";\n}\n.fa-credit-card:before {\n content: "\\F09D";\n}\n.fa-feed:before,\n.fa-rss:before {\n content: "\\F09E";\n}\n.fa-hdd-o:before {\n content: "\\F0A0";\n}\n.fa-bullhorn:before {\n content: "\\F0A1";\n}\n.fa-bell:before {\n content: "\\F0F3";\n}\n.fa-certificate:before {\n content: "\\F0A3";\n}\n.fa-hand-o-right:before {\n content: "\\F0A4";\n}\n.fa-hand-o-left:before {\n content: "\\F0A5";\n}\n.fa-hand-o-up:before {\n content: "\\F0A6";\n}\n.fa-hand-o-down:before {\n content: "\\F0A7";\n}\n.fa-arrow-circle-left:before {\n content: "\\F0A8";\n}\n.fa-arrow-circle-right:before {\n content: "\\F0A9";\n}\n.fa-arrow-circle-up:before {\n content: "\\F0AA";\n}\n.fa-arrow-circle-down:before {\n content: "\\F0AB";\n}\n.fa-globe:before {\n content: "\\F0AC";\n}\n.fa-wrench:before {\n content: "\\F0AD";\n}\n.fa-tasks:before {\n content: "\\F0AE";\n}\n.fa-filter:before {\n content: "\\F0B0";\n}\n.fa-briefcase:before {\n content: "\\F0B1";\n}\n.fa-arrows-alt:before {\n content: "\\F0B2";\n}\n.fa-group:before,\n.fa-users:before {\n content: "\\F0C0";\n}\n.fa-chain:before,\n.fa-link:before {\n content: "\\F0C1";\n}\n.fa-cloud:before {\n content: "\\F0C2";\n}\n.fa-flask:before {\n content: "\\F0C3";\n}\n.fa-cut:before,\n.fa-scissors:before {\n content: "\\F0C4";\n}\n.fa-copy:before,\n.fa-files-o:before {\n content: "\\F0C5";\n}\n.fa-paperclip:before {\n content: "\\F0C6";\n}\n.fa-save:before,\n.fa-floppy-o:before {\n content: "\\F0C7";\n}\n.fa-square:before {\n content: "\\F0C8";\n}\n.fa-navicon:before,\n.fa-reorder:before,\n.fa-bars:before {\n content: "\\F0C9";\n}\n.fa-list-ul:before {\n content: "\\F0CA";\n}\n.fa-list-ol:before {\n content: "\\F0CB";\n}\n.fa-strikethrough:before {\n content: "\\F0CC";\n}\n.fa-underline:before {\n content: "\\F0CD";\n}\n.fa-table:before {\n content: "\\F0CE";\n}\n.fa-magic:before {\n content: "\\F0D0";\n}\n.fa-truck:before {\n content: "\\F0D1";\n}\n.fa-pinterest:before {\n content: "\\F0D2";\n}\n.fa-pinterest-square:before {\n content: "\\F0D3";\n}\n.fa-google-plus-square:before {\n content: "\\F0D4";\n}\n.fa-google-plus:before {\n content: "\\F0D5";\n}\n.fa-money:before {\n content: "\\F0D6";\n}\n.fa-caret-down:before {\n content: "\\F0D7";\n}\n.fa-caret-up:before {\n content: "\\F0D8";\n}\n.fa-caret-left:before {\n content: "\\F0D9";\n}\n.fa-caret-right:before {\n content: "\\F0DA";\n}\n.fa-columns:before {\n content: "\\F0DB";\n}\n.fa-unsorted:before,\n.fa-sort:before {\n content: "\\F0DC";\n}\n.fa-sort-down:before,\n.fa-sort-desc:before {\n content: "\\F0DD";\n}\n.fa-sort-up:before,\n.fa-sort-asc:before {\n content: "\\F0DE";\n}\n.fa-envelope:before {\n content: "\\F0E0";\n}\n.fa-linkedin:before {\n content: "\\F0E1";\n}\n.fa-rotate-left:before,\n.fa-undo:before {\n content: "\\F0E2";\n}\n.fa-legal:before,\n.fa-gavel:before {\n content: "\\F0E3";\n}\n.fa-dashboard:before,\n.fa-tachometer:before {\n content: "\\F0E4";\n}\n.fa-comment-o:before {\n content: "\\F0E5";\n}\n.fa-comments-o:before {\n content: "\\F0E6";\n}\n.fa-flash:before,\n.fa-bolt:before {\n content: "\\F0E7";\n}\n.fa-sitemap:before {\n content: "\\F0E8";\n}\n.fa-umbrella:before {\n content: "\\F0E9";\n}\n.fa-paste:before,\n.fa-clipboard:before {\n content: "\\F0EA";\n}\n.fa-lightbulb-o:before {\n content: "\\F0EB";\n}\n.fa-exchange:before {\n content: "\\F0EC";\n}\n.fa-cloud-download:before {\n content: "\\F0ED";\n}\n.fa-cloud-upload:before {\n content: "\\F0EE";\n}\n.fa-user-md:before {\n content: "\\F0F0";\n}\n.fa-stethoscope:before {\n content: "\\F0F1";\n}\n.fa-suitcase:before {\n content: "\\F0F2";\n}\n.fa-bell-o:before {\n content: "\\F0A2";\n}\n.fa-coffee:before {\n content: "\\F0F4";\n}\n.fa-cutlery:before {\n content: "\\F0F5";\n}\n.fa-file-text-o:before {\n content: "\\F0F6";\n}\n.fa-building-o:before {\n content: "\\F0F7";\n}\n.fa-hospital-o:before {\n content: "\\F0F8";\n}\n.fa-ambulance:before {\n content: "\\F0F9";\n}\n.fa-medkit:before {\n content: "\\F0FA";\n}\n.fa-fighter-jet:before {\n content: "\\F0FB";\n}\n.fa-beer:before {\n content: "\\F0FC";\n}\n.fa-h-square:before {\n content: "\\F0FD";\n}\n.fa-plus-square:before {\n content: "\\F0FE";\n}\n.fa-angle-double-left:before {\n content: "\\F100";\n}\n.fa-angle-double-right:before {\n content: "\\F101";\n}\n.fa-angle-double-up:before {\n content: "\\F102";\n}\n.fa-angle-double-down:before {\n content: "\\F103";\n}\n.fa-angle-left:before {\n content: "\\F104";\n}\n.fa-angle-right:before {\n content: "\\F105";\n}\n.fa-angle-up:before {\n content: "\\F106";\n}\n.fa-angle-down:before {\n content: "\\F107";\n}\n.fa-desktop:before {\n content: "\\F108";\n}\n.fa-laptop:before {\n content: "\\F109";\n}\n.fa-tablet:before {\n content: "\\F10A";\n}\n.fa-mobile-phone:before,\n.fa-mobile:before {\n content: "\\F10B";\n}\n.fa-circle-o:before {\n content: "\\F10C";\n}\n.fa-quote-left:before {\n content: "\\F10D";\n}\n.fa-quote-right:before {\n content: "\\F10E";\n}\n.fa-spinner:before {\n content: "\\F110";\n}\n.fa-circle:before {\n content: "\\F111";\n}\n.fa-mail-reply:before,\n.fa-reply:before {\n content: "\\F112";\n}\n.fa-github-alt:before {\n content: "\\F113";\n}\n.fa-folder-o:before {\n content: "\\F114";\n}\n.fa-folder-open-o:before {\n content: "\\F115";\n}\n.fa-smile-o:before {\n content: "\\F118";\n}\n.fa-frown-o:before {\n content: "\\F119";\n}\n.fa-meh-o:before {\n content: "\\F11A";\n}\n.fa-gamepad:before {\n content: "\\F11B";\n}\n.fa-keyboard-o:before {\n content: "\\F11C";\n}\n.fa-flag-o:before {\n content: "\\F11D";\n}\n.fa-flag-checkered:before {\n content: "\\F11E";\n}\n.fa-terminal:before {\n content: "\\F120";\n}\n.fa-code:before {\n content: "\\F121";\n}\n.fa-mail-reply-all:before,\n.fa-reply-all:before {\n content: "\\F122";\n}\n.fa-star-half-empty:before,\n.fa-star-half-full:before,\n.fa-star-half-o:before {\n content: "\\F123";\n}\n.fa-location-arrow:before {\n content: "\\F124";\n}\n.fa-crop:before {\n content: "\\F125";\n}\n.fa-code-fork:before {\n content: "\\F126";\n}\n.fa-unlink:before,\n.fa-chain-broken:before {\n content: "\\F127";\n}\n.fa-question:before {\n content: "\\F128";\n}\n.fa-info:before {\n content: "\\F129";\n}\n.fa-exclamation:before {\n content: "\\F12A";\n}\n.fa-superscript:before {\n content: "\\F12B";\n}\n.fa-subscript:before {\n content: "\\F12C";\n}\n.fa-eraser:before {\n content: "\\F12D";\n}\n.fa-puzzle-piece:before {\n content: "\\F12E";\n}\n.fa-microphone:before {\n content: "\\F130";\n}\n.fa-microphone-slash:before {\n content: "\\F131";\n}\n.fa-shield:before {\n content: "\\F132";\n}\n.fa-calendar-o:before {\n content: "\\F133";\n}\n.fa-fire-extinguisher:before {\n content: "\\F134";\n}\n.fa-rocket:before {\n content: "\\F135";\n}\n.fa-maxcdn:before {\n content: "\\F136";\n}\n.fa-chevron-circle-left:before {\n content: "\\F137";\n}\n.fa-chevron-circle-right:before {\n content: "\\F138";\n}\n.fa-chevron-circle-up:before {\n content: "\\F139";\n}\n.fa-chevron-circle-down:before {\n content: "\\F13A";\n}\n.fa-html5:before {\n content: "\\F13B";\n}\n.fa-css3:before {\n content: "\\F13C";\n}\n.fa-anchor:before {\n content: "\\F13D";\n}\n.fa-unlock-alt:before {\n content: "\\F13E";\n}\n.fa-bullseye:before {\n content: "\\F140";\n}\n.fa-ellipsis-h:before {\n content: "\\F141";\n}\n.fa-ellipsis-v:before {\n content: "\\F142";\n}\n.fa-rss-square:before {\n content: "\\F143";\n}\n.fa-play-circle:before {\n content: "\\F144";\n}\n.fa-ticket:before {\n content: "\\F145";\n}\n.fa-minus-square:before {\n content: "\\F146";\n}\n.fa-minus-square-o:before {\n content: "\\F147";\n}\n.fa-level-up:before {\n content: "\\F148";\n}\n.fa-level-down:before {\n content: "\\F149";\n}\n.fa-check-square:before {\n content: "\\F14A";\n}\n.fa-pencil-square:before {\n content: "\\F14B";\n}\n.fa-external-link-square:before {\n content: "\\F14C";\n}\n.fa-share-square:before {\n content: "\\F14D";\n}\n.fa-compass:before {\n content: "\\F14E";\n}\n.fa-toggle-down:before,\n.fa-caret-square-o-down:before {\n content: "\\F150";\n}\n.fa-toggle-up:before,\n.fa-caret-square-o-up:before {\n content: "\\F151";\n}\n.fa-toggle-right:before,\n.fa-caret-square-o-right:before {\n content: "\\F152";\n}\n.fa-euro:before,\n.fa-eur:before {\n content: "\\F153";\n}\n.fa-gbp:before {\n content: "\\F154";\n}\n.fa-dollar:before,\n.fa-usd:before {\n content: "\\F155";\n}\n.fa-rupee:before,\n.fa-inr:before {\n content: "\\F156";\n}\n.fa-cny:before,\n.fa-rmb:before,\n.fa-yen:before,\n.fa-jpy:before {\n content: "\\F157";\n}\n.fa-ruble:before,\n.fa-rouble:before,\n.fa-rub:before {\n content: "\\F158";\n}\n.fa-won:before,\n.fa-krw:before {\n content: "\\F159";\n}\n.fa-bitcoin:before,\n.fa-btc:before {\n content: "\\F15A";\n}\n.fa-file:before {\n content: "\\F15B";\n}\n.fa-file-text:before {\n content: "\\F15C";\n}\n.fa-sort-alpha-asc:before {\n content: "\\F15D";\n}\n.fa-sort-alpha-desc:before {\n content: "\\F15E";\n}\n.fa-sort-amount-asc:before {\n content: "\\F160";\n}\n.fa-sort-amount-desc:before {\n content: "\\F161";\n}\n.fa-sort-numeric-asc:before {\n content: "\\F162";\n}\n.fa-sort-numeric-desc:before {\n content: "\\F163";\n}\n.fa-thumbs-up:before {\n content: "\\F164";\n}\n.fa-thumbs-down:before {\n content: "\\F165";\n}\n.fa-youtube-square:before {\n content: "\\F166";\n}\n.fa-youtube:before {\n content: "\\F167";\n}\n.fa-xing:before {\n content: "\\F168";\n}\n.fa-xing-square:before {\n content: "\\F169";\n}\n.fa-youtube-play:before {\n content: "\\F16A";\n}\n.fa-dropbox:before {\n content: "\\F16B";\n}\n.fa-stack-overflow:before {\n content: "\\F16C";\n}\n.fa-instagram:before {\n content: "\\F16D";\n}\n.fa-flickr:before {\n content: "\\F16E";\n}\n.fa-adn:before {\n content: "\\F170";\n}\n.fa-bitbucket:before {\n content: "\\F171";\n}\n.fa-bitbucket-square:before {\n content: "\\F172";\n}\n.fa-tumblr:before {\n content: "\\F173";\n}\n.fa-tumblr-square:before {\n content: "\\F174";\n}\n.fa-long-arrow-down:before {\n content: "\\F175";\n}\n.fa-long-arrow-up:before {\n content: "\\F176";\n}\n.fa-long-arrow-left:before {\n content: "\\F177";\n}\n.fa-long-arrow-right:before {\n content: "\\F178";\n}\n.fa-apple:before {\n content: "\\F179";\n}\n.fa-windows:before {\n content: "\\F17A";\n}\n.fa-android:before {\n content: "\\F17B";\n}\n.fa-linux:before {\n content: "\\F17C";\n}\n.fa-dribbble:before {\n content: "\\F17D";\n}\n.fa-skype:before {\n content: "\\F17E";\n}\n.fa-foursquare:before {\n content: "\\F180";\n}\n.fa-trello:before {\n content: "\\F181";\n}\n.fa-female:before {\n content: "\\F182";\n}\n.fa-male:before {\n content: "\\F183";\n}\n.fa-gittip:before,\n.fa-gratipay:before {\n content: "\\F184";\n}\n.fa-sun-o:before {\n content: "\\F185";\n}\n.fa-moon-o:before {\n content: "\\F186";\n}\n.fa-archive:before {\n content: "\\F187";\n}\n.fa-bug:before {\n content: "\\F188";\n}\n.fa-vk:before {\n content: "\\F189";\n}\n.fa-weibo:before {\n content: "\\F18A";\n}\n.fa-renren:before {\n content: "\\F18B";\n}\n.fa-pagelines:before {\n content: "\\F18C";\n}\n.fa-stack-exchange:before {\n content: "\\F18D";\n}\n.fa-arrow-circle-o-right:before {\n content: "\\F18E";\n}\n.fa-arrow-circle-o-left:before {\n content: "\\F190";\n}\n.fa-toggle-left:before,\n.fa-caret-square-o-left:before {\n content: "\\F191";\n}\n.fa-dot-circle-o:before {\n content: "\\F192";\n}\n.fa-wheelchair:before {\n content: "\\F193";\n}\n.fa-vimeo-square:before {\n content: "\\F194";\n}\n.fa-turkish-lira:before,\n.fa-try:before {\n content: "\\F195";\n}\n.fa-plus-square-o:before {\n content: "\\F196";\n}\n.fa-space-shuttle:before {\n content: "\\F197";\n}\n.fa-slack:before {\n content: "\\F198";\n}\n.fa-envelope-square:before {\n content: "\\F199";\n}\n.fa-wordpress:before {\n content: "\\F19A";\n}\n.fa-openid:before {\n content: "\\F19B";\n}\n.fa-institution:before,\n.fa-bank:before,\n.fa-university:before {\n content: "\\F19C";\n}\n.fa-mortar-board:before,\n.fa-graduation-cap:before {\n content: "\\F19D";\n}\n.fa-yahoo:before {\n content: "\\F19E";\n}\n.fa-google:before {\n content: "\\F1A0";\n}\n.fa-reddit:before {\n content: "\\F1A1";\n}\n.fa-reddit-square:before {\n content: "\\F1A2";\n}\n.fa-stumbleupon-circle:before {\n content: "\\F1A3";\n}\n.fa-stumbleupon:before {\n content: "\\F1A4";\n}\n.fa-delicious:before {\n content: "\\F1A5";\n}\n.fa-digg:before {\n content: "\\F1A6";\n}\n.fa-pied-piper-pp:before {\n content: "\\F1A7";\n}\n.fa-pied-piper-alt:before {\n content: "\\F1A8";\n}\n.fa-drupal:before {\n content: "\\F1A9";\n}\n.fa-joomla:before {\n content: "\\F1AA";\n}\n.fa-language:before {\n content: "\\F1AB";\n}\n.fa-fax:before {\n content: "\\F1AC";\n}\n.fa-building:before {\n content: "\\F1AD";\n}\n.fa-child:before {\n content: "\\F1AE";\n}\n.fa-paw:before {\n content: "\\F1B0";\n}\n.fa-spoon:before {\n content: "\\F1B1";\n}\n.fa-cube:before {\n content: "\\F1B2";\n}\n.fa-cubes:before {\n content: "\\F1B3";\n}\n.fa-behance:before {\n content: "\\F1B4";\n}\n.fa-behance-square:before {\n content: "\\F1B5";\n}\n.fa-steam:before {\n content: "\\F1B6";\n}\n.fa-steam-square:before {\n content: "\\F1B7";\n}\n.fa-recycle:before {\n content: "\\F1B8";\n}\n.fa-automobile:before,\n.fa-car:before {\n content: "\\F1B9";\n}\n.fa-cab:before,\n.fa-taxi:before {\n content: "\\F1BA";\n}\n.fa-tree:before {\n content: "\\F1BB";\n}\n.fa-spotify:before {\n content: "\\F1BC";\n}\n.fa-deviantart:before {\n content: "\\F1BD";\n}\n.fa-soundcloud:before {\n content: "\\F1BE";\n}\n.fa-database:before {\n content: "\\F1C0";\n}\n.fa-file-pdf-o:before {\n content: "\\F1C1";\n}\n.fa-file-word-o:before {\n content: "\\F1C2";\n}\n.fa-file-excel-o:before {\n content: "\\F1C3";\n}\n.fa-file-powerpoint-o:before {\n content: "\\F1C4";\n}\n.fa-file-photo-o:before,\n.fa-file-picture-o:before,\n.fa-file-image-o:before {\n content: "\\F1C5";\n}\n.fa-file-zip-o:before,\n.fa-file-archive-o:before {\n content: "\\F1C6";\n}\n.fa-file-sound-o:before,\n.fa-file-audio-o:before {\n content: "\\F1C7";\n}\n.fa-file-movie-o:before,\n.fa-file-video-o:before {\n content: "\\F1C8";\n}\n.fa-file-code-o:before {\n content: "\\F1C9";\n}\n.fa-vine:before {\n content: "\\F1CA";\n}\n.fa-codepen:before {\n content: "\\F1CB";\n}\n.fa-jsfiddle:before {\n content: "\\F1CC";\n}\n.fa-life-bouy:before,\n.fa-life-buoy:before,\n.fa-life-saver:before,\n.fa-support:before,\n.fa-life-ring:before {\n content: "\\F1CD";\n}\n.fa-circle-o-notch:before {\n content: "\\F1CE";\n}\n.fa-ra:before,\n.fa-resistance:before,\n.fa-rebel:before {\n content: "\\F1D0";\n}\n.fa-ge:before,\n.fa-empire:before {\n content: "\\F1D1";\n}\n.fa-git-square:before {\n content: "\\F1D2";\n}\n.fa-git:before {\n content: "\\F1D3";\n}\n.fa-y-combinator-square:before,\n.fa-yc-square:before,\n.fa-hacker-news:before {\n content: "\\F1D4";\n}\n.fa-tencent-weibo:before {\n content: "\\F1D5";\n}\n.fa-qq:before {\n content: "\\F1D6";\n}\n.fa-wechat:before,\n.fa-weixin:before {\n content: "\\F1D7";\n}\n.fa-send:before,\n.fa-paper-plane:before {\n content: "\\F1D8";\n}\n.fa-send-o:before,\n.fa-paper-plane-o:before {\n content: "\\F1D9";\n}\n.fa-history:before {\n content: "\\F1DA";\n}\n.fa-circle-thin:before {\n content: "\\F1DB";\n}\n.fa-header:before {\n content: "\\F1DC";\n}\n.fa-paragraph:before {\n content: "\\F1DD";\n}\n.fa-sliders:before {\n content: "\\F1DE";\n}\n.fa-share-alt:before {\n content: "\\F1E0";\n}\n.fa-share-alt-square:before {\n content: "\\F1E1";\n}\n.fa-bomb:before {\n content: "\\F1E2";\n}\n.fa-soccer-ball-o:before,\n.fa-futbol-o:before {\n content: "\\F1E3";\n}\n.fa-tty:before {\n content: "\\F1E4";\n}\n.fa-binoculars:before {\n content: "\\F1E5";\n}\n.fa-plug:before {\n content: "\\F1E6";\n}\n.fa-slideshare:before {\n content: "\\F1E7";\n}\n.fa-twitch:before {\n content: "\\F1E8";\n}\n.fa-yelp:before {\n content: "\\F1E9";\n}\n.fa-newspaper-o:before {\n content: "\\F1EA";\n}\n.fa-wifi:before {\n content: "\\F1EB";\n}\n.fa-calculator:before {\n content: "\\F1EC";\n}\n.fa-paypal:before {\n content: "\\F1ED";\n}\n.fa-google-wallet:before {\n content: "\\F1EE";\n}\n.fa-cc-visa:before {\n content: "\\F1F0";\n}\n.fa-cc-mastercard:before {\n content: "\\F1F1";\n}\n.fa-cc-discover:before {\n content: "\\F1F2";\n}\n.fa-cc-amex:before {\n content: "\\F1F3";\n}\n.fa-cc-paypal:before {\n content: "\\F1F4";\n}\n.fa-cc-stripe:before {\n content: "\\F1F5";\n}\n.fa-bell-slash:before {\n content: "\\F1F6";\n}\n.fa-bell-slash-o:before {\n content: "\\F1F7";\n}\n.fa-trash:before {\n content: "\\F1F8";\n}\n.fa-copyright:before {\n content: "\\F1F9";\n}\n.fa-at:before {\n content: "\\F1FA";\n}\n.fa-eyedropper:before {\n content: "\\F1FB";\n}\n.fa-paint-brush:before {\n content: "\\F1FC";\n}\n.fa-birthday-cake:before {\n content: "\\F1FD";\n}\n.fa-area-chart:before {\n content: "\\F1FE";\n}\n.fa-pie-chart:before {\n content: "\\F200";\n}\n.fa-line-chart:before {\n content: "\\F201";\n}\n.fa-lastfm:before {\n content: "\\F202";\n}\n.fa-lastfm-square:before {\n content: "\\F203";\n}\n.fa-toggle-off:before {\n content: "\\F204";\n}\n.fa-toggle-on:before {\n content: "\\F205";\n}\n.fa-bicycle:before {\n content: "\\F206";\n}\n.fa-bus:before {\n content: "\\F207";\n}\n.fa-ioxhost:before {\n content: "\\F208";\n}\n.fa-angellist:before {\n content: "\\F209";\n}\n.fa-cc:before {\n content: "\\F20A";\n}\n.fa-shekel:before,\n.fa-sheqel:before,\n.fa-ils:before {\n content: "\\F20B";\n}\n.fa-meanpath:before {\n content: "\\F20C";\n}\n.fa-buysellads:before {\n content: "\\F20D";\n}\n.fa-connectdevelop:before {\n content: "\\F20E";\n}\n.fa-dashcube:before {\n content: "\\F210";\n}\n.fa-forumbee:before {\n content: "\\F211";\n}\n.fa-leanpub:before {\n content: "\\F212";\n}\n.fa-sellsy:before {\n content: "\\F213";\n}\n.fa-shirtsinbulk:before {\n content: "\\F214";\n}\n.fa-simplybuilt:before {\n content: "\\F215";\n}\n.fa-skyatlas:before {\n content: "\\F216";\n}\n.fa-cart-plus:before {\n content: "\\F217";\n}\n.fa-cart-arrow-down:before {\n content: "\\F218";\n}\n.fa-diamond:before {\n content: "\\F219";\n}\n.fa-ship:before {\n content: "\\F21A";\n}\n.fa-user-secret:before {\n content: "\\F21B";\n}\n.fa-motorcycle:before {\n content: "\\F21C";\n}\n.fa-street-view:before {\n content: "\\F21D";\n}\n.fa-heartbeat:before {\n content: "\\F21E";\n}\n.fa-venus:before {\n content: "\\F221";\n}\n.fa-mars:before {\n content: "\\F222";\n}\n.fa-mercury:before {\n content: "\\F223";\n}\n.fa-intersex:before,\n.fa-transgender:before {\n content: "\\F224";\n}\n.fa-transgender-alt:before {\n content: "\\F225";\n}\n.fa-venus-double:before {\n content: "\\F226";\n}\n.fa-mars-double:before {\n content: "\\F227";\n}\n.fa-venus-mars:before {\n content: "\\F228";\n}\n.fa-mars-stroke:before {\n content: "\\F229";\n}\n.fa-mars-stroke-v:before {\n content: "\\F22A";\n}\n.fa-mars-stroke-h:before {\n content: "\\F22B";\n}\n.fa-neuter:before {\n content: "\\F22C";\n}\n.fa-genderless:before {\n content: "\\F22D";\n}\n.fa-facebook-official:before {\n content: "\\F230";\n}\n.fa-pinterest-p:before {\n content: "\\F231";\n}\n.fa-whatsapp:before {\n content: "\\F232";\n}\n.fa-server:before {\n content: "\\F233";\n}\n.fa-user-plus:before {\n content: "\\F234";\n}\n.fa-user-times:before {\n content: "\\F235";\n}\n.fa-hotel:before,\n.fa-bed:before {\n content: "\\F236";\n}\n.fa-viacoin:before {\n content: "\\F237";\n}\n.fa-train:before {\n content: "\\F238";\n}\n.fa-subway:before {\n content: "\\F239";\n}\n.fa-medium:before {\n content: "\\F23A";\n}\n.fa-yc:before,\n.fa-y-combinator:before {\n content: "\\F23B";\n}\n.fa-optin-monster:before {\n content: "\\F23C";\n}\n.fa-opencart:before {\n content: "\\F23D";\n}\n.fa-expeditedssl:before {\n content: "\\F23E";\n}\n.fa-battery-4:before,\n.fa-battery:before,\n.fa-battery-full:before {\n content: "\\F240";\n}\n.fa-battery-3:before,\n.fa-battery-three-quarters:before {\n content: "\\F241";\n}\n.fa-battery-2:before,\n.fa-battery-half:before {\n content: "\\F242";\n}\n.fa-battery-1:before,\n.fa-battery-quarter:before {\n content: "\\F243";\n}\n.fa-battery-0:before,\n.fa-battery-empty:before {\n content: "\\F244";\n}\n.fa-mouse-pointer:before {\n content: "\\F245";\n}\n.fa-i-cursor:before {\n content: "\\F246";\n}\n.fa-object-group:before {\n content: "\\F247";\n}\n.fa-object-ungroup:before {\n content: "\\F248";\n}\n.fa-sticky-note:before {\n content: "\\F249";\n}\n.fa-sticky-note-o:before {\n content: "\\F24A";\n}\n.fa-cc-jcb:before {\n content: "\\F24B";\n}\n.fa-cc-diners-club:before {\n content: "\\F24C";\n}\n.fa-clone:before {\n content: "\\F24D";\n}\n.fa-balance-scale:before {\n content: "\\F24E";\n}\n.fa-hourglass-o:before {\n content: "\\F250";\n}\n.fa-hourglass-1:before,\n.fa-hourglass-start:before {\n content: "\\F251";\n}\n.fa-hourglass-2:before,\n.fa-hourglass-half:before {\n content: "\\F252";\n}\n.fa-hourglass-3:before,\n.fa-hourglass-end:before {\n content: "\\F253";\n}\n.fa-hourglass:before {\n content: "\\F254";\n}\n.fa-hand-grab-o:before,\n.fa-hand-rock-o:before {\n content: "\\F255";\n}\n.fa-hand-stop-o:before,\n.fa-hand-paper-o:before {\n content: "\\F256";\n}\n.fa-hand-scissors-o:before {\n content: "\\F257";\n}\n.fa-hand-lizard-o:before {\n content: "\\F258";\n}\n.fa-hand-spock-o:before {\n content: "\\F259";\n}\n.fa-hand-pointer-o:before {\n content: "\\F25A";\n}\n.fa-hand-peace-o:before {\n content: "\\F25B";\n}\n.fa-trademark:before {\n content: "\\F25C";\n}\n.fa-registered:before {\n content: "\\F25D";\n}\n.fa-creative-commons:before {\n content: "\\F25E";\n}\n.fa-gg:before {\n content: "\\F260";\n}\n.fa-gg-circle:before {\n content: "\\F261";\n}\n.fa-tripadvisor:before {\n content: "\\F262";\n}\n.fa-odnoklassniki:before {\n content: "\\F263";\n}\n.fa-odnoklassniki-square:before {\n content: "\\F264";\n}\n.fa-get-pocket:before {\n content: "\\F265";\n}\n.fa-wikipedia-w:before {\n content: "\\F266";\n}\n.fa-safari:before {\n content: "\\F267";\n}\n.fa-chrome:before {\n content: "\\F268";\n}\n.fa-firefox:before {\n content: "\\F269";\n}\n.fa-opera:before {\n content: "\\F26A";\n}\n.fa-internet-explorer:before {\n content: "\\F26B";\n}\n.fa-tv:before,\n.fa-television:before {\n content: "\\F26C";\n}\n.fa-contao:before {\n content: "\\F26D";\n}\n.fa-500px:before {\n content: "\\F26E";\n}\n.fa-amazon:before {\n content: "\\F270";\n}\n.fa-calendar-plus-o:before {\n content: "\\F271";\n}\n.fa-calendar-minus-o:before {\n content: "\\F272";\n}\n.fa-calendar-times-o:before {\n content: "\\F273";\n}\n.fa-calendar-check-o:before {\n content: "\\F274";\n}\n.fa-industry:before {\n content: "\\F275";\n}\n.fa-map-pin:before {\n content: "\\F276";\n}\n.fa-map-signs:before {\n content: "\\F277";\n}\n.fa-map-o:before {\n content: "\\F278";\n}\n.fa-map:before {\n content: "\\F279";\n}\n.fa-commenting:before {\n content: "\\F27A";\n}\n.fa-commenting-o:before {\n content: "\\F27B";\n}\n.fa-houzz:before {\n content: "\\F27C";\n}\n.fa-vimeo:before {\n content: "\\F27D";\n}\n.fa-black-tie:before {\n content: "\\F27E";\n}\n.fa-fonticons:before {\n content: "\\F280";\n}\n.fa-reddit-alien:before {\n content: "\\F281";\n}\n.fa-edge:before {\n content: "\\F282";\n}\n.fa-credit-card-alt:before {\n content: "\\F283";\n}\n.fa-codiepie:before {\n content: "\\F284";\n}\n.fa-modx:before {\n content: "\\F285";\n}\n.fa-fort-awesome:before {\n content: "\\F286";\n}\n.fa-usb:before {\n content: "\\F287";\n}\n.fa-product-hunt:before {\n content: "\\F288";\n}\n.fa-mixcloud:before {\n content: "\\F289";\n}\n.fa-scribd:before {\n content: "\\F28A";\n}\n.fa-pause-circle:before {\n content: "\\F28B";\n}\n.fa-pause-circle-o:before {\n content: "\\F28C";\n}\n.fa-stop-circle:before {\n content: "\\F28D";\n}\n.fa-stop-circle-o:before {\n content: "\\F28E";\n}\n.fa-shopping-bag:before {\n content: "\\F290";\n}\n.fa-shopping-basket:before {\n content: "\\F291";\n}\n.fa-hashtag:before {\n content: "\\F292";\n}\n.fa-bluetooth:before {\n content: "\\F293";\n}\n.fa-bluetooth-b:before {\n content: "\\F294";\n}\n.fa-percent:before {\n content: "\\F295";\n}\n.fa-gitlab:before {\n content: "\\F296";\n}\n.fa-wpbeginner:before {\n content: "\\F297";\n}\n.fa-wpforms:before {\n content: "\\F298";\n}\n.fa-envira:before {\n content: "\\F299";\n}\n.fa-universal-access:before {\n content: "\\F29A";\n}\n.fa-wheelchair-alt:before {\n content: "\\F29B";\n}\n.fa-question-circle-o:before {\n content: "\\F29C";\n}\n.fa-blind:before {\n content: "\\F29D";\n}\n.fa-audio-description:before {\n content: "\\F29E";\n}\n.fa-volume-control-phone:before {\n content: "\\F2A0";\n}\n.fa-braille:before {\n content: "\\F2A1";\n}\n.fa-assistive-listening-systems:before {\n content: "\\F2A2";\n}\n.fa-asl-interpreting:before,\n.fa-american-sign-language-interpreting:before {\n content: "\\F2A3";\n}\n.fa-deafness:before,\n.fa-hard-of-hearing:before,\n.fa-deaf:before {\n content: "\\F2A4";\n}\n.fa-glide:before {\n content: "\\F2A5";\n}\n.fa-glide-g:before {\n content: "\\F2A6";\n}\n.fa-signing:before,\n.fa-sign-language:before {\n content: "\\F2A7";\n}\n.fa-low-vision:before {\n content: "\\F2A8";\n}\n.fa-viadeo:before {\n content: "\\F2A9";\n}\n.fa-viadeo-square:before {\n content: "\\F2AA";\n}\n.fa-snapchat:before {\n content: "\\F2AB";\n}\n.fa-snapchat-ghost:before {\n content: "\\F2AC";\n}\n.fa-snapchat-square:before {\n content: "\\F2AD";\n}\n.fa-pied-piper:before {\n content: "\\F2AE";\n}\n.fa-first-order:before {\n content: "\\F2B0";\n}\n.fa-yoast:before {\n content: "\\F2B1";\n}\n.fa-themeisle:before {\n content: "\\F2B2";\n}\n.fa-google-plus-circle:before,\n.fa-google-plus-official:before {\n content: "\\F2B3";\n}\n.fa-fa:before,\n.fa-font-awesome:before {\n content: "\\F2B4";\n}\n.fa-handshake-o:before {\n content: "\\F2B5";\n}\n.fa-envelope-open:before {\n content: "\\F2B6";\n}\n.fa-envelope-open-o:before {\n content: "\\F2B7";\n}\n.fa-linode:before {\n content: "\\F2B8";\n}\n.fa-address-book:before {\n content: "\\F2B9";\n}\n.fa-address-book-o:before {\n content: "\\F2BA";\n}\n.fa-vcard:before,\n.fa-address-card:before {\n content: "\\F2BB";\n}\n.fa-vcard-o:before,\n.fa-address-card-o:before {\n content: "\\F2BC";\n}\n.fa-user-circle:before {\n content: "\\F2BD";\n}\n.fa-user-circle-o:before {\n content: "\\F2BE";\n}\n.fa-user-o:before {\n content: "\\F2C0";\n}\n.fa-id-badge:before {\n content: "\\F2C1";\n}\n.fa-drivers-license:before,\n.fa-id-card:before {\n content: "\\F2C2";\n}\n.fa-drivers-license-o:before,\n.fa-id-card-o:before {\n content: "\\F2C3";\n}\n.fa-quora:before {\n content: "\\F2C4";\n}\n.fa-free-code-camp:before {\n content: "\\F2C5";\n}\n.fa-telegram:before {\n content: "\\F2C6";\n}\n.fa-thermometer-4:before,\n.fa-thermometer:before,\n.fa-thermometer-full:before {\n content: "\\F2C7";\n}\n.fa-thermometer-3:before,\n.fa-thermometer-three-quarters:before {\n content: "\\F2C8";\n}\n.fa-thermometer-2:before,\n.fa-thermometer-half:before {\n content: "\\F2C9";\n}\n.fa-thermometer-1:before,\n.fa-thermometer-quarter:before {\n content: "\\F2CA";\n}\n.fa-thermometer-0:before,\n.fa-thermometer-empty:before {\n content: "\\F2CB";\n}\n.fa-shower:before {\n content: "\\F2CC";\n}\n.fa-bathtub:before,\n.fa-s15:before,\n.fa-bath:before {\n content: "\\F2CD";\n}\n.fa-podcast:before {\n content: "\\F2CE";\n}\n.fa-window-maximize:before {\n content: "\\F2D0";\n}\n.fa-window-minimize:before {\n content: "\\F2D1";\n}\n.fa-window-restore:before {\n content: "\\F2D2";\n}\n.fa-times-rectangle:before,\n.fa-window-close:before {\n content: "\\F2D3";\n}\n.fa-times-rectangle-o:before,\n.fa-window-close-o:before {\n content: "\\F2D4";\n}\n.fa-bandcamp:before {\n content: "\\F2D5";\n}\n.fa-grav:before {\n content: "\\F2D6";\n}\n.fa-etsy:before {\n content: "\\F2D7";\n}\n.fa-imdb:before {\n content: "\\F2D8";\n}\n.fa-ravelry:before {\n content: "\\F2D9";\n}\n.fa-eercast:before {\n content: "\\F2DA";\n}\n.fa-microchip:before {\n content: "\\F2DB";\n}\n.fa-snowflake-o:before {\n content: "\\F2DC";\n}\n.fa-superpowers:before {\n content: "\\F2DD";\n}\n.fa-wpexplorer:before {\n content: "\\F2DE";\n}\n.fa-meetup:before {\n content: "\\F2E0";\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n', "" ]);
+ var escape = __webpack_require__(499);
+ exports = module.exports = __webpack_require__(500)(!1), exports.push([ module.i, "/*!\n * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome\n * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)\n */\n/* FONT PATH\n * -------------------------- */\n@font-face {\n font-family: 'FontAwesome';\n \n src: url(" + escape(__webpack_require__(501)) + ") format('woff2'), url(" + escape(__webpack_require__(502)) + ') format(\'woff\');\n font-weight: normal;\n font-style: normal;\n}\n.fa {\n display: inline-block;\n font: normal normal normal 14px/1 FontAwesome;\n font-size: inherit;\n text-rendering: auto;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n/* makes the font 33% larger relative to the icon container */\n.fa-lg {\n font-size: 1.33333333em;\n line-height: 0.75em;\n vertical-align: -15%;\n}\n.fa-2x {\n font-size: 2em;\n}\n.fa-3x {\n font-size: 3em;\n}\n.fa-4x {\n font-size: 4em;\n}\n.fa-5x {\n font-size: 5em;\n}\n.fa-fw {\n width: 1.28571429em;\n text-align: center;\n}\n.fa-ul {\n padding-left: 0;\n margin-left: 2.14285714em;\n list-style-type: none;\n}\n.fa-ul > li {\n position: relative;\n}\n.fa-li {\n position: absolute;\n left: -2.14285714em;\n width: 2.14285714em;\n top: 0.14285714em;\n text-align: center;\n}\n.fa-li.fa-lg {\n left: -1.85714286em;\n}\n.fa-border {\n padding: .2em .25em .15em;\n border: solid 0.08em #eeeeee;\n border-radius: .1em;\n}\n.fa-pull-left {\n float: left;\n}\n.fa-pull-right {\n float: right;\n}\n.fa.fa-pull-left {\n margin-right: .3em;\n}\n.fa.fa-pull-right {\n margin-left: .3em;\n}\n/* Deprecated as of 4.4.0 */\n.pull-right {\n float: right;\n}\n.pull-left {\n float: left;\n}\n.fa.pull-left {\n margin-right: .3em;\n}\n.fa.pull-right {\n margin-left: .3em;\n}\n.fa-spin {\n -webkit-animation: fa-spin 2s infinite linear;\n animation: fa-spin 2s infinite linear;\n}\n.fa-pulse {\n -webkit-animation: fa-spin 1s infinite steps(8);\n animation: fa-spin 1s infinite steps(8);\n}\n@-webkit-keyframes fa-spin {\n 0% {\n -webkit-transform: rotate(0deg);\n transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(359deg);\n transform: rotate(359deg);\n }\n}\n@keyframes fa-spin {\n 0% {\n -webkit-transform: rotate(0deg);\n transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(359deg);\n transform: rotate(359deg);\n }\n}\n.fa-rotate-90 {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";\n -webkit-transform: rotate(90deg);\n -ms-transform: rotate(90deg);\n transform: rotate(90deg);\n}\n.fa-rotate-180 {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";\n -webkit-transform: rotate(180deg);\n -ms-transform: rotate(180deg);\n transform: rotate(180deg);\n}\n.fa-rotate-270 {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";\n -webkit-transform: rotate(270deg);\n -ms-transform: rotate(270deg);\n transform: rotate(270deg);\n}\n.fa-flip-horizontal {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";\n -webkit-transform: scale(-1, 1);\n -ms-transform: scale(-1, 1);\n transform: scale(-1, 1);\n}\n.fa-flip-vertical {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";\n -webkit-transform: scale(1, -1);\n -ms-transform: scale(1, -1);\n transform: scale(1, -1);\n}\n:root .fa-rotate-90,\n:root .fa-rotate-180,\n:root .fa-rotate-270,\n:root .fa-flip-horizontal,\n:root .fa-flip-vertical {\n filter: none;\n}\n.fa-stack {\n position: relative;\n display: inline-block;\n width: 2em;\n height: 2em;\n line-height: 2em;\n vertical-align: middle;\n}\n.fa-stack-1x,\n.fa-stack-2x {\n position: absolute;\n left: 0;\n width: 100%;\n text-align: center;\n}\n.fa-stack-1x {\n line-height: inherit;\n}\n.fa-stack-2x {\n font-size: 2em;\n}\n.fa-inverse {\n color: #ffffff;\n}\n/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen\n readers do not read off random characters that represent icons */\n.fa-glass:before {\n content: "\\F000";\n}\n.fa-music:before {\n content: "\\F001";\n}\n.fa-search:before {\n content: "\\F002";\n}\n.fa-envelope-o:before {\n content: "\\F003";\n}\n.fa-heart:before {\n content: "\\F004";\n}\n.fa-star:before {\n content: "\\F005";\n}\n.fa-star-o:before {\n content: "\\F006";\n}\n.fa-user:before {\n content: "\\F007";\n}\n.fa-film:before {\n content: "\\F008";\n}\n.fa-th-large:before {\n content: "\\F009";\n}\n.fa-th:before {\n content: "\\F00A";\n}\n.fa-th-list:before {\n content: "\\F00B";\n}\n.fa-check:before {\n content: "\\F00C";\n}\n.fa-remove:before,\n.fa-close:before,\n.fa-times:before {\n content: "\\F00D";\n}\n.fa-search-plus:before {\n content: "\\F00E";\n}\n.fa-search-minus:before {\n content: "\\F010";\n}\n.fa-power-off:before {\n content: "\\F011";\n}\n.fa-signal:before {\n content: "\\F012";\n}\n.fa-gear:before,\n.fa-cog:before {\n content: "\\F013";\n}\n.fa-trash-o:before {\n content: "\\F014";\n}\n.fa-home:before {\n content: "\\F015";\n}\n.fa-file-o:before {\n content: "\\F016";\n}\n.fa-clock-o:before {\n content: "\\F017";\n}\n.fa-road:before {\n content: "\\F018";\n}\n.fa-download:before {\n content: "\\F019";\n}\n.fa-arrow-circle-o-down:before {\n content: "\\F01A";\n}\n.fa-arrow-circle-o-up:before {\n content: "\\F01B";\n}\n.fa-inbox:before {\n content: "\\F01C";\n}\n.fa-play-circle-o:before {\n content: "\\F01D";\n}\n.fa-rotate-right:before,\n.fa-repeat:before {\n content: "\\F01E";\n}\n.fa-refresh:before {\n content: "\\F021";\n}\n.fa-list-alt:before {\n content: "\\F022";\n}\n.fa-lock:before {\n content: "\\F023";\n}\n.fa-flag:before {\n content: "\\F024";\n}\n.fa-headphones:before {\n content: "\\F025";\n}\n.fa-volume-off:before {\n content: "\\F026";\n}\n.fa-volume-down:before {\n content: "\\F027";\n}\n.fa-volume-up:before {\n content: "\\F028";\n}\n.fa-qrcode:before {\n content: "\\F029";\n}\n.fa-barcode:before {\n content: "\\F02A";\n}\n.fa-tag:before {\n content: "\\F02B";\n}\n.fa-tags:before {\n content: "\\F02C";\n}\n.fa-book:before {\n content: "\\F02D";\n}\n.fa-bookmark:before {\n content: "\\F02E";\n}\n.fa-print:before {\n content: "\\F02F";\n}\n.fa-camera:before {\n content: "\\F030";\n}\n.fa-font:before {\n content: "\\F031";\n}\n.fa-bold:before {\n content: "\\F032";\n}\n.fa-italic:before {\n content: "\\F033";\n}\n.fa-text-height:before {\n content: "\\F034";\n}\n.fa-text-width:before {\n content: "\\F035";\n}\n.fa-align-left:before {\n content: "\\F036";\n}\n.fa-align-center:before {\n content: "\\F037";\n}\n.fa-align-right:before {\n content: "\\F038";\n}\n.fa-align-justify:before {\n content: "\\F039";\n}\n.fa-list:before {\n content: "\\F03A";\n}\n.fa-dedent:before,\n.fa-outdent:before {\n content: "\\F03B";\n}\n.fa-indent:before {\n content: "\\F03C";\n}\n.fa-video-camera:before {\n content: "\\F03D";\n}\n.fa-photo:before,\n.fa-image:before,\n.fa-picture-o:before {\n content: "\\F03E";\n}\n.fa-pencil:before {\n content: "\\F040";\n}\n.fa-map-marker:before {\n content: "\\F041";\n}\n.fa-adjust:before {\n content: "\\F042";\n}\n.fa-tint:before {\n content: "\\F043";\n}\n.fa-edit:before,\n.fa-pencil-square-o:before {\n content: "\\F044";\n}\n.fa-share-square-o:before {\n content: "\\F045";\n}\n.fa-check-square-o:before {\n content: "\\F046";\n}\n.fa-arrows:before {\n content: "\\F047";\n}\n.fa-step-backward:before {\n content: "\\F048";\n}\n.fa-fast-backward:before {\n content: "\\F049";\n}\n.fa-backward:before {\n content: "\\F04A";\n}\n.fa-play:before {\n content: "\\F04B";\n}\n.fa-pause:before {\n content: "\\F04C";\n}\n.fa-stop:before {\n content: "\\F04D";\n}\n.fa-forward:before {\n content: "\\F04E";\n}\n.fa-fast-forward:before {\n content: "\\F050";\n}\n.fa-step-forward:before {\n content: "\\F051";\n}\n.fa-eject:before {\n content: "\\F052";\n}\n.fa-chevron-left:before {\n content: "\\F053";\n}\n.fa-chevron-right:before {\n content: "\\F054";\n}\n.fa-plus-circle:before {\n content: "\\F055";\n}\n.fa-minus-circle:before {\n content: "\\F056";\n}\n.fa-times-circle:before {\n content: "\\F057";\n}\n.fa-check-circle:before {\n content: "\\F058";\n}\n.fa-question-circle:before {\n content: "\\F059";\n}\n.fa-info-circle:before {\n content: "\\F05A";\n}\n.fa-crosshairs:before {\n content: "\\F05B";\n}\n.fa-times-circle-o:before {\n content: "\\F05C";\n}\n.fa-check-circle-o:before {\n content: "\\F05D";\n}\n.fa-ban:before {\n content: "\\F05E";\n}\n.fa-arrow-left:before {\n content: "\\F060";\n}\n.fa-arrow-right:before {\n content: "\\F061";\n}\n.fa-arrow-up:before {\n content: "\\F062";\n}\n.fa-arrow-down:before {\n content: "\\F063";\n}\n.fa-mail-forward:before,\n.fa-share:before {\n content: "\\F064";\n}\n.fa-expand:before {\n content: "\\F065";\n}\n.fa-compress:before {\n content: "\\F066";\n}\n.fa-plus:before {\n content: "\\F067";\n}\n.fa-minus:before {\n content: "\\F068";\n}\n.fa-asterisk:before {\n content: "\\F069";\n}\n.fa-exclamation-circle:before {\n content: "\\F06A";\n}\n.fa-gift:before {\n content: "\\F06B";\n}\n.fa-leaf:before {\n content: "\\F06C";\n}\n.fa-fire:before {\n content: "\\F06D";\n}\n.fa-eye:before {\n content: "\\F06E";\n}\n.fa-eye-slash:before {\n content: "\\F070";\n}\n.fa-warning:before,\n.fa-exclamation-triangle:before {\n content: "\\F071";\n}\n.fa-plane:before {\n content: "\\F072";\n}\n.fa-calendar:before {\n content: "\\F073";\n}\n.fa-random:before {\n content: "\\F074";\n}\n.fa-comment:before {\n content: "\\F075";\n}\n.fa-magnet:before {\n content: "\\F076";\n}\n.fa-chevron-up:before {\n content: "\\F077";\n}\n.fa-chevron-down:before {\n content: "\\F078";\n}\n.fa-retweet:before {\n content: "\\F079";\n}\n.fa-shopping-cart:before {\n content: "\\F07A";\n}\n.fa-folder:before {\n content: "\\F07B";\n}\n.fa-folder-open:before {\n content: "\\F07C";\n}\n.fa-arrows-v:before {\n content: "\\F07D";\n}\n.fa-arrows-h:before {\n content: "\\F07E";\n}\n.fa-bar-chart-o:before,\n.fa-bar-chart:before {\n content: "\\F080";\n}\n.fa-twitter-square:before {\n content: "\\F081";\n}\n.fa-facebook-square:before {\n content: "\\F082";\n}\n.fa-camera-retro:before {\n content: "\\F083";\n}\n.fa-key:before {\n content: "\\F084";\n}\n.fa-gears:before,\n.fa-cogs:before {\n content: "\\F085";\n}\n.fa-comments:before {\n content: "\\F086";\n}\n.fa-thumbs-o-up:before {\n content: "\\F087";\n}\n.fa-thumbs-o-down:before {\n content: "\\F088";\n}\n.fa-star-half:before {\n content: "\\F089";\n}\n.fa-heart-o:before {\n content: "\\F08A";\n}\n.fa-sign-out:before {\n content: "\\F08B";\n}\n.fa-linkedin-square:before {\n content: "\\F08C";\n}\n.fa-thumb-tack:before {\n content: "\\F08D";\n}\n.fa-external-link:before {\n content: "\\F08E";\n}\n.fa-sign-in:before {\n content: "\\F090";\n}\n.fa-trophy:before {\n content: "\\F091";\n}\n.fa-github-square:before {\n content: "\\F092";\n}\n.fa-upload:before {\n content: "\\F093";\n}\n.fa-lemon-o:before {\n content: "\\F094";\n}\n.fa-phone:before {\n content: "\\F095";\n}\n.fa-square-o:before {\n content: "\\F096";\n}\n.fa-bookmark-o:before {\n content: "\\F097";\n}\n.fa-phone-square:before {\n content: "\\F098";\n}\n.fa-twitter:before {\n content: "\\F099";\n}\n.fa-facebook-f:before,\n.fa-facebook:before {\n content: "\\F09A";\n}\n.fa-github:before {\n content: "\\F09B";\n}\n.fa-unlock:before {\n content: "\\F09C";\n}\n.fa-credit-card:before {\n content: "\\F09D";\n}\n.fa-feed:before,\n.fa-rss:before {\n content: "\\F09E";\n}\n.fa-hdd-o:before {\n content: "\\F0A0";\n}\n.fa-bullhorn:before {\n content: "\\F0A1";\n}\n.fa-bell:before {\n content: "\\F0F3";\n}\n.fa-certificate:before {\n content: "\\F0A3";\n}\n.fa-hand-o-right:before {\n content: "\\F0A4";\n}\n.fa-hand-o-left:before {\n content: "\\F0A5";\n}\n.fa-hand-o-up:before {\n content: "\\F0A6";\n}\n.fa-hand-o-down:before {\n content: "\\F0A7";\n}\n.fa-arrow-circle-left:before {\n content: "\\F0A8";\n}\n.fa-arrow-circle-right:before {\n content: "\\F0A9";\n}\n.fa-arrow-circle-up:before {\n content: "\\F0AA";\n}\n.fa-arrow-circle-down:before {\n content: "\\F0AB";\n}\n.fa-globe:before {\n content: "\\F0AC";\n}\n.fa-wrench:before {\n content: "\\F0AD";\n}\n.fa-tasks:before {\n content: "\\F0AE";\n}\n.fa-filter:before {\n content: "\\F0B0";\n}\n.fa-briefcase:before {\n content: "\\F0B1";\n}\n.fa-arrows-alt:before {\n content: "\\F0B2";\n}\n.fa-group:before,\n.fa-users:before {\n content: "\\F0C0";\n}\n.fa-chain:before,\n.fa-link:before {\n content: "\\F0C1";\n}\n.fa-cloud:before {\n content: "\\F0C2";\n}\n.fa-flask:before {\n content: "\\F0C3";\n}\n.fa-cut:before,\n.fa-scissors:before {\n content: "\\F0C4";\n}\n.fa-copy:before,\n.fa-files-o:before {\n content: "\\F0C5";\n}\n.fa-paperclip:before {\n content: "\\F0C6";\n}\n.fa-save:before,\n.fa-floppy-o:before {\n content: "\\F0C7";\n}\n.fa-square:before {\n content: "\\F0C8";\n}\n.fa-navicon:before,\n.fa-reorder:before,\n.fa-bars:before {\n content: "\\F0C9";\n}\n.fa-list-ul:before {\n content: "\\F0CA";\n}\n.fa-list-ol:before {\n content: "\\F0CB";\n}\n.fa-strikethrough:before {\n content: "\\F0CC";\n}\n.fa-underline:before {\n content: "\\F0CD";\n}\n.fa-table:before {\n content: "\\F0CE";\n}\n.fa-magic:before {\n content: "\\F0D0";\n}\n.fa-truck:before {\n content: "\\F0D1";\n}\n.fa-pinterest:before {\n content: "\\F0D2";\n}\n.fa-pinterest-square:before {\n content: "\\F0D3";\n}\n.fa-google-plus-square:before {\n content: "\\F0D4";\n}\n.fa-google-plus:before {\n content: "\\F0D5";\n}\n.fa-money:before {\n content: "\\F0D6";\n}\n.fa-caret-down:before {\n content: "\\F0D7";\n}\n.fa-caret-up:before {\n content: "\\F0D8";\n}\n.fa-caret-left:before {\n content: "\\F0D9";\n}\n.fa-caret-right:before {\n content: "\\F0DA";\n}\n.fa-columns:before {\n content: "\\F0DB";\n}\n.fa-unsorted:before,\n.fa-sort:before {\n content: "\\F0DC";\n}\n.fa-sort-down:before,\n.fa-sort-desc:before {\n content: "\\F0DD";\n}\n.fa-sort-up:before,\n.fa-sort-asc:before {\n content: "\\F0DE";\n}\n.fa-envelope:before {\n content: "\\F0E0";\n}\n.fa-linkedin:before {\n content: "\\F0E1";\n}\n.fa-rotate-left:before,\n.fa-undo:before {\n content: "\\F0E2";\n}\n.fa-legal:before,\n.fa-gavel:before {\n content: "\\F0E3";\n}\n.fa-dashboard:before,\n.fa-tachometer:before {\n content: "\\F0E4";\n}\n.fa-comment-o:before {\n content: "\\F0E5";\n}\n.fa-comments-o:before {\n content: "\\F0E6";\n}\n.fa-flash:before,\n.fa-bolt:before {\n content: "\\F0E7";\n}\n.fa-sitemap:before {\n content: "\\F0E8";\n}\n.fa-umbrella:before {\n content: "\\F0E9";\n}\n.fa-paste:before,\n.fa-clipboard:before {\n content: "\\F0EA";\n}\n.fa-lightbulb-o:before {\n content: "\\F0EB";\n}\n.fa-exchange:before {\n content: "\\F0EC";\n}\n.fa-cloud-download:before {\n content: "\\F0ED";\n}\n.fa-cloud-upload:before {\n content: "\\F0EE";\n}\n.fa-user-md:before {\n content: "\\F0F0";\n}\n.fa-stethoscope:before {\n content: "\\F0F1";\n}\n.fa-suitcase:before {\n content: "\\F0F2";\n}\n.fa-bell-o:before {\n content: "\\F0A2";\n}\n.fa-coffee:before {\n content: "\\F0F4";\n}\n.fa-cutlery:before {\n content: "\\F0F5";\n}\n.fa-file-text-o:before {\n content: "\\F0F6";\n}\n.fa-building-o:before {\n content: "\\F0F7";\n}\n.fa-hospital-o:before {\n content: "\\F0F8";\n}\n.fa-ambulance:before {\n content: "\\F0F9";\n}\n.fa-medkit:before {\n content: "\\F0FA";\n}\n.fa-fighter-jet:before {\n content: "\\F0FB";\n}\n.fa-beer:before {\n content: "\\F0FC";\n}\n.fa-h-square:before {\n content: "\\F0FD";\n}\n.fa-plus-square:before {\n content: "\\F0FE";\n}\n.fa-angle-double-left:before {\n content: "\\F100";\n}\n.fa-angle-double-right:before {\n content: "\\F101";\n}\n.fa-angle-double-up:before {\n content: "\\F102";\n}\n.fa-angle-double-down:before {\n content: "\\F103";\n}\n.fa-angle-left:before {\n content: "\\F104";\n}\n.fa-angle-right:before {\n content: "\\F105";\n}\n.fa-angle-up:before {\n content: "\\F106";\n}\n.fa-angle-down:before {\n content: "\\F107";\n}\n.fa-desktop:before {\n content: "\\F108";\n}\n.fa-laptop:before {\n content: "\\F109";\n}\n.fa-tablet:before {\n content: "\\F10A";\n}\n.fa-mobile-phone:before,\n.fa-mobile:before {\n content: "\\F10B";\n}\n.fa-circle-o:before {\n content: "\\F10C";\n}\n.fa-quote-left:before {\n content: "\\F10D";\n}\n.fa-quote-right:before {\n content: "\\F10E";\n}\n.fa-spinner:before {\n content: "\\F110";\n}\n.fa-circle:before {\n content: "\\F111";\n}\n.fa-mail-reply:before,\n.fa-reply:before {\n content: "\\F112";\n}\n.fa-github-alt:before {\n content: "\\F113";\n}\n.fa-folder-o:before {\n content: "\\F114";\n}\n.fa-folder-open-o:before {\n content: "\\F115";\n}\n.fa-smile-o:before {\n content: "\\F118";\n}\n.fa-frown-o:before {\n content: "\\F119";\n}\n.fa-meh-o:before {\n content: "\\F11A";\n}\n.fa-gamepad:before {\n content: "\\F11B";\n}\n.fa-keyboard-o:before {\n content: "\\F11C";\n}\n.fa-flag-o:before {\n content: "\\F11D";\n}\n.fa-flag-checkered:before {\n content: "\\F11E";\n}\n.fa-terminal:before {\n content: "\\F120";\n}\n.fa-code:before {\n content: "\\F121";\n}\n.fa-mail-reply-all:before,\n.fa-reply-all:before {\n content: "\\F122";\n}\n.fa-star-half-empty:before,\n.fa-star-half-full:before,\n.fa-star-half-o:before {\n content: "\\F123";\n}\n.fa-location-arrow:before {\n content: "\\F124";\n}\n.fa-crop:before {\n content: "\\F125";\n}\n.fa-code-fork:before {\n content: "\\F126";\n}\n.fa-unlink:before,\n.fa-chain-broken:before {\n content: "\\F127";\n}\n.fa-question:before {\n content: "\\F128";\n}\n.fa-info:before {\n content: "\\F129";\n}\n.fa-exclamation:before {\n content: "\\F12A";\n}\n.fa-superscript:before {\n content: "\\F12B";\n}\n.fa-subscript:before {\n content: "\\F12C";\n}\n.fa-eraser:before {\n content: "\\F12D";\n}\n.fa-puzzle-piece:before {\n content: "\\F12E";\n}\n.fa-microphone:before {\n content: "\\F130";\n}\n.fa-microphone-slash:before {\n content: "\\F131";\n}\n.fa-shield:before {\n content: "\\F132";\n}\n.fa-calendar-o:before {\n content: "\\F133";\n}\n.fa-fire-extinguisher:before {\n content: "\\F134";\n}\n.fa-rocket:before {\n content: "\\F135";\n}\n.fa-maxcdn:before {\n content: "\\F136";\n}\n.fa-chevron-circle-left:before {\n content: "\\F137";\n}\n.fa-chevron-circle-right:before {\n content: "\\F138";\n}\n.fa-chevron-circle-up:before {\n content: "\\F139";\n}\n.fa-chevron-circle-down:before {\n content: "\\F13A";\n}\n.fa-html5:before {\n content: "\\F13B";\n}\n.fa-css3:before {\n content: "\\F13C";\n}\n.fa-anchor:before {\n content: "\\F13D";\n}\n.fa-unlock-alt:before {\n content: "\\F13E";\n}\n.fa-bullseye:before {\n content: "\\F140";\n}\n.fa-ellipsis-h:before {\n content: "\\F141";\n}\n.fa-ellipsis-v:before {\n content: "\\F142";\n}\n.fa-rss-square:before {\n content: "\\F143";\n}\n.fa-play-circle:before {\n content: "\\F144";\n}\n.fa-ticket:before {\n content: "\\F145";\n}\n.fa-minus-square:before {\n content: "\\F146";\n}\n.fa-minus-square-o:before {\n content: "\\F147";\n}\n.fa-level-up:before {\n content: "\\F148";\n}\n.fa-level-down:before {\n content: "\\F149";\n}\n.fa-check-square:before {\n content: "\\F14A";\n}\n.fa-pencil-square:before {\n content: "\\F14B";\n}\n.fa-external-link-square:before {\n content: "\\F14C";\n}\n.fa-share-square:before {\n content: "\\F14D";\n}\n.fa-compass:before {\n content: "\\F14E";\n}\n.fa-toggle-down:before,\n.fa-caret-square-o-down:before {\n content: "\\F150";\n}\n.fa-toggle-up:before,\n.fa-caret-square-o-up:before {\n content: "\\F151";\n}\n.fa-toggle-right:before,\n.fa-caret-square-o-right:before {\n content: "\\F152";\n}\n.fa-euro:before,\n.fa-eur:before {\n content: "\\F153";\n}\n.fa-gbp:before {\n content: "\\F154";\n}\n.fa-dollar:before,\n.fa-usd:before {\n content: "\\F155";\n}\n.fa-rupee:before,\n.fa-inr:before {\n content: "\\F156";\n}\n.fa-cny:before,\n.fa-rmb:before,\n.fa-yen:before,\n.fa-jpy:before {\n content: "\\F157";\n}\n.fa-ruble:before,\n.fa-rouble:before,\n.fa-rub:before {\n content: "\\F158";\n}\n.fa-won:before,\n.fa-krw:before {\n content: "\\F159";\n}\n.fa-bitcoin:before,\n.fa-btc:before {\n content: "\\F15A";\n}\n.fa-file:before {\n content: "\\F15B";\n}\n.fa-file-text:before {\n content: "\\F15C";\n}\n.fa-sort-alpha-asc:before {\n content: "\\F15D";\n}\n.fa-sort-alpha-desc:before {\n content: "\\F15E";\n}\n.fa-sort-amount-asc:before {\n content: "\\F160";\n}\n.fa-sort-amount-desc:before {\n content: "\\F161";\n}\n.fa-sort-numeric-asc:before {\n content: "\\F162";\n}\n.fa-sort-numeric-desc:before {\n content: "\\F163";\n}\n.fa-thumbs-up:before {\n content: "\\F164";\n}\n.fa-thumbs-down:before {\n content: "\\F165";\n}\n.fa-youtube-square:before {\n content: "\\F166";\n}\n.fa-youtube:before {\n content: "\\F167";\n}\n.fa-xing:before {\n content: "\\F168";\n}\n.fa-xing-square:before {\n content: "\\F169";\n}\n.fa-youtube-play:before {\n content: "\\F16A";\n}\n.fa-dropbox:before {\n content: "\\F16B";\n}\n.fa-stack-overflow:before {\n content: "\\F16C";\n}\n.fa-instagram:before {\n content: "\\F16D";\n}\n.fa-flickr:before {\n content: "\\F16E";\n}\n.fa-adn:before {\n content: "\\F170";\n}\n.fa-bitbucket:before {\n content: "\\F171";\n}\n.fa-bitbucket-square:before {\n content: "\\F172";\n}\n.fa-tumblr:before {\n content: "\\F173";\n}\n.fa-tumblr-square:before {\n content: "\\F174";\n}\n.fa-long-arrow-down:before {\n content: "\\F175";\n}\n.fa-long-arrow-up:before {\n content: "\\F176";\n}\n.fa-long-arrow-left:before {\n content: "\\F177";\n}\n.fa-long-arrow-right:before {\n content: "\\F178";\n}\n.fa-apple:before {\n content: "\\F179";\n}\n.fa-windows:before {\n content: "\\F17A";\n}\n.fa-android:before {\n content: "\\F17B";\n}\n.fa-linux:before {\n content: "\\F17C";\n}\n.fa-dribbble:before {\n content: "\\F17D";\n}\n.fa-skype:before {\n content: "\\F17E";\n}\n.fa-foursquare:before {\n content: "\\F180";\n}\n.fa-trello:before {\n content: "\\F181";\n}\n.fa-female:before {\n content: "\\F182";\n}\n.fa-male:before {\n content: "\\F183";\n}\n.fa-gittip:before,\n.fa-gratipay:before {\n content: "\\F184";\n}\n.fa-sun-o:before {\n content: "\\F185";\n}\n.fa-moon-o:before {\n content: "\\F186";\n}\n.fa-archive:before {\n content: "\\F187";\n}\n.fa-bug:before {\n content: "\\F188";\n}\n.fa-vk:before {\n content: "\\F189";\n}\n.fa-weibo:before {\n content: "\\F18A";\n}\n.fa-renren:before {\n content: "\\F18B";\n}\n.fa-pagelines:before {\n content: "\\F18C";\n}\n.fa-stack-exchange:before {\n content: "\\F18D";\n}\n.fa-arrow-circle-o-right:before {\n content: "\\F18E";\n}\n.fa-arrow-circle-o-left:before {\n content: "\\F190";\n}\n.fa-toggle-left:before,\n.fa-caret-square-o-left:before {\n content: "\\F191";\n}\n.fa-dot-circle-o:before {\n content: "\\F192";\n}\n.fa-wheelchair:before {\n content: "\\F193";\n}\n.fa-vimeo-square:before {\n content: "\\F194";\n}\n.fa-turkish-lira:before,\n.fa-try:before {\n content: "\\F195";\n}\n.fa-plus-square-o:before {\n content: "\\F196";\n}\n.fa-space-shuttle:before {\n content: "\\F197";\n}\n.fa-slack:before {\n content: "\\F198";\n}\n.fa-envelope-square:before {\n content: "\\F199";\n}\n.fa-wordpress:before {\n content: "\\F19A";\n}\n.fa-openid:before {\n content: "\\F19B";\n}\n.fa-institution:before,\n.fa-bank:before,\n.fa-university:before {\n content: "\\F19C";\n}\n.fa-mortar-board:before,\n.fa-graduation-cap:before {\n content: "\\F19D";\n}\n.fa-yahoo:before {\n content: "\\F19E";\n}\n.fa-google:before {\n content: "\\F1A0";\n}\n.fa-reddit:before {\n content: "\\F1A1";\n}\n.fa-reddit-square:before {\n content: "\\F1A2";\n}\n.fa-stumbleupon-circle:before {\n content: "\\F1A3";\n}\n.fa-stumbleupon:before {\n content: "\\F1A4";\n}\n.fa-delicious:before {\n content: "\\F1A5";\n}\n.fa-digg:before {\n content: "\\F1A6";\n}\n.fa-pied-piper-pp:before {\n content: "\\F1A7";\n}\n.fa-pied-piper-alt:before {\n content: "\\F1A8";\n}\n.fa-drupal:before {\n content: "\\F1A9";\n}\n.fa-joomla:before {\n content: "\\F1AA";\n}\n.fa-language:before {\n content: "\\F1AB";\n}\n.fa-fax:before {\n content: "\\F1AC";\n}\n.fa-building:before {\n content: "\\F1AD";\n}\n.fa-child:before {\n content: "\\F1AE";\n}\n.fa-paw:before {\n content: "\\F1B0";\n}\n.fa-spoon:before {\n content: "\\F1B1";\n}\n.fa-cube:before {\n content: "\\F1B2";\n}\n.fa-cubes:before {\n content: "\\F1B3";\n}\n.fa-behance:before {\n content: "\\F1B4";\n}\n.fa-behance-square:before {\n content: "\\F1B5";\n}\n.fa-steam:before {\n content: "\\F1B6";\n}\n.fa-steam-square:before {\n content: "\\F1B7";\n}\n.fa-recycle:before {\n content: "\\F1B8";\n}\n.fa-automobile:before,\n.fa-car:before {\n content: "\\F1B9";\n}\n.fa-cab:before,\n.fa-taxi:before {\n content: "\\F1BA";\n}\n.fa-tree:before {\n content: "\\F1BB";\n}\n.fa-spotify:before {\n content: "\\F1BC";\n}\n.fa-deviantart:before {\n content: "\\F1BD";\n}\n.fa-soundcloud:before {\n content: "\\F1BE";\n}\n.fa-database:before {\n content: "\\F1C0";\n}\n.fa-file-pdf-o:before {\n content: "\\F1C1";\n}\n.fa-file-word-o:before {\n content: "\\F1C2";\n}\n.fa-file-excel-o:before {\n content: "\\F1C3";\n}\n.fa-file-powerpoint-o:before {\n content: "\\F1C4";\n}\n.fa-file-photo-o:before,\n.fa-file-picture-o:before,\n.fa-file-image-o:before {\n content: "\\F1C5";\n}\n.fa-file-zip-o:before,\n.fa-file-archive-o:before {\n content: "\\F1C6";\n}\n.fa-file-sound-o:before,\n.fa-file-audio-o:before {\n content: "\\F1C7";\n}\n.fa-file-movie-o:before,\n.fa-file-video-o:before {\n content: "\\F1C8";\n}\n.fa-file-code-o:before {\n content: "\\F1C9";\n}\n.fa-vine:before {\n content: "\\F1CA";\n}\n.fa-codepen:before {\n content: "\\F1CB";\n}\n.fa-jsfiddle:before {\n content: "\\F1CC";\n}\n.fa-life-bouy:before,\n.fa-life-buoy:before,\n.fa-life-saver:before,\n.fa-support:before,\n.fa-life-ring:before {\n content: "\\F1CD";\n}\n.fa-circle-o-notch:before {\n content: "\\F1CE";\n}\n.fa-ra:before,\n.fa-resistance:before,\n.fa-rebel:before {\n content: "\\F1D0";\n}\n.fa-ge:before,\n.fa-empire:before {\n content: "\\F1D1";\n}\n.fa-git-square:before {\n content: "\\F1D2";\n}\n.fa-git:before {\n content: "\\F1D3";\n}\n.fa-y-combinator-square:before,\n.fa-yc-square:before,\n.fa-hacker-news:before {\n content: "\\F1D4";\n}\n.fa-tencent-weibo:before {\n content: "\\F1D5";\n}\n.fa-qq:before {\n content: "\\F1D6";\n}\n.fa-wechat:before,\n.fa-weixin:before {\n content: "\\F1D7";\n}\n.fa-send:before,\n.fa-paper-plane:before {\n content: "\\F1D8";\n}\n.fa-send-o:before,\n.fa-paper-plane-o:before {\n content: "\\F1D9";\n}\n.fa-history:before {\n content: "\\F1DA";\n}\n.fa-circle-thin:before {\n content: "\\F1DB";\n}\n.fa-header:before {\n content: "\\F1DC";\n}\n.fa-paragraph:before {\n content: "\\F1DD";\n}\n.fa-sliders:before {\n content: "\\F1DE";\n}\n.fa-share-alt:before {\n content: "\\F1E0";\n}\n.fa-share-alt-square:before {\n content: "\\F1E1";\n}\n.fa-bomb:before {\n content: "\\F1E2";\n}\n.fa-soccer-ball-o:before,\n.fa-futbol-o:before {\n content: "\\F1E3";\n}\n.fa-tty:before {\n content: "\\F1E4";\n}\n.fa-binoculars:before {\n content: "\\F1E5";\n}\n.fa-plug:before {\n content: "\\F1E6";\n}\n.fa-slideshare:before {\n content: "\\F1E7";\n}\n.fa-twitch:before {\n content: "\\F1E8";\n}\n.fa-yelp:before {\n content: "\\F1E9";\n}\n.fa-newspaper-o:before {\n content: "\\F1EA";\n}\n.fa-wifi:before {\n content: "\\F1EB";\n}\n.fa-calculator:before {\n content: "\\F1EC";\n}\n.fa-paypal:before {\n content: "\\F1ED";\n}\n.fa-google-wallet:before {\n content: "\\F1EE";\n}\n.fa-cc-visa:before {\n content: "\\F1F0";\n}\n.fa-cc-mastercard:before {\n content: "\\F1F1";\n}\n.fa-cc-discover:before {\n content: "\\F1F2";\n}\n.fa-cc-amex:before {\n content: "\\F1F3";\n}\n.fa-cc-paypal:before {\n content: "\\F1F4";\n}\n.fa-cc-stripe:before {\n content: "\\F1F5";\n}\n.fa-bell-slash:before {\n content: "\\F1F6";\n}\n.fa-bell-slash-o:before {\n content: "\\F1F7";\n}\n.fa-trash:before {\n content: "\\F1F8";\n}\n.fa-copyright:before {\n content: "\\F1F9";\n}\n.fa-at:before {\n content: "\\F1FA";\n}\n.fa-eyedropper:before {\n content: "\\F1FB";\n}\n.fa-paint-brush:before {\n content: "\\F1FC";\n}\n.fa-birthday-cake:before {\n content: "\\F1FD";\n}\n.fa-area-chart:before {\n content: "\\F1FE";\n}\n.fa-pie-chart:before {\n content: "\\F200";\n}\n.fa-line-chart:before {\n content: "\\F201";\n}\n.fa-lastfm:before {\n content: "\\F202";\n}\n.fa-lastfm-square:before {\n content: "\\F203";\n}\n.fa-toggle-off:before {\n content: "\\F204";\n}\n.fa-toggle-on:before {\n content: "\\F205";\n}\n.fa-bicycle:before {\n content: "\\F206";\n}\n.fa-bus:before {\n content: "\\F207";\n}\n.fa-ioxhost:before {\n content: "\\F208";\n}\n.fa-angellist:before {\n content: "\\F209";\n}\n.fa-cc:before {\n content: "\\F20A";\n}\n.fa-shekel:before,\n.fa-sheqel:before,\n.fa-ils:before {\n content: "\\F20B";\n}\n.fa-meanpath:before {\n content: "\\F20C";\n}\n.fa-buysellads:before {\n content: "\\F20D";\n}\n.fa-connectdevelop:before {\n content: "\\F20E";\n}\n.fa-dashcube:before {\n content: "\\F210";\n}\n.fa-forumbee:before {\n content: "\\F211";\n}\n.fa-leanpub:before {\n content: "\\F212";\n}\n.fa-sellsy:before {\n content: "\\F213";\n}\n.fa-shirtsinbulk:before {\n content: "\\F214";\n}\n.fa-simplybuilt:before {\n content: "\\F215";\n}\n.fa-skyatlas:before {\n content: "\\F216";\n}\n.fa-cart-plus:before {\n content: "\\F217";\n}\n.fa-cart-arrow-down:before {\n content: "\\F218";\n}\n.fa-diamond:before {\n content: "\\F219";\n}\n.fa-ship:before {\n content: "\\F21A";\n}\n.fa-user-secret:before {\n content: "\\F21B";\n}\n.fa-motorcycle:before {\n content: "\\F21C";\n}\n.fa-street-view:before {\n content: "\\F21D";\n}\n.fa-heartbeat:before {\n content: "\\F21E";\n}\n.fa-venus:before {\n content: "\\F221";\n}\n.fa-mars:before {\n content: "\\F222";\n}\n.fa-mercury:before {\n content: "\\F223";\n}\n.fa-intersex:before,\n.fa-transgender:before {\n content: "\\F224";\n}\n.fa-transgender-alt:before {\n content: "\\F225";\n}\n.fa-venus-double:before {\n content: "\\F226";\n}\n.fa-mars-double:before {\n content: "\\F227";\n}\n.fa-venus-mars:before {\n content: "\\F228";\n}\n.fa-mars-stroke:before {\n content: "\\F229";\n}\n.fa-mars-stroke-v:before {\n content: "\\F22A";\n}\n.fa-mars-stroke-h:before {\n content: "\\F22B";\n}\n.fa-neuter:before {\n content: "\\F22C";\n}\n.fa-genderless:before {\n content: "\\F22D";\n}\n.fa-facebook-official:before {\n content: "\\F230";\n}\n.fa-pinterest-p:before {\n content: "\\F231";\n}\n.fa-whatsapp:before {\n content: "\\F232";\n}\n.fa-server:before {\n content: "\\F233";\n}\n.fa-user-plus:before {\n content: "\\F234";\n}\n.fa-user-times:before {\n content: "\\F235";\n}\n.fa-hotel:before,\n.fa-bed:before {\n content: "\\F236";\n}\n.fa-viacoin:before {\n content: "\\F237";\n}\n.fa-train:before {\n content: "\\F238";\n}\n.fa-subway:before {\n content: "\\F239";\n}\n.fa-medium:before {\n content: "\\F23A";\n}\n.fa-yc:before,\n.fa-y-combinator:before {\n content: "\\F23B";\n}\n.fa-optin-monster:before {\n content: "\\F23C";\n}\n.fa-opencart:before {\n content: "\\F23D";\n}\n.fa-expeditedssl:before {\n content: "\\F23E";\n}\n.fa-battery-4:before,\n.fa-battery:before,\n.fa-battery-full:before {\n content: "\\F240";\n}\n.fa-battery-3:before,\n.fa-battery-three-quarters:before {\n content: "\\F241";\n}\n.fa-battery-2:before,\n.fa-battery-half:before {\n content: "\\F242";\n}\n.fa-battery-1:before,\n.fa-battery-quarter:before {\n content: "\\F243";\n}\n.fa-battery-0:before,\n.fa-battery-empty:before {\n content: "\\F244";\n}\n.fa-mouse-pointer:before {\n content: "\\F245";\n}\n.fa-i-cursor:before {\n content: "\\F246";\n}\n.fa-object-group:before {\n content: "\\F247";\n}\n.fa-object-ungroup:before {\n content: "\\F248";\n}\n.fa-sticky-note:before {\n content: "\\F249";\n}\n.fa-sticky-note-o:before {\n content: "\\F24A";\n}\n.fa-cc-jcb:before {\n content: "\\F24B";\n}\n.fa-cc-diners-club:before {\n content: "\\F24C";\n}\n.fa-clone:before {\n content: "\\F24D";\n}\n.fa-balance-scale:before {\n content: "\\F24E";\n}\n.fa-hourglass-o:before {\n content: "\\F250";\n}\n.fa-hourglass-1:before,\n.fa-hourglass-start:before {\n content: "\\F251";\n}\n.fa-hourglass-2:before,\n.fa-hourglass-half:before {\n content: "\\F252";\n}\n.fa-hourglass-3:before,\n.fa-hourglass-end:before {\n content: "\\F253";\n}\n.fa-hourglass:before {\n content: "\\F254";\n}\n.fa-hand-grab-o:before,\n.fa-hand-rock-o:before {\n content: "\\F255";\n}\n.fa-hand-stop-o:before,\n.fa-hand-paper-o:before {\n content: "\\F256";\n}\n.fa-hand-scissors-o:before {\n content: "\\F257";\n}\n.fa-hand-lizard-o:before {\n content: "\\F258";\n}\n.fa-hand-spock-o:before {\n content: "\\F259";\n}\n.fa-hand-pointer-o:before {\n content: "\\F25A";\n}\n.fa-hand-peace-o:before {\n content: "\\F25B";\n}\n.fa-trademark:before {\n content: "\\F25C";\n}\n.fa-registered:before {\n content: "\\F25D";\n}\n.fa-creative-commons:before {\n content: "\\F25E";\n}\n.fa-gg:before {\n content: "\\F260";\n}\n.fa-gg-circle:before {\n content: "\\F261";\n}\n.fa-tripadvisor:before {\n content: "\\F262";\n}\n.fa-odnoklassniki:before {\n content: "\\F263";\n}\n.fa-odnoklassniki-square:before {\n content: "\\F264";\n}\n.fa-get-pocket:before {\n content: "\\F265";\n}\n.fa-wikipedia-w:before {\n content: "\\F266";\n}\n.fa-safari:before {\n content: "\\F267";\n}\n.fa-chrome:before {\n content: "\\F268";\n}\n.fa-firefox:before {\n content: "\\F269";\n}\n.fa-opera:before {\n content: "\\F26A";\n}\n.fa-internet-explorer:before {\n content: "\\F26B";\n}\n.fa-tv:before,\n.fa-television:before {\n content: "\\F26C";\n}\n.fa-contao:before {\n content: "\\F26D";\n}\n.fa-500px:before {\n content: "\\F26E";\n}\n.fa-amazon:before {\n content: "\\F270";\n}\n.fa-calendar-plus-o:before {\n content: "\\F271";\n}\n.fa-calendar-minus-o:before {\n content: "\\F272";\n}\n.fa-calendar-times-o:before {\n content: "\\F273";\n}\n.fa-calendar-check-o:before {\n content: "\\F274";\n}\n.fa-industry:before {\n content: "\\F275";\n}\n.fa-map-pin:before {\n content: "\\F276";\n}\n.fa-map-signs:before {\n content: "\\F277";\n}\n.fa-map-o:before {\n content: "\\F278";\n}\n.fa-map:before {\n content: "\\F279";\n}\n.fa-commenting:before {\n content: "\\F27A";\n}\n.fa-commenting-o:before {\n content: "\\F27B";\n}\n.fa-houzz:before {\n content: "\\F27C";\n}\n.fa-vimeo:before {\n content: "\\F27D";\n}\n.fa-black-tie:before {\n content: "\\F27E";\n}\n.fa-fonticons:before {\n content: "\\F280";\n}\n.fa-reddit-alien:before {\n content: "\\F281";\n}\n.fa-edge:before {\n content: "\\F282";\n}\n.fa-credit-card-alt:before {\n content: "\\F283";\n}\n.fa-codiepie:before {\n content: "\\F284";\n}\n.fa-modx:before {\n content: "\\F285";\n}\n.fa-fort-awesome:before {\n content: "\\F286";\n}\n.fa-usb:before {\n content: "\\F287";\n}\n.fa-product-hunt:before {\n content: "\\F288";\n}\n.fa-mixcloud:before {\n content: "\\F289";\n}\n.fa-scribd:before {\n content: "\\F28A";\n}\n.fa-pause-circle:before {\n content: "\\F28B";\n}\n.fa-pause-circle-o:before {\n content: "\\F28C";\n}\n.fa-stop-circle:before {\n content: "\\F28D";\n}\n.fa-stop-circle-o:before {\n content: "\\F28E";\n}\n.fa-shopping-bag:before {\n content: "\\F290";\n}\n.fa-shopping-basket:before {\n content: "\\F291";\n}\n.fa-hashtag:before {\n content: "\\F292";\n}\n.fa-bluetooth:before {\n content: "\\F293";\n}\n.fa-bluetooth-b:before {\n content: "\\F294";\n}\n.fa-percent:before {\n content: "\\F295";\n}\n.fa-gitlab:before {\n content: "\\F296";\n}\n.fa-wpbeginner:before {\n content: "\\F297";\n}\n.fa-wpforms:before {\n content: "\\F298";\n}\n.fa-envira:before {\n content: "\\F299";\n}\n.fa-universal-access:before {\n content: "\\F29A";\n}\n.fa-wheelchair-alt:before {\n content: "\\F29B";\n}\n.fa-question-circle-o:before {\n content: "\\F29C";\n}\n.fa-blind:before {\n content: "\\F29D";\n}\n.fa-audio-description:before {\n content: "\\F29E";\n}\n.fa-volume-control-phone:before {\n content: "\\F2A0";\n}\n.fa-braille:before {\n content: "\\F2A1";\n}\n.fa-assistive-listening-systems:before {\n content: "\\F2A2";\n}\n.fa-asl-interpreting:before,\n.fa-american-sign-language-interpreting:before {\n content: "\\F2A3";\n}\n.fa-deafness:before,\n.fa-hard-of-hearing:before,\n.fa-deaf:before {\n content: "\\F2A4";\n}\n.fa-glide:before {\n content: "\\F2A5";\n}\n.fa-glide-g:before {\n content: "\\F2A6";\n}\n.fa-signing:before,\n.fa-sign-language:before {\n content: "\\F2A7";\n}\n.fa-low-vision:before {\n content: "\\F2A8";\n}\n.fa-viadeo:before {\n content: "\\F2A9";\n}\n.fa-viadeo-square:before {\n content: "\\F2AA";\n}\n.fa-snapchat:before {\n content: "\\F2AB";\n}\n.fa-snapchat-ghost:before {\n content: "\\F2AC";\n}\n.fa-snapchat-square:before {\n content: "\\F2AD";\n}\n.fa-pied-piper:before {\n content: "\\F2AE";\n}\n.fa-first-order:before {\n content: "\\F2B0";\n}\n.fa-yoast:before {\n content: "\\F2B1";\n}\n.fa-themeisle:before {\n content: "\\F2B2";\n}\n.fa-google-plus-circle:before,\n.fa-google-plus-official:before {\n content: "\\F2B3";\n}\n.fa-fa:before,\n.fa-font-awesome:before {\n content: "\\F2B4";\n}\n.fa-handshake-o:before {\n content: "\\F2B5";\n}\n.fa-envelope-open:before {\n content: "\\F2B6";\n}\n.fa-envelope-open-o:before {\n content: "\\F2B7";\n}\n.fa-linode:before {\n content: "\\F2B8";\n}\n.fa-address-book:before {\n content: "\\F2B9";\n}\n.fa-address-book-o:before {\n content: "\\F2BA";\n}\n.fa-vcard:before,\n.fa-address-card:before {\n content: "\\F2BB";\n}\n.fa-vcard-o:before,\n.fa-address-card-o:before {\n content: "\\F2BC";\n}\n.fa-user-circle:before {\n content: "\\F2BD";\n}\n.fa-user-circle-o:before {\n content: "\\F2BE";\n}\n.fa-user-o:before {\n content: "\\F2C0";\n}\n.fa-id-badge:before {\n content: "\\F2C1";\n}\n.fa-drivers-license:before,\n.fa-id-card:before {\n content: "\\F2C2";\n}\n.fa-drivers-license-o:before,\n.fa-id-card-o:before {\n content: "\\F2C3";\n}\n.fa-quora:before {\n content: "\\F2C4";\n}\n.fa-free-code-camp:before {\n content: "\\F2C5";\n}\n.fa-telegram:before {\n content: "\\F2C6";\n}\n.fa-thermometer-4:before,\n.fa-thermometer:before,\n.fa-thermometer-full:before {\n content: "\\F2C7";\n}\n.fa-thermometer-3:before,\n.fa-thermometer-three-quarters:before {\n content: "\\F2C8";\n}\n.fa-thermometer-2:before,\n.fa-thermometer-half:before {\n content: "\\F2C9";\n}\n.fa-thermometer-1:before,\n.fa-thermometer-quarter:before {\n content: "\\F2CA";\n}\n.fa-thermometer-0:before,\n.fa-thermometer-empty:before {\n content: "\\F2CB";\n}\n.fa-shower:before {\n content: "\\F2CC";\n}\n.fa-bathtub:before,\n.fa-s15:before,\n.fa-bath:before {\n content: "\\F2CD";\n}\n.fa-podcast:before {\n content: "\\F2CE";\n}\n.fa-window-maximize:before {\n content: "\\F2D0";\n}\n.fa-window-minimize:before {\n content: "\\F2D1";\n}\n.fa-window-restore:before {\n content: "\\F2D2";\n}\n.fa-times-rectangle:before,\n.fa-window-close:before {\n content: "\\F2D3";\n}\n.fa-times-rectangle-o:before,\n.fa-window-close-o:before {\n content: "\\F2D4";\n}\n.fa-bandcamp:before {\n content: "\\F2D5";\n}\n.fa-grav:before {\n content: "\\F2D6";\n}\n.fa-etsy:before {\n content: "\\F2D7";\n}\n.fa-imdb:before {\n content: "\\F2D8";\n}\n.fa-ravelry:before {\n content: "\\F2D9";\n}\n.fa-eercast:before {\n content: "\\F2DA";\n}\n.fa-microchip:before {\n content: "\\F2DB";\n}\n.fa-snowflake-o:before {\n content: "\\F2DC";\n}\n.fa-superpowers:before {\n content: "\\F2DD";\n}\n.fa-wpexplorer:before {\n content: "\\F2DE";\n}\n.fa-meetup:before {\n content: "\\F2E0";\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n', "" ]);
+}, function(module, exports) {
+ module.exports = function(url) {
+ return "string" != typeof url ? url : (/^['"].*['"]$/.test(url) && (url = url.slice(1, -1)),
+ /["'() \t\n]/.test(url) ? '"' + url.replace(/"/g, '\\"').replace(/\n/g, "\\n") + '"' : url);
+ };
}, function(module, exports) {
function cssWithMappingToString(item, useSourceMap) {
var content = item[1] || "", cssMapping = item[3];
@@ -35090,7 +30827,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}(function(target) {
return document.querySelector(target);
- }), singleton = null, singletonCounter = 0, stylesInsertedAtTop = [], fixUrls = __webpack_require__(825);
+ }), singleton = null, singletonCounter = 0, stylesInsertedAtTop = [], fixUrls = __webpack_require__(504);
module.exports = function(list, options) {
if ("undefined" != typeof DEBUG && DEBUG && "object" != typeof document) throw new Error("The style-loader cannot be used in a non-browser environment");
options = options || {}, options.attrs = "object" == typeof options.attrs ? options.attrs : {},
@@ -35184,12 +30921,12 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _react = __webpack_require__(1), React = function(obj) {
+ }(), _react = __webpack_require__(0), React = function(obj) {
if (obj && obj.__esModule) return obj;
var newObj = {};
if (null != obj) for (var key in obj) Object.prototype.hasOwnProperty.call(obj, key) && (newObj[key] = obj[key]);
return newObj.default = obj, newObj;
- }(_react), _propTypes = __webpack_require__(2), _propTypes2 = function(obj) {
+ }(_react), _propTypes = __webpack_require__(1), _propTypes2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -35272,12 +31009,12 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _react = __webpack_require__(1), React = function(obj) {
+ }(), _react = __webpack_require__(0), React = function(obj) {
if (obj && obj.__esModule) return obj;
var newObj = {};
if (null != obj) for (var key in obj) Object.prototype.hasOwnProperty.call(obj, key) && (newObj[key] = obj[key]);
return newObj.default = obj, newObj;
- }(_react), _propTypes = __webpack_require__(2), _propTypes2 = function(obj) {
+ }(_react), _propTypes = __webpack_require__(1), _propTypes2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -35342,13 +31079,21 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _Home = __webpack_require__(829), _Home2 = _interopRequireDefault(_Home), _Common = __webpack_require__(150), styles = function(theme) {
+ }(), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _common = __webpack_require__(61), _Footer = __webpack_require__(508), _Footer2 = _interopRequireDefault(_Footer), styles = {
+ wrapper: {
+ display: "flex",
+ flexDirection: "column",
+ width: "100%"
+ },
+ content: {
+ flex: 1,
+ overflow: "auto"
+ }
+ }, themeStyles = function(theme) {
return {
content: {
- flexGrow: 1,
backgroundColor: theme.palette.background.default,
- padding: 3 * theme.spacing.unit,
- overflow: "auto"
+ padding: 3 * theme.spacing.unit
}
};
}, Main = function(_Component) {
@@ -35360,22 +31105,15 @@ var _publicBundleJs = []byte(`!function(modules) {
value: function() {
var _props = this.props, classes = _props.classes, active = _props.active, content = _props.content, shouldUpdate = _props.shouldUpdate, children = null;
switch (active) {
- case _Common.MENU.get("home").id:
- children = _react2.default.createElement(_Home2.default, {
- memory: content.home.memory,
- traffic: content.home.traffic,
- shouldUpdate: shouldUpdate
- });
- break;
-
- case _Common.MENU.get("chain").id:
- case _Common.MENU.get("txpool").id:
- case _Common.MENU.get("network").id:
- case _Common.MENU.get("system").id:
+ case _common.MENU.get("home").id:
+ case _common.MENU.get("chain").id:
+ case _common.MENU.get("txpool").id:
+ case _common.MENU.get("network").id:
+ case _common.MENU.get("system").id:
children = _react2.default.createElement("div", null, "Work in progress.");
break;
- case _Common.MENU.get("logs").id:
+ case _common.MENU.get("logs").id:
children = _react2.default.createElement("div", null, content.logs.log.map(function(log, index) {
return _react2.default.createElement("div", {
key: index
@@ -35383,12 +31121,18 @@ var _publicBundleJs = []byte(`!function(modules) {
}));
}
return _react2.default.createElement("div", {
- className: classes.content
- }, children);
+ style: styles.wrapper
+ }, _react2.default.createElement("div", {
+ className: classes.content,
+ style: styles.content
+ }, children), _react2.default.createElement(_Footer2.default, {
+ content: content,
+ shouldUpdate: shouldUpdate
+ }));
}
} ]), Main;
}(_react.Component);
- exports.default = (0, _withStyles2.default)(styles)(Main);
+ exports.default = (0, _withStyles2.default)(themeStyles)(Main);
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -35396,6 +31140,13 @@ var _publicBundleJs = []byte(`!function(modules) {
default: obj
};
}
+ function _toConsumableArray(arr) {
+ if (Array.isArray(arr)) {
+ for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
+ return arr2;
+ }
+ return Array.from(arr);
+ }
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
}
@@ -35429,75 +31180,1038 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _withTheme = __webpack_require__(361), _withTheme2 = _interopRequireDefault(_withTheme), _recharts = __webpack_require__(362), _ChartGrid = __webpack_require__(1111), _ChartGrid2 = _interopRequireDefault(_ChartGrid), Home = function(_Component) {
- function Home(props) {
- _classCallCheck(this, Home);
- var _this = _possibleConstructorReturn(this, (Home.__proto__ || Object.getPrototypeOf(Home)).call(this, props)), theme = props.theme;
- return _this.memoryColor = theme.palette.primary[300], _this.trafficColor = theme.palette.secondary[300],
- _this;
+ }(), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _Typography = __webpack_require__(109), _Typography2 = _interopRequireDefault(_Typography), _Grid = __webpack_require__(241), _Grid2 = _interopRequireDefault(_Grid), _recharts = __webpack_require__(524), _ChartRow = __webpack_require__(804), _ChartRow2 = _interopRequireDefault(_ChartRow), _CustomTooltip = __webpack_require__(805), _CustomTooltip2 = _interopRequireDefault(_CustomTooltip), _common = __webpack_require__(61), styles = {
+ footer: {
+ maxWidth: "100%",
+ flexWrap: "nowrap",
+ margin: 0
+ },
+ chartRowWrapper: {
+ height: "100%",
+ padding: 0
+ },
+ doubleChartWrapper: {
+ height: "100%",
+ width: "99%",
+ paddingTop: 5
}
- return _inherits(Home, _Component), _createClass(Home, [ {
+ }, themeStyles = function(theme) {
+ return {
+ footer: {
+ backgroundColor: theme.palette.background.appBar,
+ color: theme.palette.getContrastText(theme.palette.background.appBar),
+ zIndex: theme.zIndex.appBar,
+ height: 10 * theme.spacing.unit
+ }
+ };
+ }, Footer = function(_Component) {
+ function Footer() {
+ var _ref, _temp, _this, _ret;
+ _classCallCheck(this, Footer);
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) args[_key] = arguments[_key];
+ return _temp = _this = _possibleConstructorReturn(this, (_ref = Footer.__proto__ || Object.getPrototypeOf(Footer)).call.apply(_ref, [ this ].concat(args))),
+ _this.info = function(about, value) {
+ return value ? _react2.default.createElement(_Typography2.default, {
+ type: "caption",
+ color: "inherit"
+ }, _react2.default.createElement("span", {
+ style: _common.styles.light
+ }, about), " ", value) : null;
+ }, _this.doubleChart = function(syncId, topChart, bottomChart) {
+ for (var topDefault = topChart.default ? topChart.default : 0, bottomDefault = bottomChart.default ? bottomChart.default : 0, topTooltip = topChart.tooltip ? _react2.default.createElement(_recharts.Tooltip, {
+ cursor: !1,
+ content: _react2.default.createElement(_CustomTooltip2.default, {
+ tooltip: topChart.tooltip
+ })
+ }) : null, bottomTooltip = bottomChart.tooltip ? _react2.default.createElement(_recharts.Tooltip, {
+ cursor: !1,
+ content: _react2.default.createElement(_CustomTooltip2.default, {
+ tooltip: bottomChart.tooltip
+ })
+ }) : null, data = [].concat(_toConsumableArray(topChart.data.map(function(_ref2) {
+ var value = _ref2.value, d = {};
+ return d.topKey = value || topDefault, d;
+ }))), i = 0; i < data.length && i < bottomChart.data.length; i++) {
+ var d = bottomChart.data[i];
+ data[i].bottomKey = d && d.value ? -d.value : bottomDefault;
+ }
+ return data = [].concat(_toConsumableArray(data), _toConsumableArray(bottomChart.data.slice(data.length).map(function(_ref3) {
+ var value = _ref3.value, d = {};
+ return d.topKey = topDefault, d.bottomKey = -value || bottomDefault, d;
+ }))), _react2.default.createElement("div", {
+ style: styles.doubleChartWrapper
+ }, _react2.default.createElement(_recharts.ResponsiveContainer, {
+ width: "100%",
+ height: "50%"
+ }, _react2.default.createElement(_recharts.AreaChart, {
+ data: data,
+ syncId: syncId
+ }, topTooltip, _react2.default.createElement(_recharts.Area, {
+ type: "monotone",
+ dataKey: "topKey",
+ stroke: "#8884d8",
+ fill: "#8884d8"
+ }))), _react2.default.createElement("div", {
+ style: {
+ marginTop: -10,
+ width: "100%",
+ height: "50%"
+ }
+ }, _react2.default.createElement(_recharts.ResponsiveContainer, {
+ width: "100%",
+ height: "100%"
+ }, _react2.default.createElement(_recharts.AreaChart, {
+ data: data,
+ syncId: syncId
+ }, bottomTooltip, _react2.default.createElement(_recharts.Area, {
+ type: "monotone",
+ dataKey: "bottomKey",
+ stroke: "#82ca9d",
+ fill: "#82ca9d"
+ })))));
+ }, _ret = _temp, _possibleConstructorReturn(_this, _ret);
+ }
+ return _inherits(Footer, _Component), _createClass(Footer, [ {
key: "shouldComponentUpdate",
value: function(nextProps) {
- return nextProps.shouldUpdate.has("memory") || nextProps.shouldUpdate.has("traffic");
+ return void 0 !== nextProps.shouldUpdate.home;
}
}, {
key: "render",
value: function() {
- var _props = this.props, memory = _props.memory, traffic = _props.traffic;
- return _react2.default.createElement(_ChartGrid2.default, {
- spacing: 24
- }, _react2.default.createElement(_recharts.AreaChart, {
- xs: 6,
- height: 300,
- values: memory
- }, _react2.default.createElement(_recharts.YAxis, null), _react2.default.createElement(_recharts.Area, {
- type: "monotone",
- dataKey: "value",
- stroke: this.memoryColor,
- fill: this.memoryColor
- })), _react2.default.createElement(_recharts.LineChart, {
- xs: 6,
- height: 300,
- values: traffic
- }, _react2.default.createElement(_recharts.Line, {
- type: "monotone",
- dataKey: "value",
- stroke: this.trafficColor,
- dot: !1
- })), _react2.default.createElement(_recharts.LineChart, {
- xs: 6,
- height: 300,
- values: memory
- }, _react2.default.createElement(_recharts.YAxis, null), _react2.default.createElement(_recharts.CartesianGrid, {
- stroke: "#eee",
- strokeDasharray: "5 5"
- }), _react2.default.createElement(_recharts.Line, {
- type: "monotone",
- dataKey: "value",
- stroke: this.memoryColor,
- dot: !1
- })), _react2.default.createElement(_recharts.AreaChart, {
- xs: 6,
- height: 300,
- values: traffic
- }, _react2.default.createElement(_recharts.CartesianGrid, {
- stroke: "#eee",
- strokeDasharray: "5 5",
- vertical: !1
- }), _react2.default.createElement(_recharts.Area, {
- type: "monotone",
- dataKey: "value",
- stroke: this.trafficColor,
- fill: this.trafficColor
- })));
+ var content = this.props.content, general = content.general, home = content.home;
+ return _react2.default.createElement(_Grid2.default, {
+ container: !0,
+ className: this.props.classes.footer,
+ direction: "row",
+ alignItems: "center",
+ style: styles.footer
+ }, _react2.default.createElement(_Grid2.default, {
+ item: !0,
+ xs: !0,
+ style: styles.chartRowWrapper
+ }, _react2.default.createElement(_ChartRow2.default, null, this.doubleChart("all", {
+ data: home.processCPU,
+ tooltip: (0, _CustomTooltip.percentPlotter)("Process")
+ }, {
+ data: home.systemCPU,
+ tooltip: (0, _CustomTooltip.percentPlotter)("System", (0, _CustomTooltip.multiplier)(-1))
+ }), this.doubleChart("all", {
+ data: home.activeMemory,
+ tooltip: (0, _CustomTooltip.bytePlotter)("Active")
+ }, {
+ data: home.virtualMemory,
+ tooltip: (0, _CustomTooltip.bytePlotter)("Virtual", (0, _CustomTooltip.multiplier)(-1))
+ }), this.doubleChart("all", {
+ data: home.diskRead,
+ tooltip: (0, _CustomTooltip.bytePerSecPlotter)("Disk Read")
+ }, {
+ data: home.diskWrite,
+ tooltip: (0, _CustomTooltip.bytePerSecPlotter)("Disk Write", (0, _CustomTooltip.multiplier)(-1))
+ }), this.doubleChart("all", {
+ data: home.networkIngress,
+ tooltip: (0, _CustomTooltip.bytePerSecPlotter)("Download")
+ }, {
+ data: home.networkEgress,
+ tooltip: (0, _CustomTooltip.bytePerSecPlotter)("Upload", (0, _CustomTooltip.multiplier)(-1))
+ }))), _react2.default.createElement(_Grid2.default, {
+ item: !0
+ }, this.info("Geth", general.version), this.info("Commit", general.commit ? general.commit.substring(0, 7) : null)));
}
- } ]), Home;
+ } ]), Footer;
}(_react.Component);
- exports.default = (0, _withTheme2.default)()(Home);
+ exports.default = (0, _withStyles2.default)(themeStyles)(Footer);
+}, function(module, exports, __webpack_require__) {
+ "use strict";
+ (function(process) {
+ function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
+ }
+ function generateGrid(globalStyles, theme, breakpoint) {
+ var styles = (0, _defineProperty3.default)({}, "grid-" + breakpoint, {
+ flexBasis: 0,
+ flexGrow: 1,
+ maxWidth: "100%"
+ });
+ GRID_SIZES.forEach(function(size) {
+ if ("boolean" != typeof size) {
+ var width = Math.round(size / 12 * Math.pow(10, 6)) / Math.pow(10, 4) + "%";
+ styles["grid-" + breakpoint + "-" + size] = {
+ flexBasis: width,
+ maxWidth: width
+ };
+ }
+ }), "xs" === breakpoint ? (0, _extends3.default)(globalStyles, styles) : globalStyles[theme.breakpoints.up(breakpoint)] = styles;
+ }
+ function generateGutter(theme, breakpoint) {
+ var styles = {};
+ return GUTTERS.forEach(function(spacing, index) {
+ 0 !== index && (styles["spacing-" + breakpoint + "-" + spacing] = {
+ margin: -spacing / 2,
+ width: "calc(100% + " + spacing + "px)",
+ "& > $typeItem": {
+ padding: spacing / 2
+ }
+ });
+ }), styles;
+ }
+ function Grid(props) {
+ var _classNames, alignContent = props.alignContent, alignItems = props.alignItems, classes = props.classes, classNameProp = props.className, Component = props.component, container = props.container, direction = props.direction, hidden = props.hidden, item = props.item, justify = props.justify, lg = props.lg, md = props.md, zeroMinWidth = props.zeroMinWidth, sm = props.sm, spacing = props.spacing, wrap = props.wrap, xl = props.xl, xs = props.xs, other = (0,
+ _objectWithoutProperties3.default)(props, [ "alignContent", "alignItems", "classes", "className", "component", "container", "direction", "hidden", "item", "justify", "lg", "md", "zeroMinWidth", "sm", "spacing", "wrap", "xl", "xs" ]), className = (0,
+ _classnames2.default)((_classNames = {}, (0, _defineProperty3.default)(_classNames, classes.typeContainer, container),
+ (0, _defineProperty3.default)(_classNames, classes.typeItem, item), (0, _defineProperty3.default)(_classNames, classes.zeroMinWidth, zeroMinWidth),
+ (0, _defineProperty3.default)(_classNames, classes["spacing-xs-" + String(spacing)], container && 0 !== spacing),
+ (0, _defineProperty3.default)(_classNames, classes["direction-xs-" + String(direction)], direction !== Grid.defaultProps.direction),
+ (0, _defineProperty3.default)(_classNames, classes["wrap-xs-" + String(wrap)], wrap !== Grid.defaultProps.wrap),
+ (0, _defineProperty3.default)(_classNames, classes["align-items-xs-" + String(alignItems)], alignItems !== Grid.defaultProps.alignItems),
+ (0, _defineProperty3.default)(_classNames, classes["align-content-xs-" + String(alignContent)], alignContent !== Grid.defaultProps.alignContent),
+ (0, _defineProperty3.default)(_classNames, classes["justify-xs-" + String(justify)], justify !== Grid.defaultProps.justify),
+ (0, _defineProperty3.default)(_classNames, classes["grid-xs"], !0 === xs), (0, _defineProperty3.default)(_classNames, classes["grid-xs-" + String(xs)], xs && !0 !== xs),
+ (0, _defineProperty3.default)(_classNames, classes["grid-sm"], !0 === sm), (0, _defineProperty3.default)(_classNames, classes["grid-sm-" + String(sm)], sm && !0 !== sm),
+ (0, _defineProperty3.default)(_classNames, classes["grid-md"], !0 === md), (0, _defineProperty3.default)(_classNames, classes["grid-md-" + String(md)], md && !0 !== md),
+ (0, _defineProperty3.default)(_classNames, classes["grid-lg"], !0 === lg), (0, _defineProperty3.default)(_classNames, classes["grid-lg-" + String(lg)], lg && !0 !== lg),
+ (0, _defineProperty3.default)(_classNames, classes["grid-xl"], !0 === xl), (0, _defineProperty3.default)(_classNames, classes["grid-xl-" + String(xl)], xl && !0 !== xl),
+ _classNames), classNameProp), gridProps = (0, _extends3.default)({
+ className: className
+ }, other);
+ return hidden ? _react2.default.createElement(_Hidden2.default, hidden, _react2.default.createElement(Component, gridProps)) : _react2.default.createElement(Component, gridProps);
+ }
+ Object.defineProperty(exports, "__esModule", {
+ value: !0
+ }), exports.styles = void 0;
+ var _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(3), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _createBreakpoints = __webpack_require__(74), _requirePropFactory = __webpack_require__(510), _requirePropFactory2 = _interopRequireDefault(_requirePropFactory), _Hidden = __webpack_require__(511), _Hidden2 = _interopRequireDefault(_Hidden), GUTTERS = [ 0, 8, 16, 24, 40 ], GRID_SIZES = [ !0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ], styles = exports.styles = function(theme) {
+ return (0, _extends3.default)({
+ typeContainer: {
+ boxSizing: "border-box",
+ display: "flex",
+ flexWrap: "wrap",
+ width: "100%"
+ },
+ typeItem: {
+ boxSizing: "border-box",
+ flex: "0 0 auto",
+ margin: "0"
+ },
+ zeroMinWidth: {
+ minWidth: 0
+ },
+ "direction-xs-column": {
+ flexDirection: "column"
+ },
+ "direction-xs-column-reverse": {
+ flexDirection: "column-reverse"
+ },
+ "direction-xs-row-reverse": {
+ flexDirection: "row-reverse"
+ },
+ "wrap-xs-nowrap": {
+ flexWrap: "nowrap"
+ },
+ "wrap-xs-wrap-reverse": {
+ flexWrap: "wrap-reverse"
+ },
+ "align-items-xs-center": {
+ alignItems: "center"
+ },
+ "align-items-xs-flex-start": {
+ alignItems: "flex-start"
+ },
+ "align-items-xs-flex-end": {
+ alignItems: "flex-end"
+ },
+ "align-items-xs-baseline": {
+ alignItems: "baseline"
+ },
+ "align-content-xs-center": {
+ alignContent: "center"
+ },
+ "align-content-xs-flex-start": {
+ alignContent: "flex-start"
+ },
+ "align-content-xs-flex-end": {
+ alignContent: "flex-end"
+ },
+ "align-content-xs-space-between": {
+ alignContent: "space-between"
+ },
+ "align-content-xs-space-around": {
+ alignContent: "space-around"
+ },
+ "justify-xs-center": {
+ justifyContent: "center"
+ },
+ "justify-xs-flex-end": {
+ justifyContent: "flex-end"
+ },
+ "justify-xs-space-between": {
+ justifyContent: "space-between"
+ },
+ "justify-xs-space-around": {
+ justifyContent: "space-around"
+ }
+ }, generateGutter(theme, "xs"), _createBreakpoints.keys.reduce(function(accumulator, key) {
+ return generateGrid(accumulator, theme, key), accumulator;
+ }, {}));
+ };
+ Grid.propTypes = "production" !== process.env.NODE_ENV ? {
+ alignContent: _propTypes2.default.oneOf([ "stretch", "center", "flex-start", "flex-end", "space-between", "space-around" ]),
+ alignItems: _propTypes2.default.oneOf([ "flex-start", "center", "flex-end", "stretch", "baseline" ]),
+ children: _propTypes2.default.node,
+ classes: _propTypes2.default.object.isRequired,
+ className: _propTypes2.default.string,
+ component: _propTypes2.default.oneOfType([ _propTypes2.default.string, _propTypes2.default.func ]),
+ container: _propTypes2.default.bool,
+ direction: _propTypes2.default.oneOf([ "row", "row-reverse", "column", "column-reverse" ]),
+ hidden: _propTypes2.default.object,
+ item: _propTypes2.default.bool,
+ justify: _propTypes2.default.oneOf([ "flex-start", "center", "flex-end", "space-between", "space-around" ]),
+ lg: _propTypes2.default.oneOf([ !0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]),
+ md: _propTypes2.default.oneOf([ !0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]),
+ sm: _propTypes2.default.oneOf([ !0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]),
+ spacing: _propTypes2.default.oneOf(GUTTERS),
+ wrap: _propTypes2.default.oneOf([ "nowrap", "wrap", "wrap-reverse" ]),
+ xl: _propTypes2.default.oneOf([ !0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]),
+ xs: _propTypes2.default.oneOf([ !0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]),
+ zeroMinWidth: _propTypes2.default.bool
+ } : {}, Grid.defaultProps = {
+ alignContent: "stretch",
+ alignItems: "stretch",
+ component: "div",
+ container: !1,
+ direction: "row",
+ item: !1,
+ justify: "flex-start",
+ zeroMinWidth: !1,
+ spacing: 16,
+ wrap: "wrap"
+ };
+ var GridWrapper = Grid;
+ if ("production" !== process.env.NODE_ENV) {
+ GridWrapper = function(props) {
+ return _react2.default.createElement(Grid, props);
+ };
+ var requireProp = (0, _requirePropFactory2.default)("Grid");
+ GridWrapper.propTypes = {
+ alignContent: requireProp("container"),
+ alignItems: requireProp("container"),
+ direction: requireProp("container"),
+ justify: requireProp("container"),
+ lg: requireProp("item"),
+ md: requireProp("item"),
+ sm: requireProp("item"),
+ spacing: requireProp("container"),
+ wrap: requireProp("container"),
+ xs: requireProp("item"),
+ zeroMinWidth: requireProp("zeroMinWidth")
+ };
+ }
+ exports.default = (0, _withStyles2.default)(styles, {
+ name: "MuiGrid"
+ })(GridWrapper);
+ }).call(exports, __webpack_require__(2));
+}, function(module, exports, __webpack_require__) {
+ "use strict";
+ Object.defineProperty(exports, "__esModule", {
+ value: !0
+ });
+ var requirePropFactory = function(componentNameInError) {
+ return function(requiredProp) {
+ return function(props, propName, componentName, location, propFullName) {
+ var propFullNameSafe = propFullName || propName;
+ return void 0 === props[propName] || props[requiredProp] ? null : new Error("The property ` + ("`" + `" + propFullNameSafe + "`))) + (("`" + (` of ` + "`")) + (`" + componentNameInError + "` + ("`" + ` must be used on `)))) + ((("`" + (`" + requiredProp + "` + "`")) + (`.");
+ };
+ };
+ };
+ exports.default = requirePropFactory;
+}, function(module, exports, __webpack_require__) {
+ "use strict";
+ function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
+ }
+ Object.defineProperty(exports, "__esModule", {
+ value: !0
+ });
+ var _Hidden = __webpack_require__(512);
+ Object.defineProperty(exports, "default", {
+ enumerable: !0,
+ get: function() {
+ return _interopRequireDefault(_Hidden).default;
+ }
+ });
+}, function(module, exports, __webpack_require__) {
+ "use strict";
+ (function(process) {
+ function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
+ }
+ function Hidden(props) {
+ var implementation = props.implementation, other = (0, _objectWithoutProperties3.default)(props, [ "implementation" ]);
+ return "js" === implementation ? _react2.default.createElement(_HiddenJs2.default, other) : _react2.default.createElement(_HiddenCss2.default, other);
+ }
+ Object.defineProperty(exports, "__esModule", {
+ value: !0
+ });
+ var _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _HiddenJs = __webpack_require__(513), _HiddenJs2 = _interopRequireDefault(_HiddenJs), _HiddenCss = __webpack_require__(523), _HiddenCss2 = _interopRequireDefault(_HiddenCss);
+ Hidden.propTypes = "production" !== process.env.NODE_ENV ? {
+ children: _propTypes2.default.node,
+ className: _propTypes2.default.string,
+ implementation: _propTypes2.default.oneOf([ "js", "css" ]),
+ initialWidth: _propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ]),
+ lgDown: _propTypes2.default.bool,
+ lgUp: _propTypes2.default.bool,
+ mdDown: _propTypes2.default.bool,
+ mdUp: _propTypes2.default.bool,
+ only: _propTypes2.default.oneOfType([ _propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ]), _propTypes2.default.arrayOf(_propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ])) ]),
+ smDown: _propTypes2.default.bool,
+ smUp: _propTypes2.default.bool,
+ xlDown: _propTypes2.default.bool,
+ xlUp: _propTypes2.default.bool,
+ xsDown: _propTypes2.default.bool,
+ xsUp: _propTypes2.default.bool
+ } : {}, Hidden.defaultProps = {
+ implementation: "js",
+ lgDown: !1,
+ lgUp: !1,
+ mdDown: !1,
+ mdUp: !1,
+ smDown: !1,
+ smUp: !1,
+ xlDown: !1,
+ xlUp: !1,
+ xsDown: !1,
+ xsUp: !1
+ }, exports.default = Hidden;
+ }).call(exports, __webpack_require__(2));
+}, function(module, exports, __webpack_require__) {
+ "use strict";
+ (function(process) {
+ function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
+ }
+ function HiddenJs(props) {
+ var children = props.children, only = (props.lgDown, props.lgUp, props.mdDown, props.mdUp,
+ props.only), width = (props.smDown, props.smUp, props.width), other = (props.xlDown,
+ props.xlUp, props.xsDown, props.xsUp, (0, _objectWithoutProperties3.default)(props, [ "children", "lgDown", "lgUp", "mdDown", "mdUp", "only", "smDown", "smUp", "width", "xlDown", "xlUp", "xsDown", "xsUp" ]));
+ "production" !== process.env.NODE_ENV && (0, _warning2.default)(0 === (0, _keys2.default)(other).length, "Material-UI: unsupported properties received " + (0,
+ _stringify2.default)(other) + " by ` + ("`" + `<Hidden />`))) + (("`" + (`.");
+ var visible = !0;
+ if (only) if (Array.isArray(only)) for (var i = 0; i < only.length; i += 1) {
+ var breakpoint = only[i];
+ if (width === breakpoint) {
+ visible = !1;
+ break;
+ }
+ } else only && width === only && (visible = !1);
+ if (visible) for (var _i = 0; _i < _createBreakpoints.keys.length; _i += 1) {
+ var _breakpoint = _createBreakpoints.keys[_i], breakpointUp = props[_breakpoint + "Up"], breakpointDown = props[_breakpoint + "Down"];
+ if (breakpointUp && (0, _withWidth.isWidthUp)(_breakpoint, width) || breakpointDown && (0,
+ _withWidth.isWidthDown)(_breakpoint, width)) {
+ visible = !1;
+ break;
+ }
+ }
+ return visible ? children : null;
+ }
+ Object.defineProperty(exports, "__esModule", {
+ value: !0
+ });
+ var _stringify = __webpack_require__(514), _stringify2 = _interopRequireDefault(_stringify), _keys = __webpack_require__(41), _keys2 = _interopRequireDefault(_keys), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), _createBreakpoints = __webpack_require__(74), _withWidth = __webpack_require__(516), _withWidth2 = _interopRequireDefault(_withWidth);
+ HiddenJs.propTypes = {
+ children: _propTypes2.default.node,
+ className: _propTypes2.default.string,
+ implementation: _propTypes2.default.oneOf([ "js", "css" ]),
+ initialWidth: _propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ]),
+ lgDown: _propTypes2.default.bool,
+ lgUp: _propTypes2.default.bool,
+ mdDown: _propTypes2.default.bool,
+ mdUp: _propTypes2.default.bool,
+ only: _propTypes2.default.oneOfType([ _propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ]), _propTypes2.default.arrayOf(_propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ])) ]),
+ smDown: _propTypes2.default.bool,
+ smUp: _propTypes2.default.bool,
+ width: _propTypes2.default.string.isRequired,
+ xlDown: _propTypes2.default.bool,
+ xlUp: _propTypes2.default.bool,
+ xsDown: _propTypes2.default.bool,
+ xsUp: _propTypes2.default.bool
+ }, exports.default = (0, _withWidth2.default)()(HiddenJs);
+ }).call(exports, __webpack_require__(2));
+}, function(module, exports, __webpack_require__) {
+ module.exports = {
+ default: __webpack_require__(515),
+ __esModule: !0
+ };
+}, function(module, exports, __webpack_require__) {
+ var core = __webpack_require__(17), $JSON = core.JSON || (core.JSON = {
+ stringify: JSON.stringify
+ });
+ module.exports = function(it) {
+ return $JSON.stringify.apply($JSON, arguments);
+ };
+}, function(module, exports, __webpack_require__) {
+ "use strict";
+ (function(process) {
+ function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
+ }
+ Object.defineProperty(exports, "__esModule", {
+ value: !0
+ }), exports.isWidthDown = exports.isWidthUp = void 0;
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _getPrototypeOf = __webpack_require__(26), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(27), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(28), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(29), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(30), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _reactEventListener = __webpack_require__(517), _reactEventListener2 = _interopRequireDefault(_reactEventListener), _debounce = __webpack_require__(157), _debounce2 = _interopRequireDefault(_debounce), _wrapDisplayName = __webpack_require__(75), _wrapDisplayName2 = _interopRequireDefault(_wrapDisplayName), _hoistNonReactStatics = __webpack_require__(152), _hoistNonReactStatics2 = _interopRequireDefault(_hoistNonReactStatics), _withTheme = __webpack_require__(522), _withTheme2 = _interopRequireDefault(_withTheme), _createBreakpoints = __webpack_require__(74), withWidth = (exports.isWidthUp = function(breakpoint, width) {
+ return arguments.length > 2 && void 0 !== arguments[2] && !arguments[2] ? _createBreakpoints.keys.indexOf(breakpoint) < _createBreakpoints.keys.indexOf(width) : _createBreakpoints.keys.indexOf(breakpoint) <= _createBreakpoints.keys.indexOf(width);
+ }, exports.isWidthDown = function(breakpoint, width) {
+ return arguments.length > 2 && void 0 !== arguments[2] && !arguments[2] ? _createBreakpoints.keys.indexOf(width) < _createBreakpoints.keys.indexOf(breakpoint) : _createBreakpoints.keys.indexOf(width) <= _createBreakpoints.keys.indexOf(breakpoint);
+ }, function() {
+ var options = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
+ return function(Component) {
+ var _options$resizeInterv = options.resizeInterval, resizeInterval = void 0 === _options$resizeInterv ? 166 : _options$resizeInterv, _options$withTheme = options.withTheme, withThemeOption = void 0 !== _options$withTheme && _options$withTheme, WithWidth = function(_React$Component) {
+ function WithWidth() {
+ var _ref, _temp, _this, _ret;
+ (0, _classCallCheck3.default)(this, WithWidth);
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) args[_key] = arguments[_key];
+ return _temp = _this = (0, _possibleConstructorReturn3.default)(this, (_ref = WithWidth.__proto__ || (0,
+ _getPrototypeOf2.default)(WithWidth)).call.apply(_ref, [ this ].concat(args))),
+ _this.state = {
+ width: void 0
+ }, _this.handleResize = (0, _debounce2.default)(function() {
+ _this.updateWidth(window.innerWidth);
+ }, resizeInterval), _ret = _temp, (0, _possibleConstructorReturn3.default)(_this, _ret);
+ }
+ return (0, _inherits3.default)(WithWidth, _React$Component), (0, _createClass3.default)(WithWidth, [ {
+ key: "componentDidMount",
+ value: function() {
+ this.updateWidth(window.innerWidth);
+ }
+ }, {
+ key: "componentWillUnmount",
+ value: function() {
+ this.handleResize.cancel();
+ }
+ }, {
+ key: "updateWidth",
+ value: function(innerWidth) {
+ for (var breakpoints = this.props.theme.breakpoints, width = null, index = 1; null === width && index < _createBreakpoints.keys.length; ) {
+ var currentWidth = _createBreakpoints.keys[index];
+ if (innerWidth < breakpoints.values[currentWidth]) {
+ width = _createBreakpoints.keys[index - 1];
+ break;
+ }
+ index += 1;
+ }
+ (width = width || "xl") !== this.state.width && this.setState({
+ width: width
+ });
+ }
+ }, {
+ key: "render",
+ value: function() {
+ var _props = this.props, initialWidth = _props.initialWidth, theme = _props.theme, width = _props.width, other = (0,
+ _objectWithoutProperties3.default)(_props, [ "initialWidth", "theme", "width" ]), props = (0,
+ _extends3.default)({
+ width: width || this.state.width || initialWidth
+ }, other), more = {};
+ return withThemeOption && (more.theme = theme), void 0 === props.width ? null : _react2.default.createElement(_reactEventListener2.default, {
+ target: "window",
+ onResize: this.handleResize
+ }, _react2.default.createElement(Component, (0, _extends3.default)({}, more, props)));
+ }
+ } ]), WithWidth;
+ }(_react2.default.Component);
+ return WithWidth.propTypes = "production" !== process.env.NODE_ENV ? {
+ initialWidth: _propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ]),
+ theme: _propTypes2.default.object.isRequired,
+ width: _propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ])
+ } : {}, "production" !== process.env.NODE_ENV && (WithWidth.displayName = (0, _wrapDisplayName2.default)(Component, "WithWidth")),
+ (0, _hoistNonReactStatics2.default)(WithWidth, Component), (0, _withTheme2.default)()(WithWidth);
+ };
+ });
+ exports.default = withWidth;
+ }).call(exports, __webpack_require__(2));
+}, function(module, exports, __webpack_require__) {
+ "use strict";
+ (function(process) {
+ function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
+ }
+ function mergeDefaultEventOptions(options) {
+ return (0, _assign2.default)({}, defaultEventOptions, options);
+ }
+ function getEventListenerArgs(eventName, callback, options) {
+ var args = [ eventName, callback ];
+ return args.push(_supports.passiveOption ? options : options.capture), args;
+ }
+ function on(target, eventName, callback, options) {
+ target.addEventListener.apply(target, getEventListenerArgs(eventName, callback, options));
+ }
+ function off(target, eventName, callback, options) {
+ target.removeEventListener.apply(target, getEventListenerArgs(eventName, callback, options));
+ }
+ function forEachListener(props, iteratee) {
+ var eventProps = (props.children, props.target, (0, _objectWithoutProperties3.default)(props, [ "children", "target" ]));
+ (0, _keys2.default)(eventProps).forEach(function(name) {
+ if ("on" === name.substring(0, 2)) {
+ var prop = eventProps[name], type = void 0 === prop ? "undefined" : (0, _typeof3.default)(prop), isObject = "object" === type, isFunction = "function" === type;
+ if (isObject || isFunction) {
+ var capture = "capture" === name.substr(-7).toLowerCase(), eventName = name.substring(2).toLowerCase();
+ eventName = capture ? eventName.substring(0, eventName.length - 7) : eventName,
+ isObject ? iteratee(eventName, prop.handler, prop.options) : iteratee(eventName, prop, mergeDefaultEventOptions({
+ capture: capture
+ }));
+ }
+ }
+ });
+ }
+ function withOptions(handler, options) {
+ return "production" !== process.env.NODE_ENV && (0, _warning2.default)(options, "react-event-listener: should be specified options in withOptions."),
+ {
+ handler: handler,
+ options: mergeDefaultEventOptions(options)
+ };
+ }
+ Object.defineProperty(exports, "__esModule", {
+ value: !0
+ });
+ var _getPrototypeOf = __webpack_require__(26), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(27), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(28), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(29), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(30), _inherits3 = _interopRequireDefault(_inherits2), _typeof2 = __webpack_require__(100), _typeof3 = _interopRequireDefault(_typeof2), _keys = __webpack_require__(41), _keys2 = _interopRequireDefault(_keys), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _assign = __webpack_require__(205), _assign2 = _interopRequireDefault(_assign);
+ exports.withOptions = withOptions;
+ var _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _shallowEqual = __webpack_require__(96), _shallowEqual2 = _interopRequireDefault(_shallowEqual), _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), _supports = __webpack_require__(518), defaultEventOptions = {
+ capture: !1,
+ passive: !1
+ }, EventListener = function(_React$Component) {
+ function EventListener() {
+ return (0, _classCallCheck3.default)(this, EventListener), (0, _possibleConstructorReturn3.default)(this, (EventListener.__proto__ || (0,
+ _getPrototypeOf2.default)(EventListener)).apply(this, arguments));
+ }
+ return (0, _inherits3.default)(EventListener, _React$Component), (0, _createClass3.default)(EventListener, [ {
+ key: "componentDidMount",
+ value: function() {
+ this.addListeners();
+ }
+ }, {
+ key: "shouldComponentUpdate",
+ value: function(nextProps) {
+ return !(0, _shallowEqual2.default)(this.props, nextProps);
+ }
+ }, {
+ key: "componentWillUpdate",
+ value: function() {
+ this.removeListeners();
+ }
+ }, {
+ key: "componentDidUpdate",
+ value: function() {
+ this.addListeners();
+ }
+ }, {
+ key: "componentWillUnmount",
+ value: function() {
+ this.removeListeners();
+ }
+ }, {
+ key: "addListeners",
+ value: function() {
+ this.applyListeners(on);
+ }
+ }, {
+ key: "removeListeners",
+ value: function() {
+ this.applyListeners(off);
+ }
+ }, {
+ key: "applyListeners",
+ value: function(onOrOff) {
+ var target = this.props.target;
+ if (target) {
+ var element = target;
+ "string" == typeof target && (element = window[target]), forEachListener(this.props, onOrOff.bind(null, element));
+ }
+ }
+ }, {
+ key: "render",
+ value: function() {
+ return this.props.children || null;
+ }
+ } ]), EventListener;
+ }(_react2.default.Component);
+ EventListener.propTypes = "production" !== process.env.NODE_ENV ? {
+ children: _propTypes2.default.node,
+ target: _propTypes2.default.oneOfType([ _propTypes2.default.object, _propTypes2.default.string ]).isRequired
+ } : {}, exports.default = EventListener;
+ }).call(exports, __webpack_require__(2));
+}, function(module, exports, __webpack_require__) {
+ "use strict";
+ function defineProperty(object, property, attr) {
+ return (0, _defineProperty2.default)(object, property, attr);
+ }
+ Object.defineProperty(exports, "__esModule", {
+ value: !0
+ }), exports.passiveOption = void 0;
+ var _defineProperty = __webpack_require__(143), _defineProperty2 = function(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
+ }(_defineProperty);
+ exports.passiveOption = function() {
+ var cache = null;
+ return function() {
+ if (null !== cache) return cache;
+ var supportsPassiveOption = !1;
+ try {
+ window.addEventListener("test", null, defineProperty({}, "passive", {
+ get: function() {
+ supportsPassiveOption = !0;
+ }
+ }));
+ } catch (err) {}
+ return cache = supportsPassiveOption, supportsPassiveOption;
+ }();
+ }();
+ exports.default = {};
+}, function(module, exports, __webpack_require__) {
+ var root = __webpack_require__(32), now = function() {
+ return root.Date.now();
+ };
+ module.exports = now;
+}, function(module, exports, __webpack_require__) {
+ function getRawTag(value) {
+ var isOwn = hasOwnProperty.call(value, symToStringTag), tag = value[symToStringTag];
+ try {
+ value[symToStringTag] = void 0;
+ var unmasked = !0;
+ } catch (e) {}
+ var result = nativeObjectToString.call(value);
+ return unmasked && (isOwn ? value[symToStringTag] = tag : delete value[symToStringTag]),
+ result;
+ }
+ var Symbol = __webpack_require__(77), objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty, nativeObjectToString = objectProto.toString, symToStringTag = Symbol ? Symbol.toStringTag : void 0;
+ module.exports = getRawTag;
+}, function(module, exports) {
+ function objectToString(value) {
+ return nativeObjectToString.call(value);
+ }
+ var objectProto = Object.prototype, nativeObjectToString = objectProto.toString;
+ module.exports = objectToString;
+}, function(module, exports, __webpack_require__) {
+ "use strict";
+ (function(process) {
+ function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
+ }
+ function getDefaultTheme() {
+ return defaultTheme || (defaultTheme = (0, _createMuiTheme2.default)());
+ }
+ Object.defineProperty(exports, "__esModule", {
+ value: !0
+ });
+ var _extends2 = __webpack_require__(7), _extends3 = _interopRequireDefault(_extends2), _getPrototypeOf = __webpack_require__(26), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(27), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(28), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(29), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(30), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _hoistNonReactStatics = __webpack_require__(152), _hoistNonReactStatics2 = _interopRequireDefault(_hoistNonReactStatics), _wrapDisplayName = __webpack_require__(75), _wrapDisplayName2 = _interopRequireDefault(_wrapDisplayName), _createMuiTheme = __webpack_require__(151), _createMuiTheme2 = _interopRequireDefault(_createMuiTheme), _themeListener = __webpack_require__(150), _themeListener2 = _interopRequireDefault(_themeListener), defaultTheme = void 0, withTheme = function() {
+ return function(Component) {
+ var WithTheme = function(_React$Component) {
+ function WithTheme(props, context) {
+ (0, _classCallCheck3.default)(this, WithTheme);
+ var _this = (0, _possibleConstructorReturn3.default)(this, (WithTheme.__proto__ || (0,
+ _getPrototypeOf2.default)(WithTheme)).call(this, props, context));
+ return _this.state = {}, _this.unsubscribeId = null, _this.state = {
+ theme: _themeListener2.default.initial(context) || getDefaultTheme()
+ }, _this;
+ }
+ return (0, _inherits3.default)(WithTheme, _React$Component), (0, _createClass3.default)(WithTheme, [ {
+ key: "componentDidMount",
+ value: function() {
+ var _this2 = this;
+ this.unsubscribeId = _themeListener2.default.subscribe(this.context, function(theme) {
+ _this2.setState({
+ theme: theme
+ });
+ });
+ }
+ }, {
+ key: "componentWillUnmount",
+ value: function() {
+ null !== this.unsubscribeId && _themeListener2.default.unsubscribe(this.context, this.unsubscribeId);
+ }
+ }, {
+ key: "render",
+ value: function() {
+ return _react2.default.createElement(Component, (0, _extends3.default)({
+ theme: this.state.theme
+ }, this.props));
+ }
+ } ]), WithTheme;
+ }(_react2.default.Component);
+ return WithTheme.contextTypes = _themeListener2.default.contextTypes, "production" !== process.env.NODE_ENV && (WithTheme.displayName = (0,
+ _wrapDisplayName2.default)(Component, "WithTheme")), (0, _hoistNonReactStatics2.default)(WithTheme, Component),
+ "production" !== process.env.NODE_ENV && (WithTheme.Naked = Component), WithTheme;
+ };
+ };
+ exports.default = withTheme;
+ }).call(exports, __webpack_require__(2));
+}, function(module, exports, __webpack_require__) {
+ "use strict";
+ (function(process) {
+ function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
+ }
+ function HiddenCss(props) {
+ var children = props.children, classes = props.classes, only = (props.lgDown, props.lgUp,
+ props.mdDown, props.mdUp, props.only), other = (props.smDown, props.smUp, props.xlDown,
+ props.xlUp, props.xsDown, props.xsUp, (0, _objectWithoutProperties3.default)(props, [ "children", "classes", "lgDown", "lgUp", "mdDown", "mdUp", "only", "smDown", "smUp", "xlDown", "xlUp", "xsDown", "xsUp" ]));
+ "production" !== process.env.NODE_ENV && (0, _warning2.default)(0 === (0, _keys2.default)(other).length || 1 === (0,
+ _keys2.default)(other).length && other.hasOwnProperty("ref"), "Material-UI: unsupported properties received " + (0,
+ _keys2.default)(other).join(", ") + " by ` + "`")) + (`<Hidden />` + ("`" + `.");
+ for (var className = [], i = 0; i < _createBreakpoints.keys.length; i += 1) {
+ var breakpoint = _createBreakpoints.keys[i], breakpointUp = props[breakpoint + "Up"], breakpointDown = props[breakpoint + "Down"];
+ breakpointUp && className.push(classes[breakpoint + "Up"]), breakpointDown && className.push(classes[breakpoint + "Down"]);
+ }
+ if (only) {
+ (Array.isArray(only) ? only : [ only ]).forEach(function(breakpoint) {
+ className.push(classes["only" + (0, _helpers.capitalizeFirstLetter)(breakpoint)]);
+ });
+ }
+ return _react2.default.createElement("div", {
+ className: className
+ }, children);
+ }
+ Object.defineProperty(exports, "__esModule", {
+ value: !0
+ });
+ var _keys = __webpack_require__(41), _keys2 = _interopRequireDefault(_keys), _objectWithoutProperties2 = __webpack_require__(6), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _defineProperty2 = __webpack_require__(13), _defineProperty3 = _interopRequireDefault(_defineProperty2), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _warning = __webpack_require__(11), _warning2 = _interopRequireDefault(_warning), _createBreakpoints = __webpack_require__(74), _helpers = __webpack_require__(52), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), styles = function(theme) {
+ var hidden = {
+ display: "none"
+ };
+ return _createBreakpoints.keys.reduce(function(acc, key) {
+ return acc["only" + (0, _helpers.capitalizeFirstLetter)(key)] = (0, _defineProperty3.default)({}, theme.breakpoints.only(key), hidden),
+ acc[key + "Up"] = (0, _defineProperty3.default)({}, theme.breakpoints.up(key), hidden),
+ acc[key + "Down"] = (0, _defineProperty3.default)({}, theme.breakpoints.down(key), hidden),
+ acc;
+ }, {});
+ };
+ HiddenCss.propTypes = "production" !== process.env.NODE_ENV ? {
+ children: _propTypes2.default.node,
+ classes: _propTypes2.default.object.isRequired,
+ className: _propTypes2.default.string,
+ implementation: _propTypes2.default.oneOf([ "js", "css" ]),
+ lgDown: _propTypes2.default.bool,
+ lgUp: _propTypes2.default.bool,
+ mdDown: _propTypes2.default.bool,
+ mdUp: _propTypes2.default.bool,
+ only: _propTypes2.default.oneOfType([ _propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ]), _propTypes2.default.arrayOf(_propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ])) ]),
+ smDown: _propTypes2.default.bool,
+ smUp: _propTypes2.default.bool,
+ xlDown: _propTypes2.default.bool,
+ xlUp: _propTypes2.default.bool,
+ xsDown: _propTypes2.default.bool,
+ xsUp: _propTypes2.default.bool
+ } : {}, exports.default = (0, _withStyles2.default)(styles, {
+ name: "MuiHiddenCss"
+ })(HiddenCss);
+ }).call(exports, __webpack_require__(2));
+}, function(module, __webpack_exports__, __webpack_require__) {
+ "use strict";
+ Object.defineProperty(__webpack_exports__, "__esModule", {
+ value: !0
+ });
+ var __WEBPACK_IMPORTED_MODULE_1__container_Surface__ = (__webpack_require__(525),
+ __webpack_require__(78));
+ __webpack_require__.d(__webpack_exports__, "Surface", function() {
+ return __WEBPACK_IMPORTED_MODULE_1__container_Surface__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_2__container_Layer__ = __webpack_require__(14);
+ __webpack_require__.d(__webpack_exports__, "Layer", function() {
+ return __WEBPACK_IMPORTED_MODULE_2__container_Layer__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_3__component_Legend__ = __webpack_require__(171);
+ __webpack_require__.d(__webpack_exports__, "Legend", function() {
+ return __WEBPACK_IMPORTED_MODULE_3__component_Legend__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_4__component_Tooltip__ = __webpack_require__(122);
+ __webpack_require__.d(__webpack_exports__, "Tooltip", function() {
+ return __WEBPACK_IMPORTED_MODULE_4__component_Tooltip__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_5__component_ResponsiveContainer__ = __webpack_require__(682);
+ __webpack_require__.d(__webpack_exports__, "ResponsiveContainer", function() {
+ return __WEBPACK_IMPORTED_MODULE_5__component_ResponsiveContainer__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_6__component_Cell__ = __webpack_require__(85);
+ __webpack_require__.d(__webpack_exports__, "Cell", function() {
+ return __WEBPACK_IMPORTED_MODULE_6__component_Cell__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_7__component_Text__ = __webpack_require__(55);
+ __webpack_require__.d(__webpack_exports__, "Text", function() {
+ return __WEBPACK_IMPORTED_MODULE_7__component_Text__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_8__component_Label__ = __webpack_require__(43);
+ __webpack_require__.d(__webpack_exports__, "Label", function() {
+ return __WEBPACK_IMPORTED_MODULE_8__component_Label__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_9__component_LabelList__ = __webpack_require__(45);
+ __webpack_require__.d(__webpack_exports__, "LabelList", function() {
+ return __WEBPACK_IMPORTED_MODULE_9__component_LabelList__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_10__shape_Sector__ = __webpack_require__(128);
+ __webpack_require__.d(__webpack_exports__, "Sector", function() {
+ return __WEBPACK_IMPORTED_MODULE_10__shape_Sector__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_11__shape_Curve__ = __webpack_require__(66);
+ __webpack_require__.d(__webpack_exports__, "Curve", function() {
+ return __WEBPACK_IMPORTED_MODULE_11__shape_Curve__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_12__shape_Rectangle__ = __webpack_require__(65);
+ __webpack_require__.d(__webpack_exports__, "Rectangle", function() {
+ return __WEBPACK_IMPORTED_MODULE_12__shape_Rectangle__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_13__shape_Polygon__ = __webpack_require__(195);
+ __webpack_require__.d(__webpack_exports__, "Polygon", function() {
+ return __WEBPACK_IMPORTED_MODULE_13__shape_Polygon__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_14__shape_Dot__ = __webpack_require__(57);
+ __webpack_require__.d(__webpack_exports__, "Dot", function() {
+ return __WEBPACK_IMPORTED_MODULE_14__shape_Dot__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_15__shape_Cross__ = __webpack_require__(323);
+ __webpack_require__.d(__webpack_exports__, "Cross", function() {
+ return __WEBPACK_IMPORTED_MODULE_15__shape_Cross__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_16__shape_Symbols__ = __webpack_require__(172);
+ __webpack_require__.d(__webpack_exports__, "Symbols", function() {
+ return __WEBPACK_IMPORTED_MODULE_16__shape_Symbols__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_17__polar_PolarGrid__ = __webpack_require__(782);
+ __webpack_require__.d(__webpack_exports__, "PolarGrid", function() {
+ return __WEBPACK_IMPORTED_MODULE_17__polar_PolarGrid__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_18__polar_PolarRadiusAxis__ = __webpack_require__(129);
+ __webpack_require__.d(__webpack_exports__, "PolarRadiusAxis", function() {
+ return __WEBPACK_IMPORTED_MODULE_18__polar_PolarRadiusAxis__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_19__polar_PolarAngleAxis__ = __webpack_require__(130);
+ __webpack_require__.d(__webpack_exports__, "PolarAngleAxis", function() {
+ return __WEBPACK_IMPORTED_MODULE_19__polar_PolarAngleAxis__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_20__polar_Pie__ = __webpack_require__(325);
+ __webpack_require__.d(__webpack_exports__, "Pie", function() {
+ return __WEBPACK_IMPORTED_MODULE_20__polar_Pie__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_21__polar_Radar__ = __webpack_require__(326);
+ __webpack_require__.d(__webpack_exports__, "Radar", function() {
+ return __WEBPACK_IMPORTED_MODULE_21__polar_Radar__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_22__polar_RadialBar__ = __webpack_require__(327);
+ __webpack_require__.d(__webpack_exports__, "RadialBar", function() {
+ return __WEBPACK_IMPORTED_MODULE_22__polar_RadialBar__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_23__cartesian_Brush__ = __webpack_require__(328);
+ __webpack_require__.d(__webpack_exports__, "Brush", function() {
+ return __WEBPACK_IMPORTED_MODULE_23__cartesian_Brush__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_24__cartesian_ReferenceLine__ = __webpack_require__(321);
+ __webpack_require__.d(__webpack_exports__, "ReferenceLine", function() {
+ return __WEBPACK_IMPORTED_MODULE_24__cartesian_ReferenceLine__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_25__cartesian_ReferenceDot__ = __webpack_require__(320);
+ __webpack_require__.d(__webpack_exports__, "ReferenceDot", function() {
+ return __WEBPACK_IMPORTED_MODULE_25__cartesian_ReferenceDot__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_26__cartesian_ReferenceArea__ = __webpack_require__(322);
+ __webpack_require__.d(__webpack_exports__, "ReferenceArea", function() {
+ return __WEBPACK_IMPORTED_MODULE_26__cartesian_ReferenceArea__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_27__cartesian_CartesianAxis__ = __webpack_require__(330);
+ __webpack_require__.d(__webpack_exports__, "CartesianAxis", function() {
+ return __WEBPACK_IMPORTED_MODULE_27__cartesian_CartesianAxis__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_28__cartesian_CartesianGrid__ = __webpack_require__(788);
+ __webpack_require__.d(__webpack_exports__, "CartesianGrid", function() {
+ return __WEBPACK_IMPORTED_MODULE_28__cartesian_CartesianGrid__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_29__cartesian_Line__ = __webpack_require__(196);
+ __webpack_require__.d(__webpack_exports__, "Line", function() {
+ return __WEBPACK_IMPORTED_MODULE_29__cartesian_Line__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_30__cartesian_Area__ = __webpack_require__(197);
+ __webpack_require__.d(__webpack_exports__, "Area", function() {
+ return __WEBPACK_IMPORTED_MODULE_30__cartesian_Area__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_31__cartesian_Bar__ = __webpack_require__(198);
+ __webpack_require__.d(__webpack_exports__, "Bar", function() {
+ return __WEBPACK_IMPORTED_MODULE_31__cartesian_Bar__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_32__cartesian_Scatter__ = __webpack_require__(199);
+ __webpack_require__.d(__webpack_exports__, "Scatter", function() {
+ return __WEBPACK_IMPORTED_MODULE_32__cartesian_Scatter__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_33__cartesian_XAxis__ = __webpack_require__(67);
+ __webpack_require__.d(__webpack_exports__, "XAxis", function() {
+ return __WEBPACK_IMPORTED_MODULE_33__cartesian_XAxis__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_34__cartesian_YAxis__ = __webpack_require__(68);
+ __webpack_require__.d(__webpack_exports__, "YAxis", function() {
+ return __WEBPACK_IMPORTED_MODULE_34__cartesian_YAxis__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_35__cartesian_ZAxis__ = __webpack_require__(131);
+ __webpack_require__.d(__webpack_exports__, "ZAxis", function() {
+ return __WEBPACK_IMPORTED_MODULE_35__cartesian_ZAxis__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_36__cartesian_ErrorBar__ = __webpack_require__(91);
+ __webpack_require__.d(__webpack_exports__, "ErrorBar", function() {
+ return __WEBPACK_IMPORTED_MODULE_36__cartesian_ErrorBar__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_37__chart_LineChart__ = __webpack_require__(789);
+ __webpack_require__.d(__webpack_exports__, "LineChart", function() {
+ return __WEBPACK_IMPORTED_MODULE_37__chart_LineChart__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_38__chart_BarChart__ = __webpack_require__(793);
+ __webpack_require__.d(__webpack_exports__, "BarChart", function() {
+ return __WEBPACK_IMPORTED_MODULE_38__chart_BarChart__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_39__chart_PieChart__ = __webpack_require__(794);
+ __webpack_require__.d(__webpack_exports__, "PieChart", function() {
+ return __WEBPACK_IMPORTED_MODULE_39__chart_PieChart__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_40__chart_Treemap__ = __webpack_require__(795);
+ __webpack_require__.d(__webpack_exports__, "Treemap", function() {
+ return __WEBPACK_IMPORTED_MODULE_40__chart_Treemap__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_41__chart_Sankey__ = __webpack_require__(796);
+ __webpack_require__.d(__webpack_exports__, "Sankey", function() {
+ return __WEBPACK_IMPORTED_MODULE_41__chart_Sankey__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_42__chart_RadarChart__ = __webpack_require__(799);
+ __webpack_require__.d(__webpack_exports__, "RadarChart", function() {
+ return __WEBPACK_IMPORTED_MODULE_42__chart_RadarChart__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_43__chart_ScatterChart__ = __webpack_require__(800);
+ __webpack_require__.d(__webpack_exports__, "ScatterChart", function() {
+ return __WEBPACK_IMPORTED_MODULE_43__chart_ScatterChart__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_44__chart_AreaChart__ = __webpack_require__(801);
+ __webpack_require__.d(__webpack_exports__, "AreaChart", function() {
+ return __WEBPACK_IMPORTED_MODULE_44__chart_AreaChart__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_45__chart_RadialBarChart__ = __webpack_require__(802);
+ __webpack_require__.d(__webpack_exports__, "RadialBarChart", function() {
+ return __WEBPACK_IMPORTED_MODULE_45__chart_RadialBarChart__.a;
+ });
+ var __WEBPACK_IMPORTED_MODULE_46__chart_ComposedChart__ = __webpack_require__(803);
+ __webpack_require__.d(__webpack_exports__, "ComposedChart", function() {
+ return __WEBPACK_IMPORTED_MODULE_46__chart_ComposedChart__.a;
+ });
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0_core_js_es6_math__ = __webpack_require__(831), testObject = (__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_core_js_es6_math__),
+ var __WEBPACK_IMPORTED_MODULE_0_core_js_es6_math__ = __webpack_require__(526), testObject = (__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_core_js_es6_math__),
{});
if (!Object.setPrototypeOf && !testObject.__proto__) {
var nativeGetPrototypeOf = Object.getPrototypeOf;
@@ -35506,21 +32220,21 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}
}, function(module, exports, __webpack_require__) {
- __webpack_require__(832), __webpack_require__(844), __webpack_require__(845), __webpack_require__(846),
- __webpack_require__(847), __webpack_require__(848), __webpack_require__(849), __webpack_require__(850),
- __webpack_require__(852), __webpack_require__(853), __webpack_require__(854), __webpack_require__(855),
- __webpack_require__(856), __webpack_require__(857), __webpack_require__(858), __webpack_require__(859),
- __webpack_require__(860), module.exports = __webpack_require__(222).Math;
+ __webpack_require__(527), __webpack_require__(539), __webpack_require__(540), __webpack_require__(541),
+ __webpack_require__(542), __webpack_require__(543), __webpack_require__(544), __webpack_require__(545),
+ __webpack_require__(547), __webpack_require__(548), __webpack_require__(549), __webpack_require__(550),
+ __webpack_require__(551), __webpack_require__(552), __webpack_require__(553), __webpack_require__(554),
+ __webpack_require__(555), module.exports = __webpack_require__(159).Math;
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20), log1p = __webpack_require__(364), sqrt = Math.sqrt, $acosh = Math.acosh;
+ var $export = __webpack_require__(15), log1p = __webpack_require__(245), sqrt = Math.sqrt, $acosh = Math.acosh;
$export($export.S + $export.F * !($acosh && 710 == Math.floor($acosh(Number.MAX_VALUE)) && $acosh(1 / 0) == 1 / 0), "Math", {
acosh: function(x) {
return (x = +x) < 1 ? NaN : x > 94906265.62425156 ? Math.log(x) + Math.LN2 : log1p(x - 1 + sqrt(x - 1) * sqrt(x + 1));
}
});
}, function(module, exports, __webpack_require__) {
- var anObject = __webpack_require__(834), IE8_DOM_DEFINE = __webpack_require__(835), toPrimitive = __webpack_require__(837), dP = Object.defineProperty;
- exports.f = __webpack_require__(224) ? Object.defineProperty : function(O, P, Attributes) {
+ var anObject = __webpack_require__(529), IE8_DOM_DEFINE = __webpack_require__(530), toPrimitive = __webpack_require__(532), dP = Object.defineProperty;
+ exports.f = __webpack_require__(161) ? Object.defineProperty : function(O, P, Attributes) {
if (anObject(O), P = toPrimitive(P, !0), anObject(Attributes), IE8_DOM_DEFINE) try {
return dP(O, P, Attributes);
} catch (e) {}
@@ -35528,26 +32242,26 @@ var _publicBundleJs = []byte(`!function(modules) {
return "value" in Attributes && (O[P] = Attributes.value), O;
};
}, function(module, exports, __webpack_require__) {
- var isObject = __webpack_require__(223);
+ var isObject = __webpack_require__(160);
module.exports = function(it) {
if (!isObject(it)) throw TypeError(it + " is not an object!");
return it;
};
}, function(module, exports, __webpack_require__) {
- module.exports = !__webpack_require__(224) && !__webpack_require__(151)(function() {
- return 7 != Object.defineProperty(__webpack_require__(836)("div"), "a", {
+ module.exports = !__webpack_require__(161) && !__webpack_require__(110)(function() {
+ return 7 != Object.defineProperty(__webpack_require__(531)("div"), "a", {
get: function() {
return 7;
}
}).a;
});
}, function(module, exports, __webpack_require__) {
- var isObject = __webpack_require__(223), document = __webpack_require__(221).document, is = isObject(document) && isObject(document.createElement);
+ var isObject = __webpack_require__(160), document = __webpack_require__(158).document, is = isObject(document) && isObject(document.createElement);
module.exports = function(it) {
return is ? document.createElement(it) : {};
};
}, function(module, exports, __webpack_require__) {
- var isObject = __webpack_require__(223);
+ var isObject = __webpack_require__(160);
module.exports = function(it, S) {
if (!isObject(it)) return it;
var fn, val;
@@ -35566,8 +32280,8 @@ var _publicBundleJs = []byte(`!function(modules) {
};
};
}, function(module, exports, __webpack_require__) {
- var global = __webpack_require__(221), hide = __webpack_require__(363), has = __webpack_require__(840), SRC = __webpack_require__(841)("src"), $toString = Function.toString, TPL = ("" + $toString).split("toString");
- __webpack_require__(222).inspectSource = function(it) {
+ var global = __webpack_require__(158), hide = __webpack_require__(244), has = __webpack_require__(535), SRC = __webpack_require__(536)("src"), $toString = Function.toString, TPL = ("" + $toString).split("toString");
+ __webpack_require__(159).inspectSource = function(it) {
return $toString.call(it);
}, (module.exports = function(O, key, val, safe) {
var isFunction = "function" == typeof val;
@@ -35588,7 +32302,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return "Symbol(".concat(void 0 === key ? "" : key, ")_", (++id + px).toString(36));
};
}, function(module, exports, __webpack_require__) {
- var aFunction = __webpack_require__(843);
+ var aFunction = __webpack_require__(538);
module.exports = function(fn, that, length) {
if (aFunction(fn), void 0 === that) return fn;
switch (length) {
@@ -35620,50 +32334,50 @@ var _publicBundleJs = []byte(`!function(modules) {
function asinh(x) {
return isFinite(x = +x) && 0 != x ? x < 0 ? -asinh(-x) : Math.log(x + Math.sqrt(x * x + 1)) : x;
}
- var $export = __webpack_require__(20), $asinh = Math.asinh;
+ var $export = __webpack_require__(15), $asinh = Math.asinh;
$export($export.S + $export.F * !($asinh && 1 / $asinh(0) > 0), "Math", {
asinh: asinh
});
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20), $atanh = Math.atanh;
+ var $export = __webpack_require__(15), $atanh = Math.atanh;
$export($export.S + $export.F * !($atanh && 1 / $atanh(-0) < 0), "Math", {
atanh: function(x) {
return 0 == (x = +x) ? x : Math.log((1 + x) / (1 - x)) / 2;
}
});
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20), sign = __webpack_require__(225);
+ var $export = __webpack_require__(15), sign = __webpack_require__(162);
$export($export.S, "Math", {
cbrt: function(x) {
return sign(x = +x) * Math.pow(Math.abs(x), 1 / 3);
}
});
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20);
+ var $export = __webpack_require__(15);
$export($export.S, "Math", {
clz32: function(x) {
return (x >>>= 0) ? 31 - Math.floor(Math.log(x + .5) * Math.LOG2E) : 32;
}
});
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20), exp = Math.exp;
+ var $export = __webpack_require__(15), exp = Math.exp;
$export($export.S, "Math", {
cosh: function(x) {
return (exp(x = +x) + exp(-x)) / 2;
}
});
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20), $expm1 = __webpack_require__(226);
+ var $export = __webpack_require__(15), $expm1 = __webpack_require__(163);
$export($export.S + $export.F * ($expm1 != Math.expm1), "Math", {
expm1: $expm1
});
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20);
+ var $export = __webpack_require__(15);
$export($export.S, "Math", {
- fround: __webpack_require__(851)
+ fround: __webpack_require__(546)
});
}, function(module, exports, __webpack_require__) {
- var sign = __webpack_require__(225), pow = Math.pow, EPSILON = pow(2, -52), EPSILON32 = pow(2, -23), MAX32 = pow(2, 127) * (2 - EPSILON32), MIN32 = pow(2, -126), roundTiesToEven = function(n) {
+ var sign = __webpack_require__(162), pow = Math.pow, EPSILON = pow(2, -52), EPSILON32 = pow(2, -23), MAX32 = pow(2, 127) * (2 - EPSILON32), MIN32 = pow(2, -126), roundTiesToEven = function(n) {
return n + 1 / EPSILON - 1 / EPSILON;
};
module.exports = Math.fround || function(x) {
@@ -35672,7 +32386,7 @@ var _publicBundleJs = []byte(`!function(modules) {
result = a - (a - $abs), result > MAX32 || result != result ? $sign * (1 / 0) : $sign * result);
};
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20), abs = Math.abs;
+ var $export = __webpack_require__(15), abs = Math.abs;
$export($export.S, "Math", {
hypot: function(value1, value2) {
for (var arg, div, sum = 0, i = 0, aLen = arguments.length, larg = 0; i < aLen; ) arg = abs(arguments[i++]),
@@ -35682,8 +32396,8 @@ var _publicBundleJs = []byte(`!function(modules) {
}
});
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20), $imul = Math.imul;
- $export($export.S + $export.F * __webpack_require__(151)(function() {
+ var $export = __webpack_require__(15), $imul = Math.imul;
+ $export($export.S + $export.F * __webpack_require__(110)(function() {
return -5 != $imul(4294967295, 5) || 2 != $imul.length;
}), "Math", {
imul: function(x, y) {
@@ -35692,32 +32406,32 @@ var _publicBundleJs = []byte(`!function(modules) {
}
});
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20);
+ var $export = __webpack_require__(15);
$export($export.S, "Math", {
log10: function(x) {
return Math.log(x) * Math.LOG10E;
}
});
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20);
+ var $export = __webpack_require__(15);
$export($export.S, "Math", {
- log1p: __webpack_require__(364)
+ log1p: __webpack_require__(245)
});
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20);
+ var $export = __webpack_require__(15);
$export($export.S, "Math", {
log2: function(x) {
return Math.log(x) / Math.LN2;
}
});
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20);
+ var $export = __webpack_require__(15);
$export($export.S, "Math", {
- sign: __webpack_require__(225)
+ sign: __webpack_require__(162)
});
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20), expm1 = __webpack_require__(226), exp = Math.exp;
- $export($export.S + $export.F * __webpack_require__(151)(function() {
+ var $export = __webpack_require__(15), expm1 = __webpack_require__(163), exp = Math.exp;
+ $export($export.S + $export.F * __webpack_require__(110)(function() {
return -2e-17 != !Math.sinh(-2e-17);
}), "Math", {
sinh: function(x) {
@@ -35725,7 +32439,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
});
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20), expm1 = __webpack_require__(226), exp = Math.exp;
+ var $export = __webpack_require__(15), expm1 = __webpack_require__(163), exp = Math.exp;
$export($export.S, "Math", {
tanh: function(x) {
var a = expm1(x = +x), b = expm1(-x);
@@ -35733,33 +32447,14 @@ var _publicBundleJs = []byte(`!function(modules) {
}
});
}, function(module, exports, __webpack_require__) {
- var $export = __webpack_require__(20);
+ var $export = __webpack_require__(15);
$export($export.S, "Math", {
trunc: function(it) {
return (it > 0 ? Math.floor : Math.ceil)(it);
}
});
}, function(module, exports, __webpack_require__) {
- function getRawTag(value) {
- var isOwn = hasOwnProperty.call(value, symToStringTag), tag = value[symToStringTag];
- try {
- value[symToStringTag] = void 0;
- var unmasked = !0;
- } catch (e) {}
- var result = nativeObjectToString.call(value);
- return unmasked && (isOwn ? value[symToStringTag] = tag : delete value[symToStringTag]),
- result;
- }
- var Symbol = __webpack_require__(104), objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty, nativeObjectToString = objectProto.toString, symToStringTag = Symbol ? Symbol.toStringTag : void 0;
- module.exports = getRawTag;
-}, function(module, exports) {
- function objectToString(value) {
- return nativeObjectToString.call(value);
- }
- var objectProto = Object.prototype, nativeObjectToString = objectProto.toString;
- module.exports = objectToString;
-}, function(module, exports, __webpack_require__) {
- var memoizeCapped = __webpack_require__(864), reLeadingDot = /^\./, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g, reEscapeChar = /\\(\\)?/g, stringToPath = memoizeCapped(function(string) {
+ var memoizeCapped = __webpack_require__(557), reLeadingDot = /^\./, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g, reEscapeChar = /\\(\\)?/g, stringToPath = memoizeCapped(function(string) {
var result = [];
return reLeadingDot.test(string) && result.push(""), string.replace(rePropName, function(match, number, quote, string) {
result.push(quote ? string.replace(reEscapeChar, "$1") : number || match);
@@ -35773,7 +32468,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), cache = result.cache;
return result;
}
- var memoize = __webpack_require__(865), MAX_MEMOIZE_SIZE = 500;
+ var memoize = __webpack_require__(558), MAX_MEMOIZE_SIZE = 500;
module.exports = memoizeCapped;
}, function(module, exports, __webpack_require__) {
function memoize(func, resolver) {
@@ -35786,7 +32481,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
return memoized.cache = new (memoize.Cache || MapCache)(), memoized;
}
- var MapCache = __webpack_require__(229), FUNC_ERROR_TEXT = "Expected a function";
+ var MapCache = __webpack_require__(167), FUNC_ERROR_TEXT = "Expected a function";
memoize.Cache = MapCache, module.exports = memoize;
}, function(module, exports, __webpack_require__) {
function mapCacheClear() {
@@ -35796,7 +32491,7 @@ var _publicBundleJs = []byte(`!function(modules) {
string: new Hash()
};
}
- var Hash = __webpack_require__(867), ListCache = __webpack_require__(154), Map = __webpack_require__(231);
+ var Hash = __webpack_require__(560), ListCache = __webpack_require__(112), Map = __webpack_require__(169);
module.exports = mapCacheClear;
}, function(module, exports, __webpack_require__) {
function Hash(entries) {
@@ -35806,32 +32501,32 @@ var _publicBundleJs = []byte(`!function(modules) {
this.set(entry[0], entry[1]);
}
}
- var hashClear = __webpack_require__(868), hashDelete = __webpack_require__(873), hashGet = __webpack_require__(874), hashHas = __webpack_require__(875), hashSet = __webpack_require__(876);
+ var hashClear = __webpack_require__(561), hashDelete = __webpack_require__(566), hashGet = __webpack_require__(567), hashHas = __webpack_require__(568), hashSet = __webpack_require__(569);
Hash.prototype.clear = hashClear, Hash.prototype.delete = hashDelete, Hash.prototype.get = hashGet,
Hash.prototype.has = hashHas, Hash.prototype.set = hashSet, module.exports = Hash;
}, function(module, exports, __webpack_require__) {
function hashClear() {
this.__data__ = nativeCreate ? nativeCreate(null) : {}, this.size = 0;
}
- var nativeCreate = __webpack_require__(153);
+ var nativeCreate = __webpack_require__(111);
module.exports = hashClear;
}, function(module, exports, __webpack_require__) {
function baseIsNative(value) {
return !(!isObject(value) || isMasked(value)) && (isFunction(value) ? reIsNative : reIsHostCtor).test(toSource(value));
}
- var isFunction = __webpack_require__(11), isMasked = __webpack_require__(870), isObject = __webpack_require__(47), toSource = __webpack_require__(368), reRegExpChar = /[\\^$.*+?()[\]{}|]/g, reIsHostCtor = /^\[object .+?Constructor\]$/, funcProto = Function.prototype, objectProto = Object.prototype, funcToString = funcProto.toString, hasOwnProperty = objectProto.hasOwnProperty, reIsNative = RegExp("^" + funcToString.call(hasOwnProperty).replace(reRegExpChar, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$");
+ var isFunction = __webpack_require__(8), isMasked = __webpack_require__(563), isObject = __webpack_require__(31), toSource = __webpack_require__(248), reRegExpChar = /[\\^$.*+?()[\]{}|]/g, reIsHostCtor = /^\[object .+?Constructor\]$/, funcProto = Function.prototype, objectProto = Object.prototype, funcToString = funcProto.toString, hasOwnProperty = objectProto.hasOwnProperty, reIsNative = RegExp("^" + funcToString.call(hasOwnProperty).replace(reRegExpChar, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$");
module.exports = baseIsNative;
}, function(module, exports, __webpack_require__) {
function isMasked(func) {
return !!maskSrcKey && maskSrcKey in func;
}
- var coreJsData = __webpack_require__(871), maskSrcKey = function() {
+ var coreJsData = __webpack_require__(564), maskSrcKey = function() {
var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || "");
return uid ? "Symbol(src)_1." + uid : "";
}();
module.exports = isMasked;
}, function(module, exports, __webpack_require__) {
- var root = __webpack_require__(46), coreJsData = root["__core-js_shared__"];
+ var root = __webpack_require__(32), coreJsData = root["__core-js_shared__"];
module.exports = coreJsData;
}, function(module, exports) {
function getValue(object, key) {
@@ -35853,14 +32548,14 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return hasOwnProperty.call(data, key) ? data[key] : void 0;
}
- var nativeCreate = __webpack_require__(153), HASH_UNDEFINED = "__lodash_hash_undefined__", objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty;
+ var nativeCreate = __webpack_require__(111), HASH_UNDEFINED = "__lodash_hash_undefined__", objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty;
module.exports = hashGet;
}, function(module, exports, __webpack_require__) {
function hashHas(key) {
var data = this.__data__;
return nativeCreate ? void 0 !== data[key] : hasOwnProperty.call(data, key);
}
- var nativeCreate = __webpack_require__(153), objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty;
+ var nativeCreate = __webpack_require__(111), objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty;
module.exports = hashHas;
}, function(module, exports, __webpack_require__) {
function hashSet(key, value) {
@@ -35868,7 +32563,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return this.size += this.has(key) ? 0 : 1, data[key] = nativeCreate && void 0 === value ? HASH_UNDEFINED : value,
this;
}
- var nativeCreate = __webpack_require__(153), HASH_UNDEFINED = "__lodash_hash_undefined__";
+ var nativeCreate = __webpack_require__(111), HASH_UNDEFINED = "__lodash_hash_undefined__";
module.exports = hashSet;
}, function(module, exports) {
function listCacheClear() {
@@ -35881,20 +32576,20 @@ var _publicBundleJs = []byte(`!function(modules) {
return !(index < 0) && (index == data.length - 1 ? data.pop() : splice.call(data, index, 1),
--this.size, !0);
}
- var assocIndexOf = __webpack_require__(155), arrayProto = Array.prototype, splice = arrayProto.splice;
+ var assocIndexOf = __webpack_require__(113), arrayProto = Array.prototype, splice = arrayProto.splice;
module.exports = listCacheDelete;
}, function(module, exports, __webpack_require__) {
function listCacheGet(key) {
var data = this.__data__, index = assocIndexOf(data, key);
return index < 0 ? void 0 : data[index][1];
}
- var assocIndexOf = __webpack_require__(155);
+ var assocIndexOf = __webpack_require__(113);
module.exports = listCacheGet;
}, function(module, exports, __webpack_require__) {
function listCacheHas(key) {
return assocIndexOf(this.__data__, key) > -1;
}
- var assocIndexOf = __webpack_require__(155);
+ var assocIndexOf = __webpack_require__(113);
module.exports = listCacheHas;
}, function(module, exports, __webpack_require__) {
function listCacheSet(key, value) {
@@ -35902,14 +32597,14 @@ var _publicBundleJs = []byte(`!function(modules) {
return index < 0 ? (++this.size, data.push([ key, value ])) : data[index][1] = value,
this;
}
- var assocIndexOf = __webpack_require__(155);
+ var assocIndexOf = __webpack_require__(113);
module.exports = listCacheSet;
}, function(module, exports, __webpack_require__) {
function mapCacheDelete(key) {
var result = getMapData(this, key).delete(key);
return this.size -= result ? 1 : 0, result;
}
- var getMapData = __webpack_require__(156);
+ var getMapData = __webpack_require__(114);
module.exports = mapCacheDelete;
}, function(module, exports) {
function isKeyable(value) {
@@ -35921,26 +32616,26 @@ var _publicBundleJs = []byte(`!function(modules) {
function mapCacheGet(key) {
return getMapData(this, key).get(key);
}
- var getMapData = __webpack_require__(156);
+ var getMapData = __webpack_require__(114);
module.exports = mapCacheGet;
}, function(module, exports, __webpack_require__) {
function mapCacheHas(key) {
return getMapData(this, key).has(key);
}
- var getMapData = __webpack_require__(156);
+ var getMapData = __webpack_require__(114);
module.exports = mapCacheHas;
}, function(module, exports, __webpack_require__) {
function mapCacheSet(key, value) {
var data = getMapData(this, key), size = data.size;
return data.set(key, value), this.size += data.size == size ? 0 : 1, this;
}
- var getMapData = __webpack_require__(156);
+ var getMapData = __webpack_require__(114);
module.exports = mapCacheSet;
}, function(module, exports, __webpack_require__) {
function toString(value) {
return null == value ? "" : baseToString(value);
}
- var baseToString = __webpack_require__(888);
+ var baseToString = __webpack_require__(581);
module.exports = toString;
}, function(module, exports, __webpack_require__) {
function baseToString(value) {
@@ -35950,7 +32645,7 @@ var _publicBundleJs = []byte(`!function(modules) {
var result = value + "";
return "0" == result && 1 / value == -INFINITY ? "-0" : result;
}
- var Symbol = __webpack_require__(104), arrayMap = __webpack_require__(157), isArray = __webpack_require__(16), isSymbol = __webpack_require__(82), INFINITY = 1 / 0, symbolProto = Symbol ? Symbol.prototype : void 0, symbolToString = symbolProto ? symbolProto.toString : void 0;
+ var Symbol = __webpack_require__(77), arrayMap = __webpack_require__(115), isArray = __webpack_require__(12), isSymbol = __webpack_require__(62), INFINITY = 1 / 0, symbolProto = Symbol ? Symbol.prototype : void 0, symbolToString = symbolProto ? symbolProto.toString : void 0;
module.exports = baseToString;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35980,7 +32675,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_4__container_Surface__ = __webpack_require__(103), __WEBPACK_IMPORTED_MODULE_5__shape_Symbols__ = __webpack_require__(234), __WEBPACK_IMPORTED_MODULE_6__util_ReactUtils__ = __webpack_require__(7), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_2_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_classnames__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_4__container_Surface__ = __webpack_require__(78), __WEBPACK_IMPORTED_MODULE_5__shape_Symbols__ = __webpack_require__(172), __WEBPACK_IMPORTED_MODULE_6__util_ReactUtils__ = __webpack_require__(4), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -36117,7 +32812,7 @@ var _publicBundleJs = []byte(`!function(modules) {
__webpack_exports__.a = DefaultLegendContent;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(105), __webpack_require__(71), __webpack_require__(106);
+ __webpack_require__(79), __webpack_require__(54), __webpack_require__(80);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
function Path() {
@@ -36170,7 +32865,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, __webpack_exports__.a = path;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(71), __webpack_require__(893), __webpack_require__(894), __webpack_require__(106);
+ __webpack_require__(54), __webpack_require__(586), __webpack_require__(587), __webpack_require__(80);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_exports__.a = function(a, b) {
@@ -36183,14 +32878,14 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(370), __webpack_require__(369), __webpack_require__(371);
+ __webpack_require__(250), __webpack_require__(249), __webpack_require__(251);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(105), __webpack_require__(373), __webpack_require__(71), __webpack_require__(237),
- __webpack_require__(372);
+ __webpack_require__(79), __webpack_require__(253), __webpack_require__(54), __webpack_require__(175),
+ __webpack_require__(252);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0_d3_path__ = __webpack_require__(105), __WEBPACK_IMPORTED_MODULE_1__symbol_circle__ = __webpack_require__(374), __WEBPACK_IMPORTED_MODULE_2__symbol_cross__ = __webpack_require__(375), __WEBPACK_IMPORTED_MODULE_3__symbol_diamond__ = __webpack_require__(376), __WEBPACK_IMPORTED_MODULE_4__symbol_star__ = __webpack_require__(377), __WEBPACK_IMPORTED_MODULE_5__symbol_square__ = __webpack_require__(378), __WEBPACK_IMPORTED_MODULE_6__symbol_triangle__ = __webpack_require__(379), __WEBPACK_IMPORTED_MODULE_7__symbol_wye__ = __webpack_require__(380), __WEBPACK_IMPORTED_MODULE_8__constant__ = __webpack_require__(71);
+ var __WEBPACK_IMPORTED_MODULE_0_d3_path__ = __webpack_require__(79), __WEBPACK_IMPORTED_MODULE_1__symbol_circle__ = __webpack_require__(254), __WEBPACK_IMPORTED_MODULE_2__symbol_cross__ = __webpack_require__(255), __WEBPACK_IMPORTED_MODULE_3__symbol_diamond__ = __webpack_require__(256), __WEBPACK_IMPORTED_MODULE_4__symbol_star__ = __webpack_require__(257), __WEBPACK_IMPORTED_MODULE_5__symbol_square__ = __webpack_require__(258), __WEBPACK_IMPORTED_MODULE_6__symbol_triangle__ = __webpack_require__(259), __WEBPACK_IMPORTED_MODULE_7__symbol_wye__ = __webpack_require__(260), __WEBPACK_IMPORTED_MODULE_8__constant__ = __webpack_require__(54);
__WEBPACK_IMPORTED_MODULE_1__symbol_circle__.a, __WEBPACK_IMPORTED_MODULE_2__symbol_cross__.a,
__WEBPACK_IMPORTED_MODULE_3__symbol_diamond__.a, __WEBPACK_IMPORTED_MODULE_5__symbol_square__.a,
__WEBPACK_IMPORTED_MODULE_4__symbol_star__.a, __WEBPACK_IMPORTED_MODULE_6__symbol_triangle__.a,
@@ -36218,7 +32913,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function BasisClosed(context) {
this._context = context;
}
- var __WEBPACK_IMPORTED_MODULE_0__noop__ = __webpack_require__(161), __WEBPACK_IMPORTED_MODULE_1__basis__ = __webpack_require__(162);
+ var __WEBPACK_IMPORTED_MODULE_0__noop__ = __webpack_require__(119), __WEBPACK_IMPORTED_MODULE_1__basis__ = __webpack_require__(120);
BasisClosed.prototype = {
areaStart: __WEBPACK_IMPORTED_MODULE_0__noop__.a,
areaEnd: __WEBPACK_IMPORTED_MODULE_0__noop__.a,
@@ -36269,7 +32964,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function BasisOpen(context) {
this._context = context;
}
- var __WEBPACK_IMPORTED_MODULE_0__basis__ = __webpack_require__(162);
+ var __WEBPACK_IMPORTED_MODULE_0__basis__ = __webpack_require__(120);
BasisOpen.prototype = {
areaStart: function() {
this._line = 0;
@@ -36316,7 +33011,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function Bundle(context, beta) {
this._basis = new __WEBPACK_IMPORTED_MODULE_0__basis__.a(context), this._beta = beta;
}
- var __WEBPACK_IMPORTED_MODULE_0__basis__ = __webpack_require__(162);
+ var __WEBPACK_IMPORTED_MODULE_0__basis__ = __webpack_require__(120);
Bundle.prototype = {
lineStart: function() {
this._x = [], this._y = [], this._basis.lineStart();
@@ -36344,7 +33039,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function CatmullRomClosed(context, alpha) {
this._context = context, this._alpha = alpha;
}
- var __WEBPACK_IMPORTED_MODULE_0__cardinalClosed__ = __webpack_require__(381), __WEBPACK_IMPORTED_MODULE_1__noop__ = __webpack_require__(161), __WEBPACK_IMPORTED_MODULE_2__catmullRom__ = __webpack_require__(238);
+ var __WEBPACK_IMPORTED_MODULE_0__cardinalClosed__ = __webpack_require__(261), __WEBPACK_IMPORTED_MODULE_1__noop__ = __webpack_require__(119), __WEBPACK_IMPORTED_MODULE_2__catmullRom__ = __webpack_require__(176);
CatmullRomClosed.prototype = {
areaStart: __WEBPACK_IMPORTED_MODULE_1__noop__.a,
areaEnd: __WEBPACK_IMPORTED_MODULE_1__noop__.a,
@@ -36405,7 +33100,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function CatmullRomOpen(context, alpha) {
this._context = context, this._alpha = alpha;
}
- var __WEBPACK_IMPORTED_MODULE_0__cardinalOpen__ = __webpack_require__(382), __WEBPACK_IMPORTED_MODULE_1__catmullRom__ = __webpack_require__(238);
+ var __WEBPACK_IMPORTED_MODULE_0__cardinalOpen__ = __webpack_require__(262), __WEBPACK_IMPORTED_MODULE_1__catmullRom__ = __webpack_require__(176);
CatmullRomOpen.prototype = {
areaStart: function() {
this._line = 0;
@@ -36462,7 +33157,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function LinearClosed(context) {
this._context = context;
}
- var __WEBPACK_IMPORTED_MODULE_0__noop__ = __webpack_require__(161);
+ var __WEBPACK_IMPORTED_MODULE_0__noop__ = __webpack_require__(119);
LinearClosed.prototype = {
areaStart: __WEBPACK_IMPORTED_MODULE_0__noop__.a,
areaEnd: __WEBPACK_IMPORTED_MODULE_0__noop__.a,
@@ -36660,7 +33355,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function stackValue(d, key) {
return d[key];
}
- var __WEBPACK_IMPORTED_MODULE_0__array__ = __webpack_require__(373), __WEBPACK_IMPORTED_MODULE_1__constant__ = __webpack_require__(71), __WEBPACK_IMPORTED_MODULE_2__offset_none__ = __webpack_require__(107), __WEBPACK_IMPORTED_MODULE_3__order_none__ = __webpack_require__(108);
+ var __WEBPACK_IMPORTED_MODULE_0__array__ = __webpack_require__(253), __WEBPACK_IMPORTED_MODULE_1__constant__ = __webpack_require__(54), __WEBPACK_IMPORTED_MODULE_2__offset_none__ = __webpack_require__(81), __WEBPACK_IMPORTED_MODULE_3__order_none__ = __webpack_require__(82);
__webpack_exports__.a = function() {
function stack(data) {
var i, oz, kz = keys.apply(this, arguments), m = data.length, n = kz.length, sz = new Array(n);
@@ -36689,7 +33384,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__none__ = __webpack_require__(107);
+ var __WEBPACK_IMPORTED_MODULE_0__none__ = __webpack_require__(81);
__webpack_exports__.a = function(series, order) {
if ((n = series.length) > 0) {
for (var i, n, y, j = 0, m = series[0].length; j < m; ++j) {
@@ -36703,7 +33398,7 @@ var _publicBundleJs = []byte(`!function(modules) {
"use strict";
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__none__ = __webpack_require__(107);
+ var __WEBPACK_IMPORTED_MODULE_0__none__ = __webpack_require__(81);
__webpack_exports__.a = function(series, order) {
if ((n = series.length) > 0) {
for (var n, j = 0, s0 = series[order[0]], m = s0.length; j < m; ++j) {
@@ -36715,7 +33410,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__none__ = __webpack_require__(107);
+ var __WEBPACK_IMPORTED_MODULE_0__none__ = __webpack_require__(81);
__webpack_exports__.a = function(series, order) {
if ((n = series.length) > 0 && (m = (s0 = series[order[0]]).length) > 0) {
for (var s0, m, n, y = 0, j = 1; j < m; ++j) {
@@ -36733,13 +33428,13 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(239);
+ __webpack_require__(177);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(108), __webpack_require__(239);
+ __webpack_require__(82), __webpack_require__(177);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(108);
+ __webpack_require__(82);
}, function(module, exports, __webpack_require__) {
function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
var objIsArr = isArray(object), othIsArr = isArray(other), objTag = objIsArr ? arrayTag : getTag(object), othTag = othIsArr ? arrayTag : getTag(other);
@@ -36759,13 +33454,13 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return !!isSameTag && (stack || (stack = new Stack()), equalObjects(object, other, bitmask, customizer, equalFunc, stack));
}
- var Stack = __webpack_require__(384), equalArrays = __webpack_require__(385), equalByTag = __webpack_require__(924), equalObjects = __webpack_require__(928), getTag = __webpack_require__(942), isArray = __webpack_require__(16), isBuffer = __webpack_require__(390), isTypedArray = __webpack_require__(391), COMPARE_PARTIAL_FLAG = 1, argsTag = "[object Arguments]", arrayTag = "[object Array]", objectTag = "[object Object]", objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty;
+ var Stack = __webpack_require__(264), equalArrays = __webpack_require__(265), equalByTag = __webpack_require__(617), equalObjects = __webpack_require__(621), getTag = __webpack_require__(635), isArray = __webpack_require__(12), isBuffer = __webpack_require__(270), isTypedArray = __webpack_require__(271), COMPARE_PARTIAL_FLAG = 1, argsTag = "[object Arguments]", arrayTag = "[object Array]", objectTag = "[object Object]", objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty;
module.exports = baseIsEqualDeep;
}, function(module, exports, __webpack_require__) {
function stackClear() {
this.__data__ = new ListCache(), this.size = 0;
}
- var ListCache = __webpack_require__(154);
+ var ListCache = __webpack_require__(112);
module.exports = stackClear;
}, function(module, exports) {
function stackDelete(key) {
@@ -36794,7 +33489,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return data.set(key, value), this.size = data.size, this;
}
- var ListCache = __webpack_require__(154), Map = __webpack_require__(231), MapCache = __webpack_require__(229), LARGE_ARRAY_SIZE = 200;
+ var ListCache = __webpack_require__(112), Map = __webpack_require__(169), MapCache = __webpack_require__(167), LARGE_ARRAY_SIZE = 200;
module.exports = stackSet;
}, function(module, exports) {
function setCacheAdd(value) {
@@ -36852,10 +33547,10 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return !1;
}
- var Symbol = __webpack_require__(104), Uint8Array = __webpack_require__(925), eq = __webpack_require__(230), equalArrays = __webpack_require__(385), mapToArray = __webpack_require__(926), setToArray = __webpack_require__(927), COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2, boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", mapTag = "[object Map]", numberTag = "[object Number]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", symbolTag = "[object Symbol]", arrayBufferTag = "[object ArrayBuffer]", dataViewTag = "[object DataView]", symbolProto = Symbol ? Symbol.prototype : void 0, symbolValueOf = symbolProto ? symbolProto.valueOf : void 0;
+ var Symbol = __webpack_require__(77), Uint8Array = __webpack_require__(618), eq = __webpack_require__(168), equalArrays = __webpack_require__(265), mapToArray = __webpack_require__(619), setToArray = __webpack_require__(620), COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2, boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", mapTag = "[object Map]", numberTag = "[object Number]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", symbolTag = "[object Symbol]", arrayBufferTag = "[object ArrayBuffer]", dataViewTag = "[object DataView]", symbolProto = Symbol ? Symbol.prototype : void 0, symbolValueOf = symbolProto ? symbolProto.valueOf : void 0;
module.exports = equalByTag;
}, function(module, exports, __webpack_require__) {
- var root = __webpack_require__(46), Uint8Array = root.Uint8Array;
+ var root = __webpack_require__(32), Uint8Array = root.Uint8Array;
module.exports = Uint8Array;
}, function(module, exports) {
function mapToArray(map) {
@@ -36901,23 +33596,23 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return stack.delete(object), stack.delete(other), result;
}
- var getAllKeys = __webpack_require__(929), COMPARE_PARTIAL_FLAG = 1, objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty;
+ var getAllKeys = __webpack_require__(622), COMPARE_PARTIAL_FLAG = 1, objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty;
module.exports = equalObjects;
}, function(module, exports, __webpack_require__) {
function getAllKeys(object) {
return baseGetAllKeys(object, keys, getSymbols);
}
- var baseGetAllKeys = __webpack_require__(930), getSymbols = __webpack_require__(931), keys = __webpack_require__(241);
+ var baseGetAllKeys = __webpack_require__(623), getSymbols = __webpack_require__(624), keys = __webpack_require__(179);
module.exports = getAllKeys;
}, function(module, exports, __webpack_require__) {
function baseGetAllKeys(object, keysFunc, symbolsFunc) {
var result = keysFunc(object);
return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
}
- var arrayPush = __webpack_require__(388), isArray = __webpack_require__(16);
+ var arrayPush = __webpack_require__(268), isArray = __webpack_require__(12);
module.exports = baseGetAllKeys;
}, function(module, exports, __webpack_require__) {
- var arrayFilter = __webpack_require__(389), stubArray = __webpack_require__(932), objectProto = Object.prototype, propertyIsEnumerable = objectProto.propertyIsEnumerable, nativeGetSymbols = Object.getOwnPropertySymbols, getSymbols = nativeGetSymbols ? function(object) {
+ var arrayFilter = __webpack_require__(269), stubArray = __webpack_require__(625), objectProto = Object.prototype, propertyIsEnumerable = objectProto.propertyIsEnumerable, nativeGetSymbols = Object.getOwnPropertySymbols, getSymbols = nativeGetSymbols ? function(object) {
return null == object ? [] : (object = Object(object), arrayFilter(nativeGetSymbols(object), function(symbol) {
return propertyIsEnumerable.call(object, symbol);
}));
@@ -36934,7 +33629,7 @@ var _publicBundleJs = []byte(`!function(modules) {
for (var key in value) !inherited && !hasOwnProperty.call(value, key) || skipIndexes && ("length" == key || isBuff && ("offset" == key || "parent" == key) || isType && ("buffer" == key || "byteLength" == key || "byteOffset" == key) || isIndex(key, length)) || result.push(key);
return result;
}
- var baseTimes = __webpack_require__(934), isArguments = __webpack_require__(242), isArray = __webpack_require__(16), isBuffer = __webpack_require__(390), isIndex = __webpack_require__(243), isTypedArray = __webpack_require__(391), objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty;
+ var baseTimes = __webpack_require__(627), isArguments = __webpack_require__(180), isArray = __webpack_require__(12), isBuffer = __webpack_require__(270), isIndex = __webpack_require__(181), isTypedArray = __webpack_require__(271), objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty;
module.exports = arrayLikeKeys;
}, function(module, exports) {
function baseTimes(n, iteratee) {
@@ -36946,7 +33641,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function baseIsArguments(value) {
return isObjectLike(value) && baseGetTag(value) == argsTag;
}
- var baseGetTag = __webpack_require__(59), isObjectLike = __webpack_require__(52), argsTag = "[object Arguments]";
+ var baseGetTag = __webpack_require__(42), isObjectLike = __webpack_require__(36), argsTag = "[object Arguments]";
module.exports = baseIsArguments;
}, function(module, exports) {
function stubFalse() {
@@ -36957,19 +33652,19 @@ var _publicBundleJs = []byte(`!function(modules) {
function baseIsTypedArray(value) {
return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
}
- var baseGetTag = __webpack_require__(59), isLength = __webpack_require__(244), isObjectLike = __webpack_require__(52), typedArrayTags = {};
+ var baseGetTag = __webpack_require__(42), isLength = __webpack_require__(182), isObjectLike = __webpack_require__(36), typedArrayTags = {};
typedArrayTags["[object Float32Array]"] = typedArrayTags["[object Float64Array]"] = typedArrayTags["[object Int8Array]"] = typedArrayTags["[object Int16Array]"] = typedArrayTags["[object Int32Array]"] = typedArrayTags["[object Uint8Array]"] = typedArrayTags["[object Uint8ClampedArray]"] = typedArrayTags["[object Uint16Array]"] = typedArrayTags["[object Uint32Array]"] = !0,
typedArrayTags["[object Arguments]"] = typedArrayTags["[object Array]"] = typedArrayTags["[object ArrayBuffer]"] = typedArrayTags["[object Boolean]"] = typedArrayTags["[object DataView]"] = typedArrayTags["[object Date]"] = typedArrayTags["[object Error]"] = typedArrayTags["[object Function]"] = typedArrayTags["[object Map]"] = typedArrayTags["[object Number]"] = typedArrayTags["[object Object]"] = typedArrayTags["[object RegExp]"] = typedArrayTags["[object Set]"] = typedArrayTags["[object String]"] = typedArrayTags["[object WeakMap]"] = !1,
module.exports = baseIsTypedArray;
}, function(module, exports, __webpack_require__) {
(function(module) {
- var freeGlobal = __webpack_require__(365), freeExports = "object" == typeof exports && exports && !exports.nodeType && exports, freeModule = freeExports && "object" == typeof module && module && !module.nodeType && module, moduleExports = freeModule && freeModule.exports === freeExports, freeProcess = moduleExports && freeGlobal.process, nodeUtil = function() {
+ var freeGlobal = __webpack_require__(242), freeExports = "object" == typeof exports && exports && !exports.nodeType && exports, freeModule = freeExports && "object" == typeof module && module && !module.nodeType && module, moduleExports = freeModule && freeModule.exports === freeExports, freeProcess = moduleExports && freeGlobal.process, nodeUtil = function() {
try {
return freeProcess && freeProcess.binding && freeProcess.binding("util");
} catch (e) {}
}();
module.exports = nodeUtil;
- }).call(exports, __webpack_require__(197)(module));
+ }).call(exports, __webpack_require__(154)(module));
}, function(module, exports, __webpack_require__) {
function baseKeys(object) {
if (!isPrototype(object)) return nativeKeys(object);
@@ -36977,7 +33672,7 @@ var _publicBundleJs = []byte(`!function(modules) {
for (var key in Object(object)) hasOwnProperty.call(object, key) && "constructor" != key && result.push(key);
return result;
}
- var isPrototype = __webpack_require__(940), nativeKeys = __webpack_require__(941), objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty;
+ var isPrototype = __webpack_require__(633), nativeKeys = __webpack_require__(634), objectProto = Object.prototype, hasOwnProperty = objectProto.hasOwnProperty;
module.exports = baseKeys;
}, function(module, exports) {
function isPrototype(value) {
@@ -36987,10 +33682,10 @@ var _publicBundleJs = []byte(`!function(modules) {
var objectProto = Object.prototype;
module.exports = isPrototype;
}, function(module, exports, __webpack_require__) {
- var overArg = __webpack_require__(392), nativeKeys = overArg(Object.keys, Object);
+ var overArg = __webpack_require__(272), nativeKeys = overArg(Object.keys, Object);
module.exports = nativeKeys;
}, function(module, exports, __webpack_require__) {
- var DataView = __webpack_require__(943), Map = __webpack_require__(231), Promise = __webpack_require__(944), Set = __webpack_require__(945), WeakMap = __webpack_require__(946), baseGetTag = __webpack_require__(59), toSource = __webpack_require__(368), dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map), promiseCtorString = toSource(Promise), setCtorString = toSource(Set), weakMapCtorString = toSource(WeakMap), getTag = baseGetTag;
+ var DataView = __webpack_require__(636), Map = __webpack_require__(169), Promise = __webpack_require__(637), Set = __webpack_require__(638), WeakMap = __webpack_require__(639), baseGetTag = __webpack_require__(42), toSource = __webpack_require__(248), dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map), promiseCtorString = toSource(Promise), setCtorString = toSource(Set), weakMapCtorString = toSource(WeakMap), getTag = baseGetTag;
(DataView && "[object DataView]" != getTag(new DataView(new ArrayBuffer(1))) || Map && "[object Map]" != getTag(new Map()) || Promise && "[object Promise]" != getTag(Promise.resolve()) || Set && "[object Set]" != getTag(new Set()) || WeakMap && "[object WeakMap]" != getTag(new WeakMap())) && (getTag = function(value) {
var result = baseGetTag(value), Ctor = "[object Object]" == result ? value.constructor : void 0, ctorString = Ctor ? toSource(Ctor) : "";
if (ctorString) switch (ctorString) {
@@ -37012,16 +33707,16 @@ var _publicBundleJs = []byte(`!function(modules) {
return result;
}), module.exports = getTag;
}, function(module, exports, __webpack_require__) {
- var getNative = __webpack_require__(70), root = __webpack_require__(46), DataView = getNative(root, "DataView");
+ var getNative = __webpack_require__(53), root = __webpack_require__(32), DataView = getNative(root, "DataView");
module.exports = DataView;
}, function(module, exports, __webpack_require__) {
- var getNative = __webpack_require__(70), root = __webpack_require__(46), Promise = getNative(root, "Promise");
+ var getNative = __webpack_require__(53), root = __webpack_require__(32), Promise = getNative(root, "Promise");
module.exports = Promise;
}, function(module, exports, __webpack_require__) {
- var getNative = __webpack_require__(70), root = __webpack_require__(46), Set = getNative(root, "Set");
+ var getNative = __webpack_require__(53), root = __webpack_require__(32), Set = getNative(root, "Set");
module.exports = Set;
}, function(module, exports, __webpack_require__) {
- var getNative = __webpack_require__(70), root = __webpack_require__(46), WeakMap = getNative(root, "WeakMap");
+ var getNative = __webpack_require__(53), root = __webpack_require__(32), WeakMap = getNative(root, "WeakMap");
module.exports = WeakMap;
}, function(module, exports, __webpack_require__) {
"use strict";
@@ -37068,7 +33763,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
exports.default = createAnimateManager;
- var _setRafTimeout = __webpack_require__(948), _setRafTimeout2 = function(obj) {
+ var _setRafTimeout = __webpack_require__(641), _setRafTimeout2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -37085,7 +33780,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.default = setRafTimeout;
- var _raf = __webpack_require__(393), _raf2 = function(obj) {
+ var _raf = __webpack_require__(273), _raf2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -37107,7 +33802,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return new Date().getTime() - loadTime;
}, loadTime = new Date().getTime());
}).call(this);
- }).call(exports, __webpack_require__(3));
+ }).call(exports, __webpack_require__(2));
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -37143,17 +33838,17 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.shallowEqual = void 0;
- var _isPlainObject2 = __webpack_require__(394), _isPlainObject3 = _interopRequireDefault(_isPlainObject2), _isEqual2 = __webpack_require__(49), _isEqual3 = _interopRequireDefault(_isEqual2), _isArray2 = __webpack_require__(16), _isArray3 = _interopRequireDefault(_isArray2), _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(obj) {
+ var _isPlainObject2 = __webpack_require__(274), _isPlainObject3 = _interopRequireDefault(_isPlainObject2), _isEqual2 = __webpack_require__(34), _isEqual3 = _interopRequireDefault(_isEqual2), _isArray2 = __webpack_require__(12), _isArray3 = _interopRequireDefault(_isArray2), _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(obj) {
return typeof obj;
} : function(obj) {
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
exports.shallowEqual = shallowEqual, exports.default = pureRenderDecorator;
}, function(module, exports, __webpack_require__) {
- var overArg = __webpack_require__(392), getPrototype = overArg(Object.getPrototypeOf, Object);
+ var overArg = __webpack_require__(272), getPrototype = overArg(Object.getPrototypeOf, Object);
module.exports = getPrototype;
}, function(module, exports, __webpack_require__) {
- var arrayMap = __webpack_require__(157), baseIntersection = __webpack_require__(953), baseRest = __webpack_require__(396), castArrayLikeObject = __webpack_require__(967), intersection = baseRest(function(arrays) {
+ var arrayMap = __webpack_require__(115), baseIntersection = __webpack_require__(646), baseRest = __webpack_require__(276), castArrayLikeObject = __webpack_require__(660), intersection = baseRest(function(arrays) {
var mapped = arrayMap(arrays, castArrayLikeObject);
return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped) : [];
});
@@ -37179,19 +33874,19 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return result;
}
- var SetCache = __webpack_require__(386), arrayIncludes = __webpack_require__(954), arrayIncludesWith = __webpack_require__(959), arrayMap = __webpack_require__(157), baseUnary = __webpack_require__(245), cacheHas = __webpack_require__(387), nativeMin = Math.min;
+ var SetCache = __webpack_require__(266), arrayIncludes = __webpack_require__(647), arrayIncludesWith = __webpack_require__(652), arrayMap = __webpack_require__(115), baseUnary = __webpack_require__(183), cacheHas = __webpack_require__(267), nativeMin = Math.min;
module.exports = baseIntersection;
}, function(module, exports, __webpack_require__) {
function arrayIncludes(array, value) {
return !!(null == array ? 0 : array.length) && baseIndexOf(array, value, 0) > -1;
}
- var baseIndexOf = __webpack_require__(955);
+ var baseIndexOf = __webpack_require__(648);
module.exports = arrayIncludes;
}, function(module, exports, __webpack_require__) {
function baseIndexOf(array, value, fromIndex) {
return value === value ? strictIndexOf(array, value, fromIndex) : baseFindIndex(array, baseIsNaN, fromIndex);
}
- var baseFindIndex = __webpack_require__(956), baseIsNaN = __webpack_require__(957), strictIndexOf = __webpack_require__(958);
+ var baseFindIndex = __webpack_require__(649), baseIsNaN = __webpack_require__(650), strictIndexOf = __webpack_require__(651);
module.exports = baseIndexOf;
}, function(module, exports) {
function baseFindIndex(array, predicate, fromIndex, fromRight) {
@@ -37225,7 +33920,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return otherArgs[start] = transform(array), apply(func, this, otherArgs);
};
}
- var apply = __webpack_require__(961), nativeMax = Math.max;
+ var apply = __webpack_require__(654), nativeMax = Math.max;
module.exports = overRest;
}, function(module, exports) {
function apply(func, thisArg, args) {
@@ -37246,10 +33941,10 @@ var _publicBundleJs = []byte(`!function(modules) {
}
module.exports = apply;
}, function(module, exports, __webpack_require__) {
- var baseSetToString = __webpack_require__(963), shortOut = __webpack_require__(966), setToString = shortOut(baseSetToString);
+ var baseSetToString = __webpack_require__(656), shortOut = __webpack_require__(659), setToString = shortOut(baseSetToString);
module.exports = setToString;
}, function(module, exports, __webpack_require__) {
- var constant = __webpack_require__(964), defineProperty = __webpack_require__(965), identity = __webpack_require__(83), baseSetToString = defineProperty ? function(func, string) {
+ var constant = __webpack_require__(657), defineProperty = __webpack_require__(658), identity = __webpack_require__(63), baseSetToString = defineProperty ? function(func, string) {
return defineProperty(func, "toString", {
configurable: !0,
enumerable: !1,
@@ -37266,7 +33961,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
module.exports = constant;
}, function(module, exports, __webpack_require__) {
- var getNative = __webpack_require__(70), defineProperty = function() {
+ var getNative = __webpack_require__(53), defineProperty = function() {
try {
var func = getNative(Object, "defineProperty");
return func({}, "", {}), func;
@@ -37290,13 +33985,13 @@ var _publicBundleJs = []byte(`!function(modules) {
function castArrayLikeObject(value) {
return isArrayLikeObject(value) ? value : [];
}
- var isArrayLikeObject = __webpack_require__(968);
+ var isArrayLikeObject = __webpack_require__(661);
module.exports = castArrayLikeObject;
}, function(module, exports, __webpack_require__) {
function isArrayLikeObject(value) {
return isObjectLike(value) && isArrayLike(value);
}
- var isArrayLike = __webpack_require__(109), isObjectLike = __webpack_require__(52);
+ var isArrayLike = __webpack_require__(83), isObjectLike = __webpack_require__(36);
module.exports = isArrayLikeObject;
}, function(module, exports, __webpack_require__) {
"use strict";
@@ -37323,7 +34018,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _filter2 = __webpack_require__(970), _filter3 = _interopRequireDefault(_filter2), _extends = Object.assign || function(target) {
+ var _filter2 = __webpack_require__(663), _filter3 = _interopRequireDefault(_filter2), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -37351,7 +34046,7 @@ var _publicBundleJs = []byte(`!function(modules) {
if (Symbol.iterator in Object(arr)) return sliceIterator(arr, i);
throw new TypeError("Invalid attempt to destructure non-iterable instance");
};
- }(), _raf = __webpack_require__(393), _raf2 = _interopRequireDefault(_raf), _util = __webpack_require__(165), alpha = function(begin, end, k) {
+ }(), _raf = __webpack_require__(273), _raf2 = _interopRequireDefault(_raf), _util = __webpack_require__(123), alpha = function(begin, end, k) {
return begin + (end - begin) * k;
}, needContinue = function(_ref) {
return _ref.from !== _ref.to;
@@ -37417,7 +34112,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function filter(collection, predicate) {
return (isArray(collection) ? arrayFilter : baseFilter)(collection, baseIteratee(predicate, 3));
}
- var arrayFilter = __webpack_require__(389), baseFilter = __webpack_require__(971), baseIteratee = __webpack_require__(110), isArray = __webpack_require__(16);
+ var arrayFilter = __webpack_require__(269), baseFilter = __webpack_require__(664), baseIteratee = __webpack_require__(84), isArray = __webpack_require__(12);
module.exports = filter;
}, function(module, exports, __webpack_require__) {
function baseFilter(collection, predicate) {
@@ -37426,16 +34121,16 @@ var _publicBundleJs = []byte(`!function(modules) {
predicate(value, index, collection) && result.push(value);
}), result;
}
- var baseEach = __webpack_require__(397);
+ var baseEach = __webpack_require__(277);
module.exports = baseFilter;
}, function(module, exports, __webpack_require__) {
function baseForOwn(object, iteratee) {
return object && baseFor(object, iteratee, keys);
}
- var baseFor = __webpack_require__(973), keys = __webpack_require__(241);
+ var baseFor = __webpack_require__(666), keys = __webpack_require__(179);
module.exports = baseForOwn;
}, function(module, exports, __webpack_require__) {
- var createBaseFor = __webpack_require__(974), baseFor = createBaseFor();
+ var createBaseFor = __webpack_require__(667), baseFor = createBaseFor();
module.exports = baseFor;
}, function(module, exports) {
function createBaseFor(fromRight) {
@@ -37457,7 +34152,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return collection;
};
}
- var isArrayLike = __webpack_require__(109);
+ var isArrayLike = __webpack_require__(83);
module.exports = createBaseEach;
}, function(module, exports, __webpack_require__) {
function baseMatches(source) {
@@ -37466,7 +34161,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return object === source || baseIsMatch(object, source, matchData);
};
}
- var baseIsMatch = __webpack_require__(977), getMatchData = __webpack_require__(978), matchesStrictComparable = __webpack_require__(399);
+ var baseIsMatch = __webpack_require__(670), getMatchData = __webpack_require__(671), matchesStrictComparable = __webpack_require__(279);
module.exports = baseMatches;
}, function(module, exports, __webpack_require__) {
function baseIsMatch(object, source, matchData, customizer) {
@@ -37489,7 +34184,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return !0;
}
- var Stack = __webpack_require__(384), baseIsEqual = __webpack_require__(240), COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2;
+ var Stack = __webpack_require__(264), baseIsEqual = __webpack_require__(178), COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2;
module.exports = baseIsMatch;
}, function(module, exports, __webpack_require__) {
function getMatchData(object) {
@@ -37499,7 +34194,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return result;
}
- var isStrictComparable = __webpack_require__(398), keys = __webpack_require__(241);
+ var isStrictComparable = __webpack_require__(278), keys = __webpack_require__(179);
module.exports = getMatchData;
}, function(module, exports, __webpack_require__) {
function baseMatchesProperty(path, srcValue) {
@@ -37508,13 +34203,13 @@ var _publicBundleJs = []byte(`!function(modules) {
return void 0 === objValue && objValue === srcValue ? hasIn(object, path) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
};
}
- var baseIsEqual = __webpack_require__(240), get = __webpack_require__(152), hasIn = __webpack_require__(980), isKey = __webpack_require__(228), isStrictComparable = __webpack_require__(398), matchesStrictComparable = __webpack_require__(399), toKey = __webpack_require__(158), COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2;
+ var baseIsEqual = __webpack_require__(178), get = __webpack_require__(165), hasIn = __webpack_require__(673), isKey = __webpack_require__(166), isStrictComparable = __webpack_require__(278), matchesStrictComparable = __webpack_require__(279), toKey = __webpack_require__(116), COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2;
module.exports = baseMatchesProperty;
}, function(module, exports, __webpack_require__) {
function hasIn(object, path) {
return null != object && hasPath(object, path, baseHasIn);
}
- var baseHasIn = __webpack_require__(981), hasPath = __webpack_require__(982);
+ var baseHasIn = __webpack_require__(674), hasPath = __webpack_require__(675);
module.exports = hasIn;
}, function(module, exports) {
function baseHasIn(object, key) {
@@ -37531,13 +34226,13 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return result || ++index != length ? result : !!(length = null == object ? 0 : object.length) && isLength(length) && isIndex(key, length) && (isArray(object) || isArguments(object));
}
- var castPath = __webpack_require__(367), isArguments = __webpack_require__(242), isArray = __webpack_require__(16), isIndex = __webpack_require__(243), isLength = __webpack_require__(244), toKey = __webpack_require__(158);
+ var castPath = __webpack_require__(247), isArguments = __webpack_require__(180), isArray = __webpack_require__(12), isIndex = __webpack_require__(181), isLength = __webpack_require__(182), toKey = __webpack_require__(116);
module.exports = hasPath;
}, function(module, exports, __webpack_require__) {
function property(path) {
return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
}
- var baseProperty = __webpack_require__(984), basePropertyDeep = __webpack_require__(985), isKey = __webpack_require__(228), toKey = __webpack_require__(158);
+ var baseProperty = __webpack_require__(677), basePropertyDeep = __webpack_require__(678), isKey = __webpack_require__(166), toKey = __webpack_require__(116);
module.exports = property;
}, function(module, exports) {
function baseProperty(key) {
@@ -37552,7 +34247,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return baseGet(object, path);
};
}
- var baseGet = __webpack_require__(366);
+ var baseGet = __webpack_require__(246);
module.exports = basePropertyDeep;
}, function(module, exports, __webpack_require__) {
"use strict";
@@ -37594,7 +34289,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _TransitionGroup = __webpack_require__(355), _TransitionGroup2 = _interopRequireDefault(_TransitionGroup), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _AnimateGroupChild = __webpack_require__(987), _AnimateGroupChild2 = _interopRequireDefault(_AnimateGroupChild), AnimateGroup = (_temp = _class = function(_Component) {
+ }(), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _TransitionGroup = __webpack_require__(236), _TransitionGroup2 = _interopRequireDefault(_TransitionGroup), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _AnimateGroupChild = __webpack_require__(680), _AnimateGroupChild2 = _interopRequireDefault(_AnimateGroupChild), AnimateGroup = (_temp = _class = function(_Component) {
function AnimateGroup() {
return _classCallCheck(this, AnimateGroup), _possibleConstructorReturn(this, (AnimateGroup.__proto__ || Object.getPrototypeOf(AnimateGroup)).apply(this, arguments));
}
@@ -37657,7 +34352,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _class, _temp2, _isNumber2 = __webpack_require__(232), _isNumber3 = _interopRequireDefault(_isNumber2), _extends = Object.assign || function(target) {
+ var _class, _temp2, _isNumber2 = __webpack_require__(170), _isNumber3 = _interopRequireDefault(_isNumber2), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -37675,7 +34370,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _Transition = __webpack_require__(149), _Transition2 = _interopRequireDefault(_Transition), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _Animate = __webpack_require__(383), _Animate2 = _interopRequireDefault(_Animate), parseDurationOfSingleTransition = function() {
+ }(), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _Transition = __webpack_require__(108), _Transition2 = _interopRequireDefault(_Transition), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _Animate = __webpack_require__(263), _Animate2 = _interopRequireDefault(_Animate), parseDurationOfSingleTransition = function() {
var options = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, steps = options.steps, duration = options.duration;
return steps && steps.length ? steps.reduce(function(result, entry) {
return result + ((0, _isNumber3.default)(entry.duration) && entry.duration > 0 ? entry.duration : 0);
@@ -37755,7 +34450,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isArray__ = __webpack_require__(16), __WEBPACK_IMPORTED_MODULE_0_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_4__util_DataUtils__ = __webpack_require__(12), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isArray__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_0_lodash_isArray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isArray__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_4__util_DataUtils__ = __webpack_require__(9), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -37877,7 +34572,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_debounce__ = __webpack_require__(246), __WEBPACK_IMPORTED_MODULE_0_lodash_debounce___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_debounce__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_3_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_classnames__), __WEBPACK_IMPORTED_MODULE_4_react_resize_detector__ = __webpack_require__(991), __WEBPACK_IMPORTED_MODULE_4_react_resize_detector___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react_resize_detector__), __WEBPACK_IMPORTED_MODULE_5__util_DataUtils__ = __webpack_require__(12), __WEBPACK_IMPORTED_MODULE_6__util_LogUtils__ = __webpack_require__(401), _createClass = function() {
+ var _class, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_debounce__ = __webpack_require__(157), __WEBPACK_IMPORTED_MODULE_0_lodash_debounce___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_debounce__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_3_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_classnames__), __WEBPACK_IMPORTED_MODULE_4_react_resize_detector__ = __webpack_require__(683), __WEBPACK_IMPORTED_MODULE_4_react_resize_detector___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react_resize_detector__), __WEBPACK_IMPORTED_MODULE_5__util_DataUtils__ = __webpack_require__(9), __WEBPACK_IMPORTED_MODULE_6__util_LogUtils__ = __webpack_require__(280), _createClass = function() {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
@@ -37989,16 +34684,11 @@ var _publicBundleJs = []byte(`!function(modules) {
}, _temp);
__webpack_exports__.a = ResponsiveContainer;
}, function(module, exports, __webpack_require__) {
- var root = __webpack_require__(46), now = function() {
- return root.Date.now();
- };
- module.exports = now;
-}, function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _ResizeDetector = __webpack_require__(992), _ResizeDetector2 = function(obj) {
+ var _ResizeDetector = __webpack_require__(684), _ResizeDetector2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -38072,7 +34762,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _resizeDetectorStyles = __webpack_require__(993), ResizeDetector = function(_Component) {
+ }(), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(1), _propTypes2 = _interopRequireDefault(_propTypes), _resizeDetectorStyles = __webpack_require__(685), ResizeDetector = function(_Component) {
function ResizeDetector() {
_classCallCheck(this, ResizeDetector);
var _this = _possibleConstructorReturn(this, (ResizeDetector.__proto__ || Object.getPrototypeOf(ResizeDetector)).call(this));
@@ -38249,7 +34939,7 @@ var _publicBundleJs = []byte(`!function(modules) {
uniqueLowerCaseUnits.push(matches[1].toLowerCase())), matches = unitRegEx.exec(expression));
return uniqueUnits;
}
- var stack, balanced = __webpack_require__(995), reduceFunctionCall = __webpack_require__(996), mexp = __webpack_require__(998), MAX_STACK = 100, NESTED_CALC_RE = /(\+|\-|\*|\\|[^a-z]|)(\s*)(\()/g;
+ var stack, balanced = __webpack_require__(687), reduceFunctionCall = __webpack_require__(688), mexp = __webpack_require__(690), MAX_STACK = 100, NESTED_CALC_RE = /(\+|\-|\*|\\|[^a-z]|)(\s*)(\()/g;
module.exports = reduceCSSCalc;
}, function(module, exports) {
function balanced(a, b, str) {
@@ -38303,7 +34993,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function evalFunctionCall(string, functionIdentifier, callback, call, functionRE) {
return callback(reduceFunctionCall(string, functionRE, callback), functionIdentifier, call);
}
- var balanced = __webpack_require__(997);
+ var balanced = __webpack_require__(689);
module.exports = reduceFunctionCall;
}, function(module, exports) {
function balanced(a, b, str) {
@@ -38333,7 +35023,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
module.exports = balanced, balanced.range = range;
}, function(module, exports, __webpack_require__) {
- var Mexp = __webpack_require__(999);
+ var Mexp = __webpack_require__(691);
Mexp.prototype.formulaEval = function() {
"use strict";
for (var pop1, pop2, pop3, disp = [], arr = this.value, i = 0; i < arr.length; i++) 1 === arr[i].type || 3 === arr[i].type ? disp.push({
@@ -38366,7 +35056,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return disp[0].value;
}, module.exports = Mexp;
}, function(module, exports, __webpack_require__) {
- var Mexp = __webpack_require__(1e3);
+ var Mexp = __webpack_require__(692);
Mexp.prototype.postfixEval = function(UserDefined) {
"use strict";
UserDefined = UserDefined || {}, UserDefined.PI = Math.PI, UserDefined.E = Math.E;
@@ -38405,7 +35095,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return void 0 === tokens ? this.lex(str).toPostfix().postfixEval() : void 0 === obj ? void 0 !== tokens.length ? this.lex(str, tokens).toPostfix().postfixEval() : this.lex(str).toPostfix().postfixEval(tokens) : this.lex(str, tokens).toPostfix().postfixEval(obj);
}, module.exports = Mexp;
}, function(module, exports, __webpack_require__) {
- var Mexp = __webpack_require__(1001);
+ var Mexp = __webpack_require__(693);
Mexp.prototype.toPostfix = function() {
"use strict";
for (var elem, popped, prep, pre, ele, post = [], stack = [ {
@@ -38436,7 +35126,7 @@ var _publicBundleJs = []byte(`!function(modules) {
for (var f = 0; f < x; f++) if (str1[i + f] !== str2[f]) return !1;
return !0;
}
- var Mexp = __webpack_require__(1002), token = [ "sin", "cos", "tan", "pi", "(", ")", "P", "C", "asin", "acos", "atan", "7", "8", "9", "int", "cosh", "acosh", "ln", "^", "root", "4", "5", "6", "/", "!", "tanh", "atanh", "Mod", "1", "2", "3", "*", "sinh", "asinh", "e", "log", "0", ".", "+", "-", ",", "Sigma", "n", "Pi", "pow" ], show = [ "sin", "cos", "tan", "&pi;", "(", ")", "P", "C", "asin", "acos", "atan", "7", "8", "9", "Int", "cosh", "acosh", " ln", "^", "root", "4", "5", "6", "&divide;", "!", "tanh", "atanh", " Mod ", "1", "2", "3", "&times;", "sinh", "asinh", "e", " log", "0", ".", "+", "-", ",", "&Sigma;", "n", "&Pi;", "pow" ], eva = [ Mexp.math.sin, Mexp.math.cos, Mexp.math.tan, "PI", "(", ")", Mexp.math.P, Mexp.math.C, Mexp.math.asin, Mexp.math.acos, Mexp.math.atan, "7", "8", "9", Math.floor, Mexp.math.cosh, Mexp.math.acosh, Math.log, Math.pow, Math.sqrt, "4", "5", "6", Mexp.math.div, Mexp.math.fact, Mexp.math.tanh, Mexp.math.atanh, Mexp.math.mod, "1", "2", "3", Mexp.math.mul, Mexp.math.sinh, Mexp.math.asinh, "E", Mexp.math.log, "0", ".", Mexp.math.add, Mexp.math.sub, ",", Mexp.math.sigma, "n", Mexp.math.Pi, Math.pow ], preced = {
+ var Mexp = __webpack_require__(694), token = [ "sin", "cos", "tan", "pi", "(", ")", "P", "C", "asin", "acos", "atan", "7", "8", "9", "int", "cosh", "acosh", "ln", "^", "root", "4", "5", "6", "/", "!", "tanh", "atanh", "Mod", "1", "2", "3", "*", "sinh", "asinh", "e", "log", "0", ".", "+", "-", ",", "Sigma", "n", "Pi", "pow" ], show = [ "sin", "cos", "tan", "&pi;", "(", ")", "P", "C", "asin", "acos", "atan", "7", "8", "9", "Int", "cosh", "acosh", " ln", "^", "root", "4", "5", "6", "&divide;", "!", "tanh", "atanh", " Mod ", "1", "2", "3", "&times;", "sinh", "asinh", "e", " log", "0", ".", "+", "-", ",", "&Sigma;", "n", "&Pi;", "pow" ], eva = [ Mexp.math.sin, Mexp.math.cos, Mexp.math.tan, "PI", "(", ")", Mexp.math.P, Mexp.math.C, Mexp.math.asin, Mexp.math.acos, Mexp.math.atan, "7", "8", "9", Math.floor, Mexp.math.cosh, Mexp.math.acosh, Math.log, Math.pow, Math.sqrt, "4", "5", "6", Mexp.math.div, Mexp.math.fact, Mexp.math.tanh, Mexp.math.atanh, Mexp.math.mod, "1", "2", "3", Mexp.math.mul, Mexp.math.sinh, Mexp.math.asinh, "E", Mexp.math.log, "0", ".", Mexp.math.add, Mexp.math.sub, ",", Mexp.math.sigma, "n", Mexp.math.Pi, Math.pow ], preced = {
0: 11,
1: 0,
2: 3,
@@ -38731,13 +35421,13 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return result;
}
- var arrayPush = __webpack_require__(388), isFlattenable = __webpack_require__(1004);
+ var arrayPush = __webpack_require__(268), isFlattenable = __webpack_require__(696);
module.exports = baseFlatten;
}, function(module, exports, __webpack_require__) {
function isFlattenable(value) {
return isArray(value) || isArguments(value) || !!(spreadableSymbol && value && value[spreadableSymbol]);
}
- var Symbol = __webpack_require__(104), isArguments = __webpack_require__(242), isArray = __webpack_require__(16), spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : void 0;
+ var Symbol = __webpack_require__(77), isArguments = __webpack_require__(180), isArray = __webpack_require__(12), spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : void 0;
module.exports = isFlattenable;
}, function(module, exports, __webpack_require__) {
function baseOrderBy(collection, iteratees, orders) {
@@ -38756,7 +35446,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return compareMultiple(object, other, orders);
});
}
- var arrayMap = __webpack_require__(157), baseIteratee = __webpack_require__(110), baseMap = __webpack_require__(1006), baseSortBy = __webpack_require__(1007), baseUnary = __webpack_require__(245), compareMultiple = __webpack_require__(1008), identity = __webpack_require__(83);
+ var arrayMap = __webpack_require__(115), baseIteratee = __webpack_require__(84), baseMap = __webpack_require__(698), baseSortBy = __webpack_require__(699), baseUnary = __webpack_require__(183), compareMultiple = __webpack_require__(700), identity = __webpack_require__(63);
module.exports = baseOrderBy;
}, function(module, exports, __webpack_require__) {
function baseMap(collection, iteratee) {
@@ -38765,7 +35455,7 @@ var _publicBundleJs = []byte(`!function(modules) {
result[++index] = iteratee(value, key, collection);
}), result;
}
- var baseEach = __webpack_require__(397), isArrayLike = __webpack_require__(109);
+ var baseEach = __webpack_require__(277), isArrayLike = __webpack_require__(83);
module.exports = baseMap;
}, function(module, exports) {
function baseSortBy(array, comparer) {
@@ -38785,7 +35475,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return object.index - other.index;
}
- var compareAscending = __webpack_require__(1009);
+ var compareAscending = __webpack_require__(701);
module.exports = compareMultiple;
}, function(module, exports, __webpack_require__) {
function compareAscending(value, other) {
@@ -38796,20 +35486,20 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return 0;
}
- var isSymbol = __webpack_require__(82);
+ var isSymbol = __webpack_require__(62);
module.exports = compareAscending;
}, function(module, exports, __webpack_require__) {
function max(array) {
return array && array.length ? baseExtremum(array, identity, baseGt) : void 0;
}
- var baseExtremum = __webpack_require__(166), baseGt = __webpack_require__(404), identity = __webpack_require__(83);
+ var baseExtremum = __webpack_require__(124), baseGt = __webpack_require__(283), identity = __webpack_require__(63);
module.exports = max;
}, function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _getNiceTickValues = __webpack_require__(1012);
+ var _getNiceTickValues = __webpack_require__(704);
Object.defineProperty(exports, "getTickValues", {
enumerable: !0,
get: function() {
@@ -38917,7 +35607,7 @@ var _publicBundleJs = []byte(`!function(modules) {
if (Symbol.iterator in Object(arr)) return sliceIterator(arr, i);
throw new TypeError("Invalid attempt to destructure non-iterable instance");
};
- }(), _utils = __webpack_require__(407), _arithmetic = __webpack_require__(1013), _arithmetic2 = function(obj) {
+ }(), _utils = __webpack_require__(286), _arithmetic = __webpack_require__(705), _arithmetic2 = function(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
@@ -38969,7 +35659,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object.defineProperty(exports, "__esModule", {
value: !0
});
- var _utils = __webpack_require__(407), interpolateNumber = (0, _utils.curry)(function(a, b, t) {
+ var _utils = __webpack_require__(286), interpolateNumber = (0, _utils.curry)(function(a, b, t) {
var newA = +a;
return newA + t * (+b - newA);
}), uninterpolateNumber = (0, _utils.curry)(function(a, b, x) {
@@ -39044,16 +35734,16 @@ var _publicBundleJs = []byte(`!function(modules) {
return pointish(band().paddingInner(1));
}
__webpack_exports__.a = band, __webpack_exports__.b = point;
- var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(53), __WEBPACK_IMPORTED_MODULE_1__ordinal__ = __webpack_require__(421);
+ var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(37), __WEBPACK_IMPORTED_MODULE_1__ordinal__ = __webpack_require__(300);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(411);
+ __webpack_require__(290);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(415), __webpack_require__(409), __webpack_require__(1018), __webpack_require__(414),
- __webpack_require__(1019), __webpack_require__(416), __webpack_require__(417), __webpack_require__(418);
+ __webpack_require__(294), __webpack_require__(288), __webpack_require__(710), __webpack_require__(293),
+ __webpack_require__(711), __webpack_require__(295), __webpack_require__(296), __webpack_require__(297);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_exports__.a = function(x) {
@@ -39068,43 +35758,43 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(415), __webpack_require__(84), __webpack_require__(112), __webpack_require__(248);
+ __webpack_require__(294), __webpack_require__(64), __webpack_require__(86), __webpack_require__(185);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(412);
+ __webpack_require__(291);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(112);
+ __webpack_require__(86);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(84), __webpack_require__(112), __webpack_require__(248);
+ __webpack_require__(64), __webpack_require__(86), __webpack_require__(185);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(84);
+ __webpack_require__(64);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(420);
+ __webpack_require__(299);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_2__src_map__ = (__webpack_require__(1032), __webpack_require__(1033),
- __webpack_require__(249));
+ var __WEBPACK_IMPORTED_MODULE_2__src_map__ = (__webpack_require__(724), __webpack_require__(725),
+ __webpack_require__(186));
__webpack_require__.d(__webpack_exports__, "a", function() {
return __WEBPACK_IMPORTED_MODULE_2__src_map__.a;
});
- __webpack_require__(1034), __webpack_require__(1035), __webpack_require__(1036);
+ __webpack_require__(726), __webpack_require__(727), __webpack_require__(728);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(249);
+ __webpack_require__(186);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
function Set() {}
@@ -39118,7 +35808,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return set;
}
- var __WEBPACK_IMPORTED_MODULE_0__map__ = __webpack_require__(249), proto = __WEBPACK_IMPORTED_MODULE_0__map__.a.prototype;
+ var __WEBPACK_IMPORTED_MODULE_0__map__ = __webpack_require__(186), proto = __WEBPACK_IMPORTED_MODULE_0__map__.a.prototype;
Set.prototype = set.prototype = {
constructor: Set,
has: proto.has,
@@ -39154,7 +35844,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, Object(__WEBPACK_IMPORTED_MODULE_1__linear__.b)(scale);
}
__webpack_exports__.a = identity;
- var __WEBPACK_IMPORTED_MODULE_0__array__ = __webpack_require__(73), __WEBPACK_IMPORTED_MODULE_1__linear__ = __webpack_require__(113), __WEBPACK_IMPORTED_MODULE_2__number__ = __webpack_require__(430);
+ var __WEBPACK_IMPORTED_MODULE_0__array__ = __webpack_require__(56), __WEBPACK_IMPORTED_MODULE_1__linear__ = __webpack_require__(87), __WEBPACK_IMPORTED_MODULE_2__number__ = __webpack_require__(309);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
function labConvert(o) {
@@ -39198,7 +35888,7 @@ var _publicBundleJs = []byte(`!function(modules) {
this.h = +h, this.c = +c, this.l = +l, this.opacity = +opacity;
}
__webpack_exports__.a = lab, __webpack_exports__.b = hcl;
- var __WEBPACK_IMPORTED_MODULE_0__define__ = __webpack_require__(252), __WEBPACK_IMPORTED_MODULE_1__color__ = __webpack_require__(251), __WEBPACK_IMPORTED_MODULE_2__math__ = __webpack_require__(422), Xn = .95047, Yn = 1, Zn = 1.08883, t0 = 4 / 29, t1 = 6 / 29, t2 = 3 * t1 * t1, t3 = t1 * t1 * t1;
+ var __WEBPACK_IMPORTED_MODULE_0__define__ = __webpack_require__(189), __WEBPACK_IMPORTED_MODULE_1__color__ = __webpack_require__(188), __WEBPACK_IMPORTED_MODULE_2__math__ = __webpack_require__(301), Xn = .95047, Yn = 1, Zn = 1.08883, t0 = 4 / 29, t1 = 6 / 29, t2 = 3 * t1 * t1, t3 = t1 * t1 * t1;
Object(__WEBPACK_IMPORTED_MODULE_0__define__.a)(Lab, lab, Object(__WEBPACK_IMPORTED_MODULE_0__define__.b)(__WEBPACK_IMPORTED_MODULE_1__color__.a, {
brighter: function(k) {
return new Lab(this.l + 18 * (null == k ? 1 : k), this.a, this.b, this.opacity);
@@ -39236,7 +35926,7 @@ var _publicBundleJs = []byte(`!function(modules) {
this.h = +h, this.s = +s, this.l = +l, this.opacity = +opacity;
}
__webpack_exports__.a = cubehelix;
- var __WEBPACK_IMPORTED_MODULE_0__define__ = __webpack_require__(252), __WEBPACK_IMPORTED_MODULE_1__color__ = __webpack_require__(251), __WEBPACK_IMPORTED_MODULE_2__math__ = __webpack_require__(422), A = -.14861, B = 1.78277, C = -.29227, D = -.90649, E = 1.97294, ED = E * D, EB = E * B, BC_DA = B * C - D * A;
+ var __WEBPACK_IMPORTED_MODULE_0__define__ = __webpack_require__(189), __WEBPACK_IMPORTED_MODULE_1__color__ = __webpack_require__(188), __WEBPACK_IMPORTED_MODULE_2__math__ = __webpack_require__(301), A = -.14861, B = 1.78277, C = -.29227, D = -.90649, E = 1.97294, ED = E * D, EB = E * B, BC_DA = B * C - D * A;
Object(__WEBPACK_IMPORTED_MODULE_0__define__.a)(Cubehelix, cubehelix, Object(__WEBPACK_IMPORTED_MODULE_0__define__.b)(__WEBPACK_IMPORTED_MODULE_1__color__.a, {
brighter: function(k) {
return k = null == k ? __WEBPACK_IMPORTED_MODULE_1__color__.c : Math.pow(__WEBPACK_IMPORTED_MODULE_1__color__.c, k),
@@ -39310,7 +36000,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
};
}
- var __WEBPACK_IMPORTED_MODULE_0__number__ = __webpack_require__(167), __WEBPACK_IMPORTED_MODULE_1__parse__ = __webpack_require__(1042);
+ var __WEBPACK_IMPORTED_MODULE_0__number__ = __webpack_require__(125), __WEBPACK_IMPORTED_MODULE_1__parse__ = __webpack_require__(734);
interpolateTransform(__WEBPACK_IMPORTED_MODULE_1__parse__.a, "px, ", "px)", "deg)"),
interpolateTransform(__WEBPACK_IMPORTED_MODULE_1__parse__.b, ", ", ")", ")");
}, function(module, __webpack_exports__, __webpack_require__) {
@@ -39327,7 +36017,7 @@ var _publicBundleJs = []byte(`!function(modules) {
Object(__WEBPACK_IMPORTED_MODULE_0__decompose__.a)(value.a, value.b, value.c, value.d, value.e, value.f)) : __WEBPACK_IMPORTED_MODULE_0__decompose__.b);
}
__webpack_exports__.a = parseCss, __webpack_exports__.b = parseSvg;
- var cssNode, cssRoot, cssView, svgNode, __WEBPACK_IMPORTED_MODULE_0__decompose__ = __webpack_require__(1043);
+ var cssNode, cssRoot, cssView, svgNode, __WEBPACK_IMPORTED_MODULE_0__decompose__ = __webpack_require__(735);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.d(__webpack_exports__, "b", function() {
@@ -39369,11 +36059,11 @@ var _publicBundleJs = []byte(`!function(modules) {
};
};
}
- var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(61), __WEBPACK_IMPORTED_MODULE_1__color__ = __webpack_require__(115);
+ var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(44), __WEBPACK_IMPORTED_MODULE_1__color__ = __webpack_require__(89);
hsl(__WEBPACK_IMPORTED_MODULE_1__color__.c), hsl(__WEBPACK_IMPORTED_MODULE_1__color__.a);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- __webpack_require__(61), __webpack_require__(115);
+ __webpack_require__(44), __webpack_require__(89);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
function hcl(hue) {
@@ -39385,7 +36075,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
};
}
- var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(61), __WEBPACK_IMPORTED_MODULE_1__color__ = __webpack_require__(115);
+ var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(44), __WEBPACK_IMPORTED_MODULE_1__color__ = __webpack_require__(89);
hcl(__WEBPACK_IMPORTED_MODULE_1__color__.c), hcl(__WEBPACK_IMPORTED_MODULE_1__color__.a);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -39404,13 +36094,13 @@ var _publicBundleJs = []byte(`!function(modules) {
__webpack_require__.d(__webpack_exports__, "a", function() {
return cubehelixLong;
});
- var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(61), __WEBPACK_IMPORTED_MODULE_1__color__ = __webpack_require__(115), cubehelixLong = (cubehelix(__WEBPACK_IMPORTED_MODULE_1__color__.c),
+ var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(44), __WEBPACK_IMPORTED_MODULE_1__color__ = __webpack_require__(89), cubehelixLong = (cubehelix(__WEBPACK_IMPORTED_MODULE_1__color__.c),
cubehelix(__WEBPACK_IMPORTED_MODULE_1__color__.a));
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(53), __WEBPACK_IMPORTED_MODULE_1_d3_format__ = __webpack_require__(431);
+ var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(37), __WEBPACK_IMPORTED_MODULE_1_d3_format__ = __webpack_require__(310);
__webpack_exports__.a = function(domain, count, specifier) {
var precision, start = domain[0], stop = domain[domain.length - 1], step = Object(__WEBPACK_IMPORTED_MODULE_0_d3_array__.g)(start, stop, null == count ? 10 : count);
switch (specifier = Object(__WEBPACK_IMPORTED_MODULE_1_d3_format__.c)(null == specifier ? ",f" : specifier),
@@ -39441,7 +36131,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "b", function() {
return formatPrefix;
});
- var locale, format, formatPrefix, __WEBPACK_IMPORTED_MODULE_0__locale__ = __webpack_require__(432);
+ var locale, format, formatPrefix, __WEBPACK_IMPORTED_MODULE_0__locale__ = __webpack_require__(311);
!function(definition) {
locale = Object(__WEBPACK_IMPORTED_MODULE_0__locale__.a)(definition), format = locale.format,
formatPrefix = locale.formatPrefix;
@@ -39492,7 +36182,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__formatDecimal__ = __webpack_require__(255);
+ var __WEBPACK_IMPORTED_MODULE_0__formatDecimal__ = __webpack_require__(192);
__webpack_exports__.a = function(x, p) {
var d = Object(__WEBPACK_IMPORTED_MODULE_0__formatDecimal__.a)(x, p);
if (!d) return x + "";
@@ -39506,19 +36196,19 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__exponent__ = __webpack_require__(169);
+ var __WEBPACK_IMPORTED_MODULE_0__exponent__ = __webpack_require__(127);
__webpack_exports__.a = function(step) {
return Math.max(0, -Object(__WEBPACK_IMPORTED_MODULE_0__exponent__.a)(Math.abs(step)));
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__exponent__ = __webpack_require__(169);
+ var __WEBPACK_IMPORTED_MODULE_0__exponent__ = __webpack_require__(127);
__webpack_exports__.a = function(step, value) {
return Math.max(0, 3 * Math.max(-8, Math.min(8, Math.floor(Object(__WEBPACK_IMPORTED_MODULE_0__exponent__.a)(value) / 3))) - Object(__WEBPACK_IMPORTED_MODULE_0__exponent__.a)(Math.abs(step)));
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__exponent__ = __webpack_require__(169);
+ var __WEBPACK_IMPORTED_MODULE_0__exponent__ = __webpack_require__(127);
__webpack_exports__.a = function(step, max) {
return step = Math.abs(step), max = Math.abs(max) - step, Math.max(0, Object(__WEBPACK_IMPORTED_MODULE_0__exponent__.a)(max) - Object(__WEBPACK_IMPORTED_MODULE_0__exponent__.a)(step)) + 1;
};
@@ -39604,7 +36294,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, scale;
}
__webpack_exports__.a = log;
- var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(53), __WEBPACK_IMPORTED_MODULE_1_d3_format__ = __webpack_require__(431), __WEBPACK_IMPORTED_MODULE_2__constant__ = __webpack_require__(254), __WEBPACK_IMPORTED_MODULE_3__nice__ = __webpack_require__(436), __WEBPACK_IMPORTED_MODULE_4__continuous__ = __webpack_require__(168);
+ var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(37), __WEBPACK_IMPORTED_MODULE_1_d3_format__ = __webpack_require__(310), __WEBPACK_IMPORTED_MODULE_2__constant__ = __webpack_require__(191), __WEBPACK_IMPORTED_MODULE_3__nice__ = __webpack_require__(315), __WEBPACK_IMPORTED_MODULE_4__continuous__ = __webpack_require__(126);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
function raise(x, exponent) {
@@ -39632,7 +36322,7 @@ var _publicBundleJs = []byte(`!function(modules) {
return pow().exponent(.5);
}
__webpack_exports__.a = pow, __webpack_exports__.b = sqrt;
- var __WEBPACK_IMPORTED_MODULE_0__constant__ = __webpack_require__(254), __WEBPACK_IMPORTED_MODULE_1__linear__ = __webpack_require__(113), __WEBPACK_IMPORTED_MODULE_2__continuous__ = __webpack_require__(168);
+ var __WEBPACK_IMPORTED_MODULE_0__constant__ = __webpack_require__(191), __WEBPACK_IMPORTED_MODULE_1__linear__ = __webpack_require__(87), __WEBPACK_IMPORTED_MODULE_2__continuous__ = __webpack_require__(126);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
function quantile() {
@@ -39663,7 +36353,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, scale;
}
__webpack_exports__.a = quantile;
- var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(53), __WEBPACK_IMPORTED_MODULE_1__array__ = __webpack_require__(73);
+ var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(37), __WEBPACK_IMPORTED_MODULE_1__array__ = __webpack_require__(56);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
function quantize() {
@@ -39689,7 +36379,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, Object(__WEBPACK_IMPORTED_MODULE_2__linear__.b)(scale);
}
__webpack_exports__.a = quantize;
- var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(53), __WEBPACK_IMPORTED_MODULE_1__array__ = __webpack_require__(73), __WEBPACK_IMPORTED_MODULE_2__linear__ = __webpack_require__(113);
+ var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(37), __WEBPACK_IMPORTED_MODULE_1__array__ = __webpack_require__(56), __WEBPACK_IMPORTED_MODULE_2__linear__ = __webpack_require__(87);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
function threshold() {
@@ -39711,10 +36401,10 @@ var _publicBundleJs = []byte(`!function(modules) {
}, scale;
}
__webpack_exports__.a = threshold;
- var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(53), __WEBPACK_IMPORTED_MODULE_1__array__ = __webpack_require__(73);
+ var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(37), __WEBPACK_IMPORTED_MODULE_1__array__ = __webpack_require__(56);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(24), millisecond = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function() {}, function(date, step) {
+ var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(18), millisecond = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function() {}, function(date, step) {
date.setTime(+date + step);
}, function(start, end) {
return end - start;
@@ -39731,7 +36421,7 @@ var _publicBundleJs = []byte(`!function(modules) {
millisecond.range;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(24), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(54), second = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
+ var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(38), second = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
date.setTime(Math.floor(date / __WEBPACK_IMPORTED_MODULE_1__duration__.d) * __WEBPACK_IMPORTED_MODULE_1__duration__.d);
}, function(date, step) {
date.setTime(+date + step * __WEBPACK_IMPORTED_MODULE_1__duration__.d);
@@ -39744,7 +36434,7 @@ var _publicBundleJs = []byte(`!function(modules) {
second.range;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(24), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(54), minute = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
+ var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(38), minute = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
date.setTime(Math.floor(date / __WEBPACK_IMPORTED_MODULE_1__duration__.c) * __WEBPACK_IMPORTED_MODULE_1__duration__.c);
}, function(date, step) {
date.setTime(+date + step * __WEBPACK_IMPORTED_MODULE_1__duration__.c);
@@ -39757,7 +36447,7 @@ var _publicBundleJs = []byte(`!function(modules) {
minute.range;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(24), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(54), hour = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
+ var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(38), hour = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
var offset = date.getTimezoneOffset() * __WEBPACK_IMPORTED_MODULE_1__duration__.c % __WEBPACK_IMPORTED_MODULE_1__duration__.b;
offset < 0 && (offset += __WEBPACK_IMPORTED_MODULE_1__duration__.b), date.setTime(Math.floor((+date - offset) / __WEBPACK_IMPORTED_MODULE_1__duration__.b) * __WEBPACK_IMPORTED_MODULE_1__duration__.b + offset);
}, function(date, step) {
@@ -39771,7 +36461,7 @@ var _publicBundleJs = []byte(`!function(modules) {
hour.range;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(24), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(54), day = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
+ var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(38), day = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
date.setHours(0, 0, 0, 0);
}, function(date, step) {
date.setDate(date.getDate() + step);
@@ -39800,12 +36490,12 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "c", function() {
return thursday;
});
- var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(24), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(54), sunday = weekday(0), monday = weekday(1), tuesday = weekday(2), wednesday = weekday(3), thursday = weekday(4), friday = weekday(5), saturday = weekday(6);
+ var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(38), sunday = weekday(0), monday = weekday(1), tuesday = weekday(2), wednesday = weekday(3), thursday = weekday(4), friday = weekday(5), saturday = weekday(6);
sunday.range, monday.range, tuesday.range, wednesday.range, thursday.range, friday.range,
saturday.range;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(24), month = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
+ var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(18), month = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
date.setDate(1), date.setHours(0, 0, 0, 0);
}, function(date, step) {
date.setMonth(date.getMonth() + step);
@@ -39818,7 +36508,7 @@ var _publicBundleJs = []byte(`!function(modules) {
month.range;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(24), year = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
+ var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(18), year = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
date.setMonth(0, 1), date.setHours(0, 0, 0, 0);
}, function(date, step) {
date.setFullYear(date.getFullYear() + step);
@@ -39837,7 +36527,7 @@ var _publicBundleJs = []byte(`!function(modules) {
year.range;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(24), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(54), utcMinute = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
+ var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(38), utcMinute = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
date.setUTCSeconds(0, 0);
}, function(date, step) {
date.setTime(+date + step * __WEBPACK_IMPORTED_MODULE_1__duration__.c);
@@ -39850,7 +36540,7 @@ var _publicBundleJs = []byte(`!function(modules) {
utcMinute.range;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(24), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(54), utcHour = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
+ var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(38), utcHour = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
date.setUTCMinutes(0, 0, 0);
}, function(date, step) {
date.setTime(+date + step * __WEBPACK_IMPORTED_MODULE_1__duration__.b);
@@ -39863,7 +36553,7 @@ var _publicBundleJs = []byte(`!function(modules) {
utcHour.range;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(24), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(54), utcDay = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
+ var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(38), utcDay = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
date.setUTCHours(0, 0, 0, 0);
}, function(date, step) {
date.setUTCDate(date.getUTCDate() + step);
@@ -39892,12 +36582,12 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "c", function() {
return utcThursday;
});
- var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(24), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(54), utcSunday = utcWeekday(0), utcMonday = utcWeekday(1), utcTuesday = utcWeekday(2), utcWednesday = utcWeekday(3), utcThursday = utcWeekday(4), utcFriday = utcWeekday(5), utcSaturday = utcWeekday(6);
+ var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_1__duration__ = __webpack_require__(38), utcSunday = utcWeekday(0), utcMonday = utcWeekday(1), utcTuesday = utcWeekday(2), utcWednesday = utcWeekday(3), utcThursday = utcWeekday(4), utcFriday = utcWeekday(5), utcSaturday = utcWeekday(6);
utcSunday.range, utcMonday.range, utcTuesday.range, utcWednesday.range, utcThursday.range,
utcFriday.range, utcSaturday.range;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(24), utcMonth = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
+ var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(18), utcMonth = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
date.setUTCDate(1), date.setUTCHours(0, 0, 0, 0);
}, function(date, step) {
date.setUTCMonth(date.getUTCMonth() + step);
@@ -39910,7 +36600,7 @@ var _publicBundleJs = []byte(`!function(modules) {
utcMonth.range;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(24), utcYear = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
+ var __WEBPACK_IMPORTED_MODULE_0__interval__ = __webpack_require__(18), utcYear = Object(__WEBPACK_IMPORTED_MODULE_0__interval__.a)(function(date) {
date.setUTCMonth(0, 1), date.setUTCHours(0, 0, 0, 0);
}, function(date, step) {
date.setUTCFullYear(date.getUTCFullYear() + step);
@@ -39934,33 +36624,33 @@ var _publicBundleJs = []byte(`!function(modules) {
var date = new Date(string);
return isNaN(date) ? null : date;
}
- var __WEBPACK_IMPORTED_MODULE_0__isoFormat__ = __webpack_require__(440), __WEBPACK_IMPORTED_MODULE_1__defaultLocale__ = __webpack_require__(257);
+ var __WEBPACK_IMPORTED_MODULE_0__isoFormat__ = __webpack_require__(319), __WEBPACK_IMPORTED_MODULE_1__defaultLocale__ = __webpack_require__(194);
+new Date("2000-01-01T00:00:00.000Z") || Object(__WEBPACK_IMPORTED_MODULE_1__defaultLocale__.c)(__WEBPACK_IMPORTED_MODULE_0__isoFormat__.a);
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__time__ = __webpack_require__(437), __WEBPACK_IMPORTED_MODULE_1_d3_time_format__ = __webpack_require__(438), __WEBPACK_IMPORTED_MODULE_2_d3_time__ = __webpack_require__(256);
+ var __WEBPACK_IMPORTED_MODULE_0__time__ = __webpack_require__(316), __WEBPACK_IMPORTED_MODULE_1_d3_time_format__ = __webpack_require__(317), __WEBPACK_IMPORTED_MODULE_2_d3_time__ = __webpack_require__(193);
__webpack_exports__.a = function() {
return Object(__WEBPACK_IMPORTED_MODULE_0__time__.a)(__WEBPACK_IMPORTED_MODULE_2_d3_time__.v, __WEBPACK_IMPORTED_MODULE_2_d3_time__.q, __WEBPACK_IMPORTED_MODULE_2_d3_time__.u, __WEBPACK_IMPORTED_MODULE_2_d3_time__.l, __WEBPACK_IMPORTED_MODULE_2_d3_time__.m, __WEBPACK_IMPORTED_MODULE_2_d3_time__.o, __WEBPACK_IMPORTED_MODULE_2_d3_time__.r, __WEBPACK_IMPORTED_MODULE_2_d3_time__.n, __WEBPACK_IMPORTED_MODULE_1_d3_time_format__.b).domain([ Date.UTC(2e3, 0, 1), Date.UTC(2e3, 0, 2) ]);
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__colors__ = __webpack_require__(116);
+ var __WEBPACK_IMPORTED_MODULE_0__colors__ = __webpack_require__(90);
__webpack_exports__.a = Object(__WEBPACK_IMPORTED_MODULE_0__colors__.a)("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf");
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__colors__ = __webpack_require__(116);
+ var __WEBPACK_IMPORTED_MODULE_0__colors__ = __webpack_require__(90);
__webpack_exports__.a = Object(__WEBPACK_IMPORTED_MODULE_0__colors__.a)("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6");
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__colors__ = __webpack_require__(116);
+ var __WEBPACK_IMPORTED_MODULE_0__colors__ = __webpack_require__(90);
__webpack_exports__.a = Object(__WEBPACK_IMPORTED_MODULE_0__colors__.a)("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9");
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__colors__ = __webpack_require__(116);
+ var __WEBPACK_IMPORTED_MODULE_0__colors__ = __webpack_require__(90);
__webpack_exports__.a = Object(__WEBPACK_IMPORTED_MODULE_0__colors__.a)("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5");
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(61), __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__ = __webpack_require__(114);
+ var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(44), __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__ = __webpack_require__(88);
__webpack_exports__.a = Object(__WEBPACK_IMPORTED_MODULE_1_d3_interpolate__.b)(Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__.b)(300, .5, 0), Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__.b)(-240, .5, 1));
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -39969,7 +36659,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "a", function() {
return cool;
});
- var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(61), __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__ = __webpack_require__(114), warm = Object(__WEBPACK_IMPORTED_MODULE_1_d3_interpolate__.b)(Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__.b)(-100, .75, .35), Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__.b)(80, 1.5, .8)), cool = Object(__WEBPACK_IMPORTED_MODULE_1_d3_interpolate__.b)(Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__.b)(260, .75, .35), Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__.b)(80, 1.5, .8)), rainbow = Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__.b)();
+ var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(44), __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__ = __webpack_require__(88), warm = Object(__WEBPACK_IMPORTED_MODULE_1_d3_interpolate__.b)(Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__.b)(-100, .75, .35), Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__.b)(80, 1.5, .8)), cool = Object(__WEBPACK_IMPORTED_MODULE_1_d3_interpolate__.b)(Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__.b)(260, .75, .35), Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__.b)(80, 1.5, .8)), rainbow = Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__.b)();
__webpack_exports__.b = function(t) {
(t < 0 || t > 1) && (t -= Math.floor(t));
var ts = Math.abs(t - .5);
@@ -39991,7 +36681,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "d", function() {
return plasma;
});
- var __WEBPACK_IMPORTED_MODULE_0__colors__ = __webpack_require__(116);
+ var __WEBPACK_IMPORTED_MODULE_0__colors__ = __webpack_require__(90);
__webpack_exports__.a = ramp(Object(__WEBPACK_IMPORTED_MODULE_0__colors__.a)("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725"));
var magma = ramp(Object(__WEBPACK_IMPORTED_MODULE_0__colors__.a)("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")), inferno = ramp(Object(__WEBPACK_IMPORTED_MODULE_0__colors__.a)("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")), plasma = ramp(Object(__WEBPACK_IMPORTED_MODULE_0__colors__.a)("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921"));
}, function(module, __webpack_exports__, __webpack_require__) {
@@ -40013,7 +36703,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}, Object(__WEBPACK_IMPORTED_MODULE_0__linear__.b)(scale);
}
__webpack_exports__.a = sequential;
- var __WEBPACK_IMPORTED_MODULE_0__linear__ = __webpack_require__(113);
+ var __WEBPACK_IMPORTED_MODULE_0__linear__ = __webpack_require__(87);
}, function(module, exports) {
function last(array) {
var length = null == array ? 0 : array.length;
@@ -40040,7 +36730,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_3__util_PolarUtils__ = __webpack_require__(35), __WEBPACK_IMPORTED_MODULE_4__util_ReactUtils__ = __webpack_require__(7), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__), __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__), __WEBPACK_IMPORTED_MODULE_2__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_3__util_PolarUtils__ = __webpack_require__(23), __WEBPACK_IMPORTED_MODULE_4__util_ReactUtils__ = __webpack_require__(4), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -40161,7 +36851,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function minBy(array, iteratee) {
return array && array.length ? baseExtremum(array, baseIteratee(iteratee, 2), baseLt) : void 0;
}
- var baseExtremum = __webpack_require__(166), baseIteratee = __webpack_require__(110), baseLt = __webpack_require__(406);
+ var baseExtremum = __webpack_require__(124), baseIteratee = __webpack_require__(84), baseLt = __webpack_require__(285);
module.exports = minBy;
}, function(module, exports, __webpack_require__) {
function createRange(fromRight) {
@@ -40171,7 +36861,7 @@ var _publicBundleJs = []byte(`!function(modules) {
step = void 0 === step ? start < end ? 1 : -1 : toFinite(step), baseRange(start, end, step, fromRight);
};
}
- var baseRange = __webpack_require__(1093), isIterateeCall = __webpack_require__(403), toFinite = __webpack_require__(1094);
+ var baseRange = __webpack_require__(785), isIterateeCall = __webpack_require__(282), toFinite = __webpack_require__(786);
module.exports = createRange;
}, function(module, exports) {
function baseRange(start, end, step, fromRight) {
@@ -40189,10 +36879,38 @@ var _publicBundleJs = []byte(`!function(modules) {
}
return value === value ? value : 0;
}
- var toNumber = __webpack_require__(400), INFINITY = 1 / 0, MAX_INTEGER = 1.7976931348623157e308;
+ var toNumber = __webpack_require__(243), INFINITY = 1 / 0, MAX_INTEGER = 1.7976931348623157e308;
module.exports = toFinite;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
+ function _defineProperty(obj, key, value) {
+ return key in obj ? Object.defineProperty(obj, key, {
+ value: value,
+ enumerable: !0,
+ configurable: !0,
+ writable: !0
+ }) : obj[key] = value, obj;
+ }
+ __webpack_require__.d(__webpack_exports__, "a", function() {
+ return generatePrefixStyle;
+ });
+ var _extends = Object.assign || function(target) {
+ for (var i = 1; i < arguments.length; i++) {
+ var source = arguments[i];
+ for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
+ }
+ return target;
+ }, PREFIX_LIST = [ "Webkit", "Moz", "O", "ms" ], generatePrefixStyle = function(name, value) {
+ if (!name) return null;
+ var camelName = name.replace(/(\w)/, function(v) {
+ return v.toUpperCase();
+ }), result = PREFIX_LIST.reduce(function(res, entry) {
+ return _extends({}, res, _defineProperty({}, entry + camelName, value));
+ }, {});
+ return result[name] = value, result;
+ };
+}, function(module, __webpack_exports__, __webpack_require__) {
+ "use strict";
function _objectWithoutProperties(obj, keys) {
var target = {};
for (var i in obj) keys.indexOf(i) >= 0 || Object.prototype.hasOwnProperty.call(obj, i) && (target[i] = obj[i]);
@@ -40216,7 +36934,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_4__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_5__util_DataUtils__ = __webpack_require__(12), _extends = Object.assign || function(target) {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_1_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_react__), __WEBPACK_IMPORTED_MODULE_2_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_2_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_prop_types__), __WEBPACK_IMPORTED_MODULE_3__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_4__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_5__util_DataUtils__ = __webpack_require__(9), _extends = Object.assign || function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
@@ -40296,11 +37014,69 @@ var _publicBundleJs = []byte(`!function(modules) {
}, items);
}
}, {
+ key: "renderVerticalStripes",
+ value: function(verticalPoints) {
+ var verticalFill = this.props.verticalFill;
+ if (!verticalFill || !verticalFill.length) return null;
+ var _props3 = this.props, fillOpacity = _props3.fillOpacity, x = _props3.x, y = _props3.y, width = _props3.width, height = _props3.height, verticalPointsUpdated = verticalPoints.slice().sort(function(a, b) {
+ return a - b > 0;
+ });
+ x !== verticalPointsUpdated[0] && verticalPointsUpdated.unshift(0);
+ var items = verticalPointsUpdated.map(function(entry, i) {
+ var lineWidth = verticalPointsUpdated[i + 1] ? verticalPointsUpdated[i + 1] - entry : x + width - entry;
+ if (lineWidth <= 0) return null;
+ var colorIndex = i % verticalFill.length;
+ return __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement("rect", {
+ key: i,
+ x: Math.round(entry + x - x),
+ y: y,
+ width: lineWidth,
+ height: height,
+ stroke: "none",
+ fill: verticalFill[colorIndex],
+ fillOpacity: fillOpacity,
+ className: "recharts-cartesian-grid-bg"
+ });
+ });
+ return __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement("g", {
+ className: "recharts-cartesian-gridstripes-vertical"
+ }, items);
+ }
+ }, {
+ key: "renderHorizontalStripes",
+ value: function(horizontalPoints) {
+ var horizontalFill = this.props.horizontalFill;
+ if (!horizontalFill || !horizontalFill.length) return null;
+ var _props4 = this.props, fillOpacity = _props4.fillOpacity, x = _props4.x, y = _props4.y, width = _props4.width, height = _props4.height, horizontalPointsUpdated = horizontalPoints.slice().sort(function(a, b) {
+ return a - b > 0;
+ });
+ y !== horizontalPointsUpdated[0] && horizontalPointsUpdated.unshift(0);
+ var items = horizontalPointsUpdated.map(function(entry, i) {
+ var lineHeight = horizontalPointsUpdated[i + 1] ? horizontalPointsUpdated[i + 1] - entry : y + height - entry;
+ if (lineHeight <= 0) return null;
+ var colorIndex = i % horizontalFill.length;
+ return __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement("rect", {
+ key: i,
+ y: Math.round(entry + y - y),
+ x: x,
+ height: lineHeight,
+ width: width,
+ stroke: "none",
+ fill: horizontalFill[colorIndex],
+ fillOpacity: fillOpacity,
+ className: "recharts-cartesian-grid-bg"
+ });
+ });
+ return __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement("g", {
+ className: "recharts-cartesian-gridstripes-horizontal"
+ }, items);
+ }
+ }, {
key: "renderBackground",
value: function() {
var fill = this.props.fill;
if (!fill || "none" === fill) return null;
- var _props3 = this.props, fillOpacity = _props3.fillOpacity, x = _props3.x, y = _props3.y, width = _props3.width, height = _props3.height;
+ var _props5 = this.props, fillOpacity = _props5.fillOpacity, x = _props5.x, y = _props5.y, width = _props5.width, height = _props5.height;
return __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement("rect", {
x: x,
y: y,
@@ -40315,9 +37091,9 @@ var _publicBundleJs = []byte(`!function(modules) {
}, {
key: "render",
value: function() {
- var _props4 = this.props, x = _props4.x, y = _props4.y, width = _props4.width, height = _props4.height, horizontal = _props4.horizontal, vertical = _props4.vertical, horizontalCoordinatesGenerator = _props4.horizontalCoordinatesGenerator, verticalCoordinatesGenerator = _props4.verticalCoordinatesGenerator, xAxis = _props4.xAxis, yAxis = _props4.yAxis, offset = _props4.offset, chartWidth = _props4.chartWidth, chartHeight = _props4.chartHeight;
+ var _props6 = this.props, x = _props6.x, y = _props6.y, width = _props6.width, height = _props6.height, horizontal = _props6.horizontal, vertical = _props6.vertical, horizontalCoordinatesGenerator = _props6.horizontalCoordinatesGenerator, verticalCoordinatesGenerator = _props6.verticalCoordinatesGenerator, xAxis = _props6.xAxis, yAxis = _props6.yAxis, offset = _props6.offset, chartWidth = _props6.chartWidth, chartHeight = _props6.chartHeight;
if (!Object(__WEBPACK_IMPORTED_MODULE_5__util_DataUtils__.g)(width) || width <= 0 || !Object(__WEBPACK_IMPORTED_MODULE_5__util_DataUtils__.g)(height) || height <= 0 || !Object(__WEBPACK_IMPORTED_MODULE_5__util_DataUtils__.g)(x) || x !== +x || !Object(__WEBPACK_IMPORTED_MODULE_5__util_DataUtils__.g)(y) || y !== +y) return null;
- var _props5 = this.props, horizontalPoints = _props5.horizontalPoints, verticalPoints = _props5.verticalPoints;
+ var _props7 = this.props, horizontalPoints = _props7.horizontalPoints, verticalPoints = _props7.verticalPoints;
return horizontalPoints && horizontalPoints.length || !__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default()(horizontalCoordinatesGenerator) || (horizontalPoints = horizontalCoordinatesGenerator({
yAxis: yAxis,
width: chartWidth,
@@ -40330,7 +37106,7 @@ var _publicBundleJs = []byte(`!function(modules) {
offset: offset
})), __WEBPACK_IMPORTED_MODULE_1_react___default.a.createElement("g", {
className: "recharts-cartesian-grid"
- }, this.renderBackground(), horizontal && this.renderHorizontal(horizontalPoints), vertical && this.renderVertical(verticalPoints));
+ }, this.renderBackground(), horizontal && this.renderHorizontal(horizontalPoints), vertical && this.renderVertical(verticalPoints), horizontal && this.renderHorizontalStripes(horizontalPoints), vertical && this.renderVerticalStripes(verticalPoints));
}
} ]), CartesianGrid;
}(__WEBPACK_IMPORTED_MODULE_1_react__.Component), _class2.displayName = "CartesianGrid",
@@ -40349,19 +37125,23 @@ var _publicBundleJs = []byte(`!function(modules) {
yAxis: __WEBPACK_IMPORTED_MODULE_2_prop_types___default.a.object,
offset: __WEBPACK_IMPORTED_MODULE_2_prop_types___default.a.object,
chartWidth: __WEBPACK_IMPORTED_MODULE_2_prop_types___default.a.number,
- chartHeight: __WEBPACK_IMPORTED_MODULE_2_prop_types___default.a.number
+ chartHeight: __WEBPACK_IMPORTED_MODULE_2_prop_types___default.a.number,
+ verticalFill: __WEBPACK_IMPORTED_MODULE_2_prop_types___default.a.arrayOf(__WEBPACK_IMPORTED_MODULE_2_prop_types___default.a.string),
+ horizontalFill: __WEBPACK_IMPORTED_MODULE_2_prop_types___default.a.arrayOf(__WEBPACK_IMPORTED_MODULE_2_prop_types___default.a.string)
}), _class2.defaultProps = {
horizontal: !0,
vertical: !0,
horizontalPoints: [],
verticalPoints: [],
stroke: "#ccc",
- fill: "none"
+ fill: "none",
+ verticalFill: [],
+ horizontalFill: []
}, _class = _temp)) || _class;
__webpack_exports__.a = CartesianGrid;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__generateCategoricalChart__ = __webpack_require__(63), __WEBPACK_IMPORTED_MODULE_1__cartesian_Line__ = __webpack_require__(259), __WEBPACK_IMPORTED_MODULE_2__cartesian_XAxis__ = __webpack_require__(87), __WEBPACK_IMPORTED_MODULE_3__cartesian_YAxis__ = __webpack_require__(88), __WEBPACK_IMPORTED_MODULE_4__util_CartesianUtils__ = __webpack_require__(118);
+ var __WEBPACK_IMPORTED_MODULE_0__generateCategoricalChart__ = __webpack_require__(46), __WEBPACK_IMPORTED_MODULE_1__cartesian_Line__ = __webpack_require__(196), __WEBPACK_IMPORTED_MODULE_2__cartesian_XAxis__ = __webpack_require__(67), __WEBPACK_IMPORTED_MODULE_3__cartesian_YAxis__ = __webpack_require__(68), __WEBPACK_IMPORTED_MODULE_4__util_CartesianUtils__ = __webpack_require__(92);
__webpack_exports__.a = Object(__WEBPACK_IMPORTED_MODULE_0__generateCategoricalChart__.a)({
chartName: "LineChart",
GraphicalChild: __WEBPACK_IMPORTED_MODULE_1__cartesian_Line__.a,
@@ -40385,7 +37165,7 @@ var _publicBundleJs = []byte(`!function(modules) {
trailing: trailing
});
}
- var debounce = __webpack_require__(246), isObject = __webpack_require__(47), FUNC_ERROR_TEXT = "Expected a function";
+ var debounce = __webpack_require__(157), isObject = __webpack_require__(31), FUNC_ERROR_TEXT = "Expected a function";
module.exports = throttle;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -40394,7 +37174,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}), __webpack_require__.d(__webpack_exports__, "a", function() {
return SYNC_EVENT;
});
- var __WEBPACK_IMPORTED_MODULE_0_events__ = __webpack_require__(1099), __WEBPACK_IMPORTED_MODULE_0_events___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_events__), eventCenter = new __WEBPACK_IMPORTED_MODULE_0_events___default.a();
+ var __WEBPACK_IMPORTED_MODULE_0_events__ = __webpack_require__(792), __WEBPACK_IMPORTED_MODULE_0_events___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_events__), eventCenter = new __WEBPACK_IMPORTED_MODULE_0_events___default.a();
eventCenter.setMaxListeners && eventCenter.setMaxListeners(10);
var SYNC_EVENT = "recharts.syncMouseEvents";
}, function(module, exports) {
@@ -40499,7 +37279,7 @@ var _publicBundleJs = []byte(`!function(modules) {
};
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__generateCategoricalChart__ = __webpack_require__(63), __WEBPACK_IMPORTED_MODULE_1__cartesian_Bar__ = __webpack_require__(261), __WEBPACK_IMPORTED_MODULE_2__cartesian_XAxis__ = __webpack_require__(87), __WEBPACK_IMPORTED_MODULE_3__cartesian_YAxis__ = __webpack_require__(88), __WEBPACK_IMPORTED_MODULE_4__util_CartesianUtils__ = __webpack_require__(118);
+ var __WEBPACK_IMPORTED_MODULE_0__generateCategoricalChart__ = __webpack_require__(46), __WEBPACK_IMPORTED_MODULE_1__cartesian_Bar__ = __webpack_require__(198), __WEBPACK_IMPORTED_MODULE_2__cartesian_XAxis__ = __webpack_require__(67), __WEBPACK_IMPORTED_MODULE_3__cartesian_YAxis__ = __webpack_require__(68), __WEBPACK_IMPORTED_MODULE_4__util_CartesianUtils__ = __webpack_require__(92);
__webpack_exports__.a = Object(__WEBPACK_IMPORTED_MODULE_0__generateCategoricalChart__.a)({
chartName: "BarChart",
GraphicalChild: __WEBPACK_IMPORTED_MODULE_1__cartesian_Bar__.a,
@@ -40514,7 +37294,7 @@ var _publicBundleJs = []byte(`!function(modules) {
});
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_0_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_prop_types__), __WEBPACK_IMPORTED_MODULE_1__generateCategoricalChart__ = __webpack_require__(63), __WEBPACK_IMPORTED_MODULE_2__polar_PolarAngleAxis__ = __webpack_require__(172), __WEBPACK_IMPORTED_MODULE_3__polar_PolarRadiusAxis__ = __webpack_require__(171), __WEBPACK_IMPORTED_MODULE_4__util_PolarUtils__ = __webpack_require__(35), __WEBPACK_IMPORTED_MODULE_5__polar_Pie__ = __webpack_require__(446);
+ var __WEBPACK_IMPORTED_MODULE_0_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_0_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_prop_types__), __WEBPACK_IMPORTED_MODULE_1__generateCategoricalChart__ = __webpack_require__(46), __WEBPACK_IMPORTED_MODULE_2__polar_PolarAngleAxis__ = __webpack_require__(130), __WEBPACK_IMPORTED_MODULE_3__polar_PolarRadiusAxis__ = __webpack_require__(129), __WEBPACK_IMPORTED_MODULE_4__util_PolarUtils__ = __webpack_require__(23), __WEBPACK_IMPORTED_MODULE_5__polar_Pie__ = __webpack_require__(325);
__webpack_exports__.a = Object(__WEBPACK_IMPORTED_MODULE_1__generateCategoricalChart__.a)({
chartName: "PieChart",
GraphicalChild: __WEBPACK_IMPORTED_MODULE_5__polar_Pie__.a,
@@ -40572,7 +37352,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_lodash_isNaN__ = __webpack_require__(159), __WEBPACK_IMPORTED_MODULE_1_lodash_isNaN___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isNaN__), __WEBPACK_IMPORTED_MODULE_2_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_2_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_react__), __WEBPACK_IMPORTED_MODULE_3_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_3_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_prop_types__), __WEBPACK_IMPORTED_MODULE_4_react_smooth__ = __webpack_require__(48), __WEBPACK_IMPORTED_MODULE_4_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react_smooth__), __WEBPACK_IMPORTED_MODULE_5_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_5_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_classnames__), __WEBPACK_IMPORTED_MODULE_6__container_Surface__ = __webpack_require__(103), __WEBPACK_IMPORTED_MODULE_7__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_8__shape_Rectangle__ = __webpack_require__(85), __WEBPACK_IMPORTED_MODULE_9__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_10__component_Tooltip__ = __webpack_require__(164), __WEBPACK_IMPORTED_MODULE_11__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_12__util_ChartUtils__ = __webpack_require__(21), _createClass = function() {
+ var _class, _class2, _temp2, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_lodash_isNaN__ = __webpack_require__(117), __WEBPACK_IMPORTED_MODULE_1_lodash_isNaN___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isNaN__), __WEBPACK_IMPORTED_MODULE_2_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_2_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_react__), __WEBPACK_IMPORTED_MODULE_3_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_3_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_prop_types__), __WEBPACK_IMPORTED_MODULE_4_react_smooth__ = __webpack_require__(33), __WEBPACK_IMPORTED_MODULE_4_react_smooth___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react_smooth__), __WEBPACK_IMPORTED_MODULE_5_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_5_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_classnames__), __WEBPACK_IMPORTED_MODULE_6__container_Surface__ = __webpack_require__(78), __WEBPACK_IMPORTED_MODULE_7__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_8__shape_Rectangle__ = __webpack_require__(65), __WEBPACK_IMPORTED_MODULE_9__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_10__component_Tooltip__ = __webpack_require__(122), __WEBPACK_IMPORTED_MODULE_11__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_12__util_ChartUtils__ = __webpack_require__(16), _createClass = function() {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
@@ -40905,7 +37685,7 @@ var _publicBundleJs = []byte(`!function(modules) {
}
}), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
- var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(11), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_lodash_sumBy__ = __webpack_require__(1104), __WEBPACK_IMPORTED_MODULE_1_lodash_sumBy___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_sumBy__), __WEBPACK_IMPORTED_MODULE_2_lodash_min__ = __webpack_require__(405), __WEBPACK_IMPORTED_MODULE_2_lodash_min___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_min__), __WEBPACK_IMPORTED_MODULE_3_lodash_maxBy__ = __webpack_require__(445), __WEBPACK_IMPORTED_MODULE_3_lodash_maxBy___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_maxBy__), __WEBPACK_IMPORTED_MODULE_4_react__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_4_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react__), __WEBPACK_IMPORTED_MODULE_5_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_5_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_prop_types__), __WEBPACK_IMPORTED_MODULE_6_classnames__ = __webpack_require__(6), __WEBPACK_IMPORTED_MODULE_6_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_classnames__), __WEBPACK_IMPORTED_MODULE_7__container_Surface__ = __webpack_require__(103), __WEBPACK_IMPORTED_MODULE_8__container_Layer__ = __webpack_require__(18), __WEBPACK_IMPORTED_MODULE_9__component_Tooltip__ = __webpack_require__(164), __WEBPACK_IMPORTED_MODULE_10__shape_Rectangle__ = __webpack_require__(85), __WEBPACK_IMPORTED_MODULE_11__util_PureRender__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_12__util_ReactUtils__ = __webpack_require__(7), __WEBPACK_IMPORTED_MODULE_13__util_ChartUtils__ = __webpack_require__(21), _createClass = function() {
+ var _class, _class2, _temp, __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__ = __webpack_require__(8), __WEBPACK_IMPORTED_MODULE_0_lodash_isFunction___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_isFunction__), __WEBPACK_IMPORTED_MODULE_1_lodash_sumBy__ = __webpack_require__(797), __WEBPACK_IMPORTED_MODULE_1_lodash_sumBy___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_sumBy__), __WEBPACK_IMPORTED_MODULE_2_lodash_min__ = __webpack_require__(284), __WEBPACK_IMPORTED_MODULE_2_lodash_min___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_min__), __WEBPACK_IMPORTED_MODULE_3_lodash_maxBy__ = __webpack_require__(324), __WEBPACK_IMPORTED_MODULE_3_lodash_maxBy___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_maxBy__), __WEBPACK_IMPORTED_MODULE_4_react__ = __webpack_require__(0), __WEBPACK_IMPORTED_MODULE_4_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_react__), __WEBPACK_IMPORTED_MODULE_5_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_5_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_prop_types__), __WEBPACK_IMPORTED_MODULE_6_classnames__ = __webpack_require__(3), __WEBPACK_IMPORTED_MODULE_6_classnames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_classnames__), __WEBPACK_IMPORTED_MODULE_7__container_Surface__ = __webpack_require__(78), __WEBPACK_IMPORTED_MODULE_8__container_Layer__ = __webpack_require__(14), __WEBPACK_IMPORTED_MODULE_9__component_Tooltip__ = __webpack_require__(122), __WEBPACK_IMPORTED_MODULE_10__shape_Rectangle__ = __webpack_require__(65), __WEBPACK_IMPORTED_MODULE_11__util_PureRender__ = __webpack_require__(5), __WEBPACK_IMPORTED_MODULE_12__util_ReactUtils__ = __webpack_require__(4), __WEBPACK_IMPORTED_MODULE_13__util_ChartUtils__ = __webpack_require__(16), _createClass = function() {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
@@ -41309,7 +38089,7 @@ var _publicBundleJs = []byte(`!function(modules) {
function sumBy(array, iteratee) {
return array && array.length ? baseSum(array, baseIteratee(iteratee, 2)) : 0;
}
- var baseIteratee = __webpack_require__(110), baseSum = __webpack_require__(1105);
+ var baseIteratee = __webpack_require__(84), baseSum = __webpack_require__(798);
module.exports = sumBy;
}, function(module, exports) {
function baseSum(array, iteratee) {
@@ -41322,7 +38102,7 @@ var _publicBundleJs = []byte(`!function(modules) {
module.exports = baseSum;
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_0_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_prop_types__), __WEBPACK_IMPORTED_MODULE_1__generateCategoricalChart__ = __webpack_require__(63), __WEBPACK_IMPORTED_MODULE_2__polar_Radar__ = __webpack_require__(447), __WEBPACK_IMPORTED_MODULE_3__polar_PolarAngleAxis__ = __webpack_require__(172), __WEBPACK_IMPORTED_MODULE_4__polar_PolarRadiusAxis__ = __webpack_require__(171), __WEBPACK_IMPORTED_MODULE_5__util_PolarUtils__ = __webpack_require__(35);
+ var __WEBPACK_IMPORTED_MODULE_0_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_0_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_prop_types__), __WEBPACK_IMPORTED_MODULE_1__generateCategoricalChart__ = __webpack_require__(46), __WEBPACK_IMPORTED_MODULE_2__polar_Radar__ = __webpack_require__(326), __WEBPACK_IMPORTED_MODULE_3__polar_PolarAngleAxis__ = __webpack_require__(130), __WEBPACK_IMPORTED_MODULE_4__polar_PolarRadiusAxis__ = __webpack_require__(129), __WEBPACK_IMPORTED_MODULE_5__util_PolarUtils__ = __webpack_require__(23);
__webpack_exports__.a = Object(__WEBPACK_IMPORTED_MODULE_1__generateCategoricalChart__.a)({
chartName: "RadarChart",
GraphicalChild: __WEBPACK_IMPORTED_MODULE_2__polar_Radar__.a,
@@ -41355,7 +38135,7 @@ var _publicBundleJs = []byte(`!function(modules) {
});
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__generateCategoricalChart__ = __webpack_require__(63), __WEBPACK_IMPORTED_MODULE_1__cartesian_Scatter__ = __webpack_require__(262), __WEBPACK_IMPORTED_MODULE_2__cartesian_XAxis__ = __webpack_require__(87), __WEBPACK_IMPORTED_MODULE_3__cartesian_YAxis__ = __webpack_require__(88), __WEBPACK_IMPORTED_MODULE_4__cartesian_ZAxis__ = __webpack_require__(173), __WEBPACK_IMPORTED_MODULE_5__util_CartesianUtils__ = __webpack_require__(118);
+ var __WEBPACK_IMPORTED_MODULE_0__generateCategoricalChart__ = __webpack_require__(46), __WEBPACK_IMPORTED_MODULE_1__cartesian_Scatter__ = __webpack_require__(199), __WEBPACK_IMPORTED_MODULE_2__cartesian_XAxis__ = __webpack_require__(67), __WEBPACK_IMPORTED_MODULE_3__cartesian_YAxis__ = __webpack_require__(68), __WEBPACK_IMPORTED_MODULE_4__cartesian_ZAxis__ = __webpack_require__(131), __WEBPACK_IMPORTED_MODULE_5__util_CartesianUtils__ = __webpack_require__(92);
__webpack_exports__.a = Object(__WEBPACK_IMPORTED_MODULE_0__generateCategoricalChart__.a)({
chartName: "ScatterChart",
GraphicalChild: __WEBPACK_IMPORTED_MODULE_1__cartesian_Scatter__.a,
@@ -41374,7 +38154,7 @@ var _publicBundleJs = []byte(`!function(modules) {
});
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__generateCategoricalChart__ = __webpack_require__(63), __WEBPACK_IMPORTED_MODULE_1__cartesian_Area__ = __webpack_require__(260), __WEBPACK_IMPORTED_MODULE_2__cartesian_XAxis__ = __webpack_require__(87), __WEBPACK_IMPORTED_MODULE_3__cartesian_YAxis__ = __webpack_require__(88), __WEBPACK_IMPORTED_MODULE_4__util_CartesianUtils__ = __webpack_require__(118);
+ var __WEBPACK_IMPORTED_MODULE_0__generateCategoricalChart__ = __webpack_require__(46), __WEBPACK_IMPORTED_MODULE_1__cartesian_Area__ = __webpack_require__(197), __WEBPACK_IMPORTED_MODULE_2__cartesian_XAxis__ = __webpack_require__(67), __WEBPACK_IMPORTED_MODULE_3__cartesian_YAxis__ = __webpack_require__(68), __WEBPACK_IMPORTED_MODULE_4__util_CartesianUtils__ = __webpack_require__(92);
__webpack_exports__.a = Object(__WEBPACK_IMPORTED_MODULE_0__generateCategoricalChart__.a)({
chartName: "AreaChart",
GraphicalChild: __WEBPACK_IMPORTED_MODULE_1__cartesian_Area__.a,
@@ -41389,7 +38169,7 @@ var _publicBundleJs = []byte(`!function(modules) {
});
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0_prop_types__ = __webpack_require__(2), __WEBPACK_IMPORTED_MODULE_0_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_prop_types__), __WEBPACK_IMPORTED_MODULE_1__generateCategoricalChart__ = __webpack_require__(63), __WEBPACK_IMPORTED_MODULE_2__polar_PolarAngleAxis__ = __webpack_require__(172), __WEBPACK_IMPORTED_MODULE_3__polar_PolarRadiusAxis__ = __webpack_require__(171), __WEBPACK_IMPORTED_MODULE_4__util_PolarUtils__ = __webpack_require__(35), __WEBPACK_IMPORTED_MODULE_5__polar_RadialBar__ = __webpack_require__(448);
+ var __WEBPACK_IMPORTED_MODULE_0_prop_types__ = __webpack_require__(1), __WEBPACK_IMPORTED_MODULE_0_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_prop_types__), __WEBPACK_IMPORTED_MODULE_1__generateCategoricalChart__ = __webpack_require__(46), __WEBPACK_IMPORTED_MODULE_2__polar_PolarAngleAxis__ = __webpack_require__(130), __WEBPACK_IMPORTED_MODULE_3__polar_PolarRadiusAxis__ = __webpack_require__(129), __WEBPACK_IMPORTED_MODULE_4__util_PolarUtils__ = __webpack_require__(23), __WEBPACK_IMPORTED_MODULE_5__polar_RadialBar__ = __webpack_require__(327);
__webpack_exports__.a = Object(__WEBPACK_IMPORTED_MODULE_1__generateCategoricalChart__.a)({
chartName: "RadialBarChart",
GraphicalChild: __WEBPACK_IMPORTED_MODULE_5__polar_RadialBar__.a,
@@ -41423,7 +38203,7 @@ var _publicBundleJs = []byte(`!function(modules) {
});
}, function(module, __webpack_exports__, __webpack_require__) {
"use strict";
- var __WEBPACK_IMPORTED_MODULE_0__generateCategoricalChart__ = __webpack_require__(63), __WEBPACK_IMPORTED_MODULE_1__cartesian_Area__ = __webpack_require__(260), __WEBPACK_IMPORTED_MODULE_2__cartesian_Bar__ = __webpack_require__(261), __WEBPACK_IMPORTED_MODULE_3__cartesian_Line__ = __webpack_require__(259), __WEBPACK_IMPORTED_MODULE_4__cartesian_Scatter__ = __webpack_require__(262), __WEBPACK_IMPORTED_MODULE_5__cartesian_XAxis__ = __webpack_require__(87), __WEBPACK_IMPORTED_MODULE_6__cartesian_YAxis__ = __webpack_require__(88), __WEBPACK_IMPORTED_MODULE_7__cartesian_ZAxis__ = __webpack_require__(173), __WEBPACK_IMPORTED_MODULE_8__util_CartesianUtils__ = __webpack_require__(118);
+ var __WEBPACK_IMPORTED_MODULE_0__generateCategoricalChart__ = __webpack_require__(46), __WEBPACK_IMPORTED_MODULE_1__cartesian_Area__ = __webpack_require__(197), __WEBPACK_IMPORTED_MODULE_2__cartesian_Bar__ = __webpack_require__(198), __WEBPACK_IMPORTED_MODULE_3__cartesian_Line__ = __webpack_require__(196), __WEBPACK_IMPORTED_MODULE_4__cartesian_Scatter__ = __webpack_require__(199), __WEBPACK_IMPORTED_MODULE_5__cartesian_XAxis__ = __webpack_require__(67), __WEBPACK_IMPORTED_MODULE_6__cartesian_YAxis__ = __webpack_require__(68), __WEBPACK_IMPORTED_MODULE_7__cartesian_ZAxis__ = __webpack_require__(131), __WEBPACK_IMPORTED_MODULE_8__util_CartesianUtils__ = __webpack_require__(92);
__webpack_exports__.a = Object(__WEBPACK_IMPORTED_MODULE_0__generateCategoricalChart__.a)({
chartName: "ComposedChart",
GraphicalChild: [ __WEBPACK_IMPORTED_MODULE_3__cartesian_Line__.a, __WEBPACK_IMPORTED_MODULE_1__cartesian_Area__.a, __WEBPACK_IMPORTED_MODULE_2__cartesian_Bar__.a, __WEBPACK_IMPORTED_MODULE_4__cartesian_Scatter__.a ],
@@ -41479,35 +38259,40 @@ var _publicBundleJs = []byte(`!function(modules) {
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
Constructor;
};
- }(), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _Grid = __webpack_require__(1112), _Grid2 = _interopRequireDefault(_Grid), _recharts = __webpack_require__(362), ChartGrid = function(_Component) {
- function ChartGrid() {
- return _classCallCheck(this, ChartGrid), _possibleConstructorReturn(this, (ChartGrid.__proto__ || Object.getPrototypeOf(ChartGrid)).apply(this, arguments));
+ }(), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _Grid = __webpack_require__(241), _Grid2 = _interopRequireDefault(_Grid), styles = {
+ container: {
+ flexWrap: "nowrap",
+ height: "100%",
+ maxWidth: "100%",
+ margin: 0
+ },
+ item: {
+ flex: 1,
+ padding: 0
}
- return _inherits(ChartGrid, _Component), _createClass(ChartGrid, [ {
+ }, ChartRow = function(_Component) {
+ function ChartRow() {
+ return _classCallCheck(this, ChartRow), _possibleConstructorReturn(this, (ChartRow.__proto__ || Object.getPrototypeOf(ChartRow)).apply(this, arguments));
+ }
+ return _inherits(ChartRow, _Component), _createClass(ChartRow, [ {
key: "render",
value: function() {
return _react2.default.createElement(_Grid2.default, {
container: !0,
- spacing: this.props.spacing
+ direction: "row",
+ style: styles.container,
+ justify: "space-between"
}, _react2.default.Children.map(this.props.children, function(child) {
return _react2.default.createElement(_Grid2.default, {
item: !0,
- xs: child.props.xs
- }, _react2.default.createElement(_recharts.ResponsiveContainer, {
- width: "100%",
- height: child.props.height
- }, _react2.default.cloneElement(child, {
- data: child.props.values.map(function(value) {
- return {
- value: value
- };
- })
- })));
+ xs: !0,
+ style: styles.item
+ }, child);
}));
}
- } ]), ChartGrid;
+ } ]), ChartRow;
}(_react.Component);
- exports.default = ChartGrid;
+ exports.default = ChartRow;
}, function(module, exports, __webpack_require__) {
"use strict";
function _interopRequireDefault(obj) {
@@ -41515,644 +38300,107 @@ var _publicBundleJs = []byte(`!function(modules) {
default: obj
};
}
- Object.defineProperty(exports, "__esModule", {
- value: !0
- });
- var _Grid = __webpack_require__(1113);
- Object.defineProperty(exports, "default", {
- enumerable: !0,
- get: function() {
- return _interopRequireDefault(_Grid).default;
- }
- });
-}, function(module, exports, __webpack_require__) {
- "use strict";
- (function(process) {
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
- };
- }
- function generateGrid(globalStyles, theme, breakpoint) {
- var styles = (0, _defineProperty3.default)({}, "grid-" + breakpoint, {
- flexBasis: 0,
- flexGrow: 1,
- maxWidth: "100%"
- });
- GRID_SIZES.forEach(function(size) {
- if ("boolean" != typeof size) {
- var width = Math.round(size / 12 * Math.pow(10, 6)) / Math.pow(10, 4) + "%";
- styles["grid-" + breakpoint + "-" + size] = {
- flexBasis: width,
- maxWidth: width
- };
- }
- }), "xs" === breakpoint ? (0, _extends3.default)(globalStyles, styles) : globalStyles[theme.breakpoints.up(breakpoint)] = styles;
- }
- function generateGutter(theme, breakpoint) {
- var styles = {};
- return GUTTERS.forEach(function(spacing, index) {
- 0 !== index && (styles["spacing-" + breakpoint + "-" + spacing] = {
- margin: -spacing / 2,
- width: "calc(100% + " + spacing + "px)",
- "& > $typeItem": {
- padding: spacing / 2
- }
- });
- }), styles;
- }
- function Grid(props) {
- var _classNames, alignContent = props.alignContent, alignItems = props.alignItems, classes = props.classes, classNameProp = props.className, ComponentProp = props.component, container = props.container, direction = props.direction, hidden = props.hidden, item = props.item, justify = props.justify, lg = props.lg, md = props.md, sm = props.sm, spacing = props.spacing, wrap = props.wrap, xl = props.xl, xs = props.xs, other = (0,
- _objectWithoutProperties3.default)(props, [ "alignContent", "alignItems", "classes", "className", "component", "container", "direction", "hidden", "item", "justify", "lg", "md", "sm", "spacing", "wrap", "xl", "xs" ]), className = (0,
- _classnames2.default)((_classNames = {}, (0, _defineProperty3.default)(_classNames, classes.typeContainer, container),
- (0, _defineProperty3.default)(_classNames, classes.typeItem, item), (0, _defineProperty3.default)(_classNames, classes["spacing-xs-" + String(spacing)], container && 0 !== spacing),
- (0, _defineProperty3.default)(_classNames, classes["direction-xs-" + String(direction)], direction !== Grid.defaultProps.direction),
- (0, _defineProperty3.default)(_classNames, classes["wrap-xs-" + String(wrap)], wrap !== Grid.defaultProps.wrap),
- (0, _defineProperty3.default)(_classNames, classes["align-items-xs-" + String(alignItems)], alignItems !== Grid.defaultProps.alignItems),
- (0, _defineProperty3.default)(_classNames, classes["align-content-xs-" + String(alignContent)], alignContent !== Grid.defaultProps.alignContent),
- (0, _defineProperty3.default)(_classNames, classes["justify-xs-" + String(justify)], justify !== Grid.defaultProps.justify),
- (0, _defineProperty3.default)(_classNames, classes["grid-xs"], !0 === xs), (0, _defineProperty3.default)(_classNames, classes["grid-xs-" + String(xs)], xs && !0 !== xs),
- (0, _defineProperty3.default)(_classNames, classes["grid-sm"], !0 === sm), (0, _defineProperty3.default)(_classNames, classes["grid-sm-" + String(sm)], sm && !0 !== sm),
- (0, _defineProperty3.default)(_classNames, classes["grid-md"], !0 === md), (0, _defineProperty3.default)(_classNames, classes["grid-md-" + String(md)], md && !0 !== md),
- (0, _defineProperty3.default)(_classNames, classes["grid-lg"], !0 === lg), (0, _defineProperty3.default)(_classNames, classes["grid-lg-" + String(lg)], lg && !0 !== lg),
- (0, _defineProperty3.default)(_classNames, classes["grid-xl"], !0 === xl), (0, _defineProperty3.default)(_classNames, classes["grid-xl-" + String(xl)], xl && !0 !== xl),
- _classNames), classNameProp), gridProps = (0, _extends3.default)({
- className: className
- }, other);
- return hidden ? _react2.default.createElement(_Hidden2.default, hidden, _react2.default.createElement(ComponentProp, gridProps)) : _react2.default.createElement(ComponentProp, gridProps);
- }
- Object.defineProperty(exports, "__esModule", {
- value: !0
- }), exports.styles = void 0;
- var _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _classnames = __webpack_require__(6), _classnames2 = _interopRequireDefault(_classnames), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), _createBreakpoints = __webpack_require__(94), _requirePropFactory = __webpack_require__(1114), _requirePropFactory2 = _interopRequireDefault(_requirePropFactory), _Hidden = __webpack_require__(1115), _Hidden2 = _interopRequireDefault(_Hidden), GUTTERS = [ 0, 8, 16, 24, 40 ], GRID_SIZES = [ !0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ], styles = exports.styles = function(theme) {
- return (0, _extends3.default)({
- typeContainer: {
- boxSizing: "border-box",
- display: "flex",
- flexWrap: "wrap",
- width: "100%"
- },
- typeItem: {
- boxSizing: "border-box",
- flex: "0 0 auto",
- margin: "0"
- },
- "direction-xs-column": {
- flexDirection: "column"
- },
- "direction-xs-column-reverse": {
- flexDirection: "column-reverse"
- },
- "direction-xs-row-reverse": {
- flexDirection: "row-reverse"
- },
- "wrap-xs-nowrap": {
- flexWrap: "nowrap"
- },
- "wrap-xs-wrap-reverse": {
- flexWrap: "wrap-reverse"
- },
- "align-items-xs-center": {
- alignItems: "center"
- },
- "align-items-xs-flex-start": {
- alignItems: "flex-start"
- },
- "align-items-xs-flex-end": {
- alignItems: "flex-end"
- },
- "align-items-xs-baseline": {
- alignItems: "baseline"
- },
- "align-content-xs-center": {
- alignContent: "center"
- },
- "align-content-xs-flex-start": {
- alignContent: "flex-start"
- },
- "align-content-xs-flex-end": {
- alignContent: "flex-end"
- },
- "align-content-xs-space-between": {
- alignContent: "space-between"
- },
- "align-content-xs-space-around": {
- alignContent: "space-around"
- },
- "justify-xs-center": {
- justifyContent: "center"
- },
- "justify-xs-flex-end": {
- justifyContent: "flex-end"
- },
- "justify-xs-space-between": {
- justifyContent: "space-between"
- },
- "justify-xs-space-around": {
- justifyContent: "space-around"
- }
- }, generateGutter(theme, "xs"), _createBreakpoints.keys.reduce(function(accumulator, key) {
- return generateGrid(accumulator, theme, key), accumulator;
- }, {}));
- };
- Grid.propTypes = "production" !== process.env.NODE_ENV ? {
- alignContent: _propTypes2.default.oneOf([ "stretch", "center", "flex-start", "flex-end", "space-between", "space-around" ]),
- alignItems: _propTypes2.default.oneOf([ "flex-start", "center", "flex-end", "stretch", "baseline" ]),
- children: _propTypes2.default.node,
- classes: _propTypes2.default.object.isRequired,
- className: _propTypes2.default.string,
- component: _propTypes2.default.oneOfType([ _propTypes2.default.string, _propTypes2.default.func ]),
- container: _propTypes2.default.bool,
- direction: _propTypes2.default.oneOf([ "row", "row-reverse", "column", "column-reverse" ]),
- hidden: _propTypes2.default.object,
- item: _propTypes2.default.bool,
- justify: _propTypes2.default.oneOf([ "flex-start", "center", "flex-end", "space-between", "space-around" ]),
- lg: _propTypes2.default.oneOf([ !0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]),
- md: _propTypes2.default.oneOf([ !0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]),
- sm: _propTypes2.default.oneOf([ !0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]),
- spacing: _propTypes2.default.oneOf(GUTTERS),
- wrap: _propTypes2.default.oneOf([ "nowrap", "wrap", "wrap-reverse" ]),
- xl: _propTypes2.default.oneOf([ !0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]),
- xs: _propTypes2.default.oneOf([ !0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ])
- } : {}, Grid.defaultProps = {
- alignContent: "stretch",
- alignItems: "stretch",
- component: "div",
- container: !1,
- direction: "row",
- item: !1,
- justify: "flex-start",
- spacing: 16,
- wrap: "wrap"
- };
- var GridWrapper = Grid;
- if ("production" !== process.env.NODE_ENV) {
- GridWrapper = function(props) {
- return _react2.default.createElement(Grid, props);
- };
- var requireProp = (0, _requirePropFactory2.default)("Grid");
- GridWrapper.propTypes = {
- alignContent: requireProp("container"),
- alignItems: requireProp("container"),
- direction: requireProp("container"),
- justify: requireProp("container"),
- lg: requireProp("item"),
- md: requireProp("item"),
- sm: requireProp("item"),
- spacing: requireProp("container"),
- wrap: requireProp("container"),
- xs: requireProp("item")
- };
- }
- exports.default = (0, _withStyles2.default)(styles, {
- name: "MuiGrid"
- })(GridWrapper);
- }).call(exports, __webpack_require__(3));
-}, function(module, exports, __webpack_require__) {
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: !0
- });
- var requirePropFactory = function(componentNameInError) {
- return function(requiredProp) {
- return function(props, propName, componentName, location, propFullName) {
- var propFullNameSafe = propFullName || propName;
- return void 0 === props[propName] || props[requiredProp] ? null : new Error("The property ` + "`" + `" + propFullNameSafe + "` + "`" + ` of ` + "`" + `" + componentNameInError + "` + "`" + ` must be used on ` + "`" + `" + requiredProp + "` + "`" + `.");
- };
- };
- };
- exports.default = requirePropFactory;
-}, function(module, exports, __webpack_require__) {
- "use strict";
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
- };
+ function _classCallCheck(instance, Constructor) {
+ if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
}
- Object.defineProperty(exports, "__esModule", {
- value: !0
- });
- var _Hidden = __webpack_require__(1116);
- Object.defineProperty(exports, "default", {
- enumerable: !0,
- get: function() {
- return _interopRequireDefault(_Hidden).default;
- }
- });
- var _HiddenJs = __webpack_require__(452);
- Object.defineProperty(exports, "HiddenJs", {
- enumerable: !0,
- get: function() {
- return _interopRequireDefault(_HiddenJs).default;
- }
- });
-}, function(module, exports, __webpack_require__) {
- "use strict";
- (function(process) {
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
- };
- }
- function Hidden(props) {
- var implementation = props.implementation, other = (0, _objectWithoutProperties3.default)(props, [ "implementation" ]);
- return "js" === implementation ? _react2.default.createElement(_HiddenJs2.default, other) : _react2.default.createElement(_HiddenCss2.default, other);
- }
- Object.defineProperty(exports, "__esModule", {
- value: !0
- });
- var _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _HiddenJs = __webpack_require__(452), _HiddenJs2 = _interopRequireDefault(_HiddenJs), _HiddenCss = __webpack_require__(1122), _HiddenCss2 = _interopRequireDefault(_HiddenCss);
- Hidden.propTypes = "production" !== process.env.NODE_ENV ? {
- children: _propTypes2.default.node,
- className: _propTypes2.default.string,
- implementation: _propTypes2.default.oneOf([ "js", "css" ]),
- initialWidth: _propTypes2.default.number,
- lgDown: _propTypes2.default.bool,
- lgUp: _propTypes2.default.bool,
- mdDown: _propTypes2.default.bool,
- mdUp: _propTypes2.default.bool,
- only: _propTypes2.default.oneOfType([ _propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ]), _propTypes2.default.arrayOf(_propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ])) ]),
- smDown: _propTypes2.default.bool,
- smUp: _propTypes2.default.bool,
- xlDown: _propTypes2.default.bool,
- xlUp: _propTypes2.default.bool,
- xsDown: _propTypes2.default.bool,
- xsUp: _propTypes2.default.bool
- } : {}, Hidden.defaultProps = {
- implementation: "js",
- lgDown: !1,
- lgUp: !1,
- mdDown: !1,
- mdUp: !1,
- smDown: !1,
- smUp: !1,
- xlDown: !1,
- xlUp: !1,
- xsDown: !1,
- xsUp: !1
- }, exports.default = Hidden;
- }).call(exports, __webpack_require__(3));
-}, function(module, exports, __webpack_require__) {
- module.exports = {
- default: __webpack_require__(1118),
- __esModule: !0
- };
-}, function(module, exports, __webpack_require__) {
- var core = __webpack_require__(22), $JSON = core.JSON || (core.JSON = {
- stringify: JSON.stringify
- });
- module.exports = function(it) {
- return $JSON.stringify.apply($JSON, arguments);
- };
-}, function(module, exports, __webpack_require__) {
- "use strict";
- (function(process) {
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
- };
- }
- Object.defineProperty(exports, "__esModule", {
- value: !0
- }), exports.isWidthDown = exports.isWidthUp = void 0;
- var _extends2 = __webpack_require__(10), _extends3 = _interopRequireDefault(_extends2), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _getPrototypeOf = __webpack_require__(38), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(39), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(40), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(41), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(42), _inherits3 = _interopRequireDefault(_inherits2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _reactEventListener = __webpack_require__(1120), _reactEventListener2 = _interopRequireDefault(_reactEventListener), _debounce = __webpack_require__(246), _debounce2 = _interopRequireDefault(_debounce), _hoistNonReactStatics = __webpack_require__(194), _hoistNonReactStatics2 = _interopRequireDefault(_hoistNonReactStatics), _wrapDisplayName = __webpack_require__(95), _wrapDisplayName2 = _interopRequireDefault(_wrapDisplayName), _withTheme = __webpack_require__(361), _withTheme2 = _interopRequireDefault(_withTheme), _createBreakpoints = __webpack_require__(94), withWidth = (exports.isWidthUp = function(breakpoint, width) {
- return arguments.length > 2 && void 0 !== arguments[2] && !arguments[2] ? _createBreakpoints.keys.indexOf(breakpoint) < _createBreakpoints.keys.indexOf(width) : _createBreakpoints.keys.indexOf(breakpoint) <= _createBreakpoints.keys.indexOf(width);
- }, exports.isWidthDown = function(breakpoint, width) {
- return arguments.length > 2 && void 0 !== arguments[2] && arguments[2] ? _createBreakpoints.keys.indexOf(width) <= _createBreakpoints.keys.indexOf(breakpoint) : _createBreakpoints.keys.indexOf(width) < _createBreakpoints.keys.indexOf(breakpoint);
- }, function() {
- var options = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
- return function(Component) {
- var _options$resizeInterv = options.resizeInterval, resizeInterval = void 0 === _options$resizeInterv ? 166 : _options$resizeInterv, Width = function(_React$Component) {
- function Width() {
- var _ref, _temp, _this, _ret;
- (0, _classCallCheck3.default)(this, Width);
- for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) args[_key] = arguments[_key];
- return _temp = _this = (0, _possibleConstructorReturn3.default)(this, (_ref = Width.__proto__ || (0,
- _getPrototypeOf2.default)(Width)).call.apply(_ref, [ this ].concat(args))), _this.state = {
- width: void 0
- }, _this.handleResize = (0, _debounce2.default)(function() {
- _this.updateWidth(window.innerWidth);
- }, resizeInterval), _ret = _temp, (0, _possibleConstructorReturn3.default)(_this, _ret);
- }
- return (0, _inherits3.default)(Width, _React$Component), (0, _createClass3.default)(Width, [ {
- key: "componentDidMount",
- value: function() {
- this.updateWidth(window.innerWidth);
- }
- }, {
- key: "componentWillUnmount",
- value: function() {
- this.handleResize.cancel();
- }
- }, {
- key: "updateWidth",
- value: function(innerWidth) {
- if (this.props.theme) {
- for (var breakpoints = this.props.theme.breakpoints, width = null, index = 1; null === width && index < _createBreakpoints.keys.length; ) {
- var currentWidth = _createBreakpoints.keys[index];
- if (innerWidth < breakpoints.values[currentWidth]) {
- width = _createBreakpoints.keys[index - 1];
- break;
- }
- index += 1;
- }
- width = width || "xl", width !== this.state.width && this.setState({
- width: width
- });
- }
- }
- }, {
- key: "render",
- value: function() {
- var _props = this.props, initialWidth = _props.initialWidth, width = (_props.theme,
- _props.width), other = (0, _objectWithoutProperties3.default)(_props, [ "initialWidth", "theme", "width" ]), props = (0,
- _extends3.default)({
- width: width || this.state.width || initialWidth
- }, other);
- return void 0 === props.width ? null : _react2.default.createElement(_reactEventListener2.default, {
- target: "window",
- onResize: this.handleResize
- }, _react2.default.createElement(Component, props));
- }
- } ]), Width;
- }(_react2.default.Component);
- return Width.propTypes = "production" !== process.env.NODE_ENV ? {
- initialWidth: _propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ]),
- theme: _propTypes2.default.object.isRequired,
- width: _propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ])
- } : {}, "production" !== process.env.NODE_ENV && (Width.displayName = (0, _wrapDisplayName2.default)(Component, "withWidth")),
- (0, _hoistNonReactStatics2.default)(Width, Component), (0, _withTheme2.default)()(Width);
- };
- });
- exports.default = withWidth;
- }).call(exports, __webpack_require__(3));
-}, function(module, exports, __webpack_require__) {
- "use strict";
- (function(process) {
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
- };
- }
- function mergeDefaultEventOptions(options) {
- return (0, _assign2.default)({}, defaultEventOptions, options);
- }
- function getEventListenerArgs(eventName, callback, options) {
- var args = [ eventName, callback ];
- return args.push(supports.passiveOption ? options : options.capture), args;
- }
- function on(target, eventName, callback, options) {
- supports.addEventListener ? target.addEventListener.apply(target, getEventListenerArgs(eventName, callback, options)) : supports.attachEvent && target.attachEvent("on" + eventName, function() {
- callback.call(target);
- });
- }
- function off(target, eventName, callback, options) {
- supports.removeEventListener ? target.removeEventListener.apply(target, getEventListenerArgs(eventName, callback, options)) : supports.detachEvent && target.detachEvent("on" + eventName, callback);
- }
- function forEachListener(props, iteratee) {
- var eventProps = (props.children, props.target, (0, _objectWithoutProperties3.default)(props, [ "children", "target" ]));
- (0, _keys2.default)(eventProps).forEach(function(name) {
- if ("on" === name.substring(0, 2)) {
- var prop = eventProps[name], type = void 0 === prop ? "undefined" : (0, _typeof3.default)(prop), isObject = "object" === type, isFunction = "function" === type;
- if (isObject || isFunction) {
- var capture = "capture" === name.substr(-7).toLowerCase(), eventName = name.substring(2).toLowerCase();
- eventName = capture ? eventName.substring(0, eventName.length - 7) : eventName,
- isObject ? iteratee(eventName, prop.handler, prop.options) : iteratee(eventName, prop, mergeDefaultEventOptions({
- capture: capture
- }));
- }
- }
- });
- }
- function withOptions(handler, options) {
- return "production" !== process.env.NODE_ENV && (0, _warning2.default)(options, "react-event-listener: Should be specified options in withOptions."),
- {
- handler: handler,
- options: mergeDefaultEventOptions(options)
- };
- }
- Object.defineProperty(exports, "__esModule", {
- value: !0
- });
- var _getPrototypeOf = __webpack_require__(38), _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf), _classCallCheck2 = __webpack_require__(39), _classCallCheck3 = _interopRequireDefault(_classCallCheck2), _createClass2 = __webpack_require__(40), _createClass3 = _interopRequireDefault(_createClass2), _possibleConstructorReturn2 = __webpack_require__(41), _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2), _inherits2 = __webpack_require__(42), _inherits3 = _interopRequireDefault(_inherits2), _typeof2 = __webpack_require__(126), _typeof3 = _interopRequireDefault(_typeof2), _keys = __webpack_require__(51), _keys2 = _interopRequireDefault(_keys), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _assign = __webpack_require__(268), _assign2 = _interopRequireDefault(_assign);
- exports.withOptions = withOptions;
- var _react = __webpack_require__(1), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _shallowEqual = __webpack_require__(122), _shallowEqual2 = _interopRequireDefault(_shallowEqual), _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), _supports = __webpack_require__(1121), supports = function(obj) {
- if (obj && obj.__esModule) return obj;
- var newObj = {};
- if (null != obj) for (var key in obj) Object.prototype.hasOwnProperty.call(obj, key) && (newObj[key] = obj[key]);
- return newObj.default = obj, newObj;
- }(_supports), defaultEventOptions = {
- capture: !1,
- passive: !1
- }, EventListener = function(_Component) {
- function EventListener() {
- return (0, _classCallCheck3.default)(this, EventListener), (0, _possibleConstructorReturn3.default)(this, (EventListener.__proto__ || (0,
- _getPrototypeOf2.default)(EventListener)).apply(this, arguments));
+ function _possibleConstructorReturn(self, call) {
+ if (!self) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+ return !call || "object" != typeof call && "function" != typeof call ? self : call;
+ }
+ function _inherits(subClass, superClass) {
+ if ("function" != typeof superClass && null !== superClass) throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
+ subClass.prototype = Object.create(superClass && superClass.prototype, {
+ constructor: {
+ value: subClass,
+ enumerable: !1,
+ writable: !0,
+ configurable: !0
}
- return (0, _inherits3.default)(EventListener, _Component), (0, _createClass3.default)(EventListener, [ {
- key: "componentDidMount",
- value: function() {
- this.addListeners();
- }
- }, {
- key: "shouldComponentUpdate",
- value: function(nextProps) {
- return !(0, _shallowEqual2.default)(this.props, nextProps);
- }
- }, {
- key: "componentWillUpdate",
- value: function() {
- this.removeListeners();
- }
- }, {
- key: "componentDidUpdate",
- value: function() {
- this.addListeners();
- }
- }, {
- key: "componentWillUnmount",
- value: function() {
- this.removeListeners();
- }
- }, {
- key: "addListeners",
- value: function() {
- this.applyListeners(on);
- }
- }, {
- key: "removeListeners",
- value: function() {
- this.applyListeners(off);
- }
- }, {
- key: "applyListeners",
- value: function(onOrOff) {
- var target = this.props.target;
- if (target) {
- var element = target;
- "string" == typeof target && (element = window[target]), forEachListener(this.props, onOrOff.bind(null, element));
- }
- }
- }, {
- key: "render",
- value: function() {
- return this.props.children || null;
- }
- } ]), EventListener;
- }(_react.Component);
- EventListener.propTypes = "production" !== process.env.NODE_ENV ? {
- children: _propTypes2.default.element,
- target: _propTypes2.default.oneOfType([ _propTypes2.default.object, _propTypes2.default.string ]).isRequired
- } : {}, exports.default = EventListener;
- }).call(exports, __webpack_require__(3));
-}, function(module, exports, __webpack_require__) {
- "use strict";
- function defineProperty(o, p, attr) {
- return (0, _defineProperty2.default)(o, p, attr);
+ }), superClass && (Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass);
}
Object.defineProperty(exports, "__esModule", {
value: !0
- }), exports.passiveOption = exports.detachEvent = exports.attachEvent = exports.removeEventListener = exports.addEventListener = void 0;
- var _defineProperty = __webpack_require__(185), _defineProperty2 = function(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
- };
- }(_defineProperty), canUseDOM = !("undefined" == typeof window || !window.document || !window.document.createElement);
- exports.addEventListener = canUseDOM && "addEventListener" in window, exports.removeEventListener = canUseDOM && "removeEventListener" in window,
- exports.attachEvent = canUseDOM && "attachEvent" in window, exports.detachEvent = canUseDOM && "detachEvent" in window,
- exports.passiveOption = function() {
- var cache = null;
- return function() {
- if (null !== cache) return cache;
- var supportsPassiveOption = !1;
- try {
- window.addEventListener("test", null, defineProperty({}, "passive", {
- get: function() {
- supportsPassiveOption = !0;
- }
- }));
- } catch (e) {}
- return cache = supportsPassiveOption, supportsPassiveOption;
- }();
- }();
-}, function(module, exports, __webpack_require__) {
- "use strict";
- (function(process) {
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {
- default: obj
- };
- }
- function HiddenCss(props) {
- var children = props.children, classes = props.classes, only = (props.lgDown, props.lgUp,
- props.mdDown, props.mdUp, props.only), other = (props.smDown, props.smUp, props.xlDown,
- props.xlUp, props.xsDown, props.xsUp, (0, _objectWithoutProperties3.default)(props, [ "children", "classes", "lgDown", "lgUp", "mdDown", "mdUp", "only", "smDown", "smUp", "xlDown", "xlUp", "xsDown", "xsUp" ]));
- "production" !== process.env.NODE_ENV && (0, _warning2.default)(0 === (0, _keys2.default)(other).length || 1 === (0,
- _keys2.default)(other).length && other.hasOwnProperty("ref"), "Material-UI: unsupported properties received " + (0,
- _keys2.default)(other).join(", ") + " by ` + "`" + `<Hidden />` + "`" + `.");
- for (var className = [], i = 0; i < _createBreakpoints.keys.length; i += 1) {
- var breakpoint = _createBreakpoints.keys[i], breakpointUp = props[breakpoint + "Up"], breakpointDown = props[breakpoint + "Down"];
- breakpointUp && className.push(classes[breakpoint + "Up"]), breakpointDown && className.push(classes[breakpoint + "Down"]);
- }
- if (only) {
- (Array.isArray(only) ? only : [ only ]).forEach(function(breakpoint) {
- className.push(classes["only" + (0, _helpers.capitalizeFirstLetter)(breakpoint)]);
- });
+ }), exports.bytePerSecPlotter = exports.bytePlotter = exports.percentPlotter = exports.multiplier = void 0;
+ var _createClass = function() {
+ function defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i];
+ descriptor.enumerable = descriptor.enumerable || !1, descriptor.configurable = !0,
+ "value" in descriptor && (descriptor.writable = !0), Object.defineProperty(target, descriptor.key, descriptor);
}
- return _react2.default.createElement("span", {
- className: className
- }, children);
}
- Object.defineProperty(exports, "__esModule", {
- value: !0
- });
- var _keys = __webpack_require__(51), _keys2 = _interopRequireDefault(_keys), _objectWithoutProperties2 = __webpack_require__(9), _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2), _defineProperty2 = __webpack_require__(17), _defineProperty3 = _interopRequireDefault(_defineProperty2), _react = __webpack_require__(1), _react2 = _interopRequireDefault(_react), _propTypes = __webpack_require__(2), _propTypes2 = _interopRequireDefault(_propTypes), _warning = __webpack_require__(14), _warning2 = _interopRequireDefault(_warning), _createBreakpoints = __webpack_require__(94), _helpers = __webpack_require__(69), _withStyles = __webpack_require__(13), _withStyles2 = _interopRequireDefault(_withStyles), styles = function(theme) {
- var hidden = {
- display: "none"
- };
- return _createBreakpoints.keys.reduce(function(acc, key) {
- return acc["only" + (0, _helpers.capitalizeFirstLetter)(key)] = (0, _defineProperty3.default)({}, theme.breakpoints.only(key), hidden),
- acc[key + "Up"] = (0, _defineProperty3.default)({}, theme.breakpoints.up(key), hidden),
- acc[key + "Down"] = (0, _defineProperty3.default)({}, theme.breakpoints.down(key), hidden),
- acc;
- }, {});
+ return function(Constructor, protoProps, staticProps) {
+ return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
+ Constructor;
};
- HiddenCss.propTypes = "production" !== process.env.NODE_ENV ? {
- children: _propTypes2.default.node,
- classes: _propTypes2.default.object.isRequired,
- className: _propTypes2.default.string,
- implementation: _propTypes2.default.oneOf([ "js", "css" ]),
- initialWidth: _propTypes2.default.number,
- lgDown: _propTypes2.default.bool,
- lgUp: _propTypes2.default.bool,
- mdDown: _propTypes2.default.bool,
- mdUp: _propTypes2.default.bool,
- only: _propTypes2.default.oneOfType([ _propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ]), _propTypes2.default.arrayOf(_propTypes2.default.oneOf([ "xs", "sm", "md", "lg", "xl" ])) ]),
- smDown: _propTypes2.default.bool,
- smUp: _propTypes2.default.bool,
- xlDown: _propTypes2.default.bool,
- xlUp: _propTypes2.default.bool,
- xsDown: _propTypes2.default.bool,
- xsUp: _propTypes2.default.bool
- } : {}, exports.default = (0, _withStyles2.default)(styles, {
- name: "MuiHiddenCss"
- })(HiddenCss);
- }).call(exports, __webpack_require__(3));
-} ]);`)
-
-func publicBundleJsBytes() ([]byte, error) {
- return _publicBundleJs, nil
-}
-
-func publicBundleJs() (*asset, error) {
- bytes, err := publicBundleJsBytes()
- if err != nil {
- return nil, err
- }
-
- info := bindataFileInfo{name: "public/bundle.js", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
- a := &asset{bytes: bytes, info: info}
- return a, nil
-}
-
-//nolint:misspell
-var _publicDashboardHtml = []byte(`<!DOCTYPE html>
-<html lang="en" style="height: 100%">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1">
-
- <title>Go Ethereum Dashboard</title>
- <link rel="shortcut icon" type="image/ico" href="https://ethereum.org/favicon.ico" />
- <style>
- ::-webkit-scrollbar {
- width: 16px;
- }
- ::-webkit-scrollbar-thumb {
- background: #212121;
+ }(), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _Typography = __webpack_require__(109), _Typography2 = _interopRequireDefault(_Typography), _common = __webpack_require__(61), multiplier = exports.multiplier = function() {
+ var by = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : 1;
+ return function(x) {
+ return x * by;
+ };
+ }, unit = (exports.percentPlotter = function(text) {
+ var mapper = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : multiplier(1);
+ return function(payload) {
+ var p = mapper(payload);
+ return "number" != typeof p ? null : _react2.default.createElement(_Typography2.default, {
+ type: "caption",
+ color: "inherit"
+ }, _react2.default.createElement("span", {
+ style: _common.styles.light
+ }, text), " ", p.toFixed(2), " %");
+ };
+ }, [ "B", "KB", "MB", "GB", "TB", "PB" ]), simplifyBytes = function(x) {
+ for (var i = 0; x > 1024 && i < 5; i++) x /= 1024;
+ return x.toFixed(2).toString().concat(" ", unit[i]);
+ }, CustomTooltip = (exports.bytePlotter = function(text) {
+ var mapper = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : multiplier(1);
+ return function(payload) {
+ var p = mapper(payload);
+ return "number" != typeof p ? null : _react2.default.createElement(_Typography2.default, {
+ type: "caption",
+ color: "inherit"
+ }, _react2.default.createElement("span", {
+ style: _common.styles.light
+ }, text), " ", simplifyBytes(p));
+ };
+ }, exports.bytePerSecPlotter = function(text) {
+ var mapper = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : multiplier(1);
+ return function(payload) {
+ var p = mapper(payload);
+ return "number" != typeof p ? null : _react2.default.createElement(_Typography2.default, {
+ type: "caption",
+ color: "inherit"
+ }, _react2.default.createElement("span", {
+ style: _common.styles.light
+ }, text), " ", simplifyBytes(p), "/s");
+ };
+ }, function(_Component) {
+ function CustomTooltip() {
+ return _classCallCheck(this, CustomTooltip), _possibleConstructorReturn(this, (CustomTooltip.__proto__ || Object.getPrototypeOf(CustomTooltip)).apply(this, arguments));
+ }
+ return _inherits(CustomTooltip, _Component), _createClass(CustomTooltip, [ {
+ key: "render",
+ value: function() {
+ var _props = this.props, active = _props.active, payload = _props.payload, tooltip = _props.tooltip;
+ return active && "function" == typeof tooltip ? tooltip(payload[0].value) : null;
}
- </style>
- </head>
- <body style="height: 100%; margin: 0">
- <div id="dashboard" style="height: 100%"></div>
- <script src="bundle.js"></script>
- </body>
-</html>
-`)
+ } ]), CustomTooltip;
+ }(_react.Component));
+ exports.default = CustomTooltip;
+} ]);`)))))))))))
-func publicDashboardHtmlBytes() ([]byte, error) {
- return _publicDashboardHtml, nil
+func bundleJsBytes() ([]byte, error) {
+ return _bundleJs, nil
}
-func publicDashboardHtml() (*asset, error) {
- bytes, err := publicDashboardHtmlBytes()
+func bundleJs() (*asset, error) {
+ bytes, err := bundleJsBytes()
if err != nil {
return nil, err
}
- info := bindataFileInfo{name: "public/dashboard.html", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
- a := &asset{bytes: bytes, info: info}
+ info := bindataFileInfo{name: "bundle.js", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+ a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc0, 0x90, 0x71, 0xbf, 0x69, 0x84, 0xe8, 0x63, 0x9a, 0x6c, 0x14, 0x49, 0xbd, 0x8b, 0x72, 0x2b, 0xe2, 0xd7, 0xdf, 0x49, 0x80, 0xea, 0x49, 0x2e, 0x7d, 0x4f, 0x23, 0x6b, 0xef, 0xcd, 0xc4, 0xdb}}
return a, nil
}
@@ -42160,8 +38408,8 @@ func publicDashboardHtml() (*asset, error) {
// It returns an error if the asset could not be found or
// could not be loaded.
func Asset(name string) ([]byte, error) {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- if f, ok := _bindata[cannonicalName]; ok {
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ if f, ok := _bindata[canonicalName]; ok {
a, err := f()
if err != nil {
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
@@ -42171,6 +38419,12 @@ func Asset(name string) ([]byte, error) {
return nil, fmt.Errorf("Asset %s not found", name)
}
+// AssetString returns the asset contents as a string (instead of a []byte).
+func AssetString(name string) (string, error) {
+ data, err := Asset(name)
+ return string(data), err
+}
+
// MustAsset is like Asset but panics when Asset would return an error.
// It simplifies safe initialization of global variables.
func MustAsset(name string) []byte {
@@ -42182,12 +38436,18 @@ func MustAsset(name string) []byte {
return a
}
+// MustAssetString is like AssetString but panics when Asset would return an
+// error. It simplifies safe initialization of global variables.
+func MustAssetString(name string) string {
+ return string(MustAsset(name))
+}
+
// AssetInfo loads and returns the asset info for the given name.
// It returns an error if the asset could not be found or
// could not be loaded.
func AssetInfo(name string) (os.FileInfo, error) {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- if f, ok := _bindata[cannonicalName]; ok {
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ if f, ok := _bindata[canonicalName]; ok {
a, err := f()
if err != nil {
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
@@ -42197,6 +38457,33 @@ func AssetInfo(name string) (os.FileInfo, error) {
return nil, fmt.Errorf("AssetInfo %s not found", name)
}
+// AssetDigest returns the digest of the file with the given name. It returns an
+// error if the asset could not be found or the digest could not be loaded.
+func AssetDigest(name string) ([sha256.Size]byte, error) {
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ if f, ok := _bindata[canonicalName]; ok {
+ a, err := f()
+ if err != nil {
+ return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err)
+ }
+ return a.digest, nil
+ }
+ return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name)
+}
+
+// Digests returns a map of all known files and their checksums.
+func Digests() (map[string][sha256.Size]byte, error) {
+ mp := make(map[string][sha256.Size]byte, len(_bindata))
+ for name := range _bindata {
+ a, err := _bindata[name]()
+ if err != nil {
+ return nil, err
+ }
+ mp[name] = a.digest
+ }
+ return mp, nil
+}
+
// AssetNames returns the names of the assets.
func AssetNames() []string {
names := make([]string, 0, len(_bindata))
@@ -42208,8 +38495,9 @@ func AssetNames() []string {
// _bindata is a table, holding each asset generator, mapped to its name.
var _bindata = map[string]func() (*asset, error){
- "public/bundle.js": publicBundleJs,
- "public/dashboard.html": publicDashboardHtml,
+ "dashboard.html": dashboardHtml,
+
+ "bundle.js": bundleJs,
}
// AssetDir returns the file names below a certain
@@ -42221,15 +38509,15 @@ var _bindata = map[string]func() (*asset, error){
// img/
// a.png
// b.png
-// then AssetDir("data") would return []string{"foo.txt", "img"}
-// AssetDir("data/img") would return []string{"a.png", "b.png"}
-// AssetDir("foo.txt") and AssetDir("notexist") would return an error
+// then AssetDir("data") would return []string{"foo.txt", "img"},
+// AssetDir("data/img") would return []string{"a.png", "b.png"},
+// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and
// AssetDir("") will return []string{"data"}.
func AssetDir(name string) ([]string, error) {
node := _bintree
if len(name) != 0 {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- pathList := strings.Split(cannonicalName, "/")
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ pathList := strings.Split(canonicalName, "/")
for _, p := range pathList {
node = node.Children[p]
if node == nil {
@@ -42253,13 +38541,11 @@ type bintree struct {
}
var _bintree = &bintree{nil, map[string]*bintree{
- "public": {nil, map[string]*bintree{
- "bundle.js": {publicBundleJs, map[string]*bintree{}},
- "dashboard.html": {publicDashboardHtml, map[string]*bintree{}},
- }},
+ "bundle.js": {bundleJs, map[string]*bintree{}},
+ "dashboard.html": {dashboardHtml, map[string]*bintree{}},
}}
-// RestoreAsset restores an asset under the given directory
+// RestoreAsset restores an asset under the given directory.
func RestoreAsset(dir, name string) error {
data, err := Asset(name)
if err != nil {
@@ -42277,14 +38563,10 @@ func RestoreAsset(dir, name string) error {
if err != nil {
return err
}
- err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
- if err != nil {
- return err
- }
- return nil
+ return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
}
-// RestoreAssets restores an asset under the given directory recursively
+// RestoreAssets restores an asset under the given directory recursively.
func RestoreAssets(dir, name string) error {
children, err := AssetDir(name)
// File
@@ -42302,6 +38584,6 @@ func RestoreAssets(dir, name string) error {
}
func _filePath(dir, name string) string {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
}
diff --git a/dashboard/assets/.eslintrc b/dashboard/assets/.eslintrc
index 67c11dcc0..ab7a3a039 100644
--- a/dashboard/assets/.eslintrc
+++ b/dashboard/assets/.eslintrc
@@ -40,6 +40,9 @@
'react/jsx-indent': ['error', 'tab'],
'react/jsx-indent-props': ['error', 'tab'],
'react/prefer-stateless-function': 'off',
+ 'jsx-quotes': ['error', 'prefer-single'],
+ 'no-plusplus': 'off',
+ 'no-console': ['error', { allow: ['error'] }],
// Specifies the maximum length of a line.
'max-len': ['warn', 120, 2, {
@@ -49,7 +52,7 @@
'ignoreStrings': true,
'ignoreTemplateLiterals': true,
}],
- // Enforces spacing between keys and values in object literal properties.
+ // Enforces consistent spacing between keys and values in object literal properties.
'key-spacing': ['error', {'align': {
'beforeColon': false,
'afterColon': true,
diff --git a/dashboard/assets/components/Common.jsx b/dashboard/assets/common.jsx
index d8723830e..08a7554ff 100644
--- a/dashboard/assets/components/Common.jsx
+++ b/dashboard/assets/common.jsx
@@ -62,32 +62,10 @@ export type MenuProp = {|...ProvidedMenuProp, id: string|};
// This way the mistyping is prevented.
export const MENU: Map<string, {...MenuProp}> = new Map(menuSkeletons.map(({id, menu}) => ([id, {id, ...menu}])));
-type ProvidedSampleProp = {|limit: number|};
-const sampleSkeletons: Array<{|id: string, sample: ProvidedSampleProp|}> = [
- {
- id: 'memory',
- sample: {
- limit: 200,
- },
- }, {
- id: 'traffic',
- sample: {
- limit: 200,
- },
- }, {
- id: 'logs',
- sample: {
- limit: 200,
- },
- },
-];
-export type SampleProp = {|...ProvidedSampleProp, id: string|};
-export const SAMPLE: Map<string, {...SampleProp}> = new Map(sampleSkeletons.map(({id, sample}) => ([id, {id, ...sample}])));
-
export const DURATION = 200;
-export const LENS: Map<string, string> = new Map([
- 'content',
- ...menuSkeletons.map(({id}) => id),
- ...sampleSkeletons.map(({id}) => id),
-].map(lens => [lens, lens]));
+export const styles = {
+ light: {
+ color: 'rgba(255, 255, 255, 0.54)',
+ },
+}
diff --git a/dashboard/assets/components/Body.jsx b/dashboard/assets/components/Body.jsx
index 14e9ac358..054e04064 100644
--- a/dashboard/assets/components/Body.jsx
+++ b/dashboard/assets/components/Body.jsx
@@ -18,35 +18,32 @@
import React, {Component} from 'react';
-import withStyles from 'material-ui/styles/withStyles';
-
import SideBar from './SideBar';
import Main from './Main';
import type {Content} from '../types/content';
-// Styles for the Body component.
-const styles = () => ({
+// styles contains the constant styles of the component.
+const styles = {
body: {
display: 'flex',
width: '100%',
height: '100%',
},
-});
+};
+
export type Props = {
- classes: Object,
opened: boolean,
- changeContent: () => {},
+ changeContent: string => void,
active: string,
content: Content,
shouldUpdate: Object,
};
+
// Body renders the body of the dashboard.
class Body extends Component<Props> {
render() {
- const {classes} = this.props; // The classes property is injected by withStyles().
-
return (
- <div className={classes.body}>
+ <div style={styles.body}>
<SideBar
opened={this.props.opened}
changeContent={this.props.changeContent}
@@ -61,4 +58,4 @@ class Body extends Component<Props> {
}
}
-export default withStyles(styles)(Body);
+export default Body;
diff --git a/dashboard/assets/components/ChartGrid.jsx b/dashboard/assets/components/ChartRow.jsx
index 45dde7499..1075346fe 100644
--- a/dashboard/assets/components/ChartGrid.jsx
+++ b/dashboard/assets/components/ChartRow.jsx
@@ -1,6 +1,6 @@
// @flow
-// Copyright 2017 The go-ethereum Authors
+// Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
@@ -17,33 +17,41 @@
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
import React, {Component} from 'react';
-import type {Node} from 'react';
+import type {ChildrenArray} from 'react';
import Grid from 'material-ui/Grid';
-import {ResponsiveContainer} from 'recharts';
+
+// styles contains the constant styles of the component.
+const styles = {
+ container: {
+ flexWrap: 'nowrap',
+ height: '100%',
+ maxWidth: '100%',
+ margin: 0,
+ },
+ item: {
+ flex: 1,
+ padding: 0,
+ },
+}
export type Props = {
- spacing: number,
- children: Node,
+ children: ChildrenArray<React$Element<any>>,
};
-// ChartGrid renders a grid container for responsive charts.
-// The children are Recharts components extended with the Material-UI's xs property.
-class ChartGrid extends Component<Props> {
+
+// ChartRow renders a row of equally sized responsive charts.
+class ChartRow extends Component<Props> {
render() {
return (
- <Grid container spacing={this.props.spacing}>
- {
- React.Children.map(this.props.children, child => (
- <Grid item xs={child.props.xs}>
- <ResponsiveContainer width="100%" height={child.props.height}>
- {React.cloneElement(child, {data: child.props.values.map(value => ({value}))})}
- </ResponsiveContainer>
- </Grid>
- ))
- }
+ <Grid container direction='row' style={styles.container} justify='space-between'>
+ {React.Children.map(this.props.children, child => (
+ <Grid item xs style={styles.item}>
+ {child}
+ </Grid>
+ ))}
</Grid>
);
}
}
-export default ChartGrid;
+export default ChartRow;
diff --git a/dashboard/assets/components/CustomTooltip.jsx b/dashboard/assets/components/CustomTooltip.jsx
new file mode 100644
index 000000000..be7c624cf
--- /dev/null
+++ b/dashboard/assets/components/CustomTooltip.jsx
@@ -0,0 +1,95 @@
+// @flow
+
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+import React, {Component} from 'react';
+
+import Typography from 'material-ui/Typography';
+import {styles} from '../common';
+
+// multiplier multiplies a number by another.
+export const multiplier = <T>(by: number = 1) => (x: number) => x * by;
+
+// percentPlotter renders a tooltip, which displays the value of the payload followed by a percent sign.
+export const percentPlotter = <T>(text: string, mapper: (T => T) = multiplier(1)) => (payload: T) => {
+ const p = mapper(payload);
+ if (typeof p !== 'number') {
+ return null;
+ }
+ return (
+ <Typography type='caption' color='inherit'>
+ <span style={styles.light}>{text}</span> {p.toFixed(2)} %
+ </Typography>
+ );
+};
+
+// unit contains the units for the bytePlotter.
+const unit = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
+
+// simplifyBytes returns the simplified version of the given value followed by the unit.
+const simplifyBytes = (x: number) => {
+ let i = 0;
+ for (; x > 1024 && i < 5; i++) {
+ x /= 1024;
+ }
+ return x.toFixed(2).toString().concat(' ', unit[i]);
+};
+
+// bytePlotter renders a tooltip, which displays the payload as a byte value.
+export const bytePlotter = <T>(text: string, mapper: (T => T) = multiplier(1)) => (payload: T) => {
+ const p = mapper(payload);
+ if (typeof p !== 'number') {
+ return null;
+ }
+ return (
+ <Typography type='caption' color='inherit'>
+ <span style={styles.light}>{text}</span> {simplifyBytes(p)}
+ </Typography>
+ );
+};
+
+// bytePlotter renders a tooltip, which displays the payload as a byte value followed by '/s'.
+export const bytePerSecPlotter = <T>(text: string, mapper: (T => T) = multiplier(1)) => (payload: T) => {
+ const p = mapper(payload);
+ if (typeof p !== 'number') {
+ return null;
+ }
+ return (
+ <Typography type='caption' color='inherit'>
+ <span style={styles.light}>{text}</span> {simplifyBytes(p)}/s
+ </Typography>
+ );
+};
+
+export type Props = {
+ active: boolean,
+ payload: Object,
+ tooltip: <T>(text: string, mapper?: T => T) => (payload: mixed) => null | React$Element<any>,
+};
+
+// CustomTooltip takes a tooltip function, and uses it to plot the active value of the chart.
+class CustomTooltip extends Component<Props> {
+ render() {
+ const {active, payload, tooltip} = this.props;
+ if (!active || typeof tooltip !== 'function') {
+ return null;
+ }
+ return tooltip(payload[0].value);
+ }
+}
+
+export default CustomTooltip;
diff --git a/dashboard/assets/components/Dashboard.jsx b/dashboard/assets/components/Dashboard.jsx
index b60736d8c..90b1a785c 100644
--- a/dashboard/assets/components/Dashboard.jsx
+++ b/dashboard/assets/components/Dashboard.jsx
@@ -19,57 +19,144 @@
import React, {Component} from 'react';
import withStyles from 'material-ui/styles/withStyles';
-import {lensPath, view, set} from 'ramda';
import Header from './Header';
import Body from './Body';
-import {MENU, SAMPLE} from './Common';
-import type {Message, HomeMessage, LogsMessage, Chart} from '../types/message';
+import {MENU} from '../common';
import type {Content} from '../types/content';
-// appender appends an array (A) to the end of another array (B) in the state.
-// lens is the path of B in the state, samples is A, and limit is the maximum size of the changed array.
+// deepUpdate updates an object corresponding to the given update data, which has
+// the shape of the same structure as the original object. updater also has the same
+// structure, except that it contains functions where the original data needs to be
+// updated. These functions are used to handle the update.
//
-// appender retrieves a function, which overrides the state's value at lens, and returns with the overridden state.
-const appender = (lens, samples, limit) => (state) => {
- const newSamples = [
- ...view(lens, state), // retrieves a specific value of the state at the given path (lens).
- ...samples,
- ];
- // set is a function of ramda.js, which needs the path, the new value, the original state, and retrieves
- // the altered state.
- return set(
- lens,
- newSamples.slice(newSamples.length > limit ? newSamples.length - limit : 0),
- state
- );
+// Since the messages have the same shape as the state content, this approach allows
+// the generalization of the message handling. The only necessary thing is to set a
+// handler function for every path of the state in order to maximize the flexibility
+// of the update.
+const deepUpdate = (updater: Object, update: Object, prev: Object): $Shape<Content> => {
+ if (typeof update === 'undefined') {
+ // TODO (kurkomisi): originally this was deep copy, investigate it.
+ return prev;
+ }
+ if (typeof updater === 'function') {
+ return updater(update, prev);
+ }
+ const updated = {};
+ Object.keys(prev).forEach((key) => {
+ updated[key] = deepUpdate(updater[key], update[key], prev[key]);
+ });
+
+ return updated;
+};
+
+// shouldUpdate returns the structure of a message. It is used to prevent unnecessary render
+// method triggerings. In the affected component's shouldComponentUpdate method it can be checked
+// whether the involved data was changed or not by checking the message structure.
+//
+// We could return the message itself too, but it's safer not to give access to it.
+const shouldUpdate = (updater: Object, msg: Object) => {
+ const su = {};
+ Object.keys(msg).forEach((key) => {
+ su[key] = typeof updater[key] !== 'function' ? shouldUpdate(updater[key], msg[key]) : true;
+ });
+
+ return su;
+};
+
+// replacer is a state updater function, which replaces the original data.
+const replacer = <T>(update: T) => update;
+
+// appender is a state updater function, which appends the update data to the
+// existing data. limit defines the maximum allowed size of the created array,
+// mapper maps the update data.
+const appender = <T>(limit: number, mapper = replacer) => (update: Array<T>, prev: Array<T>) => [
+ ...prev,
+ ...update.map(sample => mapper(sample)),
+].slice(-limit);
+
+// defaultContent is the initial value of the state content.
+const defaultContent: Content = {
+ general: {
+ version: null,
+ commit: null,
+ },
+ home: {
+ activeMemory: [],
+ virtualMemory: [],
+ networkIngress: [],
+ networkEgress: [],
+ processCPU: [],
+ systemCPU: [],
+ diskRead: [],
+ diskWrite: [],
+ },
+ chain: {},
+ txpool: {},
+ network: {},
+ system: {},
+ logs: {
+ log: [],
+ },
+};
+
+// updaters contains the state updater functions for each path of the state.
+//
+// TODO (kurkomisi): Define a tricky type which embraces the content and the updaters.
+const updaters = {
+ general: {
+ version: replacer,
+ commit: replacer,
+ },
+ home: {
+ activeMemory: appender(200),
+ virtualMemory: appender(200),
+ networkIngress: appender(200),
+ networkEgress: appender(200),
+ processCPU: appender(200),
+ systemCPU: appender(200),
+ diskRead: appender(200),
+ diskWrite: appender(200),
+ },
+ chain: null,
+ txpool: null,
+ network: null,
+ system: null,
+ logs: {
+ log: appender(200),
+ },
+};
+
+// styles contains the constant styles of the component.
+const styles = {
+ dashboard: {
+ display: 'flex',
+ flexFlow: 'column',
+ width: '100%',
+ height: '100%',
+ zIndex: 1,
+ overflow: 'hidden',
+ }
};
-// Lenses for specific data fields in the state, used for a clearer deep update.
-// NOTE: This solution will be changed very likely.
-const memoryLens = lensPath(['content', 'home', 'memory']);
-const trafficLens = lensPath(['content', 'home', 'traffic']);
-const logLens = lensPath(['content', 'logs', 'log']);
-// styles retrieves the styles for the Dashboard component.
-const styles = theme => ({
+
+// themeStyles returns the styles generated from the theme for the component.
+const themeStyles: Object = (theme: Object) => ({
dashboard: {
- display: 'flex',
- flexFlow: 'column',
- width: '100%',
- height: '100%',
background: theme.palette.background.default,
- zIndex: 1,
- overflow: 'hidden',
},
});
+
export type Props = {
- classes: Object,
+ classes: Object, // injected by withStyles()
};
+
type State = {
active: string, // active menu
sideBar: boolean, // true if the sidebar is opened
- content: $Shape<Content>, // the visualized data
- shouldUpdate: Set<string> // labels for the components, which need to rerender based on the incoming message
+ content: Content, // the visualized data
+ shouldUpdate: Object, // labels for the components, which need to re-render based on the incoming message
};
+
// Dashboard is the main component, which renders the whole page, makes connection with the server and
// listens for messages. When there is an incoming message, updates the page's content correspondingly.
class Dashboard extends Component<Props, State> {
@@ -78,8 +165,8 @@ class Dashboard extends Component<Props, State> {
this.state = {
active: MENU.get('home').id,
sideBar: true,
- content: {home: {memory: [], traffic: []}, logs: {log: []}},
- shouldUpdate: new Set(),
+ content: defaultContent,
+ shouldUpdate: {},
};
}
@@ -91,13 +178,14 @@ class Dashboard extends Component<Props, State> {
// reconnect establishes a websocket connection with the server, listens for incoming messages
// and tries to reconnect on connection loss.
reconnect = () => {
- this.setState({
- content: {home: {memory: [], traffic: []}, logs: {log: []}},
- });
const server = new WebSocket(`${((window.location.protocol === 'https:') ? 'wss://' : 'ws://') + window.location.host}/api`);
+ server.onopen = () => {
+ this.setState({content: defaultContent, shouldUpdate: {}});
+ };
server.onmessage = (event) => {
- const msg: Message = JSON.parse(event.data);
+ const msg: $Shape<Content> = JSON.parse(event.data);
if (!msg) {
+ console.error(`Incoming message is ${msg}`);
return;
}
this.update(msg);
@@ -107,56 +195,12 @@ class Dashboard extends Component<Props, State> {
};
};
- // samples retrieves the raw data of a chart field from the incoming message.
- samples = (chart: Chart) => {
- let s = [];
- if (chart.history) {
- s = chart.history.map(({value}) => (value || 0)); // traffic comes without value at the beginning
- }
- if (chart.new) {
- s = [...s, chart.new.value || 0];
- }
- return s;
- };
-
- // handleHome changes the home-menu related part of the state.
- handleHome = (home: HomeMessage) => {
- this.setState((prevState) => {
- let newState = prevState;
- newState.shouldUpdate = new Set();
- if (home.memory) {
- newState = appender(memoryLens, this.samples(home.memory), SAMPLE.get('memory').limit)(newState);
- newState.shouldUpdate.add('memory');
- }
- if (home.traffic) {
- newState = appender(trafficLens, this.samples(home.traffic), SAMPLE.get('traffic').limit)(newState);
- newState.shouldUpdate.add('traffic');
- }
- return newState;
- });
- };
-
- // handleLogs changes the logs-menu related part of the state.
- handleLogs = (logs: LogsMessage) => {
- this.setState((prevState) => {
- let newState = prevState;
- newState.shouldUpdate = new Set();
- if (logs.log) {
- newState = appender(logLens, [logs.log], SAMPLE.get('logs').limit)(newState);
- newState.shouldUpdate.add('logs');
- }
- return newState;
- });
- };
-
- // update analyzes the incoming message, and updates the charts' content correspondingly.
- update = (msg: Message) => {
- if (msg.home) {
- this.handleHome(msg.home);
- }
- if (msg.logs) {
- this.handleLogs(msg.logs);
- }
+ // update updates the content corresponding to the incoming message.
+ update = (msg: $Shape<Content>) => {
+ this.setState(prevState => ({
+ content: deepUpdate(updaters, msg, prevState.content),
+ shouldUpdate: shouldUpdate(updaters, msg),
+ }));
};
// changeContent sets the active label, which is used at the content rendering.
@@ -164,25 +208,17 @@ class Dashboard extends Component<Props, State> {
this.setState(prevState => (prevState.active !== newActive ? {active: newActive} : {}));
};
- // openSideBar opens the sidebar.
- openSideBar = () => {
- this.setState({sideBar: true});
- };
-
- // closeSideBar closes the sidebar.
- closeSideBar = () => {
- this.setState({sideBar: false});
+ // switchSideBar opens or closes the sidebar's state.
+ switchSideBar = () => {
+ this.setState(prevState => ({sideBar: !prevState.sideBar}));
};
render() {
- const {classes} = this.props; // The classes property is injected by withStyles().
-
return (
- <div className={classes.dashboard}>
+ <div className={this.props.classes.dashboard} style={styles.dashboard}>
<Header
opened={this.state.sideBar}
- openSideBar={this.openSideBar}
- closeSideBar={this.closeSideBar}
+ switchSideBar={this.switchSideBar}
/>
<Body
opened={this.state.sideBar}
@@ -196,4 +232,4 @@ class Dashboard extends Component<Props, State> {
}
}
-export default withStyles(styles)(Dashboard);
+export default withStyles(themeStyles)(Dashboard);
diff --git a/dashboard/assets/components/Footer.jsx b/dashboard/assets/components/Footer.jsx
new file mode 100644
index 000000000..54b67c464
--- /dev/null
+++ b/dashboard/assets/components/Footer.jsx
@@ -0,0 +1,173 @@
+// @flow
+
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+import React, {Component} from 'react';
+
+import withStyles from 'material-ui/styles/withStyles';
+import Typography from 'material-ui/Typography';
+import Grid from 'material-ui/Grid';
+import {ResponsiveContainer, AreaChart, Area, Tooltip} from 'recharts';
+
+import ChartRow from './ChartRow';
+import CustomTooltip, {bytePlotter, bytePerSecPlotter, percentPlotter, multiplier} from './CustomTooltip';
+import {styles as commonStyles} from '../common';
+import type {Content} from '../types/content';
+
+// styles contains the constant styles of the component.
+const styles = {
+ footer: {
+ maxWidth: '100%',
+ flexWrap: 'nowrap',
+ margin: 0,
+ },
+ chartRowWrapper: {
+ height: '100%',
+ padding: 0,
+ },
+ doubleChartWrapper: {
+ height: '100%',
+ width: '99%',
+ paddingTop: 5,
+ },
+};
+
+// themeStyles returns the styles generated from the theme for the component.
+const themeStyles: Object = (theme: Object) => ({
+ footer: {
+ backgroundColor: theme.palette.background.appBar,
+ color: theme.palette.getContrastText(theme.palette.background.appBar),
+ zIndex: theme.zIndex.appBar,
+ height: theme.spacing.unit * 10,
+ },
+});
+
+export type Props = {
+ classes: Object, // injected by withStyles()
+ theme: Object,
+ content: Content,
+ shouldUpdate: Object,
+};
+
+// Footer renders the footer of the dashboard.
+class Footer extends Component<Props> {
+ shouldComponentUpdate(nextProps) {
+ return typeof nextProps.shouldUpdate.home !== 'undefined';
+ }
+
+ // info renders a label with the given values.
+ info = (about: string, value: ?string) => (value ? (
+ <Typography type='caption' color='inherit'>
+ <span style={commonStyles.light}>{about}</span> {value}
+ </Typography>
+ ) : null);
+
+ // doubleChart renders a pair of charts separated by the baseline.
+ doubleChart = (syncId, topChart, bottomChart) => {
+ const topKey = 'topKey';
+ const bottomKey = 'bottomKey';
+ const topDefault = topChart.default ? topChart.default : 0;
+ const bottomDefault = bottomChart.default ? bottomChart.default : 0;
+ const topTooltip = topChart.tooltip ? (
+ <Tooltip cursor={false} content={<CustomTooltip tooltip={topChart.tooltip} />} />
+ ) : null;
+ const bottomTooltip = bottomChart.tooltip ? (
+ <Tooltip cursor={false} content={<CustomTooltip tooltip={bottomChart.tooltip} />} />
+ ) : null;
+ const topColor = '#8884d8';
+ const bottomColor = '#82ca9d';
+
+ // Put the samples of the two charts into the same array in order to avoid problems
+ // at the synchronized area charts. If one of the two arrays doesn't have value at
+ // a given position, give it a 0 default value.
+ let data = [...topChart.data.map(({value}) => {
+ const d = {};
+ d[topKey] = value || topDefault;
+ return d;
+ })];
+ for (let i = 0; i < data.length && i < bottomChart.data.length; i++) {
+ // The value needs to be negative in order to plot it upside down.
+ const d = bottomChart.data[i];
+ data[i][bottomKey] = d && d.value ? -d.value : bottomDefault;
+ }
+ data = [...data, ...bottomChart.data.slice(data.length).map(({value}) => {
+ const d = {};
+ d[topKey] = topDefault;
+ d[bottomKey] = -value || bottomDefault;
+ return d;
+ })];
+
+ return (
+ <div style={styles.doubleChartWrapper}>
+ <ResponsiveContainer width='100%' height='50%'>
+ <AreaChart data={data} syncId={syncId} >
+ {topTooltip}
+ <Area type='monotone' dataKey={topKey} stroke={topColor} fill={topColor} />
+ </AreaChart>
+ </ResponsiveContainer>
+ <div style={{marginTop: -10, width: '100%', height: '50%'}}>
+ <ResponsiveContainer width='100%' height='100%'>
+ <AreaChart data={data} syncId={syncId} >
+ {bottomTooltip}
+ <Area type='monotone' dataKey={bottomKey} stroke={bottomColor} fill={bottomColor} />
+ </AreaChart>
+ </ResponsiveContainer>
+ </div>
+ </div>
+ );
+ }
+
+ render() {
+ const {content} = this.props;
+ const {general, home} = content;
+
+ return (
+ <Grid container className={this.props.classes.footer} direction='row' alignItems='center' style={styles.footer}>
+ <Grid item xs style={styles.chartRowWrapper}>
+ <ChartRow>
+ {this.doubleChart(
+ 'all',
+ {data: home.processCPU, tooltip: percentPlotter('Process')},
+ {data: home.systemCPU, tooltip: percentPlotter('System', multiplier(-1))},
+ )}
+ {this.doubleChart(
+ 'all',
+ {data: home.activeMemory, tooltip: bytePlotter('Active')},
+ {data: home.virtualMemory, tooltip: bytePlotter('Virtual', multiplier(-1))},
+ )}
+ {this.doubleChart(
+ 'all',
+ {data: home.diskRead, tooltip: bytePerSecPlotter('Disk Read')},
+ {data: home.diskWrite, tooltip: bytePerSecPlotter('Disk Write', multiplier(-1))},
+ )}
+ {this.doubleChart(
+ 'all',
+ {data: home.networkIngress, tooltip: bytePerSecPlotter('Download')},
+ {data: home.networkEgress, tooltip: bytePerSecPlotter('Upload', multiplier(-1))},
+ )}
+ </ChartRow>
+ </Grid>
+ <Grid item >
+ {this.info('Geth', general.version)}
+ {this.info('Commit', general.commit ? general.commit.substring(0, 7) : null)}
+ </Grid>
+ </Grid>
+ );
+ }
+}
+
+export default withStyles(themeStyles)(Footer);
diff --git a/dashboard/assets/components/Header.jsx b/dashboard/assets/components/Header.jsx
index e29507bef..e91885af3 100644
--- a/dashboard/assets/components/Header.jsx
+++ b/dashboard/assets/components/Header.jsx
@@ -26,18 +26,22 @@ import IconButton from 'material-ui/IconButton';
import Typography from 'material-ui/Typography';
import ChevronLeftIcon from 'material-ui-icons/ChevronLeft';
-import {DURATION} from './Common';
+import {DURATION} from '../common';
-// arrowDefault is the default style of the arrow button.
-const arrowDefault = {
- transition: `transform ${DURATION}ms`,
-};
-// arrowTransition is the additional style of the arrow button corresponding to the transition's state.
-const arrowTransition = {
- entered: {transform: 'rotate(180deg)'},
+// styles contains the constant styles of the component.
+const styles = {
+ arrow: {
+ default: {
+ transition: `transform ${DURATION}ms`,
+ },
+ transition: {
+ entered: {transform: 'rotate(180deg)'},
+ },
+ },
};
-// Styles for the Header component.
-const styles = theme => ({
+
+// themeStyles returns the styles generated from the theme for the component.
+const themeStyles = (theme: Object) => ({
header: {
backgroundColor: theme.palette.background.appBar,
color: theme.palette.getContrastText(theme.palette.background.appBar),
@@ -47,53 +51,45 @@ const styles = theme => ({
paddingLeft: theme.spacing.unit,
paddingRight: theme.spacing.unit,
},
- mainText: {
+ title: {
paddingLeft: theme.spacing.unit,
},
});
+
export type Props = {
- classes: Object,
+ classes: Object, // injected by withStyles()
opened: boolean,
- openSideBar: () => {},
- closeSideBar: () => {},
+ switchSideBar: () => void,
};
+
// Header renders the header of the dashboard.
class Header extends Component<Props> {
shouldComponentUpdate(nextProps) {
return nextProps.opened !== this.props.opened;
}
- // changeSideBar opens or closes the sidebar corresponding to the previous state.
- changeSideBar = () => {
- if (this.props.opened) {
- this.props.closeSideBar();
- } else {
- this.props.openSideBar();
- }
- };
-
- // arrowButton is connected to the sidebar; changes its state.
- arrowButton = (transitionState: string) => (
- <IconButton onClick={this.changeSideBar}>
+ // arrow renders a button, which changes the sidebar's state.
+ arrow = (transitionState: string) => (
+ <IconButton onClick={this.props.switchSideBar}>
<ChevronLeftIcon
style={{
- ...arrowDefault,
- ...arrowTransition[transitionState],
+ ...styles.arrow.default,
+ ...styles.arrow.transition[transitionState],
}}
/>
</IconButton>
);
render() {
- const {classes, opened} = this.props; // The classes property is injected by withStyles().
+ const {classes, opened} = this.props;
return (
- <AppBar position="static" className={classes.header}>
+ <AppBar position='static' className={classes.header}>
<Toolbar className={classes.toolbar}>
<Transition mountOnEnter in={opened} timeout={{enter: DURATION}}>
- {this.arrowButton}
+ {this.arrow}
</Transition>
- <Typography type="title" color="inherit" noWrap className={classes.mainText}>
+ <Typography type='title' color='inherit' noWrap className={classes.title}>
Go Ethereum Dashboard
</Typography>
</Toolbar>
@@ -102,4 +98,4 @@ class Header extends Component<Props> {
}
}
-export default withStyles(styles)(Header);
+export default withStyles(themeStyles)(Header);
diff --git a/dashboard/assets/components/Home.jsx b/dashboard/assets/components/Home.jsx
deleted file mode 100644
index d3e1004f9..000000000
--- a/dashboard/assets/components/Home.jsx
+++ /dev/null
@@ -1,72 +0,0 @@
-// @flow
-
-// Copyright 2017 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-import React, {Component} from 'react';
-
-import withTheme from 'material-ui/styles/withTheme';
-import {LineChart, AreaChart, Area, YAxis, CartesianGrid, Line} from 'recharts';
-
-import ChartGrid from './ChartGrid';
-import type {ChartEntry} from '../types/message';
-
-export type Props = {
- theme: Object,
- memory: Array<ChartEntry>,
- traffic: Array<ChartEntry>,
- shouldUpdate: Object,
-};
-// Home renders the home content.
-class Home extends Component<Props> {
- constructor(props: Props) {
- super(props);
- const {theme} = props; // The theme property is injected by withTheme().
- this.memoryColor = theme.palette.primary[300];
- this.trafficColor = theme.palette.secondary[300];
- }
-
- shouldComponentUpdate(nextProps) {
- return nextProps.shouldUpdate.has('memory') || nextProps.shouldUpdate.has('traffic');
- }
-
- render() {
- const {memory, traffic} = this.props;
-
- return (
- <ChartGrid spacing={24}>
- <AreaChart xs={6} height={300} values={memory}>
- <YAxis />
- <Area type="monotone" dataKey="value" stroke={this.memoryColor} fill={this.memoryColor} />
- </AreaChart>
- <LineChart xs={6} height={300} values={traffic}>
- <Line type="monotone" dataKey="value" stroke={this.trafficColor} dot={false} />
- </LineChart>
- <LineChart xs={6} height={300} values={memory}>
- <YAxis />
- <CartesianGrid stroke="#eee" strokeDasharray="5 5" />
- <Line type="monotone" dataKey="value" stroke={this.memoryColor} dot={false} />
- </LineChart>
- <AreaChart xs={6} height={300} values={traffic}>
- <CartesianGrid stroke="#eee" strokeDasharray="5 5" vertical={false} />
- <Area type="monotone" dataKey="value" stroke={this.trafficColor} fill={this.trafficColor} />
- </AreaChart>
- </ChartGrid>
- );
- }
-}
-
-export default withTheme()(Home);
diff --git a/dashboard/assets/components/Main.jsx b/dashboard/assets/components/Main.jsx
index 6f1668a29..a9e3d3578 100644
--- a/dashboard/assets/components/Main.jsx
+++ b/dashboard/assets/components/Main.jsx
@@ -20,25 +20,38 @@ import React, {Component} from 'react';
import withStyles from 'material-ui/styles/withStyles';
-import Home from './Home';
-import {MENU} from './Common';
+import {MENU} from '../common';
+import Footer from './Footer';
import type {Content} from '../types/content';
-// Styles for the Content component.
-const styles = theme => ({
+// styles contains the constant styles of the component.
+const styles = {
+ wrapper: {
+ display: 'flex',
+ flexDirection: 'column',
+ width: '100%',
+ },
+ content: {
+ flex: 1,
+ overflow: 'auto',
+ },
+};
+
+// themeStyles returns the styles generated from the theme for the component.
+const themeStyles = theme => ({
content: {
- flexGrow: 1,
backgroundColor: theme.palette.background.default,
padding: theme.spacing.unit * 3,
- overflow: 'auto',
},
});
+
export type Props = {
classes: Object,
active: string,
content: Content,
shouldUpdate: Object,
};
+
// Main renders the chosen content.
class Main extends Component<Props> {
render() {
@@ -49,8 +62,6 @@ class Main extends Component<Props> {
let children = null;
switch (active) {
case MENU.get('home').id:
- children = <Home memory={content.home.memory} traffic={content.home.traffic} shouldUpdate={shouldUpdate} />;
- break;
case MENU.get('chain').id:
case MENU.get('txpool').id:
case MENU.get('network').id:
@@ -61,8 +72,16 @@ class Main extends Component<Props> {
children = <div>{content.logs.log.map((log, index) => <div key={index}>{log}</div>)}</div>;
}
- return <div className={classes.content}>{children}</div>;
+ return (
+ <div style={styles.wrapper}>
+ <div className={classes.content} style={styles.content}>{children}</div>
+ <Footer
+ content={content}
+ shouldUpdate={shouldUpdate}
+ />
+ </div>
+ );
}
}
-export default withStyles(styles)(Main);
+export default withStyles(themeStyles)(Main);
diff --git a/dashboard/assets/components/SideBar.jsx b/dashboard/assets/components/SideBar.jsx
index 319e6f305..c2e419ae9 100644
--- a/dashboard/assets/components/SideBar.jsx
+++ b/dashboard/assets/components/SideBar.jsx
@@ -24,18 +24,22 @@ import Icon from 'material-ui/Icon';
import Transition from 'react-transition-group/Transition';
import {Icon as FontAwesome} from 'react-fa';
-import {MENU, DURATION} from './Common';
+import {MENU, DURATION} from '../common';
-// menuDefault is the default style of the menu.
-const menuDefault = {
- transition: `margin-left ${DURATION}ms`,
-};
-// menuTransition is the additional style of the menu corresponding to the transition's state.
-const menuTransition = {
- entered: {marginLeft: -200},
+// styles contains the constant styles of the component.
+const styles = {
+ menu: {
+ default: {
+ transition: `margin-left ${DURATION}ms`,
+ },
+ transition: {
+ entered: {marginLeft: -200},
+ },
+ },
};
-// Styles for the SideBar component.
-const styles = theme => ({
+
+// themeStyles returns the styles generated from the theme for the component.
+const themeStyles = theme => ({
list: {
background: theme.palette.background.appBar,
},
@@ -46,38 +50,32 @@ const styles = theme => ({
fontSize: theme.spacing.unit * 3,
},
});
+
export type Props = {
- classes: Object,
+ classes: Object, // injected by withStyles()
opened: boolean,
- changeContent: () => {},
+ changeContent: string => void,
};
+
// SideBar renders the sidebar of the dashboard.
class SideBar extends Component<Props> {
- constructor(props) {
- super(props);
-
- // clickOn contains onClick event functions for the menu items.
- // Instantiate only once, and reuse the existing functions to prevent the creation of
- // new function instances every time the render method is triggered.
- this.clickOn = {};
- MENU.forEach((menu) => {
- this.clickOn[menu.id] = (event) => {
- event.preventDefault();
- props.changeContent(menu.id);
- };
- });
- }
-
shouldComponentUpdate(nextProps) {
return nextProps.opened !== this.props.opened;
}
+ // clickOn returns a click event handler function for the given menu item.
+ clickOn = menu => (event) => {
+ event.preventDefault();
+ this.props.changeContent(menu);
+ };
+
+ // menuItems returns the menu items corresponding to the sidebar state.
menuItems = (transitionState) => {
const {classes} = this.props;
const children = [];
MENU.forEach((menu) => {
- children.push(
- <ListItem button key={menu.id} onClick={this.clickOn[menu.id]} className={classes.listItem}>
+ children.push((
+ <ListItem button key={menu.id} onClick={this.clickOn(menu.id)} className={classes.listItem}>
<ListItemIcon>
<Icon className={classes.icon}>
<FontAwesome name={menu.icon} />
@@ -86,29 +84,25 @@ class SideBar extends Component<Props> {
<ListItemText
primary={menu.title}
style={{
- ...menuDefault,
- ...menuTransition[transitionState],
+ ...styles.menu.default,
+ ...styles.menu.transition[transitionState],
padding: 0,
}}
/>
- </ListItem>,
- );
+ </ListItem>
+ ));
});
return children;
};
// menu renders the list of the menu items.
- menu = (transitionState) => {
- const {classes} = this.props; // The classes property is injected by withStyles().
-
- return (
- <div className={classes.list}>
- <List>
- {this.menuItems(transitionState)}
- </List>
- </div>
- );
- };
+ menu = (transitionState: Object) => (
+ <div className={this.props.classes.list}>
+ <List>
+ {this.menuItems(transitionState)}
+ </List>
+ </div>
+ );
render() {
return (
@@ -119,4 +113,4 @@ class SideBar extends Component<Props> {
}
}
-export default withStyles(styles)(SideBar);
+export default withStyles(themeStyles)(SideBar);
diff --git a/dashboard/assets/public/dashboard.html b/dashboard/assets/dashboard.html
index 2491bf1ea..2491bf1ea 100644
--- a/dashboard/assets/public/dashboard.html
+++ b/dashboard/assets/dashboard.html
diff --git a/dashboard/assets/index.jsx b/dashboard/assets/index.jsx
index e10095baf..4ee567b01 100644
--- a/dashboard/assets/index.jsx
+++ b/dashboard/assets/index.jsx
@@ -24,18 +24,18 @@ import createMuiTheme from 'material-ui/styles/createMuiTheme';
import Dashboard from './components/Dashboard';
-const theme = createMuiTheme({
- palette: {
- type: 'dark',
- },
+const theme: Object = createMuiTheme({
+ palette: {
+ type: 'dark',
+ },
});
const dashboard = document.getElementById('dashboard');
if (dashboard) {
- // Renders the whole dashboard.
- render(
- <MuiThemeProvider theme={theme}>
- <Dashboard />
- </MuiThemeProvider>,
- dashboard,
- );
+ // Renders the whole dashboard.
+ render(
+ <MuiThemeProvider theme={theme}>
+ <Dashboard />
+ </MuiThemeProvider>,
+ dashboard,
+ );
}
diff --git a/dashboard/assets/package-lock.json b/dashboard/assets/package-lock.json
index 38a7cea24..a70fda6d5 100644
--- a/dashboard/assets/package-lock.json
+++ b/dashboard/assets/package-lock.json
@@ -3,9 +3,9 @@
"lockfileVersion": 1,
"dependencies": {
"@babel/code-frame": {
- "version": "7.0.0-beta.31",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.31.tgz",
- "integrity": "sha512-yd7CkUughvHQoEahQqcMdrZw6o/6PwUxiRkfZuVDVHCDe77mysD/suoNyk5mK6phTnRW1kyIbPHyCJgxw++LXg==",
+ "version": "7.0.0-beta.36",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.36.tgz",
+ "integrity": "sha512-sW77BFwJ48YvQp3Gzz5xtAUiXuYOL2aMJKDwiaY3OcvdqBFurtYfOpSa4QrNyDxmOGRFSYzUpabU2m9QrlWE7w==",
"requires": {
"chalk": "2.3.0",
"esutils": "2.0.2",
@@ -41,61 +41,60 @@
}
},
"@babel/helper-function-name": {
- "version": "7.0.0-beta.31",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.31.tgz",
- "integrity": "sha512-c+DAyp8LMm2nzSs2uXEuxp4LYGSUYEyHtU3fU57avFChjsnTmmpWmXj2dv0yUxHTEydgVAv5fIzA+4KJwoqWDA==",
+ "version": "7.0.0-beta.36",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.36.tgz",
+ "integrity": "sha512-/SGPOyifPf20iTrMN+WdlY2MbKa7/o4j7B/4IAsdOusASp2icT+Wcdjf4tjJHaXNX8Pe9bpgVxLNxhRvcf8E5w==",
"requires": {
- "@babel/helper-get-function-arity": "7.0.0-beta.31",
- "@babel/template": "7.0.0-beta.31",
- "@babel/traverse": "7.0.0-beta.31",
- "@babel/types": "7.0.0-beta.31"
+ "@babel/helper-get-function-arity": "7.0.0-beta.36",
+ "@babel/template": "7.0.0-beta.36",
+ "@babel/types": "7.0.0-beta.36"
}
},
"@babel/helper-get-function-arity": {
- "version": "7.0.0-beta.31",
- "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.31.tgz",
- "integrity": "sha512-m7rVVX/dMLbbB9NCzKYRrrFb0qZxgpmQ4Wv6y7zEsB6skoJHRuXVeb/hAFze79vXBbuD63ci7AVHXzAdZSk9KQ==",
+ "version": "7.0.0-beta.36",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.36.tgz",
+ "integrity": "sha512-vPPcx2vsSoDbcyWr9S3nd0FM3B4hEXnt0p1oKpwa08GwK0fSRxa98MyaRGf8suk8frdQlG1P3mDrz5p/Rr3pbA==",
"requires": {
- "@babel/types": "7.0.0-beta.31"
+ "@babel/types": "7.0.0-beta.36"
}
},
"@babel/template": {
- "version": "7.0.0-beta.31",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.31.tgz",
- "integrity": "sha512-97IRmLvoDhIDSQkqklVt3UCxJsv0LUEVb/0DzXWtc8Lgiyxj567qZkmTG9aR21CmcJVVIvq2Y/moZj4oEpl5AA==",
+ "version": "7.0.0-beta.36",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.36.tgz",
+ "integrity": "sha512-mUBi90WRyZ9iVvlWLEdeo8gn/tROyJdjKNC4W5xJTSZL+9MS89rTJSqiaJKXIkxk/YRDL/g/8snrG/O0xl33uA==",
"requires": {
- "@babel/code-frame": "7.0.0-beta.31",
- "@babel/types": "7.0.0-beta.31",
- "babylon": "7.0.0-beta.31",
+ "@babel/code-frame": "7.0.0-beta.36",
+ "@babel/types": "7.0.0-beta.36",
+ "babylon": "7.0.0-beta.36",
"lodash": "4.17.4"
},
"dependencies": {
"babylon": {
- "version": "7.0.0-beta.31",
- "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.31.tgz",
- "integrity": "sha512-6lm2mV3S51yEnKmQQNnswoABL1U1H1KHoCCVwdwI3hvIv+W7ya4ki7Aw4o4KxtUHjNKkK5WpZb22rrMMOcJXJQ=="
+ "version": "7.0.0-beta.36",
+ "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.36.tgz",
+ "integrity": "sha512-rw4YdadGwajAMMRl6a5swhQ0JCOOFyaYCfJ0AsmNBD8uBD/r4J8mux7wBaqavvFKqUKQYWOzA1Speams4YDzsQ=="
}
}
},
"@babel/traverse": {
- "version": "7.0.0-beta.31",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.31.tgz",
- "integrity": "sha512-3N+VJW+KlezEjFBG7WSYeMyC5kIqVLPb/PGSzCDPFcJrnArluD1GIl7Y3xC7cjKiTq2/JohaLWHVPjJWHlo9Gg==",
- "requires": {
- "@babel/code-frame": "7.0.0-beta.31",
- "@babel/helper-function-name": "7.0.0-beta.31",
- "@babel/types": "7.0.0-beta.31",
- "babylon": "7.0.0-beta.31",
+ "version": "7.0.0-beta.36",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.36.tgz",
+ "integrity": "sha512-OTUb6iSKVR/98dGThRJ1BiyfwbuX10BVnkz89IpaerjTPRhDfMBfLsqmzxz5MiywUOW4M0Clta0o7rSxkfcuzw==",
+ "requires": {
+ "@babel/code-frame": "7.0.0-beta.36",
+ "@babel/helper-function-name": "7.0.0-beta.36",
+ "@babel/types": "7.0.0-beta.36",
+ "babylon": "7.0.0-beta.36",
"debug": "3.1.0",
- "globals": "10.4.0",
+ "globals": "11.1.0",
"invariant": "2.2.2",
"lodash": "4.17.4"
},
"dependencies": {
"babylon": {
- "version": "7.0.0-beta.31",
- "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.31.tgz",
- "integrity": "sha512-6lm2mV3S51yEnKmQQNnswoABL1U1H1KHoCCVwdwI3hvIv+W7ya4ki7Aw4o4KxtUHjNKkK5WpZb22rrMMOcJXJQ=="
+ "version": "7.0.0-beta.36",
+ "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.36.tgz",
+ "integrity": "sha512-rw4YdadGwajAMMRl6a5swhQ0JCOOFyaYCfJ0AsmNBD8uBD/r4J8mux7wBaqavvFKqUKQYWOzA1Speams4YDzsQ=="
},
"debug": {
"version": "3.1.0",
@@ -106,16 +105,16 @@
}
},
"globals": {
- "version": "10.4.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-10.4.0.tgz",
- "integrity": "sha512-uNUtxIZpGyuaq+5BqGGQHsL4wUlJAXRqOm6g3Y48/CWNGTLONgBibI0lh6lGxjR2HljFYUfszb+mk4WkgMntsA=="
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.1.0.tgz",
+ "integrity": "sha512-uEuWt9mqTlPDwSqi+sHjD4nWU/1N+q0fiWI9T1mZpD2UENqX20CFD5T/ziLZvztPaBKl7ZylUi1q6Qfm7E2CiQ=="
}
}
},
"@babel/types": {
- "version": "7.0.0-beta.31",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.31.tgz",
- "integrity": "sha512-exAHB+NeFGxkfQ5dSUD03xl3zYGneeSk2Mw2ldTt/nTvYxuDiuSp3DlxgUBgzbdTFG4fbwPk0WtKWOoTXCmNGg==",
+ "version": "7.0.0-beta.36",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.36.tgz",
+ "integrity": "sha512-PyAORDO9um9tfnrddXgmWN9e6Sq9qxraQIt5ynqBOSXKA5qvK1kUr+Q3nSzKFdzorsiK+oqcUnAFvEoKxv9D+Q==",
"requires": {
"esutils": "2.0.2",
"lodash": "4.17.4",
@@ -129,10 +128,28 @@
}
}
},
+ "@types/jss": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/@types/jss/-/jss-9.3.0.tgz",
+ "integrity": "sha512-n7MUYCO/Wt4d6Yj0ZewXSSkqBcrdLFgpQ4mUBRXBWDmLfXtgT3tJ26GVPr8HiyRLLze6iQfaBJTlvjRTjgZpRg=="
+ },
+ "@types/react": {
+ "version": "16.0.34",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-16.0.34.tgz",
+ "integrity": "sha512-Ee66fX2qMsDnDq7sPnDtq1bGoo479j6Fo1BlSnne+L5rp6ndzBUgz72+MRNuN56zg9uuteRCkJAMdDJEX2Uqig=="
+ },
+ "@types/react-transition-group": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-2.0.6.tgz",
+ "integrity": "sha512-mVhRv+d0MIoLWl6hEFA7Nnd/obW2RQpZViTAKhM37mltuTDWCdoj8xAZv94ntB8wgAc6DDiDCXxFXPgClGnsfQ==",
+ "requires": {
+ "@types/react": "16.0.34"
+ }
+ },
"acorn": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz",
- "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w=="
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz",
+ "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug=="
},
"acorn-dynamic-import": {
"version": "2.0.2",
@@ -342,7 +359,7 @@
"integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=",
"requires": {
"browserslist": "1.7.7",
- "caniuse-db": "1.0.30000784",
+ "caniuse-db": "1.0.30000793",
"normalize-range": "0.1.2",
"num2fraction": "1.2.2",
"postcss": "5.2.18",
@@ -354,8 +371,8 @@
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz",
"integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=",
"requires": {
- "caniuse-db": "1.0.30000784",
- "electron-to-chromium": "1.3.30"
+ "caniuse-db": "1.0.30000793",
+ "electron-to-chromium": "1.3.31"
}
}
}
@@ -415,20 +432,22 @@
}
},
"babel-eslint": {
- "version": "8.0.3",
- "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.0.3.tgz",
- "integrity": "sha512-7D4iUpylEiKJPGbeSAlNddGcmA41PadgZ6UAb6JVyh003h3d0EbZusYFBR/+nBgqtaVJM2J2zUVa3N0hrpMH6g==",
- "requires": {
- "@babel/code-frame": "7.0.0-beta.31",
- "@babel/traverse": "7.0.0-beta.31",
- "@babel/types": "7.0.0-beta.31",
- "babylon": "7.0.0-beta.31"
+ "version": "8.2.1",
+ "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.1.tgz",
+ "integrity": "sha512-RzdVOyWKQRUnLXhwLk+eKb4oyW+BykZSkpYwFhM4tnfzAG5OWfvG0w/uyzMp5XKEU0jN82+JefHr39bG2+KhRQ==",
+ "requires": {
+ "@babel/code-frame": "7.0.0-beta.36",
+ "@babel/traverse": "7.0.0-beta.36",
+ "@babel/types": "7.0.0-beta.36",
+ "babylon": "7.0.0-beta.36",
+ "eslint-scope": "3.7.1",
+ "eslint-visitor-keys": "1.0.0"
},
"dependencies": {
"babylon": {
- "version": "7.0.0-beta.31",
- "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.31.tgz",
- "integrity": "sha512-6lm2mV3S51yEnKmQQNnswoABL1U1H1KHoCCVwdwI3hvIv+W7ya4ki7Aw4o4KxtUHjNKkK5WpZb22rrMMOcJXJQ=="
+ "version": "7.0.0-beta.36",
+ "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.36.tgz",
+ "integrity": "sha512-rw4YdadGwajAMMRl6a5swhQ0JCOOFyaYCfJ0AsmNBD8uBD/r4J8mux7wBaqavvFKqUKQYWOzA1Speams4YDzsQ=="
}
}
},
@@ -1139,9 +1158,9 @@
"babel-plugin-transform-es2015-unicode-regex": "6.24.1",
"babel-plugin-transform-exponentiation-operator": "6.24.1",
"babel-plugin-transform-regenerator": "6.26.0",
- "browserslist": "2.10.0",
+ "browserslist": "2.11.3",
"invariant": "2.2.2",
- "semver": "5.4.1"
+ "semver": "5.5.0"
}
},
"babel-preset-flow": {
@@ -1394,7 +1413,7 @@
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
"requires": {
"bn.js": "4.11.8",
- "randombytes": "2.0.5"
+ "randombytes": "2.0.6"
}
},
"browserify-sign": {
@@ -1420,12 +1439,12 @@
}
},
"browserslist": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.10.0.tgz",
- "integrity": "sha512-WyvzSLsuAVPOjbljXnyeWl14Ae+ukAT8MUuagKVzIDvwBxl4UAwD1xqtyQs2eWYPGUKMeC3Ol62goqYuKqTTcw==",
+ "version": "2.11.3",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz",
+ "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==",
"requires": {
- "caniuse-lite": "1.0.30000784",
- "electron-to-chromium": "1.3.30"
+ "caniuse-lite": "1.0.30000792",
+ "electron-to-chromium": "1.3.31"
}
},
"buffer": {
@@ -1482,7 +1501,7 @@
"integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=",
"requires": {
"browserslist": "1.7.7",
- "caniuse-db": "1.0.30000784",
+ "caniuse-db": "1.0.30000793",
"lodash.memoize": "4.1.2",
"lodash.uniq": "4.5.0"
},
@@ -1492,21 +1511,21 @@
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz",
"integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=",
"requires": {
- "caniuse-db": "1.0.30000784",
- "electron-to-chromium": "1.3.30"
+ "caniuse-db": "1.0.30000793",
+ "electron-to-chromium": "1.3.31"
}
}
}
},
"caniuse-db": {
- "version": "1.0.30000784",
- "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000784.tgz",
- "integrity": "sha1-G+lQEtlInHcZB0+BruV9vf/mNhs="
+ "version": "1.0.30000793",
+ "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000793.tgz",
+ "integrity": "sha1-PADGbkI6ehkHx92Wdpp4sq+opy4="
},
"caniuse-lite": {
- "version": "1.0.30000784",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000784.tgz",
- "integrity": "sha1-EpztdOmhKApEGIC2zSvOMO9Z5sA="
+ "version": "1.0.30000792",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000792.tgz",
+ "integrity": "sha1-0M6pgfgRjzlhRxr7tDyaHlu/AzI="
},
"caseless": {
"version": "0.12.0",
@@ -1574,6 +1593,7 @@
"requires": {
"anymatch": "1.3.2",
"async-each": "1.0.1",
+ "fsevents": "1.1.3",
"glob-parent": "2.0.0",
"inherits": "2.0.3",
"is-binary-path": "1.0.1",
@@ -1799,7 +1819,7 @@
"cipher-base": "1.0.4",
"inherits": "2.0.3",
"ripemd160": "2.0.1",
- "sha.js": "2.4.9"
+ "sha.js": "2.4.10"
}
},
"create-hmac": {
@@ -1812,7 +1832,7 @@
"inherits": "2.0.3",
"ripemd160": "2.0.1",
"safe-buffer": "5.1.1",
- "sha.js": "2.4.9"
+ "sha.js": "2.4.10"
}
},
"cross-spawn": {
@@ -1862,7 +1882,7 @@
"inherits": "2.0.3",
"pbkdf2": "3.0.14",
"public-encrypt": "4.0.0",
- "randombytes": "2.0.5",
+ "randombytes": "2.0.6",
"randomfill": "1.0.3"
}
},
@@ -1872,9 +1892,9 @@
"integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA="
},
"css-loader": {
- "version": "0.28.7",
- "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.7.tgz",
- "integrity": "sha512-GxMpax8a/VgcfRrVy0gXD6yLd5ePYbXX/5zGgTVYp4wXtJklS8Z2VaUArJgc//f6/Dzil7BaJObdSv8eKKCPgg==",
+ "version": "0.28.9",
+ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.9.tgz",
+ "integrity": "sha512-r3dgelMm/mkPz5Y7m9SeiGE46i2VsEU/OYbez+1llfxtv8b2y5/b5StaeEvPK3S5tlNQI+tDW/xDIhKJoZgDtw==",
"requires": {
"babel-code-frame": "6.26.0",
"css-selector-tokenizer": "0.7.0",
@@ -1884,7 +1904,7 @@
"lodash.camelcase": "4.3.0",
"object-assign": "4.1.1",
"postcss": "5.2.18",
- "postcss-modules-extract-imports": "1.1.0",
+ "postcss-modules-extract-imports": "1.2.0",
"postcss-modules-local-by-default": "1.2.0",
"postcss-modules-scope": "1.1.0",
"postcss-modules-values": "1.3.0",
@@ -1980,7 +2000,7 @@
"resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
"integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
"requires": {
- "es5-ext": "0.10.37"
+ "es5-ext": "0.10.38"
}
},
"d3-array": {
@@ -1999,9 +2019,9 @@
"integrity": "sha1-vHZD/KjlOoNH4vva/6I2eWtYUJs="
},
"d3-format": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.2.1.tgz",
- "integrity": "sha512-U4zRVLDXW61bmqoo+OJ/V687e1T5nVd3TAKAJKgtpZ/P1JsMgyod0y9br+mlQOryTAACdiXI3wCjuERHFNp91w=="
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.2.2.tgz",
+ "integrity": "sha512-zH9CfF/3C8zUI47nsiKfD0+AGDEuM8LwBIP7pBVpyR4l/sKkZqITmMtxRp04rwBrlshIZ17XeFAaovN3++wzkw=="
},
"d3-interpolate": {
"version": "1.1.6",
@@ -2024,7 +2044,7 @@
"d3-array": "1.2.1",
"d3-collection": "1.0.4",
"d3-color": "1.0.3",
- "d3-format": "1.2.1",
+ "d3-format": "1.2.2",
"d3-interpolate": "1.1.6",
"d3-time": "1.0.8",
"d3-time-format": "2.1.1"
@@ -2164,13 +2184,13 @@
"requires": {
"bn.js": "4.11.8",
"miller-rabin": "4.0.1",
- "randombytes": "2.0.5"
+ "randombytes": "2.0.6"
}
},
"doctrine": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.2.tgz",
- "integrity": "sha512-y0tm5Pq6ywp3qSTZ1vPgVdAnbDEoeoc5wlOHXoY1c4Wug/a7JvqHIl7BTvwodaHmejWkK/9dSb3sCYfyo/om8A==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
"requires": {
"esutils": "2.0.2"
}
@@ -2204,18 +2224,10 @@
"jsbn": "0.1.1"
}
},
- "electron-releases": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/electron-releases/-/electron-releases-2.1.0.tgz",
- "integrity": "sha512-cyKFD1bTE/UgULXfaueIN1k5EPFzs+FRc/rvCY5tIynefAPqopQEgjr0EzY+U3Dqrk/G4m9tXSPuZ77v6dL/Rw=="
- },
"electron-to-chromium": {
- "version": "1.3.30",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.30.tgz",
- "integrity": "sha512-zx1Prv7kYLfc4OA60FhxGbSo4qrEjgSzpo1/37i7l9ltXPYOoQBtjQxY9KmsgfHnBxHlBGXwLlsbt/gub1w5lw==",
- "requires": {
- "electron-releases": "2.1.0"
- }
+ "version": "1.3.31",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.31.tgz",
+ "integrity": "sha512-XE4CLbswkZgZFn34cKFy1xaX+F5LHxeDLjY1+rsK9asDzknhbrd9g/n/01/acbU25KTsUSiLKwvlLyA+6XLUOA=="
},
"elliptic": {
"version": "6.4.0",
@@ -2299,9 +2311,9 @@
}
},
"es5-ext": {
- "version": "0.10.37",
- "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz",
- "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=",
+ "version": "0.10.38",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.38.tgz",
+ "integrity": "sha512-jCMyePo7AXbUESwbl8Qi01VSH2piY9s/a3rSU/5w/MlTIx8HPL1xn2InGN8ejt/xulcJgnTO7vqNtOAxzYd2Kg==",
"requires": {
"es6-iterator": "2.0.3",
"es6-symbol": "3.1.1"
@@ -2313,7 +2325,7 @@
"integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
"requires": {
"d": "1.0.0",
- "es5-ext": "0.10.37",
+ "es5-ext": "0.10.38",
"es6-symbol": "3.1.1"
}
},
@@ -2323,7 +2335,7 @@
"integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
"requires": {
"d": "1.0.0",
- "es5-ext": "0.10.37",
+ "es5-ext": "0.10.38",
"es6-iterator": "2.0.3",
"es6-set": "0.1.5",
"es6-symbol": "3.1.1",
@@ -2336,7 +2348,7 @@
"integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
"requires": {
"d": "1.0.0",
- "es5-ext": "0.10.37",
+ "es5-ext": "0.10.38",
"es6-iterator": "2.0.3",
"es6-symbol": "3.1.1",
"event-emitter": "0.3.5"
@@ -2348,7 +2360,7 @@
"integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
"requires": {
"d": "1.0.0",
- "es5-ext": "0.10.37"
+ "es5-ext": "0.10.38"
}
},
"es6-weak-map": {
@@ -2357,7 +2369,7 @@
"integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=",
"requires": {
"d": "1.0.0",
- "es5-ext": "0.10.37",
+ "es5-ext": "0.10.38",
"es6-iterator": "2.0.3",
"es6-symbol": "3.1.1"
}
@@ -2379,9 +2391,9 @@
}
},
"eslint": {
- "version": "4.13.1",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.13.1.tgz",
- "integrity": "sha512-UCJVV50RtLHYzBp1DZ8CMPtRSg4iVZvjgO9IJHIKyWU/AnJVjtdRikoUPLB29n5pzMB7TnsLQWf0V6VUJfoPfw==",
+ "version": "4.16.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.16.0.tgz",
+ "integrity": "sha512-YVXV4bDhNoHHcv0qzU4Meof7/P26B4EuaktMi5L1Tnt52Aov85KmYA8c5D+xyZr/BkhvwUqr011jDSD/QTULxg==",
"requires": {
"ajv": "5.5.2",
"babel-code-frame": "6.26.0",
@@ -2389,11 +2401,11 @@
"concat-stream": "1.6.0",
"cross-spawn": "5.1.0",
"debug": "3.1.0",
- "doctrine": "2.0.2",
+ "doctrine": "2.1.0",
"eslint-scope": "3.7.1",
+ "eslint-visitor-keys": "1.0.0",
"espree": "3.5.2",
"esquery": "1.0.0",
- "estraverse": "4.2.0",
"esutils": "2.0.2",
"file-entry-cache": "2.0.0",
"functional-red-black-tree": "1.0.1",
@@ -2402,7 +2414,7 @@
"ignore": "3.3.7",
"imurmurhash": "0.1.4",
"inquirer": "3.3.0",
- "is-resolvable": "1.0.1",
+ "is-resolvable": "1.1.0",
"js-yaml": "3.10.0",
"json-stable-stringify-without-jsonify": "1.0.1",
"levn": "0.3.0",
@@ -2415,7 +2427,7 @@
"pluralize": "7.0.0",
"progress": "2.0.0",
"require-uncached": "1.0.3",
- "semver": "5.4.1",
+ "semver": "5.5.0",
"strip-ansi": "4.0.0",
"strip-json-comments": "2.0.1",
"table": "4.0.2",
@@ -2507,9 +2519,9 @@
}
},
"eslint-import-resolver-node": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz",
- "integrity": "sha512-yUtXS15gIcij68NmXmP9Ni77AQuCN0itXbCc/jWd8C6/yKZaSNXicpC8cgvjnxVdmfsosIXrjpzFq7GcDryb6A==",
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz",
+ "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==",
"requires": {
"debug": "2.6.9",
"resolve": "1.5.0"
@@ -2564,9 +2576,9 @@
}
},
"eslint-plugin-flowtype": {
- "version": "2.40.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.40.1.tgz",
- "integrity": "sha512-0EBDPR3/iguDQin7nb5WMT1ZWYB95eNllY+oiFZjvLa1oqE0BGO6ZSFnMdNE9HEkajB6Cw850PRIBbp+O+EzYQ==",
+ "version": "2.41.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.41.0.tgz",
+ "integrity": "sha512-M5X6qu/zvvXQ7flXp9plyBRlNRMQGNl3c+kQmox+m/jpnCZt0txgauxcrBKAVa9LKE/hBnsItJ9BojdmkefAkA==",
"requires": {
"lodash": "4.17.4"
}
@@ -2580,7 +2592,7 @@
"contains-path": "0.1.0",
"debug": "2.6.9",
"doctrine": "1.5.0",
- "eslint-import-resolver-node": "0.3.1",
+ "eslint-import-resolver-node": "0.3.2",
"eslint-module-utils": "2.1.1",
"has": "1.0.1",
"lodash.cond": "4.5.2",
@@ -2618,7 +2630,7 @@
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.5.1.tgz",
"integrity": "sha512-YGSjB9Qu6QbVTroUZi66pYky3DfoIPLdHQ/wmrBGyBRnwxQsBXAov9j2rpXt/55i8nyMv6IRWJv2s4d4YnduzQ==",
"requires": {
- "doctrine": "2.0.2",
+ "doctrine": "2.1.0",
"has": "1.0.1",
"jsx-ast-utils": "2.0.1",
"prop-types": "15.6.0"
@@ -2638,12 +2650,17 @@
"estraverse": "4.2.0"
}
},
+ "eslint-visitor-keys": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
+ "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ=="
+ },
"espree": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz",
"integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==",
"requires": {
- "acorn": "5.2.1",
+ "acorn": "5.3.0",
"acorn-jsx": "3.0.1"
}
},
@@ -2685,7 +2702,7 @@
"integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
"requires": {
"d": "1.0.0",
- "es5-ext": "0.10.37"
+ "es5-ext": "0.10.38"
}
},
"events": {
@@ -2889,9 +2906,9 @@
"integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I="
},
"flow-bin": {
- "version": "0.61.0",
- "resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.61.0.tgz",
- "integrity": "sha512-w6SGi5CDfKLNGzYssRhW6N37qKclDXijsxDQ5M8c3WbivRYta0Horv22bwakegfKBVDnyeS0lRW3OqBC74eq2g=="
+ "version": "0.63.1",
+ "resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.63.1.tgz",
+ "integrity": "sha512-aWKHYs3UECgpwrIDVUiABjSC8dgaKmonymQDWO+6FhGcp9lnnxdDBE6Sfm3F7YaRPfLYsWAY4lndBrfrfyn+9g=="
},
"flow-bin-loader": {
"version": "1.0.2",
@@ -2916,7 +2933,7 @@
"mkdirp": "0.5.1",
"request": "2.83.0",
"rimraf": "2.6.2",
- "semver": "5.4.1",
+ "semver": "5.5.0",
"table": "4.0.2",
"through": "2.3.8",
"unzip": "0.1.11",
@@ -2977,6 +2994,795 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
+ "fsevents": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz",
+ "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==",
+ "optional": true,
+ "requires": {
+ "nan": "2.8.0",
+ "node-pre-gyp": "0.6.39"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.0",
+ "bundled": true,
+ "optional": true
+ },
+ "ajv": {
+ "version": "4.11.8",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "co": "4.6.0",
+ "json-stable-stringify": "1.0.1"
+ }
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true
+ },
+ "aproba": {
+ "version": "1.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "delegates": "1.0.0",
+ "readable-stream": "2.2.9"
+ }
+ },
+ "asn1": {
+ "version": "0.2.3",
+ "bundled": true,
+ "optional": true
+ },
+ "assert-plus": {
+ "version": "0.2.0",
+ "bundled": true,
+ "optional": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "bundled": true,
+ "optional": true
+ },
+ "aws-sign2": {
+ "version": "0.6.0",
+ "bundled": true,
+ "optional": true
+ },
+ "aws4": {
+ "version": "1.6.0",
+ "bundled": true,
+ "optional": true
+ },
+ "balanced-match": {
+ "version": "0.4.2",
+ "bundled": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "tweetnacl": "0.14.5"
+ }
+ },
+ "block-stream": {
+ "version": "0.0.9",
+ "bundled": true,
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "boom": {
+ "version": "2.10.1",
+ "bundled": true,
+ "requires": {
+ "hoek": "2.16.3"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.7",
+ "bundled": true,
+ "requires": {
+ "balanced-match": "0.4.2",
+ "concat-map": "0.0.1"
+ }
+ },
+ "buffer-shims": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "bundled": true,
+ "optional": true
+ },
+ "co": {
+ "version": "4.6.0",
+ "bundled": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "combined-stream": {
+ "version": "1.0.5",
+ "bundled": true,
+ "requires": {
+ "delayed-stream": "1.0.0"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "cryptiles": {
+ "version": "2.0.5",
+ "bundled": true,
+ "requires": {
+ "boom": "2.10.1"
+ }
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "1.0.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "debug": {
+ "version": "2.6.8",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "deep-extend": {
+ "version": "0.4.2",
+ "bundled": true,
+ "optional": true
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "detect-libc": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "ecc-jsbn": {
+ "version": "0.1.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "jsbn": "0.1.1"
+ }
+ },
+ "extend": {
+ "version": "3.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "extsprintf": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "bundled": true,
+ "optional": true
+ },
+ "form-data": {
+ "version": "2.1.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "asynckit": "0.4.0",
+ "combined-stream": "1.0.5",
+ "mime-types": "2.1.15"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "fstream": {
+ "version": "1.0.11",
+ "bundled": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "inherits": "2.0.3",
+ "mkdirp": "0.5.1",
+ "rimraf": "2.6.1"
+ }
+ },
+ "fstream-ignore": {
+ "version": "1.0.5",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "fstream": "1.0.11",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4"
+ }
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "aproba": "1.1.1",
+ "console-control-strings": "1.1.0",
+ "has-unicode": "2.0.1",
+ "object-assign": "4.1.1",
+ "signal-exit": "3.0.2",
+ "string-width": "1.0.2",
+ "strip-ansi": "3.0.1",
+ "wide-align": "1.1.2"
+ }
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "1.0.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "bundled": true,
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "bundled": true
+ },
+ "har-schema": {
+ "version": "1.0.5",
+ "bundled": true,
+ "optional": true
+ },
+ "har-validator": {
+ "version": "4.2.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "ajv": "4.11.8",
+ "har-schema": "1.0.5"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "hawk": {
+ "version": "3.1.3",
+ "bundled": true,
+ "requires": {
+ "boom": "2.10.1",
+ "cryptiles": "2.0.5",
+ "hoek": "2.16.3",
+ "sntp": "1.0.9"
+ }
+ },
+ "hoek": {
+ "version": "2.16.3",
+ "bundled": true
+ },
+ "http-signature": {
+ "version": "1.1.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "0.2.0",
+ "jsprim": "1.4.0",
+ "sshpk": "1.13.0"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true
+ },
+ "ini": {
+ "version": "1.3.4",
+ "bundled": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "requires": {
+ "number-is-nan": "1.0.1"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "bundled": true,
+ "optional": true
+ },
+ "jodid25519": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "jsbn": "0.1.1"
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "bundled": true,
+ "optional": true
+ },
+ "json-stable-stringify": {
+ "version": "1.0.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "jsonify": "0.0.0"
+ }
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "jsonify": {
+ "version": "0.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "jsprim": {
+ "version": "1.4.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.0.2",
+ "json-schema": "0.2.3",
+ "verror": "1.3.6"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "mime-db": {
+ "version": "1.27.0",
+ "bundled": true
+ },
+ "mime-types": {
+ "version": "2.1.15",
+ "bundled": true,
+ "requires": {
+ "mime-db": "1.27.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "requires": {
+ "brace-expansion": "1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "node-pre-gyp": {
+ "version": "0.6.39",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "1.0.2",
+ "hawk": "3.1.3",
+ "mkdirp": "0.5.1",
+ "nopt": "4.0.1",
+ "npmlog": "4.1.0",
+ "rc": "1.2.1",
+ "request": "2.81.0",
+ "rimraf": "2.6.1",
+ "semver": "5.3.0",
+ "tar": "2.2.1",
+ "tar-pack": "3.4.0"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1.1.0",
+ "osenv": "0.1.4"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "1.1.4",
+ "console-control-strings": "1.1.0",
+ "gauge": "2.7.4",
+ "set-blocking": "2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "oauth-sign": {
+ "version": "0.8.2",
+ "bundled": true,
+ "optional": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "os-homedir": "1.0.2",
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "performance-now": {
+ "version": "0.2.0",
+ "bundled": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "bundled": true
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "bundled": true,
+ "optional": true
+ },
+ "qs": {
+ "version": "6.4.0",
+ "bundled": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "deep-extend": "0.4.2",
+ "ini": "1.3.4",
+ "minimist": "1.2.0",
+ "strip-json-comments": "2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.2.9",
+ "bundled": true,
+ "requires": {
+ "buffer-shims": "1.0.0",
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "string_decoder": "1.0.1",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "request": {
+ "version": "2.81.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "aws-sign2": "0.6.0",
+ "aws4": "1.6.0",
+ "caseless": "0.12.0",
+ "combined-stream": "1.0.5",
+ "extend": "3.0.1",
+ "forever-agent": "0.6.1",
+ "form-data": "2.1.4",
+ "har-validator": "4.2.1",
+ "hawk": "3.1.3",
+ "http-signature": "1.1.1",
+ "is-typedarray": "1.0.0",
+ "isstream": "0.1.2",
+ "json-stringify-safe": "5.0.1",
+ "mime-types": "2.1.15",
+ "oauth-sign": "0.8.2",
+ "performance-now": "0.2.0",
+ "qs": "6.4.0",
+ "safe-buffer": "5.0.1",
+ "stringstream": "0.0.5",
+ "tough-cookie": "2.3.2",
+ "tunnel-agent": "0.6.0",
+ "uuid": "3.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.1",
+ "bundled": true,
+ "requires": {
+ "glob": "7.1.2"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.0.1",
+ "bundled": true
+ },
+ "semver": {
+ "version": "5.3.0",
+ "bundled": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "sntp": {
+ "version": "1.0.9",
+ "bundled": true,
+ "requires": {
+ "hoek": "2.16.3"
+ }
+ },
+ "sshpk": {
+ "version": "1.13.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "asn1": "0.2.3",
+ "assert-plus": "1.0.0",
+ "bcrypt-pbkdf": "1.0.1",
+ "dashdash": "1.14.1",
+ "ecc-jsbn": "0.1.1",
+ "getpass": "0.1.7",
+ "jodid25519": "1.0.2",
+ "jsbn": "0.1.1",
+ "tweetnacl": "0.14.5"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "requires": {
+ "code-point-at": "1.1.0",
+ "is-fullwidth-code-point": "1.0.0",
+ "strip-ansi": "3.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.1",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "5.0.1"
+ }
+ },
+ "stringstream": {
+ "version": "0.0.5",
+ "bundled": true,
+ "optional": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "2.2.1",
+ "bundled": true,
+ "requires": {
+ "block-stream": "0.0.9",
+ "fstream": "1.0.11",
+ "inherits": "2.0.3"
+ }
+ },
+ "tar-pack": {
+ "version": "3.4.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "debug": "2.6.8",
+ "fstream": "1.0.11",
+ "fstream-ignore": "1.0.5",
+ "once": "1.4.0",
+ "readable-stream": "2.2.9",
+ "rimraf": "2.6.1",
+ "tar": "2.2.1",
+ "uid-number": "0.0.6"
+ }
+ },
+ "tough-cookie": {
+ "version": "2.3.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "punycode": "1.4.1"
+ }
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "bundled": true,
+ "optional": true
+ },
+ "uid-number": {
+ "version": "0.0.6",
+ "bundled": true,
+ "optional": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "uuid": {
+ "version": "3.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "verror": {
+ "version": "1.3.6",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "extsprintf": "1.0.2"
+ }
+ },
+ "wide-align": {
+ "version": "1.1.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "string-width": "1.0.2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true
+ }
+ }
+ },
"fstream": {
"version": "0.1.31",
"resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz",
@@ -3269,7 +4075,7 @@
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz",
"integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=",
"requires": {
- "postcss": "6.0.14"
+ "postcss": "6.0.16"
},
"dependencies": {
"ansi-styles": {
@@ -3288,16 +4094,26 @@
"ansi-styles": "3.2.0",
"escape-string-regexp": "1.0.5",
"supports-color": "4.5.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
}
},
"postcss": {
- "version": "6.0.14",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
- "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "version": "6.0.16",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz",
+ "integrity": "sha512-m758RWPmSjFH/2MyyG3UOW1fgYbR9rtdzz5UNJnlm7OLtu4B2h9C6gi+bE4qFKghsBRFfZT8NzoQBs6JhLotoA==",
"requires": {
"chalk": "2.3.0",
"source-map": "0.6.1",
- "supports-color": "4.5.0"
+ "supports-color": "5.1.0"
}
},
"source-map": {
@@ -3306,9 +4122,9 @@
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"supports-color": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
- "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz",
+ "integrity": "sha512-Ry0AwkoKjDpVKK4sV4h6o3UJmNRbjYm2uXhwfj3J56lMVdvnUNqzQVRztOOMGQ++w1K/TjNDFvpJk0F/LoeBCQ==",
"requires": {
"has-flag": "2.0.0"
}
@@ -3600,9 +4416,9 @@
}
},
"is-resolvable": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.1.tgz",
- "integrity": "sha512-y5CXYbzvB3jTnWAZH1Nl7ykUWb6T3BcTs56HUruwBf8MhF56n1HWqhDWnVFo8GHrUPDgvUUNVhrc2U8W7iqz5g=="
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
+ "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg=="
},
"is-retry-allowed": {
"version": "1.1.0",
@@ -3676,9 +4492,9 @@
}
},
"js-base64": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.0.tgz",
- "integrity": "sha512-Wehd+7Pf9tFvGb+ydPm9TjYjV8X1YHOVyG8QyELZxEMqOhemVwGRmoG8iQ/soqI3n8v4xn59zaLxiCJiaaRzKA=="
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.1.tgz",
+ "integrity": "sha512-2h586r2I/CqU7z1aa1kBgWaVAXWAZK+zHnceGi/jFgn7+7VSluxYer/i3xOZVearCxxXvyDkLtTBo+OeJCA3kA=="
},
"js-tokens": {
"version": "3.0.2",
@@ -3755,9 +4571,9 @@
}
},
"jss": {
- "version": "9.4.0",
- "resolved": "https://registry.npmjs.org/jss/-/jss-9.4.0.tgz",
- "integrity": "sha512-ckJpElL5CimehboeLDQoHeY7mlxn0KPnPn2EZVbn6pomhfbTXiQJ6fAJXSp9rUM2hPtE0PG8Swzdy9vhB2v82w==",
+ "version": "9.5.1",
+ "resolved": "https://registry.npmjs.org/jss/-/jss-9.5.1.tgz",
+ "integrity": "sha512-py//ogG1xeztpEDmosJtrkfUXibx3qiAr+1GQvfLHp7azpqkzTPLCnainDgH7Zn0q6S7rcM1eINrVT9n/r5f2w==",
"requires": {
"is-in-browser": "1.1.3",
"symbol-observable": "1.1.0",
@@ -3809,9 +4625,9 @@
}
},
"jss-preset-default": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/jss-preset-default/-/jss-preset-default-4.0.1.tgz",
- "integrity": "sha512-ZBj1ifZAPDn8iiC9PuB1jDCm/I0Bn53UNL9NHBgOY6AyMorDPgEb3IRjt6H+OHKwnEuCHw8tC/e3/q4I4DgTIw==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/jss-preset-default/-/jss-preset-default-4.1.0.tgz",
+ "integrity": "sha512-C6SyfDg99EFrt0bv0lsg2OEN3e72Fry9/hMPW2sO6MSVsx+vc/Og6TJJY3F2MY5Z/V2/wlARHVmCb3TYMr0zFA==",
"requires": {
"jss-camel-case": "6.0.0",
"jss-compose": "5.0.0",
@@ -3821,7 +4637,7 @@
"jss-global": "3.0.0",
"jss-nested": "6.0.1",
"jss-props-sort": "6.0.0",
- "jss-template": "1.0.0",
+ "jss-template": "1.0.1",
"jss-vendor-prefixer": "7.0.0"
}
},
@@ -3831,9 +4647,9 @@
"integrity": "sha512-E89UDcrphmI0LzmvYk25Hp4aE5ZBsXqMWlkFXS0EtPkunJkRr+WXdCNYbXbksIPnKlBenGB9OxzQY+mVc70S+g=="
},
"jss-template": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/jss-template/-/jss-template-1.0.0.tgz",
- "integrity": "sha512-NFAgcAp8V2fUxffWGGQ5zAolJq3neAvNjmWIwSmy9M6bmXTK9rnTu0fBlAcUh0ALC94B596/2TRphdkE5WRECQ==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/jss-template/-/jss-template-1.0.1.tgz",
+ "integrity": "sha512-m5BqEWha17fmIVXm1z8xbJhY6GFJxNB9H68GVnCWPyGYfxiAgY9WTQyvDAVj+pYRgrXSOfN5V1T4+SzN1sJTeg==",
"requires": {
"warning": "3.0.0"
}
@@ -4080,25 +4896,32 @@
}
},
"material-ui": {
- "version": "1.0.0-beta.24",
- "resolved": "https://registry.npmjs.org/material-ui/-/material-ui-1.0.0-beta.24.tgz",
- "integrity": "sha512-tPKQeR9RXXSJFj/QIhU5+mAnnZm5Gk6WcTufbVBDd0946wpfMJA2NY2J+M/SK9NXe+BTTVUCnWY92UCw5YA9tA==",
+ "version": "1.0.0-beta.30",
+ "resolved": "https://registry.npmjs.org/material-ui/-/material-ui-1.0.0-beta.30.tgz",
+ "integrity": "sha512-cgUUYf+sXjkUQmImjngHPmwo6kBIfvZKrNxmp56cpATYyaeoBydfERwv9SfUu1zzJyXLhJ6tt17XeUBn8aSqug==",
"requires": {
+ "@types/jss": "9.3.0",
+ "@types/react-transition-group": "2.0.6",
"babel-runtime": "6.26.0",
"brcast": "3.0.1",
"classnames": "2.2.5",
"deepmerge": "2.0.1",
"dom-helpers": "3.3.1",
"hoist-non-react-statics": "2.3.1",
- "jss": "9.4.0",
- "jss-preset-default": "4.0.1",
+ "jss": "9.5.1",
+ "jss-camel-case": "6.0.0",
+ "jss-default-unit": "8.0.2",
+ "jss-global": "3.0.0",
+ "jss-nested": "6.0.1",
+ "jss-props-sort": "6.0.0",
+ "jss-vendor-prefixer": "7.0.0",
"keycode": "2.1.9",
"lodash": "4.17.4",
"normalize-scroll-left": "0.1.2",
"prop-types": "15.6.0",
- "react-event-listener": "0.5.2",
- "react-jss": "8.2.0",
- "react-popper": "0.7.4",
+ "react-event-listener": "0.5.3",
+ "react-jss": "8.2.1",
+ "react-popper": "0.7.5",
"react-scrollbar-size": "2.0.2",
"react-transition-group": "2.2.1",
"recompose": "0.26.0",
@@ -4272,6 +5095,12 @@
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s="
},
+ "nan": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz",
+ "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=",
+ "optional": true
+ },
"natives": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz",
@@ -4312,7 +5141,7 @@
"querystring-es3": "0.2.1",
"readable-stream": "2.3.3",
"stream-browserify": "2.0.1",
- "stream-http": "2.7.2",
+ "stream-http": "2.8.0",
"string_decoder": "1.0.3",
"timers-browserify": "2.0.4",
"tty-browserify": "0.0.0",
@@ -4335,7 +5164,7 @@
"requires": {
"hosted-git-info": "2.5.0",
"is-builtin-module": "1.0.0",
- "semver": "5.4.1",
+ "semver": "5.5.0",
"validate-npm-package-license": "3.0.1"
}
},
@@ -4483,16 +5312,19 @@
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
},
"p-limit": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz",
- "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw="
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz",
+ "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==",
+ "requires": {
+ "p-try": "1.0.0"
+ }
},
"p-locate": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
"integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
"requires": {
- "p-limit": "1.1.0"
+ "p-limit": "1.2.0"
}
},
"p-timeout": {
@@ -4503,6 +5335,11 @@
"p-finally": "1.0.0"
}
},
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
+ },
"pako": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz",
@@ -4609,7 +5446,7 @@
"create-hmac": "1.1.6",
"ripemd160": "2.0.1",
"safe-buffer": "5.1.1",
- "sha.js": "2.4.9"
+ "sha.js": "2.4.10"
}
},
"performance-now": {
@@ -4659,7 +5496,7 @@
"integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
"requires": {
"chalk": "1.1.3",
- "js-base64": "2.4.0",
+ "js-base64": "2.4.1",
"source-map": "0.5.7",
"supports-color": "3.2.3"
},
@@ -4793,8 +5630,8 @@
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz",
"integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=",
"requires": {
- "caniuse-db": "1.0.30000784",
- "electron-to-chromium": "1.3.30"
+ "caniuse-db": "1.0.30000793",
+ "electron-to-chromium": "1.3.31"
}
}
}
@@ -4846,11 +5683,11 @@
}
},
"postcss-modules-extract-imports": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz",
- "integrity": "sha1-thTJcgvmgW6u41+zpfqh26agXds=",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz",
+ "integrity": "sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=",
"requires": {
- "postcss": "6.0.14"
+ "postcss": "6.0.16"
},
"dependencies": {
"ansi-styles": {
@@ -4869,16 +5706,26 @@
"ansi-styles": "3.2.0",
"escape-string-regexp": "1.0.5",
"supports-color": "4.5.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
}
},
"postcss": {
- "version": "6.0.14",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
- "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "version": "6.0.16",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz",
+ "integrity": "sha512-m758RWPmSjFH/2MyyG3UOW1fgYbR9rtdzz5UNJnlm7OLtu4B2h9C6gi+bE4qFKghsBRFfZT8NzoQBs6JhLotoA==",
"requires": {
"chalk": "2.3.0",
"source-map": "0.6.1",
- "supports-color": "4.5.0"
+ "supports-color": "5.1.0"
}
},
"source-map": {
@@ -4887,9 +5734,9 @@
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"supports-color": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
- "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz",
+ "integrity": "sha512-Ry0AwkoKjDpVKK4sV4h6o3UJmNRbjYm2uXhwfj3J56lMVdvnUNqzQVRztOOMGQ++w1K/TjNDFvpJk0F/LoeBCQ==",
"requires": {
"has-flag": "2.0.0"
}
@@ -4902,7 +5749,7 @@
"integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=",
"requires": {
"css-selector-tokenizer": "0.7.0",
- "postcss": "6.0.14"
+ "postcss": "6.0.16"
},
"dependencies": {
"ansi-styles": {
@@ -4921,16 +5768,26 @@
"ansi-styles": "3.2.0",
"escape-string-regexp": "1.0.5",
"supports-color": "4.5.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
}
},
"postcss": {
- "version": "6.0.14",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
- "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "version": "6.0.16",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz",
+ "integrity": "sha512-m758RWPmSjFH/2MyyG3UOW1fgYbR9rtdzz5UNJnlm7OLtu4B2h9C6gi+bE4qFKghsBRFfZT8NzoQBs6JhLotoA==",
"requires": {
"chalk": "2.3.0",
"source-map": "0.6.1",
- "supports-color": "4.5.0"
+ "supports-color": "5.1.0"
}
},
"source-map": {
@@ -4939,9 +5796,9 @@
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"supports-color": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
- "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz",
+ "integrity": "sha512-Ry0AwkoKjDpVKK4sV4h6o3UJmNRbjYm2uXhwfj3J56lMVdvnUNqzQVRztOOMGQ++w1K/TjNDFvpJk0F/LoeBCQ==",
"requires": {
"has-flag": "2.0.0"
}
@@ -4954,7 +5811,7 @@
"integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=",
"requires": {
"css-selector-tokenizer": "0.7.0",
- "postcss": "6.0.14"
+ "postcss": "6.0.16"
},
"dependencies": {
"ansi-styles": {
@@ -4973,16 +5830,26 @@
"ansi-styles": "3.2.0",
"escape-string-regexp": "1.0.5",
"supports-color": "4.5.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
}
},
"postcss": {
- "version": "6.0.14",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
- "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "version": "6.0.16",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz",
+ "integrity": "sha512-m758RWPmSjFH/2MyyG3UOW1fgYbR9rtdzz5UNJnlm7OLtu4B2h9C6gi+bE4qFKghsBRFfZT8NzoQBs6JhLotoA==",
"requires": {
"chalk": "2.3.0",
"source-map": "0.6.1",
- "supports-color": "4.5.0"
+ "supports-color": "5.1.0"
}
},
"source-map": {
@@ -4991,9 +5858,9 @@
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"supports-color": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
- "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz",
+ "integrity": "sha512-Ry0AwkoKjDpVKK4sV4h6o3UJmNRbjYm2uXhwfj3J56lMVdvnUNqzQVRztOOMGQ++w1K/TjNDFvpJk0F/LoeBCQ==",
"requires": {
"has-flag": "2.0.0"
}
@@ -5006,7 +5873,7 @@
"integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=",
"requires": {
"icss-replace-symbols": "1.1.0",
- "postcss": "6.0.14"
+ "postcss": "6.0.16"
},
"dependencies": {
"ansi-styles": {
@@ -5025,16 +5892,26 @@
"ansi-styles": "3.2.0",
"escape-string-regexp": "1.0.5",
"supports-color": "4.5.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
}
},
"postcss": {
- "version": "6.0.14",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
- "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "version": "6.0.16",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz",
+ "integrity": "sha512-m758RWPmSjFH/2MyyG3UOW1fgYbR9rtdzz5UNJnlm7OLtu4B2h9C6gi+bE4qFKghsBRFfZT8NzoQBs6JhLotoA==",
"requires": {
"chalk": "2.3.0",
"source-map": "0.6.1",
- "supports-color": "4.5.0"
+ "supports-color": "5.1.0"
}
},
"source-map": {
@@ -5043,9 +5920,9 @@
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"supports-color": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
- "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz",
+ "integrity": "sha512-Ry0AwkoKjDpVKK4sV4h6o3UJmNRbjYm2uXhwfj3J56lMVdvnUNqzQVRztOOMGQ++w1K/TjNDFvpJk0F/LoeBCQ==",
"requires": {
"has-flag": "2.0.0"
}
@@ -5225,7 +6102,7 @@
"browserify-rsa": "4.0.1",
"create-hash": "1.1.3",
"parse-asn1": "5.1.0",
- "randombytes": "2.0.5"
+ "randombytes": "2.0.6"
}
},
"pullstream": {
@@ -5312,11 +6189,6 @@
"global": "4.3.2"
}
},
- "ramda": {
- "version": "0.25.0",
- "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.25.0.tgz",
- "integrity": "sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ=="
- },
"randomatic": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
@@ -5355,9 +6227,9 @@
}
},
"randombytes": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz",
- "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==",
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz",
+ "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==",
"requires": {
"safe-buffer": "5.1.1"
}
@@ -5367,7 +6239,7 @@
"resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz",
"integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==",
"requires": {
- "randombytes": "2.0.5",
+ "randombytes": "2.0.6",
"safe-buffer": "5.1.1"
}
},
@@ -5394,9 +6266,9 @@
}
},
"react-event-listener": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/react-event-listener/-/react-event-listener-0.5.2.tgz",
- "integrity": "sha512-E22Sc/PtzVWw/fRidkEy1ZNnpSMJARUVV/5LymsDe4NjIHzNcVpNLV/R2Kt40NN8X6tu/X5p2inCny7vqd97mg==",
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/react-event-listener/-/react-event-listener-0.5.3.tgz",
+ "integrity": "sha512-fTGYvhe7eTsqq0m664Km0rxKQcqLIGZWZINmy1LU0fu312tay8Mt3Twq2P5Xj1dfDVvvzT1Ql3/FDkiMPJ1MOg==",
"requires": {
"babel-runtime": "6.26.0",
"fbjs": "0.8.16",
@@ -5414,21 +6286,21 @@
}
},
"react-jss": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/react-jss/-/react-jss-8.2.0.tgz",
- "integrity": "sha512-GaD9lPMFeNaLGbgrGNVKn8MwqxEULfi2+nuU0chYALK4wivhVJ2qya7UN6UNXzqxb+rjR1rOqdUQejHKCTQRTg==",
+ "version": "8.2.1",
+ "resolved": "https://registry.npmjs.org/react-jss/-/react-jss-8.2.1.tgz",
+ "integrity": "sha512-H1fm32xG8pi4LMHkXjqpLyFOvSDsravd0HI6Dtlb/iyma1tfi7qqqSH2bf0kKyTAJV5hvYL0ls0qvRJWKfDPcA==",
"requires": {
"hoist-non-react-statics": "2.3.1",
- "jss": "9.4.0",
- "jss-preset-default": "4.0.1",
+ "jss": "9.5.1",
+ "jss-preset-default": "4.1.0",
"prop-types": "15.6.0",
"theming": "1.3.0"
}
},
"react-popper": {
- "version": "0.7.4",
- "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-0.7.4.tgz",
- "integrity": "sha512-dx1fcKYYkidq7f71I1g+YX7g3QBLZ9taqiSRdJ7wbP7v/o7F6JsrUaNWGbVNul+TqdDDIZ5/k0xPUol9baqQJQ==",
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-0.7.5.tgz",
+ "integrity": "sha512-ya9dhhGCf74JTOB2uyksEHhIGw7w9tNZRUJF73lEq2h4H5JT6MBa4PdT4G+sx6fZwq+xKZAL/sVNAIuojPn7Dg==",
"requires": {
"popper.js": "1.12.9",
"prop-types": "15.6.0"
@@ -5449,7 +6321,7 @@
"requires": {
"babel-runtime": "6.26.0",
"prop-types": "15.6.0",
- "react-event-listener": "0.5.2"
+ "react-event-listener": "0.5.3"
}
},
"react-smooth": {
@@ -5521,9 +6393,9 @@
}
},
"recharts": {
- "version": "1.0.0-beta.7",
- "resolved": "https://registry.npmjs.org/recharts/-/recharts-1.0.0-beta.7.tgz",
- "integrity": "sha1-/M+T6vWVH3Q4y3a1pd0P50rVRFA=",
+ "version": "1.0.0-beta.9",
+ "resolved": "https://registry.npmjs.org/recharts/-/recharts-1.0.0-beta.9.tgz",
+ "integrity": "sha1-8A/33Jt7AXyLT2ahC5bzmyDNE1M=",
"requires": {
"classnames": "2.2.5",
"core-js": "2.5.1",
@@ -5700,7 +6572,7 @@
"stringstream": "0.0.5",
"tough-cookie": "2.3.3",
"tunnel-agent": "0.6.0",
- "uuid": "3.1.0"
+ "uuid": "3.2.1"
}
},
"require-directory": {
@@ -5817,9 +6689,9 @@
}
},
"semver": {
- "version": "5.4.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
- "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg=="
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+ "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA=="
},
"set-blocking": {
"version": "2.0.0",
@@ -5837,9 +6709,9 @@
"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
},
"sha.js": {
- "version": "2.4.9",
- "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz",
- "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==",
+ "version": "2.4.10",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz",
+ "integrity": "sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==",
"requires": {
"inherits": "2.0.3",
"safe-buffer": "5.1.1"
@@ -5989,9 +6861,9 @@
}
},
"stream-http": {
- "version": "2.7.2",
- "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz",
- "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==",
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz",
+ "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==",
"requires": {
"builtin-status-codes": "3.0.0",
"inherits": "2.0.3",
@@ -6434,9 +7306,9 @@
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"uuid": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
- "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g=="
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
+ "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA=="
},
"validate-npm-package-license": {
"version": "3.0.1",
@@ -6493,7 +7365,7 @@
"resolved": "https://registry.npmjs.org/webpack/-/webpack-3.10.0.tgz",
"integrity": "sha512-fxxKXoicjdXNUMY7LIdY89tkJJJ0m1Oo8PQutZ5rLgWbV5QVKI15Cn7+/IHnRTd3vfKfiwBx6SBqlorAuNA8LA==",
"requires": {
- "acorn": "5.2.1",
+ "acorn": "5.3.0",
"acorn-dynamic-import": "2.0.2",
"ajv": "5.5.2",
"ajv-keywords": "2.1.1",
diff --git a/dashboard/assets/package.json b/dashboard/assets/package.json
index 5bbfc185c..847fd4bc1 100644
--- a/dashboard/assets/package.json
+++ b/dashboard/assets/package.json
@@ -1,7 +1,7 @@
{
"dependencies": {
"babel-core": "^6.26.0",
- "babel-eslint": "^8.0.3",
+ "babel-eslint": "^8.2.1",
"babel-loader": "^7.1.2",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
@@ -12,27 +12,26 @@
"babel-preset-stage-0": "^6.24.1",
"babel-runtime": "^6.26.0",
"classnames": "^2.2.5",
- "css-loader": "^0.28.7",
- "eslint": "^4.13.1",
+ "css-loader": "^0.28.9",
+ "eslint": "^4.16.0",
"eslint-config-airbnb": "^16.1.0",
"eslint-loader": "^1.9.0",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-react": "^7.5.1",
- "eslint-plugin-flowtype": "^2.40.1",
+ "eslint-plugin-flowtype": "^2.41.0",
"file-loader": "^1.1.6",
- "flow-bin": "^0.61.0",
+ "flow-bin": "^0.63.1",
"flow-bin-loader": "^1.0.2",
"flow-typed": "^2.2.3",
- "material-ui": "^1.0.0-beta.24",
+ "material-ui": "^1.0.0-beta.30",
"material-ui-icons": "^1.0.0-beta.17",
"path": "^0.12.7",
- "ramda": "^0.25.0",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-fa": "^5.0.0",
"react-transition-group": "^2.2.1",
- "recharts": "^1.0.0-beta.6",
+ "recharts": "^1.0.0-beta.9",
"style-loader": "^0.19.1",
"url": "^0.11.0",
"url-loader": "^0.6.2",
diff --git a/dashboard/assets/types/content.jsx b/dashboard/assets/types/content.jsx
index f8a2b1e50..546125397 100644
--- a/dashboard/assets/types/content.jsx
+++ b/dashboard/assets/types/content.jsx
@@ -16,38 +16,55 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-import type {ChartEntry} from './message';
-
export type Content = {
- home: Home,
- chain: Chain,
- txpool: TxPool,
- network: Network,
- system: System,
- logs: Logs,
+ general: General,
+ home: Home,
+ chain: Chain,
+ txpool: TxPool,
+ network: Network,
+ system: System,
+ logs: Logs,
+};
+
+export type General = {
+ version: ?string,
+ commit: ?string,
};
export type Home = {
- memory: Array<ChartEntry>,
- traffic: Array<ChartEntry>,
+ activeMemory: ChartEntries,
+ virtualMemory: ChartEntries,
+ networkIngress: ChartEntries,
+ networkEgress: ChartEntries,
+ processCPU: ChartEntries,
+ systemCPU: ChartEntries,
+ diskRead: ChartEntries,
+ diskWrite: ChartEntries,
+};
+
+export type ChartEntries = Array<ChartEntry>;
+
+export type ChartEntry = {
+ time: Date,
+ value: number,
};
export type Chain = {
- /* TODO (kurkomisi) */
+ /* TODO (kurkomisi) */
};
export type TxPool = {
- /* TODO (kurkomisi) */
+ /* TODO (kurkomisi) */
};
export type Network = {
- /* TODO (kurkomisi) */
+ /* TODO (kurkomisi) */
};
export type System = {
- /* TODO (kurkomisi) */
+ /* TODO (kurkomisi) */
};
export type Logs = {
- log: Array<string>,
+ log: Array<string>,
};
diff --git a/dashboard/assets/webpack.config.js b/dashboard/assets/webpack.config.js
index cf92e6c97..d90c4fabd 100644
--- a/dashboard/assets/webpack.config.js
+++ b/dashboard/assets/webpack.config.js
@@ -23,7 +23,7 @@ module.exports = {
},
entry: './index',
output: {
- path: path.resolve(__dirname, 'public'),
+ path: path.resolve(__dirname, ''),
filename: 'bundle.js',
},
plugins: [
diff --git a/dashboard/config.go b/dashboard/config.go
index 57d902aee..604a5f2c9 100644
--- a/dashboard/config.go
+++ b/dashboard/config.go
@@ -22,7 +22,7 @@ import "time"
var DefaultConfig = Config{
Host: "localhost",
Port: 8080,
- Refresh: 3 * time.Second,
+ Refresh: 5 * time.Second,
}
// Config contains the configuration parameters of the dashboard.
diff --git a/dashboard/assets/types/message.jsx b/dashboard/cpu.go
index a806196ca..c89879028 100644
--- a/dashboard/assets/types/message.jsx
+++ b/dashboard/cpu.go
@@ -1,6 +1,4 @@
-// @flow
-
-// Copyright 2017 The go-ethereum Authors
+// Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
@@ -16,46 +14,22 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-export type Message = {
- home?: HomeMessage,
- chain?: ChainMessage,
- txpool?: TxPoolMessage,
- network?: NetworkMessage,
- system?: SystemMessage,
- logs?: LogsMessage,
-};
-
-export type HomeMessage = {
- memory?: Chart,
- traffic?: Chart,
-};
-
-export type Chart = {
- history?: Array<ChartEntry>,
- new?: ChartEntry,
-};
-
-export type ChartEntry = {
- time: Date,
- value: number,
-};
-
-export type ChainMessage = {
- /* TODO (kurkomisi) */
-};
+// +build !windows
-export type TxPoolMessage = {
- /* TODO (kurkomisi) */
-};
+package dashboard
-export type NetworkMessage = {
- /* TODO (kurkomisi) */
-};
+import (
+ "syscall"
-export type SystemMessage = {
- /* TODO (kurkomisi) */
-};
+ "github.com/ethereum/go-ethereum/log"
+)
-export type LogsMessage = {
- log: string,
-};
+// getProcessCPUTime retrieves the process' CPU time since program startup.
+func getProcessCPUTime() float64 {
+ var usage syscall.Rusage
+ if err := syscall.Getrusage(syscall.RUSAGE_SELF, &usage); err != nil {
+ log.Warn("Failed to retrieve CPU time", "err", err)
+ return 0
+ }
+ return float64(usage.Utime.Sec+usage.Stime.Sec) + float64(usage.Utime.Usec+usage.Stime.Usec)/1000000
+}
diff --git a/dashboard/cpu_windows.go b/dashboard/cpu_windows.go
new file mode 100644
index 000000000..9bb7ec789
--- /dev/null
+++ b/dashboard/cpu_windows.go
@@ -0,0 +1,23 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package dashboard
+
+// getProcessCPUTime returns 0 on Windows as there is no system call to resolve
+// the actual process' CPU time.
+func getProcessCPUTime() float64 {
+ return 0
+}
diff --git a/dashboard/dashboard.go b/dashboard/dashboard.go
index 513099e01..09038638e 100644
--- a/dashboard/dashboard.go
+++ b/dashboard/dashboard.go
@@ -16,10 +16,12 @@
package dashboard
+//go:generate npm --prefix ./assets install
//go:generate ./assets/node_modules/.bin/webpack --config ./assets/webpack.config.js --context ./assets
-//go:generate go-bindata -nometadata -o assets.go -prefix assets -nocompress -pkg dashboard assets/public/...
-//go:generate gofmt -s -w assets.go
-//go:generate sed -i "s#var _public#//nolint:misspell\\n&#" assets.go
+//go:generate go-bindata -nometadata -o assets.go -prefix assets -nocompress -pkg dashboard assets/dashboard.html assets/bundle.js
+//go:generate sh -c "sed 's#var _bundleJs#//nolint:misspell\\\n&#' assets.go > assets.go.tmp && mv assets.go.tmp assets.go"
+//go:generate sh -c "sed 's#var _dashboardHtml#//nolint:misspell\\\n&#' assets.go > assets.go.tmp && mv assets.go.tmp assets.go"
+//go:generate gofmt -w -s assets.go
import (
"fmt"
@@ -27,20 +29,29 @@ import (
"net"
"net/http"
"path/filepath"
+ "runtime"
"sync"
"sync/atomic"
"time"
+ "github.com/elastic/gosigar"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/rcrowley/go-metrics"
"golang.org/x/net/websocket"
)
const (
- memorySampleLimit = 200 // Maximum number of memory data samples
- trafficSampleLimit = 200 // Maximum number of traffic data samples
+ activeMemorySampleLimit = 200 // Maximum number of active memory data samples
+ virtualMemorySampleLimit = 200 // Maximum number of virtual memory data samples
+ networkIngressSampleLimit = 200 // Maximum number of network ingress data samples
+ networkEgressSampleLimit = 200 // Maximum number of network egress data samples
+ processCPUSampleLimit = 200 // Maximum number of process cpu data samples
+ systemCPUSampleLimit = 200 // Maximum number of system cpu data samples
+ diskReadSampleLimit = 200 // Maximum number of disk read data samples
+ diskWriteSampleLimit = 200 // Maximum number of disk write data samples
)
var nextID uint32 // Next connection id
@@ -52,6 +63,7 @@ type Dashboard struct {
listener net.Listener
conns map[uint32]*client // Currently live websocket connections
charts *HomeMessage
+ commit string
lock sync.RWMutex // Lock protecting the dashboard's internals
quit chan chan error // Channel used for graceful exit
@@ -66,16 +78,36 @@ type client struct {
}
// New creates a new dashboard instance with the given configuration.
-func New(config *Config) (*Dashboard, error) {
- return &Dashboard{
+func New(config *Config, commit string) (*Dashboard, error) {
+ now := time.Now()
+ db := &Dashboard{
conns: make(map[uint32]*client),
config: config,
quit: make(chan chan error),
charts: &HomeMessage{
- Memory: &Chart{},
- Traffic: &Chart{},
+ ActiveMemory: emptyChartEntries(now, activeMemorySampleLimit, config.Refresh),
+ VirtualMemory: emptyChartEntries(now, virtualMemorySampleLimit, config.Refresh),
+ NetworkIngress: emptyChartEntries(now, networkIngressSampleLimit, config.Refresh),
+ NetworkEgress: emptyChartEntries(now, networkEgressSampleLimit, config.Refresh),
+ ProcessCPU: emptyChartEntries(now, processCPUSampleLimit, config.Refresh),
+ SystemCPU: emptyChartEntries(now, systemCPUSampleLimit, config.Refresh),
+ DiskRead: emptyChartEntries(now, diskReadSampleLimit, config.Refresh),
+ DiskWrite: emptyChartEntries(now, diskWriteSampleLimit, config.Refresh),
},
- }, nil
+ commit: commit,
+ }
+ return db, nil
+}
+
+// emptyChartEntries returns a ChartEntry array containing limit number of empty samples.
+func emptyChartEntries(t time.Time, limit int, refresh time.Duration) ChartEntries {
+ ce := make(ChartEntries, limit)
+ for i := 0; i < limit; i++ {
+ ce[i] = &ChartEntry{
+ Time: t.Add(-time.Duration(i) * refresh),
+ }
+ }
+ return ce
}
// Protocols is a meaningless implementation of node.Service.
@@ -86,6 +118,8 @@ func (db *Dashboard) APIs() []rpc.API { return nil }
// Start implements node.Service, starting the data collection thread and the listening server of the dashboard.
func (db *Dashboard) Start(server *p2p.Server) error {
+ log.Info("Starting dashboard")
+
db.wg.Add(2)
go db.collectData()
go db.collectLogs() // In case of removing this line change 2 back to 1 in wg.Add.
@@ -159,7 +193,7 @@ func (db *Dashboard) webHandler(w http.ResponseWriter, r *http.Request) {
w.Write(blob)
return
}
- blob, err := Asset(filepath.Join("public", path))
+ blob, err := Asset(path[1:])
if err != nil {
log.Warn("Failed to load the asset", "path", path, "err", err)
http.Error(w, "not found", http.StatusNotFound)
@@ -196,15 +230,26 @@ func (db *Dashboard) apiHandler(conn *websocket.Conn) {
}
}
}()
+
+ versionMeta := ""
+ if len(params.VersionMeta) > 0 {
+ versionMeta = fmt.Sprintf(" (%s)", params.VersionMeta)
+ }
// Send the past data.
client.msg <- Message{
+ General: &GeneralMessage{
+ Version: fmt.Sprintf("v%d.%d.%d%s", params.VersionMajor, params.VersionMinor, params.VersionPatch, versionMeta),
+ Commit: db.commit,
+ },
Home: &HomeMessage{
- Memory: &Chart{
- History: db.charts.Memory.History,
- },
- Traffic: &Chart{
- History: db.charts.Traffic.History,
- },
+ ActiveMemory: db.charts.ActiveMemory,
+ VirtualMemory: db.charts.VirtualMemory,
+ NetworkIngress: db.charts.NetworkIngress,
+ NetworkEgress: db.charts.NetworkEgress,
+ ProcessCPU: db.charts.ProcessCPU,
+ SystemCPU: db.charts.SystemCPU,
+ DiskRead: db.charts.DiskRead,
+ DiskWrite: db.charts.DiskWrite,
},
}
// Start tracking the connection and drop at connection loss.
@@ -229,6 +274,19 @@ func (db *Dashboard) apiHandler(conn *websocket.Conn) {
// collectData collects the required data to plot on the dashboard.
func (db *Dashboard) collectData() {
defer db.wg.Done()
+ systemCPUUsage := gosigar.Cpu{}
+ systemCPUUsage.Get()
+ var (
+ prevNetworkIngress = metrics.DefaultRegistry.Get("p2p/InboundTraffic").(metrics.Meter).Count()
+ prevNetworkEgress = metrics.DefaultRegistry.Get("p2p/OutboundTraffic").(metrics.Meter).Count()
+ prevProcessCPUTime = getProcessCPUTime()
+ prevSystemCPUUsage = systemCPUUsage
+ prevDiskRead = metrics.DefaultRegistry.Get("eth/db/chaindata/compact/input").(metrics.Meter).Count()
+ prevDiskWrite = metrics.DefaultRegistry.Get("eth/db/chaindata/compact/output").(metrics.Meter).Count()
+
+ frequency = float64(db.config.Refresh / time.Second)
+ numCPU = float64(runtime.NumCPU())
+ )
for {
select {
@@ -236,36 +294,84 @@ func (db *Dashboard) collectData() {
errc <- nil
return
case <-time.After(db.config.Refresh):
- inboundTraffic := metrics.DefaultRegistry.Get("p2p/InboundTraffic").(metrics.Meter).Rate1()
- memoryInUse := metrics.DefaultRegistry.Get("system/memory/inuse").(metrics.Meter).Rate1()
+ systemCPUUsage.Get()
+ var (
+ curNetworkIngress = metrics.DefaultRegistry.Get("p2p/InboundTraffic").(metrics.Meter).Count()
+ curNetworkEgress = metrics.DefaultRegistry.Get("p2p/OutboundTraffic").(metrics.Meter).Count()
+ curProcessCPUTime = getProcessCPUTime()
+ curSystemCPUUsage = systemCPUUsage
+ curDiskRead = metrics.DefaultRegistry.Get("eth/db/chaindata/compact/input").(metrics.Meter).Count()
+ curDiskWrite = metrics.DefaultRegistry.Get("eth/db/chaindata/compact/output").(metrics.Meter).Count()
+
+ deltaNetworkIngress = float64(curNetworkIngress - prevNetworkIngress)
+ deltaNetworkEgress = float64(curNetworkEgress - prevNetworkEgress)
+ deltaProcessCPUTime = curProcessCPUTime - prevProcessCPUTime
+ deltaSystemCPUUsage = systemCPUUsage.Delta(prevSystemCPUUsage)
+ deltaDiskRead = curDiskRead - prevDiskRead
+ deltaDiskWrite = curDiskWrite - prevDiskWrite
+ )
+ prevNetworkIngress = curNetworkIngress
+ prevNetworkEgress = curNetworkEgress
+ prevProcessCPUTime = curProcessCPUTime
+ prevSystemCPUUsage = curSystemCPUUsage
+ prevDiskRead = curDiskRead
+ prevDiskWrite = curDiskWrite
+
now := time.Now()
- memory := &ChartEntry{
+
+ var mem runtime.MemStats
+ runtime.ReadMemStats(&mem)
+ activeMemory := &ChartEntry{
Time: now,
- Value: memoryInUse,
+ Value: float64(mem.Alloc) / frequency,
}
- traffic := &ChartEntry{
+ virtualMemory := &ChartEntry{
Time: now,
- Value: inboundTraffic,
+ Value: float64(mem.Sys) / frequency,
}
- first := 0
- if len(db.charts.Memory.History) == memorySampleLimit {
- first = 1
+ networkIngress := &ChartEntry{
+ Time: now,
+ Value: deltaNetworkIngress / frequency,
+ }
+ networkEgress := &ChartEntry{
+ Time: now,
+ Value: deltaNetworkEgress / frequency,
+ }
+ processCPU := &ChartEntry{
+ Time: now,
+ Value: deltaProcessCPUTime / frequency / numCPU * 100,
}
- db.charts.Memory.History = append(db.charts.Memory.History[first:], memory)
- first = 0
- if len(db.charts.Traffic.History) == trafficSampleLimit {
- first = 1
+ systemCPU := &ChartEntry{
+ Time: now,
+ Value: float64(deltaSystemCPUUsage.Sys+deltaSystemCPUUsage.User) / frequency / numCPU,
+ }
+ diskRead := &ChartEntry{
+ Time: now,
+ Value: float64(deltaDiskRead) / frequency,
+ }
+ diskWrite := &ChartEntry{
+ Time: now,
+ Value: float64(deltaDiskWrite) / frequency,
}
- db.charts.Traffic.History = append(db.charts.Traffic.History[first:], traffic)
+ db.charts.ActiveMemory = append(db.charts.ActiveMemory[1:], activeMemory)
+ db.charts.VirtualMemory = append(db.charts.VirtualMemory[1:], virtualMemory)
+ db.charts.NetworkIngress = append(db.charts.NetworkIngress[1:], networkIngress)
+ db.charts.NetworkEgress = append(db.charts.NetworkEgress[1:], networkEgress)
+ db.charts.ProcessCPU = append(db.charts.ProcessCPU[1:], processCPU)
+ db.charts.SystemCPU = append(db.charts.SystemCPU[1:], systemCPU)
+ db.charts.DiskRead = append(db.charts.DiskRead[1:], diskRead)
+ db.charts.DiskWrite = append(db.charts.DiskRead[1:], diskWrite)
db.sendToAll(&Message{
Home: &HomeMessage{
- Memory: &Chart{
- New: memory,
- },
- Traffic: &Chart{
- New: traffic,
- },
+ ActiveMemory: ChartEntries{activeMemory},
+ VirtualMemory: ChartEntries{virtualMemory},
+ NetworkIngress: ChartEntries{networkIngress},
+ NetworkEgress: ChartEntries{networkEgress},
+ ProcessCPU: ChartEntries{processCPU},
+ SystemCPU: ChartEntries{systemCPU},
+ DiskRead: ChartEntries{diskRead},
+ DiskWrite: ChartEntries{diskWrite},
},
})
}
@@ -286,7 +392,7 @@ func (db *Dashboard) collectLogs() {
case <-time.After(db.config.Refresh / 2):
db.sendToAll(&Message{
Logs: &LogsMessage{
- Log: fmt.Sprintf("%-4d: This is a fake log.", id),
+ Log: []string{fmt.Sprintf("%-4d: This is a fake log.", id)},
},
})
id++
diff --git a/dashboard/message.go b/dashboard/message.go
index 240de0c34..f0d4280e8 100644
--- a/dashboard/message.go
+++ b/dashboard/message.go
@@ -19,6 +19,7 @@ package dashboard
import "time"
type Message struct {
+ General *GeneralMessage `json:"general,omitempty"`
Home *HomeMessage `json:"home,omitempty"`
Chain *ChainMessage `json:"chain,omitempty"`
TxPool *TxPoolMessage `json:"txpool,omitempty"`
@@ -27,16 +28,24 @@ type Message struct {
Logs *LogsMessage `json:"logs,omitempty"`
}
-type HomeMessage struct {
- Memory *Chart `json:"memory,omitempty"`
- Traffic *Chart `json:"traffic,omitempty"`
+type GeneralMessage struct {
+ Version string `json:"version,omitempty"`
+ Commit string `json:"commit,omitempty"`
}
-type Chart struct {
- History []*ChartEntry `json:"history,omitempty"`
- New *ChartEntry `json:"new,omitempty"`
+type HomeMessage struct {
+ ActiveMemory ChartEntries `json:"activeMemory,omitempty"`
+ VirtualMemory ChartEntries `json:"virtualMemory,omitempty"`
+ NetworkIngress ChartEntries `json:"networkIngress,omitempty"`
+ NetworkEgress ChartEntries `json:"networkEgress,omitempty"`
+ ProcessCPU ChartEntries `json:"processCPU,omitempty"`
+ SystemCPU ChartEntries `json:"systemCPU,omitempty"`
+ DiskRead ChartEntries `json:"diskRead,omitempty"`
+ DiskWrite ChartEntries `json:"diskWrite,omitempty"`
}
+type ChartEntries []*ChartEntry
+
type ChartEntry struct {
Time time.Time `json:"time,omitempty"`
Value float64 `json:"value,omitempty"`
@@ -59,5 +68,5 @@ type SystemMessage struct {
}
type LogsMessage struct {
- Log string `json:"log,omitempty"`
+ Log []string `json:"log,omitempty"`
}
diff --git a/eth/api.go b/eth/api.go
index 0db3eb554..a345b57e4 100644
--- a/eth/api.go
+++ b/eth/api.go
@@ -462,11 +462,11 @@ func (api *PrivateDebugAPI) getModifiedAccounts(startBlock, endBlock *types.Bloc
return nil, fmt.Errorf("start block height (%d) must be less than end block height (%d)", startBlock.Number().Uint64(), endBlock.Number().Uint64())
}
- oldTrie, err := trie.NewSecure(startBlock.Root(), api.eth.chainDb, 0)
+ oldTrie, err := trie.NewSecure(startBlock.Root(), trie.NewDatabase(api.eth.chainDb), 0)
if err != nil {
return nil, err
}
- newTrie, err := trie.NewSecure(endBlock.Root(), api.eth.chainDb, 0)
+ newTrie, err := trie.NewSecure(endBlock.Root(), trie.NewDatabase(api.eth.chainDb), 0)
if err != nil {
return nil, err
}
diff --git a/eth/api_test.go b/eth/api_test.go
index 248bc3ab6..900a82bb6 100644
--- a/eth/api_test.go
+++ b/eth/api_test.go
@@ -1,4 +1,4 @@
-// Copyright 2016 The go-ethereum Authors
+// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
diff --git a/eth/api_tracer.go b/eth/api_tracer.go
index 0d0e2a73c..07c4457bc 100644
--- a/eth/api_tracer.go
+++ b/eth/api_tracer.go
@@ -24,7 +24,6 @@ import (
"io/ioutil"
"runtime"
"sync"
- "sync/atomic"
"time"
"github.com/ethereum/go-ethereum/common"
@@ -34,7 +33,6 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
@@ -72,6 +70,7 @@ type txTraceResult struct {
type blockTraceTask struct {
statedb *state.StateDB // Intermediate state prepped for tracing
block *types.Block // Block to trace the transactions from
+ rootref common.Hash // Trie root reference held for this task
results []*txTraceResult // Trace results procudes by the task
}
@@ -90,59 +89,6 @@ type txTraceTask struct {
index int // Transaction offset in the block
}
-// ephemeralDatabase is a memory wrapper around a proper database, which acts as
-// an ephemeral write layer. This construct is used by the chain tracer to write
-// state tries for intermediate blocks without serializing to disk, but at the
-// same time to allow disk fallback for reads that do no hit the memory layer.
-type ephemeralDatabase struct {
- diskdb ethdb.Database // Persistent disk database to fall back to with reads
- memdb *ethdb.MemDatabase // Ephemeral memory database for primary reads and writes
-}
-
-func (db *ephemeralDatabase) Put(key []byte, value []byte) error { return db.memdb.Put(key, value) }
-func (db *ephemeralDatabase) Delete(key []byte) error { return errors.New("delete not supported") }
-func (db *ephemeralDatabase) Close() { db.memdb.Close() }
-func (db *ephemeralDatabase) NewBatch() ethdb.Batch {
- return db.memdb.NewBatch()
-}
-func (db *ephemeralDatabase) Has(key []byte) (bool, error) {
- if has, _ := db.memdb.Has(key); has {
- return has, nil
- }
- return db.diskdb.Has(key)
-}
-func (db *ephemeralDatabase) Get(key []byte) ([]byte, error) {
- if blob, _ := db.memdb.Get(key); blob != nil {
- return blob, nil
- }
- return db.diskdb.Get(key)
-}
-
-// Prune does a state sync into a new memory write layer and replaces the old one.
-// This allows us to discard entries that are no longer referenced from the current
-// state.
-func (db *ephemeralDatabase) Prune(root common.Hash) {
- // Pull the still relevant state data into memory
- sync := state.NewStateSync(root, db.diskdb)
- for sync.Pending() > 0 {
- hash := sync.Missing(1)[0]
-
- // Move the next trie node from the memory layer into a sync struct
- node, err := db.memdb.Get(hash[:])
- if err != nil {
- panic(err) // memdb must have the data
- }
- if _, _, err := sync.Process([]trie.SyncResult{{Hash: hash, Data: node}}); err != nil {
- panic(err) // it's not possible to fail processing a node
- }
- }
- // Discard the old memory layer and write a new one
- db.memdb, _ = ethdb.NewMemDatabaseWithCap(db.memdb.Len())
- if _, err := sync.Commit(db); err != nil {
- panic(err) // writing into a memdb cannot fail
- }
-}
-
// TraceChain returns the structured logs created during the execution of EVM
// between two blocks (excluding start) and returns them as a JSON object.
func (api *PrivateDebugAPI) TraceChain(ctx context.Context, start, end rpc.BlockNumber, config *TraceConfig) (*rpc.Subscription, error) {
@@ -188,23 +134,19 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
// Ensure we have a valid starting state before doing any work
origin := start.NumberU64()
+ database := state.NewDatabase(api.eth.ChainDb())
- memdb, _ := ethdb.NewMemDatabase()
- db := &ephemeralDatabase{
- diskdb: api.eth.ChainDb(),
- memdb: memdb,
- }
if number := start.NumberU64(); number > 0 {
start = api.eth.blockchain.GetBlock(start.ParentHash(), start.NumberU64()-1)
if start == nil {
return nil, fmt.Errorf("parent block #%d not found", number-1)
}
}
- statedb, err := state.New(start.Root(), state.NewDatabase(db))
+ statedb, err := state.New(start.Root(), database)
if err != nil {
// If the starting state is missing, allow some number of blocks to be reexecuted
reexec := defaultTraceReexec
- if config.Reexec != nil {
+ if config != nil && config.Reexec != nil {
reexec = *config.Reexec
}
// Find the most recent block that has the state available
@@ -213,7 +155,7 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
if start == nil {
break
}
- if statedb, err = state.New(start.Root(), state.NewDatabase(db)); err == nil {
+ if statedb, err = state.New(start.Root(), database); err == nil {
break
}
}
@@ -256,7 +198,7 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
res, err := api.traceTx(ctx, msg, vmctx, task.statedb, config)
if err != nil {
task.results[i] = &txTraceResult{Error: err.Error()}
- log.Warn("Tracing failed", "err", err)
+ log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
break
}
task.statedb.DeleteSuicides()
@@ -273,7 +215,6 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
}
// Start a goroutine to feed all the blocks into the tracers
begin := time.Now()
- complete := start.NumberU64()
go func() {
var (
@@ -281,6 +222,7 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
number uint64
traced uint64
failed error
+ proot common.Hash
)
// Ensure everything is properly cleaned up on any exit path
defer func() {
@@ -308,7 +250,7 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
// Print progress logs if long enough time elapsed
if time.Since(logged) > 8*time.Second {
if number > origin {
- log.Info("Tracing chain segment", "start", origin, "end", end.NumberU64(), "current", number, "transactions", traced, "elapsed", time.Since(begin))
+ log.Info("Tracing chain segment", "start", origin, "end", end.NumberU64(), "current", number, "transactions", traced, "elapsed", time.Since(begin), "memory", database.TrieDB().Size())
} else {
log.Info("Preparing state for chain trace", "block", number, "start", origin, "elapsed", time.Since(begin))
}
@@ -325,13 +267,11 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
txs := block.Transactions()
select {
- case tasks <- &blockTraceTask{statedb: statedb.Copy(), block: block, results: make([]*txTraceResult, len(txs))}:
+ case tasks <- &blockTraceTask{statedb: statedb.Copy(), block: block, rootref: proot, results: make([]*txTraceResult, len(txs))}:
case <-notifier.Closed():
return
}
traced += uint64(len(txs))
- } else {
- atomic.StoreUint64(&complete, number)
}
// Generate the next state snapshot fast without tracing
_, _, _, err := api.eth.blockchain.Processor().Process(block, statedb, vm.Config{})
@@ -340,7 +280,7 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
break
}
// Finalize the state so any modifications are written to the trie
- root, err := statedb.CommitTo(db, true)
+ root, err := statedb.Commit(true)
if err != nil {
failed = err
break
@@ -349,26 +289,14 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
failed = err
break
}
- // After every N blocks, prune the database to only retain relevant data
- if (number-start.NumberU64())%4096 == 0 {
- // Wait until currently pending trace jobs finish
- for atomic.LoadUint64(&complete) != number {
- select {
- case <-time.After(100 * time.Millisecond):
- case <-notifier.Closed():
- return
- }
- }
- // No more concurrent access at this point, prune the database
- var (
- nodes = db.memdb.Len()
- start = time.Now()
- )
- db.Prune(root)
- log.Info("Pruned tracer state entries", "deleted", nodes-db.memdb.Len(), "left", db.memdb.Len(), "elapsed", time.Since(start))
-
- statedb, _ = state.New(root, state.NewDatabase(db))
+ // Reference the trie twice, once for us, once for the trancer
+ database.TrieDB().Reference(root, common.Hash{})
+ if number >= origin {
+ database.TrieDB().Reference(root, common.Hash{})
}
+ // Dereference all past tries we ourselves are done working with
+ database.TrieDB().Dereference(proot, common.Hash{})
+ proot = root
}
}()
@@ -387,12 +315,14 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
}
done[uint64(result.Block)] = result
+ // Dereference any paret tries held in memory by this task
+ database.TrieDB().Dereference(res.rootref, common.Hash{})
+
// Stream completed traces to the user, aborting on the first error
for result, ok := done[next]; ok; result, ok = done[next] {
if len(result.Traces) > 0 || next == end.NumberU64() {
notifier.Notify(sub.ID, result)
}
- atomic.StoreUint64(&complete, next)
delete(done, next)
next++
}
@@ -465,7 +395,7 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
return nil, fmt.Errorf("parent %x not found", block.ParentHash())
}
reexec := defaultTraceReexec
- if config.Reexec != nil {
+ if config != nil && config.Reexec != nil {
reexec = *config.Reexec
}
statedb, err := api.computeStateDB(parent, reexec)
@@ -544,18 +474,14 @@ func (api *PrivateDebugAPI) computeStateDB(block *types.Block, reexec uint64) (*
}
// Otherwise try to reexec blocks until we find a state or reach our limit
origin := block.NumberU64()
+ database := state.NewDatabase(api.eth.ChainDb())
- memdb, _ := ethdb.NewMemDatabase()
- db := &ephemeralDatabase{
- diskdb: api.eth.ChainDb(),
- memdb: memdb,
- }
for i := uint64(0); i < reexec; i++ {
block = api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
if block == nil {
break
}
- if statedb, err = state.New(block.Root(), state.NewDatabase(db)); err == nil {
+ if statedb, err = state.New(block.Root(), database); err == nil {
break
}
}
@@ -571,6 +497,7 @@ func (api *PrivateDebugAPI) computeStateDB(block *types.Block, reexec uint64) (*
var (
start = time.Now()
logged time.Time
+ proot common.Hash
)
for block.NumberU64() < origin {
// Print progress logs if long enough time elapsed
@@ -587,26 +514,18 @@ func (api *PrivateDebugAPI) computeStateDB(block *types.Block, reexec uint64) (*
return nil, err
}
// Finalize the state so any modifications are written to the trie
- root, err := statedb.CommitTo(db, true)
+ root, err := statedb.Commit(true)
if err != nil {
return nil, err
}
if err := statedb.Reset(root); err != nil {
return nil, err
}
- // After every N blocks, prune the database to only retain relevant data
- if block.NumberU64()%4096 == 0 || block.NumberU64() == origin {
- var (
- nodes = db.memdb.Len()
- begin = time.Now()
- )
- db.Prune(root)
- log.Info("Pruned tracer state entries", "deleted", nodes-db.memdb.Len(), "left", db.memdb.Len(), "elapsed", time.Since(begin))
-
- statedb, _ = state.New(root, state.NewDatabase(db))
- }
+ database.TrieDB().Reference(root, common.Hash{})
+ database.TrieDB().Dereference(proot, common.Hash{})
+ proot = root
}
- log.Info("Historical state regenerated", "block", block.NumberU64(), "elapsed", time.Since(start))
+ log.Info("Historical state regenerated", "block", block.NumberU64(), "elapsed", time.Since(start), "size", database.TrieDB().Size())
return statedb, nil
}
@@ -619,7 +538,7 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, hash common.Ha
return nil, fmt.Errorf("transaction %x not found", hash)
}
reexec := defaultTraceReexec
- if config.Reexec != nil {
+ if config != nil && config.Reexec != nil {
reexec = *config.Reexec
}
msg, vmctx, statedb, err := api.computeTxEnv(blockHash, int(index), reexec)
diff --git a/eth/backend.go b/eth/backend.go
index c39974a2c..94aad2310 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -144,9 +144,11 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
}
core.WriteBlockChainVersion(chainDb, core.BlockChainVersion)
}
-
- vmConfig := vm.Config{EnablePreimageRecording: config.EnablePreimageRecording}
- eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.engine, vmConfig)
+ var (
+ vmConfig = vm.Config{EnablePreimageRecording: config.EnablePreimageRecording}
+ cacheConfig = &core.CacheConfig{Disabled: config.NoPruning, TrieNodeLimit: config.TrieCache, TrieTimeLimit: config.TrieTimeout}
+ )
+ eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, eth.chainConfig, eth.engine, vmConfig)
if err != nil {
return nil, err
}
@@ -393,10 +395,10 @@ func (s *Ethereum) Start(srvr *p2p.Server) error {
// Figure out a max peers count based on the server limits
maxPeers := srvr.MaxPeers
if s.config.LightServ > 0 {
- maxPeers -= s.config.LightPeers
- if maxPeers < srvr.MaxPeers/2 {
- maxPeers = srvr.MaxPeers / 2
+ if s.config.LightPeers >= srvr.MaxPeers {
+ return fmt.Errorf("invalid peer config: light peer count (%d) >= total peer count (%d)", s.config.LightPeers, srvr.MaxPeers)
}
+ maxPeers -= s.config.LightPeers
}
// Start the networking layer and the light server if requested
s.protocolManager.Start(maxPeers)
diff --git a/eth/bind.go b/eth/bind.go
deleted file mode 100644
index d09977dbc..000000000
--- a/eth/bind.go
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2015 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-package eth
-
-import (
- "context"
- "math/big"
-
- "github.com/ethereum/go-ethereum"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/internal/ethapi"
- "github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/rpc"
-)
-
-// ContractBackend implements bind.ContractBackend with direct calls to Ethereum
-// internals to support operating on contracts within subprotocols like eth and
-// swarm.
-//
-// Internally this backend uses the already exposed API endpoints of the Ethereum
-// object. These should be rewritten to internal Go method calls when the Go API
-// is refactored to support a clean library use.
-type ContractBackend struct {
- eapi *ethapi.PublicEthereumAPI // Wrapper around the Ethereum object to access metadata
- bcapi *ethapi.PublicBlockChainAPI // Wrapper around the blockchain to access chain data
- txapi *ethapi.PublicTransactionPoolAPI // Wrapper around the transaction pool to access transaction data
-}
-
-// NewContractBackend creates a new native contract backend using an existing
-// Ethereum object.
-func NewContractBackend(apiBackend ethapi.Backend) *ContractBackend {
- return &ContractBackend{
- eapi: ethapi.NewPublicEthereumAPI(apiBackend),
- bcapi: ethapi.NewPublicBlockChainAPI(apiBackend),
- txapi: ethapi.NewPublicTransactionPoolAPI(apiBackend, new(ethapi.AddrLocker)),
- }
-}
-
-// CodeAt retrieves any code associated with the contract from the local API.
-func (b *ContractBackend) CodeAt(ctx context.Context, contract common.Address, blockNum *big.Int) ([]byte, error) {
- return b.bcapi.GetCode(ctx, contract, toBlockNumber(blockNum))
-}
-
-// CodeAt retrieves any code associated with the contract from the local API.
-func (b *ContractBackend) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) {
- return b.bcapi.GetCode(ctx, contract, rpc.PendingBlockNumber)
-}
-
-// ContractCall implements bind.ContractCaller executing an Ethereum contract
-// call with the specified data as the input. The pending flag requests execution
-// against the pending block, not the stable head of the chain.
-func (b *ContractBackend) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNum *big.Int) ([]byte, error) {
- out, err := b.bcapi.Call(ctx, toCallArgs(msg), toBlockNumber(blockNum))
- return out, err
-}
-
-// ContractCall implements bind.ContractCaller executing an Ethereum contract
-// call with the specified data as the input. The pending flag requests execution
-// against the pending block, not the stable head of the chain.
-func (b *ContractBackend) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) {
- out, err := b.bcapi.Call(ctx, toCallArgs(msg), rpc.PendingBlockNumber)
- return out, err
-}
-
-func toCallArgs(msg ethereum.CallMsg) ethapi.CallArgs {
- args := ethapi.CallArgs{
- To: msg.To,
- From: msg.From,
- Data: msg.Data,
- }
- if msg.Gas != nil {
- args.Gas = hexutil.Big(*msg.Gas)
- }
- if msg.GasPrice != nil {
- args.GasPrice = hexutil.Big(*msg.GasPrice)
- }
- if msg.Value != nil {
- args.Value = hexutil.Big(*msg.Value)
- }
- return args
-}
-
-func toBlockNumber(num *big.Int) rpc.BlockNumber {
- if num == nil {
- return rpc.LatestBlockNumber
- }
- return rpc.BlockNumber(num.Int64())
-}
-
-// PendingAccountNonce implements bind.ContractTransactor retrieving the current
-// pending nonce associated with an account.
-func (b *ContractBackend) PendingNonceAt(ctx context.Context, account common.Address) (nonce uint64, err error) {
- out, err := b.txapi.GetTransactionCount(ctx, account, rpc.PendingBlockNumber)
- if out != nil {
- nonce = uint64(*out)
- }
- return nonce, err
-}
-
-// SuggestGasPrice implements bind.ContractTransactor retrieving the currently
-// suggested gas price to allow a timely execution of a transaction.
-func (b *ContractBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
- return b.eapi.GasPrice(ctx)
-}
-
-// EstimateGasLimit implements bind.ContractTransactor triing to estimate the gas
-// needed to execute a specific transaction based on the current pending state of
-// the backend blockchain. There is no guarantee that this is the true gas limit
-// requirement as other transactions may be added or removed by miners, but it
-// should provide a basis for setting a reasonable default.
-func (b *ContractBackend) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (*big.Int, error) {
- out, err := b.bcapi.EstimateGas(ctx, toCallArgs(msg))
- return out.ToInt(), err
-}
-
-// SendTransaction implements bind.ContractTransactor injects the transaction
-// into the pending pool for execution.
-func (b *ContractBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error {
- raw, _ := rlp.EncodeToBytes(tx)
- _, err := b.txapi.SendRawTransaction(ctx, raw)
- return err
-}
diff --git a/eth/config.go b/eth/config.go
index 383cd6783..dd7f42c7d 100644
--- a/eth/config.go
+++ b/eth/config.go
@@ -22,6 +22,7 @@ import (
"os/user"
"path/filepath"
"runtime"
+ "time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
@@ -43,14 +44,16 @@ var DefaultConfig = Config{
DatasetsOnDisk: 2,
},
NetworkId: 1,
- LightPeers: 20,
- DatabaseCache: 128,
+ LightPeers: 100,
+ DatabaseCache: 768,
+ TrieCache: 256,
+ TrieTimeout: 5 * time.Minute,
GasPrice: big.NewInt(18 * params.Shannon),
TxPool: core.DefaultTxPoolConfig,
GPO: gasprice.Config{
- Blocks: 10,
- Percentile: 50,
+ Blocks: 20,
+ Percentile: 60,
},
}
@@ -78,6 +81,7 @@ type Config struct {
// Protocol options
NetworkId uint64 // Network ID to use for selecting peers to connect to
SyncMode downloader.SyncMode
+ NoPruning bool
// Light client options
LightServ int `toml:",omitempty"` // Maximum percentage of time allowed for serving LES requests
@@ -87,6 +91,8 @@ type Config struct {
SkipBcVersionCheck bool `toml:"-"`
DatabaseHandles int `toml:"-"`
DatabaseCache int
+ TrieCache int
+ TrieTimeout time.Duration
// Mining-related options
Etherbase common.Address `toml:",omitempty"`
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go
index b338129e0..7ede530a9 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/downloader.go
@@ -18,10 +18,8 @@
package downloader
import (
- "crypto/rand"
"errors"
"fmt"
- "math"
"math/big"
"sync"
"sync/atomic"
@@ -61,12 +59,11 @@ var (
maxHeadersProcess = 2048 // Number of header download results to import at once into the chain
maxResultsProcess = 2048 // Number of content download results to import at once into the chain
- fsHeaderCheckFrequency = 100 // Verification frequency of the downloaded headers during fast sync
- fsHeaderSafetyNet = 2048 // Number of headers to discard in case a chain violation is detected
- fsHeaderForceVerify = 24 // Number of headers to verify before and after the pivot to accept it
- fsPivotInterval = 256 // Number of headers out of which to randomize the pivot point
- fsMinFullBlocks = 64 // Number of blocks to retrieve fully even in fast sync
- fsCriticalTrials = uint32(32) // Number of times to retry in the cricical section before bailing
+ fsHeaderCheckFrequency = 100 // Verification frequency of the downloaded headers during fast sync
+ fsHeaderSafetyNet = 2048 // Number of headers to discard in case a chain violation is detected
+ fsHeaderForceVerify = 24 // Number of headers to verify before and after the pivot to accept it
+ fsHeaderContCheck = 3 * time.Second // Time interval to check for header continuations during state download
+ fsMinFullBlocks = 64 // Number of blocks to retrieve fully even in fast sync
)
var (
@@ -102,9 +99,6 @@ type Downloader struct {
peers *peerSet // Set of active peers from which download can proceed
stateDB ethdb.Database
- fsPivotLock *types.Header // Pivot header on critical section entry (cannot change between retries)
- fsPivotFails uint32 // Number of subsequent fast sync failures in the critical section
-
rttEstimate uint64 // Round trip time to target for download requests
rttConfidence uint64 // Confidence in the estimated RTT (unit: millionths to allow atomic ops)
@@ -124,6 +118,7 @@ type Downloader struct {
synchroniseMock func(id string, hash common.Hash) error // Replacement for synchronise during testing
synchronising int32
notified int32
+ committed int32
// Channels
headerCh chan dataPack // [eth/62] Channel receiving inbound block headers
@@ -156,7 +151,7 @@ type Downloader struct {
// LightChain encapsulates functions required to synchronise a light chain.
type LightChain interface {
// HasHeader verifies a header's presence in the local chain.
- HasHeader(h common.Hash, number uint64) bool
+ HasHeader(common.Hash, uint64) bool
// GetHeaderByHash retrieves a header from the local chain.
GetHeaderByHash(common.Hash) *types.Header
@@ -164,8 +159,8 @@ type LightChain interface {
// CurrentHeader retrieves the head header from the local chain.
CurrentHeader() *types.Header
- // GetTdByHash returns the total difficulty of a local block.
- GetTdByHash(common.Hash) *big.Int
+ // GetTd returns the total difficulty of a local block.
+ GetTd(common.Hash, uint64) *big.Int
// InsertHeaderChain inserts a batch of headers into the local chain.
InsertHeaderChain([]*types.Header, int) (int, error)
@@ -178,8 +173,8 @@ type LightChain interface {
type BlockChain interface {
LightChain
- // HasBlockAndState verifies block and associated states' presence in the local chain.
- HasBlockAndState(common.Hash) bool
+ // HasBlock verifies a block's presence in the local chain.
+ HasBlock(common.Hash, uint64) bool
// GetBlockByHash retrieves a block from the local chain.
GetBlockByHash(common.Hash) *types.Block
@@ -271,7 +266,6 @@ func (d *Downloader) Synchronising() bool {
// RegisterPeer injects a new download peer into the set of block source to be
// used for fetching hashes and blocks from.
func (d *Downloader) RegisterPeer(id string, version int, peer Peer) error {
-
logger := log.New("peer", id)
logger.Trace("Registering sync peer")
if err := d.peers.Register(newPeerConnection(id, version, peer, logger)); err != nil {
@@ -324,8 +318,13 @@ func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode
errEmptyHeaderSet, errPeersUnavailable, errTooOld,
errInvalidAncestor, errInvalidChain:
log.Warn("Synchronisation failed, dropping peer", "peer", id, "err", err)
- d.dropPeer(id)
-
+ if d.dropPeer == nil {
+ // The dropPeer method is nil when `--copydb` is used for a local copy.
+ // Timeouts can occur if e.g. compaction hits at the wrong time, and can be ignored
+ log.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", id)
+ } else {
+ d.dropPeer(id)
+ }
default:
log.Warn("Synchronisation failed, retrying", "err", err)
}
@@ -386,9 +385,7 @@ func (d *Downloader) synchronise(id string, hash common.Hash, td *big.Int, mode
// Set the requested sync mode, unless it's forbidden
d.mode = mode
- if d.mode == FastSync && atomic.LoadUint32(&d.fsPivotFails) >= fsCriticalTrials {
- d.mode = FullSync
- }
+
// Retrieve the origin peer and initiate the downloading process
p := d.peers.Peer(id)
if p == nil {
@@ -436,57 +433,40 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I
d.syncStatsChainHeight = height
d.syncStatsLock.Unlock()
- // Initiate the sync using a concurrent header and content retrieval algorithm
+ // Ensure our origin point is below any fast sync pivot point
pivot := uint64(0)
- switch d.mode {
- case LightSync:
- pivot = height
- case FastSync:
- // Calculate the new fast/slow sync pivot point
- if d.fsPivotLock == nil {
- pivotOffset, err := rand.Int(rand.Reader, big.NewInt(int64(fsPivotInterval)))
- if err != nil {
- panic(fmt.Sprintf("Failed to access crypto random source: %v", err))
- }
- if height > uint64(fsMinFullBlocks)+pivotOffset.Uint64() {
- pivot = height - uint64(fsMinFullBlocks) - pivotOffset.Uint64()
- }
+ if d.mode == FastSync {
+ if height <= uint64(fsMinFullBlocks) {
+ origin = 0
} else {
- // Pivot point locked in, use this and do not pick a new one!
- pivot = d.fsPivotLock.Number.Uint64()
- }
- // If the point is below the origin, move origin back to ensure state download
- if pivot < origin {
- if pivot > 0 {
+ pivot = height - uint64(fsMinFullBlocks)
+ if pivot <= origin {
origin = pivot - 1
- } else {
- origin = 0
}
}
- log.Debug("Fast syncing until pivot block", "pivot", pivot)
}
- d.queue.Prepare(origin+1, d.mode, pivot, latest)
+ d.committed = 1
+ if d.mode == FastSync && pivot != 0 {
+ d.committed = 0
+ }
+ // Initiate the sync using a concurrent header and content retrieval algorithm
+ d.queue.Prepare(origin+1, d.mode)
if d.syncInitHook != nil {
d.syncInitHook(origin, height)
}
fetchers := []func() error{
- func() error { return d.fetchHeaders(p, origin+1) }, // Headers are always retrieved
- func() error { return d.fetchBodies(origin + 1) }, // Bodies are retrieved during normal and fast sync
- func() error { return d.fetchReceipts(origin + 1) }, // Receipts are retrieved during fast sync
- func() error { return d.processHeaders(origin+1, td) },
+ func() error { return d.fetchHeaders(p, origin+1, pivot) }, // Headers are always retrieved
+ func() error { return d.fetchBodies(origin + 1) }, // Bodies are retrieved during normal and fast sync
+ func() error { return d.fetchReceipts(origin + 1) }, // Receipts are retrieved during fast sync
+ func() error { return d.processHeaders(origin+1, pivot, td) },
}
if d.mode == FastSync {
fetchers = append(fetchers, func() error { return d.processFastSyncContent(latest) })
} else if d.mode == FullSync {
fetchers = append(fetchers, d.processFullSyncContent)
}
- err = d.spawnSync(fetchers)
- if err != nil && d.mode == FastSync && d.fsPivotLock != nil {
- // If sync failed in the critical section, bump the fail counter.
- atomic.AddUint32(&d.fsPivotFails, 1)
- }
- return err
+ return d.spawnSync(fetchers)
}
// spawnSync runs d.process and all given fetcher functions to completion in
@@ -602,7 +582,6 @@ func (d *Downloader) findAncestor(p *peerConnection, height uint64) (uint64, err
// Figure out the valid ancestor range to prevent rewrite attacks
floor, ceil := int64(-1), d.lightchain.CurrentHeader().Number.Uint64()
- p.log.Debug("Looking for common ancestor", "local", ceil, "remote", height)
if d.mode == FullSync {
ceil = d.blockchain.CurrentBlock().NumberU64()
} else if d.mode == FastSync {
@@ -611,6 +590,8 @@ func (d *Downloader) findAncestor(p *peerConnection, height uint64) (uint64, err
if ceil >= MaxForkAncestry {
floor = int64(ceil - MaxForkAncestry)
}
+ p.log.Debug("Looking for common ancestor", "local", ceil, "remote", height)
+
// Request the topmost blocks to short circuit binary ancestor lookup
head := ceil
if head > height {
@@ -666,7 +647,7 @@ func (d *Downloader) findAncestor(p *peerConnection, height uint64) (uint64, err
continue
}
// Otherwise check if we already know the header or not
- if (d.mode == FullSync && d.blockchain.HasBlockAndState(headers[i].Hash())) || (d.mode != FullSync && d.lightchain.HasHeader(headers[i].Hash(), headers[i].Number.Uint64())) {
+ if (d.mode == FullSync && d.blockchain.HasBlock(headers[i].Hash(), headers[i].Number.Uint64())) || (d.mode != FullSync && d.lightchain.HasHeader(headers[i].Hash(), headers[i].Number.Uint64())) {
number, hash = headers[i].Number.Uint64(), headers[i].Hash()
// If every header is known, even future ones, the peer straight out lied about its head
@@ -731,7 +712,7 @@ func (d *Downloader) findAncestor(p *peerConnection, height uint64) (uint64, err
arrived = true
// Modify the search interval based on the response
- if (d.mode == FullSync && !d.blockchain.HasBlockAndState(headers[0].Hash())) || (d.mode != FullSync && !d.lightchain.HasHeader(headers[0].Hash(), headers[0].Number.Uint64())) {
+ if (d.mode == FullSync && !d.blockchain.HasBlock(headers[0].Hash(), headers[0].Number.Uint64())) || (d.mode != FullSync && !d.lightchain.HasHeader(headers[0].Hash(), headers[0].Number.Uint64())) {
end = check
break
}
@@ -769,7 +750,7 @@ func (d *Downloader) findAncestor(p *peerConnection, height uint64) (uint64, err
// other peers are only accepted if they map cleanly to the skeleton. If no one
// can fill in the skeleton - not even the origin peer - it's assumed invalid and
// the origin is dropped.
-func (d *Downloader) fetchHeaders(p *peerConnection, from uint64) error {
+func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64) error {
p.log.Debug("Directing header downloads", "origin", from)
defer p.log.Debug("Header download terminated")
@@ -820,6 +801,18 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64) error {
}
// If no more headers are inbound, notify the content fetchers and return
if packet.Items() == 0 {
+ // Don't abort header fetches while the pivot is downloading
+ if atomic.LoadInt32(&d.committed) == 0 && pivot <= from {
+ p.log.Debug("No headers, waiting for pivot commit")
+ select {
+ case <-time.After(fsHeaderContCheck):
+ getHeaders(from)
+ continue
+ case <-d.cancelCh:
+ return errCancelHeaderFetch
+ }
+ }
+ // Pivot done (or not in fast sync) and no more headers, terminate the process
p.log.Debug("No more headers available")
select {
case d.headerProcCh <- nil:
@@ -853,6 +846,12 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64) error {
getHeaders(from)
case <-timeout.C:
+ if d.dropPeer == nil {
+ // The dropPeer method is nil when `--copydb` is used for a local copy.
+ // Timeouts can occur if e.g. compaction hits at the wrong time, and can be ignored
+ p.log.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", p.id)
+ break
+ }
// Header retrieval timed out, consider the peer bad and drop
p.log.Debug("Header request timed out", "elapsed", ttl)
headerTimeoutMeter.Mark(1)
@@ -1071,7 +1070,13 @@ func (d *Downloader) fetchParts(errCancel error, deliveryCh chan dataPack, deliv
setIdle(peer, 0)
} else {
peer.log.Debug("Stalling delivery, dropping", "type", kind)
- d.dropPeer(pid)
+ if d.dropPeer == nil {
+ // The dropPeer method is nil when `--copydb` is used for a local copy.
+ // Timeouts can occur if e.g. compaction hits at the wrong time, and can be ignored
+ peer.log.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", pid)
+ } else {
+ d.dropPeer(pid)
+ }
}
}
}
@@ -1112,10 +1117,8 @@ func (d *Downloader) fetchParts(errCancel error, deliveryCh chan dataPack, deliv
}
if request.From > 0 {
peer.log.Trace("Requesting new batch of data", "type", kind, "from", request.From)
- } else if len(request.Headers) > 0 {
- peer.log.Trace("Requesting new batch of data", "type", kind, "count", len(request.Headers), "from", request.Headers[0].Number)
} else {
- peer.log.Trace("Requesting new batch of data", "type", kind, "count", len(request.Hashes))
+ peer.log.Trace("Requesting new batch of data", "type", kind, "count", len(request.Headers), "from", request.Headers[0].Number)
}
// Fetch the chunk and make sure any errors return the hashes to the queue
if fetchHook != nil {
@@ -1143,10 +1146,7 @@ func (d *Downloader) fetchParts(errCancel error, deliveryCh chan dataPack, deliv
// processHeaders takes batches of retrieved headers from an input channel and
// keeps processing and scheduling them into the header chain and downloader's
// queue until the stream ends or a failure occurs.
-func (d *Downloader) processHeaders(origin uint64, td *big.Int) error {
- // Calculate the pivoting point for switching from fast to slow sync
- pivot := d.queue.FastSyncPivot()
-
+func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) error {
// Keep a count of uncertain headers to roll back
rollback := []*types.Header{}
defer func() {
@@ -1171,19 +1171,6 @@ func (d *Downloader) processHeaders(origin uint64, td *big.Int) error {
"header", fmt.Sprintf("%d->%d", lastHeader, d.lightchain.CurrentHeader().Number),
"fast", fmt.Sprintf("%d->%d", lastFastBlock, curFastBlock),
"block", fmt.Sprintf("%d->%d", lastBlock, curBlock))
-
- // If we're already past the pivot point, this could be an attack, thread carefully
- if rollback[len(rollback)-1].Number.Uint64() > pivot {
- // If we didn't ever fail, lock in the pivot header (must! not! change!)
- if atomic.LoadUint32(&d.fsPivotFails) == 0 {
- for _, header := range rollback {
- if header.Number.Uint64() == pivot {
- log.Warn("Fast-sync pivot locked in", "number", pivot, "hash", header.Hash())
- d.fsPivotLock = header
- }
- }
- }
- }
}
}()
@@ -1218,7 +1205,8 @@ func (d *Downloader) processHeaders(origin uint64, td *big.Int) error {
// L: Request new headers up from 11 (R's TD was higher, it must have something)
// R: Nothing to give
if d.mode != LightSync {
- if !gotHeaders && td.Cmp(d.blockchain.GetTdByHash(d.blockchain.CurrentBlock().Hash())) > 0 {
+ head := d.blockchain.CurrentBlock()
+ if !gotHeaders && td.Cmp(d.blockchain.GetTd(head.Hash(), head.NumberU64())) > 0 {
return errStallingPeer
}
}
@@ -1230,7 +1218,8 @@ func (d *Downloader) processHeaders(origin uint64, td *big.Int) error {
// queued for processing when the header download completes. However, as long as the
// peer gave us something useful, we're already happy/progressed (above check).
if d.mode == FastSync || d.mode == LightSync {
- if td.Cmp(d.lightchain.GetTdByHash(d.lightchain.CurrentHeader().Hash())) > 0 {
+ head := d.lightchain.CurrentHeader()
+ if td.Cmp(d.lightchain.GetTd(head.Hash(), head.Number.Uint64())) > 0 {
return errStallingPeer
}
}
@@ -1283,13 +1272,6 @@ func (d *Downloader) processHeaders(origin uint64, td *big.Int) error {
rollback = append(rollback[:0], rollback[len(rollback)-fsHeaderSafetyNet:]...)
}
}
- // If we're fast syncing and just pulled in the pivot, make sure it's the one locked in
- if d.mode == FastSync && d.fsPivotLock != nil && chunk[0].Number.Uint64() <= pivot && chunk[len(chunk)-1].Number.Uint64() >= pivot {
- if pivot := chunk[int(pivot-chunk[0].Number.Uint64())]; pivot.Hash() != d.fsPivotLock.Hash() {
- log.Warn("Pivot doesn't match locked in one", "remoteNumber", pivot.Number, "remoteHash", pivot.Hash(), "localNumber", d.fsPivotLock.Number, "localHash", d.fsPivotLock.Hash())
- return errInvalidChain
- }
- }
// Unless we're doing light chains, schedule the headers for associated content retrieval
if d.mode == FullSync || d.mode == FastSync {
// If we've reached the allowed number of pending headers, stall a bit
@@ -1324,7 +1306,7 @@ func (d *Downloader) processHeaders(origin uint64, td *big.Int) error {
// processFullSyncContent takes fetch results from the queue and imports them into the chain.
func (d *Downloader) processFullSyncContent() error {
for {
- results := d.queue.WaitResults()
+ results := d.queue.Results(true)
if len(results) == 0 {
return nil
}
@@ -1338,30 +1320,28 @@ func (d *Downloader) processFullSyncContent() error {
}
func (d *Downloader) importBlockResults(results []*fetchResult) error {
- for len(results) != 0 {
- // Check for any termination requests. This makes clean shutdown faster.
- select {
- case <-d.quitCh:
- return errCancelContentProcessing
- default:
- }
- // Retrieve the a batch of results to import
- items := int(math.Min(float64(len(results)), float64(maxResultsProcess)))
- first, last := results[0].Header, results[items-1].Header
- log.Debug("Inserting downloaded chain", "items", len(results),
- "firstnum", first.Number, "firsthash", first.Hash(),
- "lastnum", last.Number, "lasthash", last.Hash(),
- )
- blocks := make([]*types.Block, items)
- for i, result := range results[:items] {
- blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles)
- }
- if index, err := d.blockchain.InsertChain(blocks); err != nil {
- log.Debug("Downloaded item processing failed", "number", results[index].Header.Number, "hash", results[index].Header.Hash(), "err", err)
- return errInvalidChain
- }
- // Shift the results to the next batch
- results = results[items:]
+ // Check for any early termination requests
+ if len(results) == 0 {
+ return nil
+ }
+ select {
+ case <-d.quitCh:
+ return errCancelContentProcessing
+ default:
+ }
+ // Retrieve the a batch of results to import
+ first, last := results[0].Header, results[len(results)-1].Header
+ log.Debug("Inserting downloaded chain", "items", len(results),
+ "firstnum", first.Number, "firsthash", first.Hash(),
+ "lastnum", last.Number, "lasthash", last.Hash(),
+ )
+ blocks := make([]*types.Block, len(results))
+ for i, result := range results {
+ blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles)
+ }
+ if index, err := d.blockchain.InsertChain(blocks); err != nil {
+ log.Debug("Downloaded item processing failed", "number", results[index].Header.Number, "hash", results[index].Header.Hash(), "err", err)
+ return errInvalidChain
}
return nil
}
@@ -1369,35 +1349,92 @@ func (d *Downloader) importBlockResults(results []*fetchResult) error {
// processFastSyncContent takes fetch results from the queue and writes them to the
// database. It also controls the synchronisation of state nodes of the pivot block.
func (d *Downloader) processFastSyncContent(latest *types.Header) error {
- // Start syncing state of the reported head block.
- // This should get us most of the state of the pivot block.
+ // Start syncing state of the reported head block. This should get us most of
+ // the state of the pivot block.
stateSync := d.syncState(latest.Root)
defer stateSync.Cancel()
go func() {
- if err := stateSync.Wait(); err != nil {
+ if err := stateSync.Wait(); err != nil && err != errCancelStateFetch {
d.queue.Close() // wake up WaitResults
}
}()
-
- pivot := d.queue.FastSyncPivot()
+ // Figure out the ideal pivot block. Note, that this goalpost may move if the
+ // sync takes long enough for the chain head to move significantly.
+ pivot := uint64(0)
+ if height := latest.Number.Uint64(); height > uint64(fsMinFullBlocks) {
+ pivot = height - uint64(fsMinFullBlocks)
+ }
+ // To cater for moving pivot points, track the pivot block and subsequently
+ // accumulated download results separatey.
+ var (
+ oldPivot *fetchResult // Locked in pivot block, might change eventually
+ oldTail []*fetchResult // Downloaded content after the pivot
+ )
for {
- results := d.queue.WaitResults()
+ // Wait for the next batch of downloaded data to be available, and if the pivot
+ // block became stale, move the goalpost
+ results := d.queue.Results(oldPivot == nil) // Block if we're not monitoring pivot staleness
if len(results) == 0 {
- return stateSync.Cancel()
+ // If pivot sync is done, stop
+ if oldPivot == nil {
+ return stateSync.Cancel()
+ }
+ // If sync failed, stop
+ select {
+ case <-d.cancelCh:
+ return stateSync.Cancel()
+ default:
+ }
}
if d.chainInsertHook != nil {
d.chainInsertHook(results)
}
+ if oldPivot != nil {
+ results = append(append([]*fetchResult{oldPivot}, oldTail...), results...)
+ }
+ // Split around the pivot block and process the two sides via fast/full sync
+ if atomic.LoadInt32(&d.committed) == 0 {
+ latest = results[len(results)-1].Header
+ if height := latest.Number.Uint64(); height > pivot+2*uint64(fsMinFullBlocks) {
+ log.Warn("Pivot became stale, moving", "old", pivot, "new", height-uint64(fsMinFullBlocks))
+ pivot = height - uint64(fsMinFullBlocks)
+ }
+ }
P, beforeP, afterP := splitAroundPivot(pivot, results)
if err := d.commitFastSyncData(beforeP, stateSync); err != nil {
return err
}
if P != nil {
- stateSync.Cancel()
- if err := d.commitPivotBlock(P); err != nil {
- return err
+ // If new pivot block found, cancel old state retrieval and restart
+ if oldPivot != P {
+ stateSync.Cancel()
+
+ stateSync = d.syncState(P.Header.Root)
+ defer stateSync.Cancel()
+ go func() {
+ if err := stateSync.Wait(); err != nil && err != errCancelStateFetch {
+ d.queue.Close() // wake up WaitResults
+ }
+ }()
+ oldPivot = P
+ }
+ // Wait for completion, occasionally checking for pivot staleness
+ select {
+ case <-stateSync.done:
+ if stateSync.err != nil {
+ return stateSync.err
+ }
+ if err := d.commitPivotBlock(P); err != nil {
+ return err
+ }
+ oldPivot = nil
+
+ case <-time.After(time.Second):
+ oldTail = afterP
+ continue
}
}
+ // Fast sync done, pivot commit done, full import
if err := d.importBlockResults(afterP); err != nil {
return err
}
@@ -1420,52 +1457,49 @@ func splitAroundPivot(pivot uint64, results []*fetchResult) (p *fetchResult, bef
}
func (d *Downloader) commitFastSyncData(results []*fetchResult, stateSync *stateSync) error {
- for len(results) != 0 {
- // Check for any termination requests.
- select {
- case <-d.quitCh:
- return errCancelContentProcessing
- case <-stateSync.done:
- if err := stateSync.Wait(); err != nil {
- return err
- }
- default:
- }
- // Retrieve the a batch of results to import
- items := int(math.Min(float64(len(results)), float64(maxResultsProcess)))
- first, last := results[0].Header, results[items-1].Header
- log.Debug("Inserting fast-sync blocks", "items", len(results),
- "firstnum", first.Number, "firsthash", first.Hash(),
- "lastnumn", last.Number, "lasthash", last.Hash(),
- )
- blocks := make([]*types.Block, items)
- receipts := make([]types.Receipts, items)
- for i, result := range results[:items] {
- blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles)
- receipts[i] = result.Receipts
- }
- if index, err := d.blockchain.InsertReceiptChain(blocks, receipts); err != nil {
- log.Debug("Downloaded item processing failed", "number", results[index].Header.Number, "hash", results[index].Header.Hash(), "err", err)
- return errInvalidChain
+ // Check for any early termination requests
+ if len(results) == 0 {
+ return nil
+ }
+ select {
+ case <-d.quitCh:
+ return errCancelContentProcessing
+ case <-stateSync.done:
+ if err := stateSync.Wait(); err != nil {
+ return err
}
- // Shift the results to the next batch
- results = results[items:]
+ default:
+ }
+ // Retrieve the a batch of results to import
+ first, last := results[0].Header, results[len(results)-1].Header
+ log.Debug("Inserting fast-sync blocks", "items", len(results),
+ "firstnum", first.Number, "firsthash", first.Hash(),
+ "lastnumn", last.Number, "lasthash", last.Hash(),
+ )
+ blocks := make([]*types.Block, len(results))
+ receipts := make([]types.Receipts, len(results))
+ for i, result := range results {
+ blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles)
+ receipts[i] = result.Receipts
+ }
+ if index, err := d.blockchain.InsertReceiptChain(blocks, receipts); err != nil {
+ log.Debug("Downloaded item processing failed", "number", results[index].Header.Number, "hash", results[index].Header.Hash(), "err", err)
+ return errInvalidChain
}
return nil
}
func (d *Downloader) commitPivotBlock(result *fetchResult) error {
- b := types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles)
- // Sync the pivot block state. This should complete reasonably quickly because
- // we've already synced up to the reported head block state earlier.
- if err := d.syncState(b.Root()).Wait(); err != nil {
+ block := types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles)
+ log.Debug("Committing fast sync pivot as new head", "number", block.Number(), "hash", block.Hash())
+ if _, err := d.blockchain.InsertReceiptChain([]*types.Block{block}, []types.Receipts{result.Receipts}); err != nil {
return err
}
- log.Debug("Committing fast sync pivot as new head", "number", b.Number(), "hash", b.Hash())
- if _, err := d.blockchain.InsertReceiptChain([]*types.Block{b}, []types.Receipts{result.Receipts}); err != nil {
+ if err := d.blockchain.FastSyncCommitHead(block.Hash()); err != nil {
return err
}
- return d.blockchain.FastSyncCommitHead(b.Hash())
+ atomic.StoreInt32(&d.committed, 1)
+ return nil
}
// DeliverHeaders injects a new batch of block headers received from a remote
diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go
index e14264944..cb671a7df 100644
--- a/eth/downloader/downloader_test.go
+++ b/eth/downloader/downloader_test.go
@@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
@@ -45,8 +44,8 @@ var (
// Reduce some of the parameters to make the tester faster.
func init() {
MaxForkAncestry = uint64(10000)
- blockCacheLimit = 1024
- fsCriticalTrials = 10
+ blockCacheItems = 1024
+ fsHeaderContCheck = 500 * time.Millisecond
}
// downloadTester is a test simulator for mocking out local block chain.
@@ -118,7 +117,7 @@ func (dl *downloadTester) makeChain(n int, seed byte, parent *types.Block, paren
// If the block number is multiple of 3, send a bonus transaction to the miner
if parent == dl.genesis && i%3 == 0 {
signer := types.MakeSigner(params.TestChainConfig, block.Number())
- tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), new(big.Int).SetUint64(params.TxGas), nil, nil), signer, testKey)
+ tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, nil, nil), signer, testKey)
if err != nil {
panic(err)
}
@@ -222,14 +221,9 @@ func (dl *downloadTester) HasHeader(hash common.Hash, number uint64) bool {
return dl.GetHeaderByHash(hash) != nil
}
-// HasBlockAndState checks if a block and associated state is present in the testers canonical chain.
-func (dl *downloadTester) HasBlockAndState(hash common.Hash) bool {
- block := dl.GetBlockByHash(hash)
- if block == nil {
- return false
- }
- _, err := dl.stateDb.Get(block.Root().Bytes())
- return err == nil
+// HasBlock checks if a block is present in the testers canonical chain.
+func (dl *downloadTester) HasBlock(hash common.Hash, number uint64) bool {
+ return dl.GetBlockByHash(hash) != nil
}
// GetHeader retrieves a header from the testers canonical chain.
@@ -293,14 +287,14 @@ func (dl *downloadTester) CurrentFastBlock() *types.Block {
func (dl *downloadTester) FastSyncCommitHead(hash common.Hash) error {
// For now only check that the state trie is correct
if block := dl.GetBlockByHash(hash); block != nil {
- _, err := trie.NewSecure(block.Root(), dl.stateDb, 0)
+ _, err := trie.NewSecure(block.Root(), trie.NewDatabase(dl.stateDb), 0)
return err
}
return fmt.Errorf("non existent block: %x", hash[:4])
}
-// GetTdByHash retrieves the block's total difficulty from the canonical chain.
-func (dl *downloadTester) GetTdByHash(hash common.Hash) *big.Int {
+// GetTd retrieves the block's total difficulty from the canonical chain.
+func (dl *downloadTester) GetTd(hash common.Hash, number uint64) *big.Int {
dl.lock.RLock()
defer dl.lock.RUnlock()
@@ -619,28 +613,22 @@ func assertOwnChain(t *testing.T, tester *downloadTester, length int) {
// number of items of the various chain components.
func assertOwnForkedChain(t *testing.T, tester *downloadTester, common int, lengths []int) {
// Initialize the counters for the first fork
- headers, blocks := lengths[0], lengths[0]
+ headers, blocks, receipts := lengths[0], lengths[0], lengths[0]-fsMinFullBlocks
- minReceipts, maxReceipts := lengths[0]-fsMinFullBlocks-fsPivotInterval, lengths[0]-fsMinFullBlocks
- if minReceipts < 0 {
- minReceipts = 1
- }
- if maxReceipts < 0 {
- maxReceipts = 1
+ if receipts < 0 {
+ receipts = 1
}
// Update the counters for each subsequent fork
for _, length := range lengths[1:] {
headers += length - common
blocks += length - common
-
- minReceipts += length - common - fsMinFullBlocks - fsPivotInterval
- maxReceipts += length - common - fsMinFullBlocks
+ receipts += length - common - fsMinFullBlocks
}
switch tester.downloader.mode {
case FullSync:
- minReceipts, maxReceipts = 1, 1
+ receipts = 1
case LightSync:
- blocks, minReceipts, maxReceipts = 1, 1, 1
+ blocks, receipts = 1, 1
}
if hs := len(tester.ownHeaders); hs != headers {
t.Fatalf("synchronised headers mismatch: have %v, want %v", hs, headers)
@@ -648,11 +636,12 @@ func assertOwnForkedChain(t *testing.T, tester *downloadTester, common int, leng
if bs := len(tester.ownBlocks); bs != blocks {
t.Fatalf("synchronised blocks mismatch: have %v, want %v", bs, blocks)
}
- if rs := len(tester.ownReceipts); rs < minReceipts || rs > maxReceipts {
- t.Fatalf("synchronised receipts mismatch: have %v, want between [%v, %v]", rs, minReceipts, maxReceipts)
+ if rs := len(tester.ownReceipts); rs != receipts {
+ t.Fatalf("synchronised receipts mismatch: have %v, want %v", rs, receipts)
}
// Verify the state trie too for fast syncs
- if tester.downloader.mode == FastSync {
+ /*if tester.downloader.mode == FastSync {
+ pivot := uint64(0)
var index int
if pivot := int(tester.downloader.queue.fastSyncPivot); pivot < common {
index = pivot
@@ -660,11 +649,11 @@ func assertOwnForkedChain(t *testing.T, tester *downloadTester, common int, leng
index = len(tester.ownHashes) - lengths[len(lengths)-1] + int(tester.downloader.queue.fastSyncPivot)
}
if index > 0 {
- if statedb, err := state.New(tester.ownHeaders[tester.ownHashes[index]].Root, state.NewDatabase(tester.stateDb)); statedb == nil || err != nil {
+ if statedb, err := state.New(tester.ownHeaders[tester.ownHashes[index]].Root, state.NewDatabase(trie.NewDatabase(tester.stateDb))); statedb == nil || err != nil {
t.Fatalf("state reconstruction failed: %v", err)
}
}
- }
+ }*/
}
// Tests that simple synchronization against a canonical chain works correctly.
@@ -684,7 +673,7 @@ func testCanonicalSynchronisation(t *testing.T, protocol int, mode SyncMode) {
defer tester.terminate()
// Create a small enough block chain to download
- targetBlocks := blockCacheLimit - 15
+ targetBlocks := blockCacheItems - 15
hashes, headers, blocks, receipts := tester.makeChain(targetBlocks, 0, tester.genesis, nil, false)
tester.newPeer("peer", protocol, hashes, headers, blocks, receipts)
@@ -710,7 +699,7 @@ func testThrottling(t *testing.T, protocol int, mode SyncMode) {
defer tester.terminate()
// Create a long block chain to download and the tester
- targetBlocks := 8 * blockCacheLimit
+ targetBlocks := 8 * blockCacheItems
hashes, headers, blocks, receipts := tester.makeChain(targetBlocks, 0, tester.genesis, nil, false)
tester.newPeer("peer", protocol, hashes, headers, blocks, receipts)
@@ -745,9 +734,9 @@ func testThrottling(t *testing.T, protocol int, mode SyncMode) {
cached = len(tester.downloader.queue.blockDonePool)
if mode == FastSync {
if receipts := len(tester.downloader.queue.receiptDonePool); receipts < cached {
- if tester.downloader.queue.resultCache[receipts].Header.Number.Uint64() < tester.downloader.queue.fastSyncPivot {
- cached = receipts
- }
+ //if tester.downloader.queue.resultCache[receipts].Header.Number.Uint64() < tester.downloader.queue.fastSyncPivot {
+ cached = receipts
+ //}
}
}
frozen = int(atomic.LoadUint32(&blocked))
@@ -755,7 +744,7 @@ func testThrottling(t *testing.T, protocol int, mode SyncMode) {
tester.downloader.queue.lock.Unlock()
tester.lock.Unlock()
- if cached == blockCacheLimit || retrieved+cached+frozen == targetBlocks+1 {
+ if cached == blockCacheItems || retrieved+cached+frozen == targetBlocks+1 {
break
}
}
@@ -765,8 +754,8 @@ func testThrottling(t *testing.T, protocol int, mode SyncMode) {
tester.lock.RLock()
retrieved = len(tester.ownBlocks)
tester.lock.RUnlock()
- if cached != blockCacheLimit && retrieved+cached+frozen != targetBlocks+1 {
- t.Fatalf("block count mismatch: have %v, want %v (owned %v, blocked %v, target %v)", cached, blockCacheLimit, retrieved, frozen, targetBlocks+1)
+ if cached != blockCacheItems && retrieved+cached+frozen != targetBlocks+1 {
+ t.Fatalf("block count mismatch: have %v, want %v (owned %v, blocked %v, target %v)", cached, blockCacheItems, retrieved, frozen, targetBlocks+1)
}
// Permit the blocked blocks to import
if atomic.LoadUint32(&blocked) > 0 {
@@ -974,7 +963,7 @@ func testCancel(t *testing.T, protocol int, mode SyncMode) {
defer tester.terminate()
// Create a small enough block chain to download and the tester
- targetBlocks := blockCacheLimit - 15
+ targetBlocks := blockCacheItems - 15
if targetBlocks >= MaxHashFetch {
targetBlocks = MaxHashFetch - 15
}
@@ -1016,12 +1005,12 @@ func testMultiSynchronisation(t *testing.T, protocol int, mode SyncMode) {
// Create various peers with various parts of the chain
targetPeers := 8
- targetBlocks := targetPeers*blockCacheLimit - 15
+ targetBlocks := targetPeers*blockCacheItems - 15
hashes, headers, blocks, receipts := tester.makeChain(targetBlocks, 0, tester.genesis, nil, false)
for i := 0; i < targetPeers; i++ {
id := fmt.Sprintf("peer #%d", i)
- tester.newPeer(id, protocol, hashes[i*blockCacheLimit:], headers, blocks, receipts)
+ tester.newPeer(id, protocol, hashes[i*blockCacheItems:], headers, blocks, receipts)
}
if err := tester.sync("peer #0", nil, mode); err != nil {
t.Fatalf("failed to synchronise blocks: %v", err)
@@ -1045,7 +1034,7 @@ func testMultiProtoSync(t *testing.T, protocol int, mode SyncMode) {
defer tester.terminate()
// Create a small enough block chain to download
- targetBlocks := blockCacheLimit - 15
+ targetBlocks := blockCacheItems - 15
hashes, headers, blocks, receipts := tester.makeChain(targetBlocks, 0, tester.genesis, nil, false)
// Create peers of every type
@@ -1084,7 +1073,7 @@ func testEmptyShortCircuit(t *testing.T, protocol int, mode SyncMode) {
defer tester.terminate()
// Create a block chain to download
- targetBlocks := 2*blockCacheLimit - 15
+ targetBlocks := 2*blockCacheItems - 15
hashes, headers, blocks, receipts := tester.makeChain(targetBlocks, 0, tester.genesis, nil, false)
tester.newPeer("peer", protocol, hashes, headers, blocks, receipts)
@@ -1110,8 +1099,8 @@ func testEmptyShortCircuit(t *testing.T, protocol int, mode SyncMode) {
bodiesNeeded++
}
}
- for hash, receipt := range receipts {
- if mode == FastSync && len(receipt) > 0 && headers[hash].Number.Uint64() <= tester.downloader.queue.fastSyncPivot {
+ for _, receipt := range receipts {
+ if mode == FastSync && len(receipt) > 0 {
receiptsNeeded++
}
}
@@ -1139,7 +1128,7 @@ func testMissingHeaderAttack(t *testing.T, protocol int, mode SyncMode) {
defer tester.terminate()
// Create a small enough block chain to download
- targetBlocks := blockCacheLimit - 15
+ targetBlocks := blockCacheItems - 15
hashes, headers, blocks, receipts := tester.makeChain(targetBlocks, 0, tester.genesis, nil, false)
// Attempt a full sync with an attacker feeding gapped headers
@@ -1174,7 +1163,7 @@ func testShiftedHeaderAttack(t *testing.T, protocol int, mode SyncMode) {
defer tester.terminate()
// Create a small enough block chain to download
- targetBlocks := blockCacheLimit - 15
+ targetBlocks := blockCacheItems - 15
hashes, headers, blocks, receipts := tester.makeChain(targetBlocks, 0, tester.genesis, nil, false)
// Attempt a full sync with an attacker feeding shifted headers
@@ -1208,7 +1197,7 @@ func testInvalidHeaderRollback(t *testing.T, protocol int, mode SyncMode) {
defer tester.terminate()
// Create a small enough block chain to download
- targetBlocks := 3*fsHeaderSafetyNet + fsPivotInterval + fsMinFullBlocks
+ targetBlocks := 3*fsHeaderSafetyNet + 256 + fsMinFullBlocks
hashes, headers, blocks, receipts := tester.makeChain(targetBlocks, 0, tester.genesis, nil, false)
// Attempt to sync with an attacker that feeds junk during the fast sync phase.
@@ -1248,7 +1237,6 @@ func testInvalidHeaderRollback(t *testing.T, protocol int, mode SyncMode) {
tester.newPeer("withhold-attack", protocol, hashes, headers, blocks, receipts)
missing = 3*fsHeaderSafetyNet + MaxHeaderFetch + 1
- tester.downloader.fsPivotFails = 0
tester.downloader.syncInitHook = func(uint64, uint64) {
for i := missing; i <= len(hashes); i++ {
delete(tester.peerHeaders["withhold-attack"], hashes[len(hashes)-i])
@@ -1267,8 +1255,6 @@ func testInvalidHeaderRollback(t *testing.T, protocol int, mode SyncMode) {
t.Errorf("fast sync pivot block #%d not rolled back", head)
}
}
- tester.downloader.fsPivotFails = fsCriticalTrials
-
// Synchronise with the valid peer and make sure sync succeeds. Since the last
// rollback should also disable fast syncing for this process, verify that we
// did a fresh full sync. Note, we can't assert anything about the receipts
@@ -1383,7 +1369,7 @@ func testSyncProgress(t *testing.T, protocol int, mode SyncMode) {
defer tester.terminate()
// Create a small enough block chain to download
- targetBlocks := blockCacheLimit - 15
+ targetBlocks := blockCacheItems - 15
hashes, headers, blocks, receipts := tester.makeChain(targetBlocks, 0, tester.genesis, nil, false)
// Set a sync init hook to catch progress changes
@@ -1532,7 +1518,7 @@ func testFailedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
defer tester.terminate()
// Create a small enough block chain to download
- targetBlocks := blockCacheLimit - 15
+ targetBlocks := blockCacheItems - 15
hashes, headers, blocks, receipts := tester.makeChain(targetBlocks, 0, tester.genesis, nil, false)
// Set a sync init hook to catch progress changes
@@ -1609,7 +1595,7 @@ func testFakedSyncProgress(t *testing.T, protocol int, mode SyncMode) {
defer tester.terminate()
// Create a small block chain
- targetBlocks := blockCacheLimit - 15
+ targetBlocks := blockCacheItems - 15
hashes, headers, blocks, receipts := tester.makeChain(targetBlocks+3, 0, tester.genesis, nil, false)
// Set a sync init hook to catch progress changes
@@ -1697,6 +1683,7 @@ func TestDeliverHeadersHang(t *testing.T) {
type floodingTestPeer struct {
peer Peer
tester *downloadTester
+ pend sync.WaitGroup
}
func (ftp *floodingTestPeer) Head() (common.Hash, *big.Int) { return ftp.peer.Head() }
@@ -1717,9 +1704,12 @@ func (ftp *floodingTestPeer) RequestHeadersByNumber(from uint64, count, skip int
deliveriesDone := make(chan struct{}, 500)
for i := 0; i < cap(deliveriesDone); i++ {
peer := fmt.Sprintf("fake-peer%d", i)
+ ftp.pend.Add(1)
+
go func() {
ftp.tester.downloader.DeliverHeaders(peer, []*types.Header{{}, {}, {}, {}})
deliveriesDone <- struct{}{}
+ ftp.pend.Done()
}()
}
// Deliver the actual requested headers.
@@ -1751,110 +1741,15 @@ func testDeliverHeadersHang(t *testing.T, protocol int, mode SyncMode) {
// Whenever the downloader requests headers, flood it with
// a lot of unrequested header deliveries.
tester.downloader.peers.peers["peer"].peer = &floodingTestPeer{
- tester.downloader.peers.peers["peer"].peer,
- tester,
+ peer: tester.downloader.peers.peers["peer"].peer,
+ tester: tester,
}
if err := tester.sync("peer", nil, mode); err != nil {
- t.Errorf("sync failed: %v", err)
+ t.Errorf("test %d: sync failed: %v", i, err)
}
tester.terminate()
- }
-}
-// Tests that if fast sync aborts in the critical section, it can restart a few
-// times before giving up.
-// We use data driven subtests to manage this so that it will be parallel on its own
-// and not with the other tests, avoiding intermittent failures.
-func TestFastCriticalRestarts(t *testing.T) {
- testCases := []struct {
- protocol int
- progress bool
- }{
- {63, false},
- {64, false},
- {63, true},
- {64, true},
- }
- for _, tc := range testCases {
- t.Run(fmt.Sprintf("protocol %d progress %v", tc.protocol, tc.progress), func(t *testing.T) {
- testFastCriticalRestarts(t, tc.protocol, tc.progress)
- })
- }
-}
-
-func testFastCriticalRestarts(t *testing.T, protocol int, progress bool) {
- t.Parallel()
-
- tester := newTester()
- defer tester.terminate()
-
- // Create a large enough blockchin to actually fast sync on
- targetBlocks := fsMinFullBlocks + 2*fsPivotInterval - 15
- hashes, headers, blocks, receipts := tester.makeChain(targetBlocks, 0, tester.genesis, nil, false)
-
- // Create a tester peer with a critical section header missing (force failures)
- tester.newPeer("peer", protocol, hashes, headers, blocks, receipts)
- delete(tester.peerHeaders["peer"], hashes[fsMinFullBlocks-1])
- tester.downloader.dropPeer = func(id string) {} // We reuse the same "faulty" peer throughout the test
-
- // Remove all possible pivot state roots and slow down replies (test failure resets later)
- for i := 0; i < fsPivotInterval; i++ {
- tester.peerMissingStates["peer"][headers[hashes[fsMinFullBlocks+i]].Root] = true
- }
- (tester.downloader.peers.peers["peer"].peer).(*downloadTesterPeer).setDelay(500 * time.Millisecond) // Enough to reach the critical section
-
- // Synchronise with the peer a few times and make sure they fail until the retry limit
- for i := 0; i < int(fsCriticalTrials)-1; i++ {
- // Attempt a sync and ensure it fails properly
- if err := tester.sync("peer", nil, FastSync); err == nil {
- t.Fatalf("failing fast sync succeeded: %v", err)
- }
- time.Sleep(150 * time.Millisecond) // Make sure no in-flight requests remain
-
- // If it's the first failure, pivot should be locked => reenable all others to detect pivot changes
- if i == 0 {
- time.Sleep(150 * time.Millisecond) // Make sure no in-flight requests remain
- if tester.downloader.fsPivotLock == nil {
- time.Sleep(400 * time.Millisecond) // Make sure the first huge timeout expires too
- t.Fatalf("pivot block not locked in after critical section failure")
- }
- tester.lock.Lock()
- tester.peerHeaders["peer"][hashes[fsMinFullBlocks-1]] = headers[hashes[fsMinFullBlocks-1]]
- tester.peerMissingStates["peer"] = map[common.Hash]bool{tester.downloader.fsPivotLock.Root: true}
- (tester.downloader.peers.peers["peer"].peer).(*downloadTesterPeer).setDelay(0)
- tester.lock.Unlock()
- }
- }
- // Return all nodes if we're testing fast sync progression
- if progress {
- tester.lock.Lock()
- tester.peerMissingStates["peer"] = map[common.Hash]bool{}
- tester.lock.Unlock()
-
- if err := tester.sync("peer", nil, FastSync); err != nil {
- t.Fatalf("failed to synchronise blocks in progressed fast sync: %v", err)
- }
- time.Sleep(150 * time.Millisecond) // Make sure no in-flight requests remain
-
- if fails := atomic.LoadUint32(&tester.downloader.fsPivotFails); fails != 1 {
- t.Fatalf("progressed pivot trial count mismatch: have %v, want %v", fails, 1)
- }
- assertOwnChain(t, tester, targetBlocks+1)
- } else {
- if err := tester.sync("peer", nil, FastSync); err == nil {
- t.Fatalf("succeeded to synchronise blocks in failed fast sync")
- }
- time.Sleep(150 * time.Millisecond) // Make sure no in-flight requests remain
-
- if fails := atomic.LoadUint32(&tester.downloader.fsPivotFails); fails != fsCriticalTrials {
- t.Fatalf("failed pivot trial count mismatch: have %v, want %v", fails, fsCriticalTrials)
- }
- }
- // Retry limit exhausted, downloader will switch to full sync, should succeed
- if err := tester.sync("peer", nil, FastSync); err != nil {
- t.Fatalf("failed to synchronise blocks in slow sync: %v", err)
+ // Flush all goroutines to prevent messing with subsequent tests
+ tester.downloader.peers.peers["peer"].peer.(*floodingTestPeer).pend.Wait()
}
- // Note, we can't assert the chain here because the test asserter assumes sync
- // completed using a single mode of operation, whereas fast-then-slow can result
- // in arbitrary intermediate state that's not cleanly verifiable.
}
diff --git a/eth/downloader/queue.go b/eth/downloader/queue.go
index 6926f1d8c..a1a70e46e 100644
--- a/eth/downloader/queue.go
+++ b/eth/downloader/queue.go
@@ -32,7 +32,11 @@ import (
"gopkg.in/karalabe/cookiejar.v2/collections/prque"
)
-var blockCacheLimit = 8192 // Maximum number of blocks to cache before throttling the download
+var (
+ blockCacheItems = 8192 // Maximum number of blocks to cache before throttling the download
+ blockCacheMemory = 64 * 1024 * 1024 // Maximum amount of memory to use for block caching
+ blockCacheSizeWeight = 0.1 // Multiplier to approximate the average block size based on past ones
+)
var (
errNoFetchesPending = errors.New("no fetches pending")
@@ -41,17 +45,17 @@ var (
// fetchRequest is a currently running data retrieval operation.
type fetchRequest struct {
- Peer *peerConnection // Peer to which the request was sent
- From uint64 // [eth/62] Requested chain element index (used for skeleton fills only)
- Hashes map[common.Hash]int // [eth/61] Requested hashes with their insertion index (priority)
- Headers []*types.Header // [eth/62] Requested headers, sorted by request order
- Time time.Time // Time when the request was made
+ Peer *peerConnection // Peer to which the request was sent
+ From uint64 // [eth/62] Requested chain element index (used for skeleton fills only)
+ Headers []*types.Header // [eth/62] Requested headers, sorted by request order
+ Time time.Time // Time when the request was made
}
// fetchResult is a struct collecting partial results from data fetchers until
// all outstanding pieces complete and the result as a whole can be processed.
type fetchResult struct {
- Pending int // Number of data fetches still pending
+ Pending int // Number of data fetches still pending
+ Hash common.Hash // Hash of the header to prevent recalculating
Header *types.Header
Uncles []*types.Header
@@ -61,12 +65,10 @@ type fetchResult struct {
// queue represents hashes that are either need fetching or are being fetched
type queue struct {
- mode SyncMode // Synchronisation mode to decide on the block parts to schedule for fetching
- fastSyncPivot uint64 // Block number where the fast sync pivots into archive synchronisation mode
-
- headerHead common.Hash // [eth/62] Hash of the last queued header to verify order
+ mode SyncMode // Synchronisation mode to decide on the block parts to schedule for fetching
// Headers are "special", they download in batches, supported by a skeleton chain
+ headerHead common.Hash // [eth/62] Hash of the last queued header to verify order
headerTaskPool map[uint64]*types.Header // [eth/62] Pending header retrieval tasks, mapping starting indexes to skeleton headers
headerTaskQueue *prque.Prque // [eth/62] Priority queue of the skeleton indexes to fetch the filling headers for
headerPeerMiss map[string]map[uint64]struct{} // [eth/62] Set of per-peer header batches known to be unavailable
@@ -87,8 +89,9 @@ type queue struct {
receiptPendPool map[string]*fetchRequest // [eth/63] Currently pending receipt retrieval operations
receiptDonePool map[common.Hash]struct{} // [eth/63] Set of the completed receipt fetches
- resultCache []*fetchResult // Downloaded but not yet delivered fetch results
- resultOffset uint64 // Offset of the first cached fetch result in the block chain
+ resultCache []*fetchResult // Downloaded but not yet delivered fetch results
+ resultOffset uint64 // Offset of the first cached fetch result in the block chain
+ resultSize common.StorageSize // Approximate size of a block (exponential moving average)
lock *sync.Mutex
active *sync.Cond
@@ -109,7 +112,7 @@ func newQueue() *queue {
receiptTaskQueue: prque.New(),
receiptPendPool: make(map[string]*fetchRequest),
receiptDonePool: make(map[common.Hash]struct{}),
- resultCache: make([]*fetchResult, blockCacheLimit),
+ resultCache: make([]*fetchResult, blockCacheItems),
active: sync.NewCond(lock),
lock: lock,
}
@@ -122,10 +125,8 @@ func (q *queue) Reset() {
q.closed = false
q.mode = FullSync
- q.fastSyncPivot = 0
q.headerHead = common.Hash{}
-
q.headerPendPool = make(map[string]*fetchRequest)
q.blockTaskPool = make(map[common.Hash]*types.Header)
@@ -138,7 +139,7 @@ func (q *queue) Reset() {
q.receiptPendPool = make(map[string]*fetchRequest)
q.receiptDonePool = make(map[common.Hash]struct{})
- q.resultCache = make([]*fetchResult, blockCacheLimit)
+ q.resultCache = make([]*fetchResult, blockCacheItems)
q.resultOffset = 0
}
@@ -214,27 +215,13 @@ func (q *queue) Idle() bool {
return (queued + pending + cached) == 0
}
-// FastSyncPivot retrieves the currently used fast sync pivot point.
-func (q *queue) FastSyncPivot() uint64 {
- q.lock.Lock()
- defer q.lock.Unlock()
-
- return q.fastSyncPivot
-}
-
// ShouldThrottleBlocks checks if the download should be throttled (active block (body)
// fetches exceed block cache).
func (q *queue) ShouldThrottleBlocks() bool {
q.lock.Lock()
defer q.lock.Unlock()
- // Calculate the currently in-flight block (body) requests
- pending := 0
- for _, request := range q.blockPendPool {
- pending += len(request.Hashes) + len(request.Headers)
- }
- // Throttle if more blocks (bodies) are in-flight than free space in the cache
- return pending >= len(q.resultCache)-len(q.blockDonePool)
+ return q.resultSlots(q.blockPendPool, q.blockDonePool) <= 0
}
// ShouldThrottleReceipts checks if the download should be throttled (active receipt
@@ -243,13 +230,39 @@ func (q *queue) ShouldThrottleReceipts() bool {
q.lock.Lock()
defer q.lock.Unlock()
- // Calculate the currently in-flight receipt requests
+ return q.resultSlots(q.receiptPendPool, q.receiptDonePool) <= 0
+}
+
+// resultSlots calculates the number of results slots available for requests
+// whilst adhering to both the item and the memory limit too of the results
+// cache.
+func (q *queue) resultSlots(pendPool map[string]*fetchRequest, donePool map[common.Hash]struct{}) int {
+ // Calculate the maximum length capped by the memory limit
+ limit := len(q.resultCache)
+ if common.StorageSize(len(q.resultCache))*q.resultSize > common.StorageSize(blockCacheMemory) {
+ limit = int((common.StorageSize(blockCacheMemory) + q.resultSize - 1) / q.resultSize)
+ }
+ // Calculate the number of slots already finished
+ finished := 0
+ for _, result := range q.resultCache[:limit] {
+ if result == nil {
+ break
+ }
+ if _, ok := donePool[result.Hash]; ok {
+ finished++
+ }
+ }
+ // Calculate the number of slots currently downloading
pending := 0
- for _, request := range q.receiptPendPool {
- pending += len(request.Headers)
+ for _, request := range pendPool {
+ for _, header := range request.Headers {
+ if header.Number.Uint64() < q.resultOffset+uint64(limit) {
+ pending++
+ }
+ }
}
- // Throttle if more receipts are in-flight than free space in the cache
- return pending >= len(q.resultCache)-len(q.receiptDonePool)
+ // Return the free slots to distribute
+ return limit - finished - pending
}
// ScheduleSkeleton adds a batch of header retrieval tasks to the queue to fill
@@ -323,8 +336,7 @@ func (q *queue) Schedule(headers []*types.Header, from uint64) []*types.Header {
q.blockTaskPool[hash] = header
q.blockTaskQueue.Push(header, -float32(header.Number.Uint64()))
- if q.mode == FastSync && header.Number.Uint64() <= q.fastSyncPivot {
- // Fast phase of the fast sync, retrieve receipts too
+ if q.mode == FastSync {
q.receiptTaskPool[hash] = header
q.receiptTaskQueue.Push(header, -float32(header.Number.Uint64()))
}
@@ -335,18 +347,25 @@ func (q *queue) Schedule(headers []*types.Header, from uint64) []*types.Header {
return inserts
}
-// WaitResults retrieves and permanently removes a batch of fetch
-// results from the cache. the result slice will be empty if the queue
-// has been closed.
-func (q *queue) WaitResults() []*fetchResult {
+// Results retrieves and permanently removes a batch of fetch results from
+// the cache. the result slice will be empty if the queue has been closed.
+func (q *queue) Results(block bool) []*fetchResult {
q.lock.Lock()
defer q.lock.Unlock()
+ // Count the number of items available for processing
nproc := q.countProcessableItems()
for nproc == 0 && !q.closed {
+ if !block {
+ return nil
+ }
q.active.Wait()
nproc = q.countProcessableItems()
}
+ // Since we have a batch limit, don't pull more into "dangling" memory
+ if nproc > maxResultsProcess {
+ nproc = maxResultsProcess
+ }
results := make([]*fetchResult, nproc)
copy(results, q.resultCache[:nproc])
if len(results) > 0 {
@@ -363,6 +382,21 @@ func (q *queue) WaitResults() []*fetchResult {
}
// Advance the expected block number of the first cache entry.
q.resultOffset += uint64(nproc)
+
+ // Recalculate the result item weights to prevent memory exhaustion
+ for _, result := range results {
+ size := result.Header.Size()
+ for _, uncle := range result.Uncles {
+ size += uncle.Size()
+ }
+ for _, receipt := range result.Receipts {
+ size += receipt.Size()
+ }
+ for _, tx := range result.Transactions {
+ size += tx.Size()
+ }
+ q.resultSize = common.StorageSize(blockCacheSizeWeight)*size + (1-common.StorageSize(blockCacheSizeWeight))*q.resultSize
+ }
}
return results
}
@@ -370,21 +404,9 @@ func (q *queue) WaitResults() []*fetchResult {
// countProcessableItems counts the processable items.
func (q *queue) countProcessableItems() int {
for i, result := range q.resultCache {
- // Don't process incomplete or unavailable items.
if result == nil || result.Pending > 0 {
return i
}
- // Stop before processing the pivot block to ensure that
- // resultCache has space for fsHeaderForceVerify items. Not
- // doing this could leave us unable to download the required
- // amount of headers.
- if q.mode == FastSync && result.Header.Number.Uint64() == q.fastSyncPivot {
- for j := 0; j < fsHeaderForceVerify; j++ {
- if i+j+1 >= len(q.resultCache) || q.resultCache[i+j+1] == nil {
- return i
- }
- }
- }
}
return len(q.resultCache)
}
@@ -473,10 +495,8 @@ func (q *queue) reserveHeaders(p *peerConnection, count int, taskPool map[common
return nil, false, nil
}
// Calculate an upper limit on the items we might fetch (i.e. throttling)
- space := len(q.resultCache) - len(donePool)
- for _, request := range pendPool {
- space -= len(request.Headers)
- }
+ space := q.resultSlots(pendPool, donePool)
+
// Retrieve a batch of tasks, skipping previously failed ones
send := make([]*types.Header, 0, count)
skip := make([]*types.Header, 0)
@@ -484,6 +504,7 @@ func (q *queue) reserveHeaders(p *peerConnection, count int, taskPool map[common
progress := false
for proc := 0; proc < space && len(send) < count && !taskQueue.Empty(); proc++ {
header := taskQueue.PopItem().(*types.Header)
+ hash := header.Hash()
// If we're the first to request this task, initialise the result container
index := int(header.Number.Int64() - int64(q.resultOffset))
@@ -493,18 +514,19 @@ func (q *queue) reserveHeaders(p *peerConnection, count int, taskPool map[common
}
if q.resultCache[index] == nil {
components := 1
- if q.mode == FastSync && header.Number.Uint64() <= q.fastSyncPivot {
+ if q.mode == FastSync {
components = 2
}
q.resultCache[index] = &fetchResult{
Pending: components,
+ Hash: hash,
Header: header,
}
}
// If this fetch task is a noop, skip this fetch operation
if isNoop(header) {
- donePool[header.Hash()] = struct{}{}
- delete(taskPool, header.Hash())
+ donePool[hash] = struct{}{}
+ delete(taskPool, hash)
space, proc = space-1, proc-1
q.resultCache[index].Pending--
@@ -512,7 +534,7 @@ func (q *queue) reserveHeaders(p *peerConnection, count int, taskPool map[common
continue
}
// Otherwise unless the peer is known not to have the data, add to the retrieve list
- if p.Lacks(header.Hash()) {
+ if p.Lacks(hash) {
skip = append(skip, header)
} else {
send = append(send, header)
@@ -565,9 +587,6 @@ func (q *queue) cancel(request *fetchRequest, taskQueue *prque.Prque, pendPool m
if request.From > 0 {
taskQueue.Push(request.From, -float32(request.From))
}
- for hash, index := range request.Hashes {
- taskQueue.Push(hash, float32(index))
- }
for _, header := range request.Headers {
taskQueue.Push(header, -float32(header.Number.Uint64()))
}
@@ -640,18 +659,11 @@ func (q *queue) expire(timeout time.Duration, pendPool map[string]*fetchRequest,
if request.From > 0 {
taskQueue.Push(request.From, -float32(request.From))
}
- for hash, index := range request.Hashes {
- taskQueue.Push(hash, float32(index))
- }
for _, header := range request.Headers {
taskQueue.Push(header, -float32(header.Number.Uint64()))
}
// Add the peer to the expiry report along the the number of failed requests
- expirations := len(request.Hashes)
- if expirations < len(request.Headers) {
- expirations = len(request.Headers)
- }
- expiries[id] = expirations
+ expiries[id] = len(request.Headers)
}
}
// Remove the expired requests from the pending pool
@@ -828,14 +840,16 @@ func (q *queue) deliver(id string, taskPool map[common.Hash]*types.Header, taskQ
failure = err
break
}
- donePool[header.Hash()] = struct{}{}
+ hash := header.Hash()
+
+ donePool[hash] = struct{}{}
q.resultCache[index].Pending--
useful = true
accepted++
// Clean up a successful fetch
request.Headers[i] = nil
- delete(taskPool, header.Hash())
+ delete(taskPool, hash)
}
// Return all failed or missing fetches to the queue
for _, header := range request.Headers {
@@ -860,7 +874,7 @@ func (q *queue) deliver(id string, taskPool map[common.Hash]*types.Header, taskQ
// Prepare configures the result cache to allow accepting and caching inbound
// fetch results.
-func (q *queue) Prepare(offset uint64, mode SyncMode, pivot uint64, head *types.Header) {
+func (q *queue) Prepare(offset uint64, mode SyncMode) {
q.lock.Lock()
defer q.lock.Unlock()
@@ -868,6 +882,5 @@ func (q *queue) Prepare(offset uint64, mode SyncMode, pivot uint64, head *types.
if q.resultOffset < offset {
q.resultOffset = offset
}
- q.fastSyncPivot = pivot
q.mode = mode
}
diff --git a/eth/downloader/statesync.go b/eth/downloader/statesync.go
index a0b05c9be..9cc65a208 100644
--- a/eth/downloader/statesync.go
+++ b/eth/downloader/statesync.go
@@ -20,7 +20,6 @@ import (
"fmt"
"hash"
"sync"
- "sync/atomic"
"time"
"github.com/ethereum/go-ethereum/common"
@@ -132,7 +131,10 @@ func (d *Downloader) runStateSync(s *stateSync) *stateSync {
// Send the next finished request to the current sync:
case deliverReqCh <- deliverReq:
- finished = append(finished[:0], finished[1:]...)
+ // Shift out the first request, but also set the emptied slot to nil for GC
+ copy(finished, finished[1:])
+ finished[len(finished)-1] = nil
+ finished = finished[:len(finished)-1]
// Handle incoming state packs:
case pack := <-d.stateCh:
@@ -291,6 +293,9 @@ func (s *stateSync) loop() error {
case <-s.cancel:
return errCancelStateFetch
+ case <-s.d.cancelCh:
+ return errCancelStateFetch
+
case req := <-s.deliver:
// Response, disconnect or timeout triggered, drop the peer if stalling
log.Trace("Received node data response", "peer", req.peer.id, "count", len(req.response), "dropped", req.dropped, "timeout", !req.dropped && req.timedOut())
@@ -301,15 +306,11 @@ func (s *stateSync) loop() error {
s.d.dropPeer(req.peer.id)
}
// Process all the received blobs and check for stale delivery
- stale, err := s.process(req)
- if err != nil {
+ if err := s.process(req); err != nil {
log.Warn("Node data write error", "err", err)
return err
}
- // The the delivery contains requested data, mark the node idle (otherwise it's a timed out delivery)
- if !stale {
- req.peer.SetNodeDataIdle(len(req.response))
- }
+ req.peer.SetNodeDataIdle(len(req.response))
}
}
return s.commit(true)
@@ -349,6 +350,7 @@ func (s *stateSync) assignTasks() {
case s.d.trackStateReq <- req:
req.peer.FetchNodeData(req.items)
case <-s.cancel:
+ case <-s.d.cancelCh:
}
}
}
@@ -387,7 +389,7 @@ func (s *stateSync) fillTasks(n int, req *stateReq) {
// process iterates over a batch of delivered state data, injecting each item
// into a running state sync, re-queuing any items that were requested but not
// delivered.
-func (s *stateSync) process(req *stateReq) (bool, error) {
+func (s *stateSync) process(req *stateReq) error {
// Collect processing stats and update progress if valid data was received
duplicate, unexpected := 0, 0
@@ -398,7 +400,7 @@ func (s *stateSync) process(req *stateReq) (bool, error) {
}(time.Now())
// Iterate over all the delivered data and inject one-by-one into the trie
- progress, stale := false, len(req.response) > 0
+ progress := false
for _, blob := range req.response {
prog, hash, err := s.processNodeData(blob)
@@ -412,20 +414,12 @@ func (s *stateSync) process(req *stateReq) (bool, error) {
case trie.ErrAlreadyProcessed:
duplicate++
default:
- return stale, fmt.Errorf("invalid state node %s: %v", hash.TerminalString(), err)
+ return fmt.Errorf("invalid state node %s: %v", hash.TerminalString(), err)
}
- // If the node delivered a requested item, mark the delivery non-stale
if _, ok := req.tasks[hash]; ok {
delete(req.tasks, hash)
- stale = false
}
}
- // If we're inside the critical section, reset fail counter since we progressed.
- if progress && atomic.LoadUint32(&s.d.fsPivotFails) > 1 {
- log.Trace("Fast-sync progressed, resetting fail counter", "previous", atomic.LoadUint32(&s.d.fsPivotFails))
- atomic.StoreUint32(&s.d.fsPivotFails, 1) // Don't ever reset to 0, as that will unlock the pivot block
- }
-
// Put unfulfilled tasks back into the retry queue
npeers := s.d.peers.Len()
for hash, task := range req.tasks {
@@ -438,12 +432,12 @@ func (s *stateSync) process(req *stateReq) (bool, error) {
// If we've requested the node too many times already, it may be a malicious
// sync where nobody has the right data. Abort.
if len(task.attempts) >= npeers {
- return stale, fmt.Errorf("state node %s failed with all peers (%d tries, %d peers)", hash.TerminalString(), len(task.attempts), npeers)
+ return fmt.Errorf("state node %s failed with all peers (%d tries, %d peers)", hash.TerminalString(), len(task.attempts), npeers)
}
// Missing item, place into the retry queue.
s.tasks[hash] = task
}
- return stale, nil
+ return nil
}
// processNodeData tries to inject a trie node data blob delivered from a remote
diff --git a/eth/fetcher/fetcher_test.go b/eth/fetcher/fetcher_test.go
index e6a639417..9d53b98b6 100644
--- a/eth/fetcher/fetcher_test.go
+++ b/eth/fetcher/fetcher_test.go
@@ -52,7 +52,7 @@ func makeChain(n int, seed byte, parent *types.Block) ([]common.Hash, map[common
// If the block number is multiple of 3, send a bonus transaction to the miner
if parent == genesis && i%3 == 0 {
signer := types.MakeSigner(params.TestChainConfig, block.Number())
- tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), new(big.Int).SetUint64(params.TxGas), nil, nil), signer, testKey)
+ tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, nil, nil), signer, testKey)
if err != nil {
panic(err)
}
diff --git a/eth/filters/api.go b/eth/filters/api.go
index 03c1d6afc..406c9442e 100644
--- a/eth/filters/api.go
+++ b/eth/filters/api.go
@@ -25,6 +25,7 @@ import (
"sync"
"time"
+ ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
@@ -240,7 +241,7 @@ func (api *PublicFilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc
matchedLogs = make(chan []*types.Log)
)
- logsSub, err := api.events.SubscribeLogs(crit, matchedLogs)
+ logsSub, err := api.events.SubscribeLogs(ethereum.FilterQuery(crit), matchedLogs)
if err != nil {
return nil, err
}
@@ -267,6 +268,8 @@ func (api *PublicFilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc
}
// FilterCriteria represents a request to create a new filter.
+//
+// TODO(karalabe): Kill this in favor of ethereum.FilterQuery.
type FilterCriteria struct {
FromBlock *big.Int
ToBlock *big.Int
@@ -289,7 +292,7 @@ type FilterCriteria struct {
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newfilter
func (api *PublicFilterAPI) NewFilter(crit FilterCriteria) (rpc.ID, error) {
logs := make(chan []*types.Log)
- logsSub, err := api.events.SubscribeLogs(crit, logs)
+ logsSub, err := api.events.SubscribeLogs(ethereum.FilterQuery(crit), logs)
if err != nil {
return rpc.ID(""), err
}
diff --git a/eth/filters/filter_system.go b/eth/filters/filter_system.go
index e08cedb27..b09998f9c 100644
--- a/eth/filters/filter_system.go
+++ b/eth/filters/filter_system.go
@@ -25,6 +25,7 @@ import (
"sync"
"time"
+ ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
@@ -75,7 +76,7 @@ type subscription struct {
id rpc.ID
typ Type
created time.Time
- logsCrit FilterCriteria
+ logsCrit ethereum.FilterQuery
logs chan []*types.Log
hashes chan common.Hash
headers chan *types.Header
@@ -162,7 +163,7 @@ func (es *EventSystem) subscribe(sub *subscription) *Subscription {
// SubscribeLogs creates a subscription that will write all logs matching the
// given criteria to the given logs channel. Default value for the from and to
// block is "latest". If the fromBlock > toBlock an error is returned.
-func (es *EventSystem) SubscribeLogs(crit FilterCriteria, logs chan []*types.Log) (*Subscription, error) {
+func (es *EventSystem) SubscribeLogs(crit ethereum.FilterQuery, logs chan []*types.Log) (*Subscription, error) {
var from, to rpc.BlockNumber
if crit.FromBlock == nil {
from = rpc.LatestBlockNumber
@@ -200,7 +201,7 @@ func (es *EventSystem) SubscribeLogs(crit FilterCriteria, logs chan []*types.Log
// subscribeMinedPendingLogs creates a subscription that returned mined and
// pending logs that match the given criteria.
-func (es *EventSystem) subscribeMinedPendingLogs(crit FilterCriteria, logs chan []*types.Log) *Subscription {
+func (es *EventSystem) subscribeMinedPendingLogs(crit ethereum.FilterQuery, logs chan []*types.Log) *Subscription {
sub := &subscription{
id: rpc.NewID(),
typ: MinedAndPendingLogsSubscription,
@@ -217,7 +218,7 @@ func (es *EventSystem) subscribeMinedPendingLogs(crit FilterCriteria, logs chan
// subscribeLogs creates a subscription that will write all logs matching the
// given criteria to the given logs channel.
-func (es *EventSystem) subscribeLogs(crit FilterCriteria, logs chan []*types.Log) *Subscription {
+func (es *EventSystem) subscribeLogs(crit ethereum.FilterQuery, logs chan []*types.Log) *Subscription {
sub := &subscription{
id: rpc.NewID(),
typ: LogsSubscription,
@@ -234,7 +235,7 @@ func (es *EventSystem) subscribeLogs(crit FilterCriteria, logs chan []*types.Log
// subscribePendingLogs creates a subscription that writes transaction hashes for
// transactions that enter the transaction pool.
-func (es *EventSystem) subscribePendingLogs(crit FilterCriteria, logs chan []*types.Log) *Subscription {
+func (es *EventSystem) subscribePendingLogs(crit ethereum.FilterQuery, logs chan []*types.Log) *Subscription {
sub := &subscription{
id: rpc.NewID(),
typ: PendingLogsSubscription,
diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go
index a5025db3d..7ec3b4be7 100644
--- a/eth/filters/filter_system_test.go
+++ b/eth/filters/filter_system_test.go
@@ -25,6 +25,7 @@ import (
"testing"
"time"
+ ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
@@ -195,11 +196,11 @@ func TestPendingTxFilter(t *testing.T) {
api = NewPublicFilterAPI(backend, false)
transactions = []*types.Transaction{
- types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), new(big.Int), new(big.Int), nil),
- types.NewTransaction(1, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), new(big.Int), new(big.Int), nil),
- types.NewTransaction(2, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), new(big.Int), new(big.Int), nil),
- types.NewTransaction(3, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), new(big.Int), new(big.Int), nil),
- types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), new(big.Int), new(big.Int), nil),
+ types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
+ types.NewTransaction(1, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
+ types.NewTransaction(2, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
+ types.NewTransaction(3, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
+ types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
}
hashes []common.Hash
@@ -488,27 +489,27 @@ func TestPendingLogsSubscription(t *testing.T) {
}
testCases = []struct {
- crit FilterCriteria
+ crit ethereum.FilterQuery
expected []*types.Log
c chan []*types.Log
sub *Subscription
}{
// match all
- {FilterCriteria{}, convertLogs(allLogs), nil, nil},
+ {ethereum.FilterQuery{}, convertLogs(allLogs), nil, nil},
// match none due to no matching addresses
- {FilterCriteria{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}}, []*types.Log{}, nil, nil},
+ {ethereum.FilterQuery{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}}, []*types.Log{}, nil, nil},
// match logs based on addresses, ignore topics
- {FilterCriteria{Addresses: []common.Address{firstAddr}}, append(convertLogs(allLogs[:2]), allLogs[5].Logs[3]), nil, nil},
+ {ethereum.FilterQuery{Addresses: []common.Address{firstAddr}}, append(convertLogs(allLogs[:2]), allLogs[5].Logs[3]), nil, nil},
// match none due to no matching topics (match with address)
- {FilterCriteria{Addresses: []common.Address{secondAddr}, Topics: [][]common.Hash{{notUsedTopic}}}, []*types.Log{}, nil, nil},
+ {ethereum.FilterQuery{Addresses: []common.Address{secondAddr}, Topics: [][]common.Hash{{notUsedTopic}}}, []*types.Log{}, nil, nil},
// match logs based on addresses and topics
- {FilterCriteria{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, append(convertLogs(allLogs[3:5]), allLogs[5].Logs[0]), nil, nil},
+ {ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, append(convertLogs(allLogs[3:5]), allLogs[5].Logs[0]), nil, nil},
// match logs based on multiple addresses and "or" topics
- {FilterCriteria{Addresses: []common.Address{secondAddr, thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, append(convertLogs(allLogs[2:5]), allLogs[5].Logs[0]), nil, nil},
+ {ethereum.FilterQuery{Addresses: []common.Address{secondAddr, thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, append(convertLogs(allLogs[2:5]), allLogs[5].Logs[0]), nil, nil},
// block numbers are ignored for filters created with New***Filter, these return all logs that match the given criteria when the state changes
- {FilterCriteria{Addresses: []common.Address{firstAddr}, FromBlock: big.NewInt(2), ToBlock: big.NewInt(3)}, append(convertLogs(allLogs[:2]), allLogs[5].Logs[3]), nil, nil},
+ {ethereum.FilterQuery{Addresses: []common.Address{firstAddr}, FromBlock: big.NewInt(2), ToBlock: big.NewInt(3)}, append(convertLogs(allLogs[:2]), allLogs[5].Logs[3]), nil, nil},
// multiple pending logs, should match only 2 topics from the logs in block 5
- {FilterCriteria{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, fourthTopic}}}, []*types.Log{allLogs[5].Logs[0], allLogs[5].Logs[2]}, nil, nil},
+ {ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, fourthTopic}}}, []*types.Log{allLogs[5].Logs[0], allLogs[5].Logs[2]}, nil, nil},
}
)
diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go
index 729d0afc8..0018142c4 100644
--- a/eth/filters/filter_test.go
+++ b/eth/filters/filter_test.go
@@ -34,7 +34,7 @@ import (
)
func makeReceipt(addr common.Address) *types.Receipt {
- receipt := types.NewReceipt(nil, false, new(big.Int))
+ receipt := types.NewReceipt(nil, false, 0)
receipt.Logs = []*types.Log{
{Address: addr},
}
@@ -136,7 +136,7 @@ func TestFilters(t *testing.T) {
chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) {
switch i {
case 1:
- receipt := types.NewReceipt(nil, false, new(big.Int))
+ receipt := types.NewReceipt(nil, false, 0)
receipt.Logs = []*types.Log{
{
Address: addr,
@@ -145,7 +145,7 @@ func TestFilters(t *testing.T) {
}
gen.AddUncheckedReceipt(receipt)
case 2:
- receipt := types.NewReceipt(nil, false, new(big.Int))
+ receipt := types.NewReceipt(nil, false, 0)
receipt.Logs = []*types.Log{
{
Address: addr,
@@ -154,7 +154,7 @@ func TestFilters(t *testing.T) {
}
gen.AddUncheckedReceipt(receipt)
case 998:
- receipt := types.NewReceipt(nil, false, new(big.Int))
+ receipt := types.NewReceipt(nil, false, 0)
receipt.Logs = []*types.Log{
{
Address: addr,
@@ -163,7 +163,7 @@ func TestFilters(t *testing.T) {
}
gen.AddUncheckedReceipt(receipt)
case 999:
- receipt := types.NewReceipt(nil, false, new(big.Int))
+ receipt := types.NewReceipt(nil, false, 0)
receipt.Logs = []*types.Log{
{
Address: addr,
diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go
index c662348e1..54325692c 100644
--- a/eth/gasprice/gasprice.go
+++ b/eth/gasprice/gasprice.go
@@ -23,6 +23,7 @@ import (
"sync"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
@@ -101,9 +102,9 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
ch := make(chan getBlockPricesResult, gpo.checkBlocks)
sent := 0
exp := 0
- var txPrices []*big.Int
+ var blockPrices []*big.Int
for sent < gpo.checkBlocks && blockNum > 0 {
- go gpo.getBlockPrices(ctx, blockNum, ch)
+ go gpo.getBlockPrices(ctx, types.MakeSigner(gpo.backend.ChainConfig(), big.NewInt(int64(blockNum))), blockNum, ch)
sent++
exp++
blockNum--
@@ -115,8 +116,8 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
return lastPrice, res.err
}
exp--
- if len(res.prices) > 0 {
- txPrices = append(txPrices, res.prices...)
+ if res.price != nil {
+ blockPrices = append(blockPrices, res.price)
continue
}
if maxEmpty > 0 {
@@ -124,16 +125,16 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
continue
}
if blockNum > 0 && sent < gpo.maxBlocks {
- go gpo.getBlockPrices(ctx, blockNum, ch)
+ go gpo.getBlockPrices(ctx, types.MakeSigner(gpo.backend.ChainConfig(), big.NewInt(int64(blockNum))), blockNum, ch)
sent++
exp++
blockNum--
}
}
price := lastPrice
- if len(txPrices) > 0 {
- sort.Sort(bigIntArray(txPrices))
- price = txPrices[(len(txPrices)-1)*gpo.percentile/100]
+ if len(blockPrices) > 0 {
+ sort.Sort(bigIntArray(blockPrices))
+ price = blockPrices[(len(blockPrices)-1)*gpo.percentile/100]
}
if price.Cmp(maxPrice) > 0 {
price = new(big.Int).Set(maxPrice)
@@ -147,24 +148,38 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
}
type getBlockPricesResult struct {
- prices []*big.Int
- err error
+ price *big.Int
+ err error
}
-// getLowestPrice calculates the lowest transaction gas price in a given block
+type transactionsByGasPrice []*types.Transaction
+
+func (t transactionsByGasPrice) Len() int { return len(t) }
+func (t transactionsByGasPrice) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
+func (t transactionsByGasPrice) Less(i, j int) bool { return t[i].GasPrice().Cmp(t[j].GasPrice()) < 0 }
+
+// getBlockPrices calculates the lowest transaction gas price in a given block
// and sends it to the result channel. If the block is empty, price is nil.
-func (gpo *Oracle) getBlockPrices(ctx context.Context, blockNum uint64, ch chan getBlockPricesResult) {
+func (gpo *Oracle) getBlockPrices(ctx context.Context, signer types.Signer, blockNum uint64, ch chan getBlockPricesResult) {
block, err := gpo.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNum))
if block == nil {
ch <- getBlockPricesResult{nil, err}
return
}
- txs := block.Transactions()
- prices := make([]*big.Int, len(txs))
- for i, tx := range txs {
- prices[i] = tx.GasPrice()
+
+ blockTxs := block.Transactions()
+ txs := make([]*types.Transaction, len(blockTxs))
+ copy(txs, blockTxs)
+ sort.Sort(transactionsByGasPrice(txs))
+
+ for _, tx := range txs {
+ sender, err := types.Sender(signer, tx)
+ if err == nil && sender != block.Coinbase() {
+ ch <- getBlockPricesResult{tx.GasPrice(), nil}
+ return
+ }
}
- ch <- getBlockPricesResult{prices, nil}
+ ch <- getBlockPricesResult{nil, nil}
}
type bigIntArray []*big.Int
diff --git a/eth/gen_config.go b/eth/gen_config.go
index e2d50e1f6..4f2e82d94 100644
--- a/eth/gen_config.go
+++ b/eth/gen_config.go
@@ -13,6 +13,8 @@ import (
"github.com/ethereum/go-ethereum/eth/gasprice"
)
+var _ = (*configMarshaling)(nil)
+
func (c Config) MarshalTOML() (interface{}, error) {
type Config struct {
Genesis *core.Genesis `toml:",omitempty"`
@@ -20,7 +22,6 @@ func (c Config) MarshalTOML() (interface{}, error) {
SyncMode downloader.SyncMode
LightServ int `toml:",omitempty"`
LightPeers int `toml:",omitempty"`
- MaxPeers int `toml:"-"`
SkipBcVersionCheck bool `toml:"-"`
DatabaseHandles int `toml:"-"`
DatabaseCache int
@@ -28,17 +29,11 @@ func (c Config) MarshalTOML() (interface{}, error) {
MinerThreads int `toml:",omitempty"`
ExtraData hexutil.Bytes `toml:",omitempty"`
GasPrice *big.Int
- EthashCacheDir string
- EthashCachesInMem int
- EthashCachesOnDisk int
- EthashDatasetDir string
- EthashDatasetsInMem int
- EthashDatasetsOnDisk int
+ Ethash ethash.Config
TxPool core.TxPoolConfig
GPO gasprice.Config
EnablePreimageRecording bool
- DocRoot string `toml:"-"`
- PowMode ethash.Mode `toml:"-"`
+ DocRoot string `toml:"-"`
}
var enc Config
enc.Genesis = c.Genesis
@@ -53,17 +48,11 @@ func (c Config) MarshalTOML() (interface{}, error) {
enc.MinerThreads = c.MinerThreads
enc.ExtraData = c.ExtraData
enc.GasPrice = c.GasPrice
- enc.EthashCacheDir = c.Ethash.CacheDir
- enc.EthashCachesInMem = c.Ethash.CachesInMem
- enc.EthashCachesOnDisk = c.Ethash.CachesOnDisk
- enc.EthashDatasetDir = c.Ethash.DatasetDir
- enc.EthashDatasetsInMem = c.Ethash.DatasetsInMem
- enc.EthashDatasetsOnDisk = c.Ethash.DatasetsOnDisk
+ enc.Ethash = c.Ethash
enc.TxPool = c.TxPool
enc.GPO = c.GPO
enc.EnablePreimageRecording = c.EnablePreimageRecording
enc.DocRoot = c.DocRoot
- enc.PowMode = c.Ethash.PowMode
return &enc, nil
}
@@ -74,25 +63,18 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
SyncMode *downloader.SyncMode
LightServ *int `toml:",omitempty"`
LightPeers *int `toml:",omitempty"`
- MaxPeers *int `toml:"-"`
SkipBcVersionCheck *bool `toml:"-"`
DatabaseHandles *int `toml:"-"`
DatabaseCache *int
Etherbase *common.Address `toml:",omitempty"`
MinerThreads *int `toml:",omitempty"`
- ExtraData hexutil.Bytes `toml:",omitempty"`
+ ExtraData *hexutil.Bytes `toml:",omitempty"`
GasPrice *big.Int
- EthashCacheDir *string
- EthashCachesInMem *int
- EthashCachesOnDisk *int
- EthashDatasetDir *string
- EthashDatasetsInMem *int
- EthashDatasetsOnDisk *int
+ Ethash *ethash.Config
TxPool *core.TxPoolConfig
GPO *gasprice.Config
EnablePreimageRecording *bool
- DocRoot *string `toml:"-"`
- PowMode *ethash.Mode `toml:"-"`
+ DocRoot *string `toml:"-"`
}
var dec Config
if err := unmarshal(&dec); err != nil {
@@ -129,28 +111,13 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
c.MinerThreads = *dec.MinerThreads
}
if dec.ExtraData != nil {
- c.ExtraData = dec.ExtraData
+ c.ExtraData = *dec.ExtraData
}
if dec.GasPrice != nil {
c.GasPrice = dec.GasPrice
}
- if dec.EthashCacheDir != nil {
- c.Ethash.CacheDir = *dec.EthashCacheDir
- }
- if dec.EthashCachesInMem != nil {
- c.Ethash.CachesInMem = *dec.EthashCachesInMem
- }
- if dec.EthashCachesOnDisk != nil {
- c.Ethash.CachesOnDisk = *dec.EthashCachesOnDisk
- }
- if dec.EthashDatasetDir != nil {
- c.Ethash.DatasetDir = *dec.EthashDatasetDir
- }
- if dec.EthashDatasetsInMem != nil {
- c.Ethash.DatasetsInMem = *dec.EthashDatasetsInMem
- }
- if dec.EthashDatasetsOnDisk != nil {
- c.Ethash.DatasetsOnDisk = *dec.EthashDatasetsOnDisk
+ if dec.Ethash != nil {
+ c.Ethash = *dec.Ethash
}
if dec.TxPool != nil {
c.TxPool = *dec.TxPool
@@ -164,8 +131,5 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
if dec.DocRoot != nil {
c.DocRoot = *dec.DocRoot
}
- if dec.PowMode != nil {
- c.Ethash.PowMode = *dec.PowMode
- }
return nil
}
diff --git a/eth/handler.go b/eth/handler.go
index 31c311687..c2426544f 100644
--- a/eth/handler.go
+++ b/eth/handler.go
@@ -71,7 +71,6 @@ type ProtocolManager struct {
txpool txPool
blockchain *core.BlockChain
- chaindb ethdb.Database
chainconfig *params.ChainConfig
maxPeers int
@@ -106,7 +105,6 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne
eventMux: mux,
txpool: txpool,
blockchain: blockchain,
- chaindb: chaindb,
chainconfig: config,
peers: newPeerSet(),
newPeerCh: make(chan *peer),
@@ -257,8 +255,14 @@ func (pm *ProtocolManager) handle(p *peer) error {
p.Log().Debug("Ethereum peer connected", "name", p.Name())
// Execute the Ethereum handshake
- td, head, genesis := pm.blockchain.Status()
- if err := p.Handshake(pm.networkId, td, head, genesis); err != nil {
+ var (
+ genesis = pm.blockchain.Genesis()
+ head = pm.blockchain.CurrentHeader()
+ hash = head.Hash()
+ number = head.Number.Uint64()
+ td = pm.blockchain.GetTd(hash, number)
+ )
+ if err := p.Handshake(pm.networkId, td, hash, genesis.Hash()); err != nil {
p.Log().Debug("Ethereum handshake failed", "err", err)
return err
}
@@ -394,14 +398,14 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
case query.Reverse:
// Number based traversal towards the genesis block
if query.Origin.Number >= query.Skip+1 {
- query.Origin.Number -= (query.Skip + 1)
+ query.Origin.Number -= query.Skip + 1
} else {
unknown = true
}
case !query.Reverse:
// Number based traversal towards the leaf block
- query.Origin.Number += (query.Skip + 1)
+ query.Origin.Number += query.Skip + 1
}
}
return p.SendBlockHeaders(headers)
@@ -532,7 +536,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
return errResp(ErrDecode, "msg %v: %v", msg, err)
}
// Retrieve the requested state entry, stopping if enough was found
- if entry, err := pm.chaindb.Get(hash.Bytes()); err == nil {
+ if entry, err := pm.blockchain.TrieNode(hash); err == nil {
data = append(data, entry)
bytes += len(entry)
}
@@ -570,7 +574,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
return errResp(ErrDecode, "msg %v: %v", msg, err)
}
// Retrieve the requested block's receipts, skipping if unknown to us
- results := core.GetBlockReceipts(pm.chaindb, hash, core.GetBlockNumber(pm.chaindb, hash))
+ results := pm.blockchain.GetReceiptsByHash(hash)
if results == nil {
if header := pm.blockchain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash {
continue
diff --git a/eth/handler_test.go b/eth/handler_test.go
index ebbd83c3a..e336dfa28 100644
--- a/eth/handler_test.go
+++ b/eth/handler_test.go
@@ -37,8 +37,6 @@ import (
"github.com/ethereum/go-ethereum/params"
)
-var bigTxGas = new(big.Int).SetUint64(params.TxGas)
-
// Tests that protocol versions and modes of operations are matched up properly.
func TestProtocolCompatibility(t *testing.T) {
// Define the compatibility chart
@@ -58,7 +56,7 @@ func TestProtocolCompatibility(t *testing.T) {
for i, tt := range tests {
ProtocolVersions = []uint{tt.version}
- pm, err := newTestProtocolManager(tt.mode, 0, nil, nil)
+ pm, _, err := newTestProtocolManager(tt.mode, 0, nil, nil)
if pm != nil {
defer pm.Stop()
}
@@ -73,7 +71,7 @@ func TestGetBlockHeaders62(t *testing.T) { testGetBlockHeaders(t, 62) }
func TestGetBlockHeaders63(t *testing.T) { testGetBlockHeaders(t, 63) }
func testGetBlockHeaders(t *testing.T, protocol int) {
- pm := newTestProtocolManagerMust(t, downloader.FullSync, downloader.MaxHashFetch+15, nil, nil)
+ pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, downloader.MaxHashFetch+15, nil, nil)
peer, _ := newTestPeer("peer", protocol, pm, true)
defer peer.close()
@@ -232,7 +230,7 @@ func TestGetBlockBodies62(t *testing.T) { testGetBlockBodies(t, 62) }
func TestGetBlockBodies63(t *testing.T) { testGetBlockBodies(t, 63) }
func testGetBlockBodies(t *testing.T, protocol int) {
- pm := newTestProtocolManagerMust(t, downloader.FullSync, downloader.MaxBlockFetch+15, nil, nil)
+ pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, downloader.MaxBlockFetch+15, nil, nil)
peer, _ := newTestPeer("peer", protocol, pm, true)
defer peer.close()
@@ -315,13 +313,13 @@ func testGetNodeData(t *testing.T, protocol int) {
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
- tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey)
+ tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
- tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, testBankKey)
- tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, acc1Key)
+ tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey)
+ tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key)
block.AddTx(tx1)
block.AddTx(tx2)
case 2:
@@ -339,13 +337,13 @@ func testGetNodeData(t *testing.T, protocol int) {
}
}
// Assemble the test environment
- pm := newTestProtocolManagerMust(t, downloader.FullSync, 4, generator, nil)
+ pm, db := newTestProtocolManagerMust(t, downloader.FullSync, 4, generator, nil)
peer, _ := newTestPeer("peer", protocol, pm, true)
defer peer.close()
// Fetch for now the entire chain db
hashes := []common.Hash{}
- for _, key := range pm.chaindb.(*ethdb.MemDatabase).Keys() {
+ for _, key := range db.Keys() {
if len(key) == len(common.Hash{}) {
hashes = append(hashes, common.BytesToHash(key))
}
@@ -407,13 +405,13 @@ func testGetReceipt(t *testing.T, protocol int) {
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
- tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey)
+ tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
- tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, testBankKey)
- tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, acc1Key)
+ tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey)
+ tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key)
block.AddTx(tx1)
block.AddTx(tx2)
case 2:
@@ -431,7 +429,7 @@ func testGetReceipt(t *testing.T, protocol int) {
}
}
// Assemble the test environment
- pm := newTestProtocolManagerMust(t, downloader.FullSync, 4, generator, nil)
+ pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, 4, generator, nil)
peer, _ := newTestPeer("peer", protocol, pm, true)
defer peer.close()
@@ -441,7 +439,7 @@ func testGetReceipt(t *testing.T, protocol int) {
block := pm.blockchain.GetBlockByNumber(i)
hashes = append(hashes, block.Hash())
- receipts = append(receipts, core.GetBlockReceipts(pm.chaindb, block.Hash(), block.NumberU64()))
+ receipts = append(receipts, pm.blockchain.GetReceiptsByHash(block.Hash()))
}
// Send the hash request and verify the response
p2p.Send(peer.app, 0x0f, hashes)
@@ -474,7 +472,7 @@ func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool
config = &params.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked}
gspec = &core.Genesis{Config: config}
genesis = gspec.MustCommit(db)
- blockchain, _ = core.NewBlockChain(db, config, pow, vm.Config{})
+ blockchain, _ = core.NewBlockChain(db, nil, config, pow, vm.Config{})
)
pm, err := NewProtocolManager(config, downloader.FullSync, DefaultConfig.NetworkId, evmux, new(testTxPool), pow, blockchain, db)
if err != nil {
diff --git a/eth/helper_test.go b/eth/helper_test.go
index bfb003c8b..2b05cea80 100644
--- a/eth/helper_test.go
+++ b/eth/helper_test.go
@@ -49,7 +49,7 @@ var (
// newTestProtocolManager creates a new protocol manager for testing purposes,
// with the given number of blocks already known, and potential notification
// channels for different events.
-func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, error) {
+func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, *ethdb.MemDatabase, error) {
var (
evmux = new(event.TypeMux)
engine = ethash.NewFaker()
@@ -59,7 +59,7 @@ func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func
Alloc: core.GenesisAlloc{testBank: {Balance: big.NewInt(1000000)}},
}
genesis = gspec.MustCommit(db)
- blockchain, _ = core.NewBlockChain(db, gspec.Config, engine, vm.Config{})
+ blockchain, _ = core.NewBlockChain(db, nil, gspec.Config, engine, vm.Config{})
)
chain, _ := core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, blocks, generator)
if _, err := blockchain.InsertChain(chain); err != nil {
@@ -68,22 +68,22 @@ func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func
pm, err := NewProtocolManager(gspec.Config, mode, DefaultConfig.NetworkId, evmux, &testTxPool{added: newtx}, engine, blockchain, db)
if err != nil {
- return nil, err
+ return nil, nil, err
}
pm.Start(1000)
- return pm, nil
+ return pm, db, nil
}
// newTestProtocolManagerMust creates a new protocol manager for testing purposes,
// with the given number of blocks already known, and potential notification
// channels for different events. In case of an error, the constructor force-
// fails the test.
-func newTestProtocolManagerMust(t *testing.T, mode downloader.SyncMode, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) *ProtocolManager {
- pm, err := newTestProtocolManager(mode, blocks, generator, newtx)
+func newTestProtocolManagerMust(t *testing.T, mode downloader.SyncMode, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, *ethdb.MemDatabase) {
+ pm, db, err := newTestProtocolManager(mode, blocks, generator, newtx)
if err != nil {
t.Fatalf("Failed to create protocol manager: %v", err)
}
- return pm
+ return pm, db
}
// testTxPool is a fake, helper transaction pool for testing purposes
@@ -130,7 +130,7 @@ func (p *testTxPool) SubscribeTxPreEvent(ch chan<- core.TxPreEvent) event.Subscr
// newTestTransaction create a new dummy transaction.
func newTestTransaction(from *ecdsa.PrivateKey, nonce uint64, datasize int) *types.Transaction {
- tx := types.NewTransaction(nonce, common.Address{}, big.NewInt(0), big.NewInt(100000), big.NewInt(0), make([]byte, datasize))
+ tx := types.NewTransaction(nonce, common.Address{}, big.NewInt(0), 100000, big.NewInt(0), make([]byte, datasize))
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, from)
return tx
}
@@ -166,8 +166,12 @@ func newTestPeer(name string, version int, pm *ProtocolManager, shake bool) (*te
tp := &testPeer{app: app, net: net, peer: peer}
// Execute any implicitly requested handshakes and return
if shake {
- td, head, genesis := pm.blockchain.Status()
- tp.handshake(nil, td, head, genesis)
+ var (
+ genesis = pm.blockchain.Genesis()
+ head = pm.blockchain.CurrentHeader()
+ td = pm.blockchain.GetTd(head.Hash(), head.Number.Uint64())
+ )
+ tp.handshake(nil, td, head.Hash(), genesis.Hash())
}
return tp, errc
}
diff --git a/eth/protocol_test.go b/eth/protocol_test.go
index d3a44ae91..b2f93d8dd 100644
--- a/eth/protocol_test.go
+++ b/eth/protocol_test.go
@@ -41,8 +41,12 @@ func TestStatusMsgErrors62(t *testing.T) { testStatusMsgErrors(t, 62) }
func TestStatusMsgErrors63(t *testing.T) { testStatusMsgErrors(t, 63) }
func testStatusMsgErrors(t *testing.T, protocol int) {
- pm := newTestProtocolManagerMust(t, downloader.FullSync, 0, nil, nil)
- td, currentBlock, genesis := pm.blockchain.Status()
+ pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, 0, nil, nil)
+ var (
+ genesis = pm.blockchain.Genesis()
+ head = pm.blockchain.CurrentHeader()
+ td = pm.blockchain.GetTd(head.Hash(), head.Number.Uint64())
+ )
defer pm.Stop()
tests := []struct {
@@ -55,16 +59,16 @@ func testStatusMsgErrors(t *testing.T, protocol int) {
wantError: errResp(ErrNoStatusMsg, "first msg has code 2 (!= 0)"),
},
{
- code: StatusMsg, data: statusData{10, DefaultConfig.NetworkId, td, currentBlock, genesis},
+ code: StatusMsg, data: statusData{10, DefaultConfig.NetworkId, td, head.Hash(), genesis.Hash()},
wantError: errResp(ErrProtocolVersionMismatch, "10 (!= %d)", protocol),
},
{
- code: StatusMsg, data: statusData{uint32(protocol), 999, td, currentBlock, genesis},
+ code: StatusMsg, data: statusData{uint32(protocol), 999, td, head.Hash(), genesis.Hash()},
wantError: errResp(ErrNetworkIdMismatch, "999 (!= 1)"),
},
{
- code: StatusMsg, data: statusData{uint32(protocol), DefaultConfig.NetworkId, td, currentBlock, common.Hash{3}},
- wantError: errResp(ErrGenesisBlockMismatch, "0300000000000000 (!= %x)", genesis[:8]),
+ code: StatusMsg, data: statusData{uint32(protocol), DefaultConfig.NetworkId, td, head.Hash(), common.Hash{3}},
+ wantError: errResp(ErrGenesisBlockMismatch, "0300000000000000 (!= %x)", genesis.Hash().Bytes()[:8]),
},
}
@@ -94,7 +98,7 @@ func TestRecvTransactions63(t *testing.T) { testRecvTransactions(t, 63) }
func testRecvTransactions(t *testing.T, protocol int) {
txAdded := make(chan []*types.Transaction)
- pm := newTestProtocolManagerMust(t, downloader.FullSync, 0, nil, txAdded)
+ pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, 0, nil, txAdded)
pm.acceptTxs = 1 // mark synced to accept transactions
p, _ := newTestPeer("peer", protocol, pm, true)
defer pm.Stop()
@@ -121,7 +125,7 @@ func TestSendTransactions62(t *testing.T) { testSendTransactions(t, 62) }
func TestSendTransactions63(t *testing.T) { testSendTransactions(t, 63) }
func testSendTransactions(t *testing.T, protocol int) {
- pm := newTestProtocolManagerMust(t, downloader.FullSync, 0, nil, nil)
+ pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, 0, nil, nil)
defer pm.Stop()
// Fill the pool with big transactions.
diff --git a/eth/sync.go b/eth/sync.go
index a8ae64617..2da1464bc 100644
--- a/eth/sync.go
+++ b/eth/sync.go
@@ -189,18 +189,13 @@ func (pm *ProtocolManager) synchronise(peer *peer) {
mode = downloader.FastSync
}
// Run the sync cycle, and disable fast sync if we've went past the pivot block
- err := pm.downloader.Synchronise(peer.id, pHead, pTd, mode)
-
- if atomic.LoadUint32(&pm.fastSync) == 1 {
- // Disable fast sync if we indeed have something in our chain
- if pm.blockchain.CurrentBlock().NumberU64() > 0 {
- log.Info("Fast sync complete, auto disabling")
- atomic.StoreUint32(&pm.fastSync, 0)
- }
- }
- if err != nil {
+ if err := pm.downloader.Synchronise(peer.id, pHead, pTd, mode); err != nil {
return
}
+ if atomic.LoadUint32(&pm.fastSync) == 1 {
+ log.Info("Fast sync complete, auto disabling")
+ atomic.StoreUint32(&pm.fastSync, 0)
+ }
atomic.StoreUint32(&pm.acceptTxs, 1) // Mark initial sync done
if head := pm.blockchain.CurrentBlock(); head.NumberU64() > 0 {
// We've completed a sync cycle, notify all peers of new state. This path is
diff --git a/eth/sync_test.go b/eth/sync_test.go
index 9eaa1156f..88c10c7f7 100644
--- a/eth/sync_test.go
+++ b/eth/sync_test.go
@@ -30,12 +30,12 @@ import (
// imported into the blockchain.
func TestFastSyncDisabling(t *testing.T) {
// Create a pristine protocol manager, check that fast sync is left enabled
- pmEmpty := newTestProtocolManagerMust(t, downloader.FastSync, 0, nil, nil)
+ pmEmpty, _ := newTestProtocolManagerMust(t, downloader.FastSync, 0, nil, nil)
if atomic.LoadUint32(&pmEmpty.fastSync) == 0 {
t.Fatalf("fast sync disabled on pristine blockchain")
}
// Create a full protocol manager, check that fast sync gets disabled
- pmFull := newTestProtocolManagerMust(t, downloader.FastSync, 1024, nil, nil)
+ pmFull, _ := newTestProtocolManagerMust(t, downloader.FastSync, 1024, nil, nil)
if atomic.LoadUint32(&pmFull.fastSync) == 1 {
t.Fatalf("fast sync not disabled on non-empty blockchain")
}
diff --git a/eth/tracers/internal/tracers/assets.go b/eth/tracers/internal/tracers/assets.go
index cb0421008..1912f74ed 100644
--- a/eth/tracers/internal/tracers/assets.go
+++ b/eth/tracers/internal/tracers/assets.go
@@ -1,4 +1,4 @@
-// Code generated by go-bindata.
+// Code generated by go-bindata. DO NOT EDIT.
// sources:
// 4byte_tracer.js
// call_tracer.js
@@ -6,7 +6,6 @@
// noop_tracer.js
// opcount_tracer.js
// prestate_tracer.js
-// DO NOT EDIT!
package tracers
@@ -197,8 +196,8 @@ func prestate_tracerJs() (*asset, error) {
// It returns an error if the asset could not be found or
// could not be loaded.
func Asset(name string) ([]byte, error) {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- if f, ok := _bindata[cannonicalName]; ok {
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ if f, ok := _bindata[canonicalName]; ok {
a, err := f()
if err != nil {
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
@@ -223,8 +222,8 @@ func MustAsset(name string) []byte {
// It returns an error if the asset could not be found or
// could not be loaded.
func AssetInfo(name string) (os.FileInfo, error) {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- if f, ok := _bindata[cannonicalName]; ok {
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ if f, ok := _bindata[canonicalName]; ok {
a, err := f()
if err != nil {
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
@@ -245,11 +244,16 @@ func AssetNames() []string {
// _bindata is a table, holding each asset generator, mapped to its name.
var _bindata = map[string]func() (*asset, error){
- "4byte_tracer.js": _4byte_tracerJs,
- "call_tracer.js": call_tracerJs,
- "evmdis_tracer.js": evmdis_tracerJs,
- "noop_tracer.js": noop_tracerJs,
- "opcount_tracer.js": opcount_tracerJs,
+ "4byte_tracer.js": _4byte_tracerJs,
+
+ "call_tracer.js": call_tracerJs,
+
+ "evmdis_tracer.js": evmdis_tracerJs,
+
+ "noop_tracer.js": noop_tracerJs,
+
+ "opcount_tracer.js": opcount_tracerJs,
+
"prestate_tracer.js": prestate_tracerJs,
}
@@ -269,8 +273,8 @@ var _bindata = map[string]func() (*asset, error){
func AssetDir(name string) ([]string, error) {
node := _bintree
if len(name) != 0 {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- pathList := strings.Split(cannonicalName, "/")
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ pathList := strings.Split(canonicalName, "/")
for _, p := range pathList {
node = node.Children[p]
if node == nil {
@@ -320,11 +324,7 @@ func RestoreAsset(dir, name string) error {
if err != nil {
return err
}
- err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
- if err != nil {
- return err
- }
- return nil
+ return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
}
// RestoreAssets restores an asset under the given directory recursively
@@ -345,6 +345,6 @@ func RestoreAssets(dir, name string) error {
}
func _filePath(dir, name string) string {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
}
diff --git a/eth/tracers/tracer.go b/eth/tracers/tracer.go
index f3f848fc1..4cec9e633 100644
--- a/eth/tracers/tracer.go
+++ b/eth/tracers/tracer.go
@@ -1,4 +1,4 @@
-// Copyright 2016 The go-ethereum Authors
+// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
diff --git a/eth/tracers/tracer_test.go b/eth/tracers/tracer_test.go
index 7224a1489..117c376b8 100644
--- a/eth/tracers/tracer_test.go
+++ b/eth/tracers/tracer_test.go
@@ -1,4 +1,4 @@
-// Copyright 2016 The go-ethereum Authors
+// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go
index 139280797..bf8120228 100644
--- a/eth/tracers/tracers_test.go
+++ b/eth/tracers/tracers_test.go
@@ -156,7 +156,7 @@ func TestCallTracer(t *testing.T) {
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
Time: new(big.Int).SetUint64(uint64(test.Context.Time)),
Difficulty: (*big.Int)(test.Context.Difficulty),
- GasLimit: new(big.Int).SetUint64(uint64(test.Context.GasLimit)),
+ GasLimit: uint64(test.Context.GasLimit),
GasPrice: tx.GasPrice(),
}
db, _ := ethdb.NewMemDatabase()
@@ -174,7 +174,7 @@ func TestCallTracer(t *testing.T) {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
- if _, _, _, _, err = st.TransitionDb(); err != nil {
+ if _, _, _, err = st.TransitionDb(); err != nil {
t.Fatalf("failed to execute transaction: %v", err)
}
// Retrieve the trace result and compare against the etalon
diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go
index 7f73ab113..87a912901 100644
--- a/ethclient/ethclient.go
+++ b/ethclient/ethclient.go
@@ -455,13 +455,13 @@ func (ec *Client) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
// the current pending state of the backend blockchain. There is no guarantee that this is
// the true gas limit requirement as other transactions may be added or removed by miners,
// but it should provide a basis for setting a reasonable default.
-func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (*big.Int, error) {
- var hex hexutil.Big
+func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) {
+ var hex hexutil.Uint64
err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg))
if err != nil {
- return nil, err
+ return 0, err
}
- return (*big.Int)(&hex), nil
+ return uint64(hex), nil
}
// SendTransaction injects a signed transaction into the pending pool for execution.
@@ -487,8 +487,8 @@ func toCallArg(msg ethereum.CallMsg) interface{} {
if msg.Value != nil {
arg["value"] = (*hexutil.Big)(msg.Value)
}
- if msg.Gas != nil {
- arg["gas"] = (*hexutil.Big)(msg.Gas)
+ if msg.Gas != 0 {
+ arg["gas"] = hexutil.Uint64(msg.Gas)
}
if msg.GasPrice != nil {
arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice)
diff --git a/ethdb/database.go b/ethdb/database.go
index 93755dd7e..d86585f07 100644
--- a/ethdb/database.go
+++ b/ethdb/database.go
@@ -299,6 +299,11 @@ func (b *ldbBatch) ValueSize() int {
return b.size
}
+func (b *ldbBatch) Reset() {
+ b.b.Reset()
+ b.size = 0
+}
+
type table struct {
db Database
prefix string
@@ -358,3 +363,7 @@ func (tb *tableBatch) Write() error {
func (tb *tableBatch) ValueSize() int {
return tb.batch.ValueSize()
}
+
+func (tb *tableBatch) Reset() {
+ tb.batch.Reset()
+}
diff --git a/ethdb/interface.go b/ethdb/interface.go
index 99a5b770d..537312003 100644
--- a/ethdb/interface.go
+++ b/ethdb/interface.go
@@ -41,4 +41,6 @@ type Batch interface {
Putter
ValueSize() int // amount of data in the batch
Write() error
+ // Reset resets the batch for reuse
+ Reset()
}
diff --git a/ethdb/memory_database.go b/ethdb/memory_database.go
index 0dd93a279..8efd7bf84 100644
--- a/ethdb/memory_database.go
+++ b/ethdb/memory_database.go
@@ -123,3 +123,8 @@ func (b *memBatch) Write() error {
func (b *memBatch) ValueSize() int {
return b.size
}
+
+func (b *memBatch) Reset() {
+ b.writes = b.writes[:0]
+ b.size = 0
+}
diff --git a/ethstats/ethstats.go b/ethstats/ethstats.go
index 1e27a1e63..ae7e25265 100644
--- a/ethstats/ethstats.go
+++ b/ethstats/ethstats.go
@@ -473,8 +473,8 @@ type blockStats struct {
ParentHash common.Hash `json:"parentHash"`
Timestamp *big.Int `json:"timestamp"`
Miner common.Address `json:"miner"`
- GasUsed *big.Int `json:"gasUsed"`
- GasLimit *big.Int `json:"gasLimit"`
+ GasUsed uint64 `json:"gasUsed"`
+ GasLimit uint64 `json:"gasLimit"`
Diff string `json:"difficulty"`
TotalDiff string `json:"totalDifficulty"`
Txs []txStats `json:"transactions"`
@@ -559,8 +559,8 @@ func (s *Service) assembleBlockStats(block *types.Block) *blockStats {
ParentHash: header.ParentHash,
Timestamp: header.Time,
Miner: author,
- GasUsed: new(big.Int).Set(header.GasUsed),
- GasLimit: new(big.Int).Set(header.GasLimit),
+ GasUsed: header.GasUsed,
+ GasLimit: header.GasLimit,
Diff: header.Difficulty.String(),
TotalDiff: td.String(),
Txs: txs,
@@ -613,6 +613,7 @@ func (s *Service) reportHistory(conn *websocket.Conn, list []uint64) error {
}
// Ran out of blocks, cut the report short and send
history = history[len(history)-i:]
+ break
}
// Assemble the history report and send it to the server
if len(history) > 0 {
diff --git a/interfaces.go b/interfaces.go
index 67f236ef7..1ae1eba48 100644
--- a/interfaces.go
+++ b/interfaces.go
@@ -115,7 +115,7 @@ type ChainSyncReader interface {
type CallMsg struct {
From common.Address // the sender of the 'transaction'
To *common.Address // the destination contract (nil for contract creation)
- Gas *big.Int // if nil, the call executes with near-infinite gas
+ Gas uint64 // if 0, the call executes with near-infinite gas
GasPrice *big.Int // wei <-> gas exchange ratio
Value *big.Int // amount of wei sent along with the call
Data []byte // input data, usually an ABI-encoded contract method invocation
@@ -200,7 +200,7 @@ type PendingContractCaller interface {
// true gas limit requirement as other transactions may be added or removed by miners, but
// it should provide a basis for setting a reasonable default.
type GasEstimator interface {
- EstimateGas(ctx context.Context, call CallMsg) (usedGas *big.Int, err error)
+ EstimateGas(ctx context.Context, call CallMsg) (uint64, error)
}
// A PendingStateEventer provides access to real time notifications about changes to the
diff --git a/internal/build/env.go b/internal/build/env.go
index c9848bf82..b553e0ed8 100644
--- a/internal/build/env.go
+++ b/internal/build/env.go
@@ -94,7 +94,7 @@ func LocalEnv() Environment {
}
if env.Branch == "" {
if head != "HEAD" {
- env.Branch = strings.TrimLeft(head, "refs/heads/")
+ env.Branch = strings.TrimPrefix(head, "refs/heads/")
}
}
if info, err := os.Stat(".git/objects"); err == nil && info.IsDir() && env.Tag == "" {
diff --git a/internal/cmdtest/test_cmd.go b/internal/cmdtest/test_cmd.go
index 541e51c4c..20e82ec2a 100644
--- a/internal/cmdtest/test_cmd.go
+++ b/internal/cmdtest/test_cmd.go
@@ -1,18 +1,18 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of go-ethereum.
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
//
-// go-ethereum is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
-// go-ethereum is distributed in the hope that it will be useful,
+// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
+// GNU Lesser General Public License for more details.
//
-// You should have received a copy of the GNU General Public License
-// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package cmdtest
@@ -25,6 +25,7 @@ import (
"os"
"os/exec"
"regexp"
+ "strings"
"sync"
"testing"
"text/template"
@@ -141,9 +142,10 @@ func (tt *TestCmd) matchExactOutput(want []byte) error {
// Note that an arbitrary amount of output may be consumed by the
// regular expression. This usually means that expect cannot be used
// after ExpectRegexp.
-func (tt *TestCmd) ExpectRegexp(resource string) (*regexp.Regexp, []string) {
+func (tt *TestCmd) ExpectRegexp(regex string) (*regexp.Regexp, []string) {
+ regex = strings.TrimPrefix(regex, "\n")
var (
- re = regexp.MustCompile(resource)
+ re = regexp.MustCompile(regex)
rtee = &runeTee{in: tt.stdout}
matches []int
)
@@ -151,7 +153,7 @@ func (tt *TestCmd) ExpectRegexp(resource string) (*regexp.Regexp, []string) {
output := rtee.buf.Bytes()
if matches == nil {
tt.Fatalf("Output did not match:\n---------------- (stdout text)\n%s\n---------------- (regular expression)\n%s",
- output, resource)
+ output, regex)
return re, nil
}
tt.Logf("Matched stdout text:\n%s", output)
diff --git a/internal/ethapi/addrlock.go b/internal/ethapi/addrlock.go
index 5a9c948b8..61ddff688 100644
--- a/internal/ethapi/addrlock.go
+++ b/internal/ethapi/addrlock.go
@@ -1,4 +1,4 @@
-// Copyright 2015 The go-ethereum Authors
+// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index d07b2e693..636d0bfe2 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -45,7 +45,6 @@ import (
)
const (
- defaultGas = 90000
defaultGasPrice = 50 * params.Shannon
)
@@ -334,28 +333,19 @@ func (s *PrivateAccountAPI) LockAccount(addr common.Address) bool {
return fetchKeystore(s.am).Lock(addr) == nil
}
-// SendTransaction will create a transaction from the given arguments and
-// tries to sign it with the key associated with args.To. If the given passwd isn't
-// able to decrypt the key it fails.
-func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs, passwd string) (common.Hash, error) {
+// signTransactions sets defaults and signs the given transaction
+// NOTE: the caller needs to ensure that the nonceLock is held, if applicable,
+// and release it after the transaction has been submitted to the tx pool
+func (s *PrivateAccountAPI) signTransaction(ctx context.Context, args SendTxArgs, passwd string) (*types.Transaction, error) {
// Look up the wallet containing the requested signer
account := accounts.Account{Address: args.From}
-
wallet, err := s.am.Find(account)
if err != nil {
- return common.Hash{}, err
- }
-
- if args.Nonce == nil {
- // Hold the addresse's mutex around signing to prevent concurrent assignment of
- // the same nonce to multiple accounts.
- s.nonceLock.LockAddr(args.From)
- defer s.nonceLock.UnlockAddr(args.From)
+ return nil, err
}
-
// Set some sanity defaults and terminate on failure
if err := args.setDefaults(ctx, s.b); err != nil {
- return common.Hash{}, err
+ return nil, err
}
// Assemble the transaction and sign with the wallet
tx := args.toTransaction()
@@ -364,13 +354,53 @@ func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs
if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) {
chainID = config.ChainId
}
- signed, err := wallet.SignTxWithPassphrase(account, passwd, tx, chainID)
+ return wallet.SignTxWithPassphrase(account, passwd, tx, chainID)
+}
+
+// SendTransaction will create a transaction from the given arguments and
+// tries to sign it with the key associated with args.To. If the given passwd isn't
+// able to decrypt the key it fails.
+func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs, passwd string) (common.Hash, error) {
+ if args.Nonce == nil {
+ // Hold the addresse's mutex around signing to prevent concurrent assignment of
+ // the same nonce to multiple accounts.
+ s.nonceLock.LockAddr(args.From)
+ defer s.nonceLock.UnlockAddr(args.From)
+ }
+ signed, err := s.signTransaction(ctx, args, passwd)
if err != nil {
return common.Hash{}, err
}
return submitTransaction(ctx, s.b, signed)
}
+// SignTransaction will create a transaction from the given arguments and
+// tries to sign it with the key associated with args.To. If the given passwd isn't
+// able to decrypt the key it fails. The transaction is returned in RLP-form, not broadcast
+// to other nodes
+func (s *PrivateAccountAPI) SignTransaction(ctx context.Context, args SendTxArgs, passwd string) (*SignTransactionResult, error) {
+ // No need to obtain the noncelock mutex, since we won't be sending this
+ // tx into the transaction pool, but right back to the user
+ if args.Gas == nil {
+ return nil, fmt.Errorf("gas not specified")
+ }
+ if args.GasPrice == nil {
+ return nil, fmt.Errorf("gasPrice not specified")
+ }
+ if args.Nonce == nil {
+ return nil, fmt.Errorf("nonce not specified")
+ }
+ signed, err := s.signTransaction(ctx, args, passwd)
+ if err != nil {
+ return nil, err
+ }
+ data, err := rlp.EncodeToBytes(signed)
+ if err != nil {
+ return nil, err
+ }
+ return &SignTransactionResult{data, signed}, nil
+}
+
// signHash is a helper function that calculates a hash for the given message that can be
// safely used to calculate a signature from.
//
@@ -575,18 +605,18 @@ func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.A
type CallArgs struct {
From common.Address `json:"from"`
To *common.Address `json:"to"`
- Gas hexutil.Big `json:"gas"`
+ Gas hexutil.Uint64 `json:"gas"`
GasPrice hexutil.Big `json:"gasPrice"`
Value hexutil.Big `json:"value"`
Data hexutil.Bytes `json:"data"`
}
-func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config) ([]byte, *big.Int, bool, error) {
+func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config) ([]byte, uint64, bool, error) {
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
state, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
if state == nil || err != nil {
- return nil, common.Big0, false, err
+ return nil, 0, false, err
}
// Set sender address or use a default if none specified
addr := args.From
@@ -598,9 +628,9 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
}
}
// Set default gas & gas price if none were set
- gas, gasPrice := args.Gas.ToInt(), args.GasPrice.ToInt()
- if gas.Sign() == 0 {
- gas = big.NewInt(50000000)
+ gas, gasPrice := uint64(args.Gas), args.GasPrice.ToInt()
+ if gas == 0 {
+ gas = 50000000
}
if gasPrice.Sign() == 0 {
gasPrice = new(big.Int).SetUint64(defaultGasPrice)
@@ -624,7 +654,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
// Get a new instance of the EVM.
evm, vmError, err := s.b.GetEVM(ctx, msg, state, header, vmCfg)
if err != nil {
- return nil, common.Big0, false, err
+ return nil, 0, false, err
}
// Wait for the context to be done and cancel the evm. Even if the
// EVM has finished, cancelling may be done (repeatedly)
@@ -635,10 +665,10 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
// Setup the gas pool (also for unmetered requests)
// and apply the message.
- gp := new(core.GasPool).AddGas(math.MaxBig256)
+ gp := new(core.GasPool).AddGas(math.MaxUint64)
res, gas, failed, err := core.ApplyMessage(evm, msg, gp)
if err := vmError(); err != nil {
- return nil, common.Big0, false, err
+ return nil, 0, false, err
}
return res, gas, failed, err
}
@@ -652,28 +682,29 @@ func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr r
// EstimateGas returns an estimate of the amount of gas needed to execute the
// given transaction against the current pending block.
-func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*hexutil.Big, error) {
- // Determine the lowest and highest possible gas limits to binary search in between
+func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (hexutil.Uint64, error) {
+ // Binary search the gas requirement, as it may be higher than the amount used
var (
lo uint64 = params.TxGas - 1
hi uint64
cap uint64
)
- if (*big.Int)(&args.Gas).Uint64() >= params.TxGas {
- hi = (*big.Int)(&args.Gas).Uint64()
+ if uint64(args.Gas) >= params.TxGas {
+ hi = uint64(args.Gas)
} else {
// Retrieve the current pending block to act as the gas ceiling
block, err := s.b.BlockByNumber(ctx, rpc.PendingBlockNumber)
if err != nil {
- return nil, err
+ return 0, err
}
- hi = block.GasLimit().Uint64()
+ hi = block.GasLimit()
}
cap = hi
// Create a helper to check if a gas allowance results in an executable transaction
executable := func(gas uint64) bool {
- (*big.Int)(&args.Gas).SetUint64(gas)
+ args.Gas = hexutil.Uint64(gas)
+
_, _, failed, err := s.doCall(ctx, args, rpc.PendingBlockNumber, vm.Config{})
if err != nil || failed {
return false
@@ -692,17 +723,17 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*
// Reject the transaction as invalid if it still fails at the highest allowance
if hi == cap {
if !executable(hi) {
- return nil, fmt.Errorf("gas required exceeds allowance or always failing transaction")
+ return 0, fmt.Errorf("gas required exceeds allowance or always failing transaction")
}
}
- return (*hexutil.Big)(new(big.Int).SetUint64(hi)), nil
+ return hexutil.Uint64(hi), nil
}
// ExecutionResult groups all structured logs emitted by the EVM
// while replaying a transaction in debug mode as well as transaction
// execution status, the amount of gas used and the return value
type ExecutionResult struct {
- Gas *big.Int `json:"gas"`
+ Gas uint64 `json:"gas"`
Failed bool `json:"failed"`
ReturnValue string `json:"returnValue"`
StructLogs []StructLogRes `json:"structLogs"`
@@ -777,9 +808,9 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx
"difficulty": (*hexutil.Big)(head.Difficulty),
"totalDifficulty": (*hexutil.Big)(s.b.GetTd(b.Hash())),
"extraData": hexutil.Bytes(head.Extra),
- "size": hexutil.Uint64(uint64(b.Size().Int64())),
- "gasLimit": (*hexutil.Big)(head.GasLimit),
- "gasUsed": (*hexutil.Big)(head.GasUsed),
+ "size": hexutil.Uint64(b.Size()),
+ "gasLimit": hexutil.Uint64(head.GasLimit),
+ "gasUsed": hexutil.Uint64(head.GasUsed),
"timestamp": (*hexutil.Big)(head.Time),
"transactionsRoot": head.TxHash,
"receiptsRoot": head.ReceiptHash,
@@ -822,7 +853,7 @@ type RPCTransaction struct {
BlockHash common.Hash `json:"blockHash"`
BlockNumber *hexutil.Big `json:"blockNumber"`
From common.Address `json:"from"`
- Gas *hexutil.Big `json:"gas"`
+ Gas hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
Hash common.Hash `json:"hash"`
Input hexutil.Bytes `json:"input"`
@@ -847,7 +878,7 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
result := &RPCTransaction{
From: from,
- Gas: (*hexutil.Big)(tx.Gas()),
+ Gas: hexutil.Uint64(tx.Gas()),
GasPrice: (*hexutil.Big)(tx.GasPrice()),
Hash: tx.Hash(),
Input: hexutil.Bytes(tx.Data()),
@@ -1024,8 +1055,8 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(hash common.Hash) (map[
"transactionIndex": hexutil.Uint64(index),
"from": from,
"to": tx.To(),
- "gasUsed": (*hexutil.Big)(receipt.GasUsed),
- "cumulativeGasUsed": (*hexutil.Big)(receipt.CumulativeGasUsed),
+ "gasUsed": hexutil.Uint64(receipt.GasUsed),
+ "cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed),
"contractAddress": nil,
"logs": receipt.Logs,
"logsBloom": receipt.Bloom,
@@ -1068,7 +1099,7 @@ func (s *PublicTransactionPoolAPI) sign(addr common.Address, tx *types.Transacti
type SendTxArgs struct {
From common.Address `json:"from"`
To *common.Address `json:"to"`
- Gas *hexutil.Big `json:"gas"`
+ Gas *hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
Value *hexutil.Big `json:"value"`
Nonce *hexutil.Uint64 `json:"nonce"`
@@ -1081,7 +1112,8 @@ type SendTxArgs struct {
// setDefaults is a helper function that fills in default values for unspecified tx fields.
func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error {
if args.Gas == nil {
- args.Gas = (*hexutil.Big)(big.NewInt(defaultGas))
+ args.Gas = new(hexutil.Uint64)
+ *(*uint64)(args.Gas) = 90000
}
if args.GasPrice == nil {
price, err := b.SuggestPrice(ctx)
@@ -1103,6 +1135,18 @@ func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error {
if args.Data != nil && args.Input != nil && !bytes.Equal(*args.Data, *args.Input) {
return errors.New(`Both "data" and "input" are set and not equal. Please use "input" to pass transaction call data.`)
}
+ if args.To == nil {
+ // Contract creation
+ var input []byte
+ if args.Data != nil {
+ input = *args.Data
+ } else if args.Input != nil {
+ input = *args.Input
+ }
+ if len(input) == 0 {
+ return errors.New(`contract creation without any data provided`)
+ }
+ }
return nil
}
@@ -1114,9 +1158,9 @@ func (args *SendTxArgs) toTransaction() *types.Transaction {
input = *args.Input
}
if args.To == nil {
- return types.NewContractCreation(uint64(*args.Nonce), (*big.Int)(args.Value), (*big.Int)(args.Gas), (*big.Int)(args.GasPrice), input)
+ return types.NewContractCreation(uint64(*args.Nonce), (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input)
}
- return types.NewTransaction(uint64(*args.Nonce), *args.To, (*big.Int)(args.Value), (*big.Int)(args.Gas), (*big.Int)(args.GasPrice), input)
+ return types.NewTransaction(uint64(*args.Nonce), *args.To, (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input)
}
// submitTransaction is a helper function that submits tx to txPool and logs a message.
@@ -1220,11 +1264,14 @@ type SignTransactionResult struct {
// The node needs to have the private key of the account corresponding with
// the given from address and it needs to be unlocked.
func (s *PublicTransactionPoolAPI) SignTransaction(ctx context.Context, args SendTxArgs) (*SignTransactionResult, error) {
+ if args.Gas == nil {
+ return nil, fmt.Errorf("gas not specified")
+ }
+ if args.GasPrice == nil {
+ return nil, fmt.Errorf("gasPrice not specified")
+ }
if args.Nonce == nil {
- // Hold the addresse's mutex around signing to prevent concurrent assignment of
- // the same nonce to multiple accounts.
- s.nonceLock.LockAddr(args.From)
- defer s.nonceLock.UnlockAddr(args.From)
+ return nil, fmt.Errorf("nonce not specified")
}
if err := args.setDefaults(ctx, s.b); err != nil {
return nil, err
@@ -1264,7 +1311,7 @@ func (s *PublicTransactionPoolAPI) PendingTransactions() ([]*RPCTransaction, err
// Resend accepts an existing transaction and a new gas price and limit. It will remove
// the given transaction from the pool and reinsert it with the new gas price and limit.
-func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, sendArgs SendTxArgs, gasPrice, gasLimit *hexutil.Big) (common.Hash, error) {
+func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, sendArgs SendTxArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) {
if sendArgs.Nonce == nil {
return common.Hash{}, fmt.Errorf("missing transaction nonce in transaction spec")
}
diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go
index 368fa4872..af95d7906 100644
--- a/internal/ethapi/backend.go
+++ b/internal/ethapi/backend.go
@@ -37,13 +37,14 @@ import (
// Backend interface provides the common API services (that are provided by
// both full and light clients) with access to necessary functions.
type Backend interface {
- // general Ethereum API
+ // General Ethereum API
Downloader() *downloader.Downloader
ProtocolVersion() int
SuggestPrice(ctx context.Context) (*big.Int, error)
ChainDb() ethdb.Database
EventMux() *event.TypeMux
AccountManager() *accounts.Manager
+
// BlockChain API
SetHead(number uint64)
HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error)
diff --git a/internal/jsre/deps/bindata.go b/internal/jsre/deps/bindata.go
index c7dde7137..7454c7cfc 100644
--- a/internal/jsre/deps/bindata.go
+++ b/internal/jsre/deps/bindata.go
@@ -1,8 +1,7 @@
-// Code generated by go-bindata.
+// Code generated by go-bindata. DO NOT EDIT.
// sources:
// bignumber.js
// web3.js
-// DO NOT EDIT!
package deps
@@ -113,8 +112,8 @@ func web3Js() (*asset, error) {
// It returns an error if the asset could not be found or
// could not be loaded.
func Asset(name string) ([]byte, error) {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- if f, ok := _bindata[cannonicalName]; ok {
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ if f, ok := _bindata[canonicalName]; ok {
a, err := f()
if err != nil {
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
@@ -139,8 +138,8 @@ func MustAsset(name string) []byte {
// It returns an error if the asset could not be found or
// could not be loaded.
func AssetInfo(name string) (os.FileInfo, error) {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- if f, ok := _bindata[cannonicalName]; ok {
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ if f, ok := _bindata[canonicalName]; ok {
a, err := f()
if err != nil {
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
@@ -162,7 +161,8 @@ func AssetNames() []string {
// _bindata is a table, holding each asset generator, mapped to its name.
var _bindata = map[string]func() (*asset, error){
"bignumber.js": bignumberJs,
- "web3.js": web3Js,
+
+ "web3.js": web3Js,
}
// AssetDir returns the file names below a certain
@@ -181,8 +181,8 @@ var _bindata = map[string]func() (*asset, error){
func AssetDir(name string) ([]string, error) {
node := _bintree
if len(name) != 0 {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- pathList := strings.Split(cannonicalName, "/")
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ pathList := strings.Split(canonicalName, "/")
for _, p := range pathList {
node = node.Children[p]
if node == nil {
@@ -228,11 +228,7 @@ func RestoreAsset(dir, name string) error {
if err != nil {
return err
}
- err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
- if err != nil {
- return err
- }
- return nil
+ return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
}
// RestoreAssets restores an asset under the given directory recursively
@@ -253,6 +249,6 @@ func RestoreAssets(dir, name string) error {
}
func _filePath(dir, name string) string {
- cannonicalName := strings.Replace(name, "\\", "/", -1)
- return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
+ canonicalName := strings.Replace(name, "\\", "/", -1)
+ return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
}
diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go
index e11aa402f..a6b81b4c2 100644
--- a/internal/web3ext/web3ext.go
+++ b/internal/web3ext/web3ext.go
@@ -517,6 +517,12 @@ web3._extend({
call: 'personal_deriveAccount',
params: 3
}),
+ new web3._extend.Method({
+ name: 'signTransaction',
+ call: 'personal_signTransaction',
+ params: 2,
+ inputFormatter: [web3._extend.formatters.inputTransactionFormatter, null]
+ }),
],
properties: [
new web3._extend.Property({
diff --git a/les/backend.go b/les/backend.go
index 7180b81d7..6a324cb04 100644
--- a/les/backend.go
+++ b/les/backend.go
@@ -46,6 +46,8 @@ import (
)
type LightEthereum struct {
+ config *eth.Config
+
odr *LesOdr
relay *LesTxRelay
chainConfig *params.ChainConfig
@@ -92,6 +94,7 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
quitSync := make(chan struct{})
leth := &LightEthereum{
+ config: config,
chainConfig: chainConfig,
chainDb: chainDb,
eventMux: ctx.EventMux,
@@ -221,11 +224,10 @@ func (s *LightEthereum) Start(srvr *p2p.Server) error {
s.startBloomHandlers()
log.Warn("Light client mode is an experimental feature")
s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.networkId)
- // search the topic belonging to the oldest supported protocol because
- // servers always advertise all supported protocols
- protocolVersion := ClientProtocolVersions[len(ClientProtocolVersions)-1]
+ // clients are searching for the first advertised protocol in the list
+ protocolVersion := AdvertiseProtocolVersions[0]
s.serverPool.start(srvr, lesTopic(s.blockchain.Genesis().Hash(), protocolVersion))
- s.protocolManager.Start()
+ s.protocolManager.Start(s.config.LightPeers)
return nil
}
diff --git a/les/fetcher.go b/les/fetcher.go
index 3fc4df30b..e12a2c78a 100644
--- a/les/fetcher.go
+++ b/les/fetcher.go
@@ -36,24 +36,26 @@ const (
maxNodeCount = 20 // maximum number of fetcherTreeNode entries remembered for each peer
)
-// lightFetcher
+// lightFetcher implements retrieval of newly announced headers. It also provides a peerHasBlock function for the
+// ODR system to ensure that we only request data related to a certain block from peers who have already processed
+// and announced that block.
type lightFetcher struct {
pm *ProtocolManager
odr *LesOdr
chain *light.LightChain
+ lock sync.Mutex // lock protects access to the fetcher's internal state variables except sent requests
maxConfirmedTd *big.Int
peers map[*peer]*fetcherPeerInfo
lastUpdateStats *updateStatsEntry
+ syncing bool
+ syncDone chan *peer
- lock sync.Mutex // qwerqwerqwe
- deliverChn chan fetchResponse
- reqMu sync.RWMutex
+ reqMu sync.RWMutex // reqMu protects access to sent header fetch requests
requested map[uint64]fetchRequest
+ deliverChn chan fetchResponse
timeoutChn chan uint64
requestChn chan bool // true if initiated from outside
- syncing bool
- syncDone chan *peer
}
// fetcherPeerInfo holds fetcher-specific information about each active peer
@@ -425,6 +427,9 @@ func (f *lightFetcher) nextRequest() (*distReq, uint64) {
},
canSend: func(dp distPeer) bool {
p := dp.(*peer)
+ f.lock.Lock()
+ defer f.lock.Unlock()
+
fp := f.peers[p]
return fp != nil && fp.nodeByHash[bestHash] != nil
},
@@ -557,8 +562,13 @@ func (f *lightFetcher) checkAnnouncedHeaders(fp *fetcherPeerInfo, headers []*typ
return true
}
// we ran out of recently delivered headers but have not reached a node known by this peer yet, continue matching
- td = f.chain.GetTd(header.ParentHash, header.Number.Uint64()-1)
- header = f.chain.GetHeader(header.ParentHash, header.Number.Uint64()-1)
+ hash, number := header.ParentHash, header.Number.Uint64()-1
+ td = f.chain.GetTd(hash, number)
+ header = f.chain.GetHeader(hash, number)
+ if header == nil || td == nil {
+ log.Error("Missing parent of validated header", "hash", hash, "number", number)
+ return false
+ }
} else {
header = headers[i]
td = tds[i]
@@ -642,13 +652,18 @@ func (f *lightFetcher) checkKnownNode(p *peer, n *fetcherTreeNode) bool {
if td == nil {
return false
}
+ header := f.chain.GetHeader(n.hash, n.number)
+ // check the availability of both header and td because reads are not protected by chain db mutex
+ // Note: returning false is always safe here
+ if header == nil {
+ return false
+ }
fp := f.peers[p]
if fp == nil {
p.Log().Debug("Unknown peer to check known nodes")
return false
}
- header := f.chain.GetHeader(n.hash, n.number)
if !f.checkAnnouncedHeaders(fp, []*types.Header{header}, []*big.Int{td}) {
p.Log().Debug("Inconsistent announcement")
go f.pm.removePeer(p.id)
diff --git a/les/handler.go b/les/handler.go
index f8cf63952..864abe605 100644
--- a/les/handler.go
+++ b/les/handler.go
@@ -18,7 +18,6 @@
package les
import (
- "bytes"
"encoding/binary"
"errors"
"fmt"
@@ -77,13 +76,12 @@ type BlockChain interface {
GetHeader(hash common.Hash, number uint64) *types.Header
GetHeaderByHash(hash common.Hash) *types.Header
CurrentHeader() *types.Header
- GetTdByHash(hash common.Hash) *big.Int
+ GetTd(hash common.Hash, number uint64) *big.Int
+ State() (*state.StateDB, error)
InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error)
Rollback(chain []common.Hash)
- Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash)
GetHeaderByNumber(number uint64) *types.Header
GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash
- LastBlockHash() common.Hash
Genesis() *types.Block
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
}
@@ -111,6 +109,7 @@ type ProtocolManager struct {
downloader *downloader.Downloader
fetcher *lightFetcher
peers *peerSet
+ maxPeers int
SubProtocols []p2p.Protocol
@@ -218,7 +217,9 @@ func (pm *ProtocolManager) removePeer(id string) {
pm.peers.Unregister(id)
}
-func (pm *ProtocolManager) Start() {
+func (pm *ProtocolManager) Start(maxPeers int) {
+ pm.maxPeers = maxPeers
+
if pm.lightSync {
go pm.syncer()
} else {
@@ -259,12 +260,21 @@ func (pm *ProtocolManager) newPeer(pv int, nv uint64, p *p2p.Peer, rw p2p.MsgRea
// handle is the callback invoked to manage the life cycle of a les peer. When
// this function terminates, the peer is disconnected.
func (pm *ProtocolManager) handle(p *peer) error {
+ if pm.peers.Len() >= pm.maxPeers {
+ return p2p.DiscTooManyPeers
+ }
+
p.Log().Debug("Light Ethereum peer connected", "name", p.Name())
// Execute the LES handshake
- td, head, genesis := pm.blockchain.Status()
- headNum := core.GetBlockNumber(pm.chainDb, head)
- if err := p.Handshake(td, head, headNum, genesis, pm.server); err != nil {
+ var (
+ genesis = pm.blockchain.Genesis()
+ head = pm.blockchain.CurrentHeader()
+ hash = head.Hash()
+ number = head.Number.Uint64()
+ td = pm.blockchain.GetTd(hash, number)
+ )
+ if err := p.Handshake(td, hash, number, genesis.Hash(), pm.server); err != nil {
p.Log().Debug("Light Ethereum handshake failed", "err", err)
return err
}
@@ -454,14 +464,14 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
case query.Reverse:
// Number based traversal towards the genesis block
if query.Origin.Number >= query.Skip+1 {
- query.Origin.Number -= (query.Skip + 1)
+ query.Origin.Number -= query.Skip + 1
} else {
unknown = true
}
case !query.Reverse:
// Number based traversal towards the leaf block
- query.Origin.Number += (query.Skip + 1)
+ query.Origin.Number += query.Skip + 1
}
}
@@ -569,17 +579,19 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
for _, req := range req.Reqs {
// Retrieve the requested state entry, stopping if enough was found
if header := core.GetHeader(pm.chainDb, req.BHash, core.GetBlockNumber(pm.chainDb, req.BHash)); header != nil {
- if trie, _ := trie.New(header.Root, pm.chainDb); trie != nil {
- sdata := trie.Get(req.AccKey)
- var acc state.Account
- if err := rlp.DecodeBytes(sdata, &acc); err == nil {
- entry, _ := pm.chainDb.Get(acc.CodeHash)
- if bytes+len(entry) >= softResponseLimit {
- break
- }
- data = append(data, entry)
- bytes += len(entry)
- }
+ statedb, err := pm.blockchain.State()
+ if err != nil {
+ continue
+ }
+ account, err := pm.getAccount(statedb, header.Root, common.BytesToHash(req.AccKey))
+ if err != nil {
+ continue
+ }
+ code, _ := statedb.Database().TrieDB().Node(common.BytesToHash(account.CodeHash))
+
+ data = append(data, code)
+ if bytes += len(code); bytes >= softResponseLimit {
+ break
}
}
}
@@ -691,25 +703,29 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
return errResp(ErrRequestRejected, "")
}
for _, req := range req.Reqs {
- if bytes >= softResponseLimit {
- break
- }
// Retrieve the requested state entry, stopping if enough was found
if header := core.GetHeader(pm.chainDb, req.BHash, core.GetBlockNumber(pm.chainDb, req.BHash)); header != nil {
- if tr, _ := trie.New(header.Root, pm.chainDb); tr != nil {
- if len(req.AccKey) > 0 {
- sdata := tr.Get(req.AccKey)
- tr = nil
- var acc state.Account
- if err := rlp.DecodeBytes(sdata, &acc); err == nil {
- tr, _ = trie.New(acc.Root, pm.chainDb)
- }
+ statedb, err := pm.blockchain.State()
+ if err != nil {
+ continue
+ }
+ var trie state.Trie
+ if len(req.AccKey) > 0 {
+ account, err := pm.getAccount(statedb, header.Root, common.BytesToHash(req.AccKey))
+ if err != nil {
+ continue
}
- if tr != nil {
- var proof light.NodeList
- tr.Prove(req.Key, 0, &proof)
- proofs = append(proofs, proof)
- bytes += proof.DataSize()
+ trie, _ = statedb.Database().OpenStorageTrie(common.BytesToHash(req.AccKey), account.Root)
+ } else {
+ trie, _ = statedb.Database().OpenTrie(header.Root)
+ }
+ if trie != nil {
+ var proof light.NodeList
+ trie.Prove(req.Key, 0, &proof)
+
+ proofs = append(proofs, proof)
+ if bytes += proof.DataSize(); bytes >= softResponseLimit {
+ break
}
}
}
@@ -730,9 +746,9 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
}
// Gather state data until the fetch or network limits is reached
var (
- lastBHash common.Hash
- lastAccKey []byte
- tr, str *trie.Trie
+ lastBHash common.Hash
+ statedb *state.StateDB
+ root common.Hash
)
reqCnt := len(req.Reqs)
if reject(uint64(reqCnt), MaxProofsFetch) {
@@ -742,41 +758,41 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
nodes := light.NewNodeSet()
for _, req := range req.Reqs {
- if nodes.DataSize() >= softResponseLimit {
- break
- }
- if tr == nil || req.BHash != lastBHash {
+ // Look up the state belonging to the request
+ if statedb == nil || req.BHash != lastBHash {
+ statedb, root, lastBHash = nil, common.Hash{}, req.BHash
+
if header := core.GetHeader(pm.chainDb, req.BHash, core.GetBlockNumber(pm.chainDb, req.BHash)); header != nil {
- tr, _ = trie.New(header.Root, pm.chainDb)
- } else {
- tr = nil
+ statedb, _ = pm.blockchain.State()
+ root = header.Root
}
- lastBHash = req.BHash
- str = nil
}
- if tr != nil {
- if len(req.AccKey) > 0 {
- if str == nil || !bytes.Equal(req.AccKey, lastAccKey) {
- sdata := tr.Get(req.AccKey)
- str = nil
- var acc state.Account
- if err := rlp.DecodeBytes(sdata, &acc); err == nil {
- str, _ = trie.New(acc.Root, pm.chainDb)
- }
- lastAccKey = common.CopyBytes(req.AccKey)
- }
- if str != nil {
- str.Prove(req.Key, req.FromLevel, nodes)
- }
- } else {
- tr.Prove(req.Key, req.FromLevel, nodes)
+ if statedb == nil {
+ continue
+ }
+ // Pull the account or storage trie of the request
+ var trie state.Trie
+ if len(req.AccKey) > 0 {
+ account, err := pm.getAccount(statedb, root, common.BytesToHash(req.AccKey))
+ if err != nil {
+ continue
}
+ trie, _ = statedb.Database().OpenStorageTrie(common.BytesToHash(req.AccKey), account.Root)
+ } else {
+ trie, _ = statedb.Database().OpenTrie(root)
+ }
+ if trie == nil {
+ continue
+ }
+ // Prove the user's request from the account or stroage trie
+ trie.Prove(req.Key, req.FromLevel, nodes)
+ if nodes.DataSize() >= softResponseLimit {
+ break
}
}
- proofs := nodes.NodeList()
bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
- return p.SendProofsV2(req.ReqID, bv, proofs)
+ return p.SendProofsV2(req.ReqID, bv, nodes.NodeList())
case ProofsV1Msg:
if pm.odr == nil {
@@ -839,22 +855,24 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
if reject(uint64(reqCnt), MaxHelperTrieProofsFetch) {
return errResp(ErrRequestRejected, "")
}
- trieDb := ethdb.NewTable(pm.chainDb, light.ChtTablePrefix)
+ trieDb := trie.NewDatabase(ethdb.NewTable(pm.chainDb, light.ChtTablePrefix))
for _, req := range req.Reqs {
- if bytes >= softResponseLimit {
- break
- }
-
if header := pm.blockchain.GetHeaderByNumber(req.BlockNum); header != nil {
- sectionHead := core.GetCanonicalHash(pm.chainDb, (req.ChtNum+1)*light.ChtV1Frequency-1)
- if root := light.GetChtRoot(pm.chainDb, req.ChtNum, sectionHead); root != (common.Hash{}) {
- if tr, _ := trie.New(root, trieDb); tr != nil {
- var encNumber [8]byte
- binary.BigEndian.PutUint64(encNumber[:], req.BlockNum)
- var proof light.NodeList
- tr.Prove(encNumber[:], 0, &proof)
- proofs = append(proofs, ChtResp{Header: header, Proof: proof})
- bytes += proof.DataSize() + estHeaderRlpSize
+ sectionHead := core.GetCanonicalHash(pm.chainDb, req.ChtNum*light.CHTFrequencyServer-1)
+ if root := light.GetChtRoot(pm.chainDb, req.ChtNum-1, sectionHead); root != (common.Hash{}) {
+ trie, err := trie.New(root, trieDb)
+ if err != nil {
+ continue
+ }
+ var encNumber [8]byte
+ binary.BigEndian.PutUint64(encNumber[:], req.BlockNum)
+
+ var proof light.NodeList
+ trie.Prove(encNumber[:], 0, &proof)
+
+ proofs = append(proofs, ChtResp{Header: header, Proof: proof})
+ if bytes += proof.DataSize() + estHeaderRlpSize; bytes >= softResponseLimit {
+ break
}
}
}
@@ -887,25 +905,17 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
lastIdx uint64
lastType uint
root common.Hash
- tr *trie.Trie
+ auxTrie *trie.Trie
)
-
nodes := light.NewNodeSet()
-
for _, req := range req.Reqs {
- if nodes.DataSize()+auxBytes >= softResponseLimit {
- break
- }
- if tr == nil || req.HelperTrieType != lastType || req.TrieIdx != lastIdx {
+ if auxTrie == nil || req.Type != lastType || req.TrieIdx != lastIdx {
+ auxTrie, lastType, lastIdx = nil, req.Type, req.TrieIdx
+
var prefix string
- root, prefix = pm.getHelperTrie(req.HelperTrieType, req.TrieIdx)
- if root != (common.Hash{}) {
- if t, err := trie.New(root, ethdb.NewTable(pm.chainDb, prefix)); err == nil {
- tr = t
- }
+ if root, prefix = pm.getHelperTrie(req.Type, req.TrieIdx); root != (common.Hash{}) {
+ auxTrie, _ = trie.New(root, trie.NewDatabase(ethdb.NewTable(pm.chainDb, prefix)))
}
- lastType = req.HelperTrieType
- lastIdx = req.TrieIdx
}
if req.AuxReq == auxRoot {
var data []byte
@@ -915,8 +925,8 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
auxData = append(auxData, data)
auxBytes += len(data)
} else {
- if tr != nil {
- tr.Prove(req.Key, req.FromLevel, nodes)
+ if auxTrie != nil {
+ auxTrie.Prove(req.Key, req.FromLevel, nodes)
}
if req.AuxReq != 0 {
data := pm.getHelperTrieAuxData(req)
@@ -924,11 +934,13 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
auxBytes += len(data)
}
}
+ if nodes.DataSize()+auxBytes >= softResponseLimit {
+ break
+ }
}
- proofs := nodes.NodeList()
bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
- return p.SendHelperTrieProofs(req.ReqID, bv, HelperTrieResps{Proofs: proofs, AuxData: auxData})
+ return p.SendHelperTrieProofs(req.ReqID, bv, HelperTrieResps{Proofs: nodes.NodeList(), AuxData: auxData})
case HeaderProofsMsg:
if pm.odr == nil {
@@ -1014,7 +1026,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
for i, stat := range stats {
if stat.Status == core.TxStatusUnknown {
if errs := pm.txpool.AddRemotes([]*types.Transaction{req.Txs[i]}); errs[0] != nil {
- stats[i].Error = errs[0]
+ stats[i].Error = errs[0].Error()
continue
}
stats[i] = pm.txStatus([]common.Hash{hashes[i]})[0]
@@ -1055,7 +1067,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
p.Log().Trace("Received tx status response")
var resp struct {
ReqID, BV uint64
- Status []core.TxStatus
+ Status []txStatus
}
if err := msg.Decode(&resp); err != nil {
return errResp(ErrDecode, "msg %v: %v", msg, err)
@@ -1080,11 +1092,28 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
return nil
}
+// getAccount retrieves an account from the state based at root.
+func (pm *ProtocolManager) getAccount(statedb *state.StateDB, root, hash common.Hash) (state.Account, error) {
+ trie, err := trie.New(root, statedb.Database().TrieDB())
+ if err != nil {
+ return state.Account{}, err
+ }
+ blob, err := trie.TryGet(hash[:])
+ if err != nil {
+ return state.Account{}, err
+ }
+ var account state.Account
+ if err = rlp.DecodeBytes(blob, &account); err != nil {
+ return state.Account{}, err
+ }
+ return account, nil
+}
+
// getHelperTrie returns the post-processed trie root for the given trie ID and section index
func (pm *ProtocolManager) getHelperTrie(id uint, idx uint64) (common.Hash, string) {
switch id {
case htCanonical:
- sectionHead := core.GetCanonicalHash(pm.chainDb, (idx+1)*light.ChtFrequency-1)
+ sectionHead := core.GetCanonicalHash(pm.chainDb, (idx+1)*light.CHTFrequencyClient-1)
return light.GetChtV2Root(pm.chainDb, idx, sectionHead), light.ChtTablePrefix
case htBloomBits:
sectionHead := core.GetCanonicalHash(pm.chainDb, (idx+1)*light.BloomTrieFrequency-1)
@@ -1095,10 +1124,8 @@ func (pm *ProtocolManager) getHelperTrie(id uint, idx uint64) (common.Hash, stri
// getHelperTrieAuxData returns requested auxiliary data for the given HelperTrie request
func (pm *ProtocolManager) getHelperTrieAuxData(req HelperTrieReq) []byte {
- if req.HelperTrieType == htCanonical && req.AuxReq == auxHeader {
- if len(req.Key) != 8 {
- return nil
- }
+ switch {
+ case req.Type == htCanonical && req.AuxReq == auxHeader && len(req.Key) == 8:
blockNum := binary.BigEndian.Uint64(req.Key)
hash := core.GetCanonicalHash(pm.chainDb, blockNum)
return core.GetHeaderRLP(pm.chainDb, hash, blockNum)
@@ -1135,12 +1162,15 @@ type NodeInfo struct {
// NodeInfo retrieves some protocol metadata about the running host node.
func (self *ProtocolManager) NodeInfo() *NodeInfo {
+ head := self.blockchain.CurrentHeader()
+ hash := head.Hash()
+
return &NodeInfo{
Network: self.networkId,
- Difficulty: self.blockchain.GetTdByHash(self.blockchain.LastBlockHash()),
+ Difficulty: self.blockchain.GetTd(hash, head.Number.Uint64()),
Genesis: self.blockchain.Genesis().Hash(),
Config: self.blockchain.Config(),
- Head: self.blockchain.LastBlockHash(),
+ Head: hash,
}
}
diff --git a/les/handler_test.go b/les/handler_test.go
index 6207061cc..9468032f6 100644
--- a/les/handler_test.go
+++ b/les/handler_test.go
@@ -17,7 +17,7 @@
package les
import (
- "bytes"
+ "encoding/binary"
"math/big"
"math/rand"
"testing"
@@ -45,27 +45,8 @@ func expectResponse(r p2p.MsgReader, msgcode, reqID, bv uint64, data interface{}
return p2p.ExpectMsg(r, msgcode, resp{reqID, bv, data})
}
-func testCheckProof(t *testing.T, exp *light.NodeSet, got light.NodeList) {
- if exp.KeyCount() > len(got) {
- t.Errorf("proof has fewer nodes than expected")
- return
- }
- if exp.KeyCount() < len(got) {
- t.Errorf("proof has more nodes than expected")
- return
- }
- for _, node := range got {
- n, _ := exp.Get(crypto.Keccak256(node))
- if !bytes.Equal(n, node) {
- t.Errorf("proof contents mismatch")
- return
- }
- }
-}
-
// Tests that block headers can be retrieved from a remote chain based on user queries.
func TestGetBlockHeadersLes1(t *testing.T) { testGetBlockHeaders(t, 1) }
-
func TestGetBlockHeadersLes2(t *testing.T) { testGetBlockHeaders(t, 2) }
func testGetBlockHeaders(t *testing.T, protocol int) {
@@ -196,7 +177,6 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
// Tests that block contents can be retrieved from a remote chain based on their hashes.
func TestGetBlockBodiesLes1(t *testing.T) { testGetBlockBodies(t, 1) }
-
func TestGetBlockBodiesLes2(t *testing.T) { testGetBlockBodies(t, 2) }
func testGetBlockBodies(t *testing.T, protocol int) {
@@ -274,7 +254,6 @@ func testGetBlockBodies(t *testing.T, protocol int) {
// Tests that the contract codes can be retrieved based on account addresses.
func TestGetCodeLes1(t *testing.T) { testGetCode(t, 1) }
-
func TestGetCodeLes2(t *testing.T) { testGetCode(t, 2) }
func testGetCode(t *testing.T, protocol int) {
@@ -309,7 +288,6 @@ func testGetCode(t *testing.T, protocol int) {
// Tests that the transaction receipts can be retrieved based on hashes.
func TestGetReceiptLes1(t *testing.T) { testGetReceipt(t, 1) }
-
func TestGetReceiptLes2(t *testing.T) { testGetReceipt(t, 2) }
func testGetReceipt(t *testing.T, protocol int) {
@@ -338,7 +316,6 @@ func testGetReceipt(t *testing.T, protocol int) {
// Tests that trie merkle proofs can be retrieved
func TestGetProofsLes1(t *testing.T) { testGetProofs(t, 1) }
-
func TestGetProofsLes2(t *testing.T) { testGetProofs(t, 2) }
func testGetProofs(t *testing.T, protocol int) {
@@ -359,7 +336,7 @@ func testGetProofs(t *testing.T, protocol int) {
for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ {
header := bc.GetHeaderByNumber(i)
root := header.Root
- trie, _ := trie.New(root, db)
+ trie, _ := trie.New(root, trie.NewDatabase(db))
for _, acc := range accounts {
req := ProofReq{
@@ -389,27 +366,126 @@ func testGetProofs(t *testing.T, protocol int) {
case 2:
cost := peer.GetRequestCost(GetProofsV2Msg, len(proofreqs))
sendRequest(peer.app, GetProofsV2Msg, 42, cost, proofreqs)
- msg, err := peer.app.ReadMsg()
- if err != nil {
- t.Errorf("Message read error: %v", err)
- }
- var resp struct {
- ReqID, BV uint64
- Data light.NodeList
- }
- if err := msg.Decode(&resp); err != nil {
- t.Errorf("reply decode error: %v", err)
+ if err := expectResponse(peer.app, ProofsV2Msg, 42, testBufLimit, proofsV2.NodeList()); err != nil {
+ t.Errorf("proofs mismatch: %v", err)
}
- if msg.Code != ProofsV2Msg {
- t.Errorf("Message code mismatch")
+ }
+}
+
+// Tests that CHT proofs can be correctly retrieved.
+func TestGetCHTProofsLes1(t *testing.T) { testGetCHTProofs(t, 1) }
+func TestGetCHTProofsLes2(t *testing.T) { testGetCHTProofs(t, 2) }
+
+func testGetCHTProofs(t *testing.T, protocol int) {
+ // Figure out the client's CHT frequency
+ frequency := uint64(light.CHTFrequencyClient)
+ if protocol == 1 {
+ frequency = uint64(light.CHTFrequencyServer)
+ }
+ // Assemble the test environment
+ db, _ := ethdb.NewMemDatabase()
+ pm := newTestProtocolManagerMust(t, false, int(frequency)+light.HelperTrieProcessConfirmations, testChainGen, nil, nil, db)
+ bc := pm.blockchain.(*core.BlockChain)
+ peer, _ := newTestPeer(t, "peer", protocol, pm, true)
+ defer peer.close()
+
+ // Wait a while for the CHT indexer to process the new headers
+ time.Sleep(100 * time.Millisecond * time.Duration(frequency/light.CHTFrequencyServer)) // Chain indexer throttling
+ time.Sleep(250 * time.Millisecond) // CI tester slack
+
+ // Assemble the proofs from the different protocols
+ header := bc.GetHeaderByNumber(frequency)
+ rlp, _ := rlp.EncodeToBytes(header)
+
+ key := make([]byte, 8)
+ binary.BigEndian.PutUint64(key, frequency)
+
+ proofsV1 := []ChtResp{{
+ Header: header,
+ }}
+ proofsV2 := HelperTrieResps{
+ AuxData: [][]byte{rlp},
+ }
+ switch protocol {
+ case 1:
+ root := light.GetChtRoot(db, 0, bc.GetHeaderByNumber(frequency-1).Hash())
+ trie, _ := trie.New(root, trie.NewDatabase(ethdb.NewTable(db, light.ChtTablePrefix)))
+
+ var proof light.NodeList
+ trie.Prove(key, 0, &proof)
+ proofsV1[0].Proof = proof
+
+ case 2:
+ root := light.GetChtV2Root(db, 0, bc.GetHeaderByNumber(frequency-1).Hash())
+ trie, _ := trie.New(root, trie.NewDatabase(ethdb.NewTable(db, light.ChtTablePrefix)))
+ trie.Prove(key, 0, &proofsV2.Proofs)
+ }
+ // Assemble the requests for the different protocols
+ requestsV1 := []ChtReq{{
+ ChtNum: 1,
+ BlockNum: frequency,
+ }}
+ requestsV2 := []HelperTrieReq{{
+ Type: htCanonical,
+ TrieIdx: 0,
+ Key: key,
+ AuxReq: auxHeader,
+ }}
+ // Send the proof request and verify the response
+ switch protocol {
+ case 1:
+ cost := peer.GetRequestCost(GetHeaderProofsMsg, len(requestsV1))
+ sendRequest(peer.app, GetHeaderProofsMsg, 42, cost, requestsV1)
+ if err := expectResponse(peer.app, HeaderProofsMsg, 42, testBufLimit, proofsV1); err != nil {
+ t.Errorf("proofs mismatch: %v", err)
}
- if resp.ReqID != 42 {
- t.Errorf("ReqID mismatch")
+ case 2:
+ cost := peer.GetRequestCost(GetHelperTrieProofsMsg, len(requestsV2))
+ sendRequest(peer.app, GetHelperTrieProofsMsg, 42, cost, requestsV2)
+ if err := expectResponse(peer.app, HelperTrieProofsMsg, 42, testBufLimit, proofsV2); err != nil {
+ t.Errorf("proofs mismatch: %v", err)
}
- if resp.BV != testBufLimit {
- t.Errorf("BV mismatch")
+ }
+}
+
+// Tests that bloombits proofs can be correctly retrieved.
+func TestGetBloombitsProofs(t *testing.T) {
+ // Assemble the test environment
+ db, _ := ethdb.NewMemDatabase()
+ pm := newTestProtocolManagerMust(t, false, light.BloomTrieFrequency+256, testChainGen, nil, nil, db)
+ bc := pm.blockchain.(*core.BlockChain)
+ peer, _ := newTestPeer(t, "peer", 2, pm, true)
+ defer peer.close()
+
+ // Wait a while for the bloombits indexer to process the new headers
+ time.Sleep(100 * time.Millisecond * time.Duration(light.BloomTrieFrequency/4096)) // Chain indexer throttling
+ time.Sleep(250 * time.Millisecond) // CI tester slack
+
+ // Request and verify each bit of the bloom bits proofs
+ for bit := 0; bit < 2048; bit++ {
+ // Assemble therequest and proofs for the bloombits
+ key := make([]byte, 10)
+
+ binary.BigEndian.PutUint16(key[:2], uint16(bit))
+ binary.BigEndian.PutUint64(key[2:], uint64(light.BloomTrieFrequency))
+
+ requests := []HelperTrieReq{{
+ Type: htBloomBits,
+ TrieIdx: 0,
+ Key: key,
+ }}
+ var proofs HelperTrieResps
+
+ root := light.GetBloomTrieRoot(db, 0, bc.GetHeaderByNumber(light.BloomTrieFrequency-1).Hash())
+ trie, _ := trie.New(root, trie.NewDatabase(ethdb.NewTable(db, light.BloomTrieTablePrefix)))
+ trie.Prove(key, 0, &proofs.Proofs)
+
+ // Send the proof request and verify the response
+ cost := peer.GetRequestCost(GetHelperTrieProofsMsg, len(requests))
+ sendRequest(peer.app, GetHelperTrieProofsMsg, 42, cost, requests)
+ if err := expectResponse(peer.app, HelperTrieProofsMsg, 42, testBufLimit, proofs); err != nil {
+ t.Errorf("bit %d: proofs mismatch: %v", bit, err)
}
- testCheckProof(t, proofsV2, resp.Data)
}
}
@@ -443,16 +519,16 @@ func TestTransactionStatusLes2(t *testing.T) {
signer := types.HomesteadSigner{}
// test error status by sending an underpriced transaction
- tx0, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey)
- test(tx0, true, txStatus{Status: core.TxStatusUnknown, Error: core.ErrUnderpriced})
+ tx0, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey)
+ test(tx0, true, txStatus{Status: core.TxStatusUnknown, Error: core.ErrUnderpriced.Error()})
- tx1, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), bigTxGas, big.NewInt(100000000000), nil), signer, testBankKey)
+ tx1, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey)
test(tx1, false, txStatus{Status: core.TxStatusUnknown}) // query before sending, should be unknown
test(tx1, true, txStatus{Status: core.TxStatusPending}) // send valid processable tx, should return pending
test(tx1, true, txStatus{Status: core.TxStatusPending}) // adding it again should not return an error
- tx2, _ := types.SignTx(types.NewTransaction(1, acc1Addr, big.NewInt(10000), bigTxGas, big.NewInt(100000000000), nil), signer, testBankKey)
- tx3, _ := types.SignTx(types.NewTransaction(2, acc1Addr, big.NewInt(10000), bigTxGas, big.NewInt(100000000000), nil), signer, testBankKey)
+ tx2, _ := types.SignTx(types.NewTransaction(1, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey)
+ tx3, _ := types.SignTx(types.NewTransaction(2, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey)
// send transactions in the wrong order, tx3 should be queued
test(tx3, true, txStatus{Status: core.TxStatusQueued})
test(tx2, true, txStatus{Status: core.TxStatusPending})
diff --git a/les/helper_test.go b/les/helper_test.go
index 92a98e27e..6d997a1a3 100644
--- a/les/helper_test.go
+++ b/les/helper_test.go
@@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/les/flowcontrol"
@@ -55,9 +56,10 @@ var (
testContractCodeDeployed = testContractCode[16:]
testContractDeployed = uint64(2)
- testBufLimit = uint64(100)
+ testEventEmitterCode = common.Hex2Bytes("60606040523415600e57600080fd5b7f57050ab73f6b9ebdd9f76b8d4997793f48cf956e965ee070551b9ca0bb71584e60405160405180910390a160358060476000396000f3006060604052600080fd00a165627a7a723058203f727efcad8b5811f8cb1fc2620ce5e8c63570d697aef968172de296ea3994140029")
+ testEventEmitterAddr common.Address
- bigTxGas = new(big.Int).SetUint64(params.TxGas)
+ testBufLimit = uint64(100)
)
/*
@@ -81,27 +83,31 @@ func testChainGen(i int, block *core.BlockGen) {
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
- tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey)
+ tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
// acc1Addr creates a test contract.
- tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, testBankKey)
+ // acc1Addr creates a test event.
nonce := block.TxNonce(acc1Addr)
- tx2, _ := types.SignTx(types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, acc1Key)
- nonce++
- tx3, _ := types.SignTx(types.NewContractCreation(nonce, big.NewInt(0), big.NewInt(200000), big.NewInt(0), testContractCode), signer, acc1Key)
- testContractAddr = crypto.CreateAddress(acc1Addr, nonce)
+
+ tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey)
+ tx2, _ := types.SignTx(types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key)
+ tx3, _ := types.SignTx(types.NewContractCreation(nonce+1, big.NewInt(0), 200000, big.NewInt(0), testContractCode), signer, acc1Key)
+ testContractAddr = crypto.CreateAddress(acc1Addr, nonce+1)
+ tx4, _ := types.SignTx(types.NewContractCreation(nonce+2, big.NewInt(0), 200000, big.NewInt(0), testEventEmitterCode), signer, acc1Key)
+ testEventEmitterAddr = crypto.CreateAddress(acc1Addr, nonce+2)
block.AddTx(tx1)
block.AddTx(tx2)
block.AddTx(tx3)
+ block.AddTx(tx4)
case 2:
// Block 3 is empty but was mined by account #2.
block.SetCoinbase(acc2Addr)
block.SetExtra([]byte("yeehaw"))
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001")
- tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data), signer, testBankKey)
+ tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data), signer, testBankKey)
block.AddTx(tx)
case 3:
// Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data).
@@ -112,7 +118,7 @@ func testChainGen(i int, block *core.BlockGen) {
b3.Extra = []byte("foo")
block.AddUncle(b3)
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002")
- tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data), signer, testBankKey)
+ tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data), signer, testBankKey)
block.AddTx(tx)
}
}
@@ -148,7 +154,17 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
if lightSync {
chain, _ = light.NewLightChain(odr, gspec.Config, engine)
} else {
- blockchain, _ := core.NewBlockChain(db, gspec.Config, engine, vm.Config{})
+ blockchain, _ := core.NewBlockChain(db, nil, gspec.Config, engine, vm.Config{})
+
+ chtIndexer := light.NewChtIndexer(db, false)
+ chtIndexer.Start(blockchain)
+
+ bbtIndexer := light.NewBloomTrieIndexer(db, false)
+
+ bloomIndexer := eth.NewBloomIndexer(db, params.BloomBitsBlocks)
+ bloomIndexer.AddChildIndexer(bbtIndexer)
+ bloomIndexer.Start(blockchain)
+
gchain, _ := core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, blocks, generator)
if _, err := blockchain.InsertChain(gchain); err != nil {
panic(err)
@@ -178,7 +194,7 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
srv.fcManager = flowcontrol.NewClientManager(50, 10, 1000000000)
srv.fcCostStats = newCostStats(nil)
}
- pm.Start()
+ pm.Start(1000)
return pm, nil
}
@@ -229,9 +245,12 @@ func newTestPeer(t *testing.T, name string, version int, pm *ProtocolManager, sh
}
// Execute any implicitly requested handshakes and return
if shake {
- td, head, genesis := pm.blockchain.Status()
- headNum := pm.blockchain.CurrentHeader().Number.Uint64()
- tp.handshake(t, td, head, headNum, genesis)
+ var (
+ genesis = pm.blockchain.Genesis()
+ head = pm.blockchain.CurrentHeader()
+ td = pm.blockchain.GetTd(head.Hash(), head.Number.Uint64())
+ )
+ tp.handshake(t, td, head.Hash(), head.Number.Uint64(), genesis.Hash())
}
return tp, errc
}
diff --git a/les/odr_requests.go b/les/odr_requests.go
index 937a4f1d9..34d759dd2 100644
--- a/les/odr_requests.go
+++ b/les/odr_requests.go
@@ -321,7 +321,7 @@ const (
)
type HelperTrieReq struct {
- HelperTrieType uint
+ Type uint
TrieIdx uint64
Key []byte
FromLevel, AuxReq uint
@@ -365,7 +365,7 @@ func (r *ChtRequest) CanSend(peer *peer) bool {
peer.lock.RLock()
defer peer.lock.RUnlock()
- return peer.headInfo.Number >= light.HelperTrieConfirmations && r.ChtNum <= (peer.headInfo.Number-light.HelperTrieConfirmations)/light.ChtFrequency
+ return peer.headInfo.Number >= light.HelperTrieConfirmations && r.ChtNum <= (peer.headInfo.Number-light.HelperTrieConfirmations)/light.CHTFrequencyClient
}
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
@@ -374,10 +374,10 @@ func (r *ChtRequest) Request(reqID uint64, peer *peer) error {
var encNum [8]byte
binary.BigEndian.PutUint64(encNum[:], r.BlockNum)
req := HelperTrieReq{
- HelperTrieType: htCanonical,
- TrieIdx: r.ChtNum,
- Key: encNum[:],
- AuxReq: auxHeader,
+ Type: htCanonical,
+ TrieIdx: r.ChtNum,
+ Key: encNum[:],
+ AuxReq: auxHeader,
}
return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []HelperTrieReq{req})
}
@@ -493,14 +493,14 @@ func (r *BloomRequest) Request(reqID uint64, peer *peer) error {
reqs := make([]HelperTrieReq, len(r.SectionIdxList))
var encNumber [10]byte
- binary.BigEndian.PutUint16(encNumber[0:2], uint16(r.BitIdx))
+ binary.BigEndian.PutUint16(encNumber[:2], uint16(r.BitIdx))
for i, sectionIdx := range r.SectionIdxList {
- binary.BigEndian.PutUint64(encNumber[2:10], sectionIdx)
+ binary.BigEndian.PutUint64(encNumber[2:], sectionIdx)
reqs[i] = HelperTrieReq{
- HelperTrieType: htBloomBits,
- TrieIdx: r.BloomTrieNum,
- Key: common.CopyBytes(encNumber[:]),
+ Type: htBloomBits,
+ TrieIdx: r.BloomTrieNum,
+ Key: common.CopyBytes(encNumber[:]),
}
}
return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), reqs)
@@ -525,10 +525,10 @@ func (r *BloomRequest) Validate(db ethdb.Database, msg *Msg) error {
// Verify the proofs
var encNumber [10]byte
- binary.BigEndian.PutUint16(encNumber[0:2], uint16(r.BitIdx))
+ binary.BigEndian.PutUint16(encNumber[:2], uint16(r.BitIdx))
for i, idx := range r.SectionIdxList {
- binary.BigEndian.PutUint64(encNumber[2:10], idx)
+ binary.BigEndian.PutUint64(encNumber[2:], idx)
value, err, _ := trie.VerifyProof(r.BloomTrieRoot, encNumber[:], reads)
if err != nil {
return err
diff --git a/les/odr_test.go b/les/odr_test.go
index 865f5d83e..88e121cda 100644
--- a/les/odr_test.go
+++ b/les/odr_test.go
@@ -101,7 +101,6 @@ func odrAccounts(ctx context.Context, db ethdb.Database, config *params.ChainCon
res = append(res, rlp...)
}
}
-
return res
}
@@ -129,13 +128,13 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
from := statedb.GetOrNewStateObject(testBankAddress)
from.SetBalance(math.MaxBig256)
- msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(100000), new(big.Int), data, false)}
+ msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false)}
context := core.NewEVMContext(msg, header, bc, nil)
vmenv := vm.NewEVM(context, statedb, config, vm.Config{})
//vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{})
- gp := new(core.GasPool).AddGas(math.MaxBig256)
+ gp := new(core.GasPool).AddGas(math.MaxUint64)
ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
res = append(res, ret...)
}
@@ -143,10 +142,10 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
header := lc.GetHeaderByHash(bhash)
state := light.NewState(ctx, header, lc.Odr())
state.SetBalance(testBankAddress, math.MaxBig256)
- msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), big.NewInt(100000), new(big.Int), data, false)}
+ msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false)}
context := core.NewEVMContext(msg, header, lc, nil)
vmenv := vm.NewEVM(context, state, config, vm.Config{})
- gp := new(core.GasPool).AddGas(math.MaxBig256)
+ gp := new(core.GasPool).AddGas(math.MaxUint64)
ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
if state.Error() == nil {
res = append(res, ret...)
diff --git a/les/peer.go b/les/peer.go
index 04d747a6b..caf568077 100644
--- a/les/peer.go
+++ b/les/peer.go
@@ -281,7 +281,6 @@ func (p *peer) RequestProofs(reqID, cost uint64, reqs []ProofReq) error {
default:
panic(nil)
}
-
}
// RequestHelperTrieProofs fetches a batch of HelperTrie merkle proofs from a remote node.
@@ -291,12 +290,12 @@ func (p *peer) RequestHelperTrieProofs(reqID, cost uint64, reqs []HelperTrieReq)
case lpv1:
reqsV1 := make([]ChtReq, len(reqs))
for i, req := range reqs {
- if req.HelperTrieType != htCanonical || req.AuxReq != auxHeader || len(req.Key) != 8 {
+ if req.Type != htCanonical || req.AuxReq != auxHeader || len(req.Key) != 8 {
return fmt.Errorf("Request invalid in LES/1 mode")
}
blockNum := binary.BigEndian.Uint64(req.Key)
// convert HelperTrie request to old CHT request
- reqsV1[i] = ChtReq{ChtNum: (req.TrieIdx+1)*(light.ChtFrequency/light.ChtV1Frequency) - 1, BlockNum: blockNum, FromLevel: req.FromLevel}
+ reqsV1[i] = ChtReq{ChtNum: (req.TrieIdx + 1) * (light.CHTFrequencyClient / light.CHTFrequencyServer), BlockNum: blockNum, FromLevel: req.FromLevel}
}
return sendRequest(p.rw, GetHeaderProofsMsg, reqID, cost, reqsV1)
case lpv2:
diff --git a/les/protocol.go b/les/protocol.go
index 05e6654d6..e1c4625bc 100644
--- a/les/protocol.go
+++ b/les/protocol.go
@@ -41,8 +41,9 @@ const (
// Supported versions of the les protocol (first is primary)
var (
- ClientProtocolVersions = []uint{lpv2, lpv1}
- ServerProtocolVersions = []uint{lpv2, lpv1}
+ ClientProtocolVersions = []uint{lpv2, lpv1}
+ ServerProtocolVersions = []uint{lpv2, lpv1}
+ AdvertiseProtocolVersions = []uint{lpv2} // clients are searching for the first advertised protocol in the list
)
// Number of implemented message corresponding to different protocol versions.
@@ -223,6 +224,6 @@ type proofsData [][]rlp.RawValue
type txStatus struct {
Status core.TxStatus
- Lookup *core.TxLookupEntry
- Error error
+ Lookup *core.TxLookupEntry `rlp:"nil"`
+ Error string
}
diff --git a/les/retrieve.go b/les/retrieve.go
index dd15b56ac..e262a3cb4 100644
--- a/les/retrieve.go
+++ b/les/retrieve.go
@@ -1,4 +1,4 @@
-// Copyright 2016 The go-ethereum Authors
+// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
diff --git a/les/server.go b/les/server.go
index d8f93cd87..28b87008a 100644
--- a/les/server.go
+++ b/les/server.go
@@ -20,7 +20,6 @@ package les
import (
"crypto/ecdsa"
"encoding/binary"
- "fmt"
"math"
"sync"
@@ -38,6 +37,7 @@ import (
)
type LesServer struct {
+ config *eth.Config
protocolManager *ProtocolManager
fcManager *flowcontrol.ClientManager // nil if our node is client only
fcCostStats *requestCostStats
@@ -56,12 +56,13 @@ func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
return nil, err
}
- lesTopics := make([]discv5.Topic, len(ServerProtocolVersions))
- for i, pv := range ServerProtocolVersions {
+ lesTopics := make([]discv5.Topic, len(AdvertiseProtocolVersions))
+ for i, pv := range AdvertiseProtocolVersions {
lesTopics[i] = lesTopic(eth.BlockChain().Genesis().Hash(), pv)
}
srv := &LesServer{
+ config: config,
protocolManager: pm,
quitSync: quitSync,
lesTopics: lesTopics,
@@ -71,23 +72,22 @@ func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
logger := log.New()
chtV1SectionCount, _, _ := srv.chtIndexer.Sections() // indexer still uses LES/1 4k section size for backwards server compatibility
- chtV2SectionCount := chtV1SectionCount / (light.ChtFrequency / light.ChtV1Frequency)
+ chtV2SectionCount := chtV1SectionCount / (light.CHTFrequencyClient / light.CHTFrequencyServer)
if chtV2SectionCount != 0 {
// convert to LES/2 section
chtLastSection := chtV2SectionCount - 1
// convert last LES/2 section index back to LES/1 index for chtIndexer.SectionHead
- chtLastSectionV1 := (chtLastSection+1)*(light.ChtFrequency/light.ChtV1Frequency) - 1
+ chtLastSectionV1 := (chtLastSection+1)*(light.CHTFrequencyClient/light.CHTFrequencyServer) - 1
chtSectionHead := srv.chtIndexer.SectionHead(chtLastSectionV1)
chtRoot := light.GetChtV2Root(pm.chainDb, chtLastSection, chtSectionHead)
- logger.Info("CHT", "section", chtLastSection, "sectionHead", fmt.Sprintf("%064x", chtSectionHead), "root", fmt.Sprintf("%064x", chtRoot))
+ logger.Info("Loaded CHT", "section", chtLastSection, "head", chtSectionHead, "root", chtRoot)
}
-
bloomTrieSectionCount, _, _ := srv.bloomTrieIndexer.Sections()
if bloomTrieSectionCount != 0 {
bloomTrieLastSection := bloomTrieSectionCount - 1
bloomTrieSectionHead := srv.bloomTrieIndexer.SectionHead(bloomTrieLastSection)
bloomTrieRoot := light.GetBloomTrieRoot(pm.chainDb, bloomTrieLastSection, bloomTrieSectionHead)
- logger.Info("BloomTrie", "section", bloomTrieLastSection, "sectionHead", fmt.Sprintf("%064x", bloomTrieSectionHead), "root", fmt.Sprintf("%064x", bloomTrieRoot))
+ logger.Info("Loaded bloom trie", "section", bloomTrieLastSection, "head", bloomTrieSectionHead, "root", bloomTrieRoot)
}
srv.chtIndexer.Start(eth.BlockChain())
@@ -108,16 +108,18 @@ func (s *LesServer) Protocols() []p2p.Protocol {
// Start starts the LES server
func (s *LesServer) Start(srvr *p2p.Server) {
- s.protocolManager.Start()
- for _, topic := range s.lesTopics {
- topic := topic
- go func() {
- logger := log.New("topic", topic)
- logger.Info("Starting topic registration")
- defer logger.Info("Terminated topic registration")
-
- srvr.DiscV5.RegisterTopic(topic, s.quitSync)
- }()
+ s.protocolManager.Start(s.config.LightPeers)
+ if srvr.DiscV5 != nil {
+ for _, topic := range s.lesTopics {
+ topic := topic
+ go func() {
+ logger := log.New("topic", topic)
+ logger.Info("Starting topic registration")
+ defer logger.Info("Terminated topic registration")
+
+ srvr.DiscV5.RegisterTopic(topic, s.quitSync)
+ }()
+ }
}
s.privateKey = srvr.PrivateKey
s.protocolManager.blockLoop()
diff --git a/les/serverpool.go b/les/serverpool.go
index dc1ea6bf0..a84c29c3a 100644
--- a/les/serverpool.go
+++ b/les/serverpool.go
@@ -618,7 +618,7 @@ func (e *knownEntry) Weight() int64 {
if e.state != psNotConnected || !e.known || e.delayedRetry {
return 0
}
- return int64(1000000000 * e.connectStats.recentAvg() * math.Exp(-float64(e.lastConnected.fails)*failDropLn-e.responseStats.recentAvg()/float64(responseScoreTC)-e.delayStats.recentAvg()/float64(delayScoreTC)) * math.Pow((1-e.timeoutStats.recentAvg()), timeoutPow))
+ return int64(1000000000 * e.connectStats.recentAvg() * math.Exp(-float64(e.lastConnected.fails)*failDropLn-e.responseStats.recentAvg()/float64(responseScoreTC)-e.delayStats.recentAvg()/float64(delayScoreTC)) * math.Pow(1-e.timeoutStats.recentAvg(), timeoutPow))
}
// poolEntryAddress is a separate object because currently it is necessary to remember
diff --git a/light/lightchain.go b/light/lightchain.go
index c5c2dcf46..181a1c2a6 100644
--- a/light/lightchain.go
+++ b/light/lightchain.go
@@ -18,6 +18,7 @@ package light
import (
"context"
+ "errors"
"math/big"
"sync"
"sync/atomic"
@@ -26,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
@@ -98,7 +100,6 @@ func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus.
if cp, ok := trustedCheckpoints[bc.genesisBlock.Hash()]; ok {
bc.addTrustedCheckpoint(cp)
}
-
if err := bc.loadLastState(); err != nil {
return nil, err
}
@@ -126,7 +127,7 @@ func (self *LightChain) addTrustedCheckpoint(cp trustedCheckpoint) {
if self.odr.BloomIndexer() != nil {
self.odr.BloomIndexer().AddKnownSectionHead(cp.sectionIdx, cp.sectionHead)
}
- log.Info("Added trusted checkpoint", "chain name", cp.name)
+ log.Info("Added trusted checkpoint", "chain", cp.name, "block", (cp.sectionIdx+1)*CHTFrequencyClient-1, "hash", cp.sectionHead)
}
func (self *LightChain) getProcInterrupt() bool {
@@ -169,32 +170,13 @@ func (bc *LightChain) SetHead(head uint64) {
}
// GasLimit returns the gas limit of the current HEAD block.
-func (self *LightChain) GasLimit() *big.Int {
+func (self *LightChain) GasLimit() uint64 {
self.mu.RLock()
defer self.mu.RUnlock()
return self.hc.CurrentHeader().GasLimit
}
-// LastBlockHash return the hash of the HEAD block.
-func (self *LightChain) LastBlockHash() common.Hash {
- self.mu.RLock()
- defer self.mu.RUnlock()
-
- return self.hc.CurrentHeader().Hash()
-}
-
-// Status returns status information about the current chain such as the HEAD Td,
-// the HEAD hash and the hash of the genesis block.
-func (self *LightChain) Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash) {
- self.mu.RLock()
- defer self.mu.RUnlock()
-
- header := self.hc.CurrentHeader()
- hash := header.Hash()
- return self.GetTd(hash, header.Number.Uint64()), hash, self.genesisBlock.Hash()
-}
-
// Reset purges the entire blockchain, restoring it to its genesis state.
func (bc *LightChain) Reset() {
bc.ResetWithGenesisBlock(bc.genesisBlock)
@@ -231,6 +213,11 @@ func (bc *LightChain) Genesis() *types.Block {
return bc.genesisBlock
}
+// State returns a new mutable state based on the current HEAD block.
+func (bc *LightChain) State() (*state.StateDB, error) {
+ return nil, errors.New("not implemented, needs client/server interface split")
+}
+
// GetBody retrieves a block body (transactions and uncles) from the database
// or ODR service by hash, caching it if found.
func (self *LightChain) GetBody(ctx context.Context, hash common.Hash) (*types.Body, error) {
@@ -337,7 +324,7 @@ func (self *LightChain) postChainEvents(events []interface{}) {
for _, event := range events {
switch ev := event.(type) {
case core.ChainEvent:
- if self.LastBlockHash() == ev.Hash {
+ if self.CurrentHeader().Hash() == ev.Hash {
self.chainHeadFeed.Send(core.ChainHeadEvent{Block: ev.Block})
}
self.chainFeed.Send(ev)
@@ -393,7 +380,7 @@ func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int)
return err
}
i, err := self.hc.InsertHeaderChain(chain, whFunc, start)
- go self.postChainEvents(events)
+ self.postChainEvents(events)
return i, err
}
@@ -466,8 +453,8 @@ func (self *LightChain) SyncCht(ctx context.Context) bool {
}
headNum := self.CurrentHeader().Number.Uint64()
chtCount, _, _ := self.odr.ChtIndexer().Sections()
- if headNum+1 < chtCount*ChtFrequency {
- num := chtCount*ChtFrequency - 1
+ if headNum+1 < chtCount*CHTFrequencyClient {
+ num := chtCount*CHTFrequencyClient - 1
header, err := GetHeaderByNumber(ctx, self.odr, num)
if header != nil && err == nil {
self.mu.Lock()
diff --git a/light/nodeset.go b/light/nodeset.go
index c530a4fbe..6f25219c1 100644
--- a/light/nodeset.go
+++ b/light/nodeset.go
@@ -1,4 +1,4 @@
-// Copyright 2014 The go-ethereum Authors
+// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
@@ -22,14 +22,16 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie"
)
// NodeSet stores a set of trie nodes. It implements trie.Database and can also
// act as a cache for another trie.Database.
type NodeSet struct {
- db map[string][]byte
+ nodes map[string][]byte
+ order []string
+
dataSize int
lock sync.RWMutex
}
@@ -37,7 +39,7 @@ type NodeSet struct {
// NewNodeSet creates an empty node set
func NewNodeSet() *NodeSet {
return &NodeSet{
- db: make(map[string][]byte),
+ nodes: make(map[string][]byte),
}
}
@@ -46,10 +48,15 @@ func (db *NodeSet) Put(key []byte, value []byte) error {
db.lock.Lock()
defer db.lock.Unlock()
- if _, ok := db.db[string(key)]; !ok {
- db.db[string(key)] = common.CopyBytes(value)
- db.dataSize += len(value)
+ if _, ok := db.nodes[string(key)]; ok {
+ return nil
}
+ keystr := string(key)
+
+ db.nodes[keystr] = common.CopyBytes(value)
+ db.order = append(db.order, keystr)
+ db.dataSize += len(value)
+
return nil
}
@@ -58,7 +65,7 @@ func (db *NodeSet) Get(key []byte) ([]byte, error) {
db.lock.RLock()
defer db.lock.RUnlock()
- if entry, ok := db.db[string(key)]; ok {
+ if entry, ok := db.nodes[string(key)]; ok {
return entry, nil
}
return nil, errors.New("not found")
@@ -75,7 +82,7 @@ func (db *NodeSet) KeyCount() int {
db.lock.RLock()
defer db.lock.RUnlock()
- return len(db.db)
+ return len(db.nodes)
}
// DataSize returns the aggregated data size of nodes in the set
@@ -92,27 +99,27 @@ func (db *NodeSet) NodeList() NodeList {
defer db.lock.RUnlock()
var values NodeList
- for _, value := range db.db {
- values = append(values, value)
+ for _, key := range db.order {
+ values = append(values, db.nodes[key])
}
return values
}
// Store writes the contents of the set to the given database
-func (db *NodeSet) Store(target trie.Database) {
+func (db *NodeSet) Store(target ethdb.Putter) {
db.lock.RLock()
defer db.lock.RUnlock()
- for key, value := range db.db {
+ for key, value := range db.nodes {
target.Put([]byte(key), value)
}
}
-// NodeList stores an ordered list of trie nodes. It implements trie.DatabaseWriter.
+// NodeList stores an ordered list of trie nodes. It implements ethdb.Putter.
type NodeList []rlp.RawValue
// Store writes the contents of the list to the given database
-func (n NodeList) Store(db trie.Database) {
+func (n NodeList) Store(db ethdb.Putter) {
for _, node := range n {
db.Put(crypto.Keccak256(node), node)
}
diff --git a/light/odr_test.go b/light/odr_test.go
index c0eb409f9..d3f9374fd 100644
--- a/light/odr_test.go
+++ b/light/odr_test.go
@@ -50,8 +50,6 @@ var (
testContractCode = common.Hex2Bytes("606060405260cc8060106000396000f360606040526000357c01000000000000000000000000000000000000000000000000000000009004806360cd2685146041578063c16431b914606b57603f565b005b6055600480803590602001909190505060a9565b6040518082815260200191505060405180910390f35b60886004808035906020019091908035906020019091905050608a565b005b80600060005083606481101560025790900160005b50819055505b5050565b6000600060005082606481101560025790900160005b5054905060c7565b91905056")
testContractAddr common.Address
-
- bigTxGas = new(big.Int).SetUint64(params.TxGas)
)
type testOdr struct {
@@ -76,7 +74,7 @@ func (odr *testOdr) Retrieve(ctx context.Context, req OdrRequest) error {
case *ReceiptsRequest:
req.Receipts = core.GetBlockReceipts(odr.sdb, req.Hash, core.GetBlockNumber(odr.sdb, req.Hash))
case *TrieRequest:
- t, _ := trie.New(req.Id.Root, odr.sdb)
+ t, _ := trie.New(req.Id.Root, trie.NewDatabase(odr.sdb))
nodes := NewNodeSet()
t.Prove(req.Key, 0, nodes)
req.Proof = nodes
@@ -178,10 +176,10 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
// Perform read-only call.
st.SetBalance(testBankAddress, math.MaxBig256)
- msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data, false)}
+ msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, new(big.Int), data, false)}
context := core.NewEVMContext(msg, header, chain, nil)
vmenv := vm.NewEVM(context, st, config, vm.Config{})
- gp := new(core.GasPool).AddGas(math.MaxBig256)
+ gp := new(core.GasPool).AddGas(math.MaxUint64)
ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
res = append(res, ret...)
if st.Error() != nil {
@@ -196,17 +194,17 @@ func testChainGen(i int, block *core.BlockGen) {
switch i {
case 0:
// In block 1, the test bank sends account #1 some ether.
- tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey)
+ tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey)
block.AddTx(tx)
case 1:
// In block 2, the test bank sends some more ether to account #1.
// acc1Addr passes it on to account #2.
// acc1Addr creates a test contract.
- tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, testBankKey)
+ tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey)
nonce := block.TxNonce(acc1Addr)
- tx2, _ := types.SignTx(types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, acc1Key)
+ tx2, _ := types.SignTx(types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key)
nonce++
- tx3, _ := types.SignTx(types.NewContractCreation(nonce, big.NewInt(0), big.NewInt(1000000), big.NewInt(0), testContractCode), signer, acc1Key)
+ tx3, _ := types.SignTx(types.NewContractCreation(nonce, big.NewInt(0), 1000000, big.NewInt(0), testContractCode), signer, acc1Key)
testContractAddr = crypto.CreateAddress(acc1Addr, nonce)
block.AddTx(tx1)
block.AddTx(tx2)
@@ -216,7 +214,7 @@ func testChainGen(i int, block *core.BlockGen) {
block.SetCoinbase(acc2Addr)
block.SetExtra([]byte("yeehaw"))
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001")
- tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data), signer, testBankKey)
+ tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data), signer, testBankKey)
block.AddTx(tx)
case 3:
// Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data).
@@ -227,7 +225,7 @@ func testChainGen(i int, block *core.BlockGen) {
b3.Extra = []byte("foo")
block.AddUncle(b3)
data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002")
- tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), big.NewInt(100000), nil, data), signer, testBankKey)
+ tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), testContractAddr, big.NewInt(0), 100000, nil, data), signer, testBankKey)
block.AddTx(tx)
}
}
@@ -241,7 +239,7 @@ func testChainOdr(t *testing.T, protocol int, fn odrTestFn) {
)
gspec.MustCommit(ldb)
// Assemble the test environment
- blockchain, _ := core.NewBlockChain(sdb, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{})
+ blockchain, _ := core.NewBlockChain(sdb, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{})
gchain, _ := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), sdb, 4, testChainGen)
if _, err := blockchain.InsertChain(gchain); err != nil {
t.Fatal(err)
diff --git a/light/odr_util.go b/light/odr_util.go
index a0eb6303d..8f92d6442 100644
--- a/light/odr_util.go
+++ b/light/odr_util.go
@@ -52,23 +52,20 @@ func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*typ
for chtCount > 0 && canonicalHash != sectionHead && canonicalHash != (common.Hash{}) {
chtCount--
if chtCount > 0 {
- sectionHeadNum = chtCount*ChtFrequency - 1
+ sectionHeadNum = chtCount*CHTFrequencyClient - 1
sectionHead = odr.ChtIndexer().SectionHead(chtCount - 1)
canonicalHash = core.GetCanonicalHash(db, sectionHeadNum)
}
}
}
-
- if number >= chtCount*ChtFrequency {
+ if number >= chtCount*CHTFrequencyClient {
return nil, ErrNoTrustedCht
}
-
r := &ChtRequest{ChtRoot: GetChtRoot(db, chtCount-1, sectionHead), ChtNum: chtCount - 1, BlockNum: number}
if err := odr.Retrieve(ctx, r); err != nil {
return nil, err
- } else {
- return r.Header, nil
}
+ return r.Header, nil
}
func GetCanonicalHash(ctx context.Context, odr OdrBackend, number uint64) (common.Hash, error) {
diff --git a/light/postprocess.go b/light/postprocess.go
index e7e513880..84149fdaa 100644
--- a/light/postprocess.go
+++ b/light/postprocess.go
@@ -1,4 +1,4 @@
-// Copyright 2016 The go-ethereum Authors
+// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
@@ -19,7 +19,6 @@ package light
import (
"encoding/binary"
"errors"
- "fmt"
"math/big"
"time"
@@ -35,8 +34,14 @@ import (
)
const (
- ChtFrequency = 32768
- ChtV1Frequency = 4096 // as long as we want to retain LES/1 compatibility, servers generate CHTs with the old, higher frequency
+ // CHTFrequencyClient is the block frequency for creating CHTs on the client side.
+ CHTFrequencyClient = 32768
+
+ // CHTFrequencyServer is the block frequency for creating CHTs on the server side.
+ // Eventually this can be merged back with the client version, but that requires a
+ // full database upgrade, so that should be left for a suitable moment.
+ CHTFrequencyServer = 4096
+
HelperTrieConfirmations = 2048 // number of confirmations before a server is expected to have the given HelperTrie available
HelperTrieProcessConfirmations = 256 // number of confirmations before a HelperTrie is generated
)
@@ -52,19 +57,19 @@ type trustedCheckpoint struct {
var (
mainnetCheckpoint = trustedCheckpoint{
- name: "ETH mainnet",
- sectionIdx: 129,
- sectionHead: common.HexToHash("64100587c8ec9a76870056d07cb0f58622552d16de6253a59cac4b580c899501"),
- chtRoot: common.HexToHash("bb4fb4076cbe6923c8a8ce8f158452bbe19564959313466989fda095a60884ca"),
- bloomTrieRoot: common.HexToHash("0db524b2c4a2a9520a42fd842b02d2e8fb58ff37c75cf57bd0eb82daeace6716"),
+ name: "mainnet",
+ sectionIdx: 153,
+ sectionHead: common.HexToHash("04c2114a8cbe49ba5c37a03cc4b4b8d3adfc0bd2c78e0e726405dd84afca1d63"),
+ chtRoot: common.HexToHash("d7ec603e5d30b567a6e894ee7704e4603232f206d3e5a589794cec0c57bf318e"),
+ bloomTrieRoot: common.HexToHash("0b139b8fb692e21f663ff200da287192201c28ef5813c1ac6ba02a0a4799eef9"),
}
ropstenCheckpoint = trustedCheckpoint{
- name: "Ropsten testnet",
- sectionIdx: 50,
- sectionHead: common.HexToHash("00bd65923a1aa67f85e6b4ae67835784dd54be165c37f056691723c55bf016bd"),
- chtRoot: common.HexToHash("6f56dc61936752cc1f8c84b4addabdbe6a1c19693de3f21cb818362df2117f03"),
- bloomTrieRoot: common.HexToHash("aca7d7c504d22737242effc3fdc604a762a0af9ced898036b5986c3a15220208"),
+ name: "ropsten",
+ sectionIdx: 79,
+ sectionHead: common.HexToHash("1b1ba890510e06411fdee9bb64ca7705c56a1a4ce3559ddb34b3680c526cb419"),
+ chtRoot: common.HexToHash("71d60207af74e5a22a3e1cfbfc89f9944f91b49aa980c86fba94d568369eaf44"),
+ bloomTrieRoot: common.HexToHash("70aca4b3b6d08dde8704c95cedb1420394453c1aec390947751e69ff8c436360"),
}
)
@@ -100,7 +105,7 @@ func GetChtRoot(db ethdb.Database, sectionIdx uint64, sectionHead common.Hash) c
// GetChtV2Root reads the CHT root assoctiated to the given section from the database
// Note that sectionIdx is specified according to LES/2 CHT section size
func GetChtV2Root(db ethdb.Database, sectionIdx uint64, sectionHead common.Hash) common.Hash {
- return GetChtRoot(db, (sectionIdx+1)*(ChtFrequency/ChtV1Frequency)-1, sectionHead)
+ return GetChtRoot(db, (sectionIdx+1)*(CHTFrequencyClient/CHTFrequencyServer)-1, sectionHead)
}
// StoreChtRoot writes the CHT root assoctiated to the given section into the database
@@ -113,7 +118,8 @@ func StoreChtRoot(db ethdb.Database, sectionIdx uint64, sectionHead, root common
// ChtIndexerBackend implements core.ChainIndexerBackend
type ChtIndexerBackend struct {
- db, cdb ethdb.Database
+ diskdb ethdb.Database
+ triedb *trie.Database
section, sectionSize uint64
lastHash common.Hash
trie *trie.Trie
@@ -121,27 +127,31 @@ type ChtIndexerBackend struct {
// NewBloomTrieIndexer creates a BloomTrie chain indexer
func NewChtIndexer(db ethdb.Database, clientMode bool) *core.ChainIndexer {
- cdb := ethdb.NewTable(db, ChtTablePrefix)
- idb := ethdb.NewTable(db, "chtIndex-")
var sectionSize, confirmReq uint64
if clientMode {
- sectionSize = ChtFrequency
+ sectionSize = CHTFrequencyClient
confirmReq = HelperTrieConfirmations
} else {
- sectionSize = ChtV1Frequency
+ sectionSize = CHTFrequencyServer
confirmReq = HelperTrieProcessConfirmations
}
- return core.NewChainIndexer(db, idb, &ChtIndexerBackend{db: db, cdb: cdb, sectionSize: sectionSize}, sectionSize, confirmReq, time.Millisecond*100, "cht")
+ idb := ethdb.NewTable(db, "chtIndex-")
+ backend := &ChtIndexerBackend{
+ diskdb: db,
+ triedb: trie.NewDatabase(ethdb.NewTable(db, ChtTablePrefix)),
+ sectionSize: sectionSize,
+ }
+ return core.NewChainIndexer(db, idb, backend, sectionSize, confirmReq, time.Millisecond*100, "cht")
}
// Reset implements core.ChainIndexerBackend
func (c *ChtIndexerBackend) Reset(section uint64, lastSectionHead common.Hash) error {
var root common.Hash
if section > 0 {
- root = GetChtRoot(c.db, section-1, lastSectionHead)
+ root = GetChtRoot(c.diskdb, section-1, lastSectionHead)
}
var err error
- c.trie, err = trie.New(root, c.cdb)
+ c.trie, err = trie.New(root, c.triedb)
c.section = section
return err
}
@@ -151,7 +161,7 @@ func (c *ChtIndexerBackend) Process(header *types.Header) {
hash, num := header.Hash(), header.Number.Uint64()
c.lastHash = hash
- td := core.GetTd(c.db, hash, num)
+ td := core.GetTd(c.diskdb, hash, num)
if td == nil {
panic(nil)
}
@@ -163,17 +173,16 @@ func (c *ChtIndexerBackend) Process(header *types.Header) {
// Commit implements core.ChainIndexerBackend
func (c *ChtIndexerBackend) Commit() error {
- batch := c.cdb.NewBatch()
- root, err := c.trie.CommitTo(batch)
+ root, err := c.trie.Commit(nil)
if err != nil {
return err
- } else {
- batch.Write()
- if ((c.section+1)*c.sectionSize)%ChtFrequency == 0 {
- log.Info("Storing CHT", "idx", c.section*c.sectionSize/ChtFrequency, "sectionHead", fmt.Sprintf("%064x", c.lastHash), "root", fmt.Sprintf("%064x", root))
- }
- StoreChtRoot(c.db, c.section, c.lastHash, root)
}
+ c.triedb.Commit(root, false)
+
+ if ((c.section+1)*c.sectionSize)%CHTFrequencyClient == 0 {
+ log.Info("Storing CHT", "section", c.section*c.sectionSize/CHTFrequencyClient, "head", c.lastHash, "root", root)
+ }
+ StoreChtRoot(c.diskdb, c.section, c.lastHash, root)
return nil
}
@@ -205,7 +214,8 @@ func StoreBloomTrieRoot(db ethdb.Database, sectionIdx uint64, sectionHead, root
// BloomTrieIndexerBackend implements core.ChainIndexerBackend
type BloomTrieIndexerBackend struct {
- db, cdb ethdb.Database
+ diskdb ethdb.Database
+ triedb *trie.Database
section, parentSectionSize, bloomTrieRatio uint64
trie *trie.Trie
sectionHeads []common.Hash
@@ -213,9 +223,12 @@ type BloomTrieIndexerBackend struct {
// NewBloomTrieIndexer creates a BloomTrie chain indexer
func NewBloomTrieIndexer(db ethdb.Database, clientMode bool) *core.ChainIndexer {
- cdb := ethdb.NewTable(db, BloomTrieTablePrefix)
+ backend := &BloomTrieIndexerBackend{
+ diskdb: db,
+ triedb: trie.NewDatabase(ethdb.NewTable(db, BloomTrieTablePrefix)),
+ }
idb := ethdb.NewTable(db, "bltIndex-")
- backend := &BloomTrieIndexerBackend{db: db, cdb: cdb}
+
var confirmReq uint64
if clientMode {
backend.parentSectionSize = BloomTrieFrequency
@@ -233,10 +246,10 @@ func NewBloomTrieIndexer(db ethdb.Database, clientMode bool) *core.ChainIndexer
func (b *BloomTrieIndexerBackend) Reset(section uint64, lastSectionHead common.Hash) error {
var root common.Hash
if section > 0 {
- root = GetBloomTrieRoot(b.db, section-1, lastSectionHead)
+ root = GetBloomTrieRoot(b.diskdb, section-1, lastSectionHead)
}
var err error
- b.trie, err = trie.New(root, b.cdb)
+ b.trie, err = trie.New(root, b.triedb)
b.section = section
return err
}
@@ -259,7 +272,7 @@ func (b *BloomTrieIndexerBackend) Commit() error {
binary.BigEndian.PutUint64(encKey[2:10], b.section)
var decomp []byte
for j := uint64(0); j < b.bloomTrieRatio; j++ {
- data, err := core.GetBloomBits(b.db, i, b.section*b.bloomTrieRatio+j, b.sectionHeads[j])
+ data, err := core.GetBloomBits(b.diskdb, i, b.section*b.bloomTrieRatio+j, b.sectionHeads[j])
if err != nil {
return err
}
@@ -279,17 +292,15 @@ func (b *BloomTrieIndexerBackend) Commit() error {
b.trie.Delete(encKey[:])
}
}
-
- batch := b.cdb.NewBatch()
- root, err := b.trie.CommitTo(batch)
+ root, err := b.trie.Commit(nil)
if err != nil {
return err
- } else {
- batch.Write()
- sectionHead := b.sectionHeads[b.bloomTrieRatio-1]
- log.Info("Storing BloomTrie", "section", b.section, "sectionHead", fmt.Sprintf("%064x", sectionHead), "root", fmt.Sprintf("%064x", root), "compression ratio", float64(compSize)/float64(decompSize))
- StoreBloomTrieRoot(b.db, b.section, sectionHead, root)
}
+ b.triedb.Commit(root, false)
+
+ sectionHead := b.sectionHeads[b.bloomTrieRatio-1]
+ log.Info("Storing bloom trie", "section", b.section, "head", sectionHead, "root", root, "compression", float64(compSize)/float64(decompSize))
+ StoreBloomTrieRoot(b.diskdb, b.section, sectionHead, root)
return nil
}
diff --git a/light/trie.go b/light/trie.go
index 7a9c86b98..c07e99461 100644
--- a/light/trie.go
+++ b/light/trie.go
@@ -18,12 +18,14 @@ package light
import (
"context"
+ "errors"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/trie"
)
@@ -83,6 +85,10 @@ func (db *odrDatabase) ContractCodeSize(addrHash, codeHash common.Hash) (int, er
return len(code), err
}
+func (db *odrDatabase) TrieDB() *trie.Database {
+ return nil
+}
+
type odrTrie struct {
db *odrDatabase
id *TrieID
@@ -113,11 +119,11 @@ func (t *odrTrie) TryDelete(key []byte) error {
})
}
-func (t *odrTrie) CommitTo(db trie.DatabaseWriter) (common.Hash, error) {
+func (t *odrTrie) Commit(onleaf trie.LeafCallback) (common.Hash, error) {
if t.trie == nil {
return t.id.Root, nil
}
- return t.trie.CommitTo(db)
+ return t.trie.Commit(onleaf)
}
func (t *odrTrie) Hash() common.Hash {
@@ -135,13 +141,17 @@ func (t *odrTrie) GetKey(sha []byte) []byte {
return nil
}
+func (t *odrTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error {
+ return errors.New("not implemented, needs client/server interface split")
+}
+
// do tries and retries to execute a function until it returns with no error or
// an error type other than MissingNodeError
func (t *odrTrie) do(key []byte, fn func() error) error {
for {
var err error
if t.trie == nil {
- t.trie, err = trie.New(t.id.Root, t.db.backend.Database())
+ t.trie, err = trie.New(t.id.Root, trie.NewDatabase(t.db.backend.Database()))
}
if err == nil {
err = fn()
@@ -167,7 +177,7 @@ func newNodeIterator(t *odrTrie, startkey []byte) trie.NodeIterator {
// Open the actual non-ODR trie if that hasn't happened yet.
if t.trie == nil {
it.do(func() error {
- t, err := trie.New(t.id.Root, t.db.backend.Database())
+ t, err := trie.New(t.id.Root, trie.NewDatabase(t.db.backend.Database()))
if err == nil {
it.t.trie = t
}
diff --git a/light/trie_test.go b/light/trie_test.go
index d99664718..0d6b2cc1d 100644
--- a/light/trie_test.go
+++ b/light/trie_test.go
@@ -40,7 +40,7 @@ func TestNodeIterator(t *testing.T) {
genesis = gspec.MustCommit(fulldb)
)
gspec.MustCommit(lightdb)
- blockchain, _ := core.NewBlockChain(fulldb, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{})
+ blockchain, _ := core.NewBlockChain(fulldb, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{})
gchain, _ := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), fulldb, 4, testChainGen)
if _, err := blockchain.InsertChain(gchain); err != nil {
panic(err)
diff --git a/light/txpool.go b/light/txpool.go
index bd215b992..ca41490bd 100644
--- a/light/txpool.go
+++ b/light/txpool.go
@@ -358,7 +358,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
// Check the transaction doesn't exceed the current
// block limit gas.
header := pool.chain.GetHeaderByHash(pool.head)
- if header.GasLimit.Cmp(tx.Gas()) < 0 {
+ if header.GasLimit < tx.Gas() {
return core.ErrGasLimit
}
@@ -376,10 +376,13 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
}
// Should supply enough intrinsic gas
- if tx.Gas().Cmp(core.IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)) < 0 {
+ gas, err := core.IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)
+ if err != nil {
+ return err
+ }
+ if tx.Gas() < gas {
return core.ErrIntrinsicGas
}
-
return currentState.Error()
}
diff --git a/light/txpool_test.go b/light/txpool_test.go
index 2ef9e0cf5..13d7d3ceb 100644
--- a/light/txpool_test.go
+++ b/light/txpool_test.go
@@ -77,7 +77,7 @@ func txPoolTestChainGen(i int, block *core.BlockGen) {
func TestTxPool(t *testing.T) {
for i := range testTx {
- testTx[i], _ = types.SignTx(types.NewTransaction(uint64(i), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), types.HomesteadSigner{}, testBankKey)
+ testTx[i], _ = types.SignTx(types.NewTransaction(uint64(i), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), types.HomesteadSigner{}, testBankKey)
}
var (
@@ -88,7 +88,7 @@ func TestTxPool(t *testing.T) {
)
gspec.MustCommit(ldb)
// Assemble the test environment
- blockchain, _ := core.NewBlockChain(sdb, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{})
+ blockchain, _ := core.NewBlockChain(sdb, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{})
gchain, _ := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), sdb, poolTestBlocks, txPoolTestChainGen)
if _, err := blockchain.InsertChain(gchain); err != nil {
panic(err)
diff --git a/miner/worker.go b/miner/worker.go
index c1f848e32..15395ae0b 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -309,7 +309,7 @@ func (self *worker) wait() {
for _, log := range work.state.Logs() {
log.BlockHash = block.Hash()
}
- stat, err := self.chain.WriteBlockAndState(block, work.receipts, work.state)
+ stat, err := self.chain.WriteBlockWithState(block, work.receipts, work.state)
if err != nil {
log.Error("Failed writing block to chain", "err", err)
continue
@@ -413,7 +413,6 @@ func (self *worker) commitNewWork() {
ParentHash: parent.Hash(),
Number: num.Add(num, common.Big1),
GasLimit: core.CalcGasLimit(parent),
- GasUsed: new(big.Int),
Extra: self.extra,
Time: big.NewInt(tstamp),
}
@@ -513,6 +512,11 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB
var coalescedLogs []*types.Log
for {
+ // If we don't have enough gas for any further transactions then we're done
+ if gp.Gas() < params.TxGas {
+ log.Trace("Not enough gas for further transactions", "gp", gp)
+ break
+ }
// Retrieve the next transaction and abort if all done
tx := txs.Peek()
if tx == nil {
@@ -588,7 +592,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB
func (env *Work) commitTransaction(tx *types.Transaction, bc *core.BlockChain, coinbase common.Address, gp *core.GasPool) (error, []*types.Log) {
snap := env.state.Snapshot()
- receipt, _, err := core.ApplyTransaction(env.config, bc, &coinbase, gp, env.state, env.header, tx, env.header.GasUsed, vm.Config{})
+ receipt, _, err := core.ApplyTransaction(env.config, bc, &coinbase, gp, env.state, env.header, tx, &env.header.GasUsed, vm.Config{})
if err != nil {
env.state.RevertToSnapshot(snap)
return err, nil
diff --git a/mobile/android_test.go b/mobile/android_test.go
index 345e009b4..3d3bd66d0 100644
--- a/mobile/android_test.go
+++ b/mobile/android_test.go
@@ -72,7 +72,7 @@ public class AndroidTest extends InstrumentationTestCase {
Transaction tx = new Transaction(
1, new Address("0x0000000000000000000000000000000000000000"),
- new BigInt(0), new BigInt(0), new BigInt(1), null); // Random empty transaction
+ new BigInt(0), 0, new BigInt(1), null); // Random empty transaction
BigInt chain = new BigInt(1); // Chain identifier of the main net
// Sign a transaction with a single authorization
@@ -164,12 +164,17 @@ func TestAndroid(t *testing.T) {
t.Skip("command gradle not found, skipping")
}
if sdk := os.Getenv("ANDROID_HOME"); sdk == "" {
- t.Skip("ANDROID_HOME environment var not set, skipping")
+ // Android SDK not explicitly given, try to auto-resolve
+ autopath := filepath.Join(os.Getenv("HOME"), "Android", "Sdk")
+ if _, err := os.Stat(autopath); err != nil {
+ t.Skip("ANDROID_HOME environment var not set, skipping")
+ }
+ os.Setenv("ANDROID_HOME", autopath)
}
if _, err := exec.Command("which", "gomobile").CombinedOutput(); err != nil {
t.Log("gomobile missing, installing it...")
- if _, err := exec.Command("go", "install", "golang.org/x/mobile/cmd/gomobile").CombinedOutput(); err != nil {
- t.Fatalf("install failed: %v", err)
+ if out, err := exec.Command("go", "get", "golang.org/x/mobile/cmd/gomobile").CombinedOutput(); err != nil {
+ t.Fatalf("install failed: %v\n%s", err, string(out))
}
t.Log("initializing gomobile...")
start := time.Now()
@@ -239,7 +244,7 @@ const gradleConfig = `buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:1.5.0'
+ classpath 'com.android.tools.build:gradle:2.2.3'
}
}
allprojects {
diff --git a/mobile/bind.go b/mobile/bind.go
index e8164d523..d6e621a25 100644
--- a/mobile/bind.go
+++ b/mobile/bind.go
@@ -77,7 +77,7 @@ func (opts *TransactOpts) GetFrom() *Address { return &Address{opts.opts.From
func (opts *TransactOpts) GetNonce() int64 { return opts.opts.Nonce.Int64() }
func (opts *TransactOpts) GetValue() *BigInt { return &BigInt{opts.opts.Value} }
func (opts *TransactOpts) GetGasPrice() *BigInt { return &BigInt{opts.opts.GasPrice} }
-func (opts *TransactOpts) GetGasLimit() int64 { return opts.opts.GasLimit.Int64() }
+func (opts *TransactOpts) GetGasLimit() int64 { return int64(opts.opts.GasLimit) }
// GetSigner cannot be reliably implemented without identity preservation (https://github.com/golang/go/issues/16876)
// func (opts *TransactOpts) GetSigner() Signer { return &signer{opts.opts.Signer} }
@@ -99,7 +99,7 @@ func (opts *TransactOpts) SetSigner(s Signer) {
}
func (opts *TransactOpts) SetValue(value *BigInt) { opts.opts.Value = value.bigint }
func (opts *TransactOpts) SetGasPrice(price *BigInt) { opts.opts.GasPrice = price.bigint }
-func (opts *TransactOpts) SetGasLimit(limit int64) { opts.opts.GasLimit = big.NewInt(limit) }
+func (opts *TransactOpts) SetGasLimit(limit int64) { opts.opts.GasLimit = uint64(limit) }
func (opts *TransactOpts) SetContext(context *Context) { opts.opts.Context = context.context }
// BoundContract is the base wrapper object that reflects a contract on the
@@ -138,7 +138,7 @@ func BindContract(address *Address, abiJSON string, client *EthereumClient) (con
return nil, err
}
return &BoundContract{
- contract: bind.NewBoundContract(address.address, parsed, client.client, client.client),
+ contract: bind.NewBoundContract(address.address, parsed, client.client, client.client, client.client),
address: address.address,
}, nil
}
diff --git a/mobile/ethclient.go b/mobile/ethclient.go
index 758863b6d..66399c6b5 100644
--- a/mobile/ethclient.go
+++ b/mobile/ethclient.go
@@ -298,9 +298,9 @@ func (ec *EthereumClient) SuggestGasPrice(ctx *Context) (price *BigInt, _ error)
// the current pending state of the backend blockchain. There is no guarantee that this is
// the true gas limit requirement as other transactions may be added or removed by miners,
// but it should provide a basis for setting a reasonable default.
-func (ec *EthereumClient) EstimateGas(ctx *Context, msg *CallMsg) (gas *BigInt, _ error) {
+func (ec *EthereumClient) EstimateGas(ctx *Context, msg *CallMsg) (gas int64, _ error) {
rawGas, err := ec.client.EstimateGas(ctx.context, msg.msg)
- return &BigInt{rawGas}, err
+ return int64(rawGas), err
}
// SendTransaction injects a signed transaction into the pending pool for execution.
diff --git a/mobile/ethereum.go b/mobile/ethereum.go
index c9bb3013c..0eb1d9055 100644
--- a/mobile/ethereum.go
+++ b/mobile/ethereum.go
@@ -20,7 +20,6 @@ package geth
import (
"errors"
- "math/big"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
@@ -49,7 +48,7 @@ func NewCallMsg() *CallMsg {
}
func (msg *CallMsg) GetFrom() *Address { return &Address{msg.msg.From} }
-func (msg *CallMsg) GetGas() int64 { return msg.msg.Gas.Int64() }
+func (msg *CallMsg) GetGas() int64 { return int64(msg.msg.Gas) }
func (msg *CallMsg) GetGasPrice() *BigInt { return &BigInt{msg.msg.GasPrice} }
func (msg *CallMsg) GetValue() *BigInt { return &BigInt{msg.msg.Value} }
func (msg *CallMsg) GetData() []byte { return msg.msg.Data }
@@ -61,7 +60,7 @@ func (msg *CallMsg) GetTo() *Address {
}
func (msg *CallMsg) SetFrom(address *Address) { msg.msg.From = address.address }
-func (msg *CallMsg) SetGas(gas int64) { msg.msg.Gas = big.NewInt(gas) }
+func (msg *CallMsg) SetGas(gas int64) { msg.msg.Gas = uint64(gas) }
func (msg *CallMsg) SetGasPrice(price *BigInt) { msg.msg.GasPrice = price.bigint }
func (msg *CallMsg) SetValue(value *BigInt) { msg.msg.Value = value.bigint }
func (msg *CallMsg) SetData(data []byte) { msg.msg.Data = common.CopyBytes(data) }
diff --git a/mobile/geth.go b/mobile/geth.go
index 7b39faade..7e3b8f491 100644
--- a/mobile/geth.go
+++ b/mobile/geth.go
@@ -116,7 +116,6 @@ func NewNode(datadir string, config *NodeConfig) (stack *Node, _ error) {
P2P: p2p.Config{
NoDiscovery: true,
DiscoveryV5: true,
- DiscoveryV5Addr: ":0",
BootstrapNodesV5: config.BootstrapNodes.nodes,
ListenAddr: ":0",
NAT: nat.Any(),
diff --git a/mobile/types.go b/mobile/types.go
index b7f8a3bc1..4790afcef 100644
--- a/mobile/types.go
+++ b/mobile/types.go
@@ -112,8 +112,8 @@ func (h *Header) GetReceiptHash() *Hash { return &Hash{h.header.ReceiptHash} }
func (h *Header) GetBloom() *Bloom { return &Bloom{h.header.Bloom} }
func (h *Header) GetDifficulty() *BigInt { return &BigInt{h.header.Difficulty} }
func (h *Header) GetNumber() int64 { return h.header.Number.Int64() }
-func (h *Header) GetGasLimit() int64 { return h.header.GasLimit.Int64() }
-func (h *Header) GetGasUsed() int64 { return h.header.GasUsed.Int64() }
+func (h *Header) GetGasLimit() int64 { return int64(h.header.GasLimit) }
+func (h *Header) GetGasUsed() int64 { return int64(h.header.GasUsed) }
func (h *Header) GetTime() int64 { return h.header.Time.Int64() }
func (h *Header) GetExtra() []byte { return h.header.Extra }
func (h *Header) GetMixDigest() *Hash { return &Hash{h.header.MixDigest} }
@@ -189,8 +189,8 @@ func (b *Block) GetReceiptHash() *Hash { return &Hash{b.block.ReceiptHash()} }
func (b *Block) GetBloom() *Bloom { return &Bloom{b.block.Bloom()} }
func (b *Block) GetDifficulty() *BigInt { return &BigInt{b.block.Difficulty()} }
func (b *Block) GetNumber() int64 { return b.block.Number().Int64() }
-func (b *Block) GetGasLimit() int64 { return b.block.GasLimit().Int64() }
-func (b *Block) GetGasUsed() int64 { return b.block.GasUsed().Int64() }
+func (b *Block) GetGasLimit() int64 { return int64(b.block.GasLimit()) }
+func (b *Block) GetGasUsed() int64 { return int64(b.block.GasUsed()) }
func (b *Block) GetTime() int64 { return b.block.Time().Int64() }
func (b *Block) GetExtra() []byte { return b.block.Extra() }
func (b *Block) GetMixDigest() *Hash { return &Hash{b.block.MixDigest()} }
@@ -212,8 +212,8 @@ type Transaction struct {
}
// NewTransaction creates a new transaction with the given properties.
-func NewTransaction(nonce int64, to *Address, amount, gasLimit, gasPrice *BigInt, data []byte) *Transaction {
- return &Transaction{types.NewTransaction(uint64(nonce), to.address, amount.bigint, gasLimit.bigint, gasPrice.bigint, common.CopyBytes(data))}
+func NewTransaction(nonce int64, to *Address, amount *BigInt, gasLimit int64, gasPrice *BigInt, data []byte) *Transaction {
+ return &Transaction{types.NewTransaction(uint64(nonce), to.address, amount.bigint, uint64(gasLimit), gasPrice.bigint, common.CopyBytes(data))}
}
// NewTransactionFromRLP parses a transaction from an RLP data dump.
@@ -256,7 +256,7 @@ func (tx *Transaction) String() string {
}
func (tx *Transaction) GetData() []byte { return tx.tx.Data() }
-func (tx *Transaction) GetGas() int64 { return tx.tx.Gas().Int64() }
+func (tx *Transaction) GetGas() int64 { return int64(tx.tx.Gas()) }
func (tx *Transaction) GetGasPrice() *BigInt { return &BigInt{tx.tx.GasPrice()} }
func (tx *Transaction) GetValue() *BigInt { return &BigInt{tx.tx.Value()} }
func (tx *Transaction) GetNonce() int64 { return int64(tx.tx.Nonce()) }
@@ -353,10 +353,10 @@ func (r *Receipt) String() string {
return r.receipt.String()
}
-func (r *Receipt) GetPostState() []byte { return r.receipt.PostState }
-func (r *Receipt) GetCumulativeGasUsed() *BigInt { return &BigInt{r.receipt.CumulativeGasUsed} }
-func (r *Receipt) GetBloom() *Bloom { return &Bloom{r.receipt.Bloom} }
-func (r *Receipt) GetLogs() *Logs { return &Logs{r.receipt.Logs} }
-func (r *Receipt) GetTxHash() *Hash { return &Hash{r.receipt.TxHash} }
-func (r *Receipt) GetContractAddress() *Address { return &Address{r.receipt.ContractAddress} }
-func (r *Receipt) GetGasUsed() *BigInt { return &BigInt{r.receipt.GasUsed} }
+func (r *Receipt) GetPostState() []byte { return r.receipt.PostState }
+func (r *Receipt) GetCumulativeGasUsed() int64 { return int64(r.receipt.CumulativeGasUsed) }
+func (r *Receipt) GetBloom() *Bloom { return &Bloom{r.receipt.Bloom} }
+func (r *Receipt) GetLogs() *Logs { return &Logs{r.receipt.Logs} }
+func (r *Receipt) GetTxHash() *Hash { return &Hash{r.receipt.TxHash} }
+func (r *Receipt) GetContractAddress() *Address { return &Address{r.receipt.ContractAddress} }
+func (r *Receipt) GetGasUsed() int64 { return int64(r.receipt.GasUsed) }
diff --git a/node/api.go b/node/api.go
index 1b04b7093..4e9b1edc4 100644
--- a/node/api.go
+++ b/node/api.go
@@ -114,7 +114,7 @@ func (api *PrivateAdminAPI) PeerEvents(ctx context.Context) (*rpc.Subscription,
}
// StartRPC starts the HTTP RPC API server.
-func (api *PrivateAdminAPI) StartRPC(host *string, port *int, cors *string, apis *string) (bool, error) {
+func (api *PrivateAdminAPI) StartRPC(host *string, port *int, cors *string, apis *string, vhosts *string) (bool, error) {
api.node.lock.Lock()
defer api.node.lock.Unlock()
@@ -141,6 +141,14 @@ func (api *PrivateAdminAPI) StartRPC(host *string, port *int, cors *string, apis
}
}
+ allowedVHosts := api.node.config.HTTPVirtualHosts
+ if vhosts != nil {
+ allowedVHosts = nil
+ for _, vhost := range strings.Split(*host, ",") {
+ allowedVHosts = append(allowedVHosts, strings.TrimSpace(vhost))
+ }
+ }
+
modules := api.node.httpWhitelist
if apis != nil {
modules = nil
@@ -149,7 +157,7 @@ func (api *PrivateAdminAPI) StartRPC(host *string, port *int, cors *string, apis
}
}
- if err := api.node.startHTTP(fmt.Sprintf("%s:%d", *host, *port), api.node.rpcAPIs, modules, allowedOrigins); err != nil {
+ if err := api.node.startHTTP(fmt.Sprintf("%s:%d", *host, *port), api.node.rpcAPIs, modules, allowedOrigins, allowedVHosts); err != nil {
return false, err
}
return true, nil
diff --git a/node/config.go b/node/config.go
index 7a0c1688e..dda24583e 100644
--- a/node/config.go
+++ b/node/config.go
@@ -105,6 +105,15 @@ type Config struct {
// useless for custom HTTP clients.
HTTPCors []string `toml:",omitempty"`
+ // HTTPVirtualHosts is the list of virtual hostnames which are allowed on incoming requests.
+ // This is by default {'localhost'}. Using this prevents attacks like
+ // DNS rebinding, which bypasses SOP by simply masquerading as being within the same
+ // origin. These attacks do not utilize CORS, since they are not cross-domain.
+ // By explicitly checking the Host-header, the server will not allow requests
+ // made against the server with a malicious host domain.
+ // Requests using ip address directly are not affected
+ HTTPVirtualHosts []string `toml:",omitempty"`
+
// HTTPModules is a list of API modules to expose via the HTTP RPC interface.
// If the module list is empty, all RPC API endpoints designated public will be
// exposed.
@@ -137,7 +146,7 @@ type Config struct {
WSExposeAll bool `toml:",omitempty"`
// Logger is a custom logger to use with the p2p.Server.
- Logger log.Logger
+ Logger log.Logger `toml:",omitempty"`
}
// IPCEndpoint resolves an IPC endpoint based on a configured value, taking into
diff --git a/node/defaults.go b/node/defaults.go
index 848f08e05..d4e148683 100644
--- a/node/defaults.go
+++ b/node/defaults.go
@@ -41,10 +41,9 @@ var DefaultConfig = Config{
WSPort: DefaultWSPort,
WSModules: []string{"net", "web3"},
P2P: p2p.Config{
- ListenAddr: ":30303",
- DiscoveryV5Addr: ":30304",
- MaxPeers: 25,
- NAT: nat.Any(),
+ ListenAddr: ":30303",
+ MaxPeers: 25,
+ NAT: nat.Any(),
},
}
diff --git a/node/node.go b/node/node.go
index ff7258033..b02aecfad 100644
--- a/node/node.go
+++ b/node/node.go
@@ -263,7 +263,7 @@ func (n *Node) startRPC(services map[reflect.Type]Service) error {
n.stopInProc()
return err
}
- if err := n.startHTTP(n.httpEndpoint, apis, n.config.HTTPModules, n.config.HTTPCors); err != nil {
+ if err := n.startHTTP(n.httpEndpoint, apis, n.config.HTTPModules, n.config.HTTPCors, n.config.HTTPVirtualHosts); err != nil {
n.stopIPC()
n.stopInProc()
return err
@@ -287,7 +287,7 @@ func (n *Node) startInProc(apis []rpc.API) error {
if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
return err
}
- n.log.Debug(fmt.Sprintf("InProc registered %T under '%s'", api.Service, api.Namespace))
+ n.log.Debug("InProc registered", "service", api.Service, "namespace", api.Namespace)
}
n.inprocHandler = handler
return nil
@@ -313,7 +313,7 @@ func (n *Node) startIPC(apis []rpc.API) error {
if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
return err
}
- n.log.Debug(fmt.Sprintf("IPC registered %T under '%s'", api.Service, api.Namespace))
+ n.log.Debug("IPC registered", "service", api.Service, "namespace", api.Namespace)
}
// All APIs registered, start the IPC listener
var (
@@ -324,7 +324,7 @@ func (n *Node) startIPC(apis []rpc.API) error {
return err
}
go func() {
- n.log.Info(fmt.Sprintf("IPC endpoint opened: %s", n.ipcEndpoint))
+ n.log.Info("IPC endpoint opened", "url", n.ipcEndpoint)
for {
conn, err := listener.Accept()
@@ -337,7 +337,7 @@ func (n *Node) startIPC(apis []rpc.API) error {
return
}
// Not closed, just some error; report and continue
- n.log.Error(fmt.Sprintf("IPC accept failed: %v", err))
+ n.log.Error("IPC accept failed", "err", err)
continue
}
go handler.ServeCodec(rpc.NewJSONCodec(conn), rpc.OptionMethodInvocation|rpc.OptionSubscriptions)
@@ -356,7 +356,7 @@ func (n *Node) stopIPC() {
n.ipcListener.Close()
n.ipcListener = nil
- n.log.Info(fmt.Sprintf("IPC endpoint closed: %s", n.ipcEndpoint))
+ n.log.Info("IPC endpoint closed", "endpoint", n.ipcEndpoint)
}
if n.ipcHandler != nil {
n.ipcHandler.Stop()
@@ -365,7 +365,7 @@ func (n *Node) stopIPC() {
}
// startHTTP initializes and starts the HTTP RPC endpoint.
-func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors []string) error {
+func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors []string, vhosts []string) error {
// Short circuit if the HTTP endpoint isn't being exposed
if endpoint == "" {
return nil
@@ -382,7 +382,7 @@ func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors
if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
return err
}
- n.log.Debug(fmt.Sprintf("HTTP registered %T under '%s'", api.Service, api.Namespace))
+ n.log.Debug("HTTP registered", "service", api.Service, "namespace", api.Namespace)
}
}
// All APIs registered, start the HTTP listener
@@ -393,9 +393,8 @@ func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors
if listener, err = net.Listen("tcp", endpoint); err != nil {
return err
}
- go rpc.NewHTTPServer(cors, handler).Serve(listener)
- n.log.Info(fmt.Sprintf("HTTP endpoint opened: http://%s", endpoint))
-
+ go rpc.NewHTTPServer(cors, vhosts, handler).Serve(listener)
+ n.log.Info("HTTP endpoint opened", "url", fmt.Sprintf("http://%s", endpoint), "cors", strings.Join(cors, ","), "vhosts", strings.Join(vhosts, ","))
// All listeners booted successfully
n.httpEndpoint = endpoint
n.httpListener = listener
@@ -410,7 +409,7 @@ func (n *Node) stopHTTP() {
n.httpListener.Close()
n.httpListener = nil
- n.log.Info(fmt.Sprintf("HTTP endpoint closed: http://%s", n.httpEndpoint))
+ n.log.Info("HTTP endpoint closed", "url", fmt.Sprintf("http://%s", n.httpEndpoint))
}
if n.httpHandler != nil {
n.httpHandler.Stop()
@@ -436,7 +435,7 @@ func (n *Node) startWS(endpoint string, apis []rpc.API, modules []string, wsOrig
if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
return err
}
- n.log.Debug(fmt.Sprintf("WebSocket registered %T under '%s'", api.Service, api.Namespace))
+ n.log.Debug("WebSocket registered", "service", api.Service, "namespace", api.Namespace)
}
}
// All APIs registered, start the HTTP listener
@@ -448,7 +447,7 @@ func (n *Node) startWS(endpoint string, apis []rpc.API, modules []string, wsOrig
return err
}
go rpc.NewWSServer(wsOrigins, handler).Serve(listener)
- n.log.Info(fmt.Sprintf("WebSocket endpoint opened: ws://%s", listener.Addr()))
+ n.log.Info("WebSocket endpoint opened", "url", fmt.Sprintf("ws://%s", listener.Addr()))
// All listeners booted successfully
n.wsEndpoint = endpoint
@@ -464,7 +463,7 @@ func (n *Node) stopWS() {
n.wsListener.Close()
n.wsListener = nil
- n.log.Info(fmt.Sprintf("WebSocket endpoint closed: ws://%s", n.wsEndpoint))
+ n.log.Info("WebSocket endpoint closed", "url", fmt.Sprintf("ws://%s", n.wsEndpoint))
}
if n.wsHandler != nil {
n.wsHandler.Stop()
diff --git a/p2p/dial.go b/p2p/dial.go
index f5ff2c211..d8feceb9f 100644
--- a/p2p/dial.go
+++ b/p2p/dial.go
@@ -154,6 +154,9 @@ func (s *dialstate) addStatic(n *discover.Node) {
func (s *dialstate) removeStatic(n *discover.Node) {
// This removes a task so future attempts to connect will not be made.
delete(s.static, n.ID)
+ // This removes a previous dial timestamp so that application
+ // can force a server to reconnect with chosen peer immediately.
+ s.hist.remove(n.ID)
}
func (s *dialstate) newTasks(nRunning int, peers map[discover.NodeID]*Peer, now time.Time) []task {
@@ -390,6 +393,16 @@ func (h dialHistory) min() pastDial {
}
func (h *dialHistory) add(id discover.NodeID, exp time.Time) {
heap.Push(h, pastDial{id, exp})
+
+}
+func (h *dialHistory) remove(id discover.NodeID) bool {
+ for i, v := range *h {
+ if v.id == id {
+ heap.Remove(h, i)
+ return true
+ }
+ }
+ return false
}
func (h dialHistory) contains(id discover.NodeID) bool {
for _, v := range h {
diff --git a/p2p/dial_test.go b/p2p/dial_test.go
index ad18ef9ab..2a7941fc6 100644
--- a/p2p/dial_test.go
+++ b/p2p/dial_test.go
@@ -515,6 +515,50 @@ func TestDialStateStaticDial(t *testing.T) {
})
}
+// This test checks that static peers will be redialed immediately if they were re-added to a static list.
+func TestDialStaticAfterReset(t *testing.T) {
+ wantStatic := []*discover.Node{
+ {ID: uintID(1)},
+ {ID: uintID(2)},
+ }
+
+ rounds := []round{
+ // Static dials are launched for the nodes that aren't yet connected.
+ {
+ peers: nil,
+ new: []task{
+ &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(1)}},
+ &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(2)}},
+ },
+ },
+ // No new dial tasks, all peers are connected.
+ {
+ peers: []*Peer{
+ {rw: &conn{flags: staticDialedConn, id: uintID(1)}},
+ {rw: &conn{flags: staticDialedConn, id: uintID(2)}},
+ },
+ done: []task{
+ &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(1)}},
+ &dialTask{flags: staticDialedConn, dest: &discover.Node{ID: uintID(2)}},
+ },
+ new: []task{
+ &waitExpireTask{Duration: 30 * time.Second},
+ },
+ },
+ }
+ dTest := dialtest{
+ init: newDialState(wantStatic, nil, fakeTable{}, 0, nil),
+ rounds: rounds,
+ }
+ runDialTest(t, dTest)
+ for _, n := range wantStatic {
+ dTest.init.removeStatic(n)
+ dTest.init.addStatic(n)
+ }
+ // without removing peers they will be considered recently dialed
+ runDialTest(t, dTest)
+}
+
// This test checks that past dials are not retried for some time.
func TestDialStateCache(t *testing.T) {
wantStatic := []*discover.Node{
diff --git a/p2p/discover/database.go b/p2p/discover/database.go
index b136609f2..6f98de9b4 100644
--- a/p2p/discover/database.go
+++ b/p2p/discover/database.go
@@ -257,7 +257,7 @@ func (db *nodeDB) expireNodes() error {
}
// Skip the node if not expired yet (and not self)
if !bytes.Equal(id[:], db.self[:]) {
- if seen := db.lastPong(id); seen.After(threshold) {
+ if seen := db.bondTime(id); seen.After(threshold) {
continue
}
}
@@ -278,13 +278,18 @@ func (db *nodeDB) updateLastPing(id NodeID, instance time.Time) error {
return db.storeInt64(makeKey(id, nodeDBDiscoverPing), instance.Unix())
}
-// lastPong retrieves the time of the last successful contact from remote node.
-func (db *nodeDB) lastPong(id NodeID) time.Time {
+// bondTime retrieves the time of the last successful pong from remote node.
+func (db *nodeDB) bondTime(id NodeID) time.Time {
return time.Unix(db.fetchInt64(makeKey(id, nodeDBDiscoverPong)), 0)
}
-// updateLastPong updates the last time a remote node successfully contacted.
-func (db *nodeDB) updateLastPong(id NodeID, instance time.Time) error {
+// hasBond reports whether the given node is considered bonded.
+func (db *nodeDB) hasBond(id NodeID) bool {
+ return time.Since(db.bondTime(id)) < nodeDBNodeExpiration
+}
+
+// updateBondTime updates the last pong time of a node.
+func (db *nodeDB) updateBondTime(id NodeID, instance time.Time) error {
return db.storeInt64(makeKey(id, nodeDBDiscoverPong), instance.Unix())
}
@@ -327,7 +332,7 @@ seek:
if n.ID == db.self {
continue seek
}
- if now.Sub(db.lastPong(n.ID)) > maxAge {
+ if now.Sub(db.bondTime(n.ID)) > maxAge {
continue seek
}
for i := range nodes {
diff --git a/p2p/discover/database_test.go b/p2p/discover/database_test.go
index be972fd2c..c4fa44d09 100644
--- a/p2p/discover/database_test.go
+++ b/p2p/discover/database_test.go
@@ -125,13 +125,13 @@ func TestNodeDBFetchStore(t *testing.T) {
t.Errorf("ping: value mismatch: have %v, want %v", stored, inst)
}
// Check fetch/store operations on a node pong object
- if stored := db.lastPong(node.ID); stored.Unix() != 0 {
+ if stored := db.bondTime(node.ID); stored.Unix() != 0 {
t.Errorf("pong: non-existing object: %v", stored)
}
- if err := db.updateLastPong(node.ID, inst); err != nil {
+ if err := db.updateBondTime(node.ID, inst); err != nil {
t.Errorf("pong: failed to update: %v", err)
}
- if stored := db.lastPong(node.ID); stored.Unix() != inst.Unix() {
+ if stored := db.bondTime(node.ID); stored.Unix() != inst.Unix() {
t.Errorf("pong: value mismatch: have %v, want %v", stored, inst)
}
// Check fetch/store operations on a node findnode-failure object
@@ -224,8 +224,8 @@ func TestNodeDBSeedQuery(t *testing.T) {
if err := db.updateNode(seed.node); err != nil {
t.Fatalf("node %d: failed to insert: %v", i, err)
}
- if err := db.updateLastPong(seed.node.ID, seed.pong); err != nil {
- t.Fatalf("node %d: failed to insert lastPong: %v", i, err)
+ if err := db.updateBondTime(seed.node.ID, seed.pong); err != nil {
+ t.Fatalf("node %d: failed to insert bondTime: %v", i, err)
}
}
@@ -332,8 +332,8 @@ func TestNodeDBExpiration(t *testing.T) {
if err := db.updateNode(seed.node); err != nil {
t.Fatalf("node %d: failed to insert: %v", i, err)
}
- if err := db.updateLastPong(seed.node.ID, seed.pong); err != nil {
- t.Fatalf("node %d: failed to update pong: %v", i, err)
+ if err := db.updateBondTime(seed.node.ID, seed.pong); err != nil {
+ t.Fatalf("node %d: failed to update bondTime: %v", i, err)
}
}
// Expire some of them, and check the rest
@@ -365,8 +365,8 @@ func TestNodeDBSelfExpiration(t *testing.T) {
if err := db.updateNode(seed.node); err != nil {
t.Fatalf("node %d: failed to insert: %v", i, err)
}
- if err := db.updateLastPong(seed.node.ID, seed.pong); err != nil {
- t.Fatalf("node %d: failed to update pong: %v", i, err)
+ if err := db.updateBondTime(seed.node.ID, seed.pong); err != nil {
+ t.Fatalf("node %d: failed to update bondTime: %v", i, err)
}
}
// Expire the nodes and make sure self has been evacuated too
diff --git a/p2p/discover/node.go b/p2p/discover/node.go
index fc928a91a..3b0c84115 100644
--- a/p2p/discover/node.go
+++ b/p2p/discover/node.go
@@ -29,6 +29,7 @@ import (
"regexp"
"strconv"
"strings"
+ "time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
@@ -51,9 +52,8 @@ type Node struct {
// with ID.
sha common.Hash
- // whether this node is currently being pinged in order to replace
- // it in a bucket
- contested bool
+ // Time when the node was added to the table.
+ addedAt time.Time
}
// NewNode creates a new node. It is mostly meant to be used for
diff --git a/p2p/discover/table.go b/p2p/discover/table.go
index ec4eb94ad..6509326e6 100644
--- a/p2p/discover/table.go
+++ b/p2p/discover/table.go
@@ -23,10 +23,11 @@
package discover
import (
- "crypto/rand"
+ crand "crypto/rand"
"encoding/binary"
"errors"
"fmt"
+ mrand "math/rand"
"net"
"sort"
"sync"
@@ -35,29 +36,45 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/p2p/netutil"
)
const (
- alpha = 3 // Kademlia concurrency factor
- bucketSize = 16 // Kademlia bucket size
- hashBits = len(common.Hash{}) * 8
- nBuckets = hashBits + 1 // Number of buckets
-
- maxBondingPingPongs = 16
- maxFindnodeFailures = 5
-
- autoRefreshInterval = 1 * time.Hour
- seedCount = 30
- seedMaxAge = 5 * 24 * time.Hour
+ alpha = 3 // Kademlia concurrency factor
+ bucketSize = 16 // Kademlia bucket size
+ maxReplacements = 10 // Size of per-bucket replacement list
+
+ // We keep buckets for the upper 1/15 of distances because
+ // it's very unlikely we'll ever encounter a node that's closer.
+ hashBits = len(common.Hash{}) * 8
+ nBuckets = hashBits / 15 // Number of buckets
+ bucketMinDistance = hashBits - nBuckets // Log distance of closest bucket
+
+ // IP address limits.
+ bucketIPLimit, bucketSubnet = 2, 24 // at most 2 addresses from the same /24
+ tableIPLimit, tableSubnet = 10, 24
+
+ maxBondingPingPongs = 16 // Limit on the number of concurrent ping/pong interactions
+ maxFindnodeFailures = 5 // Nodes exceeding this limit are dropped
+
+ refreshInterval = 30 * time.Minute
+ revalidateInterval = 10 * time.Second
+ copyNodesInterval = 30 * time.Second
+ seedMinTableTime = 5 * time.Minute
+ seedCount = 30
+ seedMaxAge = 5 * 24 * time.Hour
)
type Table struct {
- mutex sync.Mutex // protects buckets, their content, and nursery
+ mutex sync.Mutex // protects buckets, bucket content, nursery, rand
buckets [nBuckets]*bucket // index of known nodes by distance
nursery []*Node // bootstrap nodes
- db *nodeDB // database of known nodes
+ rand *mrand.Rand // source of randomness, periodically reseeded
+ ips netutil.DistinctNetSet
+ db *nodeDB // database of known nodes
refreshReq chan chan struct{}
+ initDone chan struct{}
closeReq chan struct{}
closed chan struct{}
@@ -89,9 +106,13 @@ type transport interface {
// bucket contains nodes, ordered by their last activity. the entry
// that was most recently active is the first element in entries.
-type bucket struct{ entries []*Node }
+type bucket struct {
+ entries []*Node // live entries, sorted by time of last contact
+ replacements []*Node // recently seen nodes to be used if revalidation fails
+ ips netutil.DistinctNetSet
+}
-func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr, nodeDBPath string) (*Table, error) {
+func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr, nodeDBPath string, bootnodes []*Node) (*Table, error) {
// If no node database was given, use an in-memory one
db, err := newNodeDB(nodeDBPath, Version, ourID)
if err != nil {
@@ -104,19 +125,42 @@ func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr, nodeDBPath string
bonding: make(map[NodeID]*bondproc),
bondslots: make(chan struct{}, maxBondingPingPongs),
refreshReq: make(chan chan struct{}),
+ initDone: make(chan struct{}),
closeReq: make(chan struct{}),
closed: make(chan struct{}),
+ rand: mrand.New(mrand.NewSource(0)),
+ ips: netutil.DistinctNetSet{Subnet: tableSubnet, Limit: tableIPLimit},
+ }
+ if err := tab.setFallbackNodes(bootnodes); err != nil {
+ return nil, err
}
for i := 0; i < cap(tab.bondslots); i++ {
tab.bondslots <- struct{}{}
}
for i := range tab.buckets {
- tab.buckets[i] = new(bucket)
+ tab.buckets[i] = &bucket{
+ ips: netutil.DistinctNetSet{Subnet: bucketSubnet, Limit: bucketIPLimit},
+ }
}
- go tab.refreshLoop()
+ tab.seedRand()
+ tab.loadSeedNodes(false)
+ // Start the background expiration goroutine after loading seeds so that the search for
+ // seed nodes also considers older nodes that would otherwise be removed by the
+ // expiration.
+ tab.db.ensureExpirer()
+ go tab.loop()
return tab, nil
}
+func (tab *Table) seedRand() {
+ var b [8]byte
+ crand.Read(b[:])
+
+ tab.mutex.Lock()
+ tab.rand.Seed(int64(binary.BigEndian.Uint64(b[:])))
+ tab.mutex.Unlock()
+}
+
// Self returns the local node.
// The returned node should not be modified by the caller.
func (tab *Table) Self() *Node {
@@ -127,9 +171,12 @@ func (tab *Table) Self() *Node {
// table. It will not write the same node more than once. The nodes in
// the slice are copies and can be modified by the caller.
func (tab *Table) ReadRandomNodes(buf []*Node) (n int) {
+ if !tab.isInitDone() {
+ return 0
+ }
tab.mutex.Lock()
defer tab.mutex.Unlock()
- // TODO: tree-based buckets would help here
+
// Find all non-empty buckets and get a fresh slice of their entries.
var buckets [][]*Node
for _, b := range tab.buckets {
@@ -141,8 +188,8 @@ func (tab *Table) ReadRandomNodes(buf []*Node) (n int) {
return 0
}
// Shuffle the buckets.
- for i := uint32(len(buckets)) - 1; i > 0; i-- {
- j := randUint(i)
+ for i := len(buckets) - 1; i > 0; i-- {
+ j := tab.rand.Intn(len(buckets))
buckets[i], buckets[j] = buckets[j], buckets[i]
}
// Move head of each bucket into buf, removing buckets that become empty.
@@ -161,15 +208,6 @@ func (tab *Table) ReadRandomNodes(buf []*Node) (n int) {
return i + 1
}
-func randUint(max uint32) uint32 {
- if max == 0 {
- return 0
- }
- var b [4]byte
- rand.Read(b[:])
- return binary.BigEndian.Uint32(b[:]) % max
-}
-
// Close terminates the network listener and flushes the node database.
func (tab *Table) Close() {
select {
@@ -180,16 +218,15 @@ func (tab *Table) Close() {
}
}
-// SetFallbackNodes sets the initial points of contact. These nodes
+// setFallbackNodes sets the initial points of contact. These nodes
// are used to connect to the network if the table is empty and there
// are no known nodes in the database.
-func (tab *Table) SetFallbackNodes(nodes []*Node) error {
+func (tab *Table) setFallbackNodes(nodes []*Node) error {
for _, n := range nodes {
if err := n.validateComplete(); err != nil {
return fmt.Errorf("bad bootstrap/fallback node %q (%v)", n, err)
}
}
- tab.mutex.Lock()
tab.nursery = make([]*Node, 0, len(nodes))
for _, n := range nodes {
cpy := *n
@@ -198,11 +235,19 @@ func (tab *Table) SetFallbackNodes(nodes []*Node) error {
cpy.sha = crypto.Keccak256Hash(n.ID[:])
tab.nursery = append(tab.nursery, &cpy)
}
- tab.mutex.Unlock()
- tab.refresh()
return nil
}
+// isInitDone returns whether the table's initial seeding procedure has completed.
+func (tab *Table) isInitDone() bool {
+ select {
+ case <-tab.initDone:
+ return true
+ default:
+ return false
+ }
+}
+
// Resolve searches for a specific node with the given ID.
// It returns nil if the node could not be found.
func (tab *Table) Resolve(targetID NodeID) *Node {
@@ -314,33 +359,49 @@ func (tab *Table) refresh() <-chan struct{} {
return done
}
-// refreshLoop schedules doRefresh runs and coordinates shutdown.
-func (tab *Table) refreshLoop() {
+// loop schedules refresh, revalidate runs and coordinates shutdown.
+func (tab *Table) loop() {
var (
- timer = time.NewTicker(autoRefreshInterval)
- waiting []chan struct{} // accumulates waiting callers while doRefresh runs
- done chan struct{} // where doRefresh reports completion
+ revalidate = time.NewTimer(tab.nextRevalidateTime())
+ refresh = time.NewTicker(refreshInterval)
+ copyNodes = time.NewTicker(copyNodesInterval)
+ revalidateDone = make(chan struct{})
+ refreshDone = make(chan struct{}) // where doRefresh reports completion
+ waiting = []chan struct{}{tab.initDone} // holds waiting callers while doRefresh runs
)
+ defer refresh.Stop()
+ defer revalidate.Stop()
+ defer copyNodes.Stop()
+
+ // Start initial refresh.
+ go tab.doRefresh(refreshDone)
+
loop:
for {
select {
- case <-timer.C:
- if done == nil {
- done = make(chan struct{})
- go tab.doRefresh(done)
+ case <-refresh.C:
+ tab.seedRand()
+ if refreshDone == nil {
+ refreshDone = make(chan struct{})
+ go tab.doRefresh(refreshDone)
}
case req := <-tab.refreshReq:
waiting = append(waiting, req)
- if done == nil {
- done = make(chan struct{})
- go tab.doRefresh(done)
+ if refreshDone == nil {
+ refreshDone = make(chan struct{})
+ go tab.doRefresh(refreshDone)
}
- case <-done:
+ case <-refreshDone:
for _, ch := range waiting {
close(ch)
}
- waiting = nil
- done = nil
+ waiting, refreshDone = nil, nil
+ case <-revalidate.C:
+ go tab.doRevalidate(revalidateDone)
+ case <-revalidateDone:
+ revalidate.Reset(tab.nextRevalidateTime())
+ case <-copyNodes.C:
+ go tab.copyBondedNodes()
case <-tab.closeReq:
break loop
}
@@ -349,8 +410,8 @@ loop:
if tab.net != nil {
tab.net.close()
}
- if done != nil {
- <-done
+ if refreshDone != nil {
+ <-refreshDone
}
for _, ch := range waiting {
close(ch)
@@ -365,38 +426,109 @@ loop:
func (tab *Table) doRefresh(done chan struct{}) {
defer close(done)
+ // Load nodes from the database and insert
+ // them. This should yield a few previously seen nodes that are
+ // (hopefully) still alive.
+ tab.loadSeedNodes(true)
+
+ // Run self lookup to discover new neighbor nodes.
+ tab.lookup(tab.self.ID, false)
+
// The Kademlia paper specifies that the bucket refresh should
// perform a lookup in the least recently used bucket. We cannot
// adhere to this because the findnode target is a 512bit value
// (not hash-sized) and it is not easily possible to generate a
// sha3 preimage that falls into a chosen bucket.
- // We perform a lookup with a random target instead.
- var target NodeID
- rand.Read(target[:])
- result := tab.lookup(target, false)
- if len(result) > 0 {
- return
+ // We perform a few lookups with a random target instead.
+ for i := 0; i < 3; i++ {
+ var target NodeID
+ crand.Read(target[:])
+ tab.lookup(target, false)
}
+}
- // The table is empty. Load nodes from the database and insert
- // them. This should yield a few previously seen nodes that are
- // (hopefully) still alive.
+func (tab *Table) loadSeedNodes(bond bool) {
seeds := tab.db.querySeeds(seedCount, seedMaxAge)
- seeds = tab.bondall(append(seeds, tab.nursery...))
+ seeds = append(seeds, tab.nursery...)
+ if bond {
+ seeds = tab.bondall(seeds)
+ }
+ for i := range seeds {
+ seed := seeds[i]
+ age := log.Lazy{Fn: func() interface{} { return time.Since(tab.db.bondTime(seed.ID)) }}
+ log.Debug("Found seed node in database", "id", seed.ID, "addr", seed.addr(), "age", age)
+ tab.add(seed)
+ }
+}
- if len(seeds) == 0 {
- log.Debug("No discv4 seed nodes found")
+// doRevalidate checks that the last node in a random bucket is still live
+// and replaces or deletes the node if it isn't.
+func (tab *Table) doRevalidate(done chan<- struct{}) {
+ defer func() { done <- struct{}{} }()
+
+ last, bi := tab.nodeToRevalidate()
+ if last == nil {
+ // No non-empty bucket found.
+ return
+ }
+
+ // Ping the selected node and wait for a pong.
+ err := tab.ping(last.ID, last.addr())
+
+ tab.mutex.Lock()
+ defer tab.mutex.Unlock()
+ b := tab.buckets[bi]
+ if err == nil {
+ // The node responded, move it to the front.
+ log.Debug("Revalidated node", "b", bi, "id", last.ID)
+ b.bump(last)
+ return
}
- for _, n := range seeds {
- age := log.Lazy{Fn: func() time.Duration { return time.Since(tab.db.lastPong(n.ID)) }}
- log.Trace("Found seed node in database", "id", n.ID, "addr", n.addr(), "age", age)
+ // No reply received, pick a replacement or delete the node if there aren't
+ // any replacements.
+ if r := tab.replace(b, last); r != nil {
+ log.Debug("Replaced dead node", "b", bi, "id", last.ID, "ip", last.IP, "r", r.ID, "rip", r.IP)
+ } else {
+ log.Debug("Removed dead node", "b", bi, "id", last.ID, "ip", last.IP)
}
+}
+
+// nodeToRevalidate returns the last node in a random, non-empty bucket.
+func (tab *Table) nodeToRevalidate() (n *Node, bi int) {
tab.mutex.Lock()
- tab.stuff(seeds)
- tab.mutex.Unlock()
+ defer tab.mutex.Unlock()
- // Finally, do a self lookup to fill up the buckets.
- tab.lookup(tab.self.ID, false)
+ for _, bi = range tab.rand.Perm(len(tab.buckets)) {
+ b := tab.buckets[bi]
+ if len(b.entries) > 0 {
+ last := b.entries[len(b.entries)-1]
+ return last, bi
+ }
+ }
+ return nil, 0
+}
+
+func (tab *Table) nextRevalidateTime() time.Duration {
+ tab.mutex.Lock()
+ defer tab.mutex.Unlock()
+
+ return time.Duration(tab.rand.Int63n(int64(revalidateInterval)))
+}
+
+// copyBondedNodes adds nodes from the table to the database if they have been in the table
+// longer then minTableTime.
+func (tab *Table) copyBondedNodes() {
+ tab.mutex.Lock()
+ defer tab.mutex.Unlock()
+
+ now := time.Now()
+ for _, b := range tab.buckets {
+ for _, n := range b.entries {
+ if now.Sub(n.addedAt) >= seedMinTableTime {
+ tab.db.updateNode(n)
+ }
+ }
+ }
}
// closest returns the n nodes in the table that are closest to the
@@ -459,15 +591,14 @@ func (tab *Table) bond(pinged bool, id NodeID, addr *net.UDPAddr, tcpPort uint16
if id == tab.self.ID {
return nil, errors.New("is self")
}
- // Retrieve a previously known node and any recent findnode failures
- node, fails := tab.db.node(id), 0
- if node != nil {
- fails = tab.db.findFails(id)
+ if pinged && !tab.isInitDone() {
+ return nil, errors.New("still initializing")
}
- // If the node is unknown (non-bonded) or failed (remotely unknown), bond from scratch
+ // Start bonding if we haven't seen this node for a while or if it failed findnode too often.
+ node, fails := tab.db.node(id), tab.db.findFails(id)
+ age := time.Since(tab.db.bondTime(id))
var result error
- age := time.Since(tab.db.lastPong(id))
- if node == nil || fails > 0 || age > nodeDBNodeExpiration {
+ if fails > 0 || age > nodeDBNodeExpiration {
log.Trace("Starting bonding ping/pong", "id", id, "known", node != nil, "failcount", fails, "age", age)
tab.bondmu.Lock()
@@ -494,10 +625,10 @@ func (tab *Table) bond(pinged bool, id NodeID, addr *net.UDPAddr, tcpPort uint16
node = w.n
}
}
+ // Add the node to the table even if the bonding ping/pong
+ // fails. It will be relaced quickly if it continues to be
+ // unresponsive.
if node != nil {
- // Add the node to the table even if the bonding ping/pong
- // fails. It will be relaced quickly if it continues to be
- // unresponsive.
tab.add(node)
tab.db.updateFindFails(id, 0)
}
@@ -522,7 +653,6 @@ func (tab *Table) pingpong(w *bondproc, pinged bool, id NodeID, addr *net.UDPAdd
}
// Bonding succeeded, update the node database.
w.n = NewNode(id, addr.IP, uint16(addr.Port), tcpPort)
- tab.db.updateNode(w.n)
close(w.done)
}
@@ -533,17 +663,19 @@ func (tab *Table) ping(id NodeID, addr *net.UDPAddr) error {
if err := tab.net.ping(id, addr); err != nil {
return err
}
- tab.db.updateLastPong(id, time.Now())
-
- // Start the background expiration goroutine after the first
- // successful communication. Subsequent calls have no effect if it
- // is already running. We do this here instead of somewhere else
- // so that the search for seed nodes also considers older nodes
- // that would otherwise be removed by the expiration.
- tab.db.ensureExpirer()
+ tab.db.updateBondTime(id, time.Now())
return nil
}
+// bucket returns the bucket for the given node ID hash.
+func (tab *Table) bucket(sha common.Hash) *bucket {
+ d := logdist(tab.self.sha, sha)
+ if d <= bucketMinDistance {
+ return tab.buckets[0]
+ }
+ return tab.buckets[d-bucketMinDistance-1]
+}
+
// add attempts to add the given node its corresponding bucket. If the
// bucket has space available, adding the node succeeds immediately.
// Otherwise, the node is added if the least recently active node in
@@ -551,57 +683,29 @@ func (tab *Table) ping(id NodeID, addr *net.UDPAddr) error {
//
// The caller must not hold tab.mutex.
func (tab *Table) add(new *Node) {
- b := tab.buckets[logdist(tab.self.sha, new.sha)]
tab.mutex.Lock()
defer tab.mutex.Unlock()
- if b.bump(new) {
- return
- }
- var oldest *Node
- if len(b.entries) == bucketSize {
- oldest = b.entries[bucketSize-1]
- if oldest.contested {
- // The node is already being replaced, don't attempt
- // to replace it.
- return
- }
- oldest.contested = true
- // Let go of the mutex so other goroutines can access
- // the table while we ping the least recently active node.
- tab.mutex.Unlock()
- err := tab.ping(oldest.ID, oldest.addr())
- tab.mutex.Lock()
- oldest.contested = false
- if err == nil {
- // The node responded, don't replace it.
- return
- }
- }
- added := b.replace(new, oldest)
- if added && tab.nodeAddedHook != nil {
- tab.nodeAddedHook(new)
+
+ b := tab.bucket(new.sha)
+ if !tab.bumpOrAdd(b, new) {
+ // Node is not in table. Add it to the replacement list.
+ tab.addReplacement(b, new)
}
}
// stuff adds nodes the table to the end of their corresponding bucket
-// if the bucket is not full. The caller must hold tab.mutex.
+// if the bucket is not full. The caller must not hold tab.mutex.
func (tab *Table) stuff(nodes []*Node) {
-outer:
+ tab.mutex.Lock()
+ defer tab.mutex.Unlock()
+
for _, n := range nodes {
if n.ID == tab.self.ID {
continue // don't add self
}
- bucket := tab.buckets[logdist(tab.self.sha, n.sha)]
- for i := range bucket.entries {
- if bucket.entries[i].ID == n.ID {
- continue outer // already in bucket
- }
- }
- if len(bucket.entries) < bucketSize {
- bucket.entries = append(bucket.entries, n)
- if tab.nodeAddedHook != nil {
- tab.nodeAddedHook(n)
- }
+ b := tab.bucket(n.sha)
+ if len(b.entries) < bucketSize {
+ tab.bumpOrAdd(b, n)
}
}
}
@@ -611,36 +715,72 @@ outer:
func (tab *Table) delete(node *Node) {
tab.mutex.Lock()
defer tab.mutex.Unlock()
- bucket := tab.buckets[logdist(tab.self.sha, node.sha)]
- for i := range bucket.entries {
- if bucket.entries[i].ID == node.ID {
- bucket.entries = append(bucket.entries[:i], bucket.entries[i+1:]...)
- return
- }
- }
+
+ tab.deleteInBucket(tab.bucket(node.sha), node)
}
-func (b *bucket) replace(n *Node, last *Node) bool {
- // Don't add if b already contains n.
- for i := range b.entries {
- if b.entries[i].ID == n.ID {
- return false
- }
+func (tab *Table) addIP(b *bucket, ip net.IP) bool {
+ if netutil.IsLAN(ip) {
+ return true
}
- // Replace last if it is still the last entry or just add n if b
- // isn't full. If is no longer the last entry, it has either been
- // replaced with someone else or became active.
- if len(b.entries) == bucketSize && (last == nil || b.entries[bucketSize-1].ID != last.ID) {
+ if !tab.ips.Add(ip) {
+ log.Debug("IP exceeds table limit", "ip", ip)
return false
}
- if len(b.entries) < bucketSize {
- b.entries = append(b.entries, nil)
+ if !b.ips.Add(ip) {
+ log.Debug("IP exceeds bucket limit", "ip", ip)
+ tab.ips.Remove(ip)
+ return false
}
- copy(b.entries[1:], b.entries)
- b.entries[0] = n
return true
}
+func (tab *Table) removeIP(b *bucket, ip net.IP) {
+ if netutil.IsLAN(ip) {
+ return
+ }
+ tab.ips.Remove(ip)
+ b.ips.Remove(ip)
+}
+
+func (tab *Table) addReplacement(b *bucket, n *Node) {
+ for _, e := range b.replacements {
+ if e.ID == n.ID {
+ return // already in list
+ }
+ }
+ if !tab.addIP(b, n.IP) {
+ return
+ }
+ var removed *Node
+ b.replacements, removed = pushNode(b.replacements, n, maxReplacements)
+ if removed != nil {
+ tab.removeIP(b, removed.IP)
+ }
+}
+
+// replace removes n from the replacement list and replaces 'last' with it if it is the
+// last entry in the bucket. If 'last' isn't the last entry, it has either been replaced
+// with someone else or became active.
+func (tab *Table) replace(b *bucket, last *Node) *Node {
+ if len(b.entries) == 0 || b.entries[len(b.entries)-1].ID != last.ID {
+ // Entry has moved, don't replace it.
+ return nil
+ }
+ // Still the last entry.
+ if len(b.replacements) == 0 {
+ tab.deleteInBucket(b, last)
+ return nil
+ }
+ r := b.replacements[tab.rand.Intn(len(b.replacements))]
+ b.replacements = deleteNode(b.replacements, r)
+ b.entries[len(b.entries)-1] = r
+ tab.removeIP(b, last.IP)
+ return r
+}
+
+// bump moves the given node to the front of the bucket entry list
+// if it is contained in that list.
func (b *bucket) bump(n *Node) bool {
for i := range b.entries {
if b.entries[i].ID == n.ID {
@@ -653,6 +793,50 @@ func (b *bucket) bump(n *Node) bool {
return false
}
+// bumpOrAdd moves n to the front of the bucket entry list or adds it if the list isn't
+// full. The return value is true if n is in the bucket.
+func (tab *Table) bumpOrAdd(b *bucket, n *Node) bool {
+ if b.bump(n) {
+ return true
+ }
+ if len(b.entries) >= bucketSize || !tab.addIP(b, n.IP) {
+ return false
+ }
+ b.entries, _ = pushNode(b.entries, n, bucketSize)
+ b.replacements = deleteNode(b.replacements, n)
+ n.addedAt = time.Now()
+ if tab.nodeAddedHook != nil {
+ tab.nodeAddedHook(n)
+ }
+ return true
+}
+
+func (tab *Table) deleteInBucket(b *bucket, n *Node) {
+ b.entries = deleteNode(b.entries, n)
+ tab.removeIP(b, n.IP)
+}
+
+// pushNode adds n to the front of list, keeping at most max items.
+func pushNode(list []*Node, n *Node, max int) ([]*Node, *Node) {
+ if len(list) < max {
+ list = append(list, nil)
+ }
+ removed := list[len(list)-1]
+ copy(list[1:], list)
+ list[0] = n
+ return list, removed
+}
+
+// deleteNode removes n from list.
+func deleteNode(list []*Node, n *Node) []*Node {
+ for i := range list {
+ if list[i].ID == n.ID {
+ return append(list[:i], list[i+1:]...)
+ }
+ }
+ return list
+}
+
// nodesByDistance is a list of nodes, ordered by
// distance to target.
type nodesByDistance struct {
diff --git a/p2p/discover/table_test.go b/p2p/discover/table_test.go
index 1037cc609..3ce48d299 100644
--- a/p2p/discover/table_test.go
+++ b/p2p/discover/table_test.go
@@ -20,6 +20,7 @@ import (
"crypto/ecdsa"
"fmt"
"math/rand"
+ "sync"
"net"
"reflect"
@@ -32,60 +33,65 @@ import (
)
func TestTable_pingReplace(t *testing.T) {
- doit := func(newNodeIsResponding, lastInBucketIsResponding bool) {
- transport := newPingRecorder()
- tab, _ := newTable(transport, NodeID{}, &net.UDPAddr{}, "")
- defer tab.Close()
- pingSender := NewNode(MustHexID("a502af0f59b2aab7746995408c79e9ca312d2793cc997e44fc55eda62f0150bbb8c59a6f9269ba3a081518b62699ee807c7c19c20125ddfccca872608af9e370"), net.IP{}, 99, 99)
+ run := func(newNodeResponding, lastInBucketResponding bool) {
+ name := fmt.Sprintf("newNodeResponding=%t/lastInBucketResponding=%t", newNodeResponding, lastInBucketResponding)
+ t.Run(name, func(t *testing.T) {
+ t.Parallel()
+ testPingReplace(t, newNodeResponding, lastInBucketResponding)
+ })
+ }
- // fill up the sender's bucket.
- last := fillBucket(tab, 253)
+ run(true, true)
+ run(false, true)
+ run(true, false)
+ run(false, false)
+}
- // this call to bond should replace the last node
- // in its bucket if the node is not responding.
- transport.responding[last.ID] = lastInBucketIsResponding
- transport.responding[pingSender.ID] = newNodeIsResponding
- tab.bond(true, pingSender.ID, &net.UDPAddr{}, 0)
+func testPingReplace(t *testing.T, newNodeIsResponding, lastInBucketIsResponding bool) {
+ transport := newPingRecorder()
+ tab, _ := newTable(transport, NodeID{}, &net.UDPAddr{}, "", nil)
+ defer tab.Close()
- // first ping goes to sender (bonding pingback)
- if !transport.pinged[pingSender.ID] {
- t.Error("table did not ping back sender")
- }
- if newNodeIsResponding {
- // second ping goes to oldest node in bucket
- // to see whether it is still alive.
- if !transport.pinged[last.ID] {
- t.Error("table did not ping last node in bucket")
- }
- }
+ // Wait for init so bond is accepted.
+ <-tab.initDone
- tab.mutex.Lock()
- defer tab.mutex.Unlock()
- if l := len(tab.buckets[253].entries); l != bucketSize {
- t.Errorf("wrong bucket size after bond: got %d, want %d", l, bucketSize)
- }
+ // fill up the sender's bucket.
+ pingSender := NewNode(MustHexID("a502af0f59b2aab7746995408c79e9ca312d2793cc997e44fc55eda62f0150bbb8c59a6f9269ba3a081518b62699ee807c7c19c20125ddfccca872608af9e370"), net.IP{}, 99, 99)
+ last := fillBucket(tab, pingSender)
- if lastInBucketIsResponding || !newNodeIsResponding {
- if !contains(tab.buckets[253].entries, last.ID) {
- t.Error("last entry was removed")
- }
- if contains(tab.buckets[253].entries, pingSender.ID) {
- t.Error("new entry was added")
- }
- } else {
- if contains(tab.buckets[253].entries, last.ID) {
- t.Error("last entry was not removed")
- }
- if !contains(tab.buckets[253].entries, pingSender.ID) {
- t.Error("new entry was not added")
- }
- }
+ // this call to bond should replace the last node
+ // in its bucket if the node is not responding.
+ transport.dead[last.ID] = !lastInBucketIsResponding
+ transport.dead[pingSender.ID] = !newNodeIsResponding
+ tab.bond(true, pingSender.ID, &net.UDPAddr{}, 0)
+ tab.doRevalidate(make(chan struct{}, 1))
+
+ // first ping goes to sender (bonding pingback)
+ if !transport.pinged[pingSender.ID] {
+ t.Error("table did not ping back sender")
+ }
+ if !transport.pinged[last.ID] {
+ // second ping goes to oldest node in bucket
+ // to see whether it is still alive.
+ t.Error("table did not ping last node in bucket")
}
- doit(true, true)
- doit(false, true)
- doit(true, false)
- doit(false, false)
+ tab.mutex.Lock()
+ defer tab.mutex.Unlock()
+ wantSize := bucketSize
+ if !lastInBucketIsResponding && !newNodeIsResponding {
+ wantSize--
+ }
+ if l := len(tab.bucket(pingSender.sha).entries); l != wantSize {
+ t.Errorf("wrong bucket size after bond: got %d, want %d", l, wantSize)
+ }
+ if found := contains(tab.bucket(pingSender.sha).entries, last.ID); found != lastInBucketIsResponding {
+ t.Errorf("last entry found: %t, want: %t", found, lastInBucketIsResponding)
+ }
+ wantNewEntry := newNodeIsResponding && !lastInBucketIsResponding
+ if found := contains(tab.bucket(pingSender.sha).entries, pingSender.ID); found != wantNewEntry {
+ t.Errorf("new entry found: %t, want: %t", found, wantNewEntry)
+ }
}
func TestBucket_bumpNoDuplicates(t *testing.T) {
@@ -130,11 +136,45 @@ func TestBucket_bumpNoDuplicates(t *testing.T) {
}
}
+// This checks that the table-wide IP limit is applied correctly.
+func TestTable_IPLimit(t *testing.T) {
+ transport := newPingRecorder()
+ tab, _ := newTable(transport, NodeID{}, &net.UDPAddr{}, "", nil)
+ defer tab.Close()
+
+ for i := 0; i < tableIPLimit+1; i++ {
+ n := nodeAtDistance(tab.self.sha, i)
+ n.IP = net.IP{172, 0, 1, byte(i)}
+ tab.add(n)
+ }
+ if tab.len() > tableIPLimit {
+ t.Errorf("too many nodes in table")
+ }
+}
+
+// This checks that the table-wide IP limit is applied correctly.
+func TestTable_BucketIPLimit(t *testing.T) {
+ transport := newPingRecorder()
+ tab, _ := newTable(transport, NodeID{}, &net.UDPAddr{}, "", nil)
+ defer tab.Close()
+
+ d := 3
+ for i := 0; i < bucketIPLimit+1; i++ {
+ n := nodeAtDistance(tab.self.sha, d)
+ n.IP = net.IP{172, 0, 1, byte(i)}
+ tab.add(n)
+ }
+ if tab.len() > bucketIPLimit {
+ t.Errorf("too many nodes in table")
+ }
+}
+
// fillBucket inserts nodes into the given bucket until
// it is full. The node's IDs dont correspond to their
// hashes.
-func fillBucket(tab *Table, ld int) (last *Node) {
- b := tab.buckets[ld]
+func fillBucket(tab *Table, n *Node) (last *Node) {
+ ld := logdist(tab.self.sha, n.sha)
+ b := tab.bucket(n.sha)
for len(b.entries) < bucketSize {
b.entries = append(b.entries, nodeAtDistance(tab.self.sha, ld))
}
@@ -146,30 +186,39 @@ func fillBucket(tab *Table, ld int) (last *Node) {
func nodeAtDistance(base common.Hash, ld int) (n *Node) {
n = new(Node)
n.sha = hashAtDistance(base, ld)
- n.IP = net.IP{10, 0, 2, byte(ld)}
+ n.IP = net.IP{byte(ld), 0, 2, byte(ld)}
copy(n.ID[:], n.sha[:]) // ensure the node still has a unique ID
return n
}
-type pingRecorder struct{ responding, pinged map[NodeID]bool }
+type pingRecorder struct {
+ mu sync.Mutex
+ dead, pinged map[NodeID]bool
+}
func newPingRecorder() *pingRecorder {
- return &pingRecorder{make(map[NodeID]bool), make(map[NodeID]bool)}
+ return &pingRecorder{
+ dead: make(map[NodeID]bool),
+ pinged: make(map[NodeID]bool),
+ }
}
func (t *pingRecorder) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node, error) {
- panic("findnode called on pingRecorder")
+ return nil, nil
}
func (t *pingRecorder) close() {}
func (t *pingRecorder) waitping(from NodeID) error {
return nil // remote always pings
}
func (t *pingRecorder) ping(toid NodeID, toaddr *net.UDPAddr) error {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+
t.pinged[toid] = true
- if t.responding[toid] {
- return nil
- } else {
+ if t.dead[toid] {
return errTimeout
+ } else {
+ return nil
}
}
@@ -178,7 +227,8 @@ func TestTable_closest(t *testing.T) {
test := func(test *closeTest) bool {
// for any node table, Target and N
- tab, _ := newTable(nil, test.Self, &net.UDPAddr{}, "")
+ transport := newPingRecorder()
+ tab, _ := newTable(transport, test.Self, &net.UDPAddr{}, "", nil)
defer tab.Close()
tab.stuff(test.All)
@@ -237,8 +287,11 @@ func TestTable_ReadRandomNodesGetAll(t *testing.T) {
},
}
test := func(buf []*Node) bool {
- tab, _ := newTable(nil, NodeID{}, &net.UDPAddr{}, "")
+ transport := newPingRecorder()
+ tab, _ := newTable(transport, NodeID{}, &net.UDPAddr{}, "", nil)
defer tab.Close()
+ <-tab.initDone
+
for i := 0; i < len(buf); i++ {
ld := cfg.Rand.Intn(len(tab.buckets))
tab.stuff([]*Node{nodeAtDistance(tab.self.sha, ld)})
@@ -280,7 +333,7 @@ func (*closeTest) Generate(rand *rand.Rand, size int) reflect.Value {
func TestTable_Lookup(t *testing.T) {
self := nodeAtDistance(common.Hash{}, 0)
- tab, _ := newTable(lookupTestnet, self.ID, &net.UDPAddr{}, "")
+ tab, _ := newTable(lookupTestnet, self.ID, &net.UDPAddr{}, "", nil)
defer tab.Close()
// lookup on empty table returns no nodes
diff --git a/p2p/discover/udp.go b/p2p/discover/udp.go
index f9eb99ee3..524c6e498 100644
--- a/p2p/discover/udp.go
+++ b/p2p/discover/udp.go
@@ -210,17 +210,28 @@ type reply struct {
matched chan<- bool
}
+// ReadPacket is sent to the unhandled channel when it could not be processed
+type ReadPacket struct {
+ Data []byte
+ Addr *net.UDPAddr
+}
+
+// Config holds Table-related settings.
+type Config struct {
+ // These settings are required and configure the UDP listener:
+ PrivateKey *ecdsa.PrivateKey
+
+ // These settings are optional:
+ AnnounceAddr *net.UDPAddr // local address announced in the DHT
+ NodeDBPath string // if set, the node database is stored at this filesystem location
+ NetRestrict *netutil.Netlist // network whitelist
+ Bootnodes []*Node // list of bootstrap nodes
+ Unhandled chan<- ReadPacket // unhandled packets are sent on this channel
+}
+
// ListenUDP returns a new table that listens for UDP packets on laddr.
-func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface, nodeDBPath string, netrestrict *netutil.Netlist) (*Table, error) {
- addr, err := net.ResolveUDPAddr("udp", laddr)
- if err != nil {
- return nil, err
- }
- conn, err := net.ListenUDP("udp", addr)
- if err != nil {
- return nil, err
- }
- tab, _, err := newUDP(priv, conn, natm, nodeDBPath, netrestrict)
+func ListenUDP(c conn, cfg Config) (*Table, error) {
+ tab, _, err := newUDP(c, cfg)
if err != nil {
return nil, err
}
@@ -228,35 +239,29 @@ func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface, nodeDBP
return tab, nil
}
-func newUDP(priv *ecdsa.PrivateKey, c conn, natm nat.Interface, nodeDBPath string, netrestrict *netutil.Netlist) (*Table, *udp, error) {
+func newUDP(c conn, cfg Config) (*Table, *udp, error) {
udp := &udp{
conn: c,
- priv: priv,
- netrestrict: netrestrict,
+ priv: cfg.PrivateKey,
+ netrestrict: cfg.NetRestrict,
closing: make(chan struct{}),
gotreply: make(chan reply),
addpending: make(chan *pending),
}
realaddr := c.LocalAddr().(*net.UDPAddr)
- if natm != nil {
- if !realaddr.IP.IsLoopback() {
- go nat.Map(natm, udp.closing, "udp", realaddr.Port, realaddr.Port, "ethereum discovery")
- }
- // TODO: react to external IP changes over time.
- if ext, err := natm.ExternalIP(); err == nil {
- realaddr = &net.UDPAddr{IP: ext, Port: realaddr.Port}
- }
+ if cfg.AnnounceAddr != nil {
+ realaddr = cfg.AnnounceAddr
}
// TODO: separate TCP port
udp.ourEndpoint = makeEndpoint(realaddr, uint16(realaddr.Port))
- tab, err := newTable(udp, PubkeyID(&priv.PublicKey), realaddr, nodeDBPath)
+ tab, err := newTable(udp, PubkeyID(&cfg.PrivateKey.PublicKey), realaddr, cfg.NodeDBPath, cfg.Bootnodes)
if err != nil {
return nil, nil, err
}
udp.Table = tab
go udp.loop()
- go udp.readLoop()
+ go udp.readLoop(cfg.Unhandled)
return udp.Table, udp, nil
}
@@ -268,14 +273,20 @@ func (t *udp) close() {
// ping sends a ping message to the given node and waits for a reply.
func (t *udp) ping(toid NodeID, toaddr *net.UDPAddr) error {
- // TODO: maybe check for ReplyTo field in callback to measure RTT
- errc := t.pending(toid, pongPacket, func(interface{}) bool { return true })
- t.send(toaddr, pingPacket, &ping{
+ req := &ping{
Version: Version,
From: t.ourEndpoint,
To: makeEndpoint(toaddr, 0), // TODO: maybe use known TCP port from DB
Expiration: uint64(time.Now().Add(expiration).Unix()),
+ }
+ packet, hash, err := encodePacket(t.priv, pingPacket, req)
+ if err != nil {
+ return err
+ }
+ errc := t.pending(toid, pongPacket, func(p interface{}) bool {
+ return bytes.Equal(p.(*pong).ReplyTok, hash)
})
+ t.write(toaddr, req.name(), packet)
return <-errc
}
@@ -459,41 +470,49 @@ func init() {
}
}
-func (t *udp) send(toaddr *net.UDPAddr, ptype byte, req packet) error {
- packet, err := encodePacket(t.priv, ptype, req)
+func (t *udp) send(toaddr *net.UDPAddr, ptype byte, req packet) ([]byte, error) {
+ packet, hash, err := encodePacket(t.priv, ptype, req)
if err != nil {
- return err
+ return hash, err
}
- _, err = t.conn.WriteToUDP(packet, toaddr)
- log.Trace(">> "+req.name(), "addr", toaddr, "err", err)
+ return hash, t.write(toaddr, req.name(), packet)
+}
+
+func (t *udp) write(toaddr *net.UDPAddr, what string, packet []byte) error {
+ _, err := t.conn.WriteToUDP(packet, toaddr)
+ log.Trace(">> "+what, "addr", toaddr, "err", err)
return err
}
-func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) ([]byte, error) {
+func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) (packet, hash []byte, err error) {
b := new(bytes.Buffer)
b.Write(headSpace)
b.WriteByte(ptype)
if err := rlp.Encode(b, req); err != nil {
log.Error("Can't encode discv4 packet", "err", err)
- return nil, err
+ return nil, nil, err
}
- packet := b.Bytes()
+ packet = b.Bytes()
sig, err := crypto.Sign(crypto.Keccak256(packet[headSize:]), priv)
if err != nil {
log.Error("Can't sign discv4 packet", "err", err)
- return nil, err
+ return nil, nil, err
}
copy(packet[macSize:], sig)
// add the hash to the front. Note: this doesn't protect the
// packet in any way. Our public key will be part of this hash in
// The future.
- copy(packet, crypto.Keccak256(packet[macSize:]))
- return packet, nil
+ hash = crypto.Keccak256(packet[macSize:])
+ copy(packet, hash)
+ return packet, hash, nil
}
// readLoop runs in its own goroutine. it handles incoming UDP packets.
-func (t *udp) readLoop() {
+func (t *udp) readLoop(unhandled chan<- ReadPacket) {
defer t.conn.Close()
+ if unhandled != nil {
+ defer close(unhandled)
+ }
// Discovery packets are defined to be no larger than 1280 bytes.
// Packets larger than this size will be cut at the end and treated
// as invalid because their hash won't match.
@@ -509,7 +528,12 @@ func (t *udp) readLoop() {
log.Debug("UDP read error", "err", err)
return
}
- t.handlePacket(from, buf[:nbytes])
+ if t.handlePacket(from, buf[:nbytes]) != nil && unhandled != nil {
+ select {
+ case unhandled <- ReadPacket{buf[:nbytes], from}:
+ default:
+ }
+ }
}
}
@@ -589,7 +613,7 @@ func (req *findnode) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte
if expired(req.Expiration) {
return errExpired
}
- if t.db.node(fromID) == nil {
+ if !t.db.hasBond(fromID) {
// No bond exists, we don't process the packet. This prevents
// an attack vector where the discovery protocol could be used
// to amplify traffic in a DDOS attack. A malicious actor
@@ -605,18 +629,22 @@ func (req *findnode) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte
t.mutex.Unlock()
p := neighbors{Expiration: uint64(time.Now().Add(expiration).Unix())}
+ var sent bool
// Send neighbors in chunks with at most maxNeighbors per packet
// to stay below the 1280 byte limit.
- for i, n := range closest {
- if netutil.CheckRelayIP(from.IP, n.IP) != nil {
- continue
+ for _, n := range closest {
+ if netutil.CheckRelayIP(from.IP, n.IP) == nil {
+ p.Nodes = append(p.Nodes, nodeToRPC(n))
}
- p.Nodes = append(p.Nodes, nodeToRPC(n))
- if len(p.Nodes) == maxNeighbors || i == len(closest)-1 {
+ if len(p.Nodes) == maxNeighbors {
t.send(from, neighborsPacket, &p)
p.Nodes = p.Nodes[:0]
+ sent = true
}
}
+ if len(p.Nodes) > 0 || !sent {
+ t.send(from, neighborsPacket, &p)
+ }
return nil
}
diff --git a/p2p/discover/udp_test.go b/p2p/discover/udp_test.go
index 21e8b561d..db9804f7b 100644
--- a/p2p/discover/udp_test.go
+++ b/p2p/discover/udp_test.go
@@ -70,13 +70,15 @@ func newUDPTest(t *testing.T) *udpTest {
remotekey: newkey(),
remoteaddr: &net.UDPAddr{IP: net.IP{10, 0, 1, 99}, Port: 30303},
}
- test.table, test.udp, _ = newUDP(test.localkey, test.pipe, nil, "", nil)
+ test.table, test.udp, _ = newUDP(test.pipe, Config{PrivateKey: test.localkey})
+ // Wait for initial refresh so the table doesn't send unexpected findnode.
+ <-test.table.initDone
return test
}
// handles a packet as if it had been sent to the transport.
func (test *udpTest) packetIn(wantError error, ptype byte, data packet) error {
- enc, err := encodePacket(test.remotekey, ptype, data)
+ enc, _, err := encodePacket(test.remotekey, ptype, data)
if err != nil {
return test.errorf("packet (%d) encode error: %v", ptype, err)
}
@@ -89,19 +91,19 @@ func (test *udpTest) packetIn(wantError error, ptype byte, data packet) error {
// waits for a packet to be sent by the transport.
// validate should have type func(*udpTest, X) error, where X is a packet type.
-func (test *udpTest) waitPacketOut(validate interface{}) error {
+func (test *udpTest) waitPacketOut(validate interface{}) ([]byte, error) {
dgram := test.pipe.waitPacketOut()
- p, _, _, err := decodePacket(dgram)
+ p, _, hash, err := decodePacket(dgram)
if err != nil {
- return test.errorf("sent packet decode error: %v", err)
+ return hash, test.errorf("sent packet decode error: %v", err)
}
fn := reflect.ValueOf(validate)
exptype := fn.Type().In(0)
if reflect.TypeOf(p) != exptype {
- return test.errorf("sent packet type mismatch, got: %v, want: %v", reflect.TypeOf(p), exptype)
+ return hash, test.errorf("sent packet type mismatch, got: %v, want: %v", reflect.TypeOf(p), exptype)
}
fn.Call([]reflect.Value{reflect.ValueOf(p)})
- return nil
+ return hash, nil
}
func (test *udpTest) errorf(format string, args ...interface{}) error {
@@ -245,12 +247,8 @@ func TestUDP_findnode(t *testing.T) {
// ensure there's a bond with the test node,
// findnode won't be accepted otherwise.
- test.table.db.updateNode(NewNode(
- PubkeyID(&test.remotekey.PublicKey),
- test.remoteaddr.IP,
- uint16(test.remoteaddr.Port),
- 99,
- ))
+ test.table.db.updateBondTime(PubkeyID(&test.remotekey.PublicKey), time.Now())
+
// check that closest neighbors are returned.
test.packetIn(nil, findnodePacket, &findnode{Target: testTarget, Expiration: futureExp})
expected := test.table.closest(targetHash, bucketSize)
@@ -350,7 +348,7 @@ func TestUDP_successfulPing(t *testing.T) {
})
// remote is unknown, the table pings back.
- test.waitPacketOut(func(p *ping) error {
+ hash, _ := test.waitPacketOut(func(p *ping) error {
if !reflect.DeepEqual(p.From, test.udp.ourEndpoint) {
t.Errorf("got ping.From %v, want %v", p.From, test.udp.ourEndpoint)
}
@@ -364,7 +362,7 @@ func TestUDP_successfulPing(t *testing.T) {
}
return nil
})
- test.packetIn(nil, pongPacket, &pong{Expiration: futureExp})
+ test.packetIn(nil, pongPacket, &pong{ReplyTok: hash, Expiration: futureExp})
// the node should be added to the table shortly after getting the
// pong packet.
diff --git a/p2p/discv5/database.go b/p2p/discv5/database.go
index a3b044ec1..3c2d5744c 100644
--- a/p2p/discv5/database.go
+++ b/p2p/discv5/database.go
@@ -239,14 +239,14 @@ func (db *nodeDB) ensureExpirer() {
// expirer should be started in a go routine, and is responsible for looping ad
// infinitum and dropping stale data from the database.
func (db *nodeDB) expirer() {
- tick := time.Tick(nodeDBCleanupCycle)
+ tick := time.NewTicker(nodeDBCleanupCycle)
+ defer tick.Stop()
for {
select {
- case <-tick:
+ case <-tick.C:
if err := db.expireNodes(); err != nil {
log.Error(fmt.Sprintf("Failed to expire nodedb items: %v", err))
}
-
case <-db.quit:
return
}
diff --git a/p2p/discv5/net.go b/p2p/discv5/net.go
index cd9981584..52c677b62 100644
--- a/p2p/discv5/net.go
+++ b/p2p/discv5/net.go
@@ -29,7 +29,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/sha3"
"github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -134,7 +133,7 @@ type timeoutEvent struct {
node *Node
}
-func newNetwork(conn transport, ourPubkey ecdsa.PublicKey, natm nat.Interface, dbPath string, netrestrict *netutil.Netlist) (*Network, error) {
+func newNetwork(conn transport, ourPubkey ecdsa.PublicKey, dbPath string, netrestrict *netutil.Netlist) (*Network, error) {
ourID := PubkeyID(&ourPubkey)
var db *nodeDB
@@ -566,11 +565,8 @@ loop:
if lookupChn := searchInfo[res.target.topic].lookupChn; lookupChn != nil {
lookupChn <- net.ticketStore.radius[res.target.topic].converged
}
- net.ticketStore.searchLookupDone(res.target, res.nodes, func(n *Node) []byte {
- net.ping(n, n.addr())
- return n.pingEcho
- }, func(n *Node, topic Topic) []byte {
- if n.state == known {
+ net.ticketStore.searchLookupDone(res.target, res.nodes, func(n *Node, topic Topic) []byte {
+ if n.state != nil && n.state.canQuery {
return net.conn.send(n, topicQueryPacket, topicQuery{Topic: topic}) // TODO: set expiration
} else {
if n.state == unknown {
@@ -634,15 +630,20 @@ loop:
}
net.refreshResp <- refreshDone
case <-refreshDone:
- log.Trace("<-net.refreshDone")
- refreshDone = nil
- list := searchReqWhenRefreshDone
- searchReqWhenRefreshDone = nil
- go func() {
- for _, req := range list {
- net.topicSearchReq <- req
- }
- }()
+ log.Trace("<-net.refreshDone", "table size", net.tab.count)
+ if net.tab.count != 0 {
+ refreshDone = nil
+ list := searchReqWhenRefreshDone
+ searchReqWhenRefreshDone = nil
+ go func() {
+ for _, req := range list {
+ net.topicSearchReq <- req
+ }
+ }()
+ } else {
+ refreshDone = make(chan struct{})
+ net.refresh(refreshDone)
+ }
}
}
log.Trace("loop stopped")
@@ -752,7 +753,15 @@ func (net *Network) internNodeFromNeighbours(sender *net.UDPAddr, rn rpcNode) (n
return n, err
}
if !n.IP.Equal(rn.IP) || n.UDP != rn.UDP || n.TCP != rn.TCP {
- err = fmt.Errorf("metadata mismatch: got %v, want %v", rn, n)
+ if n.state == known {
+ // reject address change if node is known by us
+ err = fmt.Errorf("metadata mismatch: got %v, want %v", rn, n)
+ } else {
+ // accept otherwise; this will be handled nicer with signed ENRs
+ n.IP = rn.IP
+ n.UDP = rn.UDP
+ n.TCP = rn.TCP
+ }
}
return n, err
}
diff --git a/p2p/discv5/net_test.go b/p2p/discv5/net_test.go
index bd234f5ba..369282ca9 100644
--- a/p2p/discv5/net_test.go
+++ b/p2p/discv5/net_test.go
@@ -28,7 +28,7 @@ import (
func TestNetwork_Lookup(t *testing.T) {
key, _ := crypto.GenerateKey()
- network, err := newNetwork(lookupTestnet, key.PublicKey, nil, "", nil)
+ network, err := newNetwork(lookupTestnet, key.PublicKey, "", nil)
if err != nil {
t.Fatal(err)
}
diff --git a/p2p/discv5/nodeevent_string.go b/p2p/discv5/nodeevent_string.go
index fde9045c5..eb696fb8b 100644
--- a/p2p/discv5/nodeevent_string.go
+++ b/p2p/discv5/nodeevent_string.go
@@ -1,8 +1,8 @@
-// Code generated by "stringer -type nodeEvent"; DO NOT EDIT
+// Code generated by "stringer -type=nodeEvent"; DO NOT EDIT.
package discv5
-import "fmt"
+import "strconv"
const (
_nodeEvent_name_0 = "invalidEventpingPacketpongPacketfindnodePacketneighborsPacketfindnodeHashPackettopicRegisterPackettopicQueryPackettopicNodesPacket"
@@ -22,6 +22,6 @@ func (i nodeEvent) String() string {
i -= 265
return _nodeEvent_name_1[_nodeEvent_index_1[i]:_nodeEvent_index_1[i+1]]
default:
- return fmt.Sprintf("nodeEvent(%d)", i)
+ return "nodeEvent(" + strconv.FormatInt(int64(i), 10) + ")"
}
}
diff --git a/p2p/discv5/sim_test.go b/p2p/discv5/sim_test.go
index bf57872e2..543faecd4 100644
--- a/p2p/discv5/sim_test.go
+++ b/p2p/discv5/sim_test.go
@@ -282,7 +282,7 @@ func (s *simulation) launchNode(log bool) *Network {
addr := &net.UDPAddr{IP: ip, Port: 30303}
transport := &simTransport{joinTime: time.Now(), sender: id, senderAddr: addr, sim: s, priv: key}
- net, err := newNetwork(transport, key.PublicKey, nil, "<no database>", nil)
+ net, err := newNetwork(transport, key.PublicKey, "<no database>", nil)
if err != nil {
panic("cannot launch new node: " + err.Error())
}
diff --git a/p2p/discv5/ticket.go b/p2p/discv5/ticket.go
index b45ec4d2b..b3d1ac4ba 100644
--- a/p2p/discv5/ticket.go
+++ b/p2p/discv5/ticket.go
@@ -350,7 +350,7 @@ func (s *ticketStore) nextFilteredTicket() (*ticketRef, time.Duration) {
regTime := now + mclock.AbsTime(wait)
topic := ticket.t.topics[ticket.idx]
- if regTime >= s.tickets[topic].nextReg {
+ if s.tickets[topic] != nil && regTime >= s.tickets[topic].nextReg {
return ticket, wait
}
s.removeTicketRef(*ticket)
@@ -420,11 +420,14 @@ func (s *ticketStore) nextRegisterableTicket() (*ticketRef, time.Duration) {
func (s *ticketStore) removeTicketRef(ref ticketRef) {
log.Trace("Removing discovery ticket reference", "node", ref.t.node.ID, "serial", ref.t.serial)
+ // Make nextRegisterableTicket return the next available ticket.
+ s.nextTicketCached = nil
+
topic := ref.topic()
tickets := s.tickets[topic]
if tickets == nil {
- log.Warn("Removing tickets from unknown topic", "topic", topic)
+ log.Trace("Removing tickets from unknown topic", "topic", topic)
return
}
bucket := timeBucket(ref.t.regTime[ref.idx] / mclock.AbsTime(ticketTimeBucketLen))
@@ -450,9 +453,6 @@ func (s *ticketStore) removeTicketRef(ref ticketRef) {
delete(s.nodes, ref.t.node)
delete(s.nodeLastReq, ref.t.node)
}
-
- // Make nextRegisterableTicket return the next available ticket.
- s.nextTicketCached = nil
}
type lookupInfo struct {
@@ -494,13 +494,13 @@ func (s *ticketStore) registerLookupDone(lookup lookupInfo, nodes []*Node, ping
}
}
-func (s *ticketStore) searchLookupDone(lookup lookupInfo, nodes []*Node, ping func(n *Node) []byte, query func(n *Node, topic Topic) []byte) {
+func (s *ticketStore) searchLookupDone(lookup lookupInfo, nodes []*Node, query func(n *Node, topic Topic) []byte) {
now := mclock.Now()
for i, n := range nodes {
if i == 0 || (binary.BigEndian.Uint64(n.sha[:8])^binary.BigEndian.Uint64(lookup.target[:8])) < s.radius[lookup.topic].minRadius {
if lookup.radiusLookup {
if lastReq, ok := s.nodeLastReq[n]; !ok || time.Duration(now-lastReq.time) > radiusTC {
- s.nodeLastReq[n] = reqInfo{pingHash: ping(n), lookup: lookup, time: now}
+ s.nodeLastReq[n] = reqInfo{pingHash: nil, lookup: lookup, time: now}
}
} // else {
if s.canQueryTopic(n, lookup.topic) {
@@ -642,7 +642,7 @@ func (s *ticketStore) gotTopicNodes(from *Node, hash common.Hash, nodes []rpcNod
if ip.IsUnspecified() || ip.IsLoopback() {
ip = from.IP
}
- n := NewNode(node.ID, ip, node.UDP-1, node.TCP-1) // subtract one from port while discv5 is running in test mode on UDPport+1
+ n := NewNode(node.ID, ip, node.UDP, node.TCP)
select {
case chn <- n:
default:
diff --git a/p2p/discv5/udp.go b/p2p/discv5/udp.go
index 26087cd8e..6ce72d2c1 100644
--- a/p2p/discv5/udp.go
+++ b/p2p/discv5/udp.go
@@ -37,7 +37,7 @@ const Version = 4
// Errors
var (
errPacketTooSmall = errors.New("too small")
- errBadHash = errors.New("bad hash")
+ errBadPrefix = errors.New("bad prefix")
errExpired = errors.New("expired")
errUnsolicitedReply = errors.New("unsolicited reply")
errUnknownNode = errors.New("unknown node")
@@ -49,7 +49,7 @@ var (
// Timeouts
const (
respTimeout = 500 * time.Millisecond
- sendTimeout = 500 * time.Millisecond
+ queryDelay = 1000 * time.Millisecond
expiration = 20 * time.Second
ntpFailureThreshold = 32 // Continuous timeouts after which to check NTP
@@ -145,10 +145,11 @@ type (
}
)
-const (
- macSize = 256 / 8
- sigSize = 520 / 8
- headSize = macSize + sigSize // space of packet frame data
+var (
+ versionPrefix = []byte("temporary discovery v5")
+ versionPrefixSize = len(versionPrefix)
+ sigSize = 520 / 8
+ headSize = versionPrefixSize + sigSize // space of packet frame data
)
// Neighbors replies are sent across multiple packets to
@@ -237,30 +238,23 @@ type udp struct {
}
// ListenUDP returns a new table that listens for UDP packets on laddr.
-func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface, nodeDBPath string, netrestrict *netutil.Netlist) (*Network, error) {
- transport, err := listenUDP(priv, laddr)
+func ListenUDP(priv *ecdsa.PrivateKey, conn conn, realaddr *net.UDPAddr, nodeDBPath string, netrestrict *netutil.Netlist) (*Network, error) {
+ transport, err := listenUDP(priv, conn, realaddr)
if err != nil {
return nil, err
}
- net, err := newNetwork(transport, priv.PublicKey, natm, nodeDBPath, netrestrict)
+ net, err := newNetwork(transport, priv.PublicKey, nodeDBPath, netrestrict)
if err != nil {
return nil, err
}
+ log.Info("UDP listener up", "net", net.tab.self)
transport.net = net
go transport.readLoop()
return net, nil
}
-func listenUDP(priv *ecdsa.PrivateKey, laddr string) (*udp, error) {
- addr, err := net.ResolveUDPAddr("udp", laddr)
- if err != nil {
- return nil, err
- }
- conn, err := net.ListenUDP("udp", addr)
- if err != nil {
- return nil, err
- }
- return &udp{conn: conn, priv: priv, ourEndpoint: makeEndpoint(addr, uint16(addr.Port))}, nil
+func listenUDP(priv *ecdsa.PrivateKey, conn conn, realaddr *net.UDPAddr) (*udp, error) {
+ return &udp{conn: conn, priv: priv, ourEndpoint: makeEndpoint(realaddr, uint16(realaddr.Port))}, nil
}
func (t *udp) localAddr() *net.UDPAddr {
@@ -324,20 +318,20 @@ func (t *udp) sendTopicRegister(remote *Node, topics []Topic, idx int, pong []by
func (t *udp) sendTopicNodes(remote *Node, queryHash common.Hash, nodes []*Node) {
p := topicNodes{Echo: queryHash}
- if len(nodes) == 0 {
- t.sendPacket(remote.ID, remote.addr(), byte(topicNodesPacket), p)
- return
- }
- for i, result := range nodes {
- if netutil.CheckRelayIP(remote.IP, result.IP) != nil {
- continue
+ var sent bool
+ for _, result := range nodes {
+ if result.IP.Equal(t.net.tab.self.IP) || netutil.CheckRelayIP(remote.IP, result.IP) == nil {
+ p.Nodes = append(p.Nodes, nodeToRPC(result))
}
- p.Nodes = append(p.Nodes, nodeToRPC(result))
- if len(p.Nodes) == maxTopicNodes || i == len(nodes)-1 {
+ if len(p.Nodes) == maxTopicNodes {
t.sendPacket(remote.ID, remote.addr(), byte(topicNodesPacket), p)
p.Nodes = p.Nodes[:0]
+ sent = true
}
}
+ if !sent || len(p.Nodes) > 0 {
+ t.sendPacket(remote.ID, remote.addr(), byte(topicNodesPacket), p)
+ }
}
func (t *udp) sendPacket(toid NodeID, toaddr *net.UDPAddr, ptype byte, req interface{}) (hash []byte, err error) {
@@ -372,11 +366,9 @@ func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) (p, hash
log.Error(fmt.Sprint("could not sign packet:", err))
return nil, nil, err
}
- copy(packet[macSize:], sig)
- // add the hash to the front. Note: this doesn't protect the
- // packet in any way.
- hash = crypto.Keccak256(packet[macSize:])
- copy(packet, hash)
+ copy(packet, versionPrefix)
+ copy(packet[versionPrefixSize:], sig)
+ hash = crypto.Keccak256(packet[versionPrefixSize:])
return packet, hash, nil
}
@@ -420,17 +412,16 @@ func decodePacket(buffer []byte, pkt *ingressPacket) error {
}
buf := make([]byte, len(buffer))
copy(buf, buffer)
- hash, sig, sigdata := buf[:macSize], buf[macSize:headSize], buf[headSize:]
- shouldhash := crypto.Keccak256(buf[macSize:])
- if !bytes.Equal(hash, shouldhash) {
- return errBadHash
+ prefix, sig, sigdata := buf[:versionPrefixSize], buf[versionPrefixSize:headSize], buf[headSize:]
+ if !bytes.Equal(prefix, versionPrefix) {
+ return errBadPrefix
}
fromID, err := recoverNodeID(crypto.Keccak256(buf[headSize:]), sig)
if err != nil {
return err
}
pkt.rawData = buf
- pkt.hash = hash
+ pkt.hash = crypto.Keccak256(buf[versionPrefixSize:])
pkt.remoteID = fromID
switch pkt.ev = nodeEvent(sigdata[0]); pkt.ev {
case pingPacket:
diff --git a/p2p/enr/enr.go b/p2p/enr/enr.go
new file mode 100644
index 000000000..2c3afb43e
--- /dev/null
+++ b/p2p/enr/enr.go
@@ -0,0 +1,290 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+// Package enr implements Ethereum Node Records as defined in EIP-778. A node record holds
+// arbitrary information about a node on the peer-to-peer network.
+//
+// Records contain named keys. To store and retrieve key/values in a record, use the Entry
+// interface.
+//
+// Records must be signed before transmitting them to another node. Decoding a record verifies
+// its signature. When creating a record, set the entries you want, then call Sign to add the
+// signature. Modifying a record invalidates the signature.
+//
+// Package enr supports the "secp256k1-keccak" identity scheme.
+package enr
+
+import (
+ "bytes"
+ "crypto/ecdsa"
+ "errors"
+ "fmt"
+ "io"
+ "sort"
+
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/crypto/sha3"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+const SizeLimit = 300 // maximum encoded size of a node record in bytes
+
+const ID_SECP256k1_KECCAK = ID("secp256k1-keccak") // the default identity scheme
+
+var (
+ errNoID = errors.New("unknown or unspecified identity scheme")
+ errInvalidSigsize = errors.New("invalid signature size")
+ errInvalidSig = errors.New("invalid signature")
+ errNotSorted = errors.New("record key/value pairs are not sorted by key")
+ errDuplicateKey = errors.New("record contains duplicate key")
+ errIncompletePair = errors.New("record contains incomplete k/v pair")
+ errTooBig = fmt.Errorf("record bigger than %d bytes", SizeLimit)
+ errEncodeUnsigned = errors.New("can't encode unsigned record")
+ errNotFound = errors.New("no such key in record")
+)
+
+// Record represents a node record. The zero value is an empty record.
+type Record struct {
+ seq uint64 // sequence number
+ signature []byte // the signature
+ raw []byte // RLP encoded record
+ pairs []pair // sorted list of all key/value pairs
+}
+
+// pair is a key/value pair in a record.
+type pair struct {
+ k string
+ v rlp.RawValue
+}
+
+// Signed reports whether the record has a valid signature.
+func (r *Record) Signed() bool {
+ return r.signature != nil
+}
+
+// Seq returns the sequence number.
+func (r *Record) Seq() uint64 {
+ return r.seq
+}
+
+// SetSeq updates the record sequence number. This invalidates any signature on the record.
+// Calling SetSeq is usually not required because signing the redord increments the
+// sequence number.
+func (r *Record) SetSeq(s uint64) {
+ r.signature = nil
+ r.raw = nil
+ r.seq = s
+}
+
+// Load retrieves the value of a key/value pair. The given Entry must be a pointer and will
+// be set to the value of the entry in the record.
+//
+// Errors returned by Load are wrapped in KeyError. You can distinguish decoding errors
+// from missing keys using the IsNotFound function.
+func (r *Record) Load(e Entry) error {
+ i := sort.Search(len(r.pairs), func(i int) bool { return r.pairs[i].k >= e.ENRKey() })
+ if i < len(r.pairs) && r.pairs[i].k == e.ENRKey() {
+ if err := rlp.DecodeBytes(r.pairs[i].v, e); err != nil {
+ return &KeyError{Key: e.ENRKey(), Err: err}
+ }
+ return nil
+ }
+ return &KeyError{Key: e.ENRKey(), Err: errNotFound}
+}
+
+// Set adds or updates the given entry in the record.
+// It panics if the value can't be encoded.
+func (r *Record) Set(e Entry) {
+ r.signature = nil
+ r.raw = nil
+ blob, err := rlp.EncodeToBytes(e)
+ if err != nil {
+ panic(fmt.Errorf("enr: can't encode %s: %v", e.ENRKey(), err))
+ }
+
+ i := sort.Search(len(r.pairs), func(i int) bool { return r.pairs[i].k >= e.ENRKey() })
+
+ if i < len(r.pairs) && r.pairs[i].k == e.ENRKey() {
+ // element is present at r.pairs[i]
+ r.pairs[i].v = blob
+ return
+ } else if i < len(r.pairs) {
+ // insert pair before i-th elem
+ el := pair{e.ENRKey(), blob}
+ r.pairs = append(r.pairs, pair{})
+ copy(r.pairs[i+1:], r.pairs[i:])
+ r.pairs[i] = el
+ return
+ }
+
+ // element should be placed at the end of r.pairs
+ r.pairs = append(r.pairs, pair{e.ENRKey(), blob})
+}
+
+// EncodeRLP implements rlp.Encoder. Encoding fails if
+// the record is unsigned.
+func (r Record) EncodeRLP(w io.Writer) error {
+ if !r.Signed() {
+ return errEncodeUnsigned
+ }
+ _, err := w.Write(r.raw)
+ return err
+}
+
+// DecodeRLP implements rlp.Decoder. Decoding verifies the signature.
+func (r *Record) DecodeRLP(s *rlp.Stream) error {
+ raw, err := s.Raw()
+ if err != nil {
+ return err
+ }
+ if len(raw) > SizeLimit {
+ return errTooBig
+ }
+
+ // Decode the RLP container.
+ dec := Record{raw: raw}
+ s = rlp.NewStream(bytes.NewReader(raw), 0)
+ if _, err := s.List(); err != nil {
+ return err
+ }
+ if err = s.Decode(&dec.signature); err != nil {
+ return err
+ }
+ if err = s.Decode(&dec.seq); err != nil {
+ return err
+ }
+ // The rest of the record contains sorted k/v pairs.
+ var prevkey string
+ for i := 0; ; i++ {
+ var kv pair
+ if err := s.Decode(&kv.k); err != nil {
+ if err == rlp.EOL {
+ break
+ }
+ return err
+ }
+ if err := s.Decode(&kv.v); err != nil {
+ if err == rlp.EOL {
+ return errIncompletePair
+ }
+ return err
+ }
+ if i > 0 {
+ if kv.k == prevkey {
+ return errDuplicateKey
+ }
+ if kv.k < prevkey {
+ return errNotSorted
+ }
+ }
+ dec.pairs = append(dec.pairs, kv)
+ prevkey = kv.k
+ }
+ if err := s.ListEnd(); err != nil {
+ return err
+ }
+
+ // Verify signature.
+ if err = dec.verifySignature(); err != nil {
+ return err
+ }
+ *r = dec
+ return nil
+}
+
+type s256raw []byte
+
+func (s256raw) ENRKey() string { return "secp256k1" }
+
+// NodeAddr returns the node address. The return value will be nil if the record is
+// unsigned.
+func (r *Record) NodeAddr() []byte {
+ var entry s256raw
+ if r.Load(&entry) != nil {
+ return nil
+ }
+ return crypto.Keccak256(entry)
+}
+
+// Sign signs the record with the given private key. It updates the record's identity
+// scheme, public key and increments the sequence number. Sign returns an error if the
+// encoded record is larger than the size limit.
+func (r *Record) Sign(privkey *ecdsa.PrivateKey) error {
+ r.seq = r.seq + 1
+ r.Set(ID_SECP256k1_KECCAK)
+ r.Set(Secp256k1(privkey.PublicKey))
+ return r.signAndEncode(privkey)
+}
+
+func (r *Record) appendPairs(list []interface{}) []interface{} {
+ list = append(list, r.seq)
+ for _, p := range r.pairs {
+ list = append(list, p.k, p.v)
+ }
+ return list
+}
+
+func (r *Record) signAndEncode(privkey *ecdsa.PrivateKey) error {
+ // Put record elements into a flat list. Leave room for the signature.
+ list := make([]interface{}, 1, len(r.pairs)*2+2)
+ list = r.appendPairs(list)
+
+ // Sign the tail of the list.
+ h := sha3.NewKeccak256()
+ rlp.Encode(h, list[1:])
+ sig, err := crypto.Sign(h.Sum(nil), privkey)
+ if err != nil {
+ return err
+ }
+ sig = sig[:len(sig)-1] // remove v
+
+ // Put signature in front.
+ r.signature, list[0] = sig, sig
+ r.raw, err = rlp.EncodeToBytes(list)
+ if err != nil {
+ return err
+ }
+ if len(r.raw) > SizeLimit {
+ return errTooBig
+ }
+ return nil
+}
+
+func (r *Record) verifySignature() error {
+ // Get identity scheme, public key, signature.
+ var id ID
+ var entry s256raw
+ if err := r.Load(&id); err != nil {
+ return err
+ } else if id != ID_SECP256k1_KECCAK {
+ return errNoID
+ }
+ if err := r.Load(&entry); err != nil {
+ return err
+ } else if len(entry) != 33 {
+ return fmt.Errorf("invalid public key")
+ }
+
+ // Verify the signature.
+ list := make([]interface{}, 0, len(r.pairs)*2+1)
+ list = r.appendPairs(list)
+ h := sha3.NewKeccak256()
+ rlp.Encode(h, list)
+ if !crypto.VerifySignature(entry, h.Sum(nil), r.signature) {
+ return errInvalidSig
+ }
+ return nil
+}
diff --git a/p2p/enr/enr_test.go b/p2p/enr/enr_test.go
new file mode 100644
index 000000000..ce7767d10
--- /dev/null
+++ b/p2p/enr/enr_test.go
@@ -0,0 +1,318 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package enr
+
+import (
+ "bytes"
+ "encoding/hex"
+ "fmt"
+ "math/rand"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+var (
+ privkey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ pubkey = &privkey.PublicKey
+)
+
+var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
+
+func randomString(strlen int) string {
+ b := make([]byte, strlen)
+ rnd.Read(b)
+ return string(b)
+}
+
+// TestGetSetID tests encoding/decoding and setting/getting of the ID key.
+func TestGetSetID(t *testing.T) {
+ id := ID("someid")
+ var r Record
+ r.Set(id)
+
+ var id2 ID
+ require.NoError(t, r.Load(&id2))
+ assert.Equal(t, id, id2)
+}
+
+// TestGetSetIP4 tests encoding/decoding and setting/getting of the IP4 key.
+func TestGetSetIP4(t *testing.T) {
+ ip := IP4{192, 168, 0, 3}
+ var r Record
+ r.Set(ip)
+
+ var ip2 IP4
+ require.NoError(t, r.Load(&ip2))
+ assert.Equal(t, ip, ip2)
+}
+
+// TestGetSetIP6 tests encoding/decoding and setting/getting of the IP6 key.
+func TestGetSetIP6(t *testing.T) {
+ ip := IP6{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68}
+ var r Record
+ r.Set(ip)
+
+ var ip2 IP6
+ require.NoError(t, r.Load(&ip2))
+ assert.Equal(t, ip, ip2)
+}
+
+// TestGetSetDiscPort tests encoding/decoding and setting/getting of the DiscPort key.
+func TestGetSetDiscPort(t *testing.T) {
+ port := DiscPort(30309)
+ var r Record
+ r.Set(port)
+
+ var port2 DiscPort
+ require.NoError(t, r.Load(&port2))
+ assert.Equal(t, port, port2)
+}
+
+// TestGetSetSecp256k1 tests encoding/decoding and setting/getting of the Secp256k1 key.
+func TestGetSetSecp256k1(t *testing.T) {
+ var r Record
+ if err := r.Sign(privkey); err != nil {
+ t.Fatal(err)
+ }
+
+ var pk Secp256k1
+ require.NoError(t, r.Load(&pk))
+ assert.EqualValues(t, pubkey, &pk)
+}
+
+func TestLoadErrors(t *testing.T) {
+ var r Record
+ ip4 := IP4{127, 0, 0, 1}
+ r.Set(ip4)
+
+ // Check error for missing keys.
+ var ip6 IP6
+ err := r.Load(&ip6)
+ if !IsNotFound(err) {
+ t.Error("IsNotFound should return true for missing key")
+ }
+ assert.Equal(t, &KeyError{Key: ip6.ENRKey(), Err: errNotFound}, err)
+
+ // Check error for invalid keys.
+ var list []uint
+ err = r.Load(WithEntry(ip4.ENRKey(), &list))
+ kerr, ok := err.(*KeyError)
+ if !ok {
+ t.Fatalf("expected KeyError, got %T", err)
+ }
+ assert.Equal(t, kerr.Key, ip4.ENRKey())
+ assert.Error(t, kerr.Err)
+ if IsNotFound(err) {
+ t.Error("IsNotFound should return false for decoding errors")
+ }
+}
+
+// TestSortedGetAndSet tests that Set produced a sorted pairs slice.
+func TestSortedGetAndSet(t *testing.T) {
+ type pair struct {
+ k string
+ v uint32
+ }
+
+ for _, tt := range []struct {
+ input []pair
+ want []pair
+ }{
+ {
+ input: []pair{{"a", 1}, {"c", 2}, {"b", 3}},
+ want: []pair{{"a", 1}, {"b", 3}, {"c", 2}},
+ },
+ {
+ input: []pair{{"a", 1}, {"c", 2}, {"b", 3}, {"d", 4}, {"a", 5}, {"bb", 6}},
+ want: []pair{{"a", 5}, {"b", 3}, {"bb", 6}, {"c", 2}, {"d", 4}},
+ },
+ {
+ input: []pair{{"c", 2}, {"b", 3}, {"d", 4}, {"a", 5}, {"bb", 6}},
+ want: []pair{{"a", 5}, {"b", 3}, {"bb", 6}, {"c", 2}, {"d", 4}},
+ },
+ } {
+ var r Record
+ for _, i := range tt.input {
+ r.Set(WithEntry(i.k, &i.v))
+ }
+ for i, w := range tt.want {
+ // set got's key from r.pair[i], so that we preserve order of pairs
+ got := pair{k: r.pairs[i].k}
+ assert.NoError(t, r.Load(WithEntry(w.k, &got.v)))
+ assert.Equal(t, w, got)
+ }
+ }
+}
+
+// TestDirty tests record signature removal on setting of new key/value pair in record.
+func TestDirty(t *testing.T) {
+ var r Record
+
+ if r.Signed() {
+ t.Error("Signed returned true for zero record")
+ }
+ if _, err := rlp.EncodeToBytes(r); err != errEncodeUnsigned {
+ t.Errorf("expected errEncodeUnsigned, got %#v", err)
+ }
+
+ require.NoError(t, r.Sign(privkey))
+ if !r.Signed() {
+ t.Error("Signed return false for signed record")
+ }
+ _, err := rlp.EncodeToBytes(r)
+ assert.NoError(t, err)
+
+ r.SetSeq(3)
+ if r.Signed() {
+ t.Error("Signed returned true for modified record")
+ }
+ if _, err := rlp.EncodeToBytes(r); err != errEncodeUnsigned {
+ t.Errorf("expected errEncodeUnsigned, got %#v", err)
+ }
+}
+
+// TestGetSetOverwrite tests value overwrite when setting a new value with an existing key in record.
+func TestGetSetOverwrite(t *testing.T) {
+ var r Record
+
+ ip := IP4{192, 168, 0, 3}
+ r.Set(ip)
+
+ ip2 := IP4{192, 168, 0, 4}
+ r.Set(ip2)
+
+ var ip3 IP4
+ require.NoError(t, r.Load(&ip3))
+ assert.Equal(t, ip2, ip3)
+}
+
+// TestSignEncodeAndDecode tests signing, RLP encoding and RLP decoding of a record.
+func TestSignEncodeAndDecode(t *testing.T) {
+ var r Record
+ r.Set(DiscPort(30303))
+ r.Set(IP4{127, 0, 0, 1})
+ require.NoError(t, r.Sign(privkey))
+
+ blob, err := rlp.EncodeToBytes(r)
+ require.NoError(t, err)
+
+ var r2 Record
+ require.NoError(t, rlp.DecodeBytes(blob, &r2))
+ assert.Equal(t, r, r2)
+
+ blob2, err := rlp.EncodeToBytes(r2)
+ require.NoError(t, err)
+ assert.Equal(t, blob, blob2)
+}
+
+func TestNodeAddr(t *testing.T) {
+ var r Record
+ if addr := r.NodeAddr(); addr != nil {
+ t.Errorf("wrong address on empty record: got %v, want %v", addr, nil)
+ }
+
+ require.NoError(t, r.Sign(privkey))
+ expected := "caaa1485d83b18b32ed9ad666026151bf0cae8a0a88c857ae2d4c5be2daa6726"
+ assert.Equal(t, expected, hex.EncodeToString(r.NodeAddr()))
+}
+
+var pyRecord, _ = hex.DecodeString("f896b840954dc36583c1f4b69ab59b1375f362f06ee99f3723cd77e64b6de6d211c27d7870642a79d4516997f94091325d2a7ca6215376971455fb221d34f35b277149a1018664697363763582765f82696490736563703235366b312d6b656363616b83697034847f00000189736563703235366b31a103ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138")
+
+// TestPythonInterop checks that we can decode and verify a record produced by the Python
+// implementation.
+func TestPythonInterop(t *testing.T) {
+ var r Record
+ if err := rlp.DecodeBytes(pyRecord, &r); err != nil {
+ t.Fatalf("can't decode: %v", err)
+ }
+
+ var (
+ wantAddr, _ = hex.DecodeString("caaa1485d83b18b32ed9ad666026151bf0cae8a0a88c857ae2d4c5be2daa6726")
+ wantSeq = uint64(1)
+ wantIP = IP4{127, 0, 0, 1}
+ wantDiscport = DiscPort(30303)
+ )
+ if r.Seq() != wantSeq {
+ t.Errorf("wrong seq: got %d, want %d", r.Seq(), wantSeq)
+ }
+ if addr := r.NodeAddr(); !bytes.Equal(addr, wantAddr) {
+ t.Errorf("wrong addr: got %x, want %x", addr, wantAddr)
+ }
+ want := map[Entry]interface{}{new(IP4): &wantIP, new(DiscPort): &wantDiscport}
+ for k, v := range want {
+ desc := fmt.Sprintf("loading key %q", k.ENRKey())
+ if assert.NoError(t, r.Load(k), desc) {
+ assert.Equal(t, k, v, desc)
+ }
+ }
+}
+
+// TestRecordTooBig tests that records bigger than SizeLimit bytes cannot be signed.
+func TestRecordTooBig(t *testing.T) {
+ var r Record
+ key := randomString(10)
+
+ // set a big value for random key, expect error
+ r.Set(WithEntry(key, randomString(300)))
+ if err := r.Sign(privkey); err != errTooBig {
+ t.Fatalf("expected to get errTooBig, got %#v", err)
+ }
+
+ // set an acceptable value for random key, expect no error
+ r.Set(WithEntry(key, randomString(100)))
+ require.NoError(t, r.Sign(privkey))
+}
+
+// TestSignEncodeAndDecodeRandom tests encoding/decoding of records containing random key/value pairs.
+func TestSignEncodeAndDecodeRandom(t *testing.T) {
+ var r Record
+
+ // random key/value pairs for testing
+ pairs := map[string]uint32{}
+ for i := 0; i < 10; i++ {
+ key := randomString(7)
+ value := rnd.Uint32()
+ pairs[key] = value
+ r.Set(WithEntry(key, &value))
+ }
+
+ require.NoError(t, r.Sign(privkey))
+ _, err := rlp.EncodeToBytes(r)
+ require.NoError(t, err)
+
+ for k, v := range pairs {
+ desc := fmt.Sprintf("key %q", k)
+ var got uint32
+ buf := WithEntry(k, &got)
+ require.NoError(t, r.Load(buf), desc)
+ require.Equal(t, v, got, desc)
+ }
+}
+
+func BenchmarkDecode(b *testing.B) {
+ var r Record
+ for i := 0; i < b.N; i++ {
+ rlp.DecodeBytes(pyRecord, &r)
+ }
+ b.StopTimer()
+ r.NodeAddr()
+}
diff --git a/p2p/enr/entries.go b/p2p/enr/entries.go
new file mode 100644
index 000000000..7591e6eff
--- /dev/null
+++ b/p2p/enr/entries.go
@@ -0,0 +1,160 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package enr
+
+import (
+ "crypto/ecdsa"
+ "fmt"
+ "io"
+ "net"
+
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// Entry is implemented by known node record entry types.
+//
+// To define a new entry that is to be included in a node record,
+// create a Go type that satisfies this interface. The type should
+// also implement rlp.Decoder if additional checks are needed on the value.
+type Entry interface {
+ ENRKey() string
+}
+
+type generic struct {
+ key string
+ value interface{}
+}
+
+func (g generic) ENRKey() string { return g.key }
+
+func (g generic) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, g.value)
+}
+
+func (g *generic) DecodeRLP(s *rlp.Stream) error {
+ return s.Decode(g.value)
+}
+
+// WithEntry wraps any value with a key name. It can be used to set and load arbitrary values
+// in a record. The value v must be supported by rlp. To use WithEntry with Load, the value
+// must be a pointer.
+func WithEntry(k string, v interface{}) Entry {
+ return &generic{key: k, value: v}
+}
+
+// DiscPort is the "discv5" key, which holds the UDP port for discovery v5.
+type DiscPort uint16
+
+func (v DiscPort) ENRKey() string { return "discv5" }
+
+// ID is the "id" key, which holds the name of the identity scheme.
+type ID string
+
+func (v ID) ENRKey() string { return "id" }
+
+// IP4 is the "ip4" key, which holds a 4-byte IPv4 address.
+type IP4 net.IP
+
+func (v IP4) ENRKey() string { return "ip4" }
+
+// EncodeRLP implements rlp.Encoder.
+func (v IP4) EncodeRLP(w io.Writer) error {
+ ip4 := net.IP(v).To4()
+ if ip4 == nil {
+ return fmt.Errorf("invalid IPv4 address: %v", v)
+ }
+ return rlp.Encode(w, ip4)
+}
+
+// DecodeRLP implements rlp.Decoder.
+func (v *IP4) DecodeRLP(s *rlp.Stream) error {
+ if err := s.Decode((*net.IP)(v)); err != nil {
+ return err
+ }
+ if len(*v) != 4 {
+ return fmt.Errorf("invalid IPv4 address, want 4 bytes: %v", *v)
+ }
+ return nil
+}
+
+// IP6 is the "ip6" key, which holds a 16-byte IPv6 address.
+type IP6 net.IP
+
+func (v IP6) ENRKey() string { return "ip6" }
+
+// EncodeRLP implements rlp.Encoder.
+func (v IP6) EncodeRLP(w io.Writer) error {
+ ip6 := net.IP(v)
+ return rlp.Encode(w, ip6)
+}
+
+// DecodeRLP implements rlp.Decoder.
+func (v *IP6) DecodeRLP(s *rlp.Stream) error {
+ if err := s.Decode((*net.IP)(v)); err != nil {
+ return err
+ }
+ if len(*v) != 16 {
+ return fmt.Errorf("invalid IPv6 address, want 16 bytes: %v", *v)
+ }
+ return nil
+}
+
+// Secp256k1 is the "secp256k1" key, which holds a public key.
+type Secp256k1 ecdsa.PublicKey
+
+func (v Secp256k1) ENRKey() string { return "secp256k1" }
+
+// EncodeRLP implements rlp.Encoder.
+func (v Secp256k1) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, crypto.CompressPubkey((*ecdsa.PublicKey)(&v)))
+}
+
+// DecodeRLP implements rlp.Decoder.
+func (v *Secp256k1) DecodeRLP(s *rlp.Stream) error {
+ buf, err := s.Bytes()
+ if err != nil {
+ return err
+ }
+ pk, err := crypto.DecompressPubkey(buf)
+ if err != nil {
+ return err
+ }
+ *v = (Secp256k1)(*pk)
+ return nil
+}
+
+// KeyError is an error related to a key.
+type KeyError struct {
+ Key string
+ Err error
+}
+
+// Error implements error.
+func (err *KeyError) Error() string {
+ if err.Err == errNotFound {
+ return fmt.Sprintf("missing ENR key %q", err.Key)
+ }
+ return fmt.Sprintf("ENR key %q: %v", err.Key, err.Err)
+}
+
+// IsNotFound reports whether the given error means that a key/value pair is
+// missing from a record.
+func IsNotFound(err error) bool {
+ kerr, ok := err.(*KeyError)
+ return ok && kerr.Err == errNotFound
+}
diff --git a/p2p/netutil/net.go b/p2p/netutil/net.go
index f6005afd2..656abb682 100644
--- a/p2p/netutil/net.go
+++ b/p2p/netutil/net.go
@@ -18,8 +18,11 @@
package netutil
import (
+ "bytes"
"errors"
+ "fmt"
"net"
+ "sort"
"strings"
)
@@ -189,3 +192,131 @@ func CheckRelayIP(sender, addr net.IP) error {
}
return nil
}
+
+// SameNet reports whether two IP addresses have an equal prefix of the given bit length.
+func SameNet(bits uint, ip, other net.IP) bool {
+ ip4, other4 := ip.To4(), other.To4()
+ switch {
+ case (ip4 == nil) != (other4 == nil):
+ return false
+ case ip4 != nil:
+ return sameNet(bits, ip4, other4)
+ default:
+ return sameNet(bits, ip.To16(), other.To16())
+ }
+}
+
+func sameNet(bits uint, ip, other net.IP) bool {
+ nb := int(bits / 8)
+ mask := ^byte(0xFF >> (bits % 8))
+ if mask != 0 && nb < len(ip) && ip[nb]&mask != other[nb]&mask {
+ return false
+ }
+ return nb <= len(ip) && bytes.Equal(ip[:nb], other[:nb])
+}
+
+// DistinctNetSet tracks IPs, ensuring that at most N of them
+// fall into the same network range.
+type DistinctNetSet struct {
+ Subnet uint // number of common prefix bits
+ Limit uint // maximum number of IPs in each subnet
+
+ members map[string]uint
+ buf net.IP
+}
+
+// Add adds an IP address to the set. It returns false (and doesn't add the IP) if the
+// number of existing IPs in the defined range exceeds the limit.
+func (s *DistinctNetSet) Add(ip net.IP) bool {
+ key := s.key(ip)
+ n := s.members[string(key)]
+ if n < s.Limit {
+ s.members[string(key)] = n + 1
+ return true
+ }
+ return false
+}
+
+// Remove removes an IP from the set.
+func (s *DistinctNetSet) Remove(ip net.IP) {
+ key := s.key(ip)
+ if n, ok := s.members[string(key)]; ok {
+ if n == 1 {
+ delete(s.members, string(key))
+ } else {
+ s.members[string(key)] = n - 1
+ }
+ }
+}
+
+// Contains whether the given IP is contained in the set.
+func (s DistinctNetSet) Contains(ip net.IP) bool {
+ key := s.key(ip)
+ _, ok := s.members[string(key)]
+ return ok
+}
+
+// Len returns the number of tracked IPs.
+func (s DistinctNetSet) Len() int {
+ n := uint(0)
+ for _, i := range s.members {
+ n += i
+ }
+ return int(n)
+}
+
+// key encodes the map key for an address into a temporary buffer.
+//
+// The first byte of key is '4' or '6' to distinguish IPv4/IPv6 address types.
+// The remainder of the key is the IP, truncated to the number of bits.
+func (s *DistinctNetSet) key(ip net.IP) net.IP {
+ // Lazily initialize storage.
+ if s.members == nil {
+ s.members = make(map[string]uint)
+ s.buf = make(net.IP, 17)
+ }
+ // Canonicalize ip and bits.
+ typ := byte('6')
+ if ip4 := ip.To4(); ip4 != nil {
+ typ, ip = '4', ip4
+ }
+ bits := s.Subnet
+ if bits > uint(len(ip)*8) {
+ bits = uint(len(ip) * 8)
+ }
+ // Encode the prefix into s.buf.
+ nb := int(bits / 8)
+ mask := ^byte(0xFF >> (bits % 8))
+ s.buf[0] = typ
+ buf := append(s.buf[:1], ip[:nb]...)
+ if nb < len(ip) && mask != 0 {
+ buf = append(buf, ip[nb]&mask)
+ }
+ return buf
+}
+
+// String implements fmt.Stringer
+func (s DistinctNetSet) String() string {
+ var buf bytes.Buffer
+ buf.WriteString("{")
+ keys := make([]string, 0, len(s.members))
+ for k := range s.members {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ for i, k := range keys {
+ var ip net.IP
+ if k[0] == '4' {
+ ip = make(net.IP, 4)
+ } else {
+ ip = make(net.IP, 16)
+ }
+ copy(ip, k[1:])
+ fmt.Fprintf(&buf, "%v×%d", ip, s.members[k])
+ if i != len(keys)-1 {
+ buf.WriteString(" ")
+ }
+ }
+ buf.WriteString("}")
+ return buf.String()
+}
diff --git a/p2p/netutil/net_test.go b/p2p/netutil/net_test.go
index 1ee1fcb4d..3a6aa081f 100644
--- a/p2p/netutil/net_test.go
+++ b/p2p/netutil/net_test.go
@@ -17,9 +17,11 @@
package netutil
import (
+ "fmt"
"net"
"reflect"
"testing"
+ "testing/quick"
"github.com/davecgh/go-spew/spew"
)
@@ -171,3 +173,90 @@ func BenchmarkCheckRelayIP(b *testing.B) {
CheckRelayIP(sender, addr)
}
}
+
+func TestSameNet(t *testing.T) {
+ tests := []struct {
+ ip, other string
+ bits uint
+ want bool
+ }{
+ {"0.0.0.0", "0.0.0.0", 32, true},
+ {"0.0.0.0", "0.0.0.1", 0, true},
+ {"0.0.0.0", "0.0.0.1", 31, true},
+ {"0.0.0.0", "0.0.0.1", 32, false},
+ {"0.33.0.1", "0.34.0.2", 8, true},
+ {"0.33.0.1", "0.34.0.2", 13, true},
+ {"0.33.0.1", "0.34.0.2", 15, false},
+ }
+
+ for _, test := range tests {
+ if ok := SameNet(test.bits, parseIP(test.ip), parseIP(test.other)); ok != test.want {
+ t.Errorf("SameNet(%d, %s, %s) == %t, want %t", test.bits, test.ip, test.other, ok, test.want)
+ }
+ }
+}
+
+func ExampleSameNet() {
+ // This returns true because the IPs are in the same /24 network:
+ fmt.Println(SameNet(24, net.IP{127, 0, 0, 1}, net.IP{127, 0, 0, 3}))
+ // This call returns false:
+ fmt.Println(SameNet(24, net.IP{127, 3, 0, 1}, net.IP{127, 5, 0, 3}))
+ // Output:
+ // true
+ // false
+}
+
+func TestDistinctNetSet(t *testing.T) {
+ ops := []struct {
+ add, remove string
+ fails bool
+ }{
+ {add: "127.0.0.1"},
+ {add: "127.0.0.2"},
+ {add: "127.0.0.3", fails: true},
+ {add: "127.32.0.1"},
+ {add: "127.32.0.2"},
+ {add: "127.32.0.3", fails: true},
+ {add: "127.33.0.1", fails: true},
+ {add: "127.34.0.1"},
+ {add: "127.34.0.2"},
+ {add: "127.34.0.3", fails: true},
+ // Make room for an address, then add again.
+ {remove: "127.0.0.1"},
+ {add: "127.0.0.3"},
+ {add: "127.0.0.3", fails: true},
+ }
+
+ set := DistinctNetSet{Subnet: 15, Limit: 2}
+ for _, op := range ops {
+ var desc string
+ if op.add != "" {
+ desc = fmt.Sprintf("Add(%s)", op.add)
+ if ok := set.Add(parseIP(op.add)); ok != !op.fails {
+ t.Errorf("%s == %t, want %t", desc, ok, !op.fails)
+ }
+ } else {
+ desc = fmt.Sprintf("Remove(%s)", op.remove)
+ set.Remove(parseIP(op.remove))
+ }
+ t.Logf("%s: %v", desc, set)
+ }
+}
+
+func TestDistinctNetSetAddRemove(t *testing.T) {
+ cfg := &quick.Config{}
+ fn := func(ips []net.IP) bool {
+ s := DistinctNetSet{Limit: 3, Subnet: 2}
+ for _, ip := range ips {
+ s.Add(ip)
+ }
+ for _, ip := range ips {
+ s.Remove(ip)
+ }
+ return s.Len() == 0
+ }
+
+ if err := quick.Check(fn, cfg); err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/p2p/peer.go b/p2p/peer.go
index bad1c8c8b..477d8c219 100644
--- a/p2p/peer.go
+++ b/p2p/peer.go
@@ -419,6 +419,9 @@ type PeerInfo struct {
Network struct {
LocalAddress string `json:"localAddress"` // Local endpoint of the TCP data connection
RemoteAddress string `json:"remoteAddress"` // Remote endpoint of the TCP data connection
+ Inbound bool `json:"inbound"`
+ Trusted bool `json:"trusted"`
+ Static bool `json:"static"`
} `json:"network"`
Protocols map[string]interface{} `json:"protocols"` // Sub-protocol specific metadata fields
}
@@ -439,6 +442,9 @@ func (p *Peer) Info() *PeerInfo {
}
info.Network.LocalAddress = p.LocalAddr().String()
info.Network.RemoteAddress = p.RemoteAddr().String()
+ info.Network.Inbound = p.rw.is(inboundConn)
+ info.Network.Trusted = p.rw.is(trustedConn)
+ info.Network.Static = p.rw.is(staticDialedConn)
// Gather all the running protocol infos
for _, proto := range p.running {
diff --git a/p2p/server.go b/p2p/server.go
index 922df55ba..90e92dc05 100644
--- a/p2p/server.go
+++ b/p2p/server.go
@@ -40,11 +40,10 @@ const (
refreshPeersInterval = 30 * time.Second
staticPeerCheckInterval = 15 * time.Second
- // Maximum number of concurrently handshaking inbound connections.
- maxAcceptConns = 50
-
- // Maximum number of concurrently dialing outbound connections.
- maxActiveDialTasks = 16
+ // Connectivity defaults.
+ maxActiveDialTasks = 16
+ defaultMaxPendingPeers = 50
+ defaultDialRatio = 3
// Maximum time allowed for reading a complete message.
// This is effectively the amount of time a connection can be idle.
@@ -70,6 +69,11 @@ type Config struct {
// Zero defaults to preset values.
MaxPendingPeers int `toml:",omitempty"`
+ // DialRatio controls the ratio of inbound to dialed connections.
+ // Example: a DialRatio of 2 allows 1/2 of connections to be dialed.
+ // Setting DialRatio to zero defaults it to 3.
+ DialRatio int `toml:",omitempty"`
+
// NoDiscovery can be used to disable the peer discovery mechanism.
// Disabling is useful for protocol debugging (manual topology).
NoDiscovery bool
@@ -78,9 +82,6 @@ type Config struct {
// protocol should be started or not.
DiscoveryV5 bool `toml:",omitempty"`
- // Listener address for the V5 discovery protocol UDP traffic.
- DiscoveryV5Addr string `toml:",omitempty"`
-
// Name sets the node name of this server.
// Use common.MakeName to create a name that follows existing conventions.
Name string `toml:"-"`
@@ -141,7 +142,7 @@ type Config struct {
EnableMsgEvents bool
// Logger is a custom logger to use with the p2p.Server.
- Logger log.Logger
+ Logger log.Logger `toml:",omitempty"`
}
// Server manages all peer connections.
@@ -354,6 +355,32 @@ func (srv *Server) Stop() {
srv.loopWG.Wait()
}
+// sharedUDPConn implements a shared connection. Write sends messages to the underlying connection while read returns
+// messages that were found unprocessable and sent to the unhandled channel by the primary listener.
+type sharedUDPConn struct {
+ *net.UDPConn
+ unhandled chan discover.ReadPacket
+}
+
+// ReadFromUDP implements discv5.conn
+func (s *sharedUDPConn) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) {
+ packet, ok := <-s.unhandled
+ if !ok {
+ return 0, nil, fmt.Errorf("Connection was closed")
+ }
+ l := len(packet.Data)
+ if l > len(b) {
+ l = len(b)
+ }
+ copy(b[:l], packet.Data[:l])
+ return l, packet.Addr, nil
+}
+
+// Close implements discv5.conn
+func (s *sharedUDPConn) Close() error {
+ return nil
+}
+
// Start starts running the server.
// Servers can not be re-used after stopping.
func (srv *Server) Start() (err error) {
@@ -388,20 +415,66 @@ func (srv *Server) Start() (err error) {
srv.peerOp = make(chan peerOpFunc)
srv.peerOpDone = make(chan struct{})
- // node table
- if !srv.NoDiscovery {
- ntab, err := discover.ListenUDP(srv.PrivateKey, srv.ListenAddr, srv.NAT, srv.NodeDatabase, srv.NetRestrict)
+ var (
+ conn *net.UDPConn
+ sconn *sharedUDPConn
+ realaddr *net.UDPAddr
+ unhandled chan discover.ReadPacket
+ )
+
+ if !srv.NoDiscovery || srv.DiscoveryV5 {
+ addr, err := net.ResolveUDPAddr("udp", srv.ListenAddr)
if err != nil {
return err
}
- if err := ntab.SetFallbackNodes(srv.BootstrapNodes); err != nil {
+ conn, err = net.ListenUDP("udp", addr)
+ if err != nil {
+ return err
+ }
+ realaddr = conn.LocalAddr().(*net.UDPAddr)
+ if srv.NAT != nil {
+ if !realaddr.IP.IsLoopback() {
+ go nat.Map(srv.NAT, srv.quit, "udp", realaddr.Port, realaddr.Port, "ethereum discovery")
+ }
+ // TODO: react to external IP changes over time.
+ if ext, err := srv.NAT.ExternalIP(); err == nil {
+ realaddr = &net.UDPAddr{IP: ext, Port: realaddr.Port}
+ }
+ }
+ }
+
+ if !srv.NoDiscovery && srv.DiscoveryV5 {
+ unhandled = make(chan discover.ReadPacket, 100)
+ sconn = &sharedUDPConn{conn, unhandled}
+ }
+
+ // node table
+ if !srv.NoDiscovery {
+ cfg := discover.Config{
+ PrivateKey: srv.PrivateKey,
+ AnnounceAddr: realaddr,
+ NodeDBPath: srv.NodeDatabase,
+ NetRestrict: srv.NetRestrict,
+ Bootnodes: srv.BootstrapNodes,
+ Unhandled: unhandled,
+ }
+ ntab, err := discover.ListenUDP(conn, cfg)
+ if err != nil {
return err
}
srv.ntab = ntab
}
if srv.DiscoveryV5 {
- ntab, err := discv5.ListenUDP(srv.PrivateKey, srv.DiscoveryV5Addr, srv.NAT, "", srv.NetRestrict) //srv.NodeDatabase)
+ var (
+ ntab *discv5.Network
+ err error
+ )
+ if sconn != nil {
+ ntab, err = discv5.ListenUDP(srv.PrivateKey, sconn, realaddr, "", srv.NetRestrict) //srv.NodeDatabase)
+ } else {
+ ntab, err = discv5.ListenUDP(srv.PrivateKey, conn, realaddr, "", srv.NetRestrict) //srv.NodeDatabase)
+ }
if err != nil {
return err
}
@@ -411,10 +484,7 @@ func (srv *Server) Start() (err error) {
srv.DiscV5 = ntab
}
- dynPeers := (srv.MaxPeers + 1) / 2
- if srv.NoDiscovery {
- dynPeers = 0
- }
+ dynPeers := srv.maxDialedConns()
dialer := newDialState(srv.StaticNodes, srv.BootstrapNodes, srv.ntab, dynPeers, srv.NetRestrict)
// handshake
@@ -471,6 +541,7 @@ func (srv *Server) run(dialstate dialer) {
defer srv.loopWG.Done()
var (
peers = make(map[discover.NodeID]*Peer)
+ inboundCount = 0
trusted = make(map[discover.NodeID]bool, len(srv.TrustedNodes))
taskdone = make(chan task, maxActiveDialTasks)
runningTasks []task
@@ -556,14 +627,14 @@ running:
}
// TODO: track in-progress inbound node IDs (pre-Peer) to avoid dialing them.
select {
- case c.cont <- srv.encHandshakeChecks(peers, c):
+ case c.cont <- srv.encHandshakeChecks(peers, inboundCount, c):
case <-srv.quit:
break running
}
case c := <-srv.addpeer:
// At this point the connection is past the protocol handshake.
// Its capabilities are known and the remote identity is verified.
- err := srv.protoHandshakeChecks(peers, c)
+ err := srv.protoHandshakeChecks(peers, inboundCount, c)
if err == nil {
// The handshakes are done and it passed all checks.
p := newPeer(c, srv.Protocols)
@@ -574,8 +645,11 @@ running:
}
name := truncateName(c.name)
srv.log.Debug("Adding p2p peer", "name", name, "addr", c.fd.RemoteAddr(), "peers", len(peers)+1)
- peers[c.id] = p
go srv.runPeer(p)
+ peers[c.id] = p
+ if p.Inbound() {
+ inboundCount++
+ }
}
// The dialer logic relies on the assumption that
// dial tasks complete after the peer has been added or
@@ -590,6 +664,9 @@ running:
d := common.PrettyDuration(mclock.Now() - pd.created)
pd.log.Debug("Removing p2p peer", "duration", d, "peers", len(peers)-1, "req", pd.requested, "err", pd.err)
delete(peers, pd.ID())
+ if pd.Inbound() {
+ inboundCount--
+ }
}
}
@@ -616,20 +693,22 @@ running:
}
}
-func (srv *Server) protoHandshakeChecks(peers map[discover.NodeID]*Peer, c *conn) error {
+func (srv *Server) protoHandshakeChecks(peers map[discover.NodeID]*Peer, inboundCount int, c *conn) error {
// Drop connections with no matching protocols.
if len(srv.Protocols) > 0 && countMatchingProtocols(srv.Protocols, c.caps) == 0 {
return DiscUselessPeer
}
// Repeat the encryption handshake checks because the
// peer set might have changed between the handshakes.
- return srv.encHandshakeChecks(peers, c)
+ return srv.encHandshakeChecks(peers, inboundCount, c)
}
-func (srv *Server) encHandshakeChecks(peers map[discover.NodeID]*Peer, c *conn) error {
+func (srv *Server) encHandshakeChecks(peers map[discover.NodeID]*Peer, inboundCount int, c *conn) error {
switch {
case !c.is(trustedConn|staticDialedConn) && len(peers) >= srv.MaxPeers:
return DiscTooManyPeers
+ case !c.is(trustedConn) && c.is(inboundConn) && inboundCount >= srv.maxInboundConns():
+ return DiscTooManyPeers
case peers[c.id] != nil:
return DiscAlreadyConnected
case c.id == srv.Self().ID:
@@ -639,6 +718,21 @@ func (srv *Server) encHandshakeChecks(peers map[discover.NodeID]*Peer, c *conn)
}
}
+func (srv *Server) maxInboundConns() int {
+ return srv.MaxPeers - srv.maxDialedConns()
+}
+
+func (srv *Server) maxDialedConns() int {
+ if srv.NoDiscovery || srv.NoDial {
+ return 0
+ }
+ r := srv.DialRatio
+ if r == 0 {
+ r = defaultDialRatio
+ }
+ return srv.MaxPeers / r
+}
+
type tempError interface {
Temporary() bool
}
@@ -649,10 +743,7 @@ func (srv *Server) listenLoop() {
defer srv.loopWG.Done()
srv.log.Info("RLPx listener up", "self", srv.makeSelf(srv.listener, srv.ntab))
- // This channel acts as a semaphore limiting
- // active inbound connections that are lingering pre-handshake.
- // If all slots are taken, no further connections are accepted.
- tokens := maxAcceptConns
+ tokens := defaultMaxPendingPeers
if srv.MaxPendingPeers > 0 {
tokens = srv.MaxPendingPeers
}
@@ -693,9 +784,6 @@ func (srv *Server) listenLoop() {
fd = newMeteredConn(fd, true)
srv.log.Trace("Accepted connection", "addr", fd.RemoteAddr())
-
- // Spawn the handler. It will give the slot back when the connection
- // has been established.
go func() {
srv.SetupConn(fd, inboundConn, nil)
slots <- struct{}{}
diff --git a/p2p/simulations/adapters/state.go b/p2p/simulations/adapters/state.go
index 8b1dfef90..0d4ecfb0f 100644
--- a/p2p/simulations/adapters/state.go
+++ b/p2p/simulations/adapters/state.go
@@ -13,6 +13,7 @@
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
package adapters
type SimStateStore struct {
diff --git a/params/bootnodes.go b/params/bootnodes.go
index ecb1acd4f..c7190ae67 100644
--- a/params/bootnodes.go
+++ b/params/bootnodes.go
@@ -33,8 +33,10 @@ var MainnetBootnodes = []string{
// TestnetBootnodes are the enode URLs of the P2P bootstrap nodes running on the
// Ropsten test network.
var TestnetBootnodes = []string{
- "enode://6ce05930c72abc632c58e2e4324f7c7ea478cec0ed4fa2528982cf34483094e9cbc9216e7aa349691242576d552a2a56aaeae426c5303ded677ce455ba1acd9d@13.84.180.240:30303", // US-TX
- "enode://20c9ad97c081d63397d7b685a412227a40e23c8bdc6688c6f37e97cfbc22d2b4d1db1510d8f61e6a8866ad7f0e17c02b14182d37ea7c3c8b9c2683aeb6b733a1@52.169.14.227:30303", // IE
+ "enode://30b7ab30a01c124a6cceca36863ece12c4f5fa68e3ba9b0b51407ccc002eeed3b3102d20a88f1c1d3c3154e2449317b8ef95090e77b312d5cc39354f86d5d606@52.176.7.10:30303", // US-Azure geth
+ "enode://865a63255b3bb68023b6bffd5095118fcc13e79dcf014fe4e47e065c350c7cc72af2e53eff895f11ba1bbb6a2b33271c1116ee870f266618eadfc2e78aa7349c@52.176.100.77:30303", // US-Azure parity
+ "enode://6332792c4a00e3e4ee0926ed89e0d27ef985424d97b6a45bf0f23e51f0dcb5e66b875777506458aea7af6f9e4ffb69f43f3778ee73c81ed9d34c51c4b16b0b0f@52.232.243.152:30303", // Parity
+ "enode://94c15d1b9e2fe7ce56e458b9a3b672ef11894ddedd0c6f247e0f1d3487f52b66208fb4aeb8179fce6e3a749ea93ed147c37976d67af557508d199d9594c35f09@192.81.208.223:30303", // @gpip
}
// RinkebyBootnodes are the enode URLs of the P2P bootstrap nodes running on the
@@ -45,18 +47,11 @@ var RinkebyBootnodes = []string{
"enode://b6b28890b006743680c52e64e0d16db57f28124885595fa03a562be1d2bf0f3a1da297d56b13da25fb992888fd556d4c1a27b1f39d531bde7de1921c90061cc6@159.89.28.211:30303", // AKASHA
}
-// RinkebyV5Bootnodes are the enode URLs of the P2P bootstrap nodes running on the
-// Rinkeby test network for the experimental RLPx v5 topic-discovery network.
-var RinkebyV5Bootnodes = []string{
- "enode://a24ac7c5484ef4ed0c5eb2d36620ba4e4aa13b8c84684e1b4aab0cebea2ae45cb4d375b77eab56516d34bfbd3c1a833fc51296ff084b770b94fb9028c4d25ccf@52.169.42.101:30303?discport=30304", // IE
- "enode://343149e4feefa15d882d9fe4ac7d88f885bd05ebb735e547f12e12080a9fa07c8014ca6fd7f373123488102fe5e34111f8509cf0b7de3f5b44339c9f25e87cb8@52.3.158.184:30303?discport=30304", // INFURA
- "enode://b6b28890b006743680c52e64e0d16db57f28124885595fa03a562be1d2bf0f3a1da297d56b13da25fb992888fd556d4c1a27b1f39d531bde7de1921c90061cc6@159.89.28.211:30303?discport=30304", // AKASHA
-}
-
// DiscoveryV5Bootnodes are the enode URLs of the P2P bootstrap nodes for the
// experimental RLPx v5 topic-discovery network.
var DiscoveryV5Bootnodes = []string{
- "enode://0cc5f5ffb5d9098c8b8c62325f3797f56509bff942704687b6530992ac706e2cb946b90a34f1f19548cd3c7baccbcaea354531e5983c7d1bc0dee16ce4b6440b@40.118.3.223:30305",
- "enode://1c7a64d76c0334b0418c004af2f67c50e36a3be60b5e4790bdac0439d21603469a85fad36f2473c9a80eb043ae60936df905fa28f1ff614c3e5dc34f15dcd2dc@40.118.3.223:30308",
- "enode://85c85d7143ae8bb96924f2b54f1b3e70d8c4d367af305325d30a61385a432f247d2c75c45c6b4a60335060d072d7f5b35dd1d4c45f76941f62a4f83b6e75daaf@40.118.3.223:30309",
+ "enode://06051a5573c81934c9554ef2898eb13b33a34b94cf36b202b69fde139ca17a85051979867720d4bdae4323d4943ddf9aeeb6643633aa656e0be843659795007a@35.177.226.168:30303",
+ "enode://0cc5f5ffb5d9098c8b8c62325f3797f56509bff942704687b6530992ac706e2cb946b90a34f1f19548cd3c7baccbcaea354531e5983c7d1bc0dee16ce4b6440b@40.118.3.223:30304",
+ "enode://1c7a64d76c0334b0418c004af2f67c50e36a3be60b5e4790bdac0439d21603469a85fad36f2473c9a80eb043ae60936df905fa28f1ff614c3e5dc34f15dcd2dc@40.118.3.223:30306",
+ "enode://85c85d7143ae8bb96924f2b54f1b3e70d8c4d367af305325d30a61385a432f247d2c75c45c6b4a60335060d072d7f5b35dd1d4c45f76941f62a4f83b6e75daaf@40.118.3.223:30307",
}
diff --git a/params/protocol_params.go b/params/protocol_params.go
index c56faf56f..5a0b14d61 100644
--- a/params/protocol_params.go
+++ b/params/protocol_params.go
@@ -18,7 +18,15 @@ package params
import "math/big"
+var (
+ TargetGasLimit uint64 = GenesisGasLimit // The artificial target
+)
+
const (
+ GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations.
+ MinGasLimit uint64 = 5000 // Minimum the gas limit may ever be.
+ GenesisGasLimit uint64 = 4712388 // Gas limit of the Genesis block.
+
MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis.
ExpByteGas uint64 = 10 // Times ceil(log256(exponent)) for the EXP instruction.
SloadGas uint64 = 50 // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
@@ -72,12 +80,8 @@ const (
)
var (
- GasLimitBoundDivisor = big.NewInt(1024) // The bound divisor of the gas limit, used in update calculations.
- MinGasLimit = big.NewInt(5000) // Minimum the gas limit may ever be.
- GenesisGasLimit = big.NewInt(4712388) // Gas limit of the Genesis block.
- TargetGasLimit = new(big.Int).Set(GenesisGasLimit) // The artificial target
- DifficultyBoundDivisor = big.NewInt(2048) // The bound divisor of the difficulty, used in the update calculations.
- GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block.
- MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be.
- DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not.
+ DifficultyBoundDivisor = big.NewInt(2048) // The bound divisor of the difficulty, used in the update calculations.
+ GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block.
+ MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be.
+ DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not.
)
diff --git a/params/version.go b/params/version.go
index 32d4a2e23..c0437cef0 100644
--- a/params/version.go
+++ b/params/version.go
@@ -23,7 +23,7 @@ import (
const (
VersionMajor = 1 // Major version component of the current release
VersionMinor = 8 // Minor version component of the current release
- VersionPatch = 0 // Patch version component of the current release
+ VersionPatch = 2 // Patch version component of the current release
VersionMeta = "unstable" // Version metadata to append to the version string
)
diff --git a/rpc/http.go b/rpc/http.go
index d61b0e470..a46d8c2b3 100644
--- a/rpc/http.go
+++ b/rpc/http.go
@@ -31,6 +31,7 @@ import (
"time"
"github.com/rs/cors"
+ "strings"
)
const (
@@ -65,8 +66,9 @@ func (hc *httpConn) Close() error {
return nil
}
-// DialHTTP creates a new RPC clients that connection to an RPC server over HTTP.
-func DialHTTP(endpoint string) (*Client, error) {
+// DialHTTPWithClient creates a new RPC client that connects to an RPC server over HTTP
+// using the provided HTTP Client.
+func DialHTTPWithClient(endpoint string, client *http.Client) (*Client, error) {
req, err := http.NewRequest(http.MethodPost, endpoint, nil)
if err != nil {
return nil, err
@@ -76,10 +78,15 @@ func DialHTTP(endpoint string) (*Client, error) {
initctx := context.Background()
return newClient(initctx, func(context.Context) (net.Conn, error) {
- return &httpConn{client: new(http.Client), req: req, closed: make(chan struct{})}, nil
+ return &httpConn{client: client, req: req, closed: make(chan struct{})}, nil
})
}
+// DialHTTP creates a new RPC client that connects to an RPC server over HTTP.
+func DialHTTP(endpoint string) (*Client, error) {
+ return DialHTTPWithClient(endpoint, new(http.Client))
+}
+
func (c *Client) sendHTTP(ctx context.Context, op *requestOp, msg interface{}) error {
hc := c.writeConn.(*httpConn)
respBody, err := hc.doRequest(ctx, msg)
@@ -142,8 +149,11 @@ func (t *httpReadWriteNopCloser) Close() error {
// NewHTTPServer creates a new HTTP RPC server around an API provider.
//
// Deprecated: Server implements http.Handler
-func NewHTTPServer(cors []string, srv *Server) *http.Server {
- return &http.Server{Handler: newCorsHandler(srv, cors)}
+func NewHTTPServer(cors []string, vhosts []string, srv *Server) *http.Server {
+ // Wrap the CORS-handler within a host-handler
+ handler := newCorsHandler(srv, cors)
+ handler = newVHostHandler(vhosts, handler)
+ return &http.Server{Handler: handler}
}
// ServeHTTP serves JSON-RPC requests over HTTP.
@@ -189,7 +199,6 @@ func newCorsHandler(srv *Server, allowedOrigins []string) http.Handler {
if len(allowedOrigins) == 0 {
return srv
}
-
c := cors.New(cors.Options{
AllowedOrigins: allowedOrigins,
AllowedMethods: []string{http.MethodPost, http.MethodGet},
@@ -198,3 +207,50 @@ func newCorsHandler(srv *Server, allowedOrigins []string) http.Handler {
})
return c.Handler(srv)
}
+
+// virtualHostHandler is a handler which validates the Host-header of incoming requests.
+// The virtualHostHandler can prevent DNS rebinding attacks, which do not utilize CORS-headers,
+// since they do in-domain requests against the RPC api. Instead, we can see on the Host-header
+// which domain was used, and validate that against a whitelist.
+type virtualHostHandler struct {
+ vhosts map[string]struct{}
+ next http.Handler
+}
+
+// ServeHTTP serves JSON-RPC requests over HTTP, implements http.Handler
+func (h *virtualHostHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ // if r.Host is not set, we can continue serving since a browser would set the Host header
+ if r.Host == "" {
+ h.next.ServeHTTP(w, r)
+ return
+ }
+ host, _, err := net.SplitHostPort(r.Host)
+ if err != nil {
+ // Either invalid (too many colons) or no port specified
+ host = r.Host
+ }
+ if ipAddr := net.ParseIP(host); ipAddr != nil {
+ // It's an IP address, we can serve that
+ h.next.ServeHTTP(w, r)
+ return
+
+ }
+ // Not an ip address, but a hostname. Need to validate
+ if _, exist := h.vhosts["*"]; exist {
+ h.next.ServeHTTP(w, r)
+ return
+ }
+ if _, exist := h.vhosts[host]; exist {
+ h.next.ServeHTTP(w, r)
+ return
+ }
+ http.Error(w, "invalid host specified", http.StatusForbidden)
+}
+
+func newVHostHandler(vhosts []string, next http.Handler) http.Handler {
+ vhostMap := make(map[string]struct{})
+ for _, allowedHost := range vhosts {
+ vhostMap[strings.ToLower(allowedHost)] = struct{}{}
+ }
+ return &virtualHostHandler{vhostMap, next}
+}
diff --git a/rpc/types_test.go b/rpc/types_test.go
index 30cef9b22..68b6d3c54 100644
--- a/rpc/types_test.go
+++ b/rpc/types_test.go
@@ -1,4 +1,4 @@
-// Copyright 2017 The go-ethereum Authors
+// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
diff --git a/swarm/api/http/error_templates.go b/swarm/api/http/error_templates.go
index 2c20ba8f9..0457cb8a7 100644
--- a/swarm/api/http/error_templates.go
+++ b/swarm/api/http/error_templates.go
@@ -37,7 +37,7 @@ func GetGenericErrorPage() string {
<meta http-equiv="X-UA-Compatible" ww="chrome=1">
<meta name="description" content="Ethereum/Swarm error page">
<meta property="og:url" content="https://swarm-gateways.net/bzz:/theswarm.eth">
-
+ <link rel="shortcut icon" type="image/x-icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHsAAAB5CAYAAAAZD150AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KTMInWQAAFzFJREFUeAHtnXuwJFV9x7vnzrKwIC95w/ImYFkxlZgiGswCIiCGxPhHCEIwmIemUqYwJkYrJmXlUZRa+IpAWYYEk4qJD4gJGAmoiBIxMQFRQCkXdhdCeL+fYdk7nc+ne87dvnPn0TPTPdNzmd/W2X6fc76/7/n9zjm/PrcniuYy18BcA3MNzDUw18BcA3MNzDUw18BcA3MNrGYNLERroyMAeNQ0QcbTLPxFUfaOOx4Wbd12ThRHp0TJ4s5RFF8RtVoXg/2BSeOfk12lxtc0fjva1jibItZEDf4li3u3i3sqipOPRIvRp6ssvjPvhc4Tq/y4Ab71pEXS1oqw7hw1mz8XJc2LoiQ6iTJaaTkxth0l69jXwNayOZ10AvubSQ+RrFOl8mKy7EOiRuN3UfjrUfItUaN1SbQt+lqp2m02T4payS9HSfxK8k1IGdEWkln2Xuzldd7keBunrsO1f4r9b5Mqk3zBlRUy9Ywb0TtQ6O9Tjx1JkvA8SSXfiJK5Fj1MGkf2jBYWzo9a8Y+TiQRaxnLpTnb+HuvzDerzLk4+mb9Q1v5qduPrUPvxURx/DiWeicK2W1lKdCT2Q7n+VqzuOei5m+Nnh1TsPtGahbOiaOFCrHn/vs8ud+PdbrWLOZr6vIX6PEF97uH4uW43jnpudVp2Mzo1ajV+AwPbgGJUYr4/1Or+jxSwu90R5f6QQdPnaBK603zD4LCLNJsnkusfcUXXrKfoL4MtOzxvfXegPrdGjeRjlHEVx4PrE57us11tlr0b/fKlKIq+OTqsjXulS80sO5Dtbdugfnf4Py5qxGenxEeppbez6LJpte6LFuIWlvhT3J/Pq8vNnBps2eE562t97A608G+xnZMdtMN2H+z3LSj+n9g3cNGN4Nzt9tddCZK0ncnnrChuHBElySaOH8k/mNtf5Pr3onWtL0WthfWUuA/XGGX3KHsw2ZYtqc9Rs4dIW2m4mxjwXd8+z2Y8mXXLXoDk38Eaz4c7+2VJzLvsXtrpRXa43+svh/TTIf1QSP0Rx0+Ei8u2L0RPM6i6hn77e9SFhsJzGWnLG9wgshvpeOEJnn+6nX+D8u+ck51p43hIvhyS38DhHiQJKiqDyDYfG42WeiAk3oO93uLJ3tK6P0pa1zK/vj5aSI6FtF15Zjvhvcle5F69xzMkywxdAk+US7aDgVmSbMTaaFwM0VdS8QNIQTll4TA/SdKd3kvS0oqWgRveeku0uO2NjM4v5TmDJda52/MSqyXfy3YrqXJxEDArcjB92Dvh4RdIjoC1hLJFUp6BAPMOBHQjalC5SdR6wfj3FVFjDV1Bcg698S7ka172y0+3y5DwiRncxAoC1OjSiN6LJTNQSd5MJruQnDqVLbrTB0mPkXEgetwy7oH0T2LppzOrv4bMnif/B0hPsS/pozSkketUZ8s2KPIq3OH5ONWjQVgFwSpO69KajVpVpfzHom3b3hctNHajwR5OOUbyLGt7n85B1VJPspvRydFi/Hba/gYUoFLKJlqPpmXx9ikdBRcZsHH7WLIjZT1F472TXHaFZ6dqO5Gsx0SkbmTvS7/8caYbG1CMJGt1Vciz5O5UKuRflUV31t1yJPdx2jDlp2MPw6wTsfA6ke1U47Pg1mVXqfwXyP1Bypg2dgiOXcDwKJgPZPsSknGPyoiv0wAtZlz6CERsAXB4v1tV/apsTFS/sIgP7xLfTdrMPhbfc6pWONNeN1alzF7lDTqfuTkHS3F0FzcbbHixCG/cUtLvAHBZs4Fluqsb2fnK+XpBS6fVp4Mo+7q6WGS+nmXvE8SJf0imDxKGlfTS3Pq0+61BipJc+9j7gOzI1bCoS3tKUwB51U3st9cwar+Kgeq/sR8GkWPXs+5kbwcYpy/yXWQg2U5brPtqI905yEPRttbfgm0jqVSZHbID7CyUeRc078kpo2lrSFWSbt6lWRd5dYreizdcLI1K4m9F2xa/zHEleGaP7Kzftj933ZgDuZcwc9W9q7QylWRevLeKd+d/lgMnt3I84M0XdwwnNlQCRvHVkOwiBaZh1ckskh20kfXnCQpKI1Opa9fFlxWRWsvSpoPIex1pbxIWxyvVVuv9lGFAZlxp0ohc8PgZMqpkgWFnBWeZ7DwWB3H/g/IMTGjlvoceRbDmBuu/kj2waBf0x9o2/ysvYN1n8ELmtbzFugDHrrsddlWqgy/z3Bw1WeGyNbrNjCclFl4XIagSn0Fl7IdHEQc3W0nh9aQvG2zMna7dt1sheBHK8R5IiPdlcwBbYtc5iZdWwNh3MyuITyFtIN7F0qTCrp0GGB8TLbQuixaTf+HJ+3MlTGQ3a7MTKWpgIQ0W8H2Bu1B4KaIFaeW7k/I4bRBbOBcauv0yHiE+iPvDOS7nJE7oV00rRFd8O57gPK78YMXV5Sesg3GNKgd7y0vsOKpzUKWjqkMfZoM43Xu20CGz3nw2TuOSxqGQfVhPovP3r9x3FejReKSv8gLnQ1w+ZuUtS2csf2pEW4vuLXmpfhPdGdeNd6us1sRy33RlyHPs69bXsIjwWQjGktN+WXff6eo5lZPMjfda4xZI/Ele5JxK3jSc5Cae7uYJcplOfjfv3iZf+vISy3bjy3PffkQ/2zgaeosP4nq78e25bt9Tp48S/TqZba1i+6tlNL5d1Sv3Mut23VcUP8hlRu4t57YOxPbhWNL7W/bKPHud0fpd9eJfiNSui1ztZKtw5rCxUyTduKTuQMK1J3eRHoBwR+Au8ldGIT00JgM8z5KH/XIt9VrLSqn1EgSlx/eQj4v7guS7LfdZAJjcDcf3YYjHQLVTrmEJd9WLixTDc/kyQrm12K42slU0wQ8jXLELIIq+FtW138zgah8oO5DkXN+8AoHsLhPPO4WzITkQqy3B+VqvFrKDsiE4NmDie2DPhfN5zL32mZm0HuaJx0l7ECo9hBs7FwSanyQb3rRfLtqYuHX6slrIJmoW/y/qDNOjYUjOs+Bz9rkP82UG30IdSjogd4MNgYHekoxazlIGk9yZdbIZdMX2l1pz+YqPkzvo0/kbrnivNskzZcmdDWkWyXaEjZtOp1H2mVpi+URnmlI//M1XYhRuDclpmttefTmX6iuzSDZz5XTwFbRaFdGd+dtFmCTbvrzqcimiXJkFslWq1mu/bFDEgdE0Fe1oX9K1cufs06wLxReXupPdLShSB+Xqxp1yOeqX8MHxdW6attSZbIMi9pX2y4HgsJ223kL5DtgC6evYr9OLpVDHpW3dyNaS80ERLahuBC8pL7cj6TZKrVz3rl5rV+86kU28Or6Tce56FOUaL5VVO4VRp15iXXXriqtlbLS1knq5nVZyDV8KJDqVuAhAK69CxGw4tIrpkx+9uZFlR39A/s7/ayV1tZyXQvovwcdPoC0XEYbIWBnKY+qU8KYrDXWWkZ+NR690G/H1L2DP3ykj0yryqCvZAavfUTkNZ34cJ3SRZVhjmWQzKIs3QvKlNMfvUj8Ha7WVupMdFHdU1Gy8DapdQDgu4WWRjbdJ/oEIwGXUyThA7aUOfbarPwdZhMt8voJr541T+rUCnxmV9HH6bAe0z7DG7N9x3H9BDXTZReqxJ/e5eGKqMk2y/bq+X0F6P256X1T2X2iiv4W0WndA+k2QzouP5Cjux0oLKTuv5FHIdrC4EyRfB8kfpcR/5dgR9yDxC4zvaWPcv42xzPHHoPKXXZ+OG1+ITuNN0gXUZD+SS3lcAcr3OpN30/ddx3ERa/GjtOfy3CvS5/mvoIzgxvkcxkLrI4wa/HuvYpJ+GTn+MDeLUc/lHyeI8b1g/BrHRTByW3kyabJfA0HvAOepQHDAZTDClm7SehzwXM3fP13E/rdJReRl5MmH5ZbWbJtnPylCtnrBZcd3UcVroOlyjgflG8rky8bpLxbkMeqxnHdnHiJinXmrdSHHN4SHJrGdFNmHo4A/h+RXA8p1XvmAQyA74NXNYu3xDSiEZ9Lf0AjXem13IHZ1DKtLzsBeDuYmX5b0kkFk2zXwfPIZSP4q+w/3yqjjvBj/lOd+lvNiFFeQQHY4Dhj/A4x/xslN4UKV26rJXktbfifEkbA9NNEFTCfZ+Vt4JrkYm9LSi/SRMf35aTxzOvdLWjfpRzZ/MpT8J+V9nAcZFxSSHcB4HvB+j7u13G4YO8nOZyzGT1LmJzhZBGP+2aH2bWFVyDpeCZxJoOFvUMIbKSBvyZ3l6R5NPST268M/jxr96sIWbgohye73J8lGCLsBK/Odc7d14WLehRRI8djI1818uf9CrPmzHA+aHXALXc5C9Cs8dwkY38RxP4yW1Q/jBjCeXhijpY8g5Vv2QgS58btR5eHUR0X2AZnWuJ9lB0iZxSTRj/i884dxkFeHCwO2B0H6L+JT7D7CGCFv2by4iLew3uxTUHUL9xQhWVR4jvgPwXgkzxTB2M+yA4SAcSMYLxgCY3h+4LYssq3oelr5BSj2BPbz/dWgShQhO58HFht/k77uPZzcQgoWmr+nc//HCMqcy517cWEtj2jxkJ98Hkv+R/YHNUjzU1fraTwf4rmT2B8GYxGyLSMIf3AYXY+HEuNmUpH6hWd7bssg24HJuSjgNynFl/j9BkfdKjIs2eZhf4wVJn+HGiRroycHyAI/rgZJrdfQUB7jub/nfteWF5FD2xh/i5vtHobFOCzZ1mkUjD7XU8YjuxH9CQ3+zeSuxdj6ilhZZ2VGIds8rPsC/7P6M+HzF9EHOS5S/s7cZzSrmLU0/IUffiQm4lMbo2MchWyKW4bxi9T4A+06eG1oGYXsHZiBnsgPlv0lpRkGHMaddavgqGTn86LvxUobvFrcFn2dfZU7jqwB4/FgdIRsQx4X46hk5zEEjAaeruXC0BiHI7tJf9xqvB0Dej2FhQFPvkKj7JdBtuU6bqA/jr/CgOuvUch1nhxaMoxvA+NpPFsWxjLIFop8OWbhj//Tn5e0YReWomTzoyiNC1CAo1qiXMO3qj41KovsUISjY+ar8U30zX/M/uZwYcB2PzAS3kyDIrr6oS2nT/5lkR2KCBhvBuP7OLkpXOi39aF+sgv28i5G2Q6C1pO8v0i/2C/Pzmv2ncX6z84nux9bP0KdRNLi+NexhRY1vpXjXvNgMZ7HvZ9Pn8meLRuj+VWB0RnQW8Ho92O+3wcjlzK3kO50+Y8fMIk/TTYncc3RZ9kKCEWWbdkhX7d6Lqcx32EQ5yDrCU/mZB3WfAnQ3sA559hVYSzbsnMQUoy8keObaklyJheezF/M79vP9ZImLd7R7kZueJrU795eeUzzvET7c02bqLnTGLufTmlynegZwZpsdeisYtycctUd4xJm3V0vCa7HD8r5VWBbjNOPfs/0ymvS531l+hiFOsWSdLH0slrdqxiZwqXLgWcHo/H77GsPASNQektR4uwVGPTwNipJvyvmWx2nAr0U2LvE6q4I2H7ZLyG4htu6ea6orHqMRclWYZnisq8D8is26apP56BKHUgPrTwMhIYhOkOxyjEOQ3ZQiFtXXegmn4TmfdkaQhxFuTw2tvglhEfJpcypkpUSo685/Vnj/djOPMZRyVYZkmvfeC/KcF66G8ntJKzcsh09+xkqlzVV2dD8UmLAuDtlBdKrxlk6xnHIBncq9nUq3PfNKsI3SuZbhTJUgJ+Q1OLCdLBKoikmlU6MDuIc4c8UxjLIztQh8Iz0zewZM9cKypzK2BdryT3nkaEiFW4Dxi2ziLFMsoOOtQL70KdRiIS7KmTUyJtWK8mOsJ3rG6suswGR3UiSx2j35Z8olYXRGUUl3qoKstWelXXu+hDbxyH9pWzzS4E4HCiSGn5G0SibUgeis5psx/gwJxzE6c2ckobZQLiv39YGorcyshcwVkK0laiKbPMOEoIyRrBCfx6u9do6ElaJDsIqA9+r8BHOZ0GZjHRnJ0X0OnGMRSo1AvYVj4QBzl1YgG7PxOvIZVaQeYOspRvA0UJmgWiqmYp1NTxbW4yTIlttZMRlLsv+XLduUCYQ6odeJTnMl8N5Ts2MDML4BBiduUwF4yTJzjOmC7OfykjPwpsqYBYJzuPK79cO4zTIDoQyuuZ7ZrEx9sRRu7H2adQnT1BZ+3mMfg+VgVjiAG6qGCetXJXA9Cm+n63ujBFo4opUpxuORh2dGpgZdRrDo1OXLhjTvysXo8lgjJgnjnGSZBttYoTd8+uEXpdw31ipDK0gWAi7MyEOKokx9MQoiED6xDFWTbZk2RfTP6df8y8aFPE9tEqRcFOdRYySTAg3foStYdwi8QAxqg9nJRPBWCXZAlYBD7KVOKWIErwvNJKgEK2gqli05Y0q4rEhP8B2FIw2koAxkF5FvD3FVxXZAI/vowRDnOO6Yj2D+Ui2/XnRBsOtlUrZGJ12aumVYSyTbEnVhT0Gv8bGbaHjEk0WqZiP/bmkB9c+8QEOZecxgrPUwE/A6JglWHmpGMsgOxCKu05J1jUp4Xx2VM7/NiAblBYg6br3SYhYLFuMklx1UKQSjOOSrQKcL+uy7bOqIJhsV4jlGje3zNCfr7ippBPTxhhcu93YWDIK2YFQ3E1qyaFfDufHqtAQD1ueXsT5ujh0fWUO4sy/DhhtbPbnYhsL47BkqwBaWmrJKtmKTJpkilwh9ue6Vvu4cQc44nHwdS/bumC0TmNjHIZslZkPGNSBZKq0JDa8cYMyAaOvV+vSkJcAtus0MsZBZDvN0VWGEbb9R91IpkorJMxdHcTp+vqJeCTWhuwsImCsO85hMKb4B5Ad21c4FXB0qNRdAVkts3raSB3EBfLCtc4trjrexMlZxzgw/mAf10ue5w/FbuWP+w6EYt89D8ysV0YDztvHjj3S7FKGDRPC+XBdI/kAe3d2uUeMt08AY4iDd6nCWKfaXim+u43xjn65FbHUBmPdV/FH+K+D9CPITEspS3Cf6as/CS9LxMQSqJiG2voivfjXOdbK+0nAeBIYj+TGkjG68DJxTX1ZEjD6jfOA0fFGXylCdsiAT080j4uS1tmc0CMMzDw82GdbNtl6H9aD8aG87MsLuvFhxE+IvJofU/9VHioRY6lki5HGyIfyFtOGXBjjMGQHpe3EVwTPobBXcEKLHGQ14blu27LIVgH8kUJyI7W5kH1XwYwjYoTwFCNeYlyMpZAdMPJFiRQjL5mGk1HIDiUchUJORCHHcsJ8RiF9XLJVwAIkX4tFXkl7vy1UrqTtkW2MP0N+Y2Aci2wxNtsYrxgH4zhkq09d3SHtr/zvx77hy2FkHLKZVjH4Wmx9kAI3kcroVrrVXYwHtzHuz/4IGEcmm2ljvKWNcTNlO8ceWcYle3vBzeapGPfJzFgZjKQCkQNlWLLb9XWRQOufoffygSWUeUOzeQrlngLG3cjWuhTEOBTZASNz/hTjZWVBKI/srEZ74PY2MEA6ETW4wC7MXXvVdxiytWQV8CVIvpoMeQM1Fdm9jfG1xTEWJpspqG/VUozXgO6BMhGWTbZ1M8/dUMibaPgb2O/neoqQbX7+ZMNVjAr+in0HJkUsitsqE+u0axvj8ewPwDiQbPPjQz/Jl8F4Cfu+Ri0do4VUKUfT151Fte3P7fs6AXDcc57twIT+Me2XL2L/dlIdxV8mOruN0YhkF4w9yZ4oxqrJlhy/VXRstNg4GZs/hmNjukEh3ci2TmuJat2KO7sCm/kmx8MOinhkohIwGngSo3PfHMYVZOcxXtnGWGYgpyv4SZAdCjZg8dPtgIUvJ5yqdZJtS+drDsknUMA32LdhzJKI8ZVgJA6RvoBpY1xGthiZORD4yYIiE8M4SbIDaX5o7lws4GWcIGacunEDF3yJKflvqP4o+1rGLMtOYPw1ML4cEASeEkfvvl8Qo4Gfj6X7/DdJmQbZAZ9BmRNQxOsIwX4XBVzBhR+Ei6tkG4IyjNxb38fqxwqKzLpOHLTtRRrwqnWmYYpx71WOcaYJmld+roG5BuYamGtgroG5BuYamJoG/h/ff6XOIB4wOAAAAABJRU5ErkJggg=="/>
<style>
body, div, header, footer {
@@ -89,8 +89,8 @@ func GetGenericErrorPage() string {
display: block;
margin: 0 auto;
/* width: 50%; */
- min-height: 60vh;
- max-height: 60vh;
+ min-height: 60vh;
+ max-height: 60vh;
padding: 50px 20px;
opacity: 0.6;
background-color: #A9F5BF;
@@ -212,7 +212,7 @@ func GetNotFoundErrorPage() string {
<meta http-equiv="X-UA-Compatible" ww="chrome=1">
<meta name="description" content="Ethereum/Swarm error page">
<meta property="og:url" content="https://swarm-gateways.net/bzz:/theswarm.eth">
-
+ <link rel="shortcut icon" type="image/x-icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHsAAAB5CAYAAAAZD150AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KTMInWQAAFzFJREFUeAHtnXuwJFV9x7vnzrKwIC95w/ImYFkxlZgiGswCIiCGxPhHCEIwmIemUqYwJkYrJmXlUZRa+IpAWYYEk4qJD4gJGAmoiBIxMQFRQCkXdhdCeL+fYdk7nc+ne87dvnPn0TPTPdNzmd/W2X6fc76/7/n9zjm/PrcniuYy18BcA3MNzDUw18BcA3MNzDUw18BcA3MNrGYNLERroyMAeNQ0QcbTLPxFUfaOOx4Wbd12ThRHp0TJ4s5RFF8RtVoXg/2BSeOfk12lxtc0fjva1jibItZEDf4li3u3i3sqipOPRIvRp6ssvjPvhc4Tq/y4Ab71pEXS1oqw7hw1mz8XJc2LoiQ6iTJaaTkxth0l69jXwNayOZ10AvubSQ+RrFOl8mKy7EOiRuN3UfjrUfItUaN1SbQt+lqp2m02T4payS9HSfxK8k1IGdEWkln2Xuzldd7keBunrsO1f4r9b5Mqk3zBlRUy9Ywb0TtQ6O9Tjx1JkvA8SSXfiJK5Fj1MGkf2jBYWzo9a8Y+TiQRaxnLpTnb+HuvzDerzLk4+mb9Q1v5qduPrUPvxURx/DiWeicK2W1lKdCT2Q7n+VqzuOei5m+Nnh1TsPtGahbOiaOFCrHn/vs8ud+PdbrWLOZr6vIX6PEF97uH4uW43jnpudVp2Mzo1ajV+AwPbgGJUYr4/1Or+jxSwu90R5f6QQdPnaBK603zD4LCLNJsnkusfcUXXrKfoL4MtOzxvfXegPrdGjeRjlHEVx4PrE57us11tlr0b/fKlKIq+OTqsjXulS80sO5Dtbdugfnf4Py5qxGenxEeppbez6LJpte6LFuIWlvhT3J/Pq8vNnBps2eE562t97A608G+xnZMdtMN2H+z3LSj+n9g3cNGN4Nzt9tddCZK0ncnnrChuHBElySaOH8k/mNtf5Pr3onWtL0WthfWUuA/XGGX3KHsw2ZYtqc9Rs4dIW2m4mxjwXd8+z2Y8mXXLXoDk38Eaz4c7+2VJzLvsXtrpRXa43+svh/TTIf1QSP0Rx0+Ei8u2L0RPM6i6hn77e9SFhsJzGWnLG9wgshvpeOEJnn+6nX+D8u+ck51p43hIvhyS38DhHiQJKiqDyDYfG42WeiAk3oO93uLJ3tK6P0pa1zK/vj5aSI6FtF15Zjvhvcle5F69xzMkywxdAk+US7aDgVmSbMTaaFwM0VdS8QNIQTll4TA/SdKd3kvS0oqWgRveeku0uO2NjM4v5TmDJda52/MSqyXfy3YrqXJxEDArcjB92Dvh4RdIjoC1hLJFUp6BAPMOBHQjalC5SdR6wfj3FVFjDV1Bcg698S7ka172y0+3y5DwiRncxAoC1OjSiN6LJTNQSd5MJruQnDqVLbrTB0mPkXEgetwy7oH0T2LppzOrv4bMnif/B0hPsS/pozSkketUZ8s2KPIq3OH5ONWjQVgFwSpO69KajVpVpfzHom3b3hctNHajwR5OOUbyLGt7n85B1VJPspvRydFi/Hba/gYUoFLKJlqPpmXx9ikdBRcZsHH7WLIjZT1F472TXHaFZ6dqO5Gsx0SkbmTvS7/8caYbG1CMJGt1Vciz5O5UKuRflUV31t1yJPdx2jDlp2MPw6wTsfA6ke1U47Pg1mVXqfwXyP1Bypg2dgiOXcDwKJgPZPsSknGPyoiv0wAtZlz6CERsAXB4v1tV/apsTFS/sIgP7xLfTdrMPhbfc6pWONNeN1alzF7lDTqfuTkHS3F0FzcbbHixCG/cUtLvAHBZs4Fluqsb2fnK+XpBS6fVp4Mo+7q6WGS+nmXvE8SJf0imDxKGlfTS3Pq0+61BipJc+9j7gOzI1bCoS3tKUwB51U3st9cwar+Kgeq/sR8GkWPXs+5kbwcYpy/yXWQg2U5brPtqI905yEPRttbfgm0jqVSZHbID7CyUeRc078kpo2lrSFWSbt6lWRd5dYreizdcLI1K4m9F2xa/zHEleGaP7Kzftj933ZgDuZcwc9W9q7QylWRevLeKd+d/lgMnt3I84M0XdwwnNlQCRvHVkOwiBaZh1ckskh20kfXnCQpKI1Opa9fFlxWRWsvSpoPIex1pbxIWxyvVVuv9lGFAZlxp0ohc8PgZMqpkgWFnBWeZ7DwWB3H/g/IMTGjlvoceRbDmBuu/kj2waBf0x9o2/ysvYN1n8ELmtbzFugDHrrsddlWqgy/z3Bw1WeGyNbrNjCclFl4XIagSn0Fl7IdHEQc3W0nh9aQvG2zMna7dt1sheBHK8R5IiPdlcwBbYtc5iZdWwNh3MyuITyFtIN7F0qTCrp0GGB8TLbQuixaTf+HJ+3MlTGQ3a7MTKWpgIQ0W8H2Bu1B4KaIFaeW7k/I4bRBbOBcauv0yHiE+iPvDOS7nJE7oV00rRFd8O57gPK78YMXV5Sesg3GNKgd7y0vsOKpzUKWjqkMfZoM43Xu20CGz3nw2TuOSxqGQfVhPovP3r9x3FejReKSv8gLnQ1w+ZuUtS2csf2pEW4vuLXmpfhPdGdeNd6us1sRy33RlyHPs69bXsIjwWQjGktN+WXff6eo5lZPMjfda4xZI/Ele5JxK3jSc5Cae7uYJcplOfjfv3iZf+vISy3bjy3PffkQ/2zgaeosP4nq78e25bt9Tp48S/TqZba1i+6tlNL5d1Sv3Mut23VcUP8hlRu4t57YOxPbhWNL7W/bKPHud0fpd9eJfiNSui1ztZKtw5rCxUyTduKTuQMK1J3eRHoBwR+Au8ldGIT00JgM8z5KH/XIt9VrLSqn1EgSlx/eQj4v7guS7LfdZAJjcDcf3YYjHQLVTrmEJd9WLixTDc/kyQrm12K42slU0wQ8jXLELIIq+FtW138zgah8oO5DkXN+8AoHsLhPPO4WzITkQqy3B+VqvFrKDsiE4NmDie2DPhfN5zL32mZm0HuaJx0l7ECo9hBs7FwSanyQb3rRfLtqYuHX6slrIJmoW/y/qDNOjYUjOs+Bz9rkP82UG30IdSjogd4MNgYHekoxazlIGk9yZdbIZdMX2l1pz+YqPkzvo0/kbrnivNskzZcmdDWkWyXaEjZtOp1H2mVpi+URnmlI//M1XYhRuDclpmttefTmX6iuzSDZz5XTwFbRaFdGd+dtFmCTbvrzqcimiXJkFslWq1mu/bFDEgdE0Fe1oX9K1cufs06wLxReXupPdLShSB+Xqxp1yOeqX8MHxdW6attSZbIMi9pX2y4HgsJ223kL5DtgC6evYr9OLpVDHpW3dyNaS80ERLahuBC8pL7cj6TZKrVz3rl5rV+86kU28Or6Tce56FOUaL5VVO4VRp15iXXXriqtlbLS1knq5nVZyDV8KJDqVuAhAK69CxGw4tIrpkx+9uZFlR39A/s7/ayV1tZyXQvovwcdPoC0XEYbIWBnKY+qU8KYrDXWWkZ+NR690G/H1L2DP3ykj0yryqCvZAavfUTkNZ34cJ3SRZVhjmWQzKIs3QvKlNMfvUj8Ha7WVupMdFHdU1Gy8DapdQDgu4WWRjbdJ/oEIwGXUyThA7aUOfbarPwdZhMt8voJr541T+rUCnxmV9HH6bAe0z7DG7N9x3H9BDXTZReqxJ/e5eGKqMk2y/bq+X0F6P256X1T2X2iiv4W0WndA+k2QzouP5Cjux0oLKTuv5FHIdrC4EyRfB8kfpcR/5dgR9yDxC4zvaWPcv42xzPHHoPKXXZ+OG1+ITuNN0gXUZD+SS3lcAcr3OpN30/ddx3ERa/GjtOfy3CvS5/mvoIzgxvkcxkLrI4wa/HuvYpJ+GTn+MDeLUc/lHyeI8b1g/BrHRTByW3kyabJfA0HvAOepQHDAZTDClm7SehzwXM3fP13E/rdJReRl5MmH5ZbWbJtnPylCtnrBZcd3UcVroOlyjgflG8rky8bpLxbkMeqxnHdnHiJinXmrdSHHN4SHJrGdFNmHo4A/h+RXA8p1XvmAQyA74NXNYu3xDSiEZ9Lf0AjXem13IHZ1DKtLzsBeDuYmX5b0kkFk2zXwfPIZSP4q+w/3yqjjvBj/lOd+lvNiFFeQQHY4Dhj/A4x/xslN4UKV26rJXktbfifEkbA9NNEFTCfZ+Vt4JrkYm9LSi/SRMf35aTxzOvdLWjfpRzZ/MpT8J+V9nAcZFxSSHcB4HvB+j7u13G4YO8nOZyzGT1LmJzhZBGP+2aH2bWFVyDpeCZxJoOFvUMIbKSBvyZ3l6R5NPST268M/jxr96sIWbgohye73J8lGCLsBK/Odc7d14WLehRRI8djI1818uf9CrPmzHA+aHXALXc5C9Cs8dwkY38RxP4yW1Q/jBjCeXhijpY8g5Vv2QgS58btR5eHUR0X2AZnWuJ9lB0iZxSTRj/i884dxkFeHCwO2B0H6L+JT7D7CGCFv2by4iLew3uxTUHUL9xQhWVR4jvgPwXgkzxTB2M+yA4SAcSMYLxgCY3h+4LYssq3oelr5BSj2BPbz/dWgShQhO58HFht/k77uPZzcQgoWmr+nc//HCMqcy517cWEtj2jxkJ98Hkv+R/YHNUjzU1fraTwf4rmT2B8GYxGyLSMIf3AYXY+HEuNmUpH6hWd7bssg24HJuSjgNynFl/j9BkfdKjIs2eZhf4wVJn+HGiRroycHyAI/rgZJrdfQUB7jub/nfteWF5FD2xh/i5vtHobFOCzZ1mkUjD7XU8YjuxH9CQ3+zeSuxdj6ilhZZ2VGIds8rPsC/7P6M+HzF9EHOS5S/s7cZzSrmLU0/IUffiQm4lMbo2MchWyKW4bxi9T4A+06eG1oGYXsHZiBnsgPlv0lpRkGHMaddavgqGTn86LvxUobvFrcFn2dfZU7jqwB4/FgdIRsQx4X46hk5zEEjAaeruXC0BiHI7tJf9xqvB0Dej2FhQFPvkKj7JdBtuU6bqA/jr/CgOuvUch1nhxaMoxvA+NpPFsWxjLIFop8OWbhj//Tn5e0YReWomTzoyiNC1CAo1qiXMO3qj41KovsUISjY+ar8U30zX/M/uZwYcB2PzAS3kyDIrr6oS2nT/5lkR2KCBhvBuP7OLkpXOi39aF+sgv28i5G2Q6C1pO8v0i/2C/Pzmv2ncX6z84nux9bP0KdRNLi+NexhRY1vpXjXvNgMZ7HvZ9Pn8meLRuj+VWB0RnQW8Ho92O+3wcjlzK3kO50+Y8fMIk/TTYncc3RZ9kKCEWWbdkhX7d6Lqcx32EQ5yDrCU/mZB3WfAnQ3sA559hVYSzbsnMQUoy8keObaklyJheezF/M79vP9ZImLd7R7kZueJrU795eeUzzvET7c02bqLnTGLufTmlynegZwZpsdeisYtycctUd4xJm3V0vCa7HD8r5VWBbjNOPfs/0ymvS531l+hiFOsWSdLH0slrdqxiZwqXLgWcHo/H77GsPASNQektR4uwVGPTwNipJvyvmWx2nAr0U2LvE6q4I2H7ZLyG4htu6ea6orHqMRclWYZnisq8D8is26apP56BKHUgPrTwMhIYhOkOxyjEOQ3ZQiFtXXegmn4TmfdkaQhxFuTw2tvglhEfJpcypkpUSo685/Vnj/djOPMZRyVYZkmvfeC/KcF66G8ntJKzcsh09+xkqlzVV2dD8UmLAuDtlBdKrxlk6xnHIBncq9nUq3PfNKsI3SuZbhTJUgJ+Q1OLCdLBKoikmlU6MDuIc4c8UxjLIztQh8Iz0zewZM9cKypzK2BdryT3nkaEiFW4Dxi2ziLFMsoOOtQL70KdRiIS7KmTUyJtWK8mOsJ3rG6suswGR3UiSx2j35Z8olYXRGUUl3qoKstWelXXu+hDbxyH9pWzzS4E4HCiSGn5G0SibUgeis5psx/gwJxzE6c2ckobZQLiv39YGorcyshcwVkK0laiKbPMOEoIyRrBCfx6u9do6ElaJDsIqA9+r8BHOZ0GZjHRnJ0X0OnGMRSo1AvYVj4QBzl1YgG7PxOvIZVaQeYOspRvA0UJmgWiqmYp1NTxbW4yTIlttZMRlLsv+XLduUCYQ6odeJTnMl8N5Ts2MDML4BBiduUwF4yTJzjOmC7OfykjPwpsqYBYJzuPK79cO4zTIDoQyuuZ7ZrEx9sRRu7H2adQnT1BZ+3mMfg+VgVjiAG6qGCetXJXA9Cm+n63ujBFo4opUpxuORh2dGpgZdRrDo1OXLhjTvysXo8lgjJgnjnGSZBttYoTd8+uEXpdw31ipDK0gWAi7MyEOKokx9MQoiED6xDFWTbZk2RfTP6df8y8aFPE9tEqRcFOdRYySTAg3foStYdwi8QAxqg9nJRPBWCXZAlYBD7KVOKWIErwvNJKgEK2gqli05Y0q4rEhP8B2FIw2koAxkF5FvD3FVxXZAI/vowRDnOO6Yj2D+Ui2/XnRBsOtlUrZGJ12aumVYSyTbEnVhT0Gv8bGbaHjEk0WqZiP/bmkB9c+8QEOZecxgrPUwE/A6JglWHmpGMsgOxCKu05J1jUp4Xx2VM7/NiAblBYg6br3SYhYLFuMklx1UKQSjOOSrQKcL+uy7bOqIJhsV4jlGje3zNCfr7ippBPTxhhcu93YWDIK2YFQ3E1qyaFfDufHqtAQD1ueXsT5ujh0fWUO4sy/DhhtbPbnYhsL47BkqwBaWmrJKtmKTJpkilwh9ue6Vvu4cQc44nHwdS/bumC0TmNjHIZslZkPGNSBZKq0JDa8cYMyAaOvV+vSkJcAtus0MsZBZDvN0VWGEbb9R91IpkorJMxdHcTp+vqJeCTWhuwsImCsO85hMKb4B5Ad21c4FXB0qNRdAVkts3raSB3EBfLCtc4trjrexMlZxzgw/mAf10ue5w/FbuWP+w6EYt89D8ysV0YDztvHjj3S7FKGDRPC+XBdI/kAe3d2uUeMt08AY4iDd6nCWKfaXim+u43xjn65FbHUBmPdV/FH+K+D9CPITEspS3Cf6as/CS9LxMQSqJiG2voivfjXOdbK+0nAeBIYj+TGkjG68DJxTX1ZEjD6jfOA0fFGXylCdsiAT080j4uS1tmc0CMMzDw82GdbNtl6H9aD8aG87MsLuvFhxE+IvJofU/9VHioRY6lki5HGyIfyFtOGXBjjMGQHpe3EVwTPobBXcEKLHGQ14blu27LIVgH8kUJyI7W5kH1XwYwjYoTwFCNeYlyMpZAdMPJFiRQjL5mGk1HIDiUchUJORCHHcsJ8RiF9XLJVwAIkX4tFXkl7vy1UrqTtkW2MP0N+Y2Aci2wxNtsYrxgH4zhkq09d3SHtr/zvx77hy2FkHLKZVjH4Wmx9kAI3kcroVrrVXYwHtzHuz/4IGEcmm2ljvKWNcTNlO8ceWcYle3vBzeapGPfJzFgZjKQCkQNlWLLb9XWRQOufoffygSWUeUOzeQrlngLG3cjWuhTEOBTZASNz/hTjZWVBKI/srEZ74PY2MEA6ETW4wC7MXXvVdxiytWQV8CVIvpoMeQM1Fdm9jfG1xTEWJpspqG/VUozXgO6BMhGWTbZ1M8/dUMibaPgb2O/neoqQbX7+ZMNVjAr+in0HJkUsitsqE+u0axvj8ewPwDiQbPPjQz/Jl8F4Cfu+Ri0do4VUKUfT151Fte3P7fs6AXDcc57twIT+Me2XL2L/dlIdxV8mOruN0YhkF4w9yZ4oxqrJlhy/VXRstNg4GZs/hmNjukEh3ci2TmuJat2KO7sCm/kmx8MOinhkohIwGngSo3PfHMYVZOcxXtnGWGYgpyv4SZAdCjZg8dPtgIUvJ5yqdZJtS+drDsknUMA32LdhzJKI8ZVgJA6RvoBpY1xGthiZORD4yYIiE8M4SbIDaX5o7lws4GWcIGacunEDF3yJKflvqP4o+1rGLMtOYPw1ML4cEASeEkfvvl8Qo4Gfj6X7/DdJmQbZAZ9BmRNQxOsIwX4XBVzBhR+Ei6tkG4IyjNxb38fqxwqKzLpOHLTtRRrwqnWmYYpx71WOcaYJmld+roG5BuYamGtgroG5BuYamJoG/h/ff6XOIB4wOAAAAABJRU5ErkJggg=="/>
<style>
body, div, header, footer {
@@ -264,8 +264,8 @@ func GetNotFoundErrorPage() string {
display: block;
margin: 0 auto;
/* width: 50%; */
- min-height: 60vh;
- max-height: 60vh;
+ min-height: 60vh;
+ max-height: 60vh;
padding: 50px 20px;
opacity: 0.6;
background-color: #A9F5BF;
@@ -329,7 +329,7 @@ func GetNotFoundErrorPage() string {
<table>
<thead>
<td style="height: 150px; font-size: 1.3em; color: black; font-weight: bold">
- Unfortunately, the resource you were trying to access could not be found on swarm.
+ Unfortunately, the resource you were trying to access could not be found on swarm.
</td>
</thead>
<tbody>
@@ -388,7 +388,7 @@ func GetMultipleChoicesErrorPage() string {
<meta http-equiv="X-UA-Compatible" ww="chrome=1">
<meta name="description" content="Ethereum/Swarm multiple options page">
<meta property="og:url" content="https://swarm-gateways.net/bzz:/theswarm.eth">
-
+ <link rel="shortcut icon" type="image/x-icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHsAAAB5CAYAAAAZD150AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KTMInWQAAFzFJREFUeAHtnXuwJFV9x7vnzrKwIC95w/ImYFkxlZgiGswCIiCGxPhHCEIwmIemUqYwJkYrJmXlUZRa+IpAWYYEk4qJD4gJGAmoiBIxMQFRQCkXdhdCeL+fYdk7nc+ne87dvnPn0TPTPdNzmd/W2X6fc76/7/n9zjm/PrcniuYy18BcA3MNzDUw18BcA3MNzDUw18BcA3MNrGYNLERroyMAeNQ0QcbTLPxFUfaOOx4Wbd12ThRHp0TJ4s5RFF8RtVoXg/2BSeOfk12lxtc0fjva1jibItZEDf4li3u3i3sqipOPRIvRp6ssvjPvhc4Tq/y4Ab71pEXS1oqw7hw1mz8XJc2LoiQ6iTJaaTkxth0l69jXwNayOZ10AvubSQ+RrFOl8mKy7EOiRuN3UfjrUfItUaN1SbQt+lqp2m02T4payS9HSfxK8k1IGdEWkln2Xuzldd7keBunrsO1f4r9b5Mqk3zBlRUy9Ywb0TtQ6O9Tjx1JkvA8SSXfiJK5Fj1MGkf2jBYWzo9a8Y+TiQRaxnLpTnb+HuvzDerzLk4+mb9Q1v5qduPrUPvxURx/DiWeicK2W1lKdCT2Q7n+VqzuOei5m+Nnh1TsPtGahbOiaOFCrHn/vs8ud+PdbrWLOZr6vIX6PEF97uH4uW43jnpudVp2Mzo1ajV+AwPbgGJUYr4/1Or+jxSwu90R5f6QQdPnaBK603zD4LCLNJsnkusfcUXXrKfoL4MtOzxvfXegPrdGjeRjlHEVx4PrE57us11tlr0b/fKlKIq+OTqsjXulS80sO5Dtbdugfnf4Py5qxGenxEeppbez6LJpte6LFuIWlvhT3J/Pq8vNnBps2eE562t97A608G+xnZMdtMN2H+z3LSj+n9g3cNGN4Nzt9tddCZK0ncnnrChuHBElySaOH8k/mNtf5Pr3onWtL0WthfWUuA/XGGX3KHsw2ZYtqc9Rs4dIW2m4mxjwXd8+z2Y8mXXLXoDk38Eaz4c7+2VJzLvsXtrpRXa43+svh/TTIf1QSP0Rx0+Ei8u2L0RPM6i6hn77e9SFhsJzGWnLG9wgshvpeOEJnn+6nX+D8u+ck51p43hIvhyS38DhHiQJKiqDyDYfG42WeiAk3oO93uLJ3tK6P0pa1zK/vj5aSI6FtF15Zjvhvcle5F69xzMkywxdAk+US7aDgVmSbMTaaFwM0VdS8QNIQTll4TA/SdKd3kvS0oqWgRveeku0uO2NjM4v5TmDJda52/MSqyXfy3YrqXJxEDArcjB92Dvh4RdIjoC1hLJFUp6BAPMOBHQjalC5SdR6wfj3FVFjDV1Bcg698S7ka172y0+3y5DwiRncxAoC1OjSiN6LJTNQSd5MJruQnDqVLbrTB0mPkXEgetwy7oH0T2LppzOrv4bMnif/B0hPsS/pozSkketUZ8s2KPIq3OH5ONWjQVgFwSpO69KajVpVpfzHom3b3hctNHajwR5OOUbyLGt7n85B1VJPspvRydFi/Hba/gYUoFLKJlqPpmXx9ikdBRcZsHH7WLIjZT1F472TXHaFZ6dqO5Gsx0SkbmTvS7/8caYbG1CMJGt1Vciz5O5UKuRflUV31t1yJPdx2jDlp2MPw6wTsfA6ke1U47Pg1mVXqfwXyP1Bypg2dgiOXcDwKJgPZPsSknGPyoiv0wAtZlz6CERsAXB4v1tV/apsTFS/sIgP7xLfTdrMPhbfc6pWONNeN1alzF7lDTqfuTkHS3F0FzcbbHixCG/cUtLvAHBZs4Fluqsb2fnK+XpBS6fVp4Mo+7q6WGS+nmXvE8SJf0imDxKGlfTS3Pq0+61BipJc+9j7gOzI1bCoS3tKUwB51U3st9cwar+Kgeq/sR8GkWPXs+5kbwcYpy/yXWQg2U5brPtqI905yEPRttbfgm0jqVSZHbID7CyUeRc078kpo2lrSFWSbt6lWRd5dYreizdcLI1K4m9F2xa/zHEleGaP7Kzftj933ZgDuZcwc9W9q7QylWRevLeKd+d/lgMnt3I84M0XdwwnNlQCRvHVkOwiBaZh1ckskh20kfXnCQpKI1Opa9fFlxWRWsvSpoPIex1pbxIWxyvVVuv9lGFAZlxp0ohc8PgZMqpkgWFnBWeZ7DwWB3H/g/IMTGjlvoceRbDmBuu/kj2waBf0x9o2/ysvYN1n8ELmtbzFugDHrrsddlWqgy/z3Bw1WeGyNbrNjCclFl4XIagSn0Fl7IdHEQc3W0nh9aQvG2zMna7dt1sheBHK8R5IiPdlcwBbYtc5iZdWwNh3MyuITyFtIN7F0qTCrp0GGB8TLbQuixaTf+HJ+3MlTGQ3a7MTKWpgIQ0W8H2Bu1B4KaIFaeW7k/I4bRBbOBcauv0yHiE+iPvDOS7nJE7oV00rRFd8O57gPK78YMXV5Sesg3GNKgd7y0vsOKpzUKWjqkMfZoM43Xu20CGz3nw2TuOSxqGQfVhPovP3r9x3FejReKSv8gLnQ1w+ZuUtS2csf2pEW4vuLXmpfhPdGdeNd6us1sRy33RlyHPs69bXsIjwWQjGktN+WXff6eo5lZPMjfda4xZI/Ele5JxK3jSc5Cae7uYJcplOfjfv3iZf+vISy3bjy3PffkQ/2zgaeosP4nq78e25bt9Tp48S/TqZba1i+6tlNL5d1Sv3Mut23VcUP8hlRu4t57YOxPbhWNL7W/bKPHud0fpd9eJfiNSui1ztZKtw5rCxUyTduKTuQMK1J3eRHoBwR+Au8ldGIT00JgM8z5KH/XIt9VrLSqn1EgSlx/eQj4v7guS7LfdZAJjcDcf3YYjHQLVTrmEJd9WLixTDc/kyQrm12K42slU0wQ8jXLELIIq+FtW138zgah8oO5DkXN+8AoHsLhPPO4WzITkQqy3B+VqvFrKDsiE4NmDie2DPhfN5zL32mZm0HuaJx0l7ECo9hBs7FwSanyQb3rRfLtqYuHX6slrIJmoW/y/qDNOjYUjOs+Bz9rkP82UG30IdSjogd4MNgYHekoxazlIGk9yZdbIZdMX2l1pz+YqPkzvo0/kbrnivNskzZcmdDWkWyXaEjZtOp1H2mVpi+URnmlI//M1XYhRuDclpmttefTmX6iuzSDZz5XTwFbRaFdGd+dtFmCTbvrzqcimiXJkFslWq1mu/bFDEgdE0Fe1oX9K1cufs06wLxReXupPdLShSB+Xqxp1yOeqX8MHxdW6attSZbIMi9pX2y4HgsJ223kL5DtgC6evYr9OLpVDHpW3dyNaS80ERLahuBC8pL7cj6TZKrVz3rl5rV+86kU28Or6Tce56FOUaL5VVO4VRp15iXXXriqtlbLS1knq5nVZyDV8KJDqVuAhAK69CxGw4tIrpkx+9uZFlR39A/s7/ayV1tZyXQvovwcdPoC0XEYbIWBnKY+qU8KYrDXWWkZ+NR690G/H1L2DP3ykj0yryqCvZAavfUTkNZ34cJ3SRZVhjmWQzKIs3QvKlNMfvUj8Ha7WVupMdFHdU1Gy8DapdQDgu4WWRjbdJ/oEIwGXUyThA7aUOfbarPwdZhMt8voJr541T+rUCnxmV9HH6bAe0z7DG7N9x3H9BDXTZReqxJ/e5eGKqMk2y/bq+X0F6P256X1T2X2iiv4W0WndA+k2QzouP5Cjux0oLKTuv5FHIdrC4EyRfB8kfpcR/5dgR9yDxC4zvaWPcv42xzPHHoPKXXZ+OG1+ITuNN0gXUZD+SS3lcAcr3OpN30/ddx3ERa/GjtOfy3CvS5/mvoIzgxvkcxkLrI4wa/HuvYpJ+GTn+MDeLUc/lHyeI8b1g/BrHRTByW3kyabJfA0HvAOepQHDAZTDClm7SehzwXM3fP13E/rdJReRl5MmH5ZbWbJtnPylCtnrBZcd3UcVroOlyjgflG8rky8bpLxbkMeqxnHdnHiJinXmrdSHHN4SHJrGdFNmHo4A/h+RXA8p1XvmAQyA74NXNYu3xDSiEZ9Lf0AjXem13IHZ1DKtLzsBeDuYmX5b0kkFk2zXwfPIZSP4q+w/3yqjjvBj/lOd+lvNiFFeQQHY4Dhj/A4x/xslN4UKV26rJXktbfifEkbA9NNEFTCfZ+Vt4JrkYm9LSi/SRMf35aTxzOvdLWjfpRzZ/MpT8J+V9nAcZFxSSHcB4HvB+j7u13G4YO8nOZyzGT1LmJzhZBGP+2aH2bWFVyDpeCZxJoOFvUMIbKSBvyZ3l6R5NPST268M/jxr96sIWbgohye73J8lGCLsBK/Odc7d14WLehRRI8djI1818uf9CrPmzHA+aHXALXc5C9Cs8dwkY38RxP4yW1Q/jBjCeXhijpY8g5Vv2QgS58btR5eHUR0X2AZnWuJ9lB0iZxSTRj/i884dxkFeHCwO2B0H6L+JT7D7CGCFv2by4iLew3uxTUHUL9xQhWVR4jvgPwXgkzxTB2M+yA4SAcSMYLxgCY3h+4LYssq3oelr5BSj2BPbz/dWgShQhO58HFht/k77uPZzcQgoWmr+nc//HCMqcy517cWEtj2jxkJ98Hkv+R/YHNUjzU1fraTwf4rmT2B8GYxGyLSMIf3AYXY+HEuNmUpH6hWd7bssg24HJuSjgNynFl/j9BkfdKjIs2eZhf4wVJn+HGiRroycHyAI/rgZJrdfQUB7jub/nfteWF5FD2xh/i5vtHobFOCzZ1mkUjD7XU8YjuxH9CQ3+zeSuxdj6ilhZZ2VGIds8rPsC/7P6M+HzF9EHOS5S/s7cZzSrmLU0/IUffiQm4lMbo2MchWyKW4bxi9T4A+06eG1oGYXsHZiBnsgPlv0lpRkGHMaddavgqGTn86LvxUobvFrcFn2dfZU7jqwB4/FgdIRsQx4X46hk5zEEjAaeruXC0BiHI7tJf9xqvB0Dej2FhQFPvkKj7JdBtuU6bqA/jr/CgOuvUch1nhxaMoxvA+NpPFsWxjLIFop8OWbhj//Tn5e0YReWomTzoyiNC1CAo1qiXMO3qj41KovsUISjY+ar8U30zX/M/uZwYcB2PzAS3kyDIrr6oS2nT/5lkR2KCBhvBuP7OLkpXOi39aF+sgv28i5G2Q6C1pO8v0i/2C/Pzmv2ncX6z84nux9bP0KdRNLi+NexhRY1vpXjXvNgMZ7HvZ9Pn8meLRuj+VWB0RnQW8Ho92O+3wcjlzK3kO50+Y8fMIk/TTYncc3RZ9kKCEWWbdkhX7d6Lqcx32EQ5yDrCU/mZB3WfAnQ3sA559hVYSzbsnMQUoy8keObaklyJheezF/M79vP9ZImLd7R7kZueJrU795eeUzzvET7c02bqLnTGLufTmlynegZwZpsdeisYtycctUd4xJm3V0vCa7HD8r5VWBbjNOPfs/0ymvS531l+hiFOsWSdLH0slrdqxiZwqXLgWcHo/H77GsPASNQektR4uwVGPTwNipJvyvmWx2nAr0U2LvE6q4I2H7ZLyG4htu6ea6orHqMRclWYZnisq8D8is26apP56BKHUgPrTwMhIYhOkOxyjEOQ3ZQiFtXXegmn4TmfdkaQhxFuTw2tvglhEfJpcypkpUSo685/Vnj/djOPMZRyVYZkmvfeC/KcF66G8ntJKzcsh09+xkqlzVV2dD8UmLAuDtlBdKrxlk6xnHIBncq9nUq3PfNKsI3SuZbhTJUgJ+Q1OLCdLBKoikmlU6MDuIc4c8UxjLIztQh8Iz0zewZM9cKypzK2BdryT3nkaEiFW4Dxi2ziLFMsoOOtQL70KdRiIS7KmTUyJtWK8mOsJ3rG6suswGR3UiSx2j35Z8olYXRGUUl3qoKstWelXXu+hDbxyH9pWzzS4E4HCiSGn5G0SibUgeis5psx/gwJxzE6c2ckobZQLiv39YGorcyshcwVkK0laiKbPMOEoIyRrBCfx6u9do6ElaJDsIqA9+r8BHOZ0GZjHRnJ0X0OnGMRSo1AvYVj4QBzl1YgG7PxOvIZVaQeYOspRvA0UJmgWiqmYp1NTxbW4yTIlttZMRlLsv+XLduUCYQ6odeJTnMl8N5Ts2MDML4BBiduUwF4yTJzjOmC7OfykjPwpsqYBYJzuPK79cO4zTIDoQyuuZ7ZrEx9sRRu7H2adQnT1BZ+3mMfg+VgVjiAG6qGCetXJXA9Cm+n63ujBFo4opUpxuORh2dGpgZdRrDo1OXLhjTvysXo8lgjJgnjnGSZBttYoTd8+uEXpdw31ipDK0gWAi7MyEOKokx9MQoiED6xDFWTbZk2RfTP6df8y8aFPE9tEqRcFOdRYySTAg3foStYdwi8QAxqg9nJRPBWCXZAlYBD7KVOKWIErwvNJKgEK2gqli05Y0q4rEhP8B2FIw2koAxkF5FvD3FVxXZAI/vowRDnOO6Yj2D+Ui2/XnRBsOtlUrZGJ12aumVYSyTbEnVhT0Gv8bGbaHjEk0WqZiP/bmkB9c+8QEOZecxgrPUwE/A6JglWHmpGMsgOxCKu05J1jUp4Xx2VM7/NiAblBYg6br3SYhYLFuMklx1UKQSjOOSrQKcL+uy7bOqIJhsV4jlGje3zNCfr7ippBPTxhhcu93YWDIK2YFQ3E1qyaFfDufHqtAQD1ueXsT5ujh0fWUO4sy/DhhtbPbnYhsL47BkqwBaWmrJKtmKTJpkilwh9ue6Vvu4cQc44nHwdS/bumC0TmNjHIZslZkPGNSBZKq0JDa8cYMyAaOvV+vSkJcAtus0MsZBZDvN0VWGEbb9R91IpkorJMxdHcTp+vqJeCTWhuwsImCsO85hMKb4B5Ad21c4FXB0qNRdAVkts3raSB3EBfLCtc4trjrexMlZxzgw/mAf10ue5w/FbuWP+w6EYt89D8ysV0YDztvHjj3S7FKGDRPC+XBdI/kAe3d2uUeMt08AY4iDd6nCWKfaXim+u43xjn65FbHUBmPdV/FH+K+D9CPITEspS3Cf6as/CS9LxMQSqJiG2voivfjXOdbK+0nAeBIYj+TGkjG68DJxTX1ZEjD6jfOA0fFGXylCdsiAT080j4uS1tmc0CMMzDw82GdbNtl6H9aD8aG87MsLuvFhxE+IvJofU/9VHioRY6lki5HGyIfyFtOGXBjjMGQHpe3EVwTPobBXcEKLHGQ14blu27LIVgH8kUJyI7W5kH1XwYwjYoTwFCNeYlyMpZAdMPJFiRQjL5mGk1HIDiUchUJORCHHcsJ8RiF9XLJVwAIkX4tFXkl7vy1UrqTtkW2MP0N+Y2Aci2wxNtsYrxgH4zhkq09d3SHtr/zvx77hy2FkHLKZVjH4Wmx9kAI3kcroVrrVXYwHtzHuz/4IGEcmm2ljvKWNcTNlO8ceWcYle3vBzeapGPfJzFgZjKQCkQNlWLLb9XWRQOufoffygSWUeUOzeQrlngLG3cjWuhTEOBTZASNz/hTjZWVBKI/srEZ74PY2MEA6ETW4wC7MXXvVdxiytWQV8CVIvpoMeQM1Fdm9jfG1xTEWJpspqG/VUozXgO6BMhGWTbZ1M8/dUMibaPgb2O/neoqQbX7+ZMNVjAr+in0HJkUsitsqE+u0axvj8ewPwDiQbPPjQz/Jl8F4Cfu+Ri0do4VUKUfT151Fte3P7fs6AXDcc57twIT+Me2XL2L/dlIdxV8mOruN0YhkF4w9yZ4oxqrJlhy/VXRstNg4GZs/hmNjukEh3ci2TmuJat2KO7sCm/kmx8MOinhkohIwGngSo3PfHMYVZOcxXtnGWGYgpyv4SZAdCjZg8dPtgIUvJ5yqdZJtS+drDsknUMA32LdhzJKI8ZVgJA6RvoBpY1xGthiZORD4yYIiE8M4SbIDaX5o7lws4GWcIGacunEDF3yJKflvqP4o+1rGLMtOYPw1ML4cEASeEkfvvl8Qo4Gfj6X7/DdJmQbZAZ9BmRNQxOsIwX4XBVzBhR+Ei6tkG4IyjNxb38fqxwqKzLpOHLTtRRrwqnWmYYpx71WOcaYJmld+roG5BuYamGtgroG5BuYamJoG/h/ff6XOIB4wOAAAAABJRU5ErkJggg=="/>
<style>
body, div, header, footer {
@@ -440,8 +440,8 @@ func GetMultipleChoicesErrorPage() string {
display: block;
margin: 0 auto;
/* width: 50%; */
- min-height: 60vh;
- max-height: 60vh;
+ min-height: 60vh;
+ max-height: 60vh;
padding: 50px 20px;
opacity: 0.6;
background-color: #A9F5BF;
diff --git a/swarm/api/http/error_test.go b/swarm/api/http/error_test.go
index ed52bafbd..c2c8b908b 100644
--- a/swarm/api/http/error_test.go
+++ b/swarm/api/http/error_test.go
@@ -1,4 +1,4 @@
-// Copyright 2016 The go-ethereum Authors
+// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
diff --git a/swarm/api/http/server_test.go b/swarm/api/http/server_test.go
index 305d5cf7d..b2efc0ea1 100644
--- a/swarm/api/http/server_test.go
+++ b/swarm/api/http/server_test.go
@@ -144,17 +144,17 @@ func TestBzzGetPath(t *testing.T) {
{
path: "/",
json: `{"common_prefixes":["a/"]}`,
- html: "<!DOCTYPE html>\n<html>\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>Swarm index of bzz:/262e5c08c03c2789b6daef487dfa14b4d132f5340d781a3ecb1d5122ab65640c/</title>\n</head>\n\n<body>\n <h1>Swarm index of bzz:/262e5c08c03c2789b6daef487dfa14b4d132f5340d781a3ecb1d5122ab65640c/</h1>\n <hr>\n <table>\n <thead>\n <tr>\n\t<th>Path</th>\n\t<th>Type</th>\n\t<th>Size</th>\n </tr>\n </thead>\n\n <tbody>\n \n\t<tr>\n\t <td><a href=\"a/\">a/</a></td>\n\t <td>DIR</td>\n\t <td>-</td>\n\t</tr>\n \n\n \n </table>\n <hr>\n</body>\n",
+ html: "<!DOCTYPE html>\n<html>\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\t\t<link rel=\"shortcut icon\" type=\"image/x-icon\" href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHsAAAB5CAYAAAAZD150AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KTMInWQAAFzFJREFUeAHtnXuwJFV9x7vnzrKwIC95w/ImYFkxlZgiGswCIiCGxPhHCEIwmIemUqYwJkYrJmXlUZRa+IpAWYYEk4qJD4gJGAmoiBIxMQFRQCkXdhdCeL+fYdk7nc+ne87dvnPn0TPTPdNzmd/W2X6fc76/7/n9zjm/PrcniuYy18BcA3MNzDUw18BcA3MNzDUw18BcA3MNrGYNLERroyMAeNQ0QcbTLPxFUfaOOx4Wbd12ThRHp0TJ4s5RFF8RtVoXg/2BSeOfk12lxtc0fjva1jibItZEDf4li3u3i3sqipOPRIvRp6ssvjPvhc4Tq/y4Ab71pEXS1oqw7hw1mz8XJc2LoiQ6iTJaaTkxth0l69jXwNayOZ10AvubSQ+RrFOl8mKy7EOiRuN3UfjrUfItUaN1SbQt+lqp2m02T4payS9HSfxK8k1IGdEWkln2Xuzldd7keBunrsO1f4r9b5Mqk3zBlRUy9Ywb0TtQ6O9Tjx1JkvA8SSXfiJK5Fj1MGkf2jBYWzo9a8Y+TiQRaxnLpTnb+HuvzDerzLk4+mb9Q1v5qduPrUPvxURx/DiWeicK2W1lKdCT2Q7n+VqzuOei5m+Nnh1TsPtGahbOiaOFCrHn/vs8ud+PdbrWLOZr6vIX6PEF97uH4uW43jnpudVp2Mzo1ajV+AwPbgGJUYr4/1Or+jxSwu90R5f6QQdPnaBK603zD4LCLNJsnkusfcUXXrKfoL4MtOzxvfXegPrdGjeRjlHEVx4PrE57us11tlr0b/fKlKIq+OTqsjXulS80sO5Dtbdugfnf4Py5qxGenxEeppbez6LJpte6LFuIWlvhT3J/Pq8vNnBps2eE562t97A608G+xnZMdtMN2H+z3LSj+n9g3cNGN4Nzt9tddCZK0ncnnrChuHBElySaOH8k/mNtf5Pr3onWtL0WthfWUuA/XGGX3KHsw2ZYtqc9Rs4dIW2m4mxjwXd8+z2Y8mXXLXoDk38Eaz4c7+2VJzLvsXtrpRXa43+svh/TTIf1QSP0Rx0+Ei8u2L0RPM6i6hn77e9SFhsJzGWnLG9wgshvpeOEJnn+6nX+D8u+ck51p43hIvhyS38DhHiQJKiqDyDYfG42WeiAk3oO93uLJ3tK6P0pa1zK/vj5aSI6FtF15Zjvhvcle5F69xzMkywxdAk+US7aDgVmSbMTaaFwM0VdS8QNIQTll4TA/SdKd3kvS0oqWgRveeku0uO2NjM4v5TmDJda52/MSqyXfy3YrqXJxEDArcjB92Dvh4RdIjoC1hLJFUp6BAPMOBHQjalC5SdR6wfj3FVFjDV1Bcg698S7ka172y0+3y5DwiRncxAoC1OjSiN6LJTNQSd5MJruQnDqVLbrTB0mPkXEgetwy7oH0T2LppzOrv4bMnif/B0hPsS/pozSkketUZ8s2KPIq3OH5ONWjQVgFwSpO69KajVpVpfzHom3b3hctNHajwR5OOUbyLGt7n85B1VJPspvRydFi/Hba/gYUoFLKJlqPpmXx9ikdBRcZsHH7WLIjZT1F472TXHaFZ6dqO5Gsx0SkbmTvS7/8caYbG1CMJGt1Vciz5O5UKuRflUV31t1yJPdx2jDlp2MPw6wTsfA6ke1U47Pg1mVXqfwXyP1Bypg2dgiOXcDwKJgPZPsSknGPyoiv0wAtZlz6CERsAXB4v1tV/apsTFS/sIgP7xLfTdrMPhbfc6pWONNeN1alzF7lDTqfuTkHS3F0FzcbbHixCG/cUtLvAHBZs4Fluqsb2fnK+XpBS6fVp4Mo+7q6WGS+nmXvE8SJf0imDxKGlfTS3Pq0+61BipJc+9j7gOzI1bCoS3tKUwB51U3st9cwar+Kgeq/sR8GkWPXs+5kbwcYpy/yXWQg2U5brPtqI905yEPRttbfgm0jqVSZHbID7CyUeRc078kpo2lrSFWSbt6lWRd5dYreizdcLI1K4m9F2xa/zHEleGaP7Kzftj933ZgDuZcwc9W9q7QylWRevLeKd+d/lgMnt3I84M0XdwwnNlQCRvHVkOwiBaZh1ckskh20kfXnCQpKI1Opa9fFlxWRWsvSpoPIex1pbxIWxyvVVuv9lGFAZlxp0ohc8PgZMqpkgWFnBWeZ7DwWB3H/g/IMTGjlvoceRbDmBuu/kj2waBf0x9o2/ysvYN1n8ELmtbzFugDHrrsddlWqgy/z3Bw1WeGyNbrNjCclFl4XIagSn0Fl7IdHEQc3W0nh9aQvG2zMna7dt1sheBHK8R5IiPdlcwBbYtc5iZdWwNh3MyuITyFtIN7F0qTCrp0GGB8TLbQuixaTf+HJ+3MlTGQ3a7MTKWpgIQ0W8H2Bu1B4KaIFaeW7k/I4bRBbOBcauv0yHiE+iPvDOS7nJE7oV00rRFd8O57gPK78YMXV5Sesg3GNKgd7y0vsOKpzUKWjqkMfZoM43Xu20CGz3nw2TuOSxqGQfVhPovP3r9x3FejReKSv8gLnQ1w+ZuUtS2csf2pEW4vuLXmpfhPdGdeNd6us1sRy33RlyHPs69bXsIjwWQjGktN+WXff6eo5lZPMjfda4xZI/Ele5JxK3jSc5Cae7uYJcplOfjfv3iZf+vISy3bjy3PffkQ/2zgaeosP4nq78e25bt9Tp48S/TqZba1i+6tlNL5d1Sv3Mut23VcUP8hlRu4t57YOxPbhWNL7W/bKPHud0fpd9eJfiNSui1ztZKtw5rCxUyTduKTuQMK1J3eRHoBwR+Au8ldGIT00JgM8z5KH/XIt9VrLSqn1EgSlx/eQj4v7guS7LfdZAJjcDcf3YYjHQLVTrmEJd9WLixTDc/kyQrm12K42slU0wQ8jXLELIIq+FtW138zgah8oO5DkXN+8AoHsLhPPO4WzITkQqy3B+VqvFrKDsiE4NmDie2DPhfN5zL32mZm0HuaJx0l7ECo9hBs7FwSanyQb3rRfLtqYuHX6slrIJmoW/y/qDNOjYUjOs+Bz9rkP82UG30IdSjogd4MNgYHekoxazlIGk9yZdbIZdMX2l1pz+YqPkzvo0/kbrnivNskzZcmdDWkWyXaEjZtOp1H2mVpi+URnmlI//M1XYhRuDclpmttefTmX6iuzSDZz5XTwFbRaFdGd+dtFmCTbvrzqcimiXJkFslWq1mu/bFDEgdE0Fe1oX9K1cufs06wLxReXupPdLShSB+Xqxp1yOeqX8MHxdW6attSZbIMi9pX2y4HgsJ223kL5DtgC6evYr9OLpVDHpW3dyNaS80ERLahuBC8pL7cj6TZKrVz3rl5rV+86kU28Or6Tce56FOUaL5VVO4VRp15iXXXriqtlbLS1knq5nVZyDV8KJDqVuAhAK69CxGw4tIrpkx+9uZFlR39A/s7/ayV1tZyXQvovwcdPoC0XEYbIWBnKY+qU8KYrDXWWkZ+NR690G/H1L2DP3ykj0yryqCvZAavfUTkNZ34cJ3SRZVhjmWQzKIs3QvKlNMfvUj8Ha7WVupMdFHdU1Gy8DapdQDgu4WWRjbdJ/oEIwGXUyThA7aUOfbarPwdZhMt8voJr541T+rUCnxmV9HH6bAe0z7DG7N9x3H9BDXTZReqxJ/e5eGKqMk2y/bq+X0F6P256X1T2X2iiv4W0WndA+k2QzouP5Cjux0oLKTuv5FHIdrC4EyRfB8kfpcR/5dgR9yDxC4zvaWPcv42xzPHHoPKXXZ+OG1+ITuNN0gXUZD+SS3lcAcr3OpN30/ddx3ERa/GjtOfy3CvS5/mvoIzgxvkcxkLrI4wa/HuvYpJ+GTn+MDeLUc/lHyeI8b1g/BrHRTByW3kyabJfA0HvAOepQHDAZTDClm7SehzwXM3fP13E/rdJReRl5MmH5ZbWbJtnPylCtnrBZcd3UcVroOlyjgflG8rky8bpLxbkMeqxnHdnHiJinXmrdSHHN4SHJrGdFNmHo4A/h+RXA8p1XvmAQyA74NXNYu3xDSiEZ9Lf0AjXem13IHZ1DKtLzsBeDuYmX5b0kkFk2zXwfPIZSP4q+w/3yqjjvBj/lOd+lvNiFFeQQHY4Dhj/A4x/xslN4UKV26rJXktbfifEkbA9NNEFTCfZ+Vt4JrkYm9LSi/SRMf35aTxzOvdLWjfpRzZ/MpT8J+V9nAcZFxSSHcB4HvB+j7u13G4YO8nOZyzGT1LmJzhZBGP+2aH2bWFVyDpeCZxJoOFvUMIbKSBvyZ3l6R5NPST268M/jxr96sIWbgohye73J8lGCLsBK/Odc7d14WLehRRI8djI1818uf9CrPmzHA+aHXALXc5C9Cs8dwkY38RxP4yW1Q/jBjCeXhijpY8g5Vv2QgS58btR5eHUR0X2AZnWuJ9lB0iZxSTRj/i884dxkFeHCwO2B0H6L+JT7D7CGCFv2by4iLew3uxTUHUL9xQhWVR4jvgPwXgkzxTB2M+yA4SAcSMYLxgCY3h+4LYssq3oelr5BSj2BPbz/dWgShQhO58HFht/k77uPZzcQgoWmr+nc//HCMqcy517cWEtj2jxkJ98Hkv+R/YHNUjzU1fraTwf4rmT2B8GYxGyLSMIf3AYXY+HEuNmUpH6hWd7bssg24HJuSjgNynFl/j9BkfdKjIs2eZhf4wVJn+HGiRroycHyAI/rgZJrdfQUB7jub/nfteWF5FD2xh/i5vtHobFOCzZ1mkUjD7XU8YjuxH9CQ3+zeSuxdj6ilhZZ2VGIds8rPsC/7P6M+HzF9EHOS5S/s7cZzSrmLU0/IUffiQm4lMbo2MchWyKW4bxi9T4A+06eG1oGYXsHZiBnsgPlv0lpRkGHMaddavgqGTn86LvxUobvFrcFn2dfZU7jqwB4/FgdIRsQx4X46hk5zEEjAaeruXC0BiHI7tJf9xqvB0Dej2FhQFPvkKj7JdBtuU6bqA/jr/CgOuvUch1nhxaMoxvA+NpPFsWxjLIFop8OWbhj//Tn5e0YReWomTzoyiNC1CAo1qiXMO3qj41KovsUISjY+ar8U30zX/M/uZwYcB2PzAS3kyDIrr6oS2nT/5lkR2KCBhvBuP7OLkpXOi39aF+sgv28i5G2Q6C1pO8v0i/2C/Pzmv2ncX6z84nux9bP0KdRNLi+NexhRY1vpXjXvNgMZ7HvZ9Pn8meLRuj+VWB0RnQW8Ho92O+3wcjlzK3kO50+Y8fMIk/TTYncc3RZ9kKCEWWbdkhX7d6Lqcx32EQ5yDrCU/mZB3WfAnQ3sA559hVYSzbsnMQUoy8keObaklyJheezF/M79vP9ZImLd7R7kZueJrU795eeUzzvET7c02bqLnTGLufTmlynegZwZpsdeisYtycctUd4xJm3V0vCa7HD8r5VWBbjNOPfs/0ymvS531l+hiFOsWSdLH0slrdqxiZwqXLgWcHo/H77GsPASNQektR4uwVGPTwNipJvyvmWx2nAr0U2LvE6q4I2H7ZLyG4htu6ea6orHqMRclWYZnisq8D8is26apP56BKHUgPrTwMhIYhOkOxyjEOQ3ZQiFtXXegmn4TmfdkaQhxFuTw2tvglhEfJpcypkpUSo685/Vnj/djOPMZRyVYZkmvfeC/KcF66G8ntJKzcsh09+xkqlzVV2dD8UmLAuDtlBdKrxlk6xnHIBncq9nUq3PfNKsI3SuZbhTJUgJ+Q1OLCdLBKoikmlU6MDuIc4c8UxjLIztQh8Iz0zewZM9cKypzK2BdryT3nkaEiFW4Dxi2ziLFMsoOOtQL70KdRiIS7KmTUyJtWK8mOsJ3rG6suswGR3UiSx2j35Z8olYXRGUUl3qoKstWelXXu+hDbxyH9pWzzS4E4HCiSGn5G0SibUgeis5psx/gwJxzE6c2ckobZQLiv39YGorcyshcwVkK0laiKbPMOEoIyRrBCfx6u9do6ElaJDsIqA9+r8BHOZ0GZjHRnJ0X0OnGMRSo1AvYVj4QBzl1YgG7PxOvIZVaQeYOspRvA0UJmgWiqmYp1NTxbW4yTIlttZMRlLsv+XLduUCYQ6odeJTnMl8N5Ts2MDML4BBiduUwF4yTJzjOmC7OfykjPwpsqYBYJzuPK79cO4zTIDoQyuuZ7ZrEx9sRRu7H2adQnT1BZ+3mMfg+VgVjiAG6qGCetXJXA9Cm+n63ujBFo4opUpxuORh2dGpgZdRrDo1OXLhjTvysXo8lgjJgnjnGSZBttYoTd8+uEXpdw31ipDK0gWAi7MyEOKokx9MQoiED6xDFWTbZk2RfTP6df8y8aFPE9tEqRcFOdRYySTAg3foStYdwi8QAxqg9nJRPBWCXZAlYBD7KVOKWIErwvNJKgEK2gqli05Y0q4rEhP8B2FIw2koAxkF5FvD3FVxXZAI/vowRDnOO6Yj2D+Ui2/XnRBsOtlUrZGJ12aumVYSyTbEnVhT0Gv8bGbaHjEk0WqZiP/bmkB9c+8QEOZecxgrPUwE/A6JglWHmpGMsgOxCKu05J1jUp4Xx2VM7/NiAblBYg6br3SYhYLFuMklx1UKQSjOOSrQKcL+uy7bOqIJhsV4jlGje3zNCfr7ippBPTxhhcu93YWDIK2YFQ3E1qyaFfDufHqtAQD1ueXsT5ujh0fWUO4sy/DhhtbPbnYhsL47BkqwBaWmrJKtmKTJpkilwh9ue6Vvu4cQc44nHwdS/bumC0TmNjHIZslZkPGNSBZKq0JDa8cYMyAaOvV+vSkJcAtus0MsZBZDvN0VWGEbb9R91IpkorJMxdHcTp+vqJeCTWhuwsImCsO85hMKb4B5Ad21c4FXB0qNRdAVkts3raSB3EBfLCtc4trjrexMlZxzgw/mAf10ue5w/FbuWP+w6EYt89D8ysV0YDztvHjj3S7FKGDRPC+XBdI/kAe3d2uUeMt08AY4iDd6nCWKfaXim+u43xjn65FbHUBmPdV/FH+K+D9CPITEspS3Cf6as/CS9LxMQSqJiG2voivfjXOdbK+0nAeBIYj+TGkjG68DJxTX1ZEjD6jfOA0fFGXylCdsiAT080j4uS1tmc0CMMzDw82GdbNtl6H9aD8aG87MsLuvFhxE+IvJofU/9VHioRY6lki5HGyIfyFtOGXBjjMGQHpe3EVwTPobBXcEKLHGQ14blu27LIVgH8kUJyI7W5kH1XwYwjYoTwFCNeYlyMpZAdMPJFiRQjL5mGk1HIDiUchUJORCHHcsJ8RiF9XLJVwAIkX4tFXkl7vy1UrqTtkW2MP0N+Y2Aci2wxNtsYrxgH4zhkq09d3SHtr/zvx77hy2FkHLKZVjH4Wmx9kAI3kcroVrrVXYwHtzHuz/4IGEcmm2ljvKWNcTNlO8ceWcYle3vBzeapGPfJzFgZjKQCkQNlWLLb9XWRQOufoffygSWUeUOzeQrlngLG3cjWuhTEOBTZASNz/hTjZWVBKI/srEZ74PY2MEA6ETW4wC7MXXvVdxiytWQV8CVIvpoMeQM1Fdm9jfG1xTEWJpspqG/VUozXgO6BMhGWTbZ1M8/dUMibaPgb2O/neoqQbX7+ZMNVjAr+in0HJkUsitsqE+u0axvj8ewPwDiQbPPjQz/Jl8F4Cfu+Ri0do4VUKUfT151Fte3P7fs6AXDcc57twIT+Me2XL2L/dlIdxV8mOruN0YhkF4w9yZ4oxqrJlhy/VXRstNg4GZs/hmNjukEh3ci2TmuJat2KO7sCm/kmx8MOinhkohIwGngSo3PfHMYVZOcxXtnGWGYgpyv4SZAdCjZg8dPtgIUvJ5yqdZJtS+drDsknUMA32LdhzJKI8ZVgJA6RvoBpY1xGthiZORD4yYIiE8M4SbIDaX5o7lws4GWcIGacunEDF3yJKflvqP4o+1rGLMtOYPw1ML4cEASeEkfvvl8Qo4Gfj6X7/DdJmQbZAZ9BmRNQxOsIwX4XBVzBhR+Ei6tkG4IyjNxb38fqxwqKzLpOHLTtRRrwqnWmYYpx71WOcaYJmld+roG5BuYamGtgroG5BuYamJoG/h/ff6XOIB4wOAAAAABJRU5ErkJggg==\"/>\n\t<title>Swarm index of bzz:/262e5c08c03c2789b6daef487dfa14b4d132f5340d781a3ecb1d5122ab65640c/</title>\n</head>\n\n<body>\n <h1>Swarm index of bzz:/262e5c08c03c2789b6daef487dfa14b4d132f5340d781a3ecb1d5122ab65640c/</h1>\n <hr>\n <table>\n <thead>\n <tr>\n\t<th>Path</th>\n\t<th>Type</th>\n\t<th>Size</th>\n </tr>\n </thead>\n\n <tbody>\n \n\t<tr>\n\t <td><a href=\"a/\">a/</a></td>\n\t <td>DIR</td>\n\t <td>-</td>\n\t</tr>\n \n\n \n </table>\n <hr>\n</body>\n",
},
{
path: "/a/",
json: `{"common_prefixes":["a/b/"],"entries":[{"hash":"011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce","path":"a/a","mod_time":"0001-01-01T00:00:00Z"}]}`,
- html: "<!DOCTYPE html>\n<html>\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>Swarm index of bzz:/262e5c08c03c2789b6daef487dfa14b4d132f5340d781a3ecb1d5122ab65640c/a/</title>\n</head>\n\n<body>\n <h1>Swarm index of bzz:/262e5c08c03c2789b6daef487dfa14b4d132f5340d781a3ecb1d5122ab65640c/a/</h1>\n <hr>\n <table>\n <thead>\n <tr>\n\t<th>Path</th>\n\t<th>Type</th>\n\t<th>Size</th>\n </tr>\n </thead>\n\n <tbody>\n \n\t<tr>\n\t <td><a href=\"b/\">b/</a></td>\n\t <td>DIR</td>\n\t <td>-</td>\n\t</tr>\n \n\n \n\t<tr>\n\t <td><a href=\"a\">a</a></td>\n\t <td></td>\n\t <td>0</td>\n\t</tr>\n \n </table>\n <hr>\n</body>\n",
+ html: "<!DOCTYPE html>\n<html>\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\t\t<link rel=\"shortcut icon\" type=\"image/x-icon\" href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHsAAAB5CAYAAAAZD150AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KTMInWQAAFzFJREFUeAHtnXuwJFV9x7vnzrKwIC95w/ImYFkxlZgiGswCIiCGxPhHCEIwmIemUqYwJkYrJmXlUZRa+IpAWYYEk4qJD4gJGAmoiBIxMQFRQCkXdhdCeL+fYdk7nc+ne87dvnPn0TPTPdNzmd/W2X6fc76/7/n9zjm/PrcniuYy18BcA3MNzDUw18BcA3MNzDUw18BcA3MNrGYNLERroyMAeNQ0QcbTLPxFUfaOOx4Wbd12ThRHp0TJ4s5RFF8RtVoXg/2BSeOfk12lxtc0fjva1jibItZEDf4li3u3i3sqipOPRIvRp6ssvjPvhc4Tq/y4Ab71pEXS1oqw7hw1mz8XJc2LoiQ6iTJaaTkxth0l69jXwNayOZ10AvubSQ+RrFOl8mKy7EOiRuN3UfjrUfItUaN1SbQt+lqp2m02T4payS9HSfxK8k1IGdEWkln2Xuzldd7keBunrsO1f4r9b5Mqk3zBlRUy9Ywb0TtQ6O9Tjx1JkvA8SSXfiJK5Fj1MGkf2jBYWzo9a8Y+TiQRaxnLpTnb+HuvzDerzLk4+mb9Q1v5qduPrUPvxURx/DiWeicK2W1lKdCT2Q7n+VqzuOei5m+Nnh1TsPtGahbOiaOFCrHn/vs8ud+PdbrWLOZr6vIX6PEF97uH4uW43jnpudVp2Mzo1ajV+AwPbgGJUYr4/1Or+jxSwu90R5f6QQdPnaBK603zD4LCLNJsnkusfcUXXrKfoL4MtOzxvfXegPrdGjeRjlHEVx4PrE57us11tlr0b/fKlKIq+OTqsjXulS80sO5Dtbdugfnf4Py5qxGenxEeppbez6LJpte6LFuIWlvhT3J/Pq8vNnBps2eE562t97A608G+xnZMdtMN2H+z3LSj+n9g3cNGN4Nzt9tddCZK0ncnnrChuHBElySaOH8k/mNtf5Pr3onWtL0WthfWUuA/XGGX3KHsw2ZYtqc9Rs4dIW2m4mxjwXd8+z2Y8mXXLXoDk38Eaz4c7+2VJzLvsXtrpRXa43+svh/TTIf1QSP0Rx0+Ei8u2L0RPM6i6hn77e9SFhsJzGWnLG9wgshvpeOEJnn+6nX+D8u+ck51p43hIvhyS38DhHiQJKiqDyDYfG42WeiAk3oO93uLJ3tK6P0pa1zK/vj5aSI6FtF15Zjvhvcle5F69xzMkywxdAk+US7aDgVmSbMTaaFwM0VdS8QNIQTll4TA/SdKd3kvS0oqWgRveeku0uO2NjM4v5TmDJda52/MSqyXfy3YrqXJxEDArcjB92Dvh4RdIjoC1hLJFUp6BAPMOBHQjalC5SdR6wfj3FVFjDV1Bcg698S7ka172y0+3y5DwiRncxAoC1OjSiN6LJTNQSd5MJruQnDqVLbrTB0mPkXEgetwy7oH0T2LppzOrv4bMnif/B0hPsS/pozSkketUZ8s2KPIq3OH5ONWjQVgFwSpO69KajVpVpfzHom3b3hctNHajwR5OOUbyLGt7n85B1VJPspvRydFi/Hba/gYUoFLKJlqPpmXx9ikdBRcZsHH7WLIjZT1F472TXHaFZ6dqO5Gsx0SkbmTvS7/8caYbG1CMJGt1Vciz5O5UKuRflUV31t1yJPdx2jDlp2MPw6wTsfA6ke1U47Pg1mVXqfwXyP1Bypg2dgiOXcDwKJgPZPsSknGPyoiv0wAtZlz6CERsAXB4v1tV/apsTFS/sIgP7xLfTdrMPhbfc6pWONNeN1alzF7lDTqfuTkHS3F0FzcbbHixCG/cUtLvAHBZs4Fluqsb2fnK+XpBS6fVp4Mo+7q6WGS+nmXvE8SJf0imDxKGlfTS3Pq0+61BipJc+9j7gOzI1bCoS3tKUwB51U3st9cwar+Kgeq/sR8GkWPXs+5kbwcYpy/yXWQg2U5brPtqI905yEPRttbfgm0jqVSZHbID7CyUeRc078kpo2lrSFWSbt6lWRd5dYreizdcLI1K4m9F2xa/zHEleGaP7Kzftj933ZgDuZcwc9W9q7QylWRevLeKd+d/lgMnt3I84M0XdwwnNlQCRvHVkOwiBaZh1ckskh20kfXnCQpKI1Opa9fFlxWRWsvSpoPIex1pbxIWxyvVVuv9lGFAZlxp0ohc8PgZMqpkgWFnBWeZ7DwWB3H/g/IMTGjlvoceRbDmBuu/kj2waBf0x9o2/ysvYN1n8ELmtbzFugDHrrsddlWqgy/z3Bw1WeGyNbrNjCclFl4XIagSn0Fl7IdHEQc3W0nh9aQvG2zMna7dt1sheBHK8R5IiPdlcwBbYtc5iZdWwNh3MyuITyFtIN7F0qTCrp0GGB8TLbQuixaTf+HJ+3MlTGQ3a7MTKWpgIQ0W8H2Bu1B4KaIFaeW7k/I4bRBbOBcauv0yHiE+iPvDOS7nJE7oV00rRFd8O57gPK78YMXV5Sesg3GNKgd7y0vsOKpzUKWjqkMfZoM43Xu20CGz3nw2TuOSxqGQfVhPovP3r9x3FejReKSv8gLnQ1w+ZuUtS2csf2pEW4vuLXmpfhPdGdeNd6us1sRy33RlyHPs69bXsIjwWQjGktN+WXff6eo5lZPMjfda4xZI/Ele5JxK3jSc5Cae7uYJcplOfjfv3iZf+vISy3bjy3PffkQ/2zgaeosP4nq78e25bt9Tp48S/TqZba1i+6tlNL5d1Sv3Mut23VcUP8hlRu4t57YOxPbhWNL7W/bKPHud0fpd9eJfiNSui1ztZKtw5rCxUyTduKTuQMK1J3eRHoBwR+Au8ldGIT00JgM8z5KH/XIt9VrLSqn1EgSlx/eQj4v7guS7LfdZAJjcDcf3YYjHQLVTrmEJd9WLixTDc/kyQrm12K42slU0wQ8jXLELIIq+FtW138zgah8oO5DkXN+8AoHsLhPPO4WzITkQqy3B+VqvFrKDsiE4NmDie2DPhfN5zL32mZm0HuaJx0l7ECo9hBs7FwSanyQb3rRfLtqYuHX6slrIJmoW/y/qDNOjYUjOs+Bz9rkP82UG30IdSjogd4MNgYHekoxazlIGk9yZdbIZdMX2l1pz+YqPkzvo0/kbrnivNskzZcmdDWkWyXaEjZtOp1H2mVpi+URnmlI//M1XYhRuDclpmttefTmX6iuzSDZz5XTwFbRaFdGd+dtFmCTbvrzqcimiXJkFslWq1mu/bFDEgdE0Fe1oX9K1cufs06wLxReXupPdLShSB+Xqxp1yOeqX8MHxdW6attSZbIMi9pX2y4HgsJ223kL5DtgC6evYr9OLpVDHpW3dyNaS80ERLahuBC8pL7cj6TZKrVz3rl5rV+86kU28Or6Tce56FOUaL5VVO4VRp15iXXXriqtlbLS1knq5nVZyDV8KJDqVuAhAK69CxGw4tIrpkx+9uZFlR39A/s7/ayV1tZyXQvovwcdPoC0XEYbIWBnKY+qU8KYrDXWWkZ+NR690G/H1L2DP3ykj0yryqCvZAavfUTkNZ34cJ3SRZVhjmWQzKIs3QvKlNMfvUj8Ha7WVupMdFHdU1Gy8DapdQDgu4WWRjbdJ/oEIwGXUyThA7aUOfbarPwdZhMt8voJr541T+rUCnxmV9HH6bAe0z7DG7N9x3H9BDXTZReqxJ/e5eGKqMk2y/bq+X0F6P256X1T2X2iiv4W0WndA+k2QzouP5Cjux0oLKTuv5FHIdrC4EyRfB8kfpcR/5dgR9yDxC4zvaWPcv42xzPHHoPKXXZ+OG1+ITuNN0gXUZD+SS3lcAcr3OpN30/ddx3ERa/GjtOfy3CvS5/mvoIzgxvkcxkLrI4wa/HuvYpJ+GTn+MDeLUc/lHyeI8b1g/BrHRTByW3kyabJfA0HvAOepQHDAZTDClm7SehzwXM3fP13E/rdJReRl5MmH5ZbWbJtnPylCtnrBZcd3UcVroOlyjgflG8rky8bpLxbkMeqxnHdnHiJinXmrdSHHN4SHJrGdFNmHo4A/h+RXA8p1XvmAQyA74NXNYu3xDSiEZ9Lf0AjXem13IHZ1DKtLzsBeDuYmX5b0kkFk2zXwfPIZSP4q+w/3yqjjvBj/lOd+lvNiFFeQQHY4Dhj/A4x/xslN4UKV26rJXktbfifEkbA9NNEFTCfZ+Vt4JrkYm9LSi/SRMf35aTxzOvdLWjfpRzZ/MpT8J+V9nAcZFxSSHcB4HvB+j7u13G4YO8nOZyzGT1LmJzhZBGP+2aH2bWFVyDpeCZxJoOFvUMIbKSBvyZ3l6R5NPST268M/jxr96sIWbgohye73J8lGCLsBK/Odc7d14WLehRRI8djI1818uf9CrPmzHA+aHXALXc5C9Cs8dwkY38RxP4yW1Q/jBjCeXhijpY8g5Vv2QgS58btR5eHUR0X2AZnWuJ9lB0iZxSTRj/i884dxkFeHCwO2B0H6L+JT7D7CGCFv2by4iLew3uxTUHUL9xQhWVR4jvgPwXgkzxTB2M+yA4SAcSMYLxgCY3h+4LYssq3oelr5BSj2BPbz/dWgShQhO58HFht/k77uPZzcQgoWmr+nc//HCMqcy517cWEtj2jxkJ98Hkv+R/YHNUjzU1fraTwf4rmT2B8GYxGyLSMIf3AYXY+HEuNmUpH6hWd7bssg24HJuSjgNynFl/j9BkfdKjIs2eZhf4wVJn+HGiRroycHyAI/rgZJrdfQUB7jub/nfteWF5FD2xh/i5vtHobFOCzZ1mkUjD7XU8YjuxH9CQ3+zeSuxdj6ilhZZ2VGIds8rPsC/7P6M+HzF9EHOS5S/s7cZzSrmLU0/IUffiQm4lMbo2MchWyKW4bxi9T4A+06eG1oGYXsHZiBnsgPlv0lpRkGHMaddavgqGTn86LvxUobvFrcFn2dfZU7jqwB4/FgdIRsQx4X46hk5zEEjAaeruXC0BiHI7tJf9xqvB0Dej2FhQFPvkKj7JdBtuU6bqA/jr/CgOuvUch1nhxaMoxvA+NpPFsWxjLIFop8OWbhj//Tn5e0YReWomTzoyiNC1CAo1qiXMO3qj41KovsUISjY+ar8U30zX/M/uZwYcB2PzAS3kyDIrr6oS2nT/5lkR2KCBhvBuP7OLkpXOi39aF+sgv28i5G2Q6C1pO8v0i/2C/Pzmv2ncX6z84nux9bP0KdRNLi+NexhRY1vpXjXvNgMZ7HvZ9Pn8meLRuj+VWB0RnQW8Ho92O+3wcjlzK3kO50+Y8fMIk/TTYncc3RZ9kKCEWWbdkhX7d6Lqcx32EQ5yDrCU/mZB3WfAnQ3sA559hVYSzbsnMQUoy8keObaklyJheezF/M79vP9ZImLd7R7kZueJrU795eeUzzvET7c02bqLnTGLufTmlynegZwZpsdeisYtycctUd4xJm3V0vCa7HD8r5VWBbjNOPfs/0ymvS531l+hiFOsWSdLH0slrdqxiZwqXLgWcHo/H77GsPASNQektR4uwVGPTwNipJvyvmWx2nAr0U2LvE6q4I2H7ZLyG4htu6ea6orHqMRclWYZnisq8D8is26apP56BKHUgPrTwMhIYhOkOxyjEOQ3ZQiFtXXegmn4TmfdkaQhxFuTw2tvglhEfJpcypkpUSo685/Vnj/djOPMZRyVYZkmvfeC/KcF66G8ntJKzcsh09+xkqlzVV2dD8UmLAuDtlBdKrxlk6xnHIBncq9nUq3PfNKsI3SuZbhTJUgJ+Q1OLCdLBKoikmlU6MDuIc4c8UxjLIztQh8Iz0zewZM9cKypzK2BdryT3nkaEiFW4Dxi2ziLFMsoOOtQL70KdRiIS7KmTUyJtWK8mOsJ3rG6suswGR3UiSx2j35Z8olYXRGUUl3qoKstWelXXu+hDbxyH9pWzzS4E4HCiSGn5G0SibUgeis5psx/gwJxzE6c2ckobZQLiv39YGorcyshcwVkK0laiKbPMOEoIyRrBCfx6u9do6ElaJDsIqA9+r8BHOZ0GZjHRnJ0X0OnGMRSo1AvYVj4QBzl1YgG7PxOvIZVaQeYOspRvA0UJmgWiqmYp1NTxbW4yTIlttZMRlLsv+XLduUCYQ6odeJTnMl8N5Ts2MDML4BBiduUwF4yTJzjOmC7OfykjPwpsqYBYJzuPK79cO4zTIDoQyuuZ7ZrEx9sRRu7H2adQnT1BZ+3mMfg+VgVjiAG6qGCetXJXA9Cm+n63ujBFo4opUpxuORh2dGpgZdRrDo1OXLhjTvysXo8lgjJgnjnGSZBttYoTd8+uEXpdw31ipDK0gWAi7MyEOKokx9MQoiED6xDFWTbZk2RfTP6df8y8aFPE9tEqRcFOdRYySTAg3foStYdwi8QAxqg9nJRPBWCXZAlYBD7KVOKWIErwvNJKgEK2gqli05Y0q4rEhP8B2FIw2koAxkF5FvD3FVxXZAI/vowRDnOO6Yj2D+Ui2/XnRBsOtlUrZGJ12aumVYSyTbEnVhT0Gv8bGbaHjEk0WqZiP/bmkB9c+8QEOZecxgrPUwE/A6JglWHmpGMsgOxCKu05J1jUp4Xx2VM7/NiAblBYg6br3SYhYLFuMklx1UKQSjOOSrQKcL+uy7bOqIJhsV4jlGje3zNCfr7ippBPTxhhcu93YWDIK2YFQ3E1qyaFfDufHqtAQD1ueXsT5ujh0fWUO4sy/DhhtbPbnYhsL47BkqwBaWmrJKtmKTJpkilwh9ue6Vvu4cQc44nHwdS/bumC0TmNjHIZslZkPGNSBZKq0JDa8cYMyAaOvV+vSkJcAtus0MsZBZDvN0VWGEbb9R91IpkorJMxdHcTp+vqJeCTWhuwsImCsO85hMKb4B5Ad21c4FXB0qNRdAVkts3raSB3EBfLCtc4trjrexMlZxzgw/mAf10ue5w/FbuWP+w6EYt89D8ysV0YDztvHjj3S7FKGDRPC+XBdI/kAe3d2uUeMt08AY4iDd6nCWKfaXim+u43xjn65FbHUBmPdV/FH+K+D9CPITEspS3Cf6as/CS9LxMQSqJiG2voivfjXOdbK+0nAeBIYj+TGkjG68DJxTX1ZEjD6jfOA0fFGXylCdsiAT080j4uS1tmc0CMMzDw82GdbNtl6H9aD8aG87MsLuvFhxE+IvJofU/9VHioRY6lki5HGyIfyFtOGXBjjMGQHpe3EVwTPobBXcEKLHGQ14blu27LIVgH8kUJyI7W5kH1XwYwjYoTwFCNeYlyMpZAdMPJFiRQjL5mGk1HIDiUchUJORCHHcsJ8RiF9XLJVwAIkX4tFXkl7vy1UrqTtkW2MP0N+Y2Aci2wxNtsYrxgH4zhkq09d3SHtr/zvx77hy2FkHLKZVjH4Wmx9kAI3kcroVrrVXYwHtzHuz/4IGEcmm2ljvKWNcTNlO8ceWcYle3vBzeapGPfJzFgZjKQCkQNlWLLb9XWRQOufoffygSWUeUOzeQrlngLG3cjWuhTEOBTZASNz/hTjZWVBKI/srEZ74PY2MEA6ETW4wC7MXXvVdxiytWQV8CVIvpoMeQM1Fdm9jfG1xTEWJpspqG/VUozXgO6BMhGWTbZ1M8/dUMibaPgb2O/neoqQbX7+ZMNVjAr+in0HJkUsitsqE+u0axvj8ewPwDiQbPPjQz/Jl8F4Cfu+Ri0do4VUKUfT151Fte3P7fs6AXDcc57twIT+Me2XL2L/dlIdxV8mOruN0YhkF4w9yZ4oxqrJlhy/VXRstNg4GZs/hmNjukEh3ci2TmuJat2KO7sCm/kmx8MOinhkohIwGngSo3PfHMYVZOcxXtnGWGYgpyv4SZAdCjZg8dPtgIUvJ5yqdZJtS+drDsknUMA32LdhzJKI8ZVgJA6RvoBpY1xGthiZORD4yYIiE8M4SbIDaX5o7lws4GWcIGacunEDF3yJKflvqP4o+1rGLMtOYPw1ML4cEASeEkfvvl8Qo4Gfj6X7/DdJmQbZAZ9BmRNQxOsIwX4XBVzBhR+Ei6tkG4IyjNxb38fqxwqKzLpOHLTtRRrwqnWmYYpx71WOcaYJmld+roG5BuYamGtgroG5BuYamJoG/h/ff6XOIB4wOAAAAABJRU5ErkJggg==\"/>\n\t<title>Swarm index of bzz:/262e5c08c03c2789b6daef487dfa14b4d132f5340d781a3ecb1d5122ab65640c/a/</title>\n</head>\n\n<body>\n <h1>Swarm index of bzz:/262e5c08c03c2789b6daef487dfa14b4d132f5340d781a3ecb1d5122ab65640c/a/</h1>\n <hr>\n <table>\n <thead>\n <tr>\n\t<th>Path</th>\n\t<th>Type</th>\n\t<th>Size</th>\n </tr>\n </thead>\n\n <tbody>\n \n\t<tr>\n\t <td><a href=\"b/\">b/</a></td>\n\t <td>DIR</td>\n\t <td>-</td>\n\t</tr>\n \n\n \n\t<tr>\n\t <td><a href=\"a\">a</a></td>\n\t <td></td>\n\t <td>0</td>\n\t</tr>\n \n </table>\n <hr>\n</body>\n",
},
{
path: "/a/b/",
json: `{"entries":[{"hash":"011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce","path":"a/b/b","mod_time":"0001-01-01T00:00:00Z"},{"hash":"011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce","path":"a/b/c","mod_time":"0001-01-01T00:00:00Z"}]}`,
- html: "<!DOCTYPE html>\n<html>\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>Swarm index of bzz:/262e5c08c03c2789b6daef487dfa14b4d132f5340d781a3ecb1d5122ab65640c/a/b/</title>\n</head>\n\n<body>\n <h1>Swarm index of bzz:/262e5c08c03c2789b6daef487dfa14b4d132f5340d781a3ecb1d5122ab65640c/a/b/</h1>\n <hr>\n <table>\n <thead>\n <tr>\n\t<th>Path</th>\n\t<th>Type</th>\n\t<th>Size</th>\n </tr>\n </thead>\n\n <tbody>\n \n\n \n\t<tr>\n\t <td><a href=\"b\">b</a></td>\n\t <td></td>\n\t <td>0</td>\n\t</tr>\n \n\t<tr>\n\t <td><a href=\"c\">c</a></td>\n\t <td></td>\n\t <td>0</td>\n\t</tr>\n \n </table>\n <hr>\n</body>\n",
+ html: "<!DOCTYPE html>\n<html>\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\t\t<link rel=\"shortcut icon\" type=\"image/x-icon\" href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHsAAAB5CAYAAAAZD150AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KTMInWQAAFzFJREFUeAHtnXuwJFV9x7vnzrKwIC95w/ImYFkxlZgiGswCIiCGxPhHCEIwmIemUqYwJkYrJmXlUZRa+IpAWYYEk4qJD4gJGAmoiBIxMQFRQCkXdhdCeL+fYdk7nc+ne87dvnPn0TPTPdNzmd/W2X6fc76/7/n9zjm/PrcniuYy18BcA3MNzDUw18BcA3MNzDUw18BcA3MNrGYNLERroyMAeNQ0QcbTLPxFUfaOOx4Wbd12ThRHp0TJ4s5RFF8RtVoXg/2BSeOfk12lxtc0fjva1jibItZEDf4li3u3i3sqipOPRIvRp6ssvjPvhc4Tq/y4Ab71pEXS1oqw7hw1mz8XJc2LoiQ6iTJaaTkxth0l69jXwNayOZ10AvubSQ+RrFOl8mKy7EOiRuN3UfjrUfItUaN1SbQt+lqp2m02T4payS9HSfxK8k1IGdEWkln2Xuzldd7keBunrsO1f4r9b5Mqk3zBlRUy9Ywb0TtQ6O9Tjx1JkvA8SSXfiJK5Fj1MGkf2jBYWzo9a8Y+TiQRaxnLpTnb+HuvzDerzLk4+mb9Q1v5qduPrUPvxURx/DiWeicK2W1lKdCT2Q7n+VqzuOei5m+Nnh1TsPtGahbOiaOFCrHn/vs8ud+PdbrWLOZr6vIX6PEF97uH4uW43jnpudVp2Mzo1ajV+AwPbgGJUYr4/1Or+jxSwu90R5f6QQdPnaBK603zD4LCLNJsnkusfcUXXrKfoL4MtOzxvfXegPrdGjeRjlHEVx4PrE57us11tlr0b/fKlKIq+OTqsjXulS80sO5Dtbdugfnf4Py5qxGenxEeppbez6LJpte6LFuIWlvhT3J/Pq8vNnBps2eE562t97A608G+xnZMdtMN2H+z3LSj+n9g3cNGN4Nzt9tddCZK0ncnnrChuHBElySaOH8k/mNtf5Pr3onWtL0WthfWUuA/XGGX3KHsw2ZYtqc9Rs4dIW2m4mxjwXd8+z2Y8mXXLXoDk38Eaz4c7+2VJzLvsXtrpRXa43+svh/TTIf1QSP0Rx0+Ei8u2L0RPM6i6hn77e9SFhsJzGWnLG9wgshvpeOEJnn+6nX+D8u+ck51p43hIvhyS38DhHiQJKiqDyDYfG42WeiAk3oO93uLJ3tK6P0pa1zK/vj5aSI6FtF15Zjvhvcle5F69xzMkywxdAk+US7aDgVmSbMTaaFwM0VdS8QNIQTll4TA/SdKd3kvS0oqWgRveeku0uO2NjM4v5TmDJda52/MSqyXfy3YrqXJxEDArcjB92Dvh4RdIjoC1hLJFUp6BAPMOBHQjalC5SdR6wfj3FVFjDV1Bcg698S7ka172y0+3y5DwiRncxAoC1OjSiN6LJTNQSd5MJruQnDqVLbrTB0mPkXEgetwy7oH0T2LppzOrv4bMnif/B0hPsS/pozSkketUZ8s2KPIq3OH5ONWjQVgFwSpO69KajVpVpfzHom3b3hctNHajwR5OOUbyLGt7n85B1VJPspvRydFi/Hba/gYUoFLKJlqPpmXx9ikdBRcZsHH7WLIjZT1F472TXHaFZ6dqO5Gsx0SkbmTvS7/8caYbG1CMJGt1Vciz5O5UKuRflUV31t1yJPdx2jDlp2MPw6wTsfA6ke1U47Pg1mVXqfwXyP1Bypg2dgiOXcDwKJgPZPsSknGPyoiv0wAtZlz6CERsAXB4v1tV/apsTFS/sIgP7xLfTdrMPhbfc6pWONNeN1alzF7lDTqfuTkHS3F0FzcbbHixCG/cUtLvAHBZs4Fluqsb2fnK+XpBS6fVp4Mo+7q6WGS+nmXvE8SJf0imDxKGlfTS3Pq0+61BipJc+9j7gOzI1bCoS3tKUwB51U3st9cwar+Kgeq/sR8GkWPXs+5kbwcYpy/yXWQg2U5brPtqI905yEPRttbfgm0jqVSZHbID7CyUeRc078kpo2lrSFWSbt6lWRd5dYreizdcLI1K4m9F2xa/zHEleGaP7Kzftj933ZgDuZcwc9W9q7QylWRevLeKd+d/lgMnt3I84M0XdwwnNlQCRvHVkOwiBaZh1ckskh20kfXnCQpKI1Opa9fFlxWRWsvSpoPIex1pbxIWxyvVVuv9lGFAZlxp0ohc8PgZMqpkgWFnBWeZ7DwWB3H/g/IMTGjlvoceRbDmBuu/kj2waBf0x9o2/ysvYN1n8ELmtbzFugDHrrsddlWqgy/z3Bw1WeGyNbrNjCclFl4XIagSn0Fl7IdHEQc3W0nh9aQvG2zMna7dt1sheBHK8R5IiPdlcwBbYtc5iZdWwNh3MyuITyFtIN7F0qTCrp0GGB8TLbQuixaTf+HJ+3MlTGQ3a7MTKWpgIQ0W8H2Bu1B4KaIFaeW7k/I4bRBbOBcauv0yHiE+iPvDOS7nJE7oV00rRFd8O57gPK78YMXV5Sesg3GNKgd7y0vsOKpzUKWjqkMfZoM43Xu20CGz3nw2TuOSxqGQfVhPovP3r9x3FejReKSv8gLnQ1w+ZuUtS2csf2pEW4vuLXmpfhPdGdeNd6us1sRy33RlyHPs69bXsIjwWQjGktN+WXff6eo5lZPMjfda4xZI/Ele5JxK3jSc5Cae7uYJcplOfjfv3iZf+vISy3bjy3PffkQ/2zgaeosP4nq78e25bt9Tp48S/TqZba1i+6tlNL5d1Sv3Mut23VcUP8hlRu4t57YOxPbhWNL7W/bKPHud0fpd9eJfiNSui1ztZKtw5rCxUyTduKTuQMK1J3eRHoBwR+Au8ldGIT00JgM8z5KH/XIt9VrLSqn1EgSlx/eQj4v7guS7LfdZAJjcDcf3YYjHQLVTrmEJd9WLixTDc/kyQrm12K42slU0wQ8jXLELIIq+FtW138zgah8oO5DkXN+8AoHsLhPPO4WzITkQqy3B+VqvFrKDsiE4NmDie2DPhfN5zL32mZm0HuaJx0l7ECo9hBs7FwSanyQb3rRfLtqYuHX6slrIJmoW/y/qDNOjYUjOs+Bz9rkP82UG30IdSjogd4MNgYHekoxazlIGk9yZdbIZdMX2l1pz+YqPkzvo0/kbrnivNskzZcmdDWkWyXaEjZtOp1H2mVpi+URnmlI//M1XYhRuDclpmttefTmX6iuzSDZz5XTwFbRaFdGd+dtFmCTbvrzqcimiXJkFslWq1mu/bFDEgdE0Fe1oX9K1cufs06wLxReXupPdLShSB+Xqxp1yOeqX8MHxdW6attSZbIMi9pX2y4HgsJ223kL5DtgC6evYr9OLpVDHpW3dyNaS80ERLahuBC8pL7cj6TZKrVz3rl5rV+86kU28Or6Tce56FOUaL5VVO4VRp15iXXXriqtlbLS1knq5nVZyDV8KJDqVuAhAK69CxGw4tIrpkx+9uZFlR39A/s7/ayV1tZyXQvovwcdPoC0XEYbIWBnKY+qU8KYrDXWWkZ+NR690G/H1L2DP3ykj0yryqCvZAavfUTkNZ34cJ3SRZVhjmWQzKIs3QvKlNMfvUj8Ha7WVupMdFHdU1Gy8DapdQDgu4WWRjbdJ/oEIwGXUyThA7aUOfbarPwdZhMt8voJr541T+rUCnxmV9HH6bAe0z7DG7N9x3H9BDXTZReqxJ/e5eGKqMk2y/bq+X0F6P256X1T2X2iiv4W0WndA+k2QzouP5Cjux0oLKTuv5FHIdrC4EyRfB8kfpcR/5dgR9yDxC4zvaWPcv42xzPHHoPKXXZ+OG1+ITuNN0gXUZD+SS3lcAcr3OpN30/ddx3ERa/GjtOfy3CvS5/mvoIzgxvkcxkLrI4wa/HuvYpJ+GTn+MDeLUc/lHyeI8b1g/BrHRTByW3kyabJfA0HvAOepQHDAZTDClm7SehzwXM3fP13E/rdJReRl5MmH5ZbWbJtnPylCtnrBZcd3UcVroOlyjgflG8rky8bpLxbkMeqxnHdnHiJinXmrdSHHN4SHJrGdFNmHo4A/h+RXA8p1XvmAQyA74NXNYu3xDSiEZ9Lf0AjXem13IHZ1DKtLzsBeDuYmX5b0kkFk2zXwfPIZSP4q+w/3yqjjvBj/lOd+lvNiFFeQQHY4Dhj/A4x/xslN4UKV26rJXktbfifEkbA9NNEFTCfZ+Vt4JrkYm9LSi/SRMf35aTxzOvdLWjfpRzZ/MpT8J+V9nAcZFxSSHcB4HvB+j7u13G4YO8nOZyzGT1LmJzhZBGP+2aH2bWFVyDpeCZxJoOFvUMIbKSBvyZ3l6R5NPST268M/jxr96sIWbgohye73J8lGCLsBK/Odc7d14WLehRRI8djI1818uf9CrPmzHA+aHXALXc5C9Cs8dwkY38RxP4yW1Q/jBjCeXhijpY8g5Vv2QgS58btR5eHUR0X2AZnWuJ9lB0iZxSTRj/i884dxkFeHCwO2B0H6L+JT7D7CGCFv2by4iLew3uxTUHUL9xQhWVR4jvgPwXgkzxTB2M+yA4SAcSMYLxgCY3h+4LYssq3oelr5BSj2BPbz/dWgShQhO58HFht/k77uPZzcQgoWmr+nc//HCMqcy517cWEtj2jxkJ98Hkv+R/YHNUjzU1fraTwf4rmT2B8GYxGyLSMIf3AYXY+HEuNmUpH6hWd7bssg24HJuSjgNynFl/j9BkfdKjIs2eZhf4wVJn+HGiRroycHyAI/rgZJrdfQUB7jub/nfteWF5FD2xh/i5vtHobFOCzZ1mkUjD7XU8YjuxH9CQ3+zeSuxdj6ilhZZ2VGIds8rPsC/7P6M+HzF9EHOS5S/s7cZzSrmLU0/IUffiQm4lMbo2MchWyKW4bxi9T4A+06eG1oGYXsHZiBnsgPlv0lpRkGHMaddavgqGTn86LvxUobvFrcFn2dfZU7jqwB4/FgdIRsQx4X46hk5zEEjAaeruXC0BiHI7tJf9xqvB0Dej2FhQFPvkKj7JdBtuU6bqA/jr/CgOuvUch1nhxaMoxvA+NpPFsWxjLIFop8OWbhj//Tn5e0YReWomTzoyiNC1CAo1qiXMO3qj41KovsUISjY+ar8U30zX/M/uZwYcB2PzAS3kyDIrr6oS2nT/5lkR2KCBhvBuP7OLkpXOi39aF+sgv28i5G2Q6C1pO8v0i/2C/Pzmv2ncX6z84nux9bP0KdRNLi+NexhRY1vpXjXvNgMZ7HvZ9Pn8meLRuj+VWB0RnQW8Ho92O+3wcjlzK3kO50+Y8fMIk/TTYncc3RZ9kKCEWWbdkhX7d6Lqcx32EQ5yDrCU/mZB3WfAnQ3sA559hVYSzbsnMQUoy8keObaklyJheezF/M79vP9ZImLd7R7kZueJrU795eeUzzvET7c02bqLnTGLufTmlynegZwZpsdeisYtycctUd4xJm3V0vCa7HD8r5VWBbjNOPfs/0ymvS531l+hiFOsWSdLH0slrdqxiZwqXLgWcHo/H77GsPASNQektR4uwVGPTwNipJvyvmWx2nAr0U2LvE6q4I2H7ZLyG4htu6ea6orHqMRclWYZnisq8D8is26apP56BKHUgPrTwMhIYhOkOxyjEOQ3ZQiFtXXegmn4TmfdkaQhxFuTw2tvglhEfJpcypkpUSo685/Vnj/djOPMZRyVYZkmvfeC/KcF66G8ntJKzcsh09+xkqlzVV2dD8UmLAuDtlBdKrxlk6xnHIBncq9nUq3PfNKsI3SuZbhTJUgJ+Q1OLCdLBKoikmlU6MDuIc4c8UxjLIztQh8Iz0zewZM9cKypzK2BdryT3nkaEiFW4Dxi2ziLFMsoOOtQL70KdRiIS7KmTUyJtWK8mOsJ3rG6suswGR3UiSx2j35Z8olYXRGUUl3qoKstWelXXu+hDbxyH9pWzzS4E4HCiSGn5G0SibUgeis5psx/gwJxzE6c2ckobZQLiv39YGorcyshcwVkK0laiKbPMOEoIyRrBCfx6u9do6ElaJDsIqA9+r8BHOZ0GZjHRnJ0X0OnGMRSo1AvYVj4QBzl1YgG7PxOvIZVaQeYOspRvA0UJmgWiqmYp1NTxbW4yTIlttZMRlLsv+XLduUCYQ6odeJTnMl8N5Ts2MDML4BBiduUwF4yTJzjOmC7OfykjPwpsqYBYJzuPK79cO4zTIDoQyuuZ7ZrEx9sRRu7H2adQnT1BZ+3mMfg+VgVjiAG6qGCetXJXA9Cm+n63ujBFo4opUpxuORh2dGpgZdRrDo1OXLhjTvysXo8lgjJgnjnGSZBttYoTd8+uEXpdw31ipDK0gWAi7MyEOKokx9MQoiED6xDFWTbZk2RfTP6df8y8aFPE9tEqRcFOdRYySTAg3foStYdwi8QAxqg9nJRPBWCXZAlYBD7KVOKWIErwvNJKgEK2gqli05Y0q4rEhP8B2FIw2koAxkF5FvD3FVxXZAI/vowRDnOO6Yj2D+Ui2/XnRBsOtlUrZGJ12aumVYSyTbEnVhT0Gv8bGbaHjEk0WqZiP/bmkB9c+8QEOZecxgrPUwE/A6JglWHmpGMsgOxCKu05J1jUp4Xx2VM7/NiAblBYg6br3SYhYLFuMklx1UKQSjOOSrQKcL+uy7bOqIJhsV4jlGje3zNCfr7ippBPTxhhcu93YWDIK2YFQ3E1qyaFfDufHqtAQD1ueXsT5ujh0fWUO4sy/DhhtbPbnYhsL47BkqwBaWmrJKtmKTJpkilwh9ue6Vvu4cQc44nHwdS/bumC0TmNjHIZslZkPGNSBZKq0JDa8cYMyAaOvV+vSkJcAtus0MsZBZDvN0VWGEbb9R91IpkorJMxdHcTp+vqJeCTWhuwsImCsO85hMKb4B5Ad21c4FXB0qNRdAVkts3raSB3EBfLCtc4trjrexMlZxzgw/mAf10ue5w/FbuWP+w6EYt89D8ysV0YDztvHjj3S7FKGDRPC+XBdI/kAe3d2uUeMt08AY4iDd6nCWKfaXim+u43xjn65FbHUBmPdV/FH+K+D9CPITEspS3Cf6as/CS9LxMQSqJiG2voivfjXOdbK+0nAeBIYj+TGkjG68DJxTX1ZEjD6jfOA0fFGXylCdsiAT080j4uS1tmc0CMMzDw82GdbNtl6H9aD8aG87MsLuvFhxE+IvJofU/9VHioRY6lki5HGyIfyFtOGXBjjMGQHpe3EVwTPobBXcEKLHGQ14blu27LIVgH8kUJyI7W5kH1XwYwjYoTwFCNeYlyMpZAdMPJFiRQjL5mGk1HIDiUchUJORCHHcsJ8RiF9XLJVwAIkX4tFXkl7vy1UrqTtkW2MP0N+Y2Aci2wxNtsYrxgH4zhkq09d3SHtr/zvx77hy2FkHLKZVjH4Wmx9kAI3kcroVrrVXYwHtzHuz/4IGEcmm2ljvKWNcTNlO8ceWcYle3vBzeapGPfJzFgZjKQCkQNlWLLb9XWRQOufoffygSWUeUOzeQrlngLG3cjWuhTEOBTZASNz/hTjZWVBKI/srEZ74PY2MEA6ETW4wC7MXXvVdxiytWQV8CVIvpoMeQM1Fdm9jfG1xTEWJpspqG/VUozXgO6BMhGWTbZ1M8/dUMibaPgb2O/neoqQbX7+ZMNVjAr+in0HJkUsitsqE+u0axvj8ewPwDiQbPPjQz/Jl8F4Cfu+Ri0do4VUKUfT151Fte3P7fs6AXDcc57twIT+Me2XL2L/dlIdxV8mOruN0YhkF4w9yZ4oxqrJlhy/VXRstNg4GZs/hmNjukEh3ci2TmuJat2KO7sCm/kmx8MOinhkohIwGngSo3PfHMYVZOcxXtnGWGYgpyv4SZAdCjZg8dPtgIUvJ5yqdZJtS+drDsknUMA32LdhzJKI8ZVgJA6RvoBpY1xGthiZORD4yYIiE8M4SbIDaX5o7lws4GWcIGacunEDF3yJKflvqP4o+1rGLMtOYPw1ML4cEASeEkfvvl8Qo4Gfj6X7/DdJmQbZAZ9BmRNQxOsIwX4XBVzBhR+Ei6tkG4IyjNxb38fqxwqKzLpOHLTtRRrwqnWmYYpx71WOcaYJmld+roG5BuYamGtgroG5BuYamJoG/h/ff6XOIB4wOAAAAABJRU5ErkJggg==\"/>\n\t<title>Swarm index of bzz:/262e5c08c03c2789b6daef487dfa14b4d132f5340d781a3ecb1d5122ab65640c/a/b/</title>\n</head>\n\n<body>\n <h1>Swarm index of bzz:/262e5c08c03c2789b6daef487dfa14b4d132f5340d781a3ecb1d5122ab65640c/a/b/</h1>\n <hr>\n <table>\n <thead>\n <tr>\n\t<th>Path</th>\n\t<th>Type</th>\n\t<th>Size</th>\n </tr>\n </thead>\n\n <tbody>\n \n\n \n\t<tr>\n\t <td><a href=\"b\">b</a></td>\n\t <td></td>\n\t <td>0</td>\n\t</tr>\n \n\t<tr>\n\t <td><a href=\"c\">c</a></td>\n\t <td></td>\n\t <td>0</td>\n\t</tr>\n \n </table>\n <hr>\n</body>\n",
},
{
path: "/x",
diff --git a/swarm/api/http/templates.go b/swarm/api/http/templates.go
index 53ce7b5a2..189a99912 100644
--- a/swarm/api/http/templates.go
+++ b/swarm/api/http/templates.go
@@ -34,7 +34,8 @@ var htmlListTemplate = template.Must(template.New("html-list").Funcs(template.Fu
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
- <title>Swarm index of {{ .URI }}</title>
+ <link rel="shortcut icon" type="image/x-icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHsAAAB5CAYAAAAZD150AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KTMInWQAAFzFJREFUeAHtnXuwJFV9x7vnzrKwIC95w/ImYFkxlZgiGswCIiCGxPhHCEIwmIemUqYwJkYrJmXlUZRa+IpAWYYEk4qJD4gJGAmoiBIxMQFRQCkXdhdCeL+fYdk7nc+ne87dvnPn0TPTPdNzmd/W2X6fc76/7/n9zjm/PrcniuYy18BcA3MNzDUw18BcA3MNzDUw18BcA3MNrGYNLERroyMAeNQ0QcbTLPxFUfaOOx4Wbd12ThRHp0TJ4s5RFF8RtVoXg/2BSeOfk12lxtc0fjva1jibItZEDf4li3u3i3sqipOPRIvRp6ssvjPvhc4Tq/y4Ab71pEXS1oqw7hw1mz8XJc2LoiQ6iTJaaTkxth0l69jXwNayOZ10AvubSQ+RrFOl8mKy7EOiRuN3UfjrUfItUaN1SbQt+lqp2m02T4payS9HSfxK8k1IGdEWkln2Xuzldd7keBunrsO1f4r9b5Mqk3zBlRUy9Ywb0TtQ6O9Tjx1JkvA8SSXfiJK5Fj1MGkf2jBYWzo9a8Y+TiQRaxnLpTnb+HuvzDerzLk4+mb9Q1v5qduPrUPvxURx/DiWeicK2W1lKdCT2Q7n+VqzuOei5m+Nnh1TsPtGahbOiaOFCrHn/vs8ud+PdbrWLOZr6vIX6PEF97uH4uW43jnpudVp2Mzo1ajV+AwPbgGJUYr4/1Or+jxSwu90R5f6QQdPnaBK603zD4LCLNJsnkusfcUXXrKfoL4MtOzxvfXegPrdGjeRjlHEVx4PrE57us11tlr0b/fKlKIq+OTqsjXulS80sO5Dtbdugfnf4Py5qxGenxEeppbez6LJpte6LFuIWlvhT3J/Pq8vNnBps2eE562t97A608G+xnZMdtMN2H+z3LSj+n9g3cNGN4Nzt9tddCZK0ncnnrChuHBElySaOH8k/mNtf5Pr3onWtL0WthfWUuA/XGGX3KHsw2ZYtqc9Rs4dIW2m4mxjwXd8+z2Y8mXXLXoDk38Eaz4c7+2VJzLvsXtrpRXa43+svh/TTIf1QSP0Rx0+Ei8u2L0RPM6i6hn77e9SFhsJzGWnLG9wgshvpeOEJnn+6nX+D8u+ck51p43hIvhyS38DhHiQJKiqDyDYfG42WeiAk3oO93uLJ3tK6P0pa1zK/vj5aSI6FtF15Zjvhvcle5F69xzMkywxdAk+US7aDgVmSbMTaaFwM0VdS8QNIQTll4TA/SdKd3kvS0oqWgRveeku0uO2NjM4v5TmDJda52/MSqyXfy3YrqXJxEDArcjB92Dvh4RdIjoC1hLJFUp6BAPMOBHQjalC5SdR6wfj3FVFjDV1Bcg698S7ka172y0+3y5DwiRncxAoC1OjSiN6LJTNQSd5MJruQnDqVLbrTB0mPkXEgetwy7oH0T2LppzOrv4bMnif/B0hPsS/pozSkketUZ8s2KPIq3OH5ONWjQVgFwSpO69KajVpVpfzHom3b3hctNHajwR5OOUbyLGt7n85B1VJPspvRydFi/Hba/gYUoFLKJlqPpmXx9ikdBRcZsHH7WLIjZT1F472TXHaFZ6dqO5Gsx0SkbmTvS7/8caYbG1CMJGt1Vciz5O5UKuRflUV31t1yJPdx2jDlp2MPw6wTsfA6ke1U47Pg1mVXqfwXyP1Bypg2dgiOXcDwKJgPZPsSknGPyoiv0wAtZlz6CERsAXB4v1tV/apsTFS/sIgP7xLfTdrMPhbfc6pWONNeN1alzF7lDTqfuTkHS3F0FzcbbHixCG/cUtLvAHBZs4Fluqsb2fnK+XpBS6fVp4Mo+7q6WGS+nmXvE8SJf0imDxKGlfTS3Pq0+61BipJc+9j7gOzI1bCoS3tKUwB51U3st9cwar+Kgeq/sR8GkWPXs+5kbwcYpy/yXWQg2U5brPtqI905yEPRttbfgm0jqVSZHbID7CyUeRc078kpo2lrSFWSbt6lWRd5dYreizdcLI1K4m9F2xa/zHEleGaP7Kzftj933ZgDuZcwc9W9q7QylWRevLeKd+d/lgMnt3I84M0XdwwnNlQCRvHVkOwiBaZh1ckskh20kfXnCQpKI1Opa9fFlxWRWsvSpoPIex1pbxIWxyvVVuv9lGFAZlxp0ohc8PgZMqpkgWFnBWeZ7DwWB3H/g/IMTGjlvoceRbDmBuu/kj2waBf0x9o2/ysvYN1n8ELmtbzFugDHrrsddlWqgy/z3Bw1WeGyNbrNjCclFl4XIagSn0Fl7IdHEQc3W0nh9aQvG2zMna7dt1sheBHK8R5IiPdlcwBbYtc5iZdWwNh3MyuITyFtIN7F0qTCrp0GGB8TLbQuixaTf+HJ+3MlTGQ3a7MTKWpgIQ0W8H2Bu1B4KaIFaeW7k/I4bRBbOBcauv0yHiE+iPvDOS7nJE7oV00rRFd8O57gPK78YMXV5Sesg3GNKgd7y0vsOKpzUKWjqkMfZoM43Xu20CGz3nw2TuOSxqGQfVhPovP3r9x3FejReKSv8gLnQ1w+ZuUtS2csf2pEW4vuLXmpfhPdGdeNd6us1sRy33RlyHPs69bXsIjwWQjGktN+WXff6eo5lZPMjfda4xZI/Ele5JxK3jSc5Cae7uYJcplOfjfv3iZf+vISy3bjy3PffkQ/2zgaeosP4nq78e25bt9Tp48S/TqZba1i+6tlNL5d1Sv3Mut23VcUP8hlRu4t57YOxPbhWNL7W/bKPHud0fpd9eJfiNSui1ztZKtw5rCxUyTduKTuQMK1J3eRHoBwR+Au8ldGIT00JgM8z5KH/XIt9VrLSqn1EgSlx/eQj4v7guS7LfdZAJjcDcf3YYjHQLVTrmEJd9WLixTDc/kyQrm12K42slU0wQ8jXLELIIq+FtW138zgah8oO5DkXN+8AoHsLhPPO4WzITkQqy3B+VqvFrKDsiE4NmDie2DPhfN5zL32mZm0HuaJx0l7ECo9hBs7FwSanyQb3rRfLtqYuHX6slrIJmoW/y/qDNOjYUjOs+Bz9rkP82UG30IdSjogd4MNgYHekoxazlIGk9yZdbIZdMX2l1pz+YqPkzvo0/kbrnivNskzZcmdDWkWyXaEjZtOp1H2mVpi+URnmlI//M1XYhRuDclpmttefTmX6iuzSDZz5XTwFbRaFdGd+dtFmCTbvrzqcimiXJkFslWq1mu/bFDEgdE0Fe1oX9K1cufs06wLxReXupPdLShSB+Xqxp1yOeqX8MHxdW6attSZbIMi9pX2y4HgsJ223kL5DtgC6evYr9OLpVDHpW3dyNaS80ERLahuBC8pL7cj6TZKrVz3rl5rV+86kU28Or6Tce56FOUaL5VVO4VRp15iXXXriqtlbLS1knq5nVZyDV8KJDqVuAhAK69CxGw4tIrpkx+9uZFlR39A/s7/ayV1tZyXQvovwcdPoC0XEYbIWBnKY+qU8KYrDXWWkZ+NR690G/H1L2DP3ykj0yryqCvZAavfUTkNZ34cJ3SRZVhjmWQzKIs3QvKlNMfvUj8Ha7WVupMdFHdU1Gy8DapdQDgu4WWRjbdJ/oEIwGXUyThA7aUOfbarPwdZhMt8voJr541T+rUCnxmV9HH6bAe0z7DG7N9x3H9BDXTZReqxJ/e5eGKqMk2y/bq+X0F6P256X1T2X2iiv4W0WndA+k2QzouP5Cjux0oLKTuv5FHIdrC4EyRfB8kfpcR/5dgR9yDxC4zvaWPcv42xzPHHoPKXXZ+OG1+ITuNN0gXUZD+SS3lcAcr3OpN30/ddx3ERa/GjtOfy3CvS5/mvoIzgxvkcxkLrI4wa/HuvYpJ+GTn+MDeLUc/lHyeI8b1g/BrHRTByW3kyabJfA0HvAOepQHDAZTDClm7SehzwXM3fP13E/rdJReRl5MmH5ZbWbJtnPylCtnrBZcd3UcVroOlyjgflG8rky8bpLxbkMeqxnHdnHiJinXmrdSHHN4SHJrGdFNmHo4A/h+RXA8p1XvmAQyA74NXNYu3xDSiEZ9Lf0AjXem13IHZ1DKtLzsBeDuYmX5b0kkFk2zXwfPIZSP4q+w/3yqjjvBj/lOd+lvNiFFeQQHY4Dhj/A4x/xslN4UKV26rJXktbfifEkbA9NNEFTCfZ+Vt4JrkYm9LSi/SRMf35aTxzOvdLWjfpRzZ/MpT8J+V9nAcZFxSSHcB4HvB+j7u13G4YO8nOZyzGT1LmJzhZBGP+2aH2bWFVyDpeCZxJoOFvUMIbKSBvyZ3l6R5NPST268M/jxr96sIWbgohye73J8lGCLsBK/Odc7d14WLehRRI8djI1818uf9CrPmzHA+aHXALXc5C9Cs8dwkY38RxP4yW1Q/jBjCeXhijpY8g5Vv2QgS58btR5eHUR0X2AZnWuJ9lB0iZxSTRj/i884dxkFeHCwO2B0H6L+JT7D7CGCFv2by4iLew3uxTUHUL9xQhWVR4jvgPwXgkzxTB2M+yA4SAcSMYLxgCY3h+4LYssq3oelr5BSj2BPbz/dWgShQhO58HFht/k77uPZzcQgoWmr+nc//HCMqcy517cWEtj2jxkJ98Hkv+R/YHNUjzU1fraTwf4rmT2B8GYxGyLSMIf3AYXY+HEuNmUpH6hWd7bssg24HJuSjgNynFl/j9BkfdKjIs2eZhf4wVJn+HGiRroycHyAI/rgZJrdfQUB7jub/nfteWF5FD2xh/i5vtHobFOCzZ1mkUjD7XU8YjuxH9CQ3+zeSuxdj6ilhZZ2VGIds8rPsC/7P6M+HzF9EHOS5S/s7cZzSrmLU0/IUffiQm4lMbo2MchWyKW4bxi9T4A+06eG1oGYXsHZiBnsgPlv0lpRkGHMaddavgqGTn86LvxUobvFrcFn2dfZU7jqwB4/FgdIRsQx4X46hk5zEEjAaeruXC0BiHI7tJf9xqvB0Dej2FhQFPvkKj7JdBtuU6bqA/jr/CgOuvUch1nhxaMoxvA+NpPFsWxjLIFop8OWbhj//Tn5e0YReWomTzoyiNC1CAo1qiXMO3qj41KovsUISjY+ar8U30zX/M/uZwYcB2PzAS3kyDIrr6oS2nT/5lkR2KCBhvBuP7OLkpXOi39aF+sgv28i5G2Q6C1pO8v0i/2C/Pzmv2ncX6z84nux9bP0KdRNLi+NexhRY1vpXjXvNgMZ7HvZ9Pn8meLRuj+VWB0RnQW8Ho92O+3wcjlzK3kO50+Y8fMIk/TTYncc3RZ9kKCEWWbdkhX7d6Lqcx32EQ5yDrCU/mZB3WfAnQ3sA559hVYSzbsnMQUoy8keObaklyJheezF/M79vP9ZImLd7R7kZueJrU795eeUzzvET7c02bqLnTGLufTmlynegZwZpsdeisYtycctUd4xJm3V0vCa7HD8r5VWBbjNOPfs/0ymvS531l+hiFOsWSdLH0slrdqxiZwqXLgWcHo/H77GsPASNQektR4uwVGPTwNipJvyvmWx2nAr0U2LvE6q4I2H7ZLyG4htu6ea6orHqMRclWYZnisq8D8is26apP56BKHUgPrTwMhIYhOkOxyjEOQ3ZQiFtXXegmn4TmfdkaQhxFuTw2tvglhEfJpcypkpUSo685/Vnj/djOPMZRyVYZkmvfeC/KcF66G8ntJKzcsh09+xkqlzVV2dD8UmLAuDtlBdKrxlk6xnHIBncq9nUq3PfNKsI3SuZbhTJUgJ+Q1OLCdLBKoikmlU6MDuIc4c8UxjLIztQh8Iz0zewZM9cKypzK2BdryT3nkaEiFW4Dxi2ziLFMsoOOtQL70KdRiIS7KmTUyJtWK8mOsJ3rG6suswGR3UiSx2j35Z8olYXRGUUl3qoKstWelXXu+hDbxyH9pWzzS4E4HCiSGn5G0SibUgeis5psx/gwJxzE6c2ckobZQLiv39YGorcyshcwVkK0laiKbPMOEoIyRrBCfx6u9do6ElaJDsIqA9+r8BHOZ0GZjHRnJ0X0OnGMRSo1AvYVj4QBzl1YgG7PxOvIZVaQeYOspRvA0UJmgWiqmYp1NTxbW4yTIlttZMRlLsv+XLduUCYQ6odeJTnMl8N5Ts2MDML4BBiduUwF4yTJzjOmC7OfykjPwpsqYBYJzuPK79cO4zTIDoQyuuZ7ZrEx9sRRu7H2adQnT1BZ+3mMfg+VgVjiAG6qGCetXJXA9Cm+n63ujBFo4opUpxuORh2dGpgZdRrDo1OXLhjTvysXo8lgjJgnjnGSZBttYoTd8+uEXpdw31ipDK0gWAi7MyEOKokx9MQoiED6xDFWTbZk2RfTP6df8y8aFPE9tEqRcFOdRYySTAg3foStYdwi8QAxqg9nJRPBWCXZAlYBD7KVOKWIErwvNJKgEK2gqli05Y0q4rEhP8B2FIw2koAxkF5FvD3FVxXZAI/vowRDnOO6Yj2D+Ui2/XnRBsOtlUrZGJ12aumVYSyTbEnVhT0Gv8bGbaHjEk0WqZiP/bmkB9c+8QEOZecxgrPUwE/A6JglWHmpGMsgOxCKu05J1jUp4Xx2VM7/NiAblBYg6br3SYhYLFuMklx1UKQSjOOSrQKcL+uy7bOqIJhsV4jlGje3zNCfr7ippBPTxhhcu93YWDIK2YFQ3E1qyaFfDufHqtAQD1ueXsT5ujh0fWUO4sy/DhhtbPbnYhsL47BkqwBaWmrJKtmKTJpkilwh9ue6Vvu4cQc44nHwdS/bumC0TmNjHIZslZkPGNSBZKq0JDa8cYMyAaOvV+vSkJcAtus0MsZBZDvN0VWGEbb9R91IpkorJMxdHcTp+vqJeCTWhuwsImCsO85hMKb4B5Ad21c4FXB0qNRdAVkts3raSB3EBfLCtc4trjrexMlZxzgw/mAf10ue5w/FbuWP+w6EYt89D8ysV0YDztvHjj3S7FKGDRPC+XBdI/kAe3d2uUeMt08AY4iDd6nCWKfaXim+u43xjn65FbHUBmPdV/FH+K+D9CPITEspS3Cf6as/CS9LxMQSqJiG2voivfjXOdbK+0nAeBIYj+TGkjG68DJxTX1ZEjD6jfOA0fFGXylCdsiAT080j4uS1tmc0CMMzDw82GdbNtl6H9aD8aG87MsLuvFhxE+IvJofU/9VHioRY6lki5HGyIfyFtOGXBjjMGQHpe3EVwTPobBXcEKLHGQ14blu27LIVgH8kUJyI7W5kH1XwYwjYoTwFCNeYlyMpZAdMPJFiRQjL5mGk1HIDiUchUJORCHHcsJ8RiF9XLJVwAIkX4tFXkl7vy1UrqTtkW2MP0N+Y2Aci2wxNtsYrxgH4zhkq09d3SHtr/zvx77hy2FkHLKZVjH4Wmx9kAI3kcroVrrVXYwHtzHuz/4IGEcmm2ljvKWNcTNlO8ceWcYle3vBzeapGPfJzFgZjKQCkQNlWLLb9XWRQOufoffygSWUeUOzeQrlngLG3cjWuhTEOBTZASNz/hTjZWVBKI/srEZ74PY2MEA6ETW4wC7MXXvVdxiytWQV8CVIvpoMeQM1Fdm9jfG1xTEWJpspqG/VUozXgO6BMhGWTbZ1M8/dUMibaPgb2O/neoqQbX7+ZMNVjAr+in0HJkUsitsqE+u0axvj8ewPwDiQbPPjQz/Jl8F4Cfu+Ri0do4VUKUfT151Fte3P7fs6AXDcc57twIT+Me2XL2L/dlIdxV8mOruN0YhkF4w9yZ4oxqrJlhy/VXRstNg4GZs/hmNjukEh3ci2TmuJat2KO7sCm/kmx8MOinhkohIwGngSo3PfHMYVZOcxXtnGWGYgpyv4SZAdCjZg8dPtgIUvJ5yqdZJtS+drDsknUMA32LdhzJKI8ZVgJA6RvoBpY1xGthiZORD4yYIiE8M4SbIDaX5o7lws4GWcIGacunEDF3yJKflvqP4o+1rGLMtOYPw1ML4cEASeEkfvvl8Qo4Gfj6X7/DdJmQbZAZ9BmRNQxOsIwX4XBVzBhR+Ei6tkG4IyjNxb38fqxwqKzLpOHLTtRRrwqnWmYYpx71WOcaYJmld+roG5BuYamGtgroG5BuYamJoG/h/ff6XOIB4wOAAAAABJRU5ErkJggg=="/>
+ <title>Swarm index of {{ .URI }}</title>
</head>
<body>
diff --git a/swarm/storage/chunker_test.go b/swarm/storage/chunker_test.go
index 6178a7bb1..6b828970b 100644
--- a/swarm/storage/chunker_test.go
+++ b/swarm/storage/chunker_test.go
@@ -60,7 +60,7 @@ func (self *chunkerTester) Split(chunker Splitter, data io.Reader, size int64, c
for {
select {
case <-timeout:
- return errors.New(("Split timeout error"))
+ return errors.New("Split timeout error")
case <-quitC:
return nil
case chunk := <-chunkC:
@@ -97,7 +97,7 @@ func (self *chunkerTester) Append(chunker Splitter, rootKey Key, data io.Reader,
for {
select {
case <-timeout:
- return errors.New(("Append timeout error"))
+ return errors.New("Append timeout error")
case <-quitC:
return nil
case chunk := <-chunkC:
@@ -146,7 +146,7 @@ func (self *chunkerTester) Join(chunker Chunker, key Key, c int, chunkC chan *Ch
for {
select {
case <-timeout:
- return errors.New(("Join timeout error"))
+ return errors.New("Join timeout error")
case chunk, ok := <-chunkC:
if !ok {
close(quitC)
@@ -155,7 +155,7 @@ func (self *chunkerTester) Join(chunker Chunker, key Key, c int, chunkC chan *Ch
// this just mocks the behaviour of a chunk store retrieval
stored, success := self.chunks[chunk.Key.String()]
if !success {
- return errors.New(("Not found"))
+ return errors.New("Not found")
}
chunk.SData = stored.SData
chunk.Size = int64(binary.LittleEndian.Uint64(chunk.SData[0:8]))
diff --git a/swarm/storage/pyramid.go b/swarm/storage/pyramid.go
index f2e85cb5b..19d493405 100644
--- a/swarm/storage/pyramid.go
+++ b/swarm/storage/pyramid.go
@@ -338,7 +338,7 @@ func (self *PyramidChunker) loadTree(chunkLevel [][]*TreeEntry, key Key, chunkC
chunkLevel[depth-1] = append(chunkLevel[depth-1], newEntry)
// Add the rest of the tree
- for lvl := (depth - 1); lvl >= 1; lvl-- {
+ for lvl := depth - 1; lvl >= 1; lvl-- {
//TODO(jmozah): instead of loading finished branches and then trim in the end,
//avoid loading them in the first place
diff --git a/tests/block_test_util.go b/tests/block_test_util.go
index a789e6d88..beba48483 100644
--- a/tests/block_test_util.go
+++ b/tests/block_test_util.go
@@ -77,8 +77,8 @@ type btHeader struct {
UncleHash common.Hash
ExtraData []byte
Difficulty *big.Int
- GasLimit *big.Int
- GasUsed *big.Int
+ GasLimit uint64
+ GasUsed uint64
Timestamp *big.Int
}
@@ -86,8 +86,8 @@ type btHeaderMarshaling struct {
ExtraData hexutil.Bytes
Number *math.HexOrDecimal256
Difficulty *math.HexOrDecimal256
- GasLimit *math.HexOrDecimal256
- GasUsed *math.HexOrDecimal256
+ GasLimit math.HexOrDecimal64
+ GasUsed math.HexOrDecimal64
Timestamp *math.HexOrDecimal256
}
@@ -110,7 +110,7 @@ func (t *BlockTest) Run() error {
return fmt.Errorf("genesis block state root does not match test: computed=%x, test=%x", gblock.Root().Bytes()[:6], t.json.Genesis.StateRoot[:6])
}
- chain, err := core.NewBlockChain(db, config, ethash.NewShared(), vm.Config{})
+ chain, err := core.NewBlockChain(db, nil, config, ethash.NewShared(), vm.Config{})
if err != nil {
return err
}
@@ -120,7 +120,7 @@ func (t *BlockTest) Run() error {
if err != nil {
return err
}
- cmlast := chain.LastBlockHash()
+ cmlast := chain.CurrentBlock().Hash()
if common.Hash(t.json.BestBlock) != cmlast {
return fmt.Errorf("last block hash validation mismatch: want: %x, have: %x", t.json.BestBlock, cmlast)
}
@@ -141,8 +141,8 @@ func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis {
Timestamp: t.json.Genesis.Timestamp.Uint64(),
ParentHash: t.json.Genesis.ParentHash,
ExtraData: t.json.Genesis.ExtraData,
- GasLimit: t.json.Genesis.GasLimit.Uint64(),
- GasUsed: t.json.Genesis.GasUsed.Uint64(),
+ GasLimit: t.json.Genesis.GasLimit,
+ GasUsed: t.json.Genesis.GasUsed,
Difficulty: t.json.Genesis.Difficulty,
Mixhash: t.json.Genesis.MixHash,
Coinbase: t.json.Genesis.Coinbase,
@@ -234,11 +234,11 @@ func validateHeader(h *btHeader, h2 *types.Header) error {
if h.Difficulty.Cmp(h2.Difficulty) != 0 {
return fmt.Errorf("Difficulty: want: %v have: %v", h.Difficulty, h2.Difficulty)
}
- if h.GasLimit.Cmp(h2.GasLimit) != 0 {
- return fmt.Errorf("GasLimit: want: %v have: %v", h.GasLimit, h2.GasLimit)
+ if h.GasLimit != h2.GasLimit {
+ return fmt.Errorf("GasLimit: want: %d have: %d", h.GasLimit, h2.GasLimit)
}
- if h.GasUsed.Cmp(h2.GasUsed) != 0 {
- return fmt.Errorf("GasUsed: want: %v have: %v", h.GasUsed, h2.GasUsed)
+ if h.GasUsed != h2.GasUsed {
+ return fmt.Errorf("GasUsed: want: %d have: %d", h.GasUsed, h2.GasUsed)
}
if h.Timestamp.Cmp(h2.Time) != 0 {
return fmt.Errorf("Timestamp: want: %v have: %v", h.Timestamp, h2.Time)
diff --git a/tests/difficulty_test.go b/tests/difficulty_test.go
index a449b1cfa..600637300 100644
--- a/tests/difficulty_test.go
+++ b/tests/difficulty_test.go
@@ -13,7 +13,6 @@
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-//
package tests
diff --git a/tests/difficulty_test_util.go b/tests/difficulty_test_util.go
index 754147793..00d699cf7 100644
--- a/tests/difficulty_test_util.go
+++ b/tests/difficulty_test_util.go
@@ -13,7 +13,6 @@
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-//
package tests
diff --git a/tests/gen_btheader.go b/tests/gen_btheader.go
index 5d65e0dbc..5cfd4bd0a 100644
--- a/tests/gen_btheader.go
+++ b/tests/gen_btheader.go
@@ -29,8 +29,8 @@ func (b btHeader) MarshalJSON() ([]byte, error) {
UncleHash common.Hash
ExtraData hexutil.Bytes
Difficulty *math.HexOrDecimal256
- GasLimit *math.HexOrDecimal256
- GasUsed *math.HexOrDecimal256
+ GasLimit math.HexOrDecimal64
+ GasUsed math.HexOrDecimal64
Timestamp *math.HexOrDecimal256
}
var enc btHeader
@@ -47,8 +47,8 @@ func (b btHeader) MarshalJSON() ([]byte, error) {
enc.UncleHash = b.UncleHash
enc.ExtraData = b.ExtraData
enc.Difficulty = (*math.HexOrDecimal256)(b.Difficulty)
- enc.GasLimit = (*math.HexOrDecimal256)(b.GasLimit)
- enc.GasUsed = (*math.HexOrDecimal256)(b.GasUsed)
+ enc.GasLimit = math.HexOrDecimal64(b.GasLimit)
+ enc.GasUsed = math.HexOrDecimal64(b.GasUsed)
enc.Timestamp = (*math.HexOrDecimal256)(b.Timestamp)
return json.Marshal(&enc)
}
@@ -66,10 +66,10 @@ func (b *btHeader) UnmarshalJSON(input []byte) error {
StateRoot *common.Hash
TransactionsTrie *common.Hash
UncleHash *common.Hash
- ExtraData hexutil.Bytes
+ ExtraData *hexutil.Bytes
Difficulty *math.HexOrDecimal256
- GasLimit *math.HexOrDecimal256
- GasUsed *math.HexOrDecimal256
+ GasLimit *math.HexOrDecimal64
+ GasUsed *math.HexOrDecimal64
Timestamp *math.HexOrDecimal256
}
var dec btHeader
@@ -110,16 +110,16 @@ func (b *btHeader) UnmarshalJSON(input []byte) error {
b.UncleHash = *dec.UncleHash
}
if dec.ExtraData != nil {
- b.ExtraData = dec.ExtraData
+ b.ExtraData = *dec.ExtraData
}
if dec.Difficulty != nil {
b.Difficulty = (*big.Int)(dec.Difficulty)
}
if dec.GasLimit != nil {
- b.GasLimit = (*big.Int)(dec.GasLimit)
+ b.GasLimit = uint64(*dec.GasLimit)
}
if dec.GasUsed != nil {
- b.GasUsed = (*big.Int)(dec.GasUsed)
+ b.GasUsed = uint64(*dec.GasUsed)
}
if dec.Timestamp != nil {
b.Timestamp = (*big.Int)(dec.Timestamp)
diff --git a/tests/gen_stenv.go b/tests/gen_stenv.go
index c780524bc..1d4baf2fd 100644
--- a/tests/gen_stenv.go
+++ b/tests/gen_stenv.go
@@ -17,14 +17,14 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
type stEnv struct {
Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
- GasLimit *math.HexOrDecimal256 `json:"currentGasLimit" gencodec:"required"`
+ GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
}
var enc stEnv
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
enc.Difficulty = (*math.HexOrDecimal256)(s.Difficulty)
- enc.GasLimit = (*math.HexOrDecimal256)(s.GasLimit)
+ enc.GasLimit = math.HexOrDecimal64(s.GasLimit)
enc.Number = math.HexOrDecimal64(s.Number)
enc.Timestamp = math.HexOrDecimal64(s.Timestamp)
return json.Marshal(&enc)
@@ -34,7 +34,7 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
type stEnv struct {
Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
- GasLimit *math.HexOrDecimal256 `json:"currentGasLimit" gencodec:"required"`
+ GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
}
@@ -53,7 +53,7 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
if dec.GasLimit == nil {
return errors.New("missing required field 'currentGasLimit' for stEnv")
}
- s.GasLimit = (*big.Int)(dec.GasLimit)
+ s.GasLimit = uint64(*dec.GasLimit)
if dec.Number == nil {
return errors.New("missing required field 'currentNumber' for stEnv")
}
diff --git a/tests/gen_sttransaction.go b/tests/gen_sttransaction.go
index 5a489d00b..451ffcbf4 100644
--- a/tests/gen_sttransaction.go
+++ b/tests/gen_sttransaction.go
@@ -46,7 +46,7 @@ func (s *stTransaction) UnmarshalJSON(input []byte) error {
Data []string `json:"data"`
GasLimit []math.HexOrDecimal64 `json:"gasLimit"`
Value []string `json:"value"`
- PrivateKey hexutil.Bytes `json:"secretKey"`
+ PrivateKey *hexutil.Bytes `json:"secretKey"`
}
var dec stTransaction
if err := json.Unmarshal(input, &dec); err != nil {
@@ -74,7 +74,7 @@ func (s *stTransaction) UnmarshalJSON(input []byte) error {
s.Value = dec.Value
}
if dec.PrivateKey != nil {
- s.PrivateKey = dec.PrivateKey
+ s.PrivateKey = *dec.PrivateKey
}
return nil
}
diff --git a/tests/gen_tttransaction.go b/tests/gen_tttransaction.go
index b6759be91..2948842d9 100644
--- a/tests/gen_tttransaction.go
+++ b/tests/gen_tttransaction.go
@@ -17,7 +17,7 @@ var _ = (*ttTransactionMarshaling)(nil)
func (t ttTransaction) MarshalJSON() ([]byte, error) {
type ttTransaction struct {
Data hexutil.Bytes `gencodec:"required"`
- GasLimit *math.HexOrDecimal256 `gencodec:"required"`
+ GasLimit math.HexOrDecimal64 `gencodec:"required"`
GasPrice *math.HexOrDecimal256 `gencodec:"required"`
Nonce math.HexOrDecimal64 `gencodec:"required"`
Value *math.HexOrDecimal256 `gencodec:"required"`
@@ -28,7 +28,7 @@ func (t ttTransaction) MarshalJSON() ([]byte, error) {
}
var enc ttTransaction
enc.Data = t.Data
- enc.GasLimit = (*math.HexOrDecimal256)(t.GasLimit)
+ enc.GasLimit = math.HexOrDecimal64(t.GasLimit)
enc.GasPrice = (*math.HexOrDecimal256)(t.GasPrice)
enc.Nonce = math.HexOrDecimal64(t.Nonce)
enc.Value = (*math.HexOrDecimal256)(t.Value)
@@ -41,8 +41,8 @@ func (t ttTransaction) MarshalJSON() ([]byte, error) {
func (t *ttTransaction) UnmarshalJSON(input []byte) error {
type ttTransaction struct {
- Data hexutil.Bytes `gencodec:"required"`
- GasLimit *math.HexOrDecimal256 `gencodec:"required"`
+ Data *hexutil.Bytes `gencodec:"required"`
+ GasLimit *math.HexOrDecimal64 `gencodec:"required"`
GasPrice *math.HexOrDecimal256 `gencodec:"required"`
Nonce *math.HexOrDecimal64 `gencodec:"required"`
Value *math.HexOrDecimal256 `gencodec:"required"`
@@ -58,11 +58,11 @@ func (t *ttTransaction) UnmarshalJSON(input []byte) error {
if dec.Data == nil {
return errors.New("missing required field 'data' for ttTransaction")
}
- t.Data = dec.Data
+ t.Data = *dec.Data
if dec.GasLimit == nil {
return errors.New("missing required field 'gasLimit' for ttTransaction")
}
- t.GasLimit = (*big.Int)(dec.GasLimit)
+ t.GasLimit = uint64(*dec.GasLimit)
if dec.GasPrice == nil {
return errors.New("missing required field 'gasPrice' for ttTransaction")
}
diff --git a/tests/gen_vmexec.go b/tests/gen_vmexec.go
index dd2d3d94e..a5f01cf45 100644
--- a/tests/gen_vmexec.go
+++ b/tests/gen_vmexec.go
@@ -42,8 +42,8 @@ func (v *vmExec) UnmarshalJSON(input []byte) error {
Address *common.UnprefixedAddress `json:"address" gencodec:"required"`
Caller *common.UnprefixedAddress `json:"caller" gencodec:"required"`
Origin *common.UnprefixedAddress `json:"origin" gencodec:"required"`
- Code hexutil.Bytes `json:"code" gencodec:"required"`
- Data hexutil.Bytes `json:"data" gencodec:"required"`
+ Code *hexutil.Bytes `json:"code" gencodec:"required"`
+ Data *hexutil.Bytes `json:"data" gencodec:"required"`
Value *math.HexOrDecimal256 `json:"value" gencodec:"required"`
GasLimit *math.HexOrDecimal64 `json:"gas" gencodec:"required"`
GasPrice *math.HexOrDecimal256 `json:"gasPrice" gencodec:"required"`
@@ -67,11 +67,11 @@ func (v *vmExec) UnmarshalJSON(input []byte) error {
if dec.Code == nil {
return errors.New("missing required field 'code' for vmExec")
}
- v.Code = dec.Code
+ v.Code = *dec.Code
if dec.Data == nil {
return errors.New("missing required field 'data' for vmExec")
}
- v.Data = dec.Data
+ v.Data = *dec.Data
if dec.Value == nil {
return errors.New("missing required field 'value' for vmExec")
}
diff --git a/tests/init.go b/tests/init.go
index 9e884efe3..ff8ee7da1 100644
--- a/tests/init.go
+++ b/tests/init.go
@@ -1,4 +1,4 @@
-// Copyright 2017 The go-ethereum Authors
+// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
diff --git a/tests/init_test.go b/tests/init_test.go
index ebb0d32c3..fbb214b08 100644
--- a/tests/init_test.go
+++ b/tests/init_test.go
@@ -1,4 +1,4 @@
-// Copyright 2015 The go-ethereum Authors
+// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
diff --git a/tests/state_test.go b/tests/state_test.go
index 5a67b290d..9ca5f1830 100644
--- a/tests/state_test.go
+++ b/tests/state_test.go
@@ -1,4 +1,4 @@
-// Copyright 2017 The go-ethereum Authors
+// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
@@ -39,16 +39,12 @@ func TestState(t *testing.T) {
st.fails(`^stRevertTest/RevertPrefoundEmptyOOG\.json/EIP158`, "bug in test")
st.fails(`^stRevertTest/RevertPrecompiledTouch\.json/Byzantium`, "bug in test")
st.fails(`^stRevertTest/RevertPrefoundEmptyOOG\.json/Byzantium`, "bug in test")
- st.fails(`^stRandom/randomStatetest645\.json/EIP150/.*`, "known bug #15119")
- st.fails(`^stRandom/randomStatetest645\.json/Frontier/.*`, "known bug #15119")
- st.fails(`^stRandom/randomStatetest645\.json/Homestead/.*`, "known bug #15119")
- st.fails(`^stRandom/randomStatetest644\.json/EIP150/.*`, "known bug #15119")
- st.fails(`^stRandom/randomStatetest644\.json/Frontier/.*`, "known bug #15119")
- st.fails(`^stRandom/randomStatetest644\.json/Homestead/.*`, "known bug #15119")
+ st.fails(`^stRandom2/randomStatetest64[45]\.json/(EIP150|Frontier|Homestead)/.*`, "known bug #15119")
st.fails(`^stCreateTest/TransactionCollisionToEmpty\.json/EIP158/2`, "known bug ")
st.fails(`^stCreateTest/TransactionCollisionToEmpty\.json/EIP158/3`, "known bug ")
st.fails(`^stCreateTest/TransactionCollisionToEmpty\.json/Byzantium/2`, "known bug ")
st.fails(`^stCreateTest/TransactionCollisionToEmpty\.json/Byzantium/3`, "known bug ")
+
st.walk(t, stateTestDir, func(t *testing.T, name string, test *StateTest) {
for _, subtest := range test.Subtests() {
subtest := subtest
@@ -68,8 +64,7 @@ func TestState(t *testing.T) {
}
// Transactions with gasLimit above this value will not get a VM trace on failure.
-//const traceErrorLimit = 400000
-const traceErrorLimit = 0
+const traceErrorLimit = 400000
func withTrace(t *testing.T, gasLimit uint64, test func(vm.Config) error) {
err := test(vm.Config{})
@@ -93,4 +88,6 @@ func withTrace(t *testing.T, gasLimit uint64, test func(vm.Config) error) {
} else {
t.Log("EVM operation log:\n" + buf.String())
}
+ t.Logf("EVM output: 0x%x", tracer.Output())
+ t.Logf("EVM error: %v", tracer.Error())
}
diff --git a/tests/state_test_util.go b/tests/state_test_util.go
index 1f4fb2bd5..3b761bd77 100644
--- a/tests/state_test_util.go
+++ b/tests/state_test_util.go
@@ -1,4 +1,4 @@
-// Copyright 2017 The go-ethereum Authors
+// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
@@ -76,7 +76,7 @@ type stPostState struct {
type stEnv struct {
Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
Difficulty *big.Int `json:"currentDifficulty" gencodec:"required"`
- GasLimit *big.Int `json:"currentGasLimit" gencodec:"required"`
+ GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
Number uint64 `json:"currentNumber" gencodec:"required"`
Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
}
@@ -84,7 +84,7 @@ type stEnv struct {
type stEnvMarshaling struct {
Coinbase common.UnprefixedAddress
Difficulty *math.HexOrDecimal256
- GasLimit *math.HexOrDecimal256
+ GasLimit math.HexOrDecimal64
Number math.HexOrDecimal64
Timestamp math.HexOrDecimal64
}
@@ -125,7 +125,7 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) (*state.StateD
if !ok {
return nil, UnsupportedForkError{subtest.Fork}
}
- block, _ := t.genesis(config).ToBlock()
+ block := t.genesis(config).ToBlock(nil)
db, _ := ethdb.NewMemDatabase()
statedb := MakePreState(db, t.json.Pre)
@@ -147,7 +147,7 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) (*state.StateD
if logs := rlpHash(statedb.Logs()); logs != common.Hash(post.Logs) {
return statedb, fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs)
}
- root, _ := statedb.CommitTo(db, config.IsEIP158(block.Number()))
+ root, _ := statedb.Commit(config.IsEIP158(block.Number()))
if root != common.Hash(post.Root) {
return statedb, fmt.Errorf("post state root mismatch: got %x, want %x", root, post.Root)
}
@@ -170,7 +170,7 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB
}
}
// Commit and re-open to start with a clean state.
- root, _ := statedb.CommitTo(db, false)
+ root, _ := statedb.Commit(false)
statedb, _ = state.New(root, sdb)
return statedb
}
@@ -180,7 +180,7 @@ func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
Config: config,
Coinbase: t.json.Env.Coinbase,
Difficulty: t.json.Env.Difficulty,
- GasLimit: t.json.Env.GasLimit.Uint64(),
+ GasLimit: t.json.Env.GasLimit,
Number: t.json.Env.Number,
Timestamp: t.json.Env.Timestamp,
Alloc: t.json.Pre,
@@ -233,7 +233,7 @@ func (tx *stTransaction) toMessage(ps stPostState) (core.Message, error) {
return nil, fmt.Errorf("invalid tx data %q", dataHex)
}
- msg := types.NewMessage(from, to, tx.Nonce, value, new(big.Int).SetUint64(gasLimit), tx.GasPrice, data, true)
+ msg := types.NewMessage(from, to, tx.Nonce, value, gasLimit, tx.GasPrice, data, true)
return msg, nil
}
diff --git a/tests/testdata b/tests/testdata
-Subproject 37f555fbc091fbf761aa6f02227132fb31f0681
+Subproject 2bb0c3da3bbb15c528bcef2a7e5ac4bd73f81f8
diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go
index 472b3d6f2..2028d2a27 100644
--- a/tests/transaction_test_util.go
+++ b/tests/transaction_test_util.go
@@ -46,7 +46,7 @@ type ttJSON struct {
type ttTransaction struct {
Data []byte `gencodec:"required"`
- GasLimit *big.Int `gencodec:"required"`
+ GasLimit uint64 `gencodec:"required"`
GasPrice *big.Int `gencodec:"required"`
Nonce uint64 `gencodec:"required"`
Value *big.Int `gencodec:"required"`
@@ -58,7 +58,7 @@ type ttTransaction struct {
type ttTransactionMarshaling struct {
Data hexutil.Bytes
- GasLimit *math.HexOrDecimal256
+ GasLimit math.HexOrDecimal64
GasPrice *math.HexOrDecimal256
Nonce math.HexOrDecimal64
Value *math.HexOrDecimal256
@@ -100,8 +100,8 @@ func (tt *ttTransaction) verify(signer types.Signer, tx *types.Transaction) erro
if !bytes.Equal(tx.Data(), tt.Data) {
return fmt.Errorf("Tx input data mismatch: got %x want %x", tx.Data(), tt.Data)
}
- if tx.Gas().Cmp(tt.GasLimit) != 0 {
- return fmt.Errorf("GasLimit mismatch: got %v, want %v", tx.Gas(), tt.GasLimit)
+ if tx.Gas() != tt.GasLimit {
+ return fmt.Errorf("GasLimit mismatch: got %d, want %d", tx.Gas(), tt.GasLimit)
}
if tx.GasPrice().Cmp(tt.GasPrice) != 0 {
return fmt.Errorf("GasPrice mismatch: got %v, want %v", tx.GasPrice(), tt.GasPrice)
diff --git a/trie/database.go b/trie/database.go
new file mode 100644
index 000000000..da36e72f9
--- /dev/null
+++ b/trie/database.go
@@ -0,0 +1,355 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package trie
+
+import (
+ "sync"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/log"
+)
+
+// secureKeyPrefix is the database key prefix used to store trie node preimages.
+var secureKeyPrefix = []byte("secure-key-")
+
+// secureKeyLength is the length of the above prefix + 32byte hash.
+const secureKeyLength = 11 + 32
+
+// DatabaseReader wraps the Get and Has method of a backing store for the trie.
+type DatabaseReader interface {
+ // Get retrieves the value associated with key form the database.
+ Get(key []byte) (value []byte, err error)
+
+ // Has retrieves whether a key is present in the database.
+ Has(key []byte) (bool, error)
+}
+
+// Database is an intermediate write layer between the trie data structures and
+// the disk database. The aim is to accumulate trie writes in-memory and only
+// periodically flush a couple tries to disk, garbage collecting the remainder.
+type Database struct {
+ diskdb ethdb.Database // Persistent storage for matured trie nodes
+
+ nodes map[common.Hash]*cachedNode // Data and references relationships of a node
+ preimages map[common.Hash][]byte // Preimages of nodes from the secure trie
+ seckeybuf [secureKeyLength]byte // Ephemeral buffer for calculating preimage keys
+
+ gctime time.Duration // Time spent on garbage collection since last commit
+ gcnodes uint64 // Nodes garbage collected since last commit
+ gcsize common.StorageSize // Data storage garbage collected since last commit
+
+ nodesSize common.StorageSize // Storage size of the nodes cache
+ preimagesSize common.StorageSize // Storage size of the preimages cache
+
+ lock sync.RWMutex
+}
+
+// cachedNode is all the information we know about a single cached node in the
+// memory database write layer.
+type cachedNode struct {
+ blob []byte // Cached data block of the trie node
+ parents int // Number of live nodes referencing this one
+ children map[common.Hash]int // Children referenced by this nodes
+}
+
+// NewDatabase creates a new trie database to store ephemeral trie content before
+// its written out to disk or garbage collected.
+func NewDatabase(diskdb ethdb.Database) *Database {
+ return &Database{
+ diskdb: diskdb,
+ nodes: map[common.Hash]*cachedNode{
+ {}: {children: make(map[common.Hash]int)},
+ },
+ preimages: make(map[common.Hash][]byte),
+ }
+}
+
+// DiskDB retrieves the persistent storage backing the trie database.
+func (db *Database) DiskDB() DatabaseReader {
+ return db.diskdb
+}
+
+// Insert writes a new trie node to the memory database if it's yet unknown. The
+// method will make a copy of the slice.
+func (db *Database) Insert(hash common.Hash, blob []byte) {
+ db.lock.Lock()
+ defer db.lock.Unlock()
+
+ db.insert(hash, blob)
+}
+
+// insert is the private locked version of Insert.
+func (db *Database) insert(hash common.Hash, blob []byte) {
+ if _, ok := db.nodes[hash]; ok {
+ return
+ }
+ db.nodes[hash] = &cachedNode{
+ blob: common.CopyBytes(blob),
+ children: make(map[common.Hash]int),
+ }
+ db.nodesSize += common.StorageSize(common.HashLength + len(blob))
+}
+
+// insertPreimage writes a new trie node pre-image to the memory database if it's
+// yet unknown. The method will make a copy of the slice.
+//
+// Note, this method assumes that the database's lock is held!
+func (db *Database) insertPreimage(hash common.Hash, preimage []byte) {
+ if _, ok := db.preimages[hash]; ok {
+ return
+ }
+ db.preimages[hash] = common.CopyBytes(preimage)
+ db.preimagesSize += common.StorageSize(common.HashLength + len(preimage))
+}
+
+// Node retrieves a cached trie node from memory. If it cannot be found cached,
+// the method queries the persistent database for the content.
+func (db *Database) Node(hash common.Hash) ([]byte, error) {
+ // Retrieve the node from cache if available
+ db.lock.RLock()
+ node := db.nodes[hash]
+ db.lock.RUnlock()
+
+ if node != nil {
+ return node.blob, nil
+ }
+ // Content unavailable in memory, attempt to retrieve from disk
+ return db.diskdb.Get(hash[:])
+}
+
+// preimage retrieves a cached trie node pre-image from memory. If it cannot be
+// found cached, the method queries the persistent database for the content.
+func (db *Database) preimage(hash common.Hash) ([]byte, error) {
+ // Retrieve the node from cache if available
+ db.lock.RLock()
+ preimage := db.preimages[hash]
+ db.lock.RUnlock()
+
+ if preimage != nil {
+ return preimage, nil
+ }
+ // Content unavailable in memory, attempt to retrieve from disk
+ return db.diskdb.Get(db.secureKey(hash[:]))
+}
+
+// secureKey returns the database key for the preimage of key, as an ephemeral
+// buffer. The caller must not hold onto the return value because it will become
+// invalid on the next call.
+func (db *Database) secureKey(key []byte) []byte {
+ buf := append(db.seckeybuf[:0], secureKeyPrefix...)
+ buf = append(buf, key...)
+ return buf
+}
+
+// Nodes retrieves the hashes of all the nodes cached within the memory database.
+// This method is extremely expensive and should only be used to validate internal
+// states in test code.
+func (db *Database) Nodes() []common.Hash {
+ db.lock.RLock()
+ defer db.lock.RUnlock()
+
+ var hashes = make([]common.Hash, 0, len(db.nodes))
+ for hash := range db.nodes {
+ if hash != (common.Hash{}) { // Special case for "root" references/nodes
+ hashes = append(hashes, hash)
+ }
+ }
+ return hashes
+}
+
+// Reference adds a new reference from a parent node to a child node.
+func (db *Database) Reference(child common.Hash, parent common.Hash) {
+ db.lock.RLock()
+ defer db.lock.RUnlock()
+
+ db.reference(child, parent)
+}
+
+// reference is the private locked version of Reference.
+func (db *Database) reference(child common.Hash, parent common.Hash) {
+ // If the node does not exist, it's a node pulled from disk, skip
+ node, ok := db.nodes[child]
+ if !ok {
+ return
+ }
+ // If the reference already exists, only duplicate for roots
+ if _, ok = db.nodes[parent].children[child]; ok && parent != (common.Hash{}) {
+ return
+ }
+ node.parents++
+ db.nodes[parent].children[child]++
+}
+
+// Dereference removes an existing reference from a parent node to a child node.
+func (db *Database) Dereference(child common.Hash, parent common.Hash) {
+ db.lock.Lock()
+ defer db.lock.Unlock()
+
+ nodes, storage, start := len(db.nodes), db.nodesSize, time.Now()
+ db.dereference(child, parent)
+
+ db.gcnodes += uint64(nodes - len(db.nodes))
+ db.gcsize += storage - db.nodesSize
+ db.gctime += time.Since(start)
+
+ log.Debug("Dereferenced trie from memory database", "nodes", nodes-len(db.nodes), "size", storage-db.nodesSize, "time", time.Since(start),
+ "gcnodes", db.gcnodes, "gcsize", db.gcsize, "gctime", db.gctime, "livenodes", len(db.nodes), "livesize", db.nodesSize)
+}
+
+// dereference is the private locked version of Dereference.
+func (db *Database) dereference(child common.Hash, parent common.Hash) {
+ // Dereference the parent-child
+ node := db.nodes[parent]
+
+ node.children[child]--
+ if node.children[child] == 0 {
+ delete(node.children, child)
+ }
+ // If the node does not exist, it's a previously committed node.
+ node, ok := db.nodes[child]
+ if !ok {
+ return
+ }
+ // If there are no more references to the child, delete it and cascade
+ node.parents--
+ if node.parents == 0 {
+ for hash := range node.children {
+ db.dereference(hash, child)
+ }
+ delete(db.nodes, child)
+ db.nodesSize -= common.StorageSize(common.HashLength + len(node.blob))
+ }
+}
+
+// Commit iterates over all the children of a particular node, writes them out
+// to disk, forcefully tearing down all references in both directions.
+//
+// As a side effect, all pre-images accumulated up to this point are also written.
+func (db *Database) Commit(node common.Hash, report bool) error {
+ // Create a database batch to flush persistent data out. It is important that
+ // outside code doesn't see an inconsistent state (referenced data removed from
+ // memory cache during commit but not yet in persistent storage). This is ensured
+ // by only uncaching existing data when the database write finalizes.
+ db.lock.RLock()
+
+ start := time.Now()
+ batch := db.diskdb.NewBatch()
+
+ // Move all of the accumulated preimages into a write batch
+ for hash, preimage := range db.preimages {
+ if err := batch.Put(db.secureKey(hash[:]), preimage); err != nil {
+ log.Error("Failed to commit preimage from trie database", "err", err)
+ db.lock.RUnlock()
+ return err
+ }
+ if batch.ValueSize() > ethdb.IdealBatchSize {
+ if err := batch.Write(); err != nil {
+ return err
+ }
+ batch.Reset()
+ }
+ }
+ // Move the trie itself into the batch, flushing if enough data is accumulated
+ nodes, storage := len(db.nodes), db.nodesSize+db.preimagesSize
+ if err := db.commit(node, batch); err != nil {
+ log.Error("Failed to commit trie from trie database", "err", err)
+ db.lock.RUnlock()
+ return err
+ }
+ // Write batch ready, unlock for readers during persistence
+ if err := batch.Write(); err != nil {
+ log.Error("Failed to write trie to disk", "err", err)
+ db.lock.RUnlock()
+ return err
+ }
+ db.lock.RUnlock()
+
+ // Write successful, clear out the flushed data
+ db.lock.Lock()
+ defer db.lock.Unlock()
+
+ db.preimages = make(map[common.Hash][]byte)
+ db.preimagesSize = 0
+
+ db.uncache(node)
+
+ logger := log.Info
+ if !report {
+ logger = log.Debug
+ }
+ logger("Persisted trie from memory database", "nodes", nodes-len(db.nodes), "size", storage-db.nodesSize, "time", time.Since(start),
+ "gcnodes", db.gcnodes, "gcsize", db.gcsize, "gctime", db.gctime, "livenodes", len(db.nodes), "livesize", db.nodesSize)
+
+ // Reset the garbage collection statistics
+ db.gcnodes, db.gcsize, db.gctime = 0, 0, 0
+
+ return nil
+}
+
+// commit is the private locked version of Commit.
+func (db *Database) commit(hash common.Hash, batch ethdb.Batch) error {
+ // If the node does not exist, it's a previously committed node
+ node, ok := db.nodes[hash]
+ if !ok {
+ return nil
+ }
+ for child := range node.children {
+ if err := db.commit(child, batch); err != nil {
+ return err
+ }
+ }
+ if err := batch.Put(hash[:], node.blob); err != nil {
+ return err
+ }
+ // If we've reached an optimal match size, commit and start over
+ if batch.ValueSize() >= ethdb.IdealBatchSize {
+ if err := batch.Write(); err != nil {
+ return err
+ }
+ batch.Reset()
+ }
+ return nil
+}
+
+// uncache is the post-processing step of a commit operation where the already
+// persisted trie is removed from the cache. The reason behind the two-phase
+// commit is to ensure consistent data availability while moving from memory
+// to disk.
+func (db *Database) uncache(hash common.Hash) {
+ // If the node does not exist, we're done on this path
+ node, ok := db.nodes[hash]
+ if !ok {
+ return
+ }
+ // Otherwise uncache the node's subtries and remove the node itself too
+ for child := range node.children {
+ db.uncache(child)
+ }
+ delete(db.nodes, hash)
+ db.nodesSize -= common.StorageSize(common.HashLength + len(node.blob))
+}
+
+// Size returns the current storage size of the memory cache in front of the
+// persistent database layer.
+func (db *Database) Size() common.StorageSize {
+ db.lock.RLock()
+ defer db.lock.RUnlock()
+
+ return db.nodesSize + db.preimagesSize
+}
diff --git a/trie/hasher.go b/trie/hasher.go
index 5186d7669..2fc44787a 100644
--- a/trie/hasher.go
+++ b/trie/hasher.go
@@ -26,51 +26,34 @@ import (
"github.com/ethereum/go-ethereum/rlp"
)
-// calculator is a utility used by the hasher to calculate the hash value of the tree node.
-type calculator struct {
- sha hash.Hash
- buffer *bytes.Buffer
-}
-
-// calculatorPool is a set of temporary calculators that may be individually saved and retrieved.
-var calculatorPool = sync.Pool{
- New: func() interface{} {
- return &calculator{buffer: new(bytes.Buffer), sha: sha3.NewKeccak256()}
- },
-}
-
-// hasher hasher is used to calculate the hash value of the whole tree.
type hasher struct {
+ tmp *bytes.Buffer
+ sha hash.Hash
cachegen uint16
cachelimit uint16
- threaded bool
- mu sync.Mutex
+ onleaf LeafCallback
}
-func newHasher(cachegen, cachelimit uint16) *hasher {
- h := &hasher{
- cachegen: cachegen,
- cachelimit: cachelimit,
- }
- return h
+// hashers live in a global db.
+var hasherPool = sync.Pool{
+ New: func() interface{} {
+ return &hasher{tmp: new(bytes.Buffer), sha: sha3.NewKeccak256()}
+ },
}
-// newCalculator retrieves a cleaned calculator from calculator pool.
-func (h *hasher) newCalculator() *calculator {
- calculator := calculatorPool.Get().(*calculator)
- calculator.buffer.Reset()
- calculator.sha.Reset()
- return calculator
+func newHasher(cachegen, cachelimit uint16, onleaf LeafCallback) *hasher {
+ h := hasherPool.Get().(*hasher)
+ h.cachegen, h.cachelimit, h.onleaf = cachegen, cachelimit, onleaf
+ return h
}
-// returnCalculator returns a no longer used calculator to the pool.
-func (h *hasher) returnCalculator(calculator *calculator) {
- calculatorPool.Put(calculator)
+func returnHasherToPool(h *hasher) {
+ hasherPool.Put(h)
}
// hash collapses a node down into a hash node, also returning a copy of the
// original node initialized with the computed hash to replace the original one.
-func (h *hasher) hash(n node, db DatabaseWriter, force bool) (node, node, error) {
+func (h *hasher) hash(n node, db *Database, force bool) (node, node, error) {
// If we're not storing the node, just hashing, use available cached data
if hash, dirty := n.cache(); hash != nil {
if db == nil {
@@ -117,7 +100,7 @@ func (h *hasher) hash(n node, db DatabaseWriter, force bool) (node, node, error)
// hashChildren replaces the children of a node with their hashes if the encoded
// size of the child is larger than a hash, returning the collapsed node as well
// as a replacement for the original node with the child hashes cached in.
-func (h *hasher) hashChildren(original node, db DatabaseWriter) (node, node, error) {
+func (h *hasher) hashChildren(original node, db *Database) (node, node, error) {
var err error
switch n := original.(type) {
@@ -142,49 +125,16 @@ func (h *hasher) hashChildren(original node, db DatabaseWriter) (node, node, err
// Hash the full node's children, caching the newly hashed subtrees
collapsed, cached := n.copy(), n.copy()
- // hashChild is a helper to hash a single child, which is called either on the
- // same thread as the caller or in a goroutine for the toplevel branching.
- hashChild := func(index int, wg *sync.WaitGroup) {
- if wg != nil {
- defer wg.Done()
- }
- // Ensure that nil children are encoded as empty strings.
- if collapsed.Children[index] == nil {
- collapsed.Children[index] = valueNode(nil)
- return
- }
- // Hash all other children properly
- var herr error
- collapsed.Children[index], cached.Children[index], herr = h.hash(n.Children[index], db, false)
- if herr != nil {
- h.mu.Lock() // rarely if ever locked, no congenstion
- err = herr
- h.mu.Unlock()
+ for i := 0; i < 16; i++ {
+ if n.Children[i] != nil {
+ collapsed.Children[i], cached.Children[i], err = h.hash(n.Children[i], db, false)
+ if err != nil {
+ return original, original, err
+ }
+ } else {
+ collapsed.Children[i] = valueNode(nil) // Ensure that nil children are encoded as empty strings.
}
}
- // If we're not running in threaded mode yet, span a goroutine for each child
- if !h.threaded {
- // Disable further threading
- h.threaded = true
-
- // Hash all the children concurrently
- var wg sync.WaitGroup
- for i := 0; i < 16; i++ {
- wg.Add(1)
- go hashChild(i, &wg)
- }
- wg.Wait()
-
- // Reenable threading for subsequent hash calls
- h.threaded = false
- } else {
- for i := 0; i < 16; i++ {
- hashChild(i, nil)
- }
- }
- if err != nil {
- return original, original, err
- }
cached.Children[16] = n.Children[16]
if collapsed.Children[16] == nil {
collapsed.Children[16] = valueNode(nil)
@@ -197,34 +147,66 @@ func (h *hasher) hashChildren(original node, db DatabaseWriter) (node, node, err
}
}
-func (h *hasher) store(n node, db DatabaseWriter, force bool) (node, error) {
+// store hashes the node n and if we have a storage layer specified, it writes
+// the key/value pair to it and tracks any node->child references as well as any
+// node->external trie references.
+func (h *hasher) store(n node, db *Database, force bool) (node, error) {
// Don't store hashes or empty nodes.
if _, isHash := n.(hashNode); n == nil || isHash {
return n, nil
}
- calculator := h.newCalculator()
- defer h.returnCalculator(calculator)
-
// Generate the RLP encoding of the node
- if err := rlp.Encode(calculator.buffer, n); err != nil {
+ h.tmp.Reset()
+ if err := rlp.Encode(h.tmp, n); err != nil {
panic("encode error: " + err.Error())
}
- if calculator.buffer.Len() < 32 && !force {
+ if h.tmp.Len() < 32 && !force {
return n, nil // Nodes smaller than 32 bytes are stored inside their parent
}
// Larger nodes are replaced by their hash and stored in the database.
hash, _ := n.cache()
if hash == nil {
- calculator.sha.Write(calculator.buffer.Bytes())
- hash = hashNode(calculator.sha.Sum(nil))
+ h.sha.Reset()
+ h.sha.Write(h.tmp.Bytes())
+ hash = hashNode(h.sha.Sum(nil))
}
if db != nil {
- // db might be a leveldb batch, which is not safe for concurrent writes
- h.mu.Lock()
- err := db.Put(hash, calculator.buffer.Bytes())
- h.mu.Unlock()
+ // We are pooling the trie nodes into an intermediate memory cache
+ db.lock.Lock()
- return hash, err
+ hash := common.BytesToHash(hash)
+ db.insert(hash, h.tmp.Bytes())
+
+ // Track all direct parent->child node references
+ switch n := n.(type) {
+ case *shortNode:
+ if child, ok := n.Val.(hashNode); ok {
+ db.reference(common.BytesToHash(child), hash)
+ }
+ case *fullNode:
+ for i := 0; i < 16; i++ {
+ if child, ok := n.Children[i].(hashNode); ok {
+ db.reference(common.BytesToHash(child), hash)
+ }
+ }
+ }
+ db.lock.Unlock()
+
+ // Track external references from account->storage trie
+ if h.onleaf != nil {
+ switch n := n.(type) {
+ case *shortNode:
+ if child, ok := n.Val.(valueNode); ok {
+ h.onleaf(child, hash)
+ }
+ case *fullNode:
+ for i := 0; i < 16; i++ {
+ if child, ok := n.Children[i].(valueNode); ok {
+ h.onleaf(child, hash)
+ }
+ }
+ }
+ }
}
return hash, nil
}
diff --git a/trie/iterator_test.go b/trie/iterator_test.go
index 4808d8b0c..dce1c78b5 100644
--- a/trie/iterator_test.go
+++ b/trie/iterator_test.go
@@ -42,7 +42,7 @@ func TestIterator(t *testing.T) {
all[val.k] = val.v
trie.Update([]byte(val.k), []byte(val.v))
}
- trie.Commit()
+ trie.Commit(nil)
found := make(map[string]string)
it := NewIterator(trie.NodeIterator(nil))
@@ -109,11 +109,18 @@ func TestNodeIteratorCoverage(t *testing.T) {
}
// Cross check the hashes and the database itself
for hash := range hashes {
- if _, err := db.Get(hash.Bytes()); err != nil {
+ if _, err := db.Node(hash); err != nil {
t.Errorf("failed to retrieve reported node %x: %v", hash, err)
}
}
- for _, key := range db.(*ethdb.MemDatabase).Keys() {
+ for hash, obj := range db.nodes {
+ if obj != nil && hash != (common.Hash{}) {
+ if _, ok := hashes[hash]; !ok {
+ t.Errorf("state entry not reported %x", hash)
+ }
+ }
+ }
+ for _, key := range db.diskdb.(*ethdb.MemDatabase).Keys() {
if _, ok := hashes[common.BytesToHash(key)]; !ok {
t.Errorf("state entry not reported %x", key)
}
@@ -191,13 +198,13 @@ func TestDifferenceIterator(t *testing.T) {
for _, val := range testdata1 {
triea.Update([]byte(val.k), []byte(val.v))
}
- triea.Commit()
+ triea.Commit(nil)
trieb := newEmpty()
for _, val := range testdata2 {
trieb.Update([]byte(val.k), []byte(val.v))
}
- trieb.Commit()
+ trieb.Commit(nil)
found := make(map[string]string)
di, _ := NewDifferenceIterator(triea.NodeIterator(nil), trieb.NodeIterator(nil))
@@ -227,13 +234,13 @@ func TestUnionIterator(t *testing.T) {
for _, val := range testdata1 {
triea.Update([]byte(val.k), []byte(val.v))
}
- triea.Commit()
+ triea.Commit(nil)
trieb := newEmpty()
for _, val := range testdata2 {
trieb.Update([]byte(val.k), []byte(val.v))
}
- trieb.Commit()
+ trieb.Commit(nil)
di, _ := NewUnionIterator([]NodeIterator{triea.NodeIterator(nil), trieb.NodeIterator(nil)})
it := NewIterator(di)
@@ -278,43 +285,75 @@ func TestIteratorNoDups(t *testing.T) {
}
// This test checks that nodeIterator.Next can be retried after inserting missing trie nodes.
-func TestIteratorContinueAfterError(t *testing.T) {
- db, _ := ethdb.NewMemDatabase()
- tr, _ := New(common.Hash{}, db)
+func TestIteratorContinueAfterErrorDisk(t *testing.T) { testIteratorContinueAfterError(t, false) }
+func TestIteratorContinueAfterErrorMemonly(t *testing.T) { testIteratorContinueAfterError(t, true) }
+
+func testIteratorContinueAfterError(t *testing.T, memonly bool) {
+ diskdb, _ := ethdb.NewMemDatabase()
+ triedb := NewDatabase(diskdb)
+
+ tr, _ := New(common.Hash{}, triedb)
for _, val := range testdata1 {
tr.Update([]byte(val.k), []byte(val.v))
}
- tr.Commit()
+ tr.Commit(nil)
+ if !memonly {
+ triedb.Commit(tr.Hash(), true)
+ }
wantNodeCount := checkIteratorNoDups(t, tr.NodeIterator(nil), nil)
- keys := db.Keys()
- t.Log("node count", wantNodeCount)
+ var (
+ diskKeys [][]byte
+ memKeys []common.Hash
+ )
+ if memonly {
+ memKeys = triedb.Nodes()
+ } else {
+ diskKeys = diskdb.Keys()
+ }
for i := 0; i < 20; i++ {
// Create trie that will load all nodes from DB.
- tr, _ := New(tr.Hash(), db)
+ tr, _ := New(tr.Hash(), triedb)
// Remove a random node from the database. It can't be the root node
// because that one is already loaded.
- var rkey []byte
+ var (
+ rkey common.Hash
+ rval []byte
+ robj *cachedNode
+ )
for {
- if rkey = keys[rand.Intn(len(keys))]; !bytes.Equal(rkey, tr.Hash().Bytes()) {
+ if memonly {
+ rkey = memKeys[rand.Intn(len(memKeys))]
+ } else {
+ copy(rkey[:], diskKeys[rand.Intn(len(diskKeys))])
+ }
+ if rkey != tr.Hash() {
break
}
}
- rval, _ := db.Get(rkey)
- db.Delete(rkey)
-
+ if memonly {
+ robj = triedb.nodes[rkey]
+ delete(triedb.nodes, rkey)
+ } else {
+ rval, _ = diskdb.Get(rkey[:])
+ diskdb.Delete(rkey[:])
+ }
// Iterate until the error is hit.
seen := make(map[string]bool)
it := tr.NodeIterator(nil)
checkIteratorNoDups(t, it, seen)
missing, ok := it.Error().(*MissingNodeError)
- if !ok || !bytes.Equal(missing.NodeHash[:], rkey) {
+ if !ok || missing.NodeHash != rkey {
t.Fatal("didn't hit missing node, got", it.Error())
}
// Add the node back and continue iteration.
- db.Put(rkey, rval)
+ if memonly {
+ triedb.nodes[rkey] = robj
+ } else {
+ diskdb.Put(rkey[:], rval)
+ }
checkIteratorNoDups(t, it, seen)
if it.Error() != nil {
t.Fatal("unexpected error", it.Error())
@@ -328,21 +367,41 @@ func TestIteratorContinueAfterError(t *testing.T) {
// Similar to the test above, this one checks that failure to create nodeIterator at a
// certain key prefix behaves correctly when Next is called. The expectation is that Next
// should retry seeking before returning true for the first time.
-func TestIteratorContinueAfterSeekError(t *testing.T) {
+func TestIteratorContinueAfterSeekErrorDisk(t *testing.T) {
+ testIteratorContinueAfterSeekError(t, false)
+}
+func TestIteratorContinueAfterSeekErrorMemonly(t *testing.T) {
+ testIteratorContinueAfterSeekError(t, true)
+}
+
+func testIteratorContinueAfterSeekError(t *testing.T, memonly bool) {
// Commit test trie to db, then remove the node containing "bars".
- db, _ := ethdb.NewMemDatabase()
- ctr, _ := New(common.Hash{}, db)
+ diskdb, _ := ethdb.NewMemDatabase()
+ triedb := NewDatabase(diskdb)
+
+ ctr, _ := New(common.Hash{}, triedb)
for _, val := range testdata1 {
ctr.Update([]byte(val.k), []byte(val.v))
}
- root, _ := ctr.Commit()
+ root, _ := ctr.Commit(nil)
+ if !memonly {
+ triedb.Commit(root, true)
+ }
barNodeHash := common.HexToHash("05041990364eb72fcb1127652ce40d8bab765f2bfe53225b1170d276cc101c2e")
- barNode, _ := db.Get(barNodeHash[:])
- db.Delete(barNodeHash[:])
-
+ var (
+ barNodeBlob []byte
+ barNodeObj *cachedNode
+ )
+ if memonly {
+ barNodeObj = triedb.nodes[barNodeHash]
+ delete(triedb.nodes, barNodeHash)
+ } else {
+ barNodeBlob, _ = diskdb.Get(barNodeHash[:])
+ diskdb.Delete(barNodeHash[:])
+ }
// Create a new iterator that seeks to "bars". Seeking can't proceed because
// the node is missing.
- tr, _ := New(root, db)
+ tr, _ := New(root, triedb)
it := tr.NodeIterator([]byte("bars"))
missing, ok := it.Error().(*MissingNodeError)
if !ok {
@@ -350,10 +409,12 @@ func TestIteratorContinueAfterSeekError(t *testing.T) {
} else if missing.NodeHash != barNodeHash {
t.Fatal("wrong node missing")
}
-
// Reinsert the missing node.
- db.Put(barNodeHash[:], barNode[:])
-
+ if memonly {
+ triedb.nodes[barNodeHash] = barNodeObj
+ } else {
+ diskdb.Put(barNodeHash[:], barNodeBlob)
+ }
// Check that iteration produces the right set of values.
if err := checkIteratorOrder(testdata1[2:], NewIterator(it)); err != nil {
t.Fatal(err)
diff --git a/trie/proof.go b/trie/proof.go
index 5e886a259..508e4a6cf 100644
--- a/trie/proof.go
+++ b/trie/proof.go
@@ -22,20 +22,19 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
)
-// Prove constructs a merkle proof for key. The result contains all
-// encoded nodes on the path to the value at key. The value itself is
-// also included in the last node and can be retrieved by verifying
-// the proof.
+// Prove constructs a merkle proof for key. The result contains all encoded nodes
+// on the path to the value at key. The value itself is also included in the last
+// node and can be retrieved by verifying the proof.
//
-// If the trie does not contain a value for key, the returned proof
-// contains all nodes of the longest existing prefix of the key
-// (at least the root node), ending with the node that proves the
-// absence of the key.
-func (t *Trie) Prove(key []byte, fromLevel uint, proofDb DatabaseWriter) error {
+// If the trie does not contain a value for key, the returned proof contains all
+// nodes of the longest existing prefix of the key (at least the root node), ending
+// with the node that proves the absence of the key.
+func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error {
// Collect all nodes on the path to key.
key = keybytesToHex(key)
nodes := []node{}
@@ -66,7 +65,7 @@ func (t *Trie) Prove(key []byte, fromLevel uint, proofDb DatabaseWriter) error {
panic(fmt.Sprintf("%T: invalid node: %v", tn, tn))
}
}
- hasher := newHasher(0, 0)
+ hasher := newHasher(0, 0, nil)
for i, n := range nodes {
// Don't bother checking for errors here since hasher panics
// if encoding doesn't work and we're not writing to any database.
@@ -89,19 +88,29 @@ func (t *Trie) Prove(key []byte, fromLevel uint, proofDb DatabaseWriter) error {
return nil
}
-// VerifyProof checks merkle proofs. The given proof must contain the
-// value for key in a trie with the given root hash. VerifyProof
-// returns an error if the proof contains invalid trie nodes or the
-// wrong value.
+// Prove constructs a merkle proof for key. The result contains all encoded nodes
+// on the path to the value at key. The value itself is also included in the last
+// node and can be retrieved by verifying the proof.
+//
+// If the trie does not contain a value for key, the returned proof contains all
+// nodes of the longest existing prefix of the key (at least the root node), ending
+// with the node that proves the absence of the key.
+func (t *SecureTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error {
+ return t.trie.Prove(key, fromLevel, proofDb)
+}
+
+// VerifyProof checks merkle proofs. The given proof must contain the value for
+// key in a trie with the given root hash. VerifyProof returns an error if the
+// proof contains invalid trie nodes or the wrong value.
func VerifyProof(rootHash common.Hash, key []byte, proofDb DatabaseReader) (value []byte, err error, nodes int) {
key = keybytesToHex(key)
- wantHash := rootHash[:]
+ wantHash := rootHash
for i := 0; ; i++ {
- buf, _ := proofDb.Get(wantHash)
+ buf, _ := proofDb.Get(wantHash[:])
if buf == nil {
- return nil, fmt.Errorf("proof node %d (hash %064x) missing", i, wantHash[:]), i
+ return nil, fmt.Errorf("proof node %d (hash %064x) missing", i, wantHash), i
}
- n, err := decodeNode(wantHash, buf, 0)
+ n, err := decodeNode(wantHash[:], buf, 0)
if err != nil {
return nil, fmt.Errorf("bad proof node %d: %v", i, err), i
}
@@ -112,7 +121,7 @@ func VerifyProof(rootHash common.Hash, key []byte, proofDb DatabaseReader) (valu
return nil, nil, i
case hashNode:
key = keyrest
- wantHash = cld
+ copy(wantHash[:], cld)
case valueNode:
return cld, nil, i + 1
}
diff --git a/trie/secure_trie.go b/trie/secure_trie.go
index 1fde45165..3881ee18a 100644
--- a/trie/secure_trie.go
+++ b/trie/secure_trie.go
@@ -23,10 +23,6 @@ import (
"github.com/ethereum/go-ethereum/log"
)
-var secureKeyPrefix = []byte("secure-key-")
-
-const secureKeyLength = 11 + 32 // Length of the above prefix + 32byte hash
-
// SecureTrie wraps a trie with key hashing. In a secure trie, all
// access operations hash the key using keccak256. This prevents
// calling code from creating long chains of nodes that
@@ -39,25 +35,25 @@ const secureKeyLength = 11 + 32 // Length of the above prefix + 32byte hash
// SecureTrie is not safe for concurrent use.
type SecureTrie struct {
trie Trie
- hashKeyBuf [secureKeyLength]byte
- secKeyBuf [200]byte
+ hashKeyBuf [common.HashLength]byte
secKeyCache map[string][]byte
secKeyCacheOwner *SecureTrie // Pointer to self, replace the key cache on mismatch
}
-// NewSecure creates a trie with an existing root node from db.
+// NewSecure creates a trie with an existing root node from a backing database
+// and optional intermediate in-memory node pool.
//
// If root is the zero hash or the sha3 hash of an empty string, the
// trie is initially empty. Otherwise, New will panic if db is nil
// and returns MissingNodeError if the root node cannot be found.
//
-// Accessing the trie loads nodes from db on demand.
+// Accessing the trie loads nodes from the database or node pool on demand.
// Loaded nodes are kept around until their 'cache generation' expires.
// A new cache generation is created by each call to Commit.
// cachelimit sets the number of past cache generations to keep.
-func NewSecure(root common.Hash, db Database, cachelimit uint16) (*SecureTrie, error) {
+func NewSecure(root common.Hash, db *Database, cachelimit uint16) (*SecureTrie, error) {
if db == nil {
- panic("NewSecure called with nil database")
+ panic("trie.NewSecure called without a database")
}
trie, err := New(root, db)
if err != nil {
@@ -135,7 +131,7 @@ func (t *SecureTrie) GetKey(shaKey []byte) []byte {
if key, ok := t.getSecKeyCache()[string(shaKey)]; ok {
return key
}
- key, _ := t.trie.db.Get(t.secKey(shaKey))
+ key, _ := t.trie.db.preimage(common.BytesToHash(shaKey))
return key
}
@@ -144,8 +140,19 @@ func (t *SecureTrie) GetKey(shaKey []byte) []byte {
//
// Committing flushes nodes from memory. Subsequent Get calls will load nodes
// from the database.
-func (t *SecureTrie) Commit() (root common.Hash, err error) {
- return t.CommitTo(t.trie.db)
+func (t *SecureTrie) Commit(onleaf LeafCallback) (root common.Hash, err error) {
+ // Write all the pre-images to the actual disk database
+ if len(t.getSecKeyCache()) > 0 {
+ t.trie.db.lock.Lock()
+ for hk, key := range t.secKeyCache {
+ t.trie.db.insertPreimage(common.BytesToHash([]byte(hk)), key)
+ }
+ t.trie.db.lock.Unlock()
+
+ t.secKeyCache = make(map[string][]byte)
+ }
+ // Commit the trie to its intermediate node database
+ return t.trie.Commit(onleaf)
}
func (t *SecureTrie) Hash() common.Hash {
@@ -167,42 +174,15 @@ func (t *SecureTrie) NodeIterator(start []byte) NodeIterator {
return t.trie.NodeIterator(start)
}
-// CommitTo writes all nodes and the secure hash pre-images to the given database.
-// Nodes are stored with their sha3 hash as the key.
-//
-// Committing flushes nodes from memory. Subsequent Get calls will load nodes from
-// the trie's database. Calling code must ensure that the changes made to db are
-// written back to the trie's attached database before using the trie.
-func (t *SecureTrie) CommitTo(db DatabaseWriter) (root common.Hash, err error) {
- if len(t.getSecKeyCache()) > 0 {
- for hk, key := range t.secKeyCache {
- if err := db.Put(t.secKey([]byte(hk)), key); err != nil {
- return common.Hash{}, err
- }
- }
- t.secKeyCache = make(map[string][]byte)
- }
- return t.trie.CommitTo(db)
-}
-
-// secKey returns the database key for the preimage of key, as an ephemeral buffer.
-// The caller must not hold onto the return value because it will become
-// invalid on the next call to hashKey or secKey.
-func (t *SecureTrie) secKey(key []byte) []byte {
- buf := append(t.secKeyBuf[:0], secureKeyPrefix...)
- buf = append(buf, key...)
- return buf
-}
-
// hashKey returns the hash of key as an ephemeral buffer.
// The caller must not hold onto the return value because it will become
// invalid on the next call to hashKey or secKey.
func (t *SecureTrie) hashKey(key []byte) []byte {
- h := newHasher(0, 0)
- calculator := h.newCalculator()
- calculator.sha.Write(key)
- buf := calculator.sha.Sum(t.hashKeyBuf[:0])
- h.returnCalculator(calculator)
+ h := newHasher(0, 0, nil)
+ h.sha.Reset()
+ h.sha.Write(key)
+ buf := h.sha.Sum(t.hashKeyBuf[:0])
+ returnHasherToPool(h)
return buf
}
diff --git a/trie/secure_trie_test.go b/trie/secure_trie_test.go
index d74102e2a..aedf5a1cd 100644
--- a/trie/secure_trie_test.go
+++ b/trie/secure_trie_test.go
@@ -28,16 +28,20 @@ import (
)
func newEmptySecure() *SecureTrie {
- db, _ := ethdb.NewMemDatabase()
- trie, _ := NewSecure(common.Hash{}, db, 0)
+ diskdb, _ := ethdb.NewMemDatabase()
+ triedb := NewDatabase(diskdb)
+
+ trie, _ := NewSecure(common.Hash{}, triedb, 0)
return trie
}
// makeTestSecureTrie creates a large enough secure trie for testing.
-func makeTestSecureTrie() (ethdb.Database, *SecureTrie, map[string][]byte) {
+func makeTestSecureTrie() (*Database, *SecureTrie, map[string][]byte) {
// Create an empty trie
- db, _ := ethdb.NewMemDatabase()
- trie, _ := NewSecure(common.Hash{}, db, 0)
+ diskdb, _ := ethdb.NewMemDatabase()
+ triedb := NewDatabase(diskdb)
+
+ trie, _ := NewSecure(common.Hash{}, triedb, 0)
// Fill it with some arbitrary data
content := make(map[string][]byte)
@@ -58,10 +62,10 @@ func makeTestSecureTrie() (ethdb.Database, *SecureTrie, map[string][]byte) {
trie.Update(key, val)
}
}
- trie.Commit()
+ trie.Commit(nil)
// Return the generated trie
- return db, trie, content
+ return triedb, trie, content
}
func TestSecureDelete(t *testing.T) {
@@ -137,7 +141,7 @@ func TestSecureTrieConcurrency(t *testing.T) {
tries[index].Update(key, val)
}
}
- tries[index].Commit()
+ tries[index].Commit(nil)
}(i)
}
// Wait for all threads to finish
diff --git a/trie/sync.go b/trie/sync.go
index fea10051f..b573a9f73 100644
--- a/trie/sync.go
+++ b/trie/sync.go
@@ -21,6 +21,7 @@ import (
"fmt"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/ethdb"
"gopkg.in/karalabe/cookiejar.v2/collections/prque"
)
@@ -42,7 +43,7 @@ type request struct {
depth int // Depth level within the trie the node is located to prioritise DFS
deps int // Number of dependencies before allowed to commit this node
- callback TrieSyncLeafCallback // Callback to invoke if a leaf node it reached on this branch
+ callback LeafCallback // Callback to invoke if a leaf node it reached on this branch
}
// SyncResult is a simple list to return missing nodes along with their request
@@ -67,11 +68,6 @@ func newSyncMemBatch() *syncMemBatch {
}
}
-// TrieSyncLeafCallback is a callback type invoked when a trie sync reaches a
-// leaf node. It's used by state syncing to check if the leaf node requires some
-// further data syncing.
-type TrieSyncLeafCallback func(leaf []byte, parent common.Hash) error
-
// TrieSync is the main state trie synchronisation scheduler, which provides yet
// unknown trie hashes to retrieve, accepts node data associated with said hashes
// and reconstructs the trie step by step until all is done.
@@ -83,7 +79,7 @@ type TrieSync struct {
}
// NewTrieSync creates a new trie data download scheduler.
-func NewTrieSync(root common.Hash, database DatabaseReader, callback TrieSyncLeafCallback) *TrieSync {
+func NewTrieSync(root common.Hash, database DatabaseReader, callback LeafCallback) *TrieSync {
ts := &TrieSync{
database: database,
membatch: newSyncMemBatch(),
@@ -95,7 +91,7 @@ func NewTrieSync(root common.Hash, database DatabaseReader, callback TrieSyncLea
}
// AddSubTrie registers a new trie to the sync code, rooted at the designated parent.
-func (s *TrieSync) AddSubTrie(root common.Hash, depth int, parent common.Hash, callback TrieSyncLeafCallback) {
+func (s *TrieSync) AddSubTrie(root common.Hash, depth int, parent common.Hash, callback LeafCallback) {
// Short circuit if the trie is empty or already known
if root == emptyRoot {
return
@@ -217,7 +213,7 @@ func (s *TrieSync) Process(results []SyncResult) (bool, int, error) {
// Commit flushes the data stored in the internal membatch out to persistent
// storage, returning th enumber of items written and any occurred error.
-func (s *TrieSync) Commit(dbw DatabaseWriter) (int, error) {
+func (s *TrieSync) Commit(dbw ethdb.Putter) (int, error) {
// Dump the membatch into a database dbw
for i, key := range s.membatch.order {
if err := dbw.Put(key[:], s.membatch.batch[key]); err != nil {
diff --git a/trie/sync_test.go b/trie/sync_test.go
index ec16a25bd..4a720612b 100644
--- a/trie/sync_test.go
+++ b/trie/sync_test.go
@@ -25,10 +25,11 @@ import (
)
// makeTestTrie create a sample test trie to test node-wise reconstruction.
-func makeTestTrie() (ethdb.Database, *Trie, map[string][]byte) {
+func makeTestTrie() (*Database, *Trie, map[string][]byte) {
// Create an empty trie
- db, _ := ethdb.NewMemDatabase()
- trie, _ := New(common.Hash{}, db)
+ diskdb, _ := ethdb.NewMemDatabase()
+ triedb := NewDatabase(diskdb)
+ trie, _ := New(common.Hash{}, triedb)
// Fill it with some arbitrary data
content := make(map[string][]byte)
@@ -49,15 +50,15 @@ func makeTestTrie() (ethdb.Database, *Trie, map[string][]byte) {
trie.Update(key, val)
}
}
- trie.Commit()
+ trie.Commit(nil)
// Return the generated trie
- return db, trie, content
+ return triedb, trie, content
}
// checkTrieContents cross references a reconstructed trie with an expected data
// content map.
-func checkTrieContents(t *testing.T, db Database, root []byte, content map[string][]byte) {
+func checkTrieContents(t *testing.T, db *Database, root []byte, content map[string][]byte) {
// Check root availability and trie contents
trie, err := New(common.BytesToHash(root), db)
if err != nil {
@@ -74,7 +75,7 @@ func checkTrieContents(t *testing.T, db Database, root []byte, content map[strin
}
// checkTrieConsistency checks that all nodes in a trie are indeed present.
-func checkTrieConsistency(db Database, root common.Hash) error {
+func checkTrieConsistency(db *Database, root common.Hash) error {
// Create and iterate a trie rooted in a subnode
trie, err := New(root, db)
if err != nil {
@@ -88,12 +89,18 @@ func checkTrieConsistency(db Database, root common.Hash) error {
// Tests that an empty trie is not scheduled for syncing.
func TestEmptyTrieSync(t *testing.T) {
- emptyA, _ := New(common.Hash{}, nil)
- emptyB, _ := New(emptyRoot, nil)
+ diskdbA, _ := ethdb.NewMemDatabase()
+ triedbA := NewDatabase(diskdbA)
+
+ diskdbB, _ := ethdb.NewMemDatabase()
+ triedbB := NewDatabase(diskdbB)
+
+ emptyA, _ := New(common.Hash{}, triedbA)
+ emptyB, _ := New(emptyRoot, triedbB)
for i, trie := range []*Trie{emptyA, emptyB} {
- db, _ := ethdb.NewMemDatabase()
- if req := NewTrieSync(common.BytesToHash(trie.Root()), db, nil).Missing(1); len(req) != 0 {
+ diskdb, _ := ethdb.NewMemDatabase()
+ if req := NewTrieSync(trie.Hash(), diskdb, nil).Missing(1); len(req) != 0 {
t.Errorf("test %d: content requested for empty trie: %v", i, req)
}
}
@@ -109,14 +116,15 @@ func testIterativeTrieSync(t *testing.T, batch int) {
srcDb, srcTrie, srcData := makeTestTrie()
// Create a destination trie and sync with the scheduler
- dstDb, _ := ethdb.NewMemDatabase()
- sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
+ diskdb, _ := ethdb.NewMemDatabase()
+ triedb := NewDatabase(diskdb)
+ sched := NewTrieSync(srcTrie.Hash(), diskdb, nil)
queue := append([]common.Hash{}, sched.Missing(batch)...)
for len(queue) > 0 {
results := make([]SyncResult, len(queue))
for i, hash := range queue {
- data, err := srcDb.Get(hash.Bytes())
+ data, err := srcDb.Node(hash)
if err != nil {
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
}
@@ -125,13 +133,13 @@ func testIterativeTrieSync(t *testing.T, batch int) {
if _, index, err := sched.Process(results); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
}
- if index, err := sched.Commit(dstDb); err != nil {
+ if index, err := sched.Commit(diskdb); err != nil {
t.Fatalf("failed to commit data #%d: %v", index, err)
}
queue = append(queue[:0], sched.Missing(batch)...)
}
// Cross check that the two tries are in sync
- checkTrieContents(t, dstDb, srcTrie.Root(), srcData)
+ checkTrieContents(t, triedb, srcTrie.Root(), srcData)
}
// Tests that the trie scheduler can correctly reconstruct the state even if only
@@ -141,15 +149,16 @@ func TestIterativeDelayedTrieSync(t *testing.T) {
srcDb, srcTrie, srcData := makeTestTrie()
// Create a destination trie and sync with the scheduler
- dstDb, _ := ethdb.NewMemDatabase()
- sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
+ diskdb, _ := ethdb.NewMemDatabase()
+ triedb := NewDatabase(diskdb)
+ sched := NewTrieSync(srcTrie.Hash(), diskdb, nil)
queue := append([]common.Hash{}, sched.Missing(10000)...)
for len(queue) > 0 {
// Sync only half of the scheduled nodes
results := make([]SyncResult, len(queue)/2+1)
for i, hash := range queue[:len(results)] {
- data, err := srcDb.Get(hash.Bytes())
+ data, err := srcDb.Node(hash)
if err != nil {
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
}
@@ -158,13 +167,13 @@ func TestIterativeDelayedTrieSync(t *testing.T) {
if _, index, err := sched.Process(results); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
}
- if index, err := sched.Commit(dstDb); err != nil {
+ if index, err := sched.Commit(diskdb); err != nil {
t.Fatalf("failed to commit data #%d: %v", index, err)
}
queue = append(queue[len(results):], sched.Missing(10000)...)
}
// Cross check that the two tries are in sync
- checkTrieContents(t, dstDb, srcTrie.Root(), srcData)
+ checkTrieContents(t, triedb, srcTrie.Root(), srcData)
}
// Tests that given a root hash, a trie can sync iteratively on a single thread,
@@ -178,8 +187,9 @@ func testIterativeRandomTrieSync(t *testing.T, batch int) {
srcDb, srcTrie, srcData := makeTestTrie()
// Create a destination trie and sync with the scheduler
- dstDb, _ := ethdb.NewMemDatabase()
- sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
+ diskdb, _ := ethdb.NewMemDatabase()
+ triedb := NewDatabase(diskdb)
+ sched := NewTrieSync(srcTrie.Hash(), diskdb, nil)
queue := make(map[common.Hash]struct{})
for _, hash := range sched.Missing(batch) {
@@ -189,7 +199,7 @@ func testIterativeRandomTrieSync(t *testing.T, batch int) {
// Fetch all the queued nodes in a random order
results := make([]SyncResult, 0, len(queue))
for hash := range queue {
- data, err := srcDb.Get(hash.Bytes())
+ data, err := srcDb.Node(hash)
if err != nil {
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
}
@@ -199,7 +209,7 @@ func testIterativeRandomTrieSync(t *testing.T, batch int) {
if _, index, err := sched.Process(results); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
}
- if index, err := sched.Commit(dstDb); err != nil {
+ if index, err := sched.Commit(diskdb); err != nil {
t.Fatalf("failed to commit data #%d: %v", index, err)
}
queue = make(map[common.Hash]struct{})
@@ -208,7 +218,7 @@ func testIterativeRandomTrieSync(t *testing.T, batch int) {
}
}
// Cross check that the two tries are in sync
- checkTrieContents(t, dstDb, srcTrie.Root(), srcData)
+ checkTrieContents(t, triedb, srcTrie.Root(), srcData)
}
// Tests that the trie scheduler can correctly reconstruct the state even if only
@@ -218,8 +228,9 @@ func TestIterativeRandomDelayedTrieSync(t *testing.T) {
srcDb, srcTrie, srcData := makeTestTrie()
// Create a destination trie and sync with the scheduler
- dstDb, _ := ethdb.NewMemDatabase()
- sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
+ diskdb, _ := ethdb.NewMemDatabase()
+ triedb := NewDatabase(diskdb)
+ sched := NewTrieSync(srcTrie.Hash(), diskdb, nil)
queue := make(map[common.Hash]struct{})
for _, hash := range sched.Missing(10000) {
@@ -229,7 +240,7 @@ func TestIterativeRandomDelayedTrieSync(t *testing.T) {
// Sync only half of the scheduled nodes, even those in random order
results := make([]SyncResult, 0, len(queue)/2+1)
for hash := range queue {
- data, err := srcDb.Get(hash.Bytes())
+ data, err := srcDb.Node(hash)
if err != nil {
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
}
@@ -243,7 +254,7 @@ func TestIterativeRandomDelayedTrieSync(t *testing.T) {
if _, index, err := sched.Process(results); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
}
- if index, err := sched.Commit(dstDb); err != nil {
+ if index, err := sched.Commit(diskdb); err != nil {
t.Fatalf("failed to commit data #%d: %v", index, err)
}
for _, result := range results {
@@ -254,7 +265,7 @@ func TestIterativeRandomDelayedTrieSync(t *testing.T) {
}
}
// Cross check that the two tries are in sync
- checkTrieContents(t, dstDb, srcTrie.Root(), srcData)
+ checkTrieContents(t, triedb, srcTrie.Root(), srcData)
}
// Tests that a trie sync will not request nodes multiple times, even if they
@@ -264,8 +275,9 @@ func TestDuplicateAvoidanceTrieSync(t *testing.T) {
srcDb, srcTrie, srcData := makeTestTrie()
// Create a destination trie and sync with the scheduler
- dstDb, _ := ethdb.NewMemDatabase()
- sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
+ diskdb, _ := ethdb.NewMemDatabase()
+ triedb := NewDatabase(diskdb)
+ sched := NewTrieSync(srcTrie.Hash(), diskdb, nil)
queue := append([]common.Hash{}, sched.Missing(0)...)
requested := make(map[common.Hash]struct{})
@@ -273,7 +285,7 @@ func TestDuplicateAvoidanceTrieSync(t *testing.T) {
for len(queue) > 0 {
results := make([]SyncResult, len(queue))
for i, hash := range queue {
- data, err := srcDb.Get(hash.Bytes())
+ data, err := srcDb.Node(hash)
if err != nil {
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
}
@@ -287,13 +299,13 @@ func TestDuplicateAvoidanceTrieSync(t *testing.T) {
if _, index, err := sched.Process(results); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
}
- if index, err := sched.Commit(dstDb); err != nil {
+ if index, err := sched.Commit(diskdb); err != nil {
t.Fatalf("failed to commit data #%d: %v", index, err)
}
queue = append(queue[:0], sched.Missing(0)...)
}
// Cross check that the two tries are in sync
- checkTrieContents(t, dstDb, srcTrie.Root(), srcData)
+ checkTrieContents(t, triedb, srcTrie.Root(), srcData)
}
// Tests that at any point in time during a sync, only complete sub-tries are in
@@ -303,8 +315,9 @@ func TestIncompleteTrieSync(t *testing.T) {
srcDb, srcTrie, _ := makeTestTrie()
// Create a destination trie and sync with the scheduler
- dstDb, _ := ethdb.NewMemDatabase()
- sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
+ diskdb, _ := ethdb.NewMemDatabase()
+ triedb := NewDatabase(diskdb)
+ sched := NewTrieSync(srcTrie.Hash(), diskdb, nil)
added := []common.Hash{}
queue := append([]common.Hash{}, sched.Missing(1)...)
@@ -312,7 +325,7 @@ func TestIncompleteTrieSync(t *testing.T) {
// Fetch a batch of trie nodes
results := make([]SyncResult, len(queue))
for i, hash := range queue {
- data, err := srcDb.Get(hash.Bytes())
+ data, err := srcDb.Node(hash)
if err != nil {
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
}
@@ -322,7 +335,7 @@ func TestIncompleteTrieSync(t *testing.T) {
if _, index, err := sched.Process(results); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
}
- if index, err := sched.Commit(dstDb); err != nil {
+ if index, err := sched.Commit(diskdb); err != nil {
t.Fatalf("failed to commit data #%d: %v", index, err)
}
for _, result := range results {
@@ -330,7 +343,7 @@ func TestIncompleteTrieSync(t *testing.T) {
}
// Check that all known sub-tries in the synced trie are complete
for _, root := range added {
- if err := checkTrieConsistency(dstDb, root); err != nil {
+ if err := checkTrieConsistency(triedb, root); err != nil {
t.Fatalf("trie inconsistent: %v", err)
}
}
@@ -340,12 +353,12 @@ func TestIncompleteTrieSync(t *testing.T) {
// Sanity check that removing any node from the database is detected
for _, node := range added[1:] {
key := node.Bytes()
- value, _ := dstDb.Get(key)
+ value, _ := diskdb.Get(key)
- dstDb.Delete(key)
- if err := checkTrieConsistency(dstDb, added[0]); err == nil {
+ diskdb.Delete(key)
+ if err := checkTrieConsistency(triedb, added[0]); err == nil {
t.Fatalf("trie inconsistency not caught, missing: %x", key)
}
- dstDb.Put(key, value)
+ diskdb.Put(key, value)
}
}
diff --git a/trie/trie.go b/trie/trie.go
index c211e7554..e37a1ae10 100644
--- a/trie/trie.go
+++ b/trie/trie.go
@@ -22,16 +22,17 @@ import (
"fmt"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/crypto/sha3"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/rcrowley/go-metrics"
)
var (
- // This is the known root hash of an empty trie.
+ // emptyRoot is the known root hash of an empty trie.
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
- // This is the known hash of an empty state trie entry.
- emptyState common.Hash
+
+ // emptyState is the known hash of an empty state trie entry.
+ emptyState = crypto.Keccak256Hash(nil)
)
var (
@@ -53,29 +54,10 @@ func CacheUnloads() int64 {
return cacheUnloadCounter.Count()
}
-func init() {
- sha3.NewKeccak256().Sum(emptyState[:0])
-}
-
-// Database must be implemented by backing stores for the trie.
-type Database interface {
- DatabaseReader
- DatabaseWriter
-}
-
-// DatabaseReader wraps the Get method of a backing store for the trie.
-type DatabaseReader interface {
- Get(key []byte) (value []byte, err error)
- Has(key []byte) (bool, error)
-}
-
-// DatabaseWriter wraps the Put method of a backing store for the trie.
-type DatabaseWriter interface {
- // Put stores the mapping key->value in the database.
- // Implementations must not hold onto the value bytes, the trie
- // will reuse the slice across calls to Put.
- Put(key, value []byte) error
-}
+// LeafCallback is a callback type invoked when a trie operation reaches a leaf
+// node. It's used by state sync and commit to allow handling external references
+// between account and storage tries.
+type LeafCallback func(leaf []byte, parent common.Hash) error
// Trie is a Merkle Patricia Trie.
// The zero value is an empty trie with no database.
@@ -83,8 +65,8 @@ type DatabaseWriter interface {
//
// Trie is not safe for concurrent use.
type Trie struct {
+ db *Database
root node
- db Database
originalRoot common.Hash
// Cache generation values.
@@ -111,12 +93,15 @@ func (t *Trie) newFlag() nodeFlag {
// trie is initially empty and does not require a database. Otherwise,
// New will panic if db is nil and returns a MissingNodeError if root does
// not exist in the database. Accessing the trie loads nodes from db on demand.
-func New(root common.Hash, db Database) (*Trie, error) {
- trie := &Trie{db: db, originalRoot: root}
+func New(root common.Hash, db *Database) (*Trie, error) {
+ if db == nil {
+ panic("trie.New called without a database")
+ }
+ trie := &Trie{
+ db: db,
+ originalRoot: root,
+ }
if (root != common.Hash{}) && root != emptyRoot {
- if db == nil {
- panic("trie.New: cannot use existing root without a database")
- }
rootnode, err := trie.resolveHash(root[:], nil)
if err != nil {
return nil, err
@@ -447,12 +432,13 @@ func (t *Trie) resolve(n node, prefix []byte) (node, error) {
func (t *Trie) resolveHash(n hashNode, prefix []byte) (node, error) {
cacheMissCounter.Inc(1)
- enc, err := t.db.Get(n)
+ hash := common.BytesToHash(n)
+
+ enc, err := t.db.Node(hash)
if err != nil || enc == nil {
- return nil, &MissingNodeError{NodeHash: common.BytesToHash(n), Path: prefix}
+ return nil, &MissingNodeError{NodeHash: hash, Path: prefix}
}
- dec := mustDecodeNode(n, enc, t.cachegen)
- return dec, nil
+ return mustDecodeNode(n, enc, t.cachegen), nil
}
// Root returns the root hash of the trie.
@@ -462,44 +448,31 @@ func (t *Trie) Root() []byte { return t.Hash().Bytes() }
// Hash returns the root hash of the trie. It does not write to the
// database and can be used even if the trie doesn't have one.
func (t *Trie) Hash() common.Hash {
- hash, cached, _ := t.hashRoot(nil)
+ hash, cached, _ := t.hashRoot(nil, nil)
t.root = cached
return common.BytesToHash(hash.(hashNode))
}
-// Commit writes all nodes to the trie's database.
-// Nodes are stored with their sha3 hash as the key.
-//
-// Committing flushes nodes from memory.
-// Subsequent Get calls will load nodes from the database.
-func (t *Trie) Commit() (root common.Hash, err error) {
+// Commit writes all nodes to the trie's memory database, tracking the internal
+// and external (for account tries) references.
+func (t *Trie) Commit(onleaf LeafCallback) (root common.Hash, err error) {
if t.db == nil {
- panic("Commit called on trie with nil database")
+ panic("commit called on trie with nil database")
}
- return t.CommitTo(t.db)
-}
-
-// CommitTo writes all nodes to the given database.
-// Nodes are stored with their sha3 hash as the key.
-//
-// Committing flushes nodes from memory. Subsequent Get calls will
-// load nodes from the trie's database. Calling code must ensure that
-// the changes made to db are written back to the trie's attached
-// database before using the trie.
-func (t *Trie) CommitTo(db DatabaseWriter) (root common.Hash, err error) {
- hash, cached, err := t.hashRoot(db)
+ hash, cached, err := t.hashRoot(t.db, onleaf)
if err != nil {
- return (common.Hash{}), err
+ return common.Hash{}, err
}
t.root = cached
t.cachegen++
return common.BytesToHash(hash.(hashNode)), nil
}
-func (t *Trie) hashRoot(db DatabaseWriter) (node, node, error) {
+func (t *Trie) hashRoot(db *Database, onleaf LeafCallback) (node, node, error) {
if t.root == nil {
return hashNode(emptyRoot.Bytes()), nil, nil
}
- h := newHasher(t.cachegen, t.cachelimit)
+ h := newHasher(t.cachegen, t.cachelimit, onleaf)
+ defer returnHasherToPool(h)
return h.hash(t.root, db, true)
}
diff --git a/trie/trie_test.go b/trie/trie_test.go
index 1e28c3bc4..997222628 100644
--- a/trie/trie_test.go
+++ b/trie/trie_test.go
@@ -43,8 +43,8 @@ func init() {
// Used for testing
func newEmpty() *Trie {
- db, _ := ethdb.NewMemDatabase()
- trie, _ := New(common.Hash{}, db)
+ diskdb, _ := ethdb.NewMemDatabase()
+ trie, _ := New(common.Hash{}, NewDatabase(diskdb))
return trie
}
@@ -68,8 +68,8 @@ func TestNull(t *testing.T) {
}
func TestMissingRoot(t *testing.T) {
- db, _ := ethdb.NewMemDatabase()
- trie, err := New(common.HexToHash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"), db)
+ diskdb, _ := ethdb.NewMemDatabase()
+ trie, err := New(common.HexToHash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"), NewDatabase(diskdb))
if trie != nil {
t.Error("New returned non-nil trie for invalid root")
}
@@ -78,70 +78,75 @@ func TestMissingRoot(t *testing.T) {
}
}
-func TestMissingNode(t *testing.T) {
- db, _ := ethdb.NewMemDatabase()
- trie, _ := New(common.Hash{}, db)
+func TestMissingNodeDisk(t *testing.T) { testMissingNode(t, false) }
+func TestMissingNodeMemonly(t *testing.T) { testMissingNode(t, true) }
+
+func testMissingNode(t *testing.T, memonly bool) {
+ diskdb, _ := ethdb.NewMemDatabase()
+ triedb := NewDatabase(diskdb)
+
+ trie, _ := New(common.Hash{}, triedb)
updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer")
updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf")
- root, _ := trie.Commit()
+ root, _ := trie.Commit(nil)
+ if !memonly {
+ triedb.Commit(root, true)
+ }
- trie, _ = New(root, db)
+ trie, _ = New(root, triedb)
_, err := trie.TryGet([]byte("120000"))
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
-
- trie, _ = New(root, db)
+ trie, _ = New(root, triedb)
_, err = trie.TryGet([]byte("120099"))
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
-
- trie, _ = New(root, db)
+ trie, _ = New(root, triedb)
_, err = trie.TryGet([]byte("123456"))
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
-
- trie, _ = New(root, db)
+ trie, _ = New(root, triedb)
err = trie.TryUpdate([]byte("120099"), []byte("zxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcv"))
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
-
- trie, _ = New(root, db)
+ trie, _ = New(root, triedb)
err = trie.TryDelete([]byte("123456"))
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
- db.Delete(common.FromHex("e1d943cc8f061a0c0b98162830b970395ac9315654824bf21b73b891365262f9"))
+ hash := common.HexToHash("0xe1d943cc8f061a0c0b98162830b970395ac9315654824bf21b73b891365262f9")
+ if memonly {
+ delete(triedb.nodes, hash)
+ } else {
+ diskdb.Delete(hash[:])
+ }
- trie, _ = New(root, db)
+ trie, _ = New(root, triedb)
_, err = trie.TryGet([]byte("120000"))
if _, ok := err.(*MissingNodeError); !ok {
t.Errorf("Wrong error: %v", err)
}
-
- trie, _ = New(root, db)
+ trie, _ = New(root, triedb)
_, err = trie.TryGet([]byte("120099"))
if _, ok := err.(*MissingNodeError); !ok {
t.Errorf("Wrong error: %v", err)
}
-
- trie, _ = New(root, db)
+ trie, _ = New(root, triedb)
_, err = trie.TryGet([]byte("123456"))
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
-
- trie, _ = New(root, db)
+ trie, _ = New(root, triedb)
err = trie.TryUpdate([]byte("120099"), []byte("zxcv"))
if _, ok := err.(*MissingNodeError); !ok {
t.Errorf("Wrong error: %v", err)
}
-
- trie, _ = New(root, db)
+ trie, _ = New(root, triedb)
err = trie.TryDelete([]byte("123456"))
if _, ok := err.(*MissingNodeError); !ok {
t.Errorf("Wrong error: %v", err)
@@ -165,7 +170,7 @@ func TestInsert(t *testing.T) {
updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab")
- root, err := trie.Commit()
+ root, err := trie.Commit(nil)
if err != nil {
t.Fatalf("commit error: %v", err)
}
@@ -194,7 +199,7 @@ func TestGet(t *testing.T) {
if i == 1 {
return
}
- trie.Commit()
+ trie.Commit(nil)
}
}
@@ -263,7 +268,7 @@ func TestReplication(t *testing.T) {
for _, val := range vals {
updateString(trie, val.k, val.v)
}
- exp, err := trie.Commit()
+ exp, err := trie.Commit(nil)
if err != nil {
t.Fatalf("commit error: %v", err)
}
@@ -278,7 +283,7 @@ func TestReplication(t *testing.T) {
t.Errorf("trie2 doesn't have %q => %q", kv.k, kv.v)
}
}
- hash, err := trie2.Commit()
+ hash, err := trie2.Commit(nil)
if err != nil {
t.Fatalf("commit error: %v", err)
}
@@ -314,7 +319,7 @@ func TestLargeValue(t *testing.T) {
}
type countingDB struct {
- Database
+ ethdb.Database
gets map[string]int
}
@@ -332,19 +337,20 @@ func TestCacheUnload(t *testing.T) {
key2 := "---some other branch"
updateString(trie, key1, "this is the branch of key1.")
updateString(trie, key2, "this is the branch of key2.")
- root, _ := trie.Commit()
+
+ root, _ := trie.Commit(nil)
+ trie.db.Commit(root, true)
// Commit the trie repeatedly and access key1.
// The branch containing it is loaded from DB exactly two times:
// in the 0th and 6th iteration.
- db := &countingDB{Database: trie.db, gets: make(map[string]int)}
- trie, _ = New(root, db)
+ db := &countingDB{Database: trie.db.diskdb, gets: make(map[string]int)}
+ trie, _ = New(root, NewDatabase(db))
trie.SetCacheLimit(5)
for i := 0; i < 12; i++ {
getString(trie, key1)
- trie.Commit()
+ trie.Commit(nil)
}
-
// Check that it got loaded two times.
for dbkey, count := range db.gets {
if count != 2 {
@@ -407,8 +413,10 @@ func (randTest) Generate(r *rand.Rand, size int) reflect.Value {
}
func runRandTest(rt randTest) bool {
- db, _ := ethdb.NewMemDatabase()
- tr, _ := New(common.Hash{}, db)
+ diskdb, _ := ethdb.NewMemDatabase()
+ triedb := NewDatabase(diskdb)
+
+ tr, _ := New(common.Hash{}, triedb)
values := make(map[string]string) // tracks content of the trie
for i, step := range rt {
@@ -426,23 +434,23 @@ func runRandTest(rt randTest) bool {
rt[i].err = fmt.Errorf("mismatch for key 0x%x, got 0x%x want 0x%x", step.key, v, want)
}
case opCommit:
- _, rt[i].err = tr.Commit()
+ _, rt[i].err = tr.Commit(nil)
case opHash:
tr.Hash()
case opReset:
- hash, err := tr.Commit()
+ hash, err := tr.Commit(nil)
if err != nil {
rt[i].err = err
return false
}
- newtr, err := New(hash, db)
+ newtr, err := New(hash, triedb)
if err != nil {
rt[i].err = err
return false
}
tr = newtr
case opItercheckhash:
- checktr, _ := New(common.Hash{}, nil)
+ checktr, _ := New(common.Hash{}, triedb)
it := NewIterator(tr.NodeIterator(nil))
for it.Next() {
checktr.Update(it.Key, it.Value)
@@ -524,7 +532,7 @@ func benchGet(b *testing.B, commit bool) {
}
binary.LittleEndian.PutUint64(k, benchElemCount/2)
if commit {
- trie.Commit()
+ trie.Commit(nil)
}
b.ResetTimer()
@@ -534,7 +542,7 @@ func benchGet(b *testing.B, commit bool) {
b.StopTimer()
if commit {
- ldb := trie.db.(*ethdb.LDBDatabase)
+ ldb := trie.db.diskdb.(*ethdb.LDBDatabase)
ldb.Close()
os.RemoveAll(ldb.Path())
}
@@ -585,16 +593,16 @@ func BenchmarkHash(b *testing.B) {
trie.Hash()
}
-func tempDB() (string, Database) {
+func tempDB() (string, *Database) {
dir, err := ioutil.TempDir("", "trie-bench")
if err != nil {
panic(fmt.Sprintf("can't create temporary directory: %v", err))
}
- db, err := ethdb.NewLDBDatabase(dir, 256, 0)
+ diskdb, err := ethdb.NewLDBDatabase(dir, 256, 0)
if err != nil {
panic(fmt.Sprintf("can't create temporary database: %v", err))
}
- return dir, db
+ return dir, NewDatabase(diskdb)
}
func getString(trie *Trie, k string) []byte {
diff --git a/vendor/github.com/StackExchange/wmi/LICENSE b/vendor/github.com/StackExchange/wmi/LICENSE
new file mode 100644
index 000000000..ae80b6720
--- /dev/null
+++ b/vendor/github.com/StackExchange/wmi/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Stack Exchange
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/github.com/StackExchange/wmi/README.md b/vendor/github.com/StackExchange/wmi/README.md
new file mode 100644
index 000000000..426d1a46b
--- /dev/null
+++ b/vendor/github.com/StackExchange/wmi/README.md
@@ -0,0 +1,6 @@
+wmi
+===
+
+Package wmi provides a WQL interface to Windows WMI.
+
+Note: It interfaces with WMI on the local machine, therefore it only runs on Windows.
diff --git a/vendor/github.com/StackExchange/wmi/swbemservices.go b/vendor/github.com/StackExchange/wmi/swbemservices.go
new file mode 100644
index 000000000..9765a53f7
--- /dev/null
+++ b/vendor/github.com/StackExchange/wmi/swbemservices.go
@@ -0,0 +1,260 @@
+// +build windows
+
+package wmi
+
+import (
+ "fmt"
+ "reflect"
+ "runtime"
+ "sync"
+
+ "github.com/go-ole/go-ole"
+ "github.com/go-ole/go-ole/oleutil"
+)
+
+// SWbemServices is used to access wmi. See https://msdn.microsoft.com/en-us/library/aa393719(v=vs.85).aspx
+type SWbemServices struct {
+ //TODO: track namespace. Not sure if we can re connect to a different namespace using the same instance
+ cWMIClient *Client //This could also be an embedded struct, but then we would need to branch on Client vs SWbemServices in the Query method
+ sWbemLocatorIUnknown *ole.IUnknown
+ sWbemLocatorIDispatch *ole.IDispatch
+ queries chan *queryRequest
+ closeError chan error
+ lQueryorClose sync.Mutex
+}
+
+type queryRequest struct {
+ query string
+ dst interface{}
+ args []interface{}
+ finished chan error
+}
+
+// InitializeSWbemServices will return a new SWbemServices object that can be used to query WMI
+func InitializeSWbemServices(c *Client, connectServerArgs ...interface{}) (*SWbemServices, error) {
+ //fmt.Println("InitializeSWbemServices: Starting")
+ //TODO: implement connectServerArgs as optional argument for init with connectServer call
+ s := new(SWbemServices)
+ s.cWMIClient = c
+ s.queries = make(chan *queryRequest)
+ initError := make(chan error)
+ go s.process(initError)
+
+ err, ok := <-initError
+ if ok {
+ return nil, err //Send error to caller
+ }
+ //fmt.Println("InitializeSWbemServices: Finished")
+ return s, nil
+}
+
+// Close will clear and release all of the SWbemServices resources
+func (s *SWbemServices) Close() error {
+ s.lQueryorClose.Lock()
+ if s == nil || s.sWbemLocatorIDispatch == nil {
+ s.lQueryorClose.Unlock()
+ return fmt.Errorf("SWbemServices is not Initialized")
+ }
+ if s.queries == nil {
+ s.lQueryorClose.Unlock()
+ return fmt.Errorf("SWbemServices has been closed")
+ }
+ //fmt.Println("Close: sending close request")
+ var result error
+ ce := make(chan error)
+ s.closeError = ce //Race condition if multiple callers to close. May need to lock here
+ close(s.queries) //Tell background to shut things down
+ s.lQueryorClose.Unlock()
+ err, ok := <-ce
+ if ok {
+ result = err
+ }
+ //fmt.Println("Close: finished")
+ return result
+}
+
+func (s *SWbemServices) process(initError chan error) {
+ //fmt.Println("process: starting background thread initialization")
+ //All OLE/WMI calls must happen on the same initialized thead, so lock this goroutine
+ runtime.LockOSThread()
+ defer runtime.LockOSThread()
+
+ err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED)
+ if err != nil {
+ oleCode := err.(*ole.OleError).Code()
+ if oleCode != ole.S_OK && oleCode != S_FALSE {
+ initError <- fmt.Errorf("ole.CoInitializeEx error: %v", err)
+ return
+ }
+ }
+ defer ole.CoUninitialize()
+
+ unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator")
+ if err != nil {
+ initError <- fmt.Errorf("CreateObject SWbemLocator error: %v", err)
+ return
+ } else if unknown == nil {
+ initError <- ErrNilCreateObject
+ return
+ }
+ defer unknown.Release()
+ s.sWbemLocatorIUnknown = unknown
+
+ dispatch, err := s.sWbemLocatorIUnknown.QueryInterface(ole.IID_IDispatch)
+ if err != nil {
+ initError <- fmt.Errorf("SWbemLocator QueryInterface error: %v", err)
+ return
+ }
+ defer dispatch.Release()
+ s.sWbemLocatorIDispatch = dispatch
+
+ // we can't do the ConnectServer call outside the loop unless we find a way to track and re-init the connectServerArgs
+ //fmt.Println("process: initialized. closing initError")
+ close(initError)
+ //fmt.Println("process: waiting for queries")
+ for q := range s.queries {
+ //fmt.Printf("process: new query: len(query)=%d\n", len(q.query))
+ errQuery := s.queryBackground(q)
+ //fmt.Println("process: s.queryBackground finished")
+ if errQuery != nil {
+ q.finished <- errQuery
+ }
+ close(q.finished)
+ }
+ //fmt.Println("process: queries channel closed")
+ s.queries = nil //set channel to nil so we know it is closed
+ //TODO: I think the Release/Clear calls can panic if things are in a bad state.
+ //TODO: May need to recover from panics and send error to method caller instead.
+ close(s.closeError)
+}
+
+// Query runs the WQL query using a SWbemServices instance and appends the values to dst.
+//
+// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in
+// the query must have the same name in dst. Supported types are all signed and
+// unsigned integers, time.Time, string, bool, or a pointer to one of those.
+// Array types are not supported.
+//
+// By default, the local machine and default namespace are used. These can be
+// changed using connectServerArgs. See
+// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details.
+func (s *SWbemServices) Query(query string, dst interface{}, connectServerArgs ...interface{}) error {
+ s.lQueryorClose.Lock()
+ if s == nil || s.sWbemLocatorIDispatch == nil {
+ s.lQueryorClose.Unlock()
+ return fmt.Errorf("SWbemServices is not Initialized")
+ }
+ if s.queries == nil {
+ s.lQueryorClose.Unlock()
+ return fmt.Errorf("SWbemServices has been closed")
+ }
+
+ //fmt.Println("Query: Sending query request")
+ qr := queryRequest{
+ query: query,
+ dst: dst,
+ args: connectServerArgs,
+ finished: make(chan error),
+ }
+ s.queries <- &qr
+ s.lQueryorClose.Unlock()
+ err, ok := <-qr.finished
+ if ok {
+ //fmt.Println("Query: Finished with error")
+ return err //Send error to caller
+ }
+ //fmt.Println("Query: Finished")
+ return nil
+}
+
+func (s *SWbemServices) queryBackground(q *queryRequest) error {
+ if s == nil || s.sWbemLocatorIDispatch == nil {
+ return fmt.Errorf("SWbemServices is not Initialized")
+ }
+ wmi := s.sWbemLocatorIDispatch //Should just rename in the code, but this will help as we break things apart
+ //fmt.Println("queryBackground: Starting")
+
+ dv := reflect.ValueOf(q.dst)
+ if dv.Kind() != reflect.Ptr || dv.IsNil() {
+ return ErrInvalidEntityType
+ }
+ dv = dv.Elem()
+ mat, elemType := checkMultiArg(dv)
+ if mat == multiArgTypeInvalid {
+ return ErrInvalidEntityType
+ }
+
+ // service is a SWbemServices
+ serviceRaw, err := oleutil.CallMethod(wmi, "ConnectServer", q.args...)
+ if err != nil {
+ return err
+ }
+ service := serviceRaw.ToIDispatch()
+ defer serviceRaw.Clear()
+
+ // result is a SWBemObjectSet
+ resultRaw, err := oleutil.CallMethod(service, "ExecQuery", q.query)
+ if err != nil {
+ return err
+ }
+ result := resultRaw.ToIDispatch()
+ defer resultRaw.Clear()
+
+ count, err := oleInt64(result, "Count")
+ if err != nil {
+ return err
+ }
+
+ enumProperty, err := result.GetProperty("_NewEnum")
+ if err != nil {
+ return err
+ }
+ defer enumProperty.Clear()
+
+ enum, err := enumProperty.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant)
+ if err != nil {
+ return err
+ }
+ if enum == nil {
+ return fmt.Errorf("can't get IEnumVARIANT, enum is nil")
+ }
+ defer enum.Release()
+
+ // Initialize a slice with Count capacity
+ dv.Set(reflect.MakeSlice(dv.Type(), 0, int(count)))
+
+ var errFieldMismatch error
+ for itemRaw, length, err := enum.Next(1); length > 0; itemRaw, length, err = enum.Next(1) {
+ if err != nil {
+ return err
+ }
+
+ err := func() error {
+ // item is a SWbemObject, but really a Win32_Process
+ item := itemRaw.ToIDispatch()
+ defer item.Release()
+
+ ev := reflect.New(elemType)
+ if err = s.cWMIClient.loadEntity(ev.Interface(), item); err != nil {
+ if _, ok := err.(*ErrFieldMismatch); ok {
+ // We continue loading entities even in the face of field mismatch errors.
+ // If we encounter any other error, that other error is returned. Otherwise,
+ // an ErrFieldMismatch is returned.
+ errFieldMismatch = err
+ } else {
+ return err
+ }
+ }
+ if mat != multiArgTypeStructPtr {
+ ev = ev.Elem()
+ }
+ dv.Set(reflect.Append(dv, ev))
+ return nil
+ }()
+ if err != nil {
+ return err
+ }
+ }
+ //fmt.Println("queryBackground: Finished")
+ return errFieldMismatch
+}
diff --git a/vendor/github.com/StackExchange/wmi/wmi.go b/vendor/github.com/StackExchange/wmi/wmi.go
new file mode 100644
index 000000000..a951b1258
--- /dev/null
+++ b/vendor/github.com/StackExchange/wmi/wmi.go
@@ -0,0 +1,486 @@
+// +build windows
+
+/*
+Package wmi provides a WQL interface for WMI on Windows.
+
+Example code to print names of running processes:
+
+ type Win32_Process struct {
+ Name string
+ }
+
+ func main() {
+ var dst []Win32_Process
+ q := wmi.CreateQuery(&dst, "")
+ err := wmi.Query(q, &dst)
+ if err != nil {
+ log.Fatal(err)
+ }
+ for i, v := range dst {
+ println(i, v.Name)
+ }
+ }
+
+*/
+package wmi
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "log"
+ "os"
+ "reflect"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/go-ole/go-ole"
+ "github.com/go-ole/go-ole/oleutil"
+)
+
+var l = log.New(os.Stdout, "", log.LstdFlags)
+
+var (
+ ErrInvalidEntityType = errors.New("wmi: invalid entity type")
+ // ErrNilCreateObject is the error returned if CreateObject returns nil even
+ // if the error was nil.
+ ErrNilCreateObject = errors.New("wmi: create object returned nil")
+ lock sync.Mutex
+)
+
+// S_FALSE is returned by CoInitializeEx if it was already called on this thread.
+const S_FALSE = 0x00000001
+
+// QueryNamespace invokes Query with the given namespace on the local machine.
+func QueryNamespace(query string, dst interface{}, namespace string) error {
+ return Query(query, dst, nil, namespace)
+}
+
+// Query runs the WQL query and appends the values to dst.
+//
+// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in
+// the query must have the same name in dst. Supported types are all signed and
+// unsigned integers, time.Time, string, bool, or a pointer to one of those.
+// Array types are not supported.
+//
+// By default, the local machine and default namespace are used. These can be
+// changed using connectServerArgs. See
+// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details.
+//
+// Query is a wrapper around DefaultClient.Query.
+func Query(query string, dst interface{}, connectServerArgs ...interface{}) error {
+ if DefaultClient.SWbemServicesClient == nil {
+ return DefaultClient.Query(query, dst, connectServerArgs...)
+ }
+ return DefaultClient.SWbemServicesClient.Query(query, dst, connectServerArgs...)
+}
+
+// A Client is an WMI query client.
+//
+// Its zero value (DefaultClient) is a usable client.
+type Client struct {
+ // NonePtrZero specifies if nil values for fields which aren't pointers
+ // should be returned as the field types zero value.
+ //
+ // Setting this to true allows stucts without pointer fields to be used
+ // without the risk failure should a nil value returned from WMI.
+ NonePtrZero bool
+
+ // PtrNil specifies if nil values for pointer fields should be returned
+ // as nil.
+ //
+ // Setting this to true will set pointer fields to nil where WMI
+ // returned nil, otherwise the types zero value will be returned.
+ PtrNil bool
+
+ // AllowMissingFields specifies that struct fields not present in the
+ // query result should not result in an error.
+ //
+ // Setting this to true allows custom queries to be used with full
+ // struct definitions instead of having to define multiple structs.
+ AllowMissingFields bool
+
+ // SWbemServiceClient is an optional SWbemServices object that can be
+ // initialized and then reused across multiple queries. If it is null
+ // then the method will initialize a new temporary client each time.
+ SWbemServicesClient *SWbemServices
+}
+
+// DefaultClient is the default Client and is used by Query, QueryNamespace
+var DefaultClient = &Client{}
+
+// Query runs the WQL query and appends the values to dst.
+//
+// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in
+// the query must have the same name in dst. Supported types are all signed and
+// unsigned integers, time.Time, string, bool, or a pointer to one of those.
+// Array types are not supported.
+//
+// By default, the local machine and default namespace are used. These can be
+// changed using connectServerArgs. See
+// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details.
+func (c *Client) Query(query string, dst interface{}, connectServerArgs ...interface{}) error {
+ dv := reflect.ValueOf(dst)
+ if dv.Kind() != reflect.Ptr || dv.IsNil() {
+ return ErrInvalidEntityType
+ }
+ dv = dv.Elem()
+ mat, elemType := checkMultiArg(dv)
+ if mat == multiArgTypeInvalid {
+ return ErrInvalidEntityType
+ }
+
+ lock.Lock()
+ defer lock.Unlock()
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED)
+ if err != nil {
+ oleCode := err.(*ole.OleError).Code()
+ if oleCode != ole.S_OK && oleCode != S_FALSE {
+ return err
+ }
+ }
+ defer ole.CoUninitialize()
+
+ unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator")
+ if err != nil {
+ return err
+ } else if unknown == nil {
+ return ErrNilCreateObject
+ }
+ defer unknown.Release()
+
+ wmi, err := unknown.QueryInterface(ole.IID_IDispatch)
+ if err != nil {
+ return err
+ }
+ defer wmi.Release()
+
+ // service is a SWbemServices
+ serviceRaw, err := oleutil.CallMethod(wmi, "ConnectServer", connectServerArgs...)
+ if err != nil {
+ return err
+ }
+ service := serviceRaw.ToIDispatch()
+ defer serviceRaw.Clear()
+
+ // result is a SWBemObjectSet
+ resultRaw, err := oleutil.CallMethod(service, "ExecQuery", query)
+ if err != nil {
+ return err
+ }
+ result := resultRaw.ToIDispatch()
+ defer resultRaw.Clear()
+
+ count, err := oleInt64(result, "Count")
+ if err != nil {
+ return err
+ }
+
+ enumProperty, err := result.GetProperty("_NewEnum")
+ if err != nil {
+ return err
+ }
+ defer enumProperty.Clear()
+
+ enum, err := enumProperty.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant)
+ if err != nil {
+ return err
+ }
+ if enum == nil {
+ return fmt.Errorf("can't get IEnumVARIANT, enum is nil")
+ }
+ defer enum.Release()
+
+ // Initialize a slice with Count capacity
+ dv.Set(reflect.MakeSlice(dv.Type(), 0, int(count)))
+
+ var errFieldMismatch error
+ for itemRaw, length, err := enum.Next(1); length > 0; itemRaw, length, err = enum.Next(1) {
+ if err != nil {
+ return err
+ }
+
+ err := func() error {
+ // item is a SWbemObject, but really a Win32_Process
+ item := itemRaw.ToIDispatch()
+ defer item.Release()
+
+ ev := reflect.New(elemType)
+ if err = c.loadEntity(ev.Interface(), item); err != nil {
+ if _, ok := err.(*ErrFieldMismatch); ok {
+ // We continue loading entities even in the face of field mismatch errors.
+ // If we encounter any other error, that other error is returned. Otherwise,
+ // an ErrFieldMismatch is returned.
+ errFieldMismatch = err
+ } else {
+ return err
+ }
+ }
+ if mat != multiArgTypeStructPtr {
+ ev = ev.Elem()
+ }
+ dv.Set(reflect.Append(dv, ev))
+ return nil
+ }()
+ if err != nil {
+ return err
+ }
+ }
+ return errFieldMismatch
+}
+
+// ErrFieldMismatch is returned when a field is to be loaded into a different
+// type than the one it was stored from, or when a field is missing or
+// unexported in the destination struct.
+// StructType is the type of the struct pointed to by the destination argument.
+type ErrFieldMismatch struct {
+ StructType reflect.Type
+ FieldName string
+ Reason string
+}
+
+func (e *ErrFieldMismatch) Error() string {
+ return fmt.Sprintf("wmi: cannot load field %q into a %q: %s",
+ e.FieldName, e.StructType, e.Reason)
+}
+
+var timeType = reflect.TypeOf(time.Time{})
+
+// loadEntity loads a SWbemObject into a struct pointer.
+func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismatch error) {
+ v := reflect.ValueOf(dst).Elem()
+ for i := 0; i < v.NumField(); i++ {
+ f := v.Field(i)
+ of := f
+ isPtr := f.Kind() == reflect.Ptr
+ if isPtr {
+ ptr := reflect.New(f.Type().Elem())
+ f.Set(ptr)
+ f = f.Elem()
+ }
+ n := v.Type().Field(i).Name
+ if !f.CanSet() {
+ return &ErrFieldMismatch{
+ StructType: of.Type(),
+ FieldName: n,
+ Reason: "CanSet() is false",
+ }
+ }
+ prop, err := oleutil.GetProperty(src, n)
+ if err != nil {
+ if !c.AllowMissingFields {
+ errFieldMismatch = &ErrFieldMismatch{
+ StructType: of.Type(),
+ FieldName: n,
+ Reason: "no such struct field",
+ }
+ }
+ continue
+ }
+ defer prop.Clear()
+
+ switch val := prop.Value().(type) {
+ case int8, int16, int32, int64, int:
+ v := reflect.ValueOf(val).Int()
+ switch f.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ f.SetInt(v)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ f.SetUint(uint64(v))
+ default:
+ return &ErrFieldMismatch{
+ StructType: of.Type(),
+ FieldName: n,
+ Reason: "not an integer class",
+ }
+ }
+ case uint8, uint16, uint32, uint64:
+ v := reflect.ValueOf(val).Uint()
+ switch f.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ f.SetInt(int64(v))
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ f.SetUint(v)
+ default:
+ return &ErrFieldMismatch{
+ StructType: of.Type(),
+ FieldName: n,
+ Reason: "not an integer class",
+ }
+ }
+ case string:
+ switch f.Kind() {
+ case reflect.String:
+ f.SetString(val)
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ iv, err := strconv.ParseInt(val, 10, 64)
+ if err != nil {
+ return err
+ }
+ f.SetInt(iv)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ uv, err := strconv.ParseUint(val, 10, 64)
+ if err != nil {
+ return err
+ }
+ f.SetUint(uv)
+ case reflect.Struct:
+ switch f.Type() {
+ case timeType:
+ if len(val) == 25 {
+ mins, err := strconv.Atoi(val[22:])
+ if err != nil {
+ return err
+ }
+ val = val[:22] + fmt.Sprintf("%02d%02d", mins/60, mins%60)
+ }
+ t, err := time.Parse("20060102150405.000000-0700", val)
+ if err != nil {
+ return err
+ }
+ f.Set(reflect.ValueOf(t))
+ }
+ }
+ case bool:
+ switch f.Kind() {
+ case reflect.Bool:
+ f.SetBool(val)
+ default:
+ return &ErrFieldMismatch{
+ StructType: of.Type(),
+ FieldName: n,
+ Reason: "not a bool",
+ }
+ }
+ case float32:
+ switch f.Kind() {
+ case reflect.Float32:
+ f.SetFloat(float64(val))
+ default:
+ return &ErrFieldMismatch{
+ StructType: of.Type(),
+ FieldName: n,
+ Reason: "not a Float32",
+ }
+ }
+ default:
+ if f.Kind() == reflect.Slice {
+ switch f.Type().Elem().Kind() {
+ case reflect.String:
+ safeArray := prop.ToArray()
+ if safeArray != nil {
+ arr := safeArray.ToValueArray()
+ fArr := reflect.MakeSlice(f.Type(), len(arr), len(arr))
+ for i, v := range arr {
+ s := fArr.Index(i)
+ s.SetString(v.(string))
+ }
+ f.Set(fArr)
+ }
+ case reflect.Uint8:
+ safeArray := prop.ToArray()
+ if safeArray != nil {
+ arr := safeArray.ToValueArray()
+ fArr := reflect.MakeSlice(f.Type(), len(arr), len(arr))
+ for i, v := range arr {
+ s := fArr.Index(i)
+ s.SetUint(reflect.ValueOf(v).Uint())
+ }
+ f.Set(fArr)
+ }
+ default:
+ return &ErrFieldMismatch{
+ StructType: of.Type(),
+ FieldName: n,
+ Reason: fmt.Sprintf("unsupported slice type (%T)", val),
+ }
+ }
+ } else {
+ typeof := reflect.TypeOf(val)
+ if typeof == nil && (isPtr || c.NonePtrZero) {
+ if (isPtr && c.PtrNil) || (!isPtr && c.NonePtrZero) {
+ of.Set(reflect.Zero(of.Type()))
+ }
+ break
+ }
+ return &ErrFieldMismatch{
+ StructType: of.Type(),
+ FieldName: n,
+ Reason: fmt.Sprintf("unsupported type (%T)", val),
+ }
+ }
+ }
+ }
+ return errFieldMismatch
+}
+
+type multiArgType int
+
+const (
+ multiArgTypeInvalid multiArgType = iota
+ multiArgTypeStruct
+ multiArgTypeStructPtr
+)
+
+// checkMultiArg checks that v has type []S, []*S for some struct type S.
+//
+// It returns what category the slice's elements are, and the reflect.Type
+// that represents S.
+func checkMultiArg(v reflect.Value) (m multiArgType, elemType reflect.Type) {
+ if v.Kind() != reflect.Slice {
+ return multiArgTypeInvalid, nil
+ }
+ elemType = v.Type().Elem()
+ switch elemType.Kind() {
+ case reflect.Struct:
+ return multiArgTypeStruct, elemType
+ case reflect.Ptr:
+ elemType = elemType.Elem()
+ if elemType.Kind() == reflect.Struct {
+ return multiArgTypeStructPtr, elemType
+ }
+ }
+ return multiArgTypeInvalid, nil
+}
+
+func oleInt64(item *ole.IDispatch, prop string) (int64, error) {
+ v, err := oleutil.GetProperty(item, prop)
+ if err != nil {
+ return 0, err
+ }
+ defer v.Clear()
+
+ i := int64(v.Val)
+ return i, nil
+}
+
+// CreateQuery returns a WQL query string that queries all columns of src. where
+// is an optional string that is appended to the query, to be used with WHERE
+// clauses. In such a case, the "WHERE" string should appear at the beginning.
+func CreateQuery(src interface{}, where string) string {
+ var b bytes.Buffer
+ b.WriteString("SELECT ")
+ s := reflect.Indirect(reflect.ValueOf(src))
+ t := s.Type()
+ if s.Kind() == reflect.Slice {
+ t = t.Elem()
+ }
+ if t.Kind() != reflect.Struct {
+ return ""
+ }
+ var fields []string
+ for i := 0; i < t.NumField(); i++ {
+ fields = append(fields, t.Field(i).Name)
+ }
+ b.WriteString(strings.Join(fields, ", "))
+ b.WriteString(" FROM ")
+ b.WriteString(t.Name())
+ b.WriteString(" " + where)
+ return b.String()
+}
diff --git a/vendor/github.com/elastic/gosigar/CHANGELOG.md b/vendor/github.com/elastic/gosigar/CHANGELOG.md
new file mode 100644
index 000000000..12695e10e
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/CHANGELOG.md
@@ -0,0 +1,102 @@
+# Change Log
+All notable changes to this project will be documented in this file.
+This project adheres to [Semantic Versioning](http://semver.org/).
+
+## [Unreleased]
+
+### Added
+
+### Fixed
+
+### Changed
+
+### Deprecated
+
+## [0.8.0]
+
+### Added
+- Added partial `getrusage` support for Windows to retrieve system CPU time and user CPU time. #95
+- Added full `getrusage` support for Unix. #95
+
+## [0.7.0]
+
+### Added
+- Added method stubs for process handling for operating system that are not supported
+ by gosigar. All methods return `ErrNotImplemented` on such systems. #88
+
+### Fixed
+- Fix freebsd build by using the common version of Get(pid). #91
+
+### Changed
+- Fixed issues in cgroup package by adding missing error checks and closing
+ file handles. #92
+
+## [0.6.0]
+
+### Added
+- Added method stubs to enable compilation for operating systems that are not
+ supported by gosigar. All methods return `ErrNotImplemented` on these unsupported
+ operating systems. #83
+- FreeBSD returns `ErrNotImplemented` for `ProcTime.Get`. #83
+
+### Changed
+- OpenBSD returns `ErrNotImplemented` for `ProcTime.Get` instead of `nil`. #83
+- Fixed incorrect `Mem.Used` calculation under linux. #82
+- Fixed `ProcState` on Linux and FreeBSD when process names contain parentheses. #81
+
+### Removed
+- Remove NetBSD build from sigar_unix.go as it is not supported by gosigar. #83
+
+## [0.5.0]
+
+### Changed
+- Fixed Trim environment variables when comparing values in the test suite. #79
+- Make `kern_procargs` more robust under darwin when we cannot retrieve
+ all the information about a process. #78
+
+## [0.4.0]
+
+### Changed
+- Fixed Windows issue that caused a hang during `init()` if WMI wasn't ready. #74
+
+## [0.3.0]
+
+### Added
+- Read `MemAvailable` value for kernel 3.14+ #71
+
+## [0.2.0]
+
+### Added
+- Added `ErrCgroupsMissing` to indicate that /proc/cgroups is missing which is
+ an indicator that cgroups were disabled at compile time. #64
+
+### Changed
+- Changed `cgroup.SupportedSubsystems()` to honor the "enabled" column in the
+ /proc/cgroups file. #64
+
+## [0.1.0]
+
+### Added
+- Added `CpuList` implementation for Windows that returns CPU timing information
+ on a per CPU basis. #55
+- Added `Uptime` implementation for Windows. #55
+- Added `Swap` implementation for Windows based on page file metrics. #55
+- Added support to `github.com/gosigar/sys/windows` for querying and enabling
+ privileges in a process token.
+- Added utility code for interfacing with linux NETLINK_INET_DIAG. #60
+- Added `ProcEnv` for getting a process's environment variables. #61
+
+### Changed
+- Changed several `OpenProcess` calls on Windows to request the lowest possible
+ access privileges. #50
+- Removed cgo usage from Windows code.
+- Added OS version checks to `ProcArgs.Get` on Windows because the
+ `Win32_Process` WMI query is not available prior to Windows vista. On XP and
+ Windows 2003, this method returns `ErrNotImplemented`. #55
+
+### Fixed
+- Fixed value of `Mem.ActualFree` and `Mem.ActualUsed` on Windows. #49
+- Fixed `ProcTime.StartTime` on Windows to report value in milliseconds since
+ Unix epoch. #51
+- Fixed `ProcStatus.PPID` value is wrong on Windows. #55
+- Fixed `ProcStatus.Username` error on Windows XP #56
diff --git a/vendor/github.com/elastic/gosigar/LICENSE b/vendor/github.com/elastic/gosigar/LICENSE
new file mode 100644
index 000000000..11069edd7
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/vendor/github.com/elastic/gosigar/NOTICE b/vendor/github.com/elastic/gosigar/NOTICE
new file mode 100644
index 000000000..fda553b5c
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/NOTICE
@@ -0,0 +1,9 @@
+Copyright (c) [2009-2011] VMware, Inc. All Rights Reserved.
+
+This product is licensed to you under the Apache License, Version 2.0 (the "License").
+You may not use this product except in compliance with the License.
+
+This product includes a number of subcomponents with
+separate copyright notices and license terms. Your use of these
+subcomponents is subject to the terms and conditions of the
+subcomponent's license, as noted in the LICENSE file. \ No newline at end of file
diff --git a/vendor/github.com/elastic/gosigar/README.md b/vendor/github.com/elastic/gosigar/README.md
new file mode 100644
index 000000000..2482620a8
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/README.md
@@ -0,0 +1,57 @@
+# Go sigar [![Build Status](https://travis-ci.org/elastic/gosigar.svg?branch=master)](https://travis-ci.org/elastic/gosigar) [![Build status](https://ci.appveyor.com/api/projects/status/4yh6sa7u97ek5uib/branch/master?svg=true)](https://ci.appveyor.com/project/elastic-beats/gosigar/branch/master)
+
+
+## Overview
+
+Go sigar is a golang implementation of the
+[sigar API](https://github.com/hyperic/sigar). The Go version of
+sigar has a very similar interface, but is being written from scratch
+in pure go/cgo, rather than cgo bindings for libsigar.
+
+## Test drive
+
+ $ go get github.com/elastic/gosigar
+ $ cd $GOPATH/src/github.com/elastic/gosigar/examples/ps
+ $ go build
+ $ ./ps
+
+## Supported platforms
+
+The features vary by operating system.
+
+| Feature | Linux | Darwin | Windows | OpenBSD | FreeBSD |
+|-----------------|:-----:|:------:|:-------:|:-------:|:-------:|
+| Cpu | X | X | X | X | X |
+| CpuList | X | X | | X | X |
+| FDUsage | X | | | | X |
+| FileSystemList | X | X | X | X | X |
+| FileSystemUsage | X | X | X | X | X |
+| LoadAverage | X | X | | X | X |
+| Mem | X | X | X | X | X |
+| ProcArgs | X | X | X | | X |
+| ProcEnv | X | X | | | X |
+| ProcExe | X | X | | | X |
+| ProcFDUsage | X | | | | X |
+| ProcList | X | X | X | | X |
+| ProcMem | X | X | X | | X |
+| ProcState | X | X | X | | X |
+| ProcTime | X | X | X | | X |
+| Swap | X | X | | X | X |
+| Uptime | X | X | | X | X |
+
+## OS Specific Notes
+
+### FreeBSD
+
+Mount both `linprocfs` and `procfs` for compatability. Consider adding these
+mounts to your `/etc/fstab` file so they are mounted automatically at boot.
+
+```
+sudo mount -t procfs proc /proc
+sudo mkdir -p /compat/linux/proc
+sudo mount -t linprocfs /dev/null /compat/linux/proc
+```
+
+## License
+
+Apache 2.0
diff --git a/vendor/github.com/elastic/gosigar/Vagrantfile b/vendor/github.com/elastic/gosigar/Vagrantfile
new file mode 100644
index 000000000..6fd990c14
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/Vagrantfile
@@ -0,0 +1,25 @@
+# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
+VAGRANTFILE_API_VERSION = "2"
+
+Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
+ config.vm.box = "hashicorp/precise64"
+ config.vm.provision "shell", inline: "mkdir -p /home/vagrant/go"
+ config.vm.synced_folder ".", "/home/vagrant/go/src/github.com/cloudfoundry/gosigar"
+ config.vm.provision "shell", inline: "chown -R vagrant:vagrant /home/vagrant/go"
+ install_go = <<-BASH
+ set -e
+
+if [ ! -d "/usr/local/go" ]; then
+ cd /tmp && wget https://storage.googleapis.com/golang/go1.3.3.linux-amd64.tar.gz
+ cd /usr/local
+ tar xvzf /tmp/go1.3.3.linux-amd64.tar.gz
+ echo 'export GOPATH=/home/vagrant/go; export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin' >> /home/vagrant/.bashrc
+fi
+export GOPATH=/home/vagrant/go
+export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin
+/usr/local/go/bin/go get -u github.com/onsi/ginkgo/ginkgo
+/usr/local/go/bin/go get -u github.com/onsi/gomega;
+BASH
+ config.vm.provision "shell", inline: 'apt-get install -y git-core'
+ config.vm.provision "shell", inline: install_go
+end
diff --git a/vendor/github.com/elastic/gosigar/codecov.yml b/vendor/github.com/elastic/gosigar/codecov.yml
new file mode 100644
index 000000000..76ade0fdb
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/codecov.yml
@@ -0,0 +1,21 @@
+# Enable coverage report message for diff on commit
+coverage:
+ status:
+ project: off
+ patch:
+ default:
+ # basic
+ target: auto
+ threshold: null
+ base: auto
+ # advanced
+ branches: null
+ if_no_uploads: error
+ if_not_found: success
+ if_ci_failed: error
+ only_pulls: false
+ flags: null
+ paths: null
+
+# Disable comments on Pull Requests
+comment: false
diff --git a/vendor/github.com/elastic/gosigar/concrete_sigar.go b/vendor/github.com/elastic/gosigar/concrete_sigar.go
new file mode 100644
index 000000000..685aa6ded
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/concrete_sigar.go
@@ -0,0 +1,83 @@
+package gosigar
+
+import (
+ "time"
+)
+
+type ConcreteSigar struct{}
+
+func (c *ConcreteSigar) CollectCpuStats(collectionInterval time.Duration) (<-chan Cpu, chan<- struct{}) {
+ // samplesCh is buffered to 1 value to immediately return first CPU sample
+ samplesCh := make(chan Cpu, 1)
+
+ stopCh := make(chan struct{})
+
+ go func() {
+ var cpuUsage Cpu
+
+ // Immediately provide non-delta value.
+ // samplesCh is buffered to 1 value, so it will not block.
+ cpuUsage.Get()
+ samplesCh <- cpuUsage
+
+ ticker := time.NewTicker(collectionInterval)
+
+ for {
+ select {
+ case <-ticker.C:
+ previousCpuUsage := cpuUsage
+
+ cpuUsage.Get()
+
+ select {
+ case samplesCh <- cpuUsage.Delta(previousCpuUsage):
+ default:
+ // Include default to avoid channel blocking
+ }
+
+ case <-stopCh:
+ return
+ }
+ }
+ }()
+
+ return samplesCh, stopCh
+}
+
+func (c *ConcreteSigar) GetLoadAverage() (LoadAverage, error) {
+ l := LoadAverage{}
+ err := l.Get()
+ return l, err
+}
+
+func (c *ConcreteSigar) GetMem() (Mem, error) {
+ m := Mem{}
+ err := m.Get()
+ return m, err
+}
+
+func (c *ConcreteSigar) GetSwap() (Swap, error) {
+ s := Swap{}
+ err := s.Get()
+ return s, err
+}
+
+func (c *ConcreteSigar) GetFileSystemUsage(path string) (FileSystemUsage, error) {
+ f := FileSystemUsage{}
+ err := f.Get(path)
+ return f, err
+}
+
+func (c *ConcreteSigar) GetFDUsage() (FDUsage, error) {
+ fd := FDUsage{}
+ err := fd.Get()
+ return fd, err
+}
+
+// GetRusage return the resource usage of the process
+// Possible params: 0 = RUSAGE_SELF, 1 = RUSAGE_CHILDREN, 2 = RUSAGE_THREAD
+func (c *ConcreteSigar) GetRusage(who int) (Rusage, error) {
+ r := Rusage{}
+ err := r.Get(who)
+ return r, err
+}
diff --git a/vendor/github.com/elastic/gosigar/sigar_darwin.go b/vendor/github.com/elastic/gosigar/sigar_darwin.go
new file mode 100644
index 000000000..f989f5160
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sigar_darwin.go
@@ -0,0 +1,494 @@
+// Copyright (c) 2012 VMware, Inc.
+
+package gosigar
+
+/*
+#include <stdlib.h>
+#include <sys/sysctl.h>
+#include <sys/mount.h>
+#include <mach/mach_init.h>
+#include <mach/mach_host.h>
+#include <mach/host_info.h>
+#include <libproc.h>
+#include <mach/processor_info.h>
+#include <mach/vm_map.h>
+*/
+import "C"
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "os/user"
+ "runtime"
+ "strconv"
+ "syscall"
+ "time"
+ "unsafe"
+)
+
+func (self *LoadAverage) Get() error {
+ avg := []C.double{0, 0, 0}
+
+ C.getloadavg(&avg[0], C.int(len(avg)))
+
+ self.One = float64(avg[0])
+ self.Five = float64(avg[1])
+ self.Fifteen = float64(avg[2])
+
+ return nil
+}
+
+func (self *Uptime) Get() error {
+ tv := syscall.Timeval32{}
+
+ if err := sysctlbyname("kern.boottime", &tv); err != nil {
+ return err
+ }
+
+ self.Length = time.Since(time.Unix(int64(tv.Sec), int64(tv.Usec)*1000)).Seconds()
+
+ return nil
+}
+
+func (self *Mem) Get() error {
+ var vmstat C.vm_statistics_data_t
+
+ if err := sysctlbyname("hw.memsize", &self.Total); err != nil {
+ return err
+ }
+
+ if err := vm_info(&vmstat); err != nil {
+ return err
+ }
+
+ kern := uint64(vmstat.inactive_count) << 12
+ self.Free = uint64(vmstat.free_count) << 12
+
+ self.Used = self.Total - self.Free
+ self.ActualFree = self.Free + kern
+ self.ActualUsed = self.Used - kern
+
+ return nil
+}
+
+type xsw_usage struct {
+ Total, Avail, Used uint64
+}
+
+func (self *Swap) Get() error {
+ sw_usage := xsw_usage{}
+
+ if err := sysctlbyname("vm.swapusage", &sw_usage); err != nil {
+ return err
+ }
+
+ self.Total = sw_usage.Total
+ self.Used = sw_usage.Used
+ self.Free = sw_usage.Avail
+
+ return nil
+}
+
+func (self *Cpu) Get() error {
+ var count C.mach_msg_type_number_t = C.HOST_CPU_LOAD_INFO_COUNT
+ var cpuload C.host_cpu_load_info_data_t
+
+ status := C.host_statistics(C.host_t(C.mach_host_self()),
+ C.HOST_CPU_LOAD_INFO,
+ C.host_info_t(unsafe.Pointer(&cpuload)),
+ &count)
+
+ if status != C.KERN_SUCCESS {
+ return fmt.Errorf("host_statistics error=%d", status)
+ }
+
+ self.User = uint64(cpuload.cpu_ticks[C.CPU_STATE_USER])
+ self.Sys = uint64(cpuload.cpu_ticks[C.CPU_STATE_SYSTEM])
+ self.Idle = uint64(cpuload.cpu_ticks[C.CPU_STATE_IDLE])
+ self.Nice = uint64(cpuload.cpu_ticks[C.CPU_STATE_NICE])
+
+ return nil
+}
+
+func (self *CpuList) Get() error {
+ var count C.mach_msg_type_number_t
+ var cpuload *C.processor_cpu_load_info_data_t
+ var ncpu C.natural_t
+
+ status := C.host_processor_info(C.host_t(C.mach_host_self()),
+ C.PROCESSOR_CPU_LOAD_INFO,
+ &ncpu,
+ (*C.processor_info_array_t)(unsafe.Pointer(&cpuload)),
+ &count)
+
+ if status != C.KERN_SUCCESS {
+ return fmt.Errorf("host_processor_info error=%d", status)
+ }
+
+ // jump through some cgo casting hoops and ensure we properly free
+ // the memory that cpuload points to
+ target := C.vm_map_t(C.mach_task_self_)
+ address := C.vm_address_t(uintptr(unsafe.Pointer(cpuload)))
+ defer C.vm_deallocate(target, address, C.vm_size_t(ncpu))
+
+ // the body of struct processor_cpu_load_info
+ // aka processor_cpu_load_info_data_t
+ var cpu_ticks [C.CPU_STATE_MAX]uint32
+
+ // copy the cpuload array to a []byte buffer
+ // where we can binary.Read the data
+ size := int(ncpu) * binary.Size(cpu_ticks)
+ buf := C.GoBytes(unsafe.Pointer(cpuload), C.int(size))
+
+ bbuf := bytes.NewBuffer(buf)
+
+ self.List = make([]Cpu, 0, ncpu)
+
+ for i := 0; i < int(ncpu); i++ {
+ cpu := Cpu{}
+
+ err := binary.Read(bbuf, binary.LittleEndian, &cpu_ticks)
+ if err != nil {
+ return err
+ }
+
+ cpu.User = uint64(cpu_ticks[C.CPU_STATE_USER])
+ cpu.Sys = uint64(cpu_ticks[C.CPU_STATE_SYSTEM])
+ cpu.Idle = uint64(cpu_ticks[C.CPU_STATE_IDLE])
+ cpu.Nice = uint64(cpu_ticks[C.CPU_STATE_NICE])
+
+ self.List = append(self.List, cpu)
+ }
+
+ return nil
+}
+
+func (self *FDUsage) Get() error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (self *FileSystemList) Get() error {
+ num, err := syscall.Getfsstat(nil, C.MNT_NOWAIT)
+ if err != nil {
+ return err
+ }
+
+ buf := make([]syscall.Statfs_t, num)
+
+ _, err = syscall.Getfsstat(buf, C.MNT_NOWAIT)
+ if err != nil {
+ return err
+ }
+
+ fslist := make([]FileSystem, 0, num)
+
+ for i := 0; i < num; i++ {
+ fs := FileSystem{}
+
+ fs.DirName = bytePtrToString(&buf[i].Mntonname[0])
+ fs.DevName = bytePtrToString(&buf[i].Mntfromname[0])
+ fs.SysTypeName = bytePtrToString(&buf[i].Fstypename[0])
+
+ fslist = append(fslist, fs)
+ }
+
+ self.List = fslist
+
+ return err
+}
+
+func (self *ProcList) Get() error {
+ n := C.proc_listpids(C.PROC_ALL_PIDS, 0, nil, 0)
+ if n <= 0 {
+ return syscall.EINVAL
+ }
+ buf := make([]byte, n)
+ n = C.proc_listpids(C.PROC_ALL_PIDS, 0, unsafe.Pointer(&buf[0]), n)
+ if n <= 0 {
+ return syscall.ENOMEM
+ }
+
+ var pid int32
+ num := int(n) / binary.Size(pid)
+ list := make([]int, 0, num)
+ bbuf := bytes.NewBuffer(buf)
+
+ for i := 0; i < num; i++ {
+ if err := binary.Read(bbuf, binary.LittleEndian, &pid); err != nil {
+ return err
+ }
+ if pid == 0 {
+ continue
+ }
+
+ list = append(list, int(pid))
+ }
+
+ self.List = list
+
+ return nil
+}
+
+func (self *ProcState) Get(pid int) error {
+ info := C.struct_proc_taskallinfo{}
+
+ if err := task_info(pid, &info); err != nil {
+ return err
+ }
+
+ self.Name = C.GoString(&info.pbsd.pbi_comm[0])
+
+ switch info.pbsd.pbi_status {
+ case C.SIDL:
+ self.State = RunStateIdle
+ case C.SRUN:
+ self.State = RunStateRun
+ case C.SSLEEP:
+ self.State = RunStateSleep
+ case C.SSTOP:
+ self.State = RunStateStop
+ case C.SZOMB:
+ self.State = RunStateZombie
+ default:
+ self.State = RunStateUnknown
+ }
+
+ self.Ppid = int(info.pbsd.pbi_ppid)
+
+ self.Pgid = int(info.pbsd.pbi_pgid)
+
+ self.Tty = int(info.pbsd.e_tdev)
+
+ self.Priority = int(info.ptinfo.pti_priority)
+
+ self.Nice = int(info.pbsd.pbi_nice)
+
+ // Get process username. Fallback to UID if username is not available.
+ uid := strconv.Itoa(int(info.pbsd.pbi_uid))
+ user, err := user.LookupId(uid)
+ if err == nil && user.Username != "" {
+ self.Username = user.Username
+ } else {
+ self.Username = uid
+ }
+
+ return nil
+}
+
+func (self *ProcMem) Get(pid int) error {
+ info := C.struct_proc_taskallinfo{}
+
+ if err := task_info(pid, &info); err != nil {
+ return err
+ }
+
+ self.Size = uint64(info.ptinfo.pti_virtual_size)
+ self.Resident = uint64(info.ptinfo.pti_resident_size)
+ self.PageFaults = uint64(info.ptinfo.pti_faults)
+
+ return nil
+}
+
+func (self *ProcTime) Get(pid int) error {
+ info := C.struct_proc_taskallinfo{}
+
+ if err := task_info(pid, &info); err != nil {
+ return err
+ }
+
+ self.User =
+ uint64(info.ptinfo.pti_total_user) / uint64(time.Millisecond)
+
+ self.Sys =
+ uint64(info.ptinfo.pti_total_system) / uint64(time.Millisecond)
+
+ self.Total = self.User + self.Sys
+
+ self.StartTime = (uint64(info.pbsd.pbi_start_tvsec) * 1000) +
+ (uint64(info.pbsd.pbi_start_tvusec) / 1000)
+
+ return nil
+}
+
+func (self *ProcArgs) Get(pid int) error {
+ var args []string
+
+ argv := func(arg string) {
+ args = append(args, arg)
+ }
+
+ err := kern_procargs(pid, nil, argv, nil)
+
+ self.List = args
+
+ return err
+}
+
+func (self *ProcEnv) Get(pid int) error {
+ if self.Vars == nil {
+ self.Vars = map[string]string{}
+ }
+
+ env := func(k, v string) {
+ self.Vars[k] = v
+ }
+
+ return kern_procargs(pid, nil, nil, env)
+}
+
+func (self *ProcExe) Get(pid int) error {
+ exe := func(arg string) {
+ self.Name = arg
+ }
+
+ return kern_procargs(pid, exe, nil, nil)
+}
+
+func (self *ProcFDUsage) Get(pid int) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+// wrapper around sysctl KERN_PROCARGS2
+// callbacks params are optional,
+// up to the caller as to which pieces of data they want
+func kern_procargs(pid int,
+ exe func(string),
+ argv func(string),
+ env func(string, string)) error {
+
+ mib := []C.int{C.CTL_KERN, C.KERN_PROCARGS2, C.int(pid)}
+ argmax := uintptr(C.ARG_MAX)
+ buf := make([]byte, argmax)
+ err := sysctl(mib, &buf[0], &argmax, nil, 0)
+ if err != nil {
+ return nil
+ }
+
+ bbuf := bytes.NewBuffer(buf)
+ bbuf.Truncate(int(argmax))
+
+ var argc int32
+ binary.Read(bbuf, binary.LittleEndian, &argc)
+
+ path, err := bbuf.ReadBytes(0)
+ if err != nil {
+ return fmt.Errorf("Error reading the argv[0]: %v", err)
+ }
+ if exe != nil {
+ exe(string(chop(path)))
+ }
+
+ // skip trailing \0's
+ for {
+ c, err := bbuf.ReadByte()
+ if err != nil {
+ return fmt.Errorf("Error skipping nils: %v", err)
+ }
+ if c != 0 {
+ bbuf.UnreadByte()
+ break // start of argv[0]
+ }
+ }
+
+ for i := 0; i < int(argc); i++ {
+ arg, err := bbuf.ReadBytes(0)
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return fmt.Errorf("Error reading args: %v", err)
+ }
+ if argv != nil {
+ argv(string(chop(arg)))
+ }
+ }
+
+ if env == nil {
+ return nil
+ }
+
+ delim := []byte{61} // "="
+
+ for {
+ line, err := bbuf.ReadBytes(0)
+ if err == io.EOF || line[0] == 0 {
+ break
+ }
+ if err != nil {
+ return fmt.Errorf("Error reading args: %v", err)
+ }
+ pair := bytes.SplitN(chop(line), delim, 2)
+
+ if len(pair) != 2 {
+ return fmt.Errorf("Error reading process information for PID: %d", pid)
+ }
+
+ env(string(pair[0]), string(pair[1]))
+ }
+
+ return nil
+}
+
+// XXX copied from zsyscall_darwin_amd64.go
+func sysctl(mib []C.int, old *byte, oldlen *uintptr,
+ new *byte, newlen uintptr) (err error) {
+ var p0 unsafe.Pointer
+ p0 = unsafe.Pointer(&mib[0])
+ _, _, e1 := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(p0),
+ uintptr(len(mib)),
+ uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)),
+ uintptr(unsafe.Pointer(new)), uintptr(newlen))
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
+func vm_info(vmstat *C.vm_statistics_data_t) error {
+ var count C.mach_msg_type_number_t = C.HOST_VM_INFO_COUNT
+
+ status := C.host_statistics(
+ C.host_t(C.mach_host_self()),
+ C.HOST_VM_INFO,
+ C.host_info_t(unsafe.Pointer(vmstat)),
+ &count)
+
+ if status != C.KERN_SUCCESS {
+ return fmt.Errorf("host_statistics=%d", status)
+ }
+
+ return nil
+}
+
+// generic Sysctl buffer unmarshalling
+func sysctlbyname(name string, data interface{}) (err error) {
+ val, err := syscall.Sysctl(name)
+ if err != nil {
+ return err
+ }
+
+ buf := []byte(val)
+
+ switch v := data.(type) {
+ case *uint64:
+ *v = *(*uint64)(unsafe.Pointer(&buf[0]))
+ return
+ }
+
+ bbuf := bytes.NewBuffer([]byte(val))
+ return binary.Read(bbuf, binary.LittleEndian, data)
+}
+
+func task_info(pid int, info *C.struct_proc_taskallinfo) error {
+ size := C.int(unsafe.Sizeof(*info))
+ ptr := unsafe.Pointer(info)
+
+ n := C.proc_pidinfo(C.int(pid), C.PROC_PIDTASKALLINFO, 0, ptr, size)
+ if n != size {
+ return fmt.Errorf("Could not read process info for pid %d", pid)
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/elastic/gosigar/sigar_format.go b/vendor/github.com/elastic/gosigar/sigar_format.go
new file mode 100644
index 000000000..ac56c9873
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sigar_format.go
@@ -0,0 +1,126 @@
+// Copyright (c) 2012 VMware, Inc.
+
+package gosigar
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "strconv"
+ "time"
+)
+
+// Go version of apr_strfsize
+func FormatSize(size uint64) string {
+ ord := []string{"K", "M", "G", "T", "P", "E"}
+ o := 0
+ buf := new(bytes.Buffer)
+ w := bufio.NewWriter(buf)
+
+ if size < 973 {
+ fmt.Fprintf(w, "%3d ", size)
+ w.Flush()
+ return buf.String()
+ }
+
+ for {
+ remain := size & 1023
+ size >>= 10
+
+ if size >= 973 {
+ o++
+ continue
+ }
+
+ if size < 9 || (size == 9 && remain < 973) {
+ remain = ((remain * 5) + 256) / 512
+ if remain >= 10 {
+ size++
+ remain = 0
+ }
+
+ fmt.Fprintf(w, "%d.%d%s", size, remain, ord[o])
+ break
+ }
+
+ if remain >= 512 {
+ size++
+ }
+
+ fmt.Fprintf(w, "%3d%s", size, ord[o])
+ break
+ }
+
+ w.Flush()
+ return buf.String()
+}
+
+func FormatPercent(percent float64) string {
+ return strconv.FormatFloat(percent, 'f', -1, 64) + "%"
+}
+
+func (self *FileSystemUsage) UsePercent() float64 {
+ b_used := (self.Total - self.Free) / 1024
+ b_avail := self.Avail / 1024
+ utotal := b_used + b_avail
+ used := b_used
+
+ if utotal != 0 {
+ u100 := used * 100
+ pct := u100 / utotal
+ if u100%utotal != 0 {
+ pct += 1
+ }
+ return (float64(pct) / float64(100)) * 100.0
+ }
+
+ return 0.0
+}
+
+func (self *Uptime) Format() string {
+ buf := new(bytes.Buffer)
+ w := bufio.NewWriter(buf)
+ uptime := uint64(self.Length)
+
+ days := uptime / (60 * 60 * 24)
+
+ if days != 0 {
+ s := ""
+ if days > 1 {
+ s = "s"
+ }
+ fmt.Fprintf(w, "%d day%s, ", days, s)
+ }
+
+ minutes := uptime / 60
+ hours := minutes / 60
+ hours %= 24
+ minutes %= 60
+
+ fmt.Fprintf(w, "%2d:%02d", hours, minutes)
+
+ w.Flush()
+ return buf.String()
+}
+
+func (self *ProcTime) FormatStartTime() string {
+ if self.StartTime == 0 {
+ return "00:00"
+ }
+ start := time.Unix(int64(self.StartTime)/1000, 0)
+ format := "Jan02"
+ if time.Since(start).Seconds() < (60 * 60 * 24) {
+ format = "15:04"
+ }
+ return start.Format(format)
+}
+
+func (self *ProcTime) FormatTotal() string {
+ t := self.Total / 1000
+ ss := t % 60
+ t /= 60
+ mm := t % 60
+ t /= 60
+ hh := t % 24
+ return fmt.Sprintf("%02d:%02d:%02d", hh, mm, ss)
+}
diff --git a/vendor/github.com/elastic/gosigar/sigar_freebsd.go b/vendor/github.com/elastic/gosigar/sigar_freebsd.go
new file mode 100644
index 000000000..602b4a0aa
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sigar_freebsd.go
@@ -0,0 +1,108 @@
+// Copied and modified from sigar_linux.go.
+
+package gosigar
+
+import (
+ "io/ioutil"
+ "strconv"
+ "strings"
+ "unsafe"
+)
+
+/*
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/ucred.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <time.h>
+*/
+import "C"
+
+func init() {
+ system.ticks = uint64(C.sysconf(C._SC_CLK_TCK))
+
+ Procd = "/compat/linux/proc"
+
+ getLinuxBootTime()
+}
+
+func getMountTableFileName() string {
+ return Procd + "/mtab"
+}
+
+func (self *Uptime) Get() error {
+ ts := C.struct_timespec{}
+
+ if _, err := C.clock_gettime(C.CLOCK_UPTIME, &ts); err != nil {
+ return err
+ }
+
+ self.Length = float64(ts.tv_sec) + 1e-9*float64(ts.tv_nsec)
+
+ return nil
+}
+
+func (self *FDUsage) Get() error {
+ val := C.uint32_t(0)
+ sc := C.size_t(4)
+
+ name := C.CString("kern.openfiles")
+ _, err := C.sysctlbyname(name, unsafe.Pointer(&val), &sc, nil, 0)
+ C.free(unsafe.Pointer(name))
+ if err != nil {
+ return err
+ }
+ self.Open = uint64(val)
+
+ name = C.CString("kern.maxfiles")
+ _, err = C.sysctlbyname(name, unsafe.Pointer(&val), &sc, nil, 0)
+ C.free(unsafe.Pointer(name))
+ if err != nil {
+ return err
+ }
+ self.Max = uint64(val)
+
+ self.Unused = self.Max - self.Open
+
+ return nil
+}
+
+func (self *ProcFDUsage) Get(pid int) error {
+ err := readFile("/proc/"+strconv.Itoa(pid)+"/rlimit", func(line string) bool {
+ if strings.HasPrefix(line, "nofile") {
+ fields := strings.Fields(line)
+ if len(fields) == 3 {
+ self.SoftLimit, _ = strconv.ParseUint(fields[1], 10, 64)
+ self.HardLimit, _ = strconv.ParseUint(fields[2], 10, 64)
+ }
+ return false
+ }
+ return true
+ })
+ if err != nil {
+ return err
+ }
+
+ // linprocfs only provides this information for this process (self).
+ fds, err := ioutil.ReadDir(procFileName(pid, "fd"))
+ if err != nil {
+ return err
+ }
+ self.Open = uint64(len(fds))
+
+ return nil
+}
+
+func parseCpuStat(self *Cpu, line string) error {
+ fields := strings.Fields(line)
+
+ self.User, _ = strtoull(fields[1])
+ self.Nice, _ = strtoull(fields[2])
+ self.Sys, _ = strtoull(fields[3])
+ self.Idle, _ = strtoull(fields[4])
+ return nil
+}
diff --git a/vendor/github.com/elastic/gosigar/sigar_interface.go b/vendor/github.com/elastic/gosigar/sigar_interface.go
new file mode 100644
index 000000000..a956af604
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sigar_interface.go
@@ -0,0 +1,197 @@
+package gosigar
+
+import (
+ "time"
+)
+
+type ErrNotImplemented struct {
+ OS string
+}
+
+func (e ErrNotImplemented) Error() string {
+ return "not implemented on " + e.OS
+}
+
+func IsNotImplemented(err error) bool {
+ switch err.(type) {
+ case ErrNotImplemented, *ErrNotImplemented:
+ return true
+ default:
+ return false
+ }
+}
+
+type Sigar interface {
+ CollectCpuStats(collectionInterval time.Duration) (<-chan Cpu, chan<- struct{})
+ GetLoadAverage() (LoadAverage, error)
+ GetMem() (Mem, error)
+ GetSwap() (Swap, error)
+ GetFileSystemUsage(string) (FileSystemUsage, error)
+ GetFDUsage() (FDUsage, error)
+ GetRusage(who int) (Rusage, error)
+}
+
+type Cpu struct {
+ User uint64
+ Nice uint64
+ Sys uint64
+ Idle uint64
+ Wait uint64
+ Irq uint64
+ SoftIrq uint64
+ Stolen uint64
+}
+
+func (cpu *Cpu) Total() uint64 {
+ return cpu.User + cpu.Nice + cpu.Sys + cpu.Idle +
+ cpu.Wait + cpu.Irq + cpu.SoftIrq + cpu.Stolen
+}
+
+func (cpu Cpu) Delta(other Cpu) Cpu {
+ return Cpu{
+ User: cpu.User - other.User,
+ Nice: cpu.Nice - other.Nice,
+ Sys: cpu.Sys - other.Sys,
+ Idle: cpu.Idle - other.Idle,
+ Wait: cpu.Wait - other.Wait,
+ Irq: cpu.Irq - other.Irq,
+ SoftIrq: cpu.SoftIrq - other.SoftIrq,
+ Stolen: cpu.Stolen - other.Stolen,
+ }
+}
+
+type LoadAverage struct {
+ One, Five, Fifteen float64
+}
+
+type Uptime struct {
+ Length float64
+}
+
+type Mem struct {
+ Total uint64
+ Used uint64
+ Free uint64
+ ActualFree uint64
+ ActualUsed uint64
+}
+
+type Swap struct {
+ Total uint64
+ Used uint64
+ Free uint64
+}
+
+type CpuList struct {
+ List []Cpu
+}
+
+type FDUsage struct {
+ Open uint64
+ Unused uint64
+ Max uint64
+}
+
+type FileSystem struct {
+ DirName string
+ DevName string
+ TypeName string
+ SysTypeName string
+ Options string
+ Flags uint32
+}
+
+type FileSystemList struct {
+ List []FileSystem
+}
+
+type FileSystemUsage struct {
+ Total uint64
+ Used uint64
+ Free uint64
+ Avail uint64
+ Files uint64
+ FreeFiles uint64
+}
+
+type ProcList struct {
+ List []int
+}
+
+type RunState byte
+
+const (
+ RunStateSleep = 'S'
+ RunStateRun = 'R'
+ RunStateStop = 'T'
+ RunStateZombie = 'Z'
+ RunStateIdle = 'D'
+ RunStateUnknown = '?'
+)
+
+type ProcState struct {
+ Name string
+ Username string
+ State RunState
+ Ppid int
+ Pgid int
+ Tty int
+ Priority int
+ Nice int
+ Processor int
+}
+
+type ProcMem struct {
+ Size uint64
+ Resident uint64
+ Share uint64
+ MinorFaults uint64
+ MajorFaults uint64
+ PageFaults uint64
+}
+
+type ProcTime struct {
+ StartTime uint64
+ User uint64
+ Sys uint64
+ Total uint64
+}
+
+type ProcArgs struct {
+ List []string
+}
+
+type ProcEnv struct {
+ Vars map[string]string
+}
+
+type ProcExe struct {
+ Name string
+ Cwd string
+ Root string
+}
+
+type ProcFDUsage struct {
+ Open uint64
+ SoftLimit uint64
+ HardLimit uint64
+}
+
+type Rusage struct {
+ Utime time.Duration
+ Stime time.Duration
+ Maxrss int64
+ Ixrss int64
+ Idrss int64
+ Isrss int64
+ Minflt int64
+ Majflt int64
+ Nswap int64
+ Inblock int64
+ Oublock int64
+ Msgsnd int64
+ Msgrcv int64
+ Nsignals int64
+ Nvcsw int64
+ Nivcsw int64
+}
diff --git a/vendor/github.com/elastic/gosigar/sigar_linux.go b/vendor/github.com/elastic/gosigar/sigar_linux.go
new file mode 100644
index 000000000..cb1d3525b
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sigar_linux.go
@@ -0,0 +1,84 @@
+// Copyright (c) 2012 VMware, Inc.
+
+package gosigar
+
+import (
+ "io/ioutil"
+ "strconv"
+ "strings"
+ "syscall"
+)
+
+func init() {
+ system.ticks = 100 // C.sysconf(C._SC_CLK_TCK)
+
+ Procd = "/proc"
+
+ getLinuxBootTime()
+}
+
+func getMountTableFileName() string {
+ return "/etc/mtab"
+}
+
+func (self *Uptime) Get() error {
+ sysinfo := syscall.Sysinfo_t{}
+
+ if err := syscall.Sysinfo(&sysinfo); err != nil {
+ return err
+ }
+
+ self.Length = float64(sysinfo.Uptime)
+
+ return nil
+}
+
+func (self *FDUsage) Get() error {
+ return readFile(Procd+"/sys/fs/file-nr", func(line string) bool {
+ fields := strings.Fields(line)
+ if len(fields) == 3 {
+ self.Open, _ = strconv.ParseUint(fields[0], 10, 64)
+ self.Unused, _ = strconv.ParseUint(fields[1], 10, 64)
+ self.Max, _ = strconv.ParseUint(fields[2], 10, 64)
+ }
+ return false
+ })
+}
+
+func (self *ProcFDUsage) Get(pid int) error {
+ err := readFile(procFileName(pid, "limits"), func(line string) bool {
+ if strings.HasPrefix(line, "Max open files") {
+ fields := strings.Fields(line)
+ if len(fields) == 6 {
+ self.SoftLimit, _ = strconv.ParseUint(fields[3], 10, 64)
+ self.HardLimit, _ = strconv.ParseUint(fields[4], 10, 64)
+ }
+ return false
+ }
+ return true
+ })
+ if err != nil {
+ return err
+ }
+ fds, err := ioutil.ReadDir(procFileName(pid, "fd"))
+ if err != nil {
+ return err
+ }
+ self.Open = uint64(len(fds))
+ return nil
+}
+
+func parseCpuStat(self *Cpu, line string) error {
+ fields := strings.Fields(line)
+
+ self.User, _ = strtoull(fields[1])
+ self.Nice, _ = strtoull(fields[2])
+ self.Sys, _ = strtoull(fields[3])
+ self.Idle, _ = strtoull(fields[4])
+ self.Wait, _ = strtoull(fields[5])
+ self.Irq, _ = strtoull(fields[6])
+ self.SoftIrq, _ = strtoull(fields[7])
+ self.Stolen, _ = strtoull(fields[8])
+
+ return nil
+}
diff --git a/vendor/github.com/elastic/gosigar/sigar_linux_common.go b/vendor/github.com/elastic/gosigar/sigar_linux_common.go
new file mode 100644
index 000000000..8e5e7856f
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sigar_linux_common.go
@@ -0,0 +1,468 @@
+// Copyright (c) 2012 VMware, Inc.
+
+// +build freebsd linux
+
+package gosigar
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "os/user"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "syscall"
+)
+
+var system struct {
+ ticks uint64
+ btime uint64
+}
+
+var Procd string
+
+func getLinuxBootTime() {
+ // grab system boot time
+ readFile(Procd+"/stat", func(line string) bool {
+ if strings.HasPrefix(line, "btime") {
+ system.btime, _ = strtoull(line[6:])
+ return false // stop reading
+ }
+ return true
+ })
+}
+
+func (self *LoadAverage) Get() error {
+ line, err := ioutil.ReadFile(Procd + "/loadavg")
+ if err != nil {
+ return nil
+ }
+
+ fields := strings.Fields(string(line))
+
+ self.One, _ = strconv.ParseFloat(fields[0], 64)
+ self.Five, _ = strconv.ParseFloat(fields[1], 64)
+ self.Fifteen, _ = strconv.ParseFloat(fields[2], 64)
+
+ return nil
+}
+
+func (self *Mem) Get() error {
+
+ table, err := parseMeminfo()
+ if err != nil {
+ return err
+ }
+
+ self.Total, _ = table["MemTotal"]
+ self.Free, _ = table["MemFree"]
+ buffers, _ := table["Buffers"]
+ cached, _ := table["Cached"]
+
+ if available, ok := table["MemAvailable"]; ok {
+ // MemAvailable is in /proc/meminfo (kernel 3.14+)
+ self.ActualFree = available
+ } else {
+ self.ActualFree = self.Free + buffers + cached
+ }
+
+ self.Used = self.Total - self.Free
+ self.ActualUsed = self.Total - self.ActualFree
+
+ return nil
+}
+
+func (self *Swap) Get() error {
+
+ table, err := parseMeminfo()
+ if err != nil {
+ return err
+ }
+ self.Total, _ = table["SwapTotal"]
+ self.Free, _ = table["SwapFree"]
+
+ self.Used = self.Total - self.Free
+ return nil
+}
+
+func (self *Cpu) Get() error {
+ return readFile(Procd+"/stat", func(line string) bool {
+ if len(line) > 4 && line[0:4] == "cpu " {
+ parseCpuStat(self, line)
+ return false
+ }
+ return true
+
+ })
+}
+
+func (self *CpuList) Get() error {
+ capacity := len(self.List)
+ if capacity == 0 {
+ capacity = 4
+ }
+ list := make([]Cpu, 0, capacity)
+
+ err := readFile(Procd+"/stat", func(line string) bool {
+ if len(line) > 3 && line[0:3] == "cpu" && line[3] != ' ' {
+ cpu := Cpu{}
+ parseCpuStat(&cpu, line)
+ list = append(list, cpu)
+ }
+ return true
+ })
+
+ self.List = list
+
+ return err
+}
+
+func (self *FileSystemList) Get() error {
+ capacity := len(self.List)
+ if capacity == 0 {
+ capacity = 10
+ }
+ fslist := make([]FileSystem, 0, capacity)
+
+ err := readFile(getMountTableFileName(), func(line string) bool {
+ fields := strings.Fields(line)
+
+ fs := FileSystem{}
+ fs.DevName = fields[0]
+ fs.DirName = fields[1]
+ fs.SysTypeName = fields[2]
+ fs.Options = fields[3]
+
+ fslist = append(fslist, fs)
+
+ return true
+ })
+
+ self.List = fslist
+
+ return err
+}
+
+func (self *ProcList) Get() error {
+ dir, err := os.Open(Procd)
+ if err != nil {
+ return err
+ }
+ defer dir.Close()
+
+ const readAllDirnames = -1 // see os.File.Readdirnames doc
+
+ names, err := dir.Readdirnames(readAllDirnames)
+ if err != nil {
+ return err
+ }
+
+ capacity := len(names)
+ list := make([]int, 0, capacity)
+
+ for _, name := range names {
+ if name[0] < '0' || name[0] > '9' {
+ continue
+ }
+ pid, err := strconv.Atoi(name)
+ if err == nil {
+ list = append(list, pid)
+ }
+ }
+
+ self.List = list
+
+ return nil
+}
+
+func (self *ProcState) Get(pid int) error {
+ data, err := readProcFile(pid, "stat")
+ if err != nil {
+ return err
+ }
+
+ // Extract the comm value with is surrounded by parentheses.
+ lIdx := bytes.Index(data, []byte("("))
+ rIdx := bytes.LastIndex(data, []byte(")"))
+ if lIdx < 0 || rIdx < 0 || lIdx >= rIdx || rIdx+2 >= len(data) {
+ return fmt.Errorf("failed to extract comm for pid %d from '%v'", pid, string(data))
+ }
+ self.Name = string(data[lIdx+1 : rIdx])
+
+ // Extract the rest of the fields that we are interested in.
+ fields := bytes.Fields(data[rIdx+2:])
+ if len(fields) <= 36 {
+ return fmt.Errorf("expected more stat fields for pid %d from '%v'", pid, string(data))
+ }
+
+ interests := bytes.Join([][]byte{
+ fields[0], // state
+ fields[1], // ppid
+ fields[2], // pgrp
+ fields[4], // tty_nr
+ fields[15], // priority
+ fields[16], // nice
+ fields[36], // processor (last processor executed on)
+ }, []byte(" "))
+
+ var state string
+ _, err = fmt.Fscan(bytes.NewBuffer(interests),
+ &state,
+ &self.Ppid,
+ &self.Pgid,
+ &self.Tty,
+ &self.Priority,
+ &self.Nice,
+ &self.Processor,
+ )
+ if err != nil {
+ return fmt.Errorf("failed to parse stat fields for pid %d from '%v': %v", pid, string(data), err)
+ }
+ self.State = RunState(state[0])
+
+ // Read /proc/[pid]/status to get the uid, then lookup uid to get username.
+ status, err := getProcStatus(pid)
+ if err != nil {
+ return fmt.Errorf("failed to read process status for pid %d: %v", pid, err)
+ }
+ uids, err := getUIDs(status)
+ if err != nil {
+ return fmt.Errorf("failed to read process status for pid %d: %v", pid, err)
+ }
+ user, err := user.LookupId(uids[0])
+ if err == nil {
+ self.Username = user.Username
+ } else {
+ self.Username = uids[0]
+ }
+
+ return nil
+}
+
+func (self *ProcMem) Get(pid int) error {
+ contents, err := readProcFile(pid, "statm")
+ if err != nil {
+ return err
+ }
+
+ fields := strings.Fields(string(contents))
+
+ size, _ := strtoull(fields[0])
+ self.Size = size << 12
+
+ rss, _ := strtoull(fields[1])
+ self.Resident = rss << 12
+
+ share, _ := strtoull(fields[2])
+ self.Share = share << 12
+
+ contents, err = readProcFile(pid, "stat")
+ if err != nil {
+ return err
+ }
+
+ fields = strings.Fields(string(contents))
+
+ self.MinorFaults, _ = strtoull(fields[10])
+ self.MajorFaults, _ = strtoull(fields[12])
+ self.PageFaults = self.MinorFaults + self.MajorFaults
+
+ return nil
+}
+
+func (self *ProcTime) Get(pid int) error {
+ contents, err := readProcFile(pid, "stat")
+ if err != nil {
+ return err
+ }
+
+ fields := strings.Fields(string(contents))
+
+ user, _ := strtoull(fields[13])
+ sys, _ := strtoull(fields[14])
+ // convert to millis
+ self.User = user * (1000 / system.ticks)
+ self.Sys = sys * (1000 / system.ticks)
+ self.Total = self.User + self.Sys
+
+ // convert to millis
+ self.StartTime, _ = strtoull(fields[21])
+ self.StartTime /= system.ticks
+ self.StartTime += system.btime
+ self.StartTime *= 1000
+
+ return nil
+}
+
+func (self *ProcArgs) Get(pid int) error {
+ contents, err := readProcFile(pid, "cmdline")
+ if err != nil {
+ return err
+ }
+
+ bbuf := bytes.NewBuffer(contents)
+
+ var args []string
+
+ for {
+ arg, err := bbuf.ReadBytes(0)
+ if err == io.EOF {
+ break
+ }
+ args = append(args, string(chop(arg)))
+ }
+
+ self.List = args
+
+ return nil
+}
+
+func (self *ProcEnv) Get(pid int) error {
+ contents, err := readProcFile(pid, "environ")
+ if err != nil {
+ return err
+ }
+
+ if self.Vars == nil {
+ self.Vars = map[string]string{}
+ }
+
+ pairs := bytes.Split(contents, []byte{0})
+ for _, kv := range pairs {
+ parts := bytes.SplitN(kv, []byte{'='}, 2)
+ if len(parts) != 2 {
+ continue
+ }
+
+ key := string(bytes.TrimSpace(parts[0]))
+ if key == "" {
+ continue
+ }
+
+ self.Vars[key] = string(bytes.TrimSpace(parts[1]))
+ }
+
+ return nil
+}
+
+func (self *ProcExe) Get(pid int) error {
+ fields := map[string]*string{
+ "exe": &self.Name,
+ "cwd": &self.Cwd,
+ "root": &self.Root,
+ }
+
+ for name, field := range fields {
+ val, err := os.Readlink(procFileName(pid, name))
+
+ if err != nil {
+ return err
+ }
+
+ *field = val
+ }
+
+ return nil
+}
+
+func parseMeminfo() (map[string]uint64, error) {
+ table := map[string]uint64{}
+
+ err := readFile(Procd+"/meminfo", func(line string) bool {
+ fields := strings.Split(line, ":")
+
+ if len(fields) != 2 {
+ return true // skip on errors
+ }
+
+ num := strings.TrimLeft(fields[1], " ")
+ val, err := strtoull(strings.Fields(num)[0])
+ if err != nil {
+ return true // skip on errors
+ }
+ table[fields[0]] = val * 1024 //in bytes
+
+ return true
+ })
+ return table, err
+}
+
+func readFile(file string, handler func(string) bool) error {
+ contents, err := ioutil.ReadFile(file)
+ if err != nil {
+ return err
+ }
+
+ reader := bufio.NewReader(bytes.NewBuffer(contents))
+
+ for {
+ line, _, err := reader.ReadLine()
+ if err == io.EOF {
+ break
+ }
+ if !handler(string(line)) {
+ break
+ }
+ }
+
+ return nil
+}
+
+func strtoull(val string) (uint64, error) {
+ return strconv.ParseUint(val, 10, 64)
+}
+
+func procFileName(pid int, name string) string {
+ return Procd + "/" + strconv.Itoa(pid) + "/" + name
+}
+
+func readProcFile(pid int, name string) ([]byte, error) {
+ path := procFileName(pid, name)
+ contents, err := ioutil.ReadFile(path)
+
+ if err != nil {
+ if perr, ok := err.(*os.PathError); ok {
+ if perr.Err == syscall.ENOENT {
+ return nil, syscall.ESRCH
+ }
+ }
+ }
+
+ return contents, err
+}
+
+// getProcStatus reads /proc/[pid]/status which contains process status
+// information in human readable form.
+func getProcStatus(pid int) (map[string]string, error) {
+ status := make(map[string]string, 42)
+ path := filepath.Join(Procd, strconv.Itoa(pid), "status")
+ err := readFile(path, func(line string) bool {
+ fields := strings.SplitN(line, ":", 2)
+ if len(fields) == 2 {
+ status[fields[0]] = strings.TrimSpace(fields[1])
+ }
+
+ return true
+ })
+ return status, err
+}
+
+// getUIDs reads the "Uid" value from status and splits it into four values --
+// real, effective, saved set, and file system UIDs.
+func getUIDs(status map[string]string) ([]string, error) {
+ uidLine, ok := status["Uid"]
+ if !ok {
+ return nil, fmt.Errorf("Uid not found in proc status")
+ }
+
+ uidStrs := strings.Fields(uidLine)
+ if len(uidStrs) != 4 {
+ return nil, fmt.Errorf("Uid line ('%s') did not contain four values", uidLine)
+ }
+
+ return uidStrs, nil
+}
diff --git a/vendor/github.com/elastic/gosigar/sigar_openbsd.go b/vendor/github.com/elastic/gosigar/sigar_openbsd.go
new file mode 100644
index 000000000..4f1383a6b
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sigar_openbsd.go
@@ -0,0 +1,418 @@
+// Copyright (c) 2016 Jasper Lievisse Adriaanse <j@jasper.la>.
+
+// +build openbsd
+
+package gosigar
+
+/*
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/mount.h>
+#include <sys/sched.h>
+#include <sys/swap.h>
+#include <stdlib.h>
+#include <unistd.h>
+*/
+import "C"
+
+//import "github.com/davecgh/go-spew/spew"
+
+import (
+ "runtime"
+ "syscall"
+ "time"
+ "unsafe"
+)
+
+type Uvmexp struct {
+ pagesize uint32
+ pagemask uint32
+ pageshift uint32
+ npages uint32
+ free uint32
+ active uint32
+ inactive uint32
+ paging uint32
+ wired uint32
+ zeropages uint32
+ reserve_pagedaemon uint32
+ reserve_kernel uint32
+ anonpages uint32
+ vnodepages uint32
+ vtextpages uint32
+ freemin uint32
+ freetarg uint32
+ inactarg uint32
+ wiredmax uint32
+ anonmin uint32
+ vtextmin uint32
+ vnodemin uint32
+ anonminpct uint32
+ vtextmi uint32
+ npct uint32
+ vnodeminpct uint32
+ nswapdev uint32
+ swpages uint32
+ swpginuse uint32
+ swpgonly uint32
+ nswget uint32
+ nanon uint32
+ nanonneeded uint32
+ nfreeanon uint32
+ faults uint32
+ traps uint32
+ intrs uint32
+ swtch uint32
+ softs uint32
+ syscalls uint32
+ pageins uint32
+ obsolete_swapins uint32
+ obsolete_swapouts uint32
+ pgswapin uint32
+ pgswapout uint32
+ forks uint32
+ forks_ppwait uint32
+ forks_sharevm uint32
+ pga_zerohit uint32
+ pga_zeromiss uint32
+ zeroaborts uint32
+ fltnoram uint32
+ fltnoanon uint32
+ fltpgwait uint32
+ fltpgrele uint32
+ fltrelck uint32
+ fltrelckok uint32
+ fltanget uint32
+ fltanretry uint32
+ fltamcopy uint32
+ fltnamap uint32
+ fltnomap uint32
+ fltlget uint32
+ fltget uint32
+ flt_anon uint32
+ flt_acow uint32
+ flt_obj uint32
+ flt_prcopy uint32
+ flt_przero uint32
+ pdwoke uint32
+ pdrevs uint32
+ pdswout uint32
+ pdfreed uint32
+ pdscans uint32
+ pdanscan uint32
+ pdobscan uint32
+ pdreact uint32
+ pdbusy uint32
+ pdpageouts uint32
+ pdpending uint32
+ pddeact uint32
+ pdreanon uint32
+ pdrevnode uint32
+ pdrevtext uint32
+ fpswtch uint32
+ kmapent uint32
+}
+
+type Bcachestats struct {
+ numbufs uint64
+ numbufpages uint64
+ numdirtypages uint64
+ numcleanpages uint64
+ pendingwrites uint64
+ pendingreads uint64
+ numwrites uint64
+ numreads uint64
+ cachehits uint64
+ busymapped uint64
+ dmapages uint64
+ highpages uint64
+ delwribufs uint64
+ kvaslots uint64
+ kvaslots_avail uint64
+}
+
+type Swapent struct {
+ se_dev C.dev_t
+ se_flags int32
+ se_nblks int32
+ se_inuse int32
+ se_priority int32
+ sw_path []byte
+}
+
+func (self *FileSystemList) Get() error {
+ num, err := syscall.Getfsstat(nil, C.MNT_NOWAIT)
+ if err != nil {
+ return err
+ }
+
+ buf := make([]syscall.Statfs_t, num)
+
+ _, err = syscall.Getfsstat(buf, C.MNT_NOWAIT)
+ if err != nil {
+ return err
+ }
+
+ fslist := make([]FileSystem, 0, num)
+
+ for i := 0; i < num; i++ {
+ fs := FileSystem{}
+
+ fs.DirName = bytePtrToString(&buf[i].F_mntonname[0])
+ fs.DevName = bytePtrToString(&buf[i].F_mntfromname[0])
+ fs.SysTypeName = bytePtrToString(&buf[i].F_fstypename[0])
+
+ fslist = append(fslist, fs)
+ }
+
+ self.List = fslist
+
+ return err
+}
+
+func (self *FileSystemUsage) Get(path string) error {
+ stat := syscall.Statfs_t{}
+ err := syscall.Statfs(path, &stat)
+ if err != nil {
+ return err
+ }
+
+ self.Total = uint64(stat.F_blocks) * uint64(stat.F_bsize)
+ self.Free = uint64(stat.F_bfree) * uint64(stat.F_bsize)
+ self.Avail = uint64(stat.F_bavail) * uint64(stat.F_bsize)
+ self.Used = self.Total - self.Free
+ self.Files = stat.F_files
+ self.FreeFiles = stat.F_ffree
+
+ return nil
+}
+
+func (self *FDUsage) Get() error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (self *LoadAverage) Get() error {
+ avg := []C.double{0, 0, 0}
+
+ C.getloadavg(&avg[0], C.int(len(avg)))
+
+ self.One = float64(avg[0])
+ self.Five = float64(avg[1])
+ self.Fifteen = float64(avg[2])
+
+ return nil
+}
+
+func (self *Uptime) Get() error {
+ tv := syscall.Timeval{}
+ mib := [2]int32{C.CTL_KERN, C.KERN_BOOTTIME}
+
+ n := uintptr(0)
+ // First we determine how much memory we'll need to pass later on (via `n`)
+ _, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
+
+ if errno != 0 || n == 0 {
+ return nil
+ }
+
+ // Now perform the actual sysctl(3) call, storing the result in tv
+ _, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, uintptr(unsafe.Pointer(&tv)), uintptr(unsafe.Pointer(&n)), 0, 0)
+
+ if errno != 0 || n == 0 {
+ return nil
+ }
+
+ self.Length = time.Since(time.Unix(int64(tv.Sec), int64(tv.Usec)*1000)).Seconds()
+
+ return nil
+}
+
+func (self *Mem) Get() error {
+ n := uintptr(0)
+
+ var uvmexp Uvmexp
+ mib := [2]int32{C.CTL_VM, C.VM_UVMEXP}
+ n = uintptr(0)
+ // First we determine how much memory we'll need to pass later on (via `n`)
+ _, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
+ if errno != 0 || n == 0 {
+ return nil
+ }
+
+ _, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, uintptr(unsafe.Pointer(&uvmexp)), uintptr(unsafe.Pointer(&n)), 0, 0)
+ if errno != 0 || n == 0 {
+ return nil
+ }
+
+ var bcachestats Bcachestats
+ mib3 := [3]int32{C.CTL_VFS, C.VFS_GENERIC, C.VFS_BCACHESTAT}
+ n = uintptr(0)
+ _, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib3[0])), 3, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
+ if errno != 0 || n == 0 {
+ return nil
+ }
+ _, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib3[0])), 3, uintptr(unsafe.Pointer(&bcachestats)), uintptr(unsafe.Pointer(&n)), 0, 0)
+ if errno != 0 || n == 0 {
+ return nil
+ }
+
+ self.Total = uint64(uvmexp.npages) << uvmexp.pageshift
+ self.Used = uint64(uvmexp.npages-uvmexp.free) << uvmexp.pageshift
+ self.Free = uint64(uvmexp.free) << uvmexp.pageshift
+
+ self.ActualFree = self.Free + (uint64(bcachestats.numbufpages) << uvmexp.pageshift)
+ self.ActualUsed = self.Used - (uint64(bcachestats.numbufpages) << uvmexp.pageshift)
+
+ return nil
+}
+
+func (self *Swap) Get() error {
+ nswap := C.swapctl(C.SWAP_NSWAP, unsafe.Pointer(uintptr(0)), 0)
+
+ // If there are no swap devices, nothing to do here.
+ if nswap == 0 {
+ return nil
+ }
+
+ swdev := make([]Swapent, nswap)
+
+ rnswap := C.swapctl(C.SWAP_STATS, unsafe.Pointer(&swdev[0]), nswap)
+ if rnswap == 0 {
+ return nil
+ }
+
+ for i := 0; i < int(nswap); i++ {
+ if swdev[i].se_flags&C.SWF_ENABLE == 2 {
+ self.Used = self.Used + uint64(swdev[i].se_inuse/(1024/C.DEV_BSIZE))
+ self.Total = self.Total + uint64(swdev[i].se_nblks/(1024/C.DEV_BSIZE))
+ }
+ }
+
+ self.Free = self.Total - self.Used
+
+ return nil
+}
+
+func (self *Cpu) Get() error {
+ load := [C.CPUSTATES]C.long{C.CP_USER, C.CP_NICE, C.CP_SYS, C.CP_INTR, C.CP_IDLE}
+
+ mib := [2]int32{C.CTL_KERN, C.KERN_CPTIME}
+ n := uintptr(0)
+ // First we determine how much memory we'll need to pass later on (via `n`)
+ _, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
+ if errno != 0 || n == 0 {
+ return nil
+ }
+
+ _, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, uintptr(unsafe.Pointer(&load)), uintptr(unsafe.Pointer(&n)), 0, 0)
+ if errno != 0 || n == 0 {
+ return nil
+ }
+
+ self.User = uint64(load[0])
+ self.Nice = uint64(load[1])
+ self.Sys = uint64(load[2])
+ self.Irq = uint64(load[3])
+ self.Idle = uint64(load[4])
+
+ return nil
+}
+
+func (self *CpuList) Get() error {
+ mib := [2]int32{C.CTL_HW, C.HW_NCPU}
+ var ncpu int
+
+ n := uintptr(0)
+ // First we determine how much memory we'll need to pass later on (via `n`)
+ _, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
+
+ if errno != 0 || n == 0 {
+ return nil
+ }
+
+ // Now perform the actual sysctl(3) call, storing the result in ncpu
+ _, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 2, uintptr(unsafe.Pointer(&ncpu)), uintptr(unsafe.Pointer(&n)), 0, 0)
+
+ if errno != 0 || n == 0 {
+ return nil
+ }
+
+ load := [C.CPUSTATES]C.long{C.CP_USER, C.CP_NICE, C.CP_SYS, C.CP_INTR, C.CP_IDLE}
+
+ self.List = make([]Cpu, ncpu)
+ for curcpu := range self.List {
+ sysctlCptime(ncpu, curcpu, &load)
+ fillCpu(&self.List[curcpu], load)
+ }
+
+ return nil
+}
+
+func (self *ProcList) Get() error {
+ return nil
+}
+
+func (self *ProcArgs) Get(pid int) error {
+ return nil
+}
+
+func (self *ProcEnv) Get(pid int) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (self *ProcState) Get(pid int) error {
+ return nil
+}
+
+func (self *ProcMem) Get(pid int) error {
+ return nil
+}
+
+func (self *ProcTime) Get(pid int) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (self *ProcExe) Get(pid int) error {
+ return nil
+}
+
+func (self *ProcFDUsage) Get(pid int) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func fillCpu(cpu *Cpu, load [C.CPUSTATES]C.long) {
+ cpu.User = uint64(load[0])
+ cpu.Nice = uint64(load[1])
+ cpu.Sys = uint64(load[2])
+ cpu.Irq = uint64(load[3])
+ cpu.Idle = uint64(load[4])
+}
+
+func sysctlCptime(ncpu int, curcpu int, load *[C.CPUSTATES]C.long) error {
+ var mib []int32
+
+ // Use the correct mib based on the number of CPUs and fill out the
+ // current CPU number in case of SMP. (0 indexed cf. self.List)
+ if ncpu == 0 {
+ mib = []int32{C.CTL_KERN, C.KERN_CPTIME}
+ } else {
+ mib = []int32{C.CTL_KERN, C.KERN_CPTIME2, int32(curcpu)}
+ }
+
+ len := len(mib)
+
+ n := uintptr(0)
+ // First we determine how much memory we'll need to pass later on (via `n`)
+ _, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), uintptr(len), 0, uintptr(unsafe.Pointer(&n)), 0, 0)
+ if errno != 0 || n == 0 {
+ return nil
+ }
+
+ _, _, errno = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), uintptr(len), uintptr(unsafe.Pointer(load)), uintptr(unsafe.Pointer(&n)), 0, 0)
+ if errno != 0 || n == 0 {
+ return nil
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/elastic/gosigar/sigar_stub.go b/vendor/github.com/elastic/gosigar/sigar_stub.go
new file mode 100644
index 000000000..0b858f1c0
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sigar_stub.go
@@ -0,0 +1,71 @@
+// +build !darwin,!freebsd,!linux,!openbsd,!windows
+
+package gosigar
+
+import (
+ "runtime"
+)
+
+func (c *Cpu) Get() error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (l *LoadAverage) Get() error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (m *Mem) Get() error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (s *Swap) Get() error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (f *FDUsage) Get() error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (p *ProcTime) Get(int) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (self *FileSystemUsage) Get(path string) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (self *CpuList) Get() error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (p *ProcState) Get(int) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (p *ProcExe) Get(int) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (p *ProcMem) Get(int) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (p *ProcFDUsage) Get(int) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (p *ProcEnv) Get(int) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (p *ProcList) Get() error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (p *ProcArgs) Get(int) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (self *Rusage) Get(int) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
diff --git a/vendor/github.com/elastic/gosigar/sigar_unix.go b/vendor/github.com/elastic/gosigar/sigar_unix.go
new file mode 100644
index 000000000..3f3a9f7ff
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sigar_unix.go
@@ -0,0 +1,69 @@
+// Copyright (c) 2012 VMware, Inc.
+
+// +build darwin freebsd linux
+
+package gosigar
+
+import (
+ "syscall"
+ "time"
+
+ "golang.org/x/sys/unix"
+)
+
+func (self *FileSystemUsage) Get(path string) error {
+ stat := syscall.Statfs_t{}
+ err := syscall.Statfs(path, &stat)
+ if err != nil {
+ return err
+ }
+
+ self.Total = uint64(stat.Blocks) * uint64(stat.Bsize)
+ self.Free = uint64(stat.Bfree) * uint64(stat.Bsize)
+ self.Avail = uint64(stat.Bavail) * uint64(stat.Bsize)
+ self.Used = self.Total - self.Free
+ self.Files = stat.Files
+ self.FreeFiles = uint64(stat.Ffree)
+
+ return nil
+}
+
+func (r *Rusage) Get(who int) error {
+ ru, err := getResourceUsage(who)
+ if err != nil {
+ return err
+ }
+
+ uTime := convertRtimeToDur(ru.Utime)
+ sTime := convertRtimeToDur(ru.Stime)
+
+ r.Utime = uTime
+ r.Stime = sTime
+ r.Maxrss = int64(ru.Maxrss)
+ r.Ixrss = int64(ru.Ixrss)
+ r.Idrss = int64(ru.Idrss)
+ r.Isrss = int64(ru.Isrss)
+ r.Minflt = int64(ru.Minflt)
+ r.Majflt = int64(ru.Majflt)
+ r.Nswap = int64(ru.Nswap)
+ r.Inblock = int64(ru.Inblock)
+ r.Oublock = int64(ru.Oublock)
+ r.Msgsnd = int64(ru.Msgsnd)
+ r.Msgrcv = int64(ru.Msgrcv)
+ r.Nsignals = int64(ru.Nsignals)
+ r.Nvcsw = int64(ru.Nvcsw)
+ r.Nivcsw = int64(ru.Nivcsw)
+
+ return nil
+}
+
+func getResourceUsage(who int) (unix.Rusage, error) {
+ r := unix.Rusage{}
+ err := unix.Getrusage(who, &r)
+
+ return r, err
+}
+
+func convertRtimeToDur(t unix.Timeval) time.Duration {
+ return time.Duration(t.Nano())
+}
diff --git a/vendor/github.com/elastic/gosigar/sigar_util.go b/vendor/github.com/elastic/gosigar/sigar_util.go
new file mode 100644
index 000000000..bf93b02b2
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sigar_util.go
@@ -0,0 +1,22 @@
+// Copyright (c) 2012 VMware, Inc.
+
+package gosigar
+
+import (
+ "unsafe"
+)
+
+func bytePtrToString(ptr *int8) string {
+ bytes := (*[10000]byte)(unsafe.Pointer(ptr))
+
+ n := 0
+ for bytes[n] != 0 {
+ n++
+ }
+
+ return string(bytes[0:n])
+}
+
+func chop(buf []byte) []byte {
+ return buf[0 : len(buf)-1]
+}
diff --git a/vendor/github.com/elastic/gosigar/sigar_windows.go b/vendor/github.com/elastic/gosigar/sigar_windows.go
new file mode 100644
index 000000000..0cdf928d1
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sigar_windows.go
@@ -0,0 +1,437 @@
+// Copyright (c) 2012 VMware, Inc.
+
+package gosigar
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "sync"
+ "syscall"
+ "time"
+
+ "github.com/StackExchange/wmi"
+ "github.com/elastic/gosigar/sys/windows"
+ "github.com/pkg/errors"
+)
+
+// Win32_Process represents a process on the Windows operating system. If
+// additional fields are added here (that match the Windows struct) they will
+// automatically be populated when calling getWin32Process.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa394372(v=vs.85).aspx
+type Win32_Process struct {
+ CommandLine string
+}
+
+// Win32_OperatingSystem WMI class represents a Windows-based operating system
+// installed on a computer.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa394239(v=vs.85).aspx
+type Win32_OperatingSystem struct {
+ LastBootUpTime time.Time
+}
+
+var (
+ // version is Windows version of the host OS.
+ version = windows.GetWindowsVersion()
+
+ // processQueryLimitedInfoAccess is set to PROCESS_QUERY_INFORMATION for Windows
+ // 2003 and XP where PROCESS_QUERY_LIMITED_INFORMATION is unknown. For all newer
+ // OS versions it is set to PROCESS_QUERY_LIMITED_INFORMATION.
+ processQueryLimitedInfoAccess = windows.PROCESS_QUERY_LIMITED_INFORMATION
+
+ // bootTime is the time when the OS was last booted. This value may be nil
+ // on operating systems that do not support the WMI query used to obtain it.
+ bootTime *time.Time
+ bootTimeLock sync.Mutex
+)
+
+func init() {
+ if !version.IsWindowsVistaOrGreater() {
+ // PROCESS_QUERY_LIMITED_INFORMATION cannot be used on 2003 or XP.
+ processQueryLimitedInfoAccess = syscall.PROCESS_QUERY_INFORMATION
+ }
+}
+
+func (self *LoadAverage) Get() error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (self *FDUsage) Get() error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (self *ProcEnv) Get(pid int) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (self *ProcExe) Get(pid int) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (self *ProcFDUsage) Get(pid int) error {
+ return ErrNotImplemented{runtime.GOOS}
+}
+
+func (self *Uptime) Get() error {
+ // Minimum supported OS is Windows Vista.
+ if !version.IsWindowsVistaOrGreater() {
+ return ErrNotImplemented{runtime.GOOS}
+ }
+
+ bootTimeLock.Lock()
+ defer bootTimeLock.Unlock()
+ if bootTime == nil {
+ os, err := getWin32OperatingSystem()
+ if err != nil {
+ return errors.Wrap(err, "failed to get boot time using WMI")
+ }
+ bootTime = &os.LastBootUpTime
+ }
+
+ self.Length = time.Since(*bootTime).Seconds()
+ return nil
+}
+
+func (self *Mem) Get() error {
+ memoryStatusEx, err := windows.GlobalMemoryStatusEx()
+ if err != nil {
+ return errors.Wrap(err, "GlobalMemoryStatusEx failed")
+ }
+
+ self.Total = memoryStatusEx.TotalPhys
+ self.Free = memoryStatusEx.AvailPhys
+ self.Used = self.Total - self.Free
+ self.ActualFree = self.Free
+ self.ActualUsed = self.Used
+ return nil
+}
+
+func (self *Swap) Get() error {
+ memoryStatusEx, err := windows.GlobalMemoryStatusEx()
+ if err != nil {
+ return errors.Wrap(err, "GlobalMemoryStatusEx failed")
+ }
+
+ self.Total = memoryStatusEx.TotalPageFile
+ self.Free = memoryStatusEx.AvailPageFile
+ self.Used = self.Total - self.Free
+ return nil
+}
+
+func (self *Cpu) Get() error {
+ idle, kernel, user, err := windows.GetSystemTimes()
+ if err != nil {
+ return errors.Wrap(err, "GetSystemTimes failed")
+ }
+
+ // CPU times are reported in milliseconds by gosigar.
+ self.Idle = uint64(idle / time.Millisecond)
+ self.Sys = uint64(kernel / time.Millisecond)
+ self.User = uint64(user / time.Millisecond)
+ return nil
+}
+
+func (self *CpuList) Get() error {
+ cpus, err := windows.NtQuerySystemProcessorPerformanceInformation()
+ if err != nil {
+ return errors.Wrap(err, "NtQuerySystemProcessorPerformanceInformation failed")
+ }
+
+ self.List = make([]Cpu, 0, len(cpus))
+ for _, cpu := range cpus {
+ self.List = append(self.List, Cpu{
+ Idle: uint64(cpu.IdleTime / time.Millisecond),
+ Sys: uint64(cpu.KernelTime / time.Millisecond),
+ User: uint64(cpu.UserTime / time.Millisecond),
+ })
+ }
+ return nil
+}
+
+func (self *FileSystemList) Get() error {
+ drives, err := windows.GetLogicalDriveStrings()
+ if err != nil {
+ return errors.Wrap(err, "GetLogicalDriveStrings failed")
+ }
+
+ for _, drive := range drives {
+ dt, err := windows.GetDriveType(drive)
+ if err != nil {
+ return errors.Wrapf(err, "GetDriveType failed")
+ }
+
+ self.List = append(self.List, FileSystem{
+ DirName: drive,
+ DevName: drive,
+ TypeName: dt.String(),
+ })
+ }
+ return nil
+}
+
+// Get retrieves a list of all process identifiers (PIDs) in the system.
+func (self *ProcList) Get() error {
+ pids, err := windows.EnumProcesses()
+ if err != nil {
+ return errors.Wrap(err, "EnumProcesses failed")
+ }
+
+ // Convert uint32 PIDs to int.
+ self.List = make([]int, 0, len(pids))
+ for _, pid := range pids {
+ self.List = append(self.List, int(pid))
+ }
+ return nil
+}
+
+func (self *ProcState) Get(pid int) error {
+ var errs []error
+
+ var err error
+ self.Name, err = getProcName(pid)
+ if err != nil {
+ errs = append(errs, errors.Wrap(err, "getProcName failed"))
+ }
+
+ self.State, err = getProcStatus(pid)
+ if err != nil {
+ errs = append(errs, errors.Wrap(err, "getProcStatus failed"))
+ }
+
+ self.Ppid, err = getParentPid(pid)
+ if err != nil {
+ errs = append(errs, errors.Wrap(err, "getParentPid failed"))
+ }
+
+ self.Username, err = getProcCredName(pid)
+ if err != nil {
+ errs = append(errs, errors.Wrap(err, "getProcCredName failed"))
+ }
+
+ if len(errs) > 0 {
+ errStrs := make([]string, 0, len(errs))
+ for _, e := range errs {
+ errStrs = append(errStrs, e.Error())
+ }
+ return errors.New(strings.Join(errStrs, "; "))
+ }
+ return nil
+}
+
+// getProcName returns the process name associated with the PID.
+func getProcName(pid int) (string, error) {
+ handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
+ if err != nil {
+ return "", errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
+ }
+ defer syscall.CloseHandle(handle)
+
+ filename, err := windows.GetProcessImageFileName(handle)
+ if err != nil {
+ return "", errors.Wrapf(err, "GetProcessImageFileName failed for pid=%v", pid)
+ }
+
+ return filepath.Base(filename), nil
+}
+
+// getProcStatus returns the status of a process.
+func getProcStatus(pid int) (RunState, error) {
+ handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
+ if err != nil {
+ return RunStateUnknown, errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
+ }
+ defer syscall.CloseHandle(handle)
+
+ var exitCode uint32
+ err = syscall.GetExitCodeProcess(handle, &exitCode)
+ if err != nil {
+ return RunStateUnknown, errors.Wrapf(err, "GetExitCodeProcess failed for pid=%v")
+ }
+
+ if exitCode == 259 { //still active
+ return RunStateRun, nil
+ }
+ return RunStateSleep, nil
+}
+
+// getParentPid returns the parent process ID of a process.
+func getParentPid(pid int) (int, error) {
+ handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
+ if err != nil {
+ return RunStateUnknown, errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
+ }
+ defer syscall.CloseHandle(handle)
+
+ procInfo, err := windows.NtQueryProcessBasicInformation(handle)
+ if err != nil {
+ return 0, errors.Wrapf(err, "NtQueryProcessBasicInformation failed for pid=%v", pid)
+ }
+
+ return int(procInfo.InheritedFromUniqueProcessID), nil
+}
+
+func getProcCredName(pid int) (string, error) {
+ handle, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, uint32(pid))
+ if err != nil {
+ return "", errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
+ }
+ defer syscall.CloseHandle(handle)
+
+ // Find process token via win32.
+ var token syscall.Token
+ err = syscall.OpenProcessToken(handle, syscall.TOKEN_QUERY, &token)
+ if err != nil {
+ return "", errors.Wrapf(err, "OpenProcessToken failed for pid=%v", pid)
+ }
+
+ // Find the token user.
+ tokenUser, err := token.GetTokenUser()
+ if err != nil {
+ return "", errors.Wrapf(err, "GetTokenInformation failed for pid=%v", pid)
+ }
+
+ // Close token to prevent handle leaks.
+ err = token.Close()
+ if err != nil {
+ return "", errors.Wrapf(err, "failed while closing process token handle for pid=%v", pid)
+ }
+
+ // Look up domain account by SID.
+ account, domain, _, err := tokenUser.User.Sid.LookupAccount("")
+ if err != nil {
+ sid, sidErr := tokenUser.User.Sid.String()
+ if sidErr != nil {
+ return "", errors.Wrapf(err, "failed while looking up account name for pid=%v", pid)
+ }
+ return "", errors.Wrapf(err, "failed while looking up account name for SID=%v of pid=%v", sid, pid)
+ }
+
+ return fmt.Sprintf(`%s\%s`, domain, account), nil
+}
+
+func (self *ProcMem) Get(pid int) error {
+ handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess|windows.PROCESS_VM_READ, false, uint32(pid))
+ if err != nil {
+ return errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
+ }
+ defer syscall.CloseHandle(handle)
+
+ counters, err := windows.GetProcessMemoryInfo(handle)
+ if err != nil {
+ return errors.Wrapf(err, "GetProcessMemoryInfo failed for pid=%v", pid)
+ }
+
+ self.Resident = uint64(counters.WorkingSetSize)
+ self.Size = uint64(counters.PrivateUsage)
+ return nil
+}
+
+func (self *ProcTime) Get(pid int) error {
+ cpu, err := getProcTimes(pid)
+ if err != nil {
+ return err
+ }
+
+ // Windows epoch times are expressed as time elapsed since midnight on
+ // January 1, 1601 at Greenwich, England. This converts the Filetime to
+ // unix epoch in milliseconds.
+ self.StartTime = uint64(cpu.CreationTime.Nanoseconds() / 1e6)
+
+ // Convert to millis.
+ self.User = uint64(windows.FiletimeToDuration(&cpu.UserTime).Nanoseconds() / 1e6)
+ self.Sys = uint64(windows.FiletimeToDuration(&cpu.KernelTime).Nanoseconds() / 1e6)
+ self.Total = self.User + self.Sys
+
+ return nil
+}
+
+func getProcTimes(pid int) (*syscall.Rusage, error) {
+ handle, err := syscall.OpenProcess(processQueryLimitedInfoAccess, false, uint32(pid))
+ if err != nil {
+ return nil, errors.Wrapf(err, "OpenProcess failed for pid=%v", pid)
+ }
+ defer syscall.CloseHandle(handle)
+
+ var cpu syscall.Rusage
+ if err := syscall.GetProcessTimes(handle, &cpu.CreationTime, &cpu.ExitTime, &cpu.KernelTime, &cpu.UserTime); err != nil {
+ return nil, errors.Wrapf(err, "GetProcessTimes failed for pid=%v", pid)
+ }
+
+ return &cpu, nil
+}
+
+func (self *ProcArgs) Get(pid int) error {
+ // The minimum supported client for Win32_Process is Windows Vista.
+ if !version.IsWindowsVistaOrGreater() {
+ return ErrNotImplemented{runtime.GOOS}
+ }
+
+ process, err := getWin32Process(int32(pid))
+ if err != nil {
+ return errors.Wrapf(err, "ProcArgs failed for pid=%v", pid)
+ }
+
+ self.List = []string{process.CommandLine}
+ return nil
+}
+
+func (self *FileSystemUsage) Get(path string) error {
+ freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes, err := windows.GetDiskFreeSpaceEx(path)
+ if err != nil {
+ return errors.Wrap(err, "GetDiskFreeSpaceEx failed")
+ }
+
+ self.Total = totalNumberOfBytes
+ self.Free = totalNumberOfFreeBytes
+ self.Used = self.Total - self.Free
+ self.Avail = freeBytesAvailable
+ return nil
+}
+
+// getWin32Process gets information about the process with the given process ID.
+// It uses a WMI query to get the information from the local system.
+func getWin32Process(pid int32) (Win32_Process, error) {
+ var dst []Win32_Process
+ query := fmt.Sprintf("WHERE ProcessId = %d", pid)
+ q := wmi.CreateQuery(&dst, query)
+ err := wmi.Query(q, &dst)
+ if err != nil {
+ return Win32_Process{}, fmt.Errorf("could not get Win32_Process %s: %v", query, err)
+ }
+ if len(dst) < 1 {
+ return Win32_Process{}, fmt.Errorf("could not get Win32_Process %s: Process not found", query)
+ }
+ return dst[0], nil
+}
+
+func getWin32OperatingSystem() (Win32_OperatingSystem, error) {
+ var dst []Win32_OperatingSystem
+ q := wmi.CreateQuery(&dst, "")
+ err := wmi.Query(q, &dst)
+ if err != nil {
+ return Win32_OperatingSystem{}, errors.Wrap(err, "wmi query for Win32_OperatingSystem failed")
+ }
+ if len(dst) != 1 {
+ return Win32_OperatingSystem{}, errors.New("wmi query for Win32_OperatingSystem failed")
+ }
+ return dst[0], nil
+}
+
+func (self *Rusage) Get(who int) error {
+ if who != 0 {
+ return ErrNotImplemented{runtime.GOOS}
+ }
+
+ pid := os.Getpid()
+ cpu, err := getProcTimes(pid)
+ if err != nil {
+ return err
+ }
+
+ self.Utime = windows.FiletimeToDuration(&cpu.UserTime)
+ self.Stime = windows.FiletimeToDuration(&cpu.KernelTime)
+
+ return nil
+}
diff --git a/vendor/github.com/elastic/gosigar/sys/windows/doc.go b/vendor/github.com/elastic/gosigar/sys/windows/doc.go
new file mode 100644
index 000000000..dda57aa83
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sys/windows/doc.go
@@ -0,0 +1,2 @@
+// Package windows contains various Windows system call.
+package windows
diff --git a/vendor/github.com/elastic/gosigar/sys/windows/ntquery.go b/vendor/github.com/elastic/gosigar/sys/windows/ntquery.go
new file mode 100644
index 000000000..85de365e1
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sys/windows/ntquery.go
@@ -0,0 +1,132 @@
+// +build windows
+
+package windows
+
+import (
+ "bytes"
+ "encoding/binary"
+ "io"
+ "runtime"
+ "syscall"
+ "time"
+ "unsafe"
+
+ "github.com/pkg/errors"
+)
+
+// On both 32-bit and 64-bit systems NtQuerySystemInformation expects the
+// size of SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION to be 48.
+const sizeofSystemProcessorPerformanceInformation = 48
+
+// ProcessBasicInformation is an equivalent representation of
+// PROCESS_BASIC_INFORMATION in the Windows API.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684280(v=vs.85).aspx
+type ProcessBasicInformation struct {
+ ExitStatus uint
+ PebBaseAddress uintptr
+ AffinityMask uint
+ BasePriority uint
+ UniqueProcessID uint
+ InheritedFromUniqueProcessID uint
+}
+
+// NtQueryProcessBasicInformation queries basic information about the process
+// associated with the given handle (provided by OpenProcess). It uses the
+// NtQueryInformationProcess function to collect the data.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684280(v=vs.85).aspx
+func NtQueryProcessBasicInformation(handle syscall.Handle) (ProcessBasicInformation, error) {
+ var processBasicInfo ProcessBasicInformation
+ processBasicInfoPtr := (*byte)(unsafe.Pointer(&processBasicInfo))
+ size := uint32(unsafe.Sizeof(processBasicInfo))
+ ntStatus, _ := _NtQueryInformationProcess(handle, 0, processBasicInfoPtr, size, nil)
+ if ntStatus != 0 {
+ return ProcessBasicInformation{}, errors.Errorf("NtQueryInformationProcess failed, NTSTATUS=0x%X", ntStatus)
+ }
+
+ return processBasicInfo, nil
+}
+
+// SystemProcessorPerformanceInformation contains CPU performance information
+// for a single CPU.
+type SystemProcessorPerformanceInformation struct {
+ IdleTime time.Duration // Amount of time spent idle.
+ KernelTime time.Duration // Kernel time does NOT include time spent in idle.
+ UserTime time.Duration // Amount of time spent executing in user mode.
+}
+
+// _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION is an equivalent representation of
+// SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION in the Windows API. This struct is
+// used internally with NtQuerySystemInformation call and is not exported. The
+// exported equivalent is SystemProcessorPerformanceInformation.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724509(v=vs.85).aspx
+type _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION struct {
+ IdleTime int64
+ KernelTime int64
+ UserTime int64
+ Reserved1 [2]int64
+ Reserved2 uint32
+}
+
+// NtQuerySystemProcessorPerformanceInformation queries CPU performance
+// information for each CPU. It uses the NtQuerySystemInformation function to
+// collect the SystemProcessorPerformanceInformation.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724509(v=vs.85).aspx
+func NtQuerySystemProcessorPerformanceInformation() ([]SystemProcessorPerformanceInformation, error) {
+ // NTSTATUS code for success.
+ // https://msdn.microsoft.com/en-us/library/cc704588.aspx
+ const STATUS_SUCCESS = 0
+
+ // From the _SYSTEM_INFORMATION_CLASS enum.
+ // http://processhacker.sourceforge.net/doc/ntexapi_8h.html#ad5d815b48e8f4da1ef2eb7a2f18a54e0
+ const systemProcessorPerformanceInformation = 8
+
+ // Create a buffer large enough to hold an entry for each processor.
+ b := make([]byte, runtime.NumCPU()*sizeofSystemProcessorPerformanceInformation)
+
+ // Query the performance information. Note that this function uses 0 to
+ // indicate success. Most other Windows functions use non-zero for success.
+ var returnLength uint32
+ ntStatus, _ := _NtQuerySystemInformation(systemProcessorPerformanceInformation, &b[0], uint32(len(b)), &returnLength)
+ if ntStatus != STATUS_SUCCESS {
+ return nil, errors.Errorf("NtQuerySystemInformation failed, NTSTATUS=0x%X, bufLength=%v, returnLength=%v", ntStatus, len(b), returnLength)
+ }
+
+ return readSystemProcessorPerformanceInformationBuffer(b)
+}
+
+// readSystemProcessorPerformanceInformationBuffer reads from a buffer
+// containing SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION data. The buffer should
+// contain one entry for each CPU.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724509(v=vs.85).aspx
+func readSystemProcessorPerformanceInformationBuffer(b []byte) ([]SystemProcessorPerformanceInformation, error) {
+ n := len(b) / sizeofSystemProcessorPerformanceInformation
+ r := bytes.NewReader(b)
+
+ rtn := make([]SystemProcessorPerformanceInformation, 0, n)
+ for i := 0; i < n; i++ {
+ _, err := r.Seek(int64(i*sizeofSystemProcessorPerformanceInformation), io.SeekStart)
+ if err != nil {
+ return nil, errors.Wrapf(err, "failed to seek to cpuN=%v in buffer", i)
+ }
+
+ times := make([]uint64, 3)
+ for j := range times {
+ err := binary.Read(r, binary.LittleEndian, &times[j])
+ if err != nil {
+ return nil, errors.Wrapf(err, "failed reading cpu times for cpuN=%v", i)
+ }
+ }
+
+ idleTime := time.Duration(times[0] * 100)
+ kernelTime := time.Duration(times[1] * 100)
+ userTime := time.Duration(times[2] * 100)
+
+ rtn = append(rtn, SystemProcessorPerformanceInformation{
+ IdleTime: idleTime,
+ KernelTime: kernelTime - idleTime, // Subtract out idle time from kernel time.
+ UserTime: userTime,
+ })
+ }
+
+ return rtn, nil
+}
diff --git a/vendor/github.com/elastic/gosigar/sys/windows/privileges.go b/vendor/github.com/elastic/gosigar/sys/windows/privileges.go
new file mode 100644
index 000000000..28c78fd22
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sys/windows/privileges.go
@@ -0,0 +1,272 @@
+// +build windows
+
+package windows
+
+import (
+ "bytes"
+ "encoding/binary"
+ "encoding/json"
+ "fmt"
+ "runtime"
+ "strings"
+ "sync"
+ "syscall"
+
+ "github.com/pkg/errors"
+ "golang.org/x/sys/windows"
+)
+
+// Cache of privilege names to LUIDs.
+var (
+ privNames = make(map[string]int64)
+ privNameMutex sync.Mutex
+)
+
+const (
+ // SeDebugPrivilege is the name of the privilege used to debug programs.
+ SeDebugPrivilege = "SeDebugPrivilege"
+)
+
+// Errors returned by AdjustTokenPrivileges.
+const (
+ ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300
+)
+
+// Attribute bits for privileges.
+const (
+ _SE_PRIVILEGE_ENABLED_BY_DEFAULT uint32 = 0x00000001
+ _SE_PRIVILEGE_ENABLED uint32 = 0x00000002
+ _SE_PRIVILEGE_REMOVED uint32 = 0x00000004
+ _SE_PRIVILEGE_USED_FOR_ACCESS uint32 = 0x80000000
+)
+
+// Privilege contains information about a single privilege associated with a
+// Token.
+type Privilege struct {
+ LUID int64 `json:"-"` // Locally unique identifier (guaranteed only until the system is restarted).
+ Name string `json:"-"`
+ EnabledByDefault bool `json:"enabled_by_default,omitempty"`
+ Enabled bool `json:"enabled"`
+ Removed bool `json:"removed,omitempty"`
+ Used bool `json:"used,omitempty"`
+}
+
+func (p Privilege) String() string {
+ var buf bytes.Buffer
+ buf.WriteString(p.Name)
+ buf.WriteString("=(")
+
+ opts := make([]string, 0, 4)
+ if p.EnabledByDefault {
+ opts = append(opts, "Default")
+ }
+ if p.Enabled {
+ opts = append(opts, "Enabled")
+ }
+ if !p.EnabledByDefault && !p.Enabled {
+ opts = append(opts, "Disabled")
+ }
+ if p.Removed {
+ opts = append(opts, "Removed")
+ }
+ if p.Used {
+ opts = append(opts, "Used")
+ }
+
+ buf.WriteString(strings.Join(opts, ", "))
+ buf.WriteString(")")
+
+ // Example: SeDebugPrivilege=(Default, Enabled)
+ return buf.String()
+}
+
+// User represent the information about a Windows account.
+type User struct {
+ SID string
+ Account string
+ Domain string
+ Type uint32
+}
+
+func (u User) String() string {
+ return fmt.Sprintf(`User:%v\%v, SID:%v, Type:%v`, u.Domain, u.Account, u.SID, u.Type)
+}
+
+// DebugInfo contains general debug info about the current process.
+type DebugInfo struct {
+ OSVersion Version // OS version info.
+ Arch string // Architecture of the machine.
+ NumCPU int // Number of CPUs.
+ User User // User that this process is running as.
+ ProcessPrivs map[string]Privilege // Privileges held by the process.
+}
+
+func (d DebugInfo) String() string {
+ bytes, _ := json.Marshal(d)
+ return string(bytes)
+}
+
+// LookupPrivilegeName looks up a privilege name given a LUID value.
+func LookupPrivilegeName(systemName string, luid int64) (string, error) {
+ buf := make([]uint16, 256)
+ bufSize := uint32(len(buf))
+ err := _LookupPrivilegeName(systemName, &luid, &buf[0], &bufSize)
+ if err != nil {
+ return "", errors.Wrapf(err, "LookupPrivilegeName failed for luid=%v", luid)
+ }
+
+ return syscall.UTF16ToString(buf), nil
+}
+
+// mapPrivileges maps privilege names to LUID values.
+func mapPrivileges(names []string) ([]int64, error) {
+ var privileges []int64
+ privNameMutex.Lock()
+ defer privNameMutex.Unlock()
+ for _, name := range names {
+ p, ok := privNames[name]
+ if !ok {
+ err := _LookupPrivilegeValue("", name, &p)
+ if err != nil {
+ return nil, errors.Wrapf(err, "LookupPrivilegeValue failed on '%v'", name)
+ }
+ privNames[name] = p
+ }
+ privileges = append(privileges, p)
+ }
+ return privileges, nil
+}
+
+// EnableTokenPrivileges enables the specified privileges in the given
+// Token. The token must have TOKEN_ADJUST_PRIVILEGES access. If the token
+// does not already contain the privilege it cannot be enabled.
+func EnableTokenPrivileges(token syscall.Token, privileges ...string) error {
+ privValues, err := mapPrivileges(privileges)
+ if err != nil {
+ return err
+ }
+
+ var b bytes.Buffer
+ binary.Write(&b, binary.LittleEndian, uint32(len(privValues)))
+ for _, p := range privValues {
+ binary.Write(&b, binary.LittleEndian, p)
+ binary.Write(&b, binary.LittleEndian, uint32(_SE_PRIVILEGE_ENABLED))
+ }
+
+ success, err := _AdjustTokenPrivileges(token, false, &b.Bytes()[0], uint32(b.Len()), nil, nil)
+ if !success {
+ return err
+ }
+ if err == ERROR_NOT_ALL_ASSIGNED {
+ return errors.Wrap(err, "error not all privileges were assigned")
+ }
+
+ return nil
+}
+
+// GetTokenPrivileges returns a list of privileges associated with a token.
+// The provided token must have at a minimum TOKEN_QUERY access. This is a
+// wrapper around the GetTokenInformation function.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa446671(v=vs.85).aspx
+func GetTokenPrivileges(token syscall.Token) (map[string]Privilege, error) {
+ // Determine the required buffer size.
+ var size uint32
+ syscall.GetTokenInformation(token, syscall.TokenPrivileges, nil, 0, &size)
+
+ // This buffer will receive a TOKEN_PRIVILEGE structure.
+ b := bytes.NewBuffer(make([]byte, size))
+ err := syscall.GetTokenInformation(token, syscall.TokenPrivileges, &b.Bytes()[0], uint32(b.Len()), &size)
+ if err != nil {
+ return nil, errors.Wrap(err, "GetTokenInformation failed")
+ }
+
+ var privilegeCount uint32
+ err = binary.Read(b, binary.LittleEndian, &privilegeCount)
+ if err != nil {
+ return nil, errors.Wrap(err, "failed to read PrivilegeCount")
+ }
+
+ rtn := make(map[string]Privilege, privilegeCount)
+ for i := 0; i < int(privilegeCount); i++ {
+ var luid int64
+ err = binary.Read(b, binary.LittleEndian, &luid)
+ if err != nil {
+ return nil, errors.Wrap(err, "failed to read LUID value")
+ }
+
+ var attributes uint32
+ err = binary.Read(b, binary.LittleEndian, &attributes)
+ if err != nil {
+ return nil, errors.Wrap(err, "failed to read attributes")
+ }
+
+ name, err := LookupPrivilegeName("", luid)
+ if err != nil {
+ return nil, errors.Wrapf(err, "LookupPrivilegeName failed for LUID=%v", luid)
+ }
+
+ rtn[name] = Privilege{
+ LUID: luid,
+ Name: name,
+ EnabledByDefault: (attributes & _SE_PRIVILEGE_ENABLED_BY_DEFAULT) > 0,
+ Enabled: (attributes & _SE_PRIVILEGE_ENABLED) > 0,
+ Removed: (attributes & _SE_PRIVILEGE_REMOVED) > 0,
+ Used: (attributes & _SE_PRIVILEGE_USED_FOR_ACCESS) > 0,
+ }
+ }
+
+ return rtn, nil
+}
+
+// GetTokenUser returns the User associated with the given Token.
+func GetTokenUser(token syscall.Token) (User, error) {
+ tokenUser, err := token.GetTokenUser()
+ if err != nil {
+ return User{}, errors.Wrap(err, "GetTokenUser failed")
+ }
+
+ var user User
+ user.SID, err = tokenUser.User.Sid.String()
+ if err != nil {
+ return user, errors.Wrap(err, "ConvertSidToStringSid failed")
+ }
+
+ user.Account, user.Domain, user.Type, err = tokenUser.User.Sid.LookupAccount("")
+ if err != nil {
+ return user, errors.Wrap(err, "LookupAccountSid failed")
+ }
+
+ return user, nil
+}
+
+// GetDebugInfo returns general debug info about the current process.
+func GetDebugInfo() (*DebugInfo, error) {
+ h, err := windows.GetCurrentProcess()
+ if err != nil {
+ return nil, err
+ }
+
+ var token syscall.Token
+ err = syscall.OpenProcessToken(syscall.Handle(h), syscall.TOKEN_QUERY, &token)
+ if err != nil {
+ return nil, err
+ }
+
+ privs, err := GetTokenPrivileges(token)
+ if err != nil {
+ return nil, err
+ }
+
+ user, err := GetTokenUser(token)
+ if err != nil {
+ return nil, err
+ }
+
+ return &DebugInfo{
+ User: user,
+ ProcessPrivs: privs,
+ OSVersion: GetWindowsVersion(),
+ Arch: runtime.GOARCH,
+ NumCPU: runtime.NumCPU(),
+ }, nil
+}
diff --git a/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go b/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go
new file mode 100644
index 000000000..88df0febf
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go
@@ -0,0 +1,385 @@
+package windows
+
+import (
+ "fmt"
+ "syscall"
+ "time"
+ "unsafe"
+
+ "github.com/pkg/errors"
+)
+
+var (
+ sizeofUint32 = 4
+ sizeofProcessEntry32 = uint32(unsafe.Sizeof(ProcessEntry32{}))
+ sizeofProcessMemoryCountersEx = uint32(unsafe.Sizeof(ProcessMemoryCountersEx{}))
+ sizeofMemoryStatusEx = uint32(unsafe.Sizeof(MemoryStatusEx{}))
+)
+
+// Process-specific access rights. Others are declared in the syscall package.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx
+const (
+ PROCESS_QUERY_LIMITED_INFORMATION uint32 = 0x1000
+ PROCESS_VM_READ uint32 = 0x0010
+)
+
+// MAX_PATH is the maximum length for a path in Windows.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
+const MAX_PATH = 260
+
+// DriveType represents a type of drive (removable, fixed, CD-ROM, RAM disk, or
+// network drive).
+type DriveType uint32
+
+// Drive types as returned by GetDriveType.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364939(v=vs.85).aspx
+const (
+ DRIVE_UNKNOWN DriveType = iota
+ DRIVE_NO_ROOT_DIR
+ DRIVE_REMOVABLE
+ DRIVE_FIXED
+ DRIVE_REMOTE
+ DRIVE_CDROM
+ DRIVE_RAMDISK
+)
+
+func (dt DriveType) String() string {
+ names := map[DriveType]string{
+ DRIVE_UNKNOWN: "unknown",
+ DRIVE_NO_ROOT_DIR: "invalid",
+ DRIVE_REMOVABLE: "removable",
+ DRIVE_FIXED: "fixed",
+ DRIVE_REMOTE: "remote",
+ DRIVE_CDROM: "cdrom",
+ DRIVE_RAMDISK: "ramdisk",
+ }
+
+ name, found := names[dt]
+ if !found {
+ return "unknown DriveType value"
+ }
+ return name
+}
+
+// Flags that can be used with CreateToolhelp32Snapshot.
+const (
+ TH32CS_INHERIT uint32 = 0x80000000 // Indicates that the snapshot handle is to be inheritable.
+ TH32CS_SNAPHEAPLIST uint32 = 0x00000001 // Includes all heaps of the process specified in th32ProcessID in the snapshot.
+ TH32CS_SNAPMODULE uint32 = 0x00000008 // Includes all modules of the process specified in th32ProcessID in the snapshot.
+ TH32CS_SNAPMODULE32 uint32 = 0x00000010 // Includes all 32-bit modules of the process specified in th32ProcessID in the snapshot when called from a 64-bit process.
+ TH32CS_SNAPPROCESS uint32 = 0x00000002 // Includes all processes in the system in the snapshot.
+ TH32CS_SNAPTHREAD uint32 = 0x00000004 // Includes all threads in the system in the snapshot.
+)
+
+// ProcessEntry32 is an equivalent representation of PROCESSENTRY32 in the
+// Windows API. It contains a process's information. Do not modify or reorder.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684839(v=vs.85).aspx
+type ProcessEntry32 struct {
+ size uint32
+ CntUsage uint32
+ ProcessID uint32
+ DefaultHeapID uintptr
+ ModuleID uint32
+ CntThreads uint32
+ ParentProcessID uint32
+ PriorityClassBase int32
+ Flags uint32
+ exeFile [MAX_PATH]uint16
+}
+
+// ExeFile returns the name of the executable file for the process. It does
+// not contain the full path.
+func (p ProcessEntry32) ExeFile() string {
+ return syscall.UTF16ToString(p.exeFile[:])
+}
+
+func (p ProcessEntry32) String() string {
+ return fmt.Sprintf("{CntUsage:%v ProcessID:%v DefaultHeapID:%v ModuleID:%v "+
+ "CntThreads:%v ParentProcessID:%v PriorityClassBase:%v Flags:%v ExeFile:%v",
+ p.CntUsage, p.ProcessID, p.DefaultHeapID, p.ModuleID, p.CntThreads,
+ p.ParentProcessID, p.PriorityClassBase, p.Flags, p.ExeFile())
+}
+
+// MemoryStatusEx is an equivalent representation of MEMORYSTATUSEX in the
+// Windows API. It contains information about the current state of both physical
+// and virtual memory, including extended memory.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366770
+type MemoryStatusEx struct {
+ length uint32
+ MemoryLoad uint32
+ TotalPhys uint64
+ AvailPhys uint64
+ TotalPageFile uint64
+ AvailPageFile uint64
+ TotalVirtual uint64
+ AvailVirtual uint64
+ AvailExtendedVirtual uint64
+}
+
+// ProcessMemoryCountersEx is an equivalent representation of
+// PROCESS_MEMORY_COUNTERS_EX in the Windows API.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684874(v=vs.85).aspx
+type ProcessMemoryCountersEx struct {
+ cb uint32
+ PageFaultCount uint32
+ PeakWorkingSetSize uintptr
+ WorkingSetSize uintptr
+ QuotaPeakPagedPoolUsage uintptr
+ QuotaPagedPoolUsage uintptr
+ QuotaPeakNonPagedPoolUsage uintptr
+ QuotaNonPagedPoolUsage uintptr
+ PagefileUsage uintptr
+ PeakPagefileUsage uintptr
+ PrivateUsage uintptr
+}
+
+// GetLogicalDriveStrings returns a list of drives in the system.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364975(v=vs.85).aspx
+func GetLogicalDriveStrings() ([]string, error) {
+ // Determine the size of the buffer required to receive all drives.
+ bufferLength, err := _GetLogicalDriveStringsW(0, nil)
+ if err != nil {
+ return nil, errors.Wrap(err, "GetLogicalDriveStringsW failed to get buffer length")
+ }
+ if bufferLength < 0 {
+ return nil, errors.New("GetLogicalDriveStringsW returned an invalid buffer length")
+ }
+
+ buffer := make([]uint16, bufferLength)
+ _, err = _GetLogicalDriveStringsW(uint32(len(buffer)), &buffer[0])
+ if err != nil {
+ return nil, errors.Wrap(err, "GetLogicalDriveStringsW failed")
+ }
+
+ // Split the uint16 slice at null-terminators.
+ var startIdx int
+ var drivesUTF16 [][]uint16
+ for i, value := range buffer {
+ if value == 0 {
+ drivesUTF16 = append(drivesUTF16, buffer[startIdx:i])
+ startIdx = i + 1
+ }
+ }
+
+ // Convert the utf16 slices to strings.
+ drives := make([]string, 0, len(drivesUTF16))
+ for _, driveUTF16 := range drivesUTF16 {
+ if len(driveUTF16) > 0 {
+ drives = append(drives, syscall.UTF16ToString(driveUTF16))
+ }
+ }
+
+ return drives, nil
+}
+
+// GlobalMemoryStatusEx retrieves information about the system's current usage
+// of both physical and virtual memory.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366589(v=vs.85).aspx
+func GlobalMemoryStatusEx() (MemoryStatusEx, error) {
+ memoryStatusEx := MemoryStatusEx{length: sizeofMemoryStatusEx}
+ err := _GlobalMemoryStatusEx(&memoryStatusEx)
+ if err != nil {
+ return MemoryStatusEx{}, errors.Wrap(err, "GlobalMemoryStatusEx failed")
+ }
+
+ return memoryStatusEx, nil
+}
+
+// GetProcessMemoryInfo retrieves information about the memory usage of the
+// specified process.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms683219(v=vs.85).aspx
+func GetProcessMemoryInfo(handle syscall.Handle) (ProcessMemoryCountersEx, error) {
+ processMemoryCountersEx := ProcessMemoryCountersEx{cb: sizeofProcessMemoryCountersEx}
+ err := _GetProcessMemoryInfo(handle, &processMemoryCountersEx, processMemoryCountersEx.cb)
+ if err != nil {
+ return ProcessMemoryCountersEx{}, errors.Wrap(err, "GetProcessMemoryInfo failed")
+ }
+
+ return processMemoryCountersEx, nil
+}
+
+// GetProcessImageFileName Retrieves the name of the executable file for the
+// specified process.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms683217(v=vs.85).aspx
+func GetProcessImageFileName(handle syscall.Handle) (string, error) {
+ buffer := make([]uint16, MAX_PATH)
+ _, err := _GetProcessImageFileName(handle, &buffer[0], uint32(len(buffer)))
+ if err != nil {
+ return "", errors.Wrap(err, "GetProcessImageFileName failed")
+ }
+
+ return syscall.UTF16ToString(buffer), nil
+}
+
+// GetSystemTimes retrieves system timing information. On a multiprocessor
+// system, the values returned are the sum of the designated times across all
+// processors. The returned kernel time does not include the system idle time.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724400(v=vs.85).aspx
+func GetSystemTimes() (idle, kernel, user time.Duration, err error) {
+ var idleTime, kernelTime, userTime syscall.Filetime
+ err = _GetSystemTimes(&idleTime, &kernelTime, &userTime)
+ if err != nil {
+ return 0, 0, 0, errors.Wrap(err, "GetSystemTimes failed")
+ }
+
+ idle = FiletimeToDuration(&idleTime)
+ kernel = FiletimeToDuration(&kernelTime) // Kernel time includes idle time so we subtract it out.
+ user = FiletimeToDuration(&userTime)
+
+ return idle, kernel - idle, user, nil
+}
+
+// FiletimeToDuration converts a Filetime to a time.Duration. Do not use this
+// method to convert a Filetime to an actual clock time, for that use
+// Filetime.Nanosecond().
+func FiletimeToDuration(ft *syscall.Filetime) time.Duration {
+ n := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime) // in 100-nanosecond intervals
+ return time.Duration(n * 100)
+}
+
+// GetDriveType Determines whether a disk drive is a removable, fixed, CD-ROM,
+// RAM disk, or network drive. A trailing backslash is required on the
+// rootPathName.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364939
+func GetDriveType(rootPathName string) (DriveType, error) {
+ rootPathNamePtr, err := syscall.UTF16PtrFromString(rootPathName)
+ if err != nil {
+ return DRIVE_UNKNOWN, errors.Wrapf(err, "UTF16PtrFromString failed for rootPathName=%v", rootPathName)
+ }
+
+ dt, err := _GetDriveType(rootPathNamePtr)
+ if err != nil {
+ return DRIVE_UNKNOWN, errors.Wrapf(err, "GetDriveType failed for rootPathName=%v", rootPathName)
+ }
+
+ return dt, nil
+}
+
+// EnumProcesses retrieves the process identifier for each process object in the
+// system. This function can return a max of 65536 PIDs. If there are more
+// processes than that then this will not return them all.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms682629(v=vs.85).aspx
+func EnumProcesses() ([]uint32, error) {
+ enumProcesses := func(size int) ([]uint32, error) {
+ var (
+ pids = make([]uint32, size)
+ sizeBytes = len(pids) * sizeofUint32
+ bytesWritten uint32
+ )
+
+ err := _EnumProcesses(&pids[0], uint32(sizeBytes), &bytesWritten)
+
+ pidsWritten := int(bytesWritten) / sizeofUint32
+ if int(bytesWritten)%sizeofUint32 != 0 || pidsWritten > len(pids) {
+ return nil, errors.Errorf("EnumProcesses returned an invalid bytesWritten value of %v", bytesWritten)
+ }
+ pids = pids[:pidsWritten]
+
+ return pids, err
+ }
+
+ // Retry the EnumProcesses call with larger arrays if needed.
+ size := 2048
+ var pids []uint32
+ for tries := 0; tries < 5; tries++ {
+ var err error
+ pids, err = enumProcesses(size)
+ if err != nil {
+ return nil, errors.Wrap(err, "EnumProcesses failed")
+ }
+
+ if len(pids) < size {
+ break
+ }
+
+ // Increase the size the pids array and retry the enumProcesses call
+ // because the array wasn't large enough to hold all of the processes.
+ size *= 2
+ }
+
+ return pids, nil
+}
+
+// GetDiskFreeSpaceEx retrieves information about the amount of space that is
+// available on a disk volume, which is the total amount of space, the total
+// amount of free space, and the total amount of free space available to the
+// user that is associated with the calling thread.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364937(v=vs.85).aspx
+func GetDiskFreeSpaceEx(directoryName string) (freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes uint64, err error) {
+ directoryNamePtr, err := syscall.UTF16PtrFromString(directoryName)
+ if err != nil {
+ return 0, 0, 0, errors.Wrapf(err, "UTF16PtrFromString failed for directoryName=%v", directoryName)
+ }
+
+ err = _GetDiskFreeSpaceEx(directoryNamePtr, &freeBytesAvailable, &totalNumberOfBytes, &totalNumberOfFreeBytes)
+ if err != nil {
+ return 0, 0, 0, err
+ }
+
+ return freeBytesAvailable, totalNumberOfBytes, totalNumberOfFreeBytes, nil
+}
+
+// CreateToolhelp32Snapshot takes a snapshot of the specified processes, as well
+// as the heaps, modules, and threads used by these processes.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms682489(v=vs.85).aspx
+func CreateToolhelp32Snapshot(flags, pid uint32) (syscall.Handle, error) {
+ h, err := _CreateToolhelp32Snapshot(flags, pid)
+ if err != nil {
+ return syscall.InvalidHandle, err
+ }
+ if h == syscall.InvalidHandle {
+ return syscall.InvalidHandle, syscall.GetLastError()
+ }
+
+ return h, nil
+}
+
+// Process32First retrieves information about the first process encountered in a
+// system snapshot.
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684834
+func Process32First(handle syscall.Handle) (ProcessEntry32, error) {
+ processEntry32 := ProcessEntry32{size: sizeofProcessEntry32}
+ err := _Process32First(handle, &processEntry32)
+ if err != nil {
+ return ProcessEntry32{}, errors.Wrap(err, "Process32First failed")
+ }
+
+ return processEntry32, nil
+}
+
+// Process32Next retrieves information about the next process recorded in a
+// system snapshot. When there are no more processes to iterate then
+// syscall.ERROR_NO_MORE_FILES is returned (use errors.Cause() to unwrap).
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684836
+func Process32Next(handle syscall.Handle) (ProcessEntry32, error) {
+ processEntry32 := ProcessEntry32{size: sizeofProcessEntry32}
+ err := _Process32Next(handle, &processEntry32)
+ if err != nil {
+ return ProcessEntry32{}, errors.Wrap(err, "Process32Next failed")
+ }
+
+ return processEntry32, nil
+}
+
+// Use "GOOS=windows go generate -v -x ." to generate the source.
+
+// Add -trace to enable debug prints around syscalls.
+//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go
+
+// Windows API calls
+//sys _GlobalMemoryStatusEx(buffer *MemoryStatusEx) (err error) = kernel32.GlobalMemoryStatusEx
+//sys _GetLogicalDriveStringsW(bufferLength uint32, buffer *uint16) (length uint32, err error) = kernel32.GetLogicalDriveStringsW
+//sys _GetProcessMemoryInfo(handle syscall.Handle, psmemCounters *ProcessMemoryCountersEx, cb uint32) (err error) = psapi.GetProcessMemoryInfo
+//sys _GetProcessImageFileName(handle syscall.Handle, outImageFileName *uint16, size uint32) (length uint32, err error) = psapi.GetProcessImageFileNameW
+//sys _GetSystemTimes(idleTime *syscall.Filetime, kernelTime *syscall.Filetime, userTime *syscall.Filetime) (err error) = kernel32.GetSystemTimes
+//sys _GetDriveType(rootPathName *uint16) (dt DriveType, err error) = kernel32.GetDriveTypeW
+//sys _EnumProcesses(processIds *uint32, sizeBytes uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses
+//sys _GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailable *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) = kernel32.GetDiskFreeSpaceExW
+//sys _Process32First(handle syscall.Handle, processEntry32 *ProcessEntry32) (err error) = kernel32.Process32FirstW
+//sys _Process32Next(handle syscall.Handle, processEntry32 *ProcessEntry32) (err error) = kernel32.Process32NextW
+//sys _CreateToolhelp32Snapshot(flags uint32, processID uint32) (handle syscall.Handle, err error) = kernel32.CreateToolhelp32Snapshot
+//sys _NtQuerySystemInformation(systemInformationClass uint32, systemInformation *byte, systemInformationLength uint32, returnLength *uint32) (ntstatus uint32, err error) = ntdll.NtQuerySystemInformation
+//sys _NtQueryInformationProcess(processHandle syscall.Handle, processInformationClass uint32, processInformation *byte, processInformationLength uint32, returnLength *uint32) (ntstatus uint32, err error) = ntdll.NtQueryInformationProcess
+//sys _LookupPrivilegeName(systemName string, luid *int64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW
+//sys _LookupPrivilegeValue(systemName string, name string, luid *int64) (err error) = advapi32.LookupPrivilegeValueW
+//sys _AdjustTokenPrivileges(token syscall.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) [true] = advapi32.AdjustTokenPrivileges
diff --git a/vendor/github.com/elastic/gosigar/sys/windows/version.go b/vendor/github.com/elastic/gosigar/sys/windows/version.go
new file mode 100644
index 000000000..d0bca89c1
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sys/windows/version.go
@@ -0,0 +1,43 @@
+// +build windows
+
+package windows
+
+import (
+ "fmt"
+ "syscall"
+)
+
+// Version identifies a Windows version by major, minor, and build number.
+type Version struct {
+ Major int
+ Minor int
+ Build int
+}
+
+// GetWindowsVersion returns the Windows version information. Applications not
+// manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version
+// value (6.2).
+//
+// For a table of version numbers see:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx
+func GetWindowsVersion() Version {
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx
+ ver, err := syscall.GetVersion()
+ if err != nil {
+ // GetVersion should never return an error.
+ panic(fmt.Errorf("GetVersion failed: %v", err))
+ }
+
+ return Version{
+ Major: int(ver & 0xFF),
+ Minor: int(ver >> 8 & 0xFF),
+ Build: int(ver >> 16),
+ }
+}
+
+// IsWindowsVistaOrGreater returns true if the Windows version is Vista or
+// greater.
+func (v Version) IsWindowsVistaOrGreater() bool {
+ // Vista is 6.0.
+ return v.Major >= 6 && v.Minor >= 0
+}
diff --git a/vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go b/vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go
new file mode 100644
index 000000000..53fae4e3b
--- /dev/null
+++ b/vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go
@@ -0,0 +1,260 @@
+// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
+
+package windows
+
+import "unsafe"
+import "syscall"
+
+var _ unsafe.Pointer
+
+var (
+ modkernel32 = syscall.NewLazyDLL("kernel32.dll")
+ modpsapi = syscall.NewLazyDLL("psapi.dll")
+ modntdll = syscall.NewLazyDLL("ntdll.dll")
+ modadvapi32 = syscall.NewLazyDLL("advapi32.dll")
+
+ procGlobalMemoryStatusEx = modkernel32.NewProc("GlobalMemoryStatusEx")
+ procGetLogicalDriveStringsW = modkernel32.NewProc("GetLogicalDriveStringsW")
+ procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
+ procGetProcessImageFileNameW = modpsapi.NewProc("GetProcessImageFileNameW")
+ procGetSystemTimes = modkernel32.NewProc("GetSystemTimes")
+ procGetDriveTypeW = modkernel32.NewProc("GetDriveTypeW")
+ procEnumProcesses = modpsapi.NewProc("EnumProcesses")
+ procGetDiskFreeSpaceExW = modkernel32.NewProc("GetDiskFreeSpaceExW")
+ procProcess32FirstW = modkernel32.NewProc("Process32FirstW")
+ procProcess32NextW = modkernel32.NewProc("Process32NextW")
+ procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot")
+ procNtQuerySystemInformation = modntdll.NewProc("NtQuerySystemInformation")
+ procNtQueryInformationProcess = modntdll.NewProc("NtQueryInformationProcess")
+ procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW")
+ procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
+ procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
+)
+
+func _GlobalMemoryStatusEx(buffer *MemoryStatusEx) (err error) {
+ r1, _, e1 := syscall.Syscall(procGlobalMemoryStatusEx.Addr(), 1, uintptr(unsafe.Pointer(buffer)), 0, 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func _GetLogicalDriveStringsW(bufferLength uint32, buffer *uint16) (length uint32, err error) {
+ r0, _, e1 := syscall.Syscall(procGetLogicalDriveStringsW.Addr(), 2, uintptr(bufferLength), uintptr(unsafe.Pointer(buffer)), 0)
+ length = uint32(r0)
+ if length == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func _GetProcessMemoryInfo(handle syscall.Handle, psmemCounters *ProcessMemoryCountersEx, cb uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procGetProcessMemoryInfo.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(psmemCounters)), uintptr(cb))
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func _GetProcessImageFileName(handle syscall.Handle, outImageFileName *uint16, size uint32) (length uint32, err error) {
+ r0, _, e1 := syscall.Syscall(procGetProcessImageFileNameW.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(outImageFileName)), uintptr(size))
+ length = uint32(r0)
+ if length == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func _GetSystemTimes(idleTime *syscall.Filetime, kernelTime *syscall.Filetime, userTime *syscall.Filetime) (err error) {
+ r1, _, e1 := syscall.Syscall(procGetSystemTimes.Addr(), 3, uintptr(unsafe.Pointer(idleTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime)))
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func _GetDriveType(rootPathName *uint16) (dt DriveType, err error) {
+ r0, _, e1 := syscall.Syscall(procGetDriveTypeW.Addr(), 1, uintptr(unsafe.Pointer(rootPathName)), 0, 0)
+ dt = DriveType(r0)
+ if dt == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func _EnumProcesses(processIds *uint32, sizeBytes uint32, bytesReturned *uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procEnumProcesses.Addr(), 3, uintptr(unsafe.Pointer(processIds)), uintptr(sizeBytes), uintptr(unsafe.Pointer(bytesReturned)))
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func _GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailable *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) {
+ r1, _, e1 := syscall.Syscall6(procGetDiskFreeSpaceExW.Addr(), 4, uintptr(unsafe.Pointer(directoryName)), uintptr(unsafe.Pointer(freeBytesAvailable)), uintptr(unsafe.Pointer(totalNumberOfBytes)), uintptr(unsafe.Pointer(totalNumberOfFreeBytes)), 0, 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func _Process32First(handle syscall.Handle, processEntry32 *ProcessEntry32) (err error) {
+ r1, _, e1 := syscall.Syscall(procProcess32FirstW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(processEntry32)), 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func _Process32Next(handle syscall.Handle, processEntry32 *ProcessEntry32) (err error) {
+ r1, _, e1 := syscall.Syscall(procProcess32NextW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(processEntry32)), 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func _CreateToolhelp32Snapshot(flags uint32, processID uint32) (handle syscall.Handle, err error) {
+ r0, _, e1 := syscall.Syscall(procCreateToolhelp32Snapshot.Addr(), 2, uintptr(flags), uintptr(processID), 0)
+ handle = syscall.Handle(r0)
+ if handle == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func _NtQuerySystemInformation(systemInformationClass uint32, systemInformation *byte, systemInformationLength uint32, returnLength *uint32) (ntstatus uint32, err error) {
+ r0, _, e1 := syscall.Syscall6(procNtQuerySystemInformation.Addr(), 4, uintptr(systemInformationClass), uintptr(unsafe.Pointer(systemInformation)), uintptr(systemInformationLength), uintptr(unsafe.Pointer(returnLength)), 0, 0)
+ ntstatus = uint32(r0)
+ if ntstatus == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func _NtQueryInformationProcess(processHandle syscall.Handle, processInformationClass uint32, processInformation *byte, processInformationLength uint32, returnLength *uint32) (ntstatus uint32, err error) {
+ r0, _, e1 := syscall.Syscall6(procNtQueryInformationProcess.Addr(), 5, uintptr(processHandle), uintptr(processInformationClass), uintptr(unsafe.Pointer(processInformation)), uintptr(processInformationLength), uintptr(unsafe.Pointer(returnLength)), 0)
+ ntstatus = uint32(r0)
+ if ntstatus == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func _LookupPrivilegeName(systemName string, luid *int64, buffer *uint16, size *uint32) (err error) {
+ var _p0 *uint16
+ _p0, err = syscall.UTF16PtrFromString(systemName)
+ if err != nil {
+ return
+ }
+ return __LookupPrivilegeName(_p0, luid, buffer, size)
+}
+
+func __LookupPrivilegeName(systemName *uint16, luid *int64, buffer *uint16, size *uint32) (err error) {
+ r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func _LookupPrivilegeValue(systemName string, name string, luid *int64) (err error) {
+ var _p0 *uint16
+ _p0, err = syscall.UTF16PtrFromString(systemName)
+ if err != nil {
+ return
+ }
+ var _p1 *uint16
+ _p1, err = syscall.UTF16PtrFromString(name)
+ if err != nil {
+ return
+ }
+ return __LookupPrivilegeValue(_p0, _p1, luid)
+}
+
+func __LookupPrivilegeValue(systemName *uint16, name *uint16, luid *int64) (err error) {
+ r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid)))
+ if r1 == 0 {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func _AdjustTokenPrivileges(token syscall.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) {
+ var _p0 uint32
+ if releaseAll {
+ _p0 = 1
+ } else {
+ _p0 = 0
+ }
+ r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize)))
+ success = r0 != 0
+ if true {
+ if e1 != 0 {
+ err = error(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
diff --git a/vendor/github.com/go-ole/go-ole/ChangeLog.md b/vendor/github.com/go-ole/go-ole/ChangeLog.md
new file mode 100644
index 000000000..4ba6a8c64
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/ChangeLog.md
@@ -0,0 +1,49 @@
+# Version 1.x.x
+
+* **Add more test cases and reference new test COM server project.** (Placeholder for future additions)
+
+# Version 1.2.0-alphaX
+
+**Minimum supported version is now Go 1.4. Go 1.1 support is deprecated, but should still build.**
+
+ * Added CI configuration for Travis-CI and AppVeyor.
+ * Added test InterfaceID and ClassID for the COM Test Server project.
+ * Added more inline documentation (#83).
+ * Added IEnumVARIANT implementation (#88).
+ * Added IEnumVARIANT test cases (#99, #100, #101).
+ * Added support for retrieving `time.Time` from VARIANT (#92).
+ * Added test case for IUnknown (#64).
+ * Added test case for IDispatch (#64).
+ * Added test cases for scalar variants (#64, #76).
+
+# Version 1.1.1
+
+ * Fixes for Linux build.
+ * Fixes for Windows build.
+
+# Version 1.1.0
+
+The change to provide building on all platforms is a new feature. The increase in minor version reflects that and allows those who wish to stay on 1.0.x to continue to do so. Support for 1.0.x will be limited to bug fixes.
+
+ * Move GUID out of variables.go into its own file to make new documentation available.
+ * Move OleError out of ole.go into its own file to make new documentation available.
+ * Add documentation to utility functions.
+ * Add documentation to variant receiver functions.
+ * Add documentation to ole structures.
+ * Make variant available to other systems outside of Windows.
+ * Make OLE structures available to other systems outside of Windows.
+
+## New Features
+
+ * Library should now be built on all platforms supported by Go. Library will NOOP on any platform that is not Windows.
+ * More functions are now documented and available on godoc.org.
+
+# Version 1.0.1
+
+ 1. Fix package references from repository location change.
+
+# Version 1.0.0
+
+This version is stable enough for use. The COM API is still incomplete, but provides enough functionality for accessing COM servers using IDispatch interface.
+
+There is no changelog for this version. Check commits for history.
diff --git a/vendor/github.com/go-ole/go-ole/LICENSE b/vendor/github.com/go-ole/go-ole/LICENSE
new file mode 100644
index 000000000..623ec06f9
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright © 2013-2017 Yasuhiro Matsumoto, <mattn.jp@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the “Software”), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/go-ole/go-ole/README.md b/vendor/github.com/go-ole/go-ole/README.md
new file mode 100644
index 000000000..0ea9db33c
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/README.md
@@ -0,0 +1,46 @@
+#Go OLE
+
+[![Build status](https://ci.appveyor.com/api/projects/status/qr0u2sf7q43us9fj?svg=true)](https://ci.appveyor.com/project/jacobsantos/go-ole-jgs28)
+[![Build Status](https://travis-ci.org/go-ole/go-ole.svg?branch=master)](https://travis-ci.org/go-ole/go-ole)
+[![GoDoc](https://godoc.org/github.com/go-ole/go-ole?status.svg)](https://godoc.org/github.com/go-ole/go-ole)
+
+Go bindings for Windows COM using shared libraries instead of cgo.
+
+By Yasuhiro Matsumoto.
+
+## Install
+
+To experiment with go-ole, you can just compile and run the example program:
+
+```
+go get github.com/go-ole/go-ole
+cd /path/to/go-ole/
+go test
+
+cd /path/to/go-ole/example/excel
+go run excel.go
+```
+
+## Continuous Integration
+
+Continuous integration configuration has been added for both Travis-CI and AppVeyor. You will have to add these to your own account for your fork in order for it to run.
+
+**Travis-CI**
+
+Travis-CI was added to check builds on Linux to ensure that `go get` works when cross building. Currently, Travis-CI is not used to test cross-building, but this may be changed in the future. It is also not currently possible to test the library on Linux, since COM API is specific to Windows and it is not currently possible to run a COM server on Linux or even connect to a remote COM server.
+
+**AppVeyor**
+
+AppVeyor is used to build on Windows using the (in-development) test COM server. It is currently only used to test the build and ensure that the code works on Windows. It will be used to register a COM server and then run the test cases based on the test COM server.
+
+The tests currently do run and do pass and this should be maintained with commits.
+
+##Versioning
+
+Go OLE uses [semantic versioning](http://semver.org) for version numbers, which is similar to the version contract of the Go language. Which means that the major version will always maintain backwards compatibility with minor versions. Minor versions will only add new additions and changes. Fixes will always be in patch.
+
+This contract should allow you to upgrade to new minor and patch versions without breakage or modifications to your existing code. Leave a ticket, if there is breakage, so that it could be fixed.
+
+##LICENSE
+
+Under the MIT License: http://mattn.mit-license.org/2013
diff --git a/vendor/github.com/go-ole/go-ole/appveyor.yml b/vendor/github.com/go-ole/go-ole/appveyor.yml
new file mode 100644
index 000000000..0d557ac2f
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/appveyor.yml
@@ -0,0 +1,54 @@
+# Notes:
+# - Minimal appveyor.yml file is an empty file. All sections are optional.
+# - Indent each level of configuration with 2 spaces. Do not use tabs!
+# - All section names are case-sensitive.
+# - Section names should be unique on each level.
+
+version: "1.3.0.{build}-alpha-{branch}"
+
+os: Windows Server 2012 R2
+
+branches:
+ only:
+ - master
+ - v1.2
+ - v1.1
+ - v1.0
+
+skip_tags: true
+
+clone_folder: c:\gopath\src\github.com\go-ole\go-ole
+
+environment:
+ GOPATH: c:\gopath
+ matrix:
+ - GOARCH: amd64
+ GOVERSION: 1.5
+ GOROOT: c:\go
+ DOWNLOADPLATFORM: "x64"
+
+install:
+ - choco install mingw
+ - SET PATH=c:\tools\mingw64\bin;%PATH%
+ # - Download COM Server
+ - ps: Start-FileDownload "https://github.com/go-ole/test-com-server/releases/download/v1.0.2/test-com-server-${env:DOWNLOADPLATFORM}.zip"
+ - 7z e test-com-server-%DOWNLOADPLATFORM%.zip -oc:\gopath\src\github.com\go-ole\go-ole > NUL
+ - c:\gopath\src\github.com\go-ole\go-ole\build\register-assembly.bat
+ # - set
+ - go version
+ - go env
+ - go get -u golang.org/x/tools/cmd/cover
+ - go get -u golang.org/x/tools/cmd/godoc
+ - go get -u golang.org/x/tools/cmd/stringer
+
+build_script:
+ - cd c:\gopath\src\github.com\go-ole\go-ole
+ - go get -v -t ./...
+ - go build
+ - go test -v -cover ./...
+
+# disable automatic tests
+test: off
+
+# disable deployment
+deploy: off
diff --git a/vendor/github.com/go-ole/go-ole/com.go b/vendor/github.com/go-ole/go-ole/com.go
new file mode 100644
index 000000000..75ebbf13f
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/com.go
@@ -0,0 +1,329 @@
+// +build windows
+
+package ole
+
+import (
+ "errors"
+ "syscall"
+ "time"
+ "unicode/utf16"
+ "unsafe"
+)
+
+var (
+ procCoInitialize, _ = modole32.FindProc("CoInitialize")
+ procCoInitializeEx, _ = modole32.FindProc("CoInitializeEx")
+ procCoUninitialize, _ = modole32.FindProc("CoUninitialize")
+ procCoCreateInstance, _ = modole32.FindProc("CoCreateInstance")
+ procCoTaskMemFree, _ = modole32.FindProc("CoTaskMemFree")
+ procCLSIDFromProgID, _ = modole32.FindProc("CLSIDFromProgID")
+ procCLSIDFromString, _ = modole32.FindProc("CLSIDFromString")
+ procStringFromCLSID, _ = modole32.FindProc("StringFromCLSID")
+ procStringFromIID, _ = modole32.FindProc("StringFromIID")
+ procIIDFromString, _ = modole32.FindProc("IIDFromString")
+ procGetUserDefaultLCID, _ = modkernel32.FindProc("GetUserDefaultLCID")
+ procCopyMemory, _ = modkernel32.FindProc("RtlMoveMemory")
+ procVariantInit, _ = modoleaut32.FindProc("VariantInit")
+ procVariantClear, _ = modoleaut32.FindProc("VariantClear")
+ procVariantTimeToSystemTime, _ = modoleaut32.FindProc("VariantTimeToSystemTime")
+ procSysAllocString, _ = modoleaut32.FindProc("SysAllocString")
+ procSysAllocStringLen, _ = modoleaut32.FindProc("SysAllocStringLen")
+ procSysFreeString, _ = modoleaut32.FindProc("SysFreeString")
+ procSysStringLen, _ = modoleaut32.FindProc("SysStringLen")
+ procCreateDispTypeInfo, _ = modoleaut32.FindProc("CreateDispTypeInfo")
+ procCreateStdDispatch, _ = modoleaut32.FindProc("CreateStdDispatch")
+ procGetActiveObject, _ = modoleaut32.FindProc("GetActiveObject")
+
+ procGetMessageW, _ = moduser32.FindProc("GetMessageW")
+ procDispatchMessageW, _ = moduser32.FindProc("DispatchMessageW")
+)
+
+// coInitialize initializes COM library on current thread.
+//
+// MSDN documentation suggests that this function should not be called. Call
+// CoInitializeEx() instead. The reason has to do with threading and this
+// function is only for single-threaded apartments.
+//
+// That said, most users of the library have gotten away with just this
+// function. If you are experiencing threading issues, then use
+// CoInitializeEx().
+func coInitialize() (err error) {
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/ms678543(v=vs.85).aspx
+ // Suggests that no value should be passed to CoInitialized.
+ // Could just be Call() since the parameter is optional. <-- Needs testing to be sure.
+ hr, _, _ := procCoInitialize.Call(uintptr(0))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+// coInitializeEx initializes COM library with concurrency model.
+func coInitializeEx(coinit uint32) (err error) {
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/ms695279(v=vs.85).aspx
+ // Suggests that the first parameter is not only optional but should always be NULL.
+ hr, _, _ := procCoInitializeEx.Call(uintptr(0), uintptr(coinit))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+// CoInitialize initializes COM library on current thread.
+//
+// MSDN documentation suggests that this function should not be called. Call
+// CoInitializeEx() instead. The reason has to do with threading and this
+// function is only for single-threaded apartments.
+//
+// That said, most users of the library have gotten away with just this
+// function. If you are experiencing threading issues, then use
+// CoInitializeEx().
+func CoInitialize(p uintptr) (err error) {
+ // p is ignored and won't be used.
+ // Avoid any variable not used errors.
+ p = uintptr(0)
+ return coInitialize()
+}
+
+// CoInitializeEx initializes COM library with concurrency model.
+func CoInitializeEx(p uintptr, coinit uint32) (err error) {
+ // Avoid any variable not used errors.
+ p = uintptr(0)
+ return coInitializeEx(coinit)
+}
+
+// CoUninitialize uninitializes COM Library.
+func CoUninitialize() {
+ procCoUninitialize.Call()
+}
+
+// CoTaskMemFree frees memory pointer.
+func CoTaskMemFree(memptr uintptr) {
+ procCoTaskMemFree.Call(memptr)
+}
+
+// CLSIDFromProgID retrieves Class Identifier with the given Program Identifier.
+//
+// The Programmatic Identifier must be registered, because it will be looked up
+// in the Windows Registry. The registry entry has the following keys: CLSID,
+// Insertable, Protocol and Shell
+// (https://msdn.microsoft.com/en-us/library/dd542719(v=vs.85).aspx).
+//
+// programID identifies the class id with less precision and is not guaranteed
+// to be unique. These are usually found in the registry under
+// HKEY_LOCAL_MACHINE\SOFTWARE\Classes, usually with the format of
+// "Program.Component.Version" with version being optional.
+//
+// CLSIDFromProgID in Windows API.
+func CLSIDFromProgID(progId string) (clsid *GUID, err error) {
+ var guid GUID
+ lpszProgID := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(progId)))
+ hr, _, _ := procCLSIDFromProgID.Call(lpszProgID, uintptr(unsafe.Pointer(&guid)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ clsid = &guid
+ return
+}
+
+// CLSIDFromString retrieves Class ID from string representation.
+//
+// This is technically the string version of the GUID and will convert the
+// string to object.
+//
+// CLSIDFromString in Windows API.
+func CLSIDFromString(str string) (clsid *GUID, err error) {
+ var guid GUID
+ lpsz := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(str)))
+ hr, _, _ := procCLSIDFromString.Call(lpsz, uintptr(unsafe.Pointer(&guid)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ clsid = &guid
+ return
+}
+
+// StringFromCLSID returns GUID formated string from GUID object.
+func StringFromCLSID(clsid *GUID) (str string, err error) {
+ var p *uint16
+ hr, _, _ := procStringFromCLSID.Call(uintptr(unsafe.Pointer(clsid)), uintptr(unsafe.Pointer(&p)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ str = LpOleStrToString(p)
+ return
+}
+
+// IIDFromString returns GUID from program ID.
+func IIDFromString(progId string) (clsid *GUID, err error) {
+ var guid GUID
+ lpsz := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(progId)))
+ hr, _, _ := procIIDFromString.Call(lpsz, uintptr(unsafe.Pointer(&guid)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ clsid = &guid
+ return
+}
+
+// StringFromIID returns GUID formatted string from GUID object.
+func StringFromIID(iid *GUID) (str string, err error) {
+ var p *uint16
+ hr, _, _ := procStringFromIID.Call(uintptr(unsafe.Pointer(iid)), uintptr(unsafe.Pointer(&p)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ str = LpOleStrToString(p)
+ return
+}
+
+// CreateInstance of single uninitialized object with GUID.
+func CreateInstance(clsid *GUID, iid *GUID) (unk *IUnknown, err error) {
+ if iid == nil {
+ iid = IID_IUnknown
+ }
+ hr, _, _ := procCoCreateInstance.Call(
+ uintptr(unsafe.Pointer(clsid)),
+ 0,
+ CLSCTX_SERVER,
+ uintptr(unsafe.Pointer(iid)),
+ uintptr(unsafe.Pointer(&unk)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+// GetActiveObject retrieves pointer to active object.
+func GetActiveObject(clsid *GUID, iid *GUID) (unk *IUnknown, err error) {
+ if iid == nil {
+ iid = IID_IUnknown
+ }
+ hr, _, _ := procGetActiveObject.Call(
+ uintptr(unsafe.Pointer(clsid)),
+ uintptr(unsafe.Pointer(iid)),
+ uintptr(unsafe.Pointer(&unk)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+// VariantInit initializes variant.
+func VariantInit(v *VARIANT) (err error) {
+ hr, _, _ := procVariantInit.Call(uintptr(unsafe.Pointer(v)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+// VariantClear clears value in Variant settings to VT_EMPTY.
+func VariantClear(v *VARIANT) (err error) {
+ hr, _, _ := procVariantClear.Call(uintptr(unsafe.Pointer(v)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+// SysAllocString allocates memory for string and copies string into memory.
+func SysAllocString(v string) (ss *int16) {
+ pss, _, _ := procSysAllocString.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(v))))
+ ss = (*int16)(unsafe.Pointer(pss))
+ return
+}
+
+// SysAllocStringLen copies up to length of given string returning pointer.
+func SysAllocStringLen(v string) (ss *int16) {
+ utf16 := utf16.Encode([]rune(v + "\x00"))
+ ptr := &utf16[0]
+
+ pss, _, _ := procSysAllocStringLen.Call(uintptr(unsafe.Pointer(ptr)), uintptr(len(utf16)-1))
+ ss = (*int16)(unsafe.Pointer(pss))
+ return
+}
+
+// SysFreeString frees string system memory. This must be called with SysAllocString.
+func SysFreeString(v *int16) (err error) {
+ hr, _, _ := procSysFreeString.Call(uintptr(unsafe.Pointer(v)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+// SysStringLen is the length of the system allocated string.
+func SysStringLen(v *int16) uint32 {
+ l, _, _ := procSysStringLen.Call(uintptr(unsafe.Pointer(v)))
+ return uint32(l)
+}
+
+// CreateStdDispatch provides default IDispatch implementation for IUnknown.
+//
+// This handles default IDispatch implementation for objects. It haves a few
+// limitations with only supporting one language. It will also only return
+// default exception codes.
+func CreateStdDispatch(unk *IUnknown, v uintptr, ptinfo *IUnknown) (disp *IDispatch, err error) {
+ hr, _, _ := procCreateStdDispatch.Call(
+ uintptr(unsafe.Pointer(unk)),
+ v,
+ uintptr(unsafe.Pointer(ptinfo)),
+ uintptr(unsafe.Pointer(&disp)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+// CreateDispTypeInfo provides default ITypeInfo implementation for IDispatch.
+//
+// This will not handle the full implementation of the interface.
+func CreateDispTypeInfo(idata *INTERFACEDATA) (pptinfo *IUnknown, err error) {
+ hr, _, _ := procCreateDispTypeInfo.Call(
+ uintptr(unsafe.Pointer(idata)),
+ uintptr(GetUserDefaultLCID()),
+ uintptr(unsafe.Pointer(&pptinfo)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+// copyMemory moves location of a block of memory.
+func copyMemory(dest unsafe.Pointer, src unsafe.Pointer, length uint32) {
+ procCopyMemory.Call(uintptr(dest), uintptr(src), uintptr(length))
+}
+
+// GetUserDefaultLCID retrieves current user default locale.
+func GetUserDefaultLCID() (lcid uint32) {
+ ret, _, _ := procGetUserDefaultLCID.Call()
+ lcid = uint32(ret)
+ return
+}
+
+// GetMessage in message queue from runtime.
+//
+// This function appears to block. PeekMessage does not block.
+func GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, err error) {
+ r0, _, err := procGetMessageW.Call(uintptr(unsafe.Pointer(msg)), uintptr(hwnd), uintptr(MsgFilterMin), uintptr(MsgFilterMax))
+ ret = int32(r0)
+ return
+}
+
+// DispatchMessage to window procedure.
+func DispatchMessage(msg *Msg) (ret int32) {
+ r0, _, _ := procDispatchMessageW.Call(uintptr(unsafe.Pointer(msg)))
+ ret = int32(r0)
+ return
+}
+
+// GetVariantDate converts COM Variant Time value to Go time.Time.
+func GetVariantDate(value float64) (time.Time, error) {
+ var st syscall.Systemtime
+ r, _, _ := procVariantTimeToSystemTime.Call(uintptr(value), uintptr(unsafe.Pointer(&st)))
+ if r != 0 {
+ return time.Date(int(st.Year), time.Month(st.Month), int(st.Day), int(st.Hour), int(st.Minute), int(st.Second), int(st.Milliseconds/1000), time.UTC), nil
+ }
+ return time.Now(), errors.New("Could not convert to time, passing current time.")
+}
diff --git a/vendor/github.com/go-ole/go-ole/com_func.go b/vendor/github.com/go-ole/go-ole/com_func.go
new file mode 100644
index 000000000..425aad323
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/com_func.go
@@ -0,0 +1,174 @@
+// +build !windows
+
+package ole
+
+import (
+ "time"
+ "unsafe"
+)
+
+// coInitialize initializes COM library on current thread.
+//
+// MSDN documentation suggests that this function should not be called. Call
+// CoInitializeEx() instead. The reason has to do with threading and this
+// function is only for single-threaded apartments.
+//
+// That said, most users of the library have gotten away with just this
+// function. If you are experiencing threading issues, then use
+// CoInitializeEx().
+func coInitialize() error {
+ return NewError(E_NOTIMPL)
+}
+
+// coInitializeEx initializes COM library with concurrency model.
+func coInitializeEx(coinit uint32) error {
+ return NewError(E_NOTIMPL)
+}
+
+// CoInitialize initializes COM library on current thread.
+//
+// MSDN documentation suggests that this function should not be called. Call
+// CoInitializeEx() instead. The reason has to do with threading and this
+// function is only for single-threaded apartments.
+//
+// That said, most users of the library have gotten away with just this
+// function. If you are experiencing threading issues, then use
+// CoInitializeEx().
+func CoInitialize(p uintptr) error {
+ return NewError(E_NOTIMPL)
+}
+
+// CoInitializeEx initializes COM library with concurrency model.
+func CoInitializeEx(p uintptr, coinit uint32) error {
+ return NewError(E_NOTIMPL)
+}
+
+// CoUninitialize uninitializes COM Library.
+func CoUninitialize() {}
+
+// CoTaskMemFree frees memory pointer.
+func CoTaskMemFree(memptr uintptr) {}
+
+// CLSIDFromProgID retrieves Class Identifier with the given Program Identifier.
+//
+// The Programmatic Identifier must be registered, because it will be looked up
+// in the Windows Registry. The registry entry has the following keys: CLSID,
+// Insertable, Protocol and Shell
+// (https://msdn.microsoft.com/en-us/library/dd542719(v=vs.85).aspx).
+//
+// programID identifies the class id with less precision and is not guaranteed
+// to be unique. These are usually found in the registry under
+// HKEY_LOCAL_MACHINE\SOFTWARE\Classes, usually with the format of
+// "Program.Component.Version" with version being optional.
+//
+// CLSIDFromProgID in Windows API.
+func CLSIDFromProgID(progId string) (*GUID, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// CLSIDFromString retrieves Class ID from string representation.
+//
+// This is technically the string version of the GUID and will convert the
+// string to object.
+//
+// CLSIDFromString in Windows API.
+func CLSIDFromString(str string) (*GUID, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// StringFromCLSID returns GUID formated string from GUID object.
+func StringFromCLSID(clsid *GUID) (string, error) {
+ return "", NewError(E_NOTIMPL)
+}
+
+// IIDFromString returns GUID from program ID.
+func IIDFromString(progId string) (*GUID, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// StringFromIID returns GUID formatted string from GUID object.
+func StringFromIID(iid *GUID) (string, error) {
+ return "", NewError(E_NOTIMPL)
+}
+
+// CreateInstance of single uninitialized object with GUID.
+func CreateInstance(clsid *GUID, iid *GUID) (*IUnknown, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// GetActiveObject retrieves pointer to active object.
+func GetActiveObject(clsid *GUID, iid *GUID) (*IUnknown, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// VariantInit initializes variant.
+func VariantInit(v *VARIANT) error {
+ return NewError(E_NOTIMPL)
+}
+
+// VariantClear clears value in Variant settings to VT_EMPTY.
+func VariantClear(v *VARIANT) error {
+ return NewError(E_NOTIMPL)
+}
+
+// SysAllocString allocates memory for string and copies string into memory.
+func SysAllocString(v string) *int16 {
+ u := int16(0)
+ return &u
+}
+
+// SysAllocStringLen copies up to length of given string returning pointer.
+func SysAllocStringLen(v string) *int16 {
+ u := int16(0)
+ return &u
+}
+
+// SysFreeString frees string system memory. This must be called with SysAllocString.
+func SysFreeString(v *int16) error {
+ return NewError(E_NOTIMPL)
+}
+
+// SysStringLen is the length of the system allocated string.
+func SysStringLen(v *int16) uint32 {
+ return uint32(0)
+}
+
+// CreateStdDispatch provides default IDispatch implementation for IUnknown.
+//
+// This handles default IDispatch implementation for objects. It haves a few
+// limitations with only supporting one language. It will also only return
+// default exception codes.
+func CreateStdDispatch(unk *IUnknown, v uintptr, ptinfo *IUnknown) (*IDispatch, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// CreateDispTypeInfo provides default ITypeInfo implementation for IDispatch.
+//
+// This will not handle the full implementation of the interface.
+func CreateDispTypeInfo(idata *INTERFACEDATA) (*IUnknown, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// copyMemory moves location of a block of memory.
+func copyMemory(dest unsafe.Pointer, src unsafe.Pointer, length uint32) {}
+
+// GetUserDefaultLCID retrieves current user default locale.
+func GetUserDefaultLCID() uint32 {
+ return uint32(0)
+}
+
+// GetMessage in message queue from runtime.
+//
+// This function appears to block. PeekMessage does not block.
+func GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (int32, error) {
+ return int32(0), NewError(E_NOTIMPL)
+}
+
+// DispatchMessage to window procedure.
+func DispatchMessage(msg *Msg) int32 {
+ return int32(0)
+}
+
+func GetVariantDate(value float64) (time.Time, error) {
+ return time.Now(), NewError(E_NOTIMPL)
+}
diff --git a/vendor/github.com/go-ole/go-ole/connect.go b/vendor/github.com/go-ole/go-ole/connect.go
new file mode 100644
index 000000000..b2ac2ec67
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/connect.go
@@ -0,0 +1,192 @@
+package ole
+
+// Connection contains IUnknown for fluent interface interaction.
+//
+// Deprecated. Use oleutil package instead.
+type Connection struct {
+ Object *IUnknown // Access COM
+}
+
+// Initialize COM.
+func (*Connection) Initialize() (err error) {
+ return coInitialize()
+}
+
+// Uninitialize COM.
+func (*Connection) Uninitialize() {
+ CoUninitialize()
+}
+
+// Create IUnknown object based first on ProgId and then from String.
+func (c *Connection) Create(progId string) (err error) {
+ var clsid *GUID
+ clsid, err = CLSIDFromProgID(progId)
+ if err != nil {
+ clsid, err = CLSIDFromString(progId)
+ if err != nil {
+ return
+ }
+ }
+
+ unknown, err := CreateInstance(clsid, IID_IUnknown)
+ if err != nil {
+ return
+ }
+ c.Object = unknown
+
+ return
+}
+
+// Release IUnknown object.
+func (c *Connection) Release() {
+ c.Object.Release()
+}
+
+// Load COM object from list of programIDs or strings.
+func (c *Connection) Load(names ...string) (errors []error) {
+ var tempErrors []error = make([]error, len(names))
+ var numErrors int = 0
+ for _, name := range names {
+ err := c.Create(name)
+ if err != nil {
+ tempErrors = append(tempErrors, err)
+ numErrors += 1
+ continue
+ }
+ break
+ }
+
+ copy(errors, tempErrors[0:numErrors])
+ return
+}
+
+// Dispatch returns Dispatch object.
+func (c *Connection) Dispatch() (object *Dispatch, err error) {
+ dispatch, err := c.Object.QueryInterface(IID_IDispatch)
+ if err != nil {
+ return
+ }
+ object = &Dispatch{dispatch}
+ return
+}
+
+// Dispatch stores IDispatch object.
+type Dispatch struct {
+ Object *IDispatch // Dispatch object.
+}
+
+// Call method on IDispatch with parameters.
+func (d *Dispatch) Call(method string, params ...interface{}) (result *VARIANT, err error) {
+ id, err := d.GetId(method)
+ if err != nil {
+ return
+ }
+
+ result, err = d.Invoke(id, DISPATCH_METHOD, params)
+ return
+}
+
+// MustCall method on IDispatch with parameters.
+func (d *Dispatch) MustCall(method string, params ...interface{}) (result *VARIANT) {
+ id, err := d.GetId(method)
+ if err != nil {
+ panic(err)
+ }
+
+ result, err = d.Invoke(id, DISPATCH_METHOD, params)
+ if err != nil {
+ panic(err)
+ }
+
+ return
+}
+
+// Get property on IDispatch with parameters.
+func (d *Dispatch) Get(name string, params ...interface{}) (result *VARIANT, err error) {
+ id, err := d.GetId(name)
+ if err != nil {
+ return
+ }
+ result, err = d.Invoke(id, DISPATCH_PROPERTYGET, params)
+ return
+}
+
+// MustGet property on IDispatch with parameters.
+func (d *Dispatch) MustGet(name string, params ...interface{}) (result *VARIANT) {
+ id, err := d.GetId(name)
+ if err != nil {
+ panic(err)
+ }
+
+ result, err = d.Invoke(id, DISPATCH_PROPERTYGET, params)
+ if err != nil {
+ panic(err)
+ }
+ return
+}
+
+// Set property on IDispatch with parameters.
+func (d *Dispatch) Set(name string, params ...interface{}) (result *VARIANT, err error) {
+ id, err := d.GetId(name)
+ if err != nil {
+ return
+ }
+ result, err = d.Invoke(id, DISPATCH_PROPERTYPUT, params)
+ return
+}
+
+// MustSet property on IDispatch with parameters.
+func (d *Dispatch) MustSet(name string, params ...interface{}) (result *VARIANT) {
+ id, err := d.GetId(name)
+ if err != nil {
+ panic(err)
+ }
+
+ result, err = d.Invoke(id, DISPATCH_PROPERTYPUT, params)
+ if err != nil {
+ panic(err)
+ }
+ return
+}
+
+// GetId retrieves ID of name on IDispatch.
+func (d *Dispatch) GetId(name string) (id int32, err error) {
+ var dispid []int32
+ dispid, err = d.Object.GetIDsOfName([]string{name})
+ if err != nil {
+ return
+ }
+ id = dispid[0]
+ return
+}
+
+// GetIds retrieves all IDs of names on IDispatch.
+func (d *Dispatch) GetIds(names ...string) (dispid []int32, err error) {
+ dispid, err = d.Object.GetIDsOfName(names)
+ return
+}
+
+// Invoke IDispatch on DisplayID of dispatch type with parameters.
+//
+// There have been problems where if send cascading params..., it would error
+// out because the parameters would be empty.
+func (d *Dispatch) Invoke(id int32, dispatch int16, params []interface{}) (result *VARIANT, err error) {
+ if len(params) < 1 {
+ result, err = d.Object.Invoke(id, dispatch)
+ } else {
+ result, err = d.Object.Invoke(id, dispatch, params...)
+ }
+ return
+}
+
+// Release IDispatch object.
+func (d *Dispatch) Release() {
+ d.Object.Release()
+}
+
+// Connect initializes COM and attempts to load IUnknown based on given names.
+func Connect(names ...string) (connection *Connection) {
+ connection.Initialize()
+ connection.Load(names...)
+ return
+}
diff --git a/vendor/github.com/go-ole/go-ole/constants.go b/vendor/github.com/go-ole/go-ole/constants.go
new file mode 100644
index 000000000..fd0c6d74b
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/constants.go
@@ -0,0 +1,153 @@
+package ole
+
+const (
+ CLSCTX_INPROC_SERVER = 1
+ CLSCTX_INPROC_HANDLER = 2
+ CLSCTX_LOCAL_SERVER = 4
+ CLSCTX_INPROC_SERVER16 = 8
+ CLSCTX_REMOTE_SERVER = 16
+ CLSCTX_ALL = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER
+ CLSCTX_INPROC = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER
+ CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER
+)
+
+const (
+ COINIT_APARTMENTTHREADED = 0x2
+ COINIT_MULTITHREADED = 0x0
+ COINIT_DISABLE_OLE1DDE = 0x4
+ COINIT_SPEED_OVER_MEMORY = 0x8
+)
+
+const (
+ DISPATCH_METHOD = 1
+ DISPATCH_PROPERTYGET = 2
+ DISPATCH_PROPERTYPUT = 4
+ DISPATCH_PROPERTYPUTREF = 8
+)
+
+const (
+ S_OK = 0x00000000
+ E_UNEXPECTED = 0x8000FFFF
+ E_NOTIMPL = 0x80004001
+ E_OUTOFMEMORY = 0x8007000E
+ E_INVALIDARG = 0x80070057
+ E_NOINTERFACE = 0x80004002
+ E_POINTER = 0x80004003
+ E_HANDLE = 0x80070006
+ E_ABORT = 0x80004004
+ E_FAIL = 0x80004005
+ E_ACCESSDENIED = 0x80070005
+ E_PENDING = 0x8000000A
+
+ CO_E_CLASSSTRING = 0x800401F3
+)
+
+const (
+ CC_FASTCALL = iota
+ CC_CDECL
+ CC_MSCPASCAL
+ CC_PASCAL = CC_MSCPASCAL
+ CC_MACPASCAL
+ CC_STDCALL
+ CC_FPFASTCALL
+ CC_SYSCALL
+ CC_MPWCDECL
+ CC_MPWPASCAL
+ CC_MAX = CC_MPWPASCAL
+)
+
+type VT uint16
+
+const (
+ VT_EMPTY VT = 0x0
+ VT_NULL VT = 0x1
+ VT_I2 VT = 0x2
+ VT_I4 VT = 0x3
+ VT_R4 VT = 0x4
+ VT_R8 VT = 0x5
+ VT_CY VT = 0x6
+ VT_DATE VT = 0x7
+ VT_BSTR VT = 0x8
+ VT_DISPATCH VT = 0x9
+ VT_ERROR VT = 0xa
+ VT_BOOL VT = 0xb
+ VT_VARIANT VT = 0xc
+ VT_UNKNOWN VT = 0xd
+ VT_DECIMAL VT = 0xe
+ VT_I1 VT = 0x10
+ VT_UI1 VT = 0x11
+ VT_UI2 VT = 0x12
+ VT_UI4 VT = 0x13
+ VT_I8 VT = 0x14
+ VT_UI8 VT = 0x15
+ VT_INT VT = 0x16
+ VT_UINT VT = 0x17
+ VT_VOID VT = 0x18
+ VT_HRESULT VT = 0x19
+ VT_PTR VT = 0x1a
+ VT_SAFEARRAY VT = 0x1b
+ VT_CARRAY VT = 0x1c
+ VT_USERDEFINED VT = 0x1d
+ VT_LPSTR VT = 0x1e
+ VT_LPWSTR VT = 0x1f
+ VT_RECORD VT = 0x24
+ VT_INT_PTR VT = 0x25
+ VT_UINT_PTR VT = 0x26
+ VT_FILETIME VT = 0x40
+ VT_BLOB VT = 0x41
+ VT_STREAM VT = 0x42
+ VT_STORAGE VT = 0x43
+ VT_STREAMED_OBJECT VT = 0x44
+ VT_STORED_OBJECT VT = 0x45
+ VT_BLOB_OBJECT VT = 0x46
+ VT_CF VT = 0x47
+ VT_CLSID VT = 0x48
+ VT_BSTR_BLOB VT = 0xfff
+ VT_VECTOR VT = 0x1000
+ VT_ARRAY VT = 0x2000
+ VT_BYREF VT = 0x4000
+ VT_RESERVED VT = 0x8000
+ VT_ILLEGAL VT = 0xffff
+ VT_ILLEGALMASKED VT = 0xfff
+ VT_TYPEMASK VT = 0xfff
+)
+
+const (
+ DISPID_UNKNOWN = -1
+ DISPID_VALUE = 0
+ DISPID_PROPERTYPUT = -3
+ DISPID_NEWENUM = -4
+ DISPID_EVALUATE = -5
+ DISPID_CONSTRUCTOR = -6
+ DISPID_DESTRUCTOR = -7
+ DISPID_COLLECT = -8
+)
+
+const (
+ TKIND_ENUM = 1
+ TKIND_RECORD = 2
+ TKIND_MODULE = 3
+ TKIND_INTERFACE = 4
+ TKIND_DISPATCH = 5
+ TKIND_COCLASS = 6
+ TKIND_ALIAS = 7
+ TKIND_UNION = 8
+ TKIND_MAX = 9
+)
+
+// Safe Array Feature Flags
+
+const (
+ FADF_AUTO = 0x0001
+ FADF_STATIC = 0x0002
+ FADF_EMBEDDED = 0x0004
+ FADF_FIXEDSIZE = 0x0010
+ FADF_RECORD = 0x0020
+ FADF_HAVEIID = 0x0040
+ FADF_HAVEVARTYPE = 0x0080
+ FADF_BSTR = 0x0100
+ FADF_UNKNOWN = 0x0200
+ FADF_DISPATCH = 0x0400
+ FADF_VARIANT = 0x0800
+ FADF_RESERVED = 0xF008
+)
diff --git a/vendor/github.com/go-ole/go-ole/error.go b/vendor/github.com/go-ole/go-ole/error.go
new file mode 100644
index 000000000..096b456d3
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/error.go
@@ -0,0 +1,51 @@
+package ole
+
+// OleError stores COM errors.
+type OleError struct {
+ hr uintptr
+ description string
+ subError error
+}
+
+// NewError creates new error with HResult.
+func NewError(hr uintptr) *OleError {
+ return &OleError{hr: hr}
+}
+
+// NewErrorWithDescription creates new COM error with HResult and description.
+func NewErrorWithDescription(hr uintptr, description string) *OleError {
+ return &OleError{hr: hr, description: description}
+}
+
+// NewErrorWithSubError creates new COM error with parent error.
+func NewErrorWithSubError(hr uintptr, description string, err error) *OleError {
+ return &OleError{hr: hr, description: description, subError: err}
+}
+
+// Code is the HResult.
+func (v *OleError) Code() uintptr {
+ return uintptr(v.hr)
+}
+
+// String description, either manually set or format message with error code.
+func (v *OleError) String() string {
+ if v.description != "" {
+ return errstr(int(v.hr)) + " (" + v.description + ")"
+ }
+ return errstr(int(v.hr))
+}
+
+// Error implements error interface.
+func (v *OleError) Error() string {
+ return v.String()
+}
+
+// Description retrieves error summary, if there is one.
+func (v *OleError) Description() string {
+ return v.description
+}
+
+// SubError returns parent error, if there is one.
+func (v *OleError) SubError() error {
+ return v.subError
+}
diff --git a/vendor/github.com/go-ole/go-ole/error_func.go b/vendor/github.com/go-ole/go-ole/error_func.go
new file mode 100644
index 000000000..8a2ffaa27
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/error_func.go
@@ -0,0 +1,8 @@
+// +build !windows
+
+package ole
+
+// errstr converts error code to string.
+func errstr(errno int) string {
+ return ""
+}
diff --git a/vendor/github.com/go-ole/go-ole/error_windows.go b/vendor/github.com/go-ole/go-ole/error_windows.go
new file mode 100644
index 000000000..d0e8e6859
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/error_windows.go
@@ -0,0 +1,24 @@
+// +build windows
+
+package ole
+
+import (
+ "fmt"
+ "syscall"
+ "unicode/utf16"
+)
+
+// errstr converts error code to string.
+func errstr(errno int) string {
+ // ask windows for the remaining errors
+ var flags uint32 = syscall.FORMAT_MESSAGE_FROM_SYSTEM | syscall.FORMAT_MESSAGE_ARGUMENT_ARRAY | syscall.FORMAT_MESSAGE_IGNORE_INSERTS
+ b := make([]uint16, 300)
+ n, err := syscall.FormatMessage(flags, 0, uint32(errno), 0, b, nil)
+ if err != nil {
+ return fmt.Sprintf("error %d (FormatMessage failed with: %v)", errno, err)
+ }
+ // trim terminating \r and \n
+ for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- {
+ }
+ return string(utf16.Decode(b[:n]))
+}
diff --git a/vendor/github.com/go-ole/go-ole/guid.go b/vendor/github.com/go-ole/go-ole/guid.go
new file mode 100644
index 000000000..8d20f68fb
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/guid.go
@@ -0,0 +1,284 @@
+package ole
+
+var (
+ // IID_NULL is null Interface ID, used when no other Interface ID is known.
+ IID_NULL = NewGUID("{00000000-0000-0000-0000-000000000000}")
+
+ // IID_IUnknown is for IUnknown interfaces.
+ IID_IUnknown = NewGUID("{00000000-0000-0000-C000-000000000046}")
+
+ // IID_IDispatch is for IDispatch interfaces.
+ IID_IDispatch = NewGUID("{00020400-0000-0000-C000-000000000046}")
+
+ // IID_IEnumVariant is for IEnumVariant interfaces
+ IID_IEnumVariant = NewGUID("{00020404-0000-0000-C000-000000000046}")
+
+ // IID_IConnectionPointContainer is for IConnectionPointContainer interfaces.
+ IID_IConnectionPointContainer = NewGUID("{B196B284-BAB4-101A-B69C-00AA00341D07}")
+
+ // IID_IConnectionPoint is for IConnectionPoint interfaces.
+ IID_IConnectionPoint = NewGUID("{B196B286-BAB4-101A-B69C-00AA00341D07}")
+
+ // IID_IInspectable is for IInspectable interfaces.
+ IID_IInspectable = NewGUID("{AF86E2E0-B12D-4C6A-9C5A-D7AA65101E90}")
+
+ // IID_IProvideClassInfo is for IProvideClassInfo interfaces.
+ IID_IProvideClassInfo = NewGUID("{B196B283-BAB4-101A-B69C-00AA00341D07}")
+)
+
+// These are for testing and not part of any library.
+var (
+ // IID_ICOMTestString is for ICOMTestString interfaces.
+ //
+ // {E0133EB4-C36F-469A-9D3D-C66B84BE19ED}
+ IID_ICOMTestString = NewGUID("{E0133EB4-C36F-469A-9D3D-C66B84BE19ED}")
+
+ // IID_ICOMTestInt8 is for ICOMTestInt8 interfaces.
+ //
+ // {BEB06610-EB84-4155-AF58-E2BFF53680B4}
+ IID_ICOMTestInt8 = NewGUID("{BEB06610-EB84-4155-AF58-E2BFF53680B4}")
+
+ // IID_ICOMTestInt16 is for ICOMTestInt16 interfaces.
+ //
+ // {DAA3F9FA-761E-4976-A860-8364CE55F6FC}
+ IID_ICOMTestInt16 = NewGUID("{DAA3F9FA-761E-4976-A860-8364CE55F6FC}")
+
+ // IID_ICOMTestInt32 is for ICOMTestInt32 interfaces.
+ //
+ // {E3DEDEE7-38A2-4540-91D1-2EEF1D8891B0}
+ IID_ICOMTestInt32 = NewGUID("{E3DEDEE7-38A2-4540-91D1-2EEF1D8891B0}")
+
+ // IID_ICOMTestInt64 is for ICOMTestInt64 interfaces.
+ //
+ // {8D437CBC-B3ED-485C-BC32-C336432A1623}
+ IID_ICOMTestInt64 = NewGUID("{8D437CBC-B3ED-485C-BC32-C336432A1623}")
+
+ // IID_ICOMTestFloat is for ICOMTestFloat interfaces.
+ //
+ // {BF1ED004-EA02-456A-AA55-2AC8AC6B054C}
+ IID_ICOMTestFloat = NewGUID("{BF1ED004-EA02-456A-AA55-2AC8AC6B054C}")
+
+ // IID_ICOMTestDouble is for ICOMTestDouble interfaces.
+ //
+ // {BF908A81-8687-4E93-999F-D86FAB284BA0}
+ IID_ICOMTestDouble = NewGUID("{BF908A81-8687-4E93-999F-D86FAB284BA0}")
+
+ // IID_ICOMTestBoolean is for ICOMTestBoolean interfaces.
+ //
+ // {D530E7A6-4EE8-40D1-8931-3D63B8605010}
+ IID_ICOMTestBoolean = NewGUID("{D530E7A6-4EE8-40D1-8931-3D63B8605010}")
+
+ // IID_ICOMEchoTestObject is for ICOMEchoTestObject interfaces.
+ //
+ // {6485B1EF-D780-4834-A4FE-1EBB51746CA3}
+ IID_ICOMEchoTestObject = NewGUID("{6485B1EF-D780-4834-A4FE-1EBB51746CA3}")
+
+ // IID_ICOMTestTypes is for ICOMTestTypes interfaces.
+ //
+ // {CCA8D7AE-91C0-4277-A8B3-FF4EDF28D3C0}
+ IID_ICOMTestTypes = NewGUID("{CCA8D7AE-91C0-4277-A8B3-FF4EDF28D3C0}")
+
+ // CLSID_COMEchoTestObject is for COMEchoTestObject class.
+ //
+ // {3C24506A-AE9E-4D50-9157-EF317281F1B0}
+ CLSID_COMEchoTestObject = NewGUID("{3C24506A-AE9E-4D50-9157-EF317281F1B0}")
+
+ // CLSID_COMTestScalarClass is for COMTestScalarClass class.
+ //
+ // {865B85C5-0334-4AC6-9EF6-AACEC8FC5E86}
+ CLSID_COMTestScalarClass = NewGUID("{865B85C5-0334-4AC6-9EF6-AACEC8FC5E86}")
+)
+
+const hextable = "0123456789ABCDEF"
+const emptyGUID = "{00000000-0000-0000-0000-000000000000}"
+
+// GUID is Windows API specific GUID type.
+//
+// This exists to match Windows GUID type for direct passing for COM.
+// Format is in xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx.
+type GUID struct {
+ Data1 uint32
+ Data2 uint16
+ Data3 uint16
+ Data4 [8]byte
+}
+
+// NewGUID converts the given string into a globally unique identifier that is
+// compliant with the Windows API.
+//
+// The supplied string may be in any of these formats:
+//
+// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+// XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
+// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+//
+// The conversion of the supplied string is not case-sensitive.
+func NewGUID(guid string) *GUID {
+ d := []byte(guid)
+ var d1, d2, d3, d4a, d4b []byte
+
+ switch len(d) {
+ case 38:
+ if d[0] != '{' || d[37] != '}' {
+ return nil
+ }
+ d = d[1:37]
+ fallthrough
+ case 36:
+ if d[8] != '-' || d[13] != '-' || d[18] != '-' || d[23] != '-' {
+ return nil
+ }
+ d1 = d[0:8]
+ d2 = d[9:13]
+ d3 = d[14:18]
+ d4a = d[19:23]
+ d4b = d[24:36]
+ case 32:
+ d1 = d[0:8]
+ d2 = d[8:12]
+ d3 = d[12:16]
+ d4a = d[16:20]
+ d4b = d[20:32]
+ default:
+ return nil
+ }
+
+ var g GUID
+ var ok1, ok2, ok3, ok4 bool
+ g.Data1, ok1 = decodeHexUint32(d1)
+ g.Data2, ok2 = decodeHexUint16(d2)
+ g.Data3, ok3 = decodeHexUint16(d3)
+ g.Data4, ok4 = decodeHexByte64(d4a, d4b)
+ if ok1 && ok2 && ok3 && ok4 {
+ return &g
+ }
+ return nil
+}
+
+func decodeHexUint32(src []byte) (value uint32, ok bool) {
+ var b1, b2, b3, b4 byte
+ var ok1, ok2, ok3, ok4 bool
+ b1, ok1 = decodeHexByte(src[0], src[1])
+ b2, ok2 = decodeHexByte(src[2], src[3])
+ b3, ok3 = decodeHexByte(src[4], src[5])
+ b4, ok4 = decodeHexByte(src[6], src[7])
+ value = (uint32(b1) << 24) | (uint32(b2) << 16) | (uint32(b3) << 8) | uint32(b4)
+ ok = ok1 && ok2 && ok3 && ok4
+ return
+}
+
+func decodeHexUint16(src []byte) (value uint16, ok bool) {
+ var b1, b2 byte
+ var ok1, ok2 bool
+ b1, ok1 = decodeHexByte(src[0], src[1])
+ b2, ok2 = decodeHexByte(src[2], src[3])
+ value = (uint16(b1) << 8) | uint16(b2)
+ ok = ok1 && ok2
+ return
+}
+
+func decodeHexByte64(s1 []byte, s2 []byte) (value [8]byte, ok bool) {
+ var ok1, ok2, ok3, ok4, ok5, ok6, ok7, ok8 bool
+ value[0], ok1 = decodeHexByte(s1[0], s1[1])
+ value[1], ok2 = decodeHexByte(s1[2], s1[3])
+ value[2], ok3 = decodeHexByte(s2[0], s2[1])
+ value[3], ok4 = decodeHexByte(s2[2], s2[3])
+ value[4], ok5 = decodeHexByte(s2[4], s2[5])
+ value[5], ok6 = decodeHexByte(s2[6], s2[7])
+ value[6], ok7 = decodeHexByte(s2[8], s2[9])
+ value[7], ok8 = decodeHexByte(s2[10], s2[11])
+ ok = ok1 && ok2 && ok3 && ok4 && ok5 && ok6 && ok7 && ok8
+ return
+}
+
+func decodeHexByte(c1, c2 byte) (value byte, ok bool) {
+ var n1, n2 byte
+ var ok1, ok2 bool
+ n1, ok1 = decodeHexChar(c1)
+ n2, ok2 = decodeHexChar(c2)
+ value = (n1 << 4) | n2
+ ok = ok1 && ok2
+ return
+}
+
+func decodeHexChar(c byte) (byte, bool) {
+ switch {
+ case '0' <= c && c <= '9':
+ return c - '0', true
+ case 'a' <= c && c <= 'f':
+ return c - 'a' + 10, true
+ case 'A' <= c && c <= 'F':
+ return c - 'A' + 10, true
+ }
+
+ return 0, false
+}
+
+// String converts the GUID to string form. It will adhere to this pattern:
+//
+// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+//
+// If the GUID is nil, the string representation of an empty GUID is returned:
+//
+// {00000000-0000-0000-0000-000000000000}
+func (guid *GUID) String() string {
+ if guid == nil {
+ return emptyGUID
+ }
+
+ var c [38]byte
+ c[0] = '{'
+ putUint32Hex(c[1:9], guid.Data1)
+ c[9] = '-'
+ putUint16Hex(c[10:14], guid.Data2)
+ c[14] = '-'
+ putUint16Hex(c[15:19], guid.Data3)
+ c[19] = '-'
+ putByteHex(c[20:24], guid.Data4[0:2])
+ c[24] = '-'
+ putByteHex(c[25:37], guid.Data4[2:8])
+ c[37] = '}'
+ return string(c[:])
+}
+
+func putUint32Hex(b []byte, v uint32) {
+ b[0] = hextable[byte(v>>24)>>4]
+ b[1] = hextable[byte(v>>24)&0x0f]
+ b[2] = hextable[byte(v>>16)>>4]
+ b[3] = hextable[byte(v>>16)&0x0f]
+ b[4] = hextable[byte(v>>8)>>4]
+ b[5] = hextable[byte(v>>8)&0x0f]
+ b[6] = hextable[byte(v)>>4]
+ b[7] = hextable[byte(v)&0x0f]
+}
+
+func putUint16Hex(b []byte, v uint16) {
+ b[0] = hextable[byte(v>>8)>>4]
+ b[1] = hextable[byte(v>>8)&0x0f]
+ b[2] = hextable[byte(v)>>4]
+ b[3] = hextable[byte(v)&0x0f]
+}
+
+func putByteHex(dst, src []byte) {
+ for i := 0; i < len(src); i++ {
+ dst[i*2] = hextable[src[i]>>4]
+ dst[i*2+1] = hextable[src[i]&0x0f]
+ }
+}
+
+// IsEqualGUID compares two GUID.
+//
+// Not constant time comparison.
+func IsEqualGUID(guid1 *GUID, guid2 *GUID) bool {
+ return guid1.Data1 == guid2.Data1 &&
+ guid1.Data2 == guid2.Data2 &&
+ guid1.Data3 == guid2.Data3 &&
+ guid1.Data4[0] == guid2.Data4[0] &&
+ guid1.Data4[1] == guid2.Data4[1] &&
+ guid1.Data4[2] == guid2.Data4[2] &&
+ guid1.Data4[3] == guid2.Data4[3] &&
+ guid1.Data4[4] == guid2.Data4[4] &&
+ guid1.Data4[5] == guid2.Data4[5] &&
+ guid1.Data4[6] == guid2.Data4[6] &&
+ guid1.Data4[7] == guid2.Data4[7]
+}
diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpoint.go b/vendor/github.com/go-ole/go-ole/iconnectionpoint.go
new file mode 100644
index 000000000..9e6c49f41
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/iconnectionpoint.go
@@ -0,0 +1,20 @@
+package ole
+
+import "unsafe"
+
+type IConnectionPoint struct {
+ IUnknown
+}
+
+type IConnectionPointVtbl struct {
+ IUnknownVtbl
+ GetConnectionInterface uintptr
+ GetConnectionPointContainer uintptr
+ Advise uintptr
+ Unadvise uintptr
+ EnumConnections uintptr
+}
+
+func (v *IConnectionPoint) VTable() *IConnectionPointVtbl {
+ return (*IConnectionPointVtbl)(unsafe.Pointer(v.RawVTable))
+}
diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go b/vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go
new file mode 100644
index 000000000..5414dc3cd
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go
@@ -0,0 +1,21 @@
+// +build !windows
+
+package ole
+
+import "unsafe"
+
+func (v *IConnectionPoint) GetConnectionInterface(piid **GUID) int32 {
+ return int32(0)
+}
+
+func (v *IConnectionPoint) Advise(unknown *IUnknown) (uint32, error) {
+ return uint32(0), NewError(E_NOTIMPL)
+}
+
+func (v *IConnectionPoint) Unadvise(cookie uint32) error {
+ return NewError(E_NOTIMPL)
+}
+
+func (v *IConnectionPoint) EnumConnections(p *unsafe.Pointer) (err error) {
+ return NewError(E_NOTIMPL)
+}
diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go b/vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go
new file mode 100644
index 000000000..32bc18324
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go
@@ -0,0 +1,43 @@
+// +build windows
+
+package ole
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+func (v *IConnectionPoint) GetConnectionInterface(piid **GUID) int32 {
+ // XXX: This doesn't look like it does what it's supposed to
+ return release((*IUnknown)(unsafe.Pointer(v)))
+}
+
+func (v *IConnectionPoint) Advise(unknown *IUnknown) (cookie uint32, err error) {
+ hr, _, _ := syscall.Syscall(
+ v.VTable().Advise,
+ 3,
+ uintptr(unsafe.Pointer(v)),
+ uintptr(unsafe.Pointer(unknown)),
+ uintptr(unsafe.Pointer(&cookie)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+func (v *IConnectionPoint) Unadvise(cookie uint32) (err error) {
+ hr, _, _ := syscall.Syscall(
+ v.VTable().Unadvise,
+ 2,
+ uintptr(unsafe.Pointer(v)),
+ uintptr(cookie),
+ 0)
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+func (v *IConnectionPoint) EnumConnections(p *unsafe.Pointer) error {
+ return NewError(E_NOTIMPL)
+}
diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go
new file mode 100644
index 000000000..165860d19
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go
@@ -0,0 +1,17 @@
+package ole
+
+import "unsafe"
+
+type IConnectionPointContainer struct {
+ IUnknown
+}
+
+type IConnectionPointContainerVtbl struct {
+ IUnknownVtbl
+ EnumConnectionPoints uintptr
+ FindConnectionPoint uintptr
+}
+
+func (v *IConnectionPointContainer) VTable() *IConnectionPointContainerVtbl {
+ return (*IConnectionPointContainerVtbl)(unsafe.Pointer(v.RawVTable))
+}
diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go
new file mode 100644
index 000000000..5dfa42aae
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go
@@ -0,0 +1,11 @@
+// +build !windows
+
+package ole
+
+func (v *IConnectionPointContainer) EnumConnectionPoints(points interface{}) error {
+ return NewError(E_NOTIMPL)
+}
+
+func (v *IConnectionPointContainer) FindConnectionPoint(iid *GUID, point **IConnectionPoint) error {
+ return NewError(E_NOTIMPL)
+}
diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go
new file mode 100644
index 000000000..ad30d79ef
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go
@@ -0,0 +1,25 @@
+// +build windows
+
+package ole
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+func (v *IConnectionPointContainer) EnumConnectionPoints(points interface{}) error {
+ return NewError(E_NOTIMPL)
+}
+
+func (v *IConnectionPointContainer) FindConnectionPoint(iid *GUID, point **IConnectionPoint) (err error) {
+ hr, _, _ := syscall.Syscall(
+ v.VTable().FindConnectionPoint,
+ 3,
+ uintptr(unsafe.Pointer(v)),
+ uintptr(unsafe.Pointer(iid)),
+ uintptr(unsafe.Pointer(point)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
diff --git a/vendor/github.com/go-ole/go-ole/idispatch.go b/vendor/github.com/go-ole/go-ole/idispatch.go
new file mode 100644
index 000000000..d4af12409
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/idispatch.go
@@ -0,0 +1,94 @@
+package ole
+
+import "unsafe"
+
+type IDispatch struct {
+ IUnknown
+}
+
+type IDispatchVtbl struct {
+ IUnknownVtbl
+ GetTypeInfoCount uintptr
+ GetTypeInfo uintptr
+ GetIDsOfNames uintptr
+ Invoke uintptr
+}
+
+func (v *IDispatch) VTable() *IDispatchVtbl {
+ return (*IDispatchVtbl)(unsafe.Pointer(v.RawVTable))
+}
+
+func (v *IDispatch) GetIDsOfName(names []string) (dispid []int32, err error) {
+ dispid, err = getIDsOfName(v, names)
+ return
+}
+
+func (v *IDispatch) Invoke(dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) {
+ result, err = invoke(v, dispid, dispatch, params...)
+ return
+}
+
+func (v *IDispatch) GetTypeInfoCount() (c uint32, err error) {
+ c, err = getTypeInfoCount(v)
+ return
+}
+
+func (v *IDispatch) GetTypeInfo() (tinfo *ITypeInfo, err error) {
+ tinfo, err = getTypeInfo(v)
+ return
+}
+
+// GetSingleIDOfName is a helper that returns single display ID for IDispatch name.
+//
+// This replaces the common pattern of attempting to get a single name from the list of available
+// IDs. It gives the first ID, if it is available.
+func (v *IDispatch) GetSingleIDOfName(name string) (displayID int32, err error) {
+ var displayIDs []int32
+ displayIDs, err = v.GetIDsOfName([]string{name})
+ if err != nil {
+ return
+ }
+ displayID = displayIDs[0]
+ return
+}
+
+// InvokeWithOptionalArgs accepts arguments as an array, works like Invoke.
+//
+// Accepts name and will attempt to retrieve Display ID to pass to Invoke.
+//
+// Passing params as an array is a workaround that could be fixed in later versions of Go that
+// prevent passing empty params. During testing it was discovered that this is an acceptable way of
+// getting around not being able to pass params normally.
+func (v *IDispatch) InvokeWithOptionalArgs(name string, dispatch int16, params []interface{}) (result *VARIANT, err error) {
+ displayID, err := v.GetSingleIDOfName(name)
+ if err != nil {
+ return
+ }
+
+ if len(params) < 1 {
+ result, err = v.Invoke(displayID, dispatch)
+ } else {
+ result, err = v.Invoke(displayID, dispatch, params...)
+ }
+
+ return
+}
+
+// CallMethod invokes named function with arguments on object.
+func (v *IDispatch) CallMethod(name string, params ...interface{}) (*VARIANT, error) {
+ return v.InvokeWithOptionalArgs(name, DISPATCH_METHOD, params)
+}
+
+// GetProperty retrieves the property with the name with the ability to pass arguments.
+//
+// Most of the time you will not need to pass arguments as most objects do not allow for this
+// feature. Or at least, should not allow for this feature. Some servers don't follow best practices
+// and this is provided for those edge cases.
+func (v *IDispatch) GetProperty(name string, params ...interface{}) (*VARIANT, error) {
+ return v.InvokeWithOptionalArgs(name, DISPATCH_PROPERTYGET, params)
+}
+
+// PutProperty attempts to mutate a property in the object.
+func (v *IDispatch) PutProperty(name string, params ...interface{}) (*VARIANT, error) {
+ return v.InvokeWithOptionalArgs(name, DISPATCH_PROPERTYPUT, params)
+}
diff --git a/vendor/github.com/go-ole/go-ole/idispatch_func.go b/vendor/github.com/go-ole/go-ole/idispatch_func.go
new file mode 100644
index 000000000..b8fbbe319
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/idispatch_func.go
@@ -0,0 +1,19 @@
+// +build !windows
+
+package ole
+
+func getIDsOfName(disp *IDispatch, names []string) ([]int32, error) {
+ return []int32{}, NewError(E_NOTIMPL)
+}
+
+func getTypeInfoCount(disp *IDispatch) (uint32, error) {
+ return uint32(0), NewError(E_NOTIMPL)
+}
+
+func getTypeInfo(disp *IDispatch) (*ITypeInfo, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (*VARIANT, error) {
+ return nil, NewError(E_NOTIMPL)
+}
diff --git a/vendor/github.com/go-ole/go-ole/idispatch_windows.go b/vendor/github.com/go-ole/go-ole/idispatch_windows.go
new file mode 100644
index 000000000..020e4f51b
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/idispatch_windows.go
@@ -0,0 +1,197 @@
+// +build windows
+
+package ole
+
+import (
+ "syscall"
+ "time"
+ "unsafe"
+)
+
+func getIDsOfName(disp *IDispatch, names []string) (dispid []int32, err error) {
+ wnames := make([]*uint16, len(names))
+ for i := 0; i < len(names); i++ {
+ wnames[i] = syscall.StringToUTF16Ptr(names[i])
+ }
+ dispid = make([]int32, len(names))
+ namelen := uint32(len(names))
+ hr, _, _ := syscall.Syscall6(
+ disp.VTable().GetIDsOfNames,
+ 6,
+ uintptr(unsafe.Pointer(disp)),
+ uintptr(unsafe.Pointer(IID_NULL)),
+ uintptr(unsafe.Pointer(&wnames[0])),
+ uintptr(namelen),
+ uintptr(GetUserDefaultLCID()),
+ uintptr(unsafe.Pointer(&dispid[0])))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+func getTypeInfoCount(disp *IDispatch) (c uint32, err error) {
+ hr, _, _ := syscall.Syscall(
+ disp.VTable().GetTypeInfoCount,
+ 2,
+ uintptr(unsafe.Pointer(disp)),
+ uintptr(unsafe.Pointer(&c)),
+ 0)
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+func getTypeInfo(disp *IDispatch) (tinfo *ITypeInfo, err error) {
+ hr, _, _ := syscall.Syscall(
+ disp.VTable().GetTypeInfo,
+ 3,
+ uintptr(unsafe.Pointer(disp)),
+ uintptr(GetUserDefaultLCID()),
+ uintptr(unsafe.Pointer(&tinfo)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) {
+ var dispparams DISPPARAMS
+
+ if dispatch&DISPATCH_PROPERTYPUT != 0 {
+ dispnames := [1]int32{DISPID_PROPERTYPUT}
+ dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0]))
+ dispparams.cNamedArgs = 1
+ } else if dispatch&DISPATCH_PROPERTYPUTREF != 0 {
+ dispnames := [1]int32{DISPID_PROPERTYPUT}
+ dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0]))
+ dispparams.cNamedArgs = 1
+ }
+ var vargs []VARIANT
+ if len(params) > 0 {
+ vargs = make([]VARIANT, len(params))
+ for i, v := range params {
+ //n := len(params)-i-1
+ n := len(params) - i - 1
+ VariantInit(&vargs[n])
+ switch vv := v.(type) {
+ case bool:
+ if vv {
+ vargs[n] = NewVariant(VT_BOOL, 0xffff)
+ } else {
+ vargs[n] = NewVariant(VT_BOOL, 0)
+ }
+ case *bool:
+ vargs[n] = NewVariant(VT_BOOL|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*bool)))))
+ case uint8:
+ vargs[n] = NewVariant(VT_I1, int64(v.(uint8)))
+ case *uint8:
+ vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint8)))))
+ case int8:
+ vargs[n] = NewVariant(VT_I1, int64(v.(int8)))
+ case *int8:
+ vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint8)))))
+ case int16:
+ vargs[n] = NewVariant(VT_I2, int64(v.(int16)))
+ case *int16:
+ vargs[n] = NewVariant(VT_I2|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int16)))))
+ case uint16:
+ vargs[n] = NewVariant(VT_UI2, int64(v.(uint16)))
+ case *uint16:
+ vargs[n] = NewVariant(VT_UI2|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint16)))))
+ case int32:
+ vargs[n] = NewVariant(VT_I4, int64(v.(int32)))
+ case *int32:
+ vargs[n] = NewVariant(VT_I4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int32)))))
+ case uint32:
+ vargs[n] = NewVariant(VT_UI4, int64(v.(uint32)))
+ case *uint32:
+ vargs[n] = NewVariant(VT_UI4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint32)))))
+ case int64:
+ vargs[n] = NewVariant(VT_I8, int64(v.(int64)))
+ case *int64:
+ vargs[n] = NewVariant(VT_I8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int64)))))
+ case uint64:
+ vargs[n] = NewVariant(VT_UI8, int64(uintptr(v.(uint64))))
+ case *uint64:
+ vargs[n] = NewVariant(VT_UI8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint64)))))
+ case int:
+ vargs[n] = NewVariant(VT_I4, int64(v.(int)))
+ case *int:
+ vargs[n] = NewVariant(VT_I4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int)))))
+ case uint:
+ vargs[n] = NewVariant(VT_UI4, int64(v.(uint)))
+ case *uint:
+ vargs[n] = NewVariant(VT_UI4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint)))))
+ case float32:
+ vargs[n] = NewVariant(VT_R4, *(*int64)(unsafe.Pointer(&vv)))
+ case *float32:
+ vargs[n] = NewVariant(VT_R4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*float32)))))
+ case float64:
+ vargs[n] = NewVariant(VT_R8, *(*int64)(unsafe.Pointer(&vv)))
+ case *float64:
+ vargs[n] = NewVariant(VT_R8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*float64)))))
+ case string:
+ vargs[n] = NewVariant(VT_BSTR, int64(uintptr(unsafe.Pointer(SysAllocStringLen(v.(string))))))
+ case *string:
+ vargs[n] = NewVariant(VT_BSTR|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*string)))))
+ case time.Time:
+ s := vv.Format("2006-01-02 15:04:05")
+ vargs[n] = NewVariant(VT_BSTR, int64(uintptr(unsafe.Pointer(SysAllocStringLen(s)))))
+ case *time.Time:
+ s := vv.Format("2006-01-02 15:04:05")
+ vargs[n] = NewVariant(VT_BSTR|VT_BYREF, int64(uintptr(unsafe.Pointer(&s))))
+ case *IDispatch:
+ vargs[n] = NewVariant(VT_DISPATCH, int64(uintptr(unsafe.Pointer(v.(*IDispatch)))))
+ case **IDispatch:
+ vargs[n] = NewVariant(VT_DISPATCH|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(**IDispatch)))))
+ case nil:
+ vargs[n] = NewVariant(VT_NULL, 0)
+ case *VARIANT:
+ vargs[n] = NewVariant(VT_VARIANT|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*VARIANT)))))
+ case []byte:
+ safeByteArray := safeArrayFromByteSlice(v.([]byte))
+ vargs[n] = NewVariant(VT_ARRAY|VT_UI1, int64(uintptr(unsafe.Pointer(safeByteArray))))
+ defer VariantClear(&vargs[n])
+ case []string:
+ safeByteArray := safeArrayFromStringSlice(v.([]string))
+ vargs[n] = NewVariant(VT_ARRAY|VT_BSTR, int64(uintptr(unsafe.Pointer(safeByteArray))))
+ defer VariantClear(&vargs[n])
+ default:
+ panic("unknown type")
+ }
+ }
+ dispparams.rgvarg = uintptr(unsafe.Pointer(&vargs[0]))
+ dispparams.cArgs = uint32(len(params))
+ }
+
+ result = new(VARIANT)
+ var excepInfo EXCEPINFO
+ VariantInit(result)
+ hr, _, _ := syscall.Syscall9(
+ disp.VTable().Invoke,
+ 9,
+ uintptr(unsafe.Pointer(disp)),
+ uintptr(dispid),
+ uintptr(unsafe.Pointer(IID_NULL)),
+ uintptr(GetUserDefaultLCID()),
+ uintptr(dispatch),
+ uintptr(unsafe.Pointer(&dispparams)),
+ uintptr(unsafe.Pointer(result)),
+ uintptr(unsafe.Pointer(&excepInfo)),
+ 0)
+ if hr != 0 {
+ err = NewErrorWithSubError(hr, BstrToString(excepInfo.bstrDescription), excepInfo)
+ }
+ for i, varg := range vargs {
+ n := len(params) - i - 1
+ if varg.VT == VT_BSTR && varg.Val != 0 {
+ SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val)))))
+ }
+ if varg.VT == (VT_BSTR|VT_BYREF) && varg.Val != 0 {
+ *(params[n].(*string)) = LpOleStrToString(*(**uint16)(unsafe.Pointer(uintptr(varg.Val))))
+ }
+ }
+ return
+}
diff --git a/vendor/github.com/go-ole/go-ole/ienumvariant.go b/vendor/github.com/go-ole/go-ole/ienumvariant.go
new file mode 100644
index 000000000..243389754
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/ienumvariant.go
@@ -0,0 +1,19 @@
+package ole
+
+import "unsafe"
+
+type IEnumVARIANT struct {
+ IUnknown
+}
+
+type IEnumVARIANTVtbl struct {
+ IUnknownVtbl
+ Next uintptr
+ Skip uintptr
+ Reset uintptr
+ Clone uintptr
+}
+
+func (v *IEnumVARIANT) VTable() *IEnumVARIANTVtbl {
+ return (*IEnumVARIANTVtbl)(unsafe.Pointer(v.RawVTable))
+}
diff --git a/vendor/github.com/go-ole/go-ole/ienumvariant_func.go b/vendor/github.com/go-ole/go-ole/ienumvariant_func.go
new file mode 100644
index 000000000..c14848199
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/ienumvariant_func.go
@@ -0,0 +1,19 @@
+// +build !windows
+
+package ole
+
+func (enum *IEnumVARIANT) Clone() (*IEnumVARIANT, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+func (enum *IEnumVARIANT) Reset() error {
+ return NewError(E_NOTIMPL)
+}
+
+func (enum *IEnumVARIANT) Skip(celt uint) error {
+ return NewError(E_NOTIMPL)
+}
+
+func (enum *IEnumVARIANT) Next(celt uint) (VARIANT, uint, error) {
+ return NewVariant(VT_NULL, int64(0)), 0, NewError(E_NOTIMPL)
+}
diff --git a/vendor/github.com/go-ole/go-ole/ienumvariant_windows.go b/vendor/github.com/go-ole/go-ole/ienumvariant_windows.go
new file mode 100644
index 000000000..4781f3b8b
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/ienumvariant_windows.go
@@ -0,0 +1,63 @@
+// +build windows
+
+package ole
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+func (enum *IEnumVARIANT) Clone() (cloned *IEnumVARIANT, err error) {
+ hr, _, _ := syscall.Syscall(
+ enum.VTable().Clone,
+ 2,
+ uintptr(unsafe.Pointer(enum)),
+ uintptr(unsafe.Pointer(&cloned)),
+ 0)
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+func (enum *IEnumVARIANT) Reset() (err error) {
+ hr, _, _ := syscall.Syscall(
+ enum.VTable().Reset,
+ 1,
+ uintptr(unsafe.Pointer(enum)),
+ 0,
+ 0)
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+func (enum *IEnumVARIANT) Skip(celt uint) (err error) {
+ hr, _, _ := syscall.Syscall(
+ enum.VTable().Skip,
+ 2,
+ uintptr(unsafe.Pointer(enum)),
+ uintptr(celt),
+ 0)
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+func (enum *IEnumVARIANT) Next(celt uint) (array VARIANT, length uint, err error) {
+ hr, _, _ := syscall.Syscall6(
+ enum.VTable().Next,
+ 4,
+ uintptr(unsafe.Pointer(enum)),
+ uintptr(celt),
+ uintptr(unsafe.Pointer(&array)),
+ uintptr(unsafe.Pointer(&length)),
+ 0,
+ 0)
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
diff --git a/vendor/github.com/go-ole/go-ole/iinspectable.go b/vendor/github.com/go-ole/go-ole/iinspectable.go
new file mode 100644
index 000000000..f4a19e253
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/iinspectable.go
@@ -0,0 +1,18 @@
+package ole
+
+import "unsafe"
+
+type IInspectable struct {
+ IUnknown
+}
+
+type IInspectableVtbl struct {
+ IUnknownVtbl
+ GetIIds uintptr
+ GetRuntimeClassName uintptr
+ GetTrustLevel uintptr
+}
+
+func (v *IInspectable) VTable() *IInspectableVtbl {
+ return (*IInspectableVtbl)(unsafe.Pointer(v.RawVTable))
+}
diff --git a/vendor/github.com/go-ole/go-ole/iinspectable_func.go b/vendor/github.com/go-ole/go-ole/iinspectable_func.go
new file mode 100644
index 000000000..348829bf0
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/iinspectable_func.go
@@ -0,0 +1,15 @@
+// +build !windows
+
+package ole
+
+func (v *IInspectable) GetIids() ([]*GUID, error) {
+ return []*GUID{}, NewError(E_NOTIMPL)
+}
+
+func (v *IInspectable) GetRuntimeClassName() (string, error) {
+ return "", NewError(E_NOTIMPL)
+}
+
+func (v *IInspectable) GetTrustLevel() (uint32, error) {
+ return uint32(0), NewError(E_NOTIMPL)
+}
diff --git a/vendor/github.com/go-ole/go-ole/iinspectable_windows.go b/vendor/github.com/go-ole/go-ole/iinspectable_windows.go
new file mode 100644
index 000000000..4519a4aa4
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/iinspectable_windows.go
@@ -0,0 +1,72 @@
+// +build windows
+
+package ole
+
+import (
+ "bytes"
+ "encoding/binary"
+ "reflect"
+ "syscall"
+ "unsafe"
+)
+
+func (v *IInspectable) GetIids() (iids []*GUID, err error) {
+ var count uint32
+ var array uintptr
+ hr, _, _ := syscall.Syscall(
+ v.VTable().GetIIds,
+ 3,
+ uintptr(unsafe.Pointer(v)),
+ uintptr(unsafe.Pointer(&count)),
+ uintptr(unsafe.Pointer(&array)))
+ if hr != 0 {
+ err = NewError(hr)
+ return
+ }
+ defer CoTaskMemFree(array)
+
+ iids = make([]*GUID, count)
+ byteCount := count * uint32(unsafe.Sizeof(GUID{}))
+ slicehdr := reflect.SliceHeader{Data: array, Len: int(byteCount), Cap: int(byteCount)}
+ byteSlice := *(*[]byte)(unsafe.Pointer(&slicehdr))
+ reader := bytes.NewReader(byteSlice)
+ for i := range iids {
+ guid := GUID{}
+ err = binary.Read(reader, binary.LittleEndian, &guid)
+ if err != nil {
+ return
+ }
+ iids[i] = &guid
+ }
+ return
+}
+
+func (v *IInspectable) GetRuntimeClassName() (s string, err error) {
+ var hstring HString
+ hr, _, _ := syscall.Syscall(
+ v.VTable().GetRuntimeClassName,
+ 2,
+ uintptr(unsafe.Pointer(v)),
+ uintptr(unsafe.Pointer(&hstring)),
+ 0)
+ if hr != 0 {
+ err = NewError(hr)
+ return
+ }
+ s = hstring.String()
+ DeleteHString(hstring)
+ return
+}
+
+func (v *IInspectable) GetTrustLevel() (level uint32, err error) {
+ hr, _, _ := syscall.Syscall(
+ v.VTable().GetTrustLevel,
+ 2,
+ uintptr(unsafe.Pointer(v)),
+ uintptr(unsafe.Pointer(&level)),
+ 0)
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
diff --git a/vendor/github.com/go-ole/go-ole/iprovideclassinfo.go b/vendor/github.com/go-ole/go-ole/iprovideclassinfo.go
new file mode 100644
index 000000000..25f3a6f24
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/iprovideclassinfo.go
@@ -0,0 +1,21 @@
+package ole
+
+import "unsafe"
+
+type IProvideClassInfo struct {
+ IUnknown
+}
+
+type IProvideClassInfoVtbl struct {
+ IUnknownVtbl
+ GetClassInfo uintptr
+}
+
+func (v *IProvideClassInfo) VTable() *IProvideClassInfoVtbl {
+ return (*IProvideClassInfoVtbl)(unsafe.Pointer(v.RawVTable))
+}
+
+func (v *IProvideClassInfo) GetClassInfo() (cinfo *ITypeInfo, err error) {
+ cinfo, err = getClassInfo(v)
+ return
+}
diff --git a/vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go
new file mode 100644
index 000000000..7e3cb63ea
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go
@@ -0,0 +1,7 @@
+// +build !windows
+
+package ole
+
+func getClassInfo(disp *IProvideClassInfo) (tinfo *ITypeInfo, err error) {
+ return nil, NewError(E_NOTIMPL)
+}
diff --git a/vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go
new file mode 100644
index 000000000..2ad016394
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go
@@ -0,0 +1,21 @@
+// +build windows
+
+package ole
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+func getClassInfo(disp *IProvideClassInfo) (tinfo *ITypeInfo, err error) {
+ hr, _, _ := syscall.Syscall(
+ disp.VTable().GetClassInfo,
+ 2,
+ uintptr(unsafe.Pointer(disp)),
+ uintptr(unsafe.Pointer(&tinfo)),
+ 0)
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
diff --git a/vendor/github.com/go-ole/go-ole/itypeinfo.go b/vendor/github.com/go-ole/go-ole/itypeinfo.go
new file mode 100644
index 000000000..dd3c5e21b
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/itypeinfo.go
@@ -0,0 +1,34 @@
+package ole
+
+import "unsafe"
+
+type ITypeInfo struct {
+ IUnknown
+}
+
+type ITypeInfoVtbl struct {
+ IUnknownVtbl
+ GetTypeAttr uintptr
+ GetTypeComp uintptr
+ GetFuncDesc uintptr
+ GetVarDesc uintptr
+ GetNames uintptr
+ GetRefTypeOfImplType uintptr
+ GetImplTypeFlags uintptr
+ GetIDsOfNames uintptr
+ Invoke uintptr
+ GetDocumentation uintptr
+ GetDllEntry uintptr
+ GetRefTypeInfo uintptr
+ AddressOfMember uintptr
+ CreateInstance uintptr
+ GetMops uintptr
+ GetContainingTypeLib uintptr
+ ReleaseTypeAttr uintptr
+ ReleaseFuncDesc uintptr
+ ReleaseVarDesc uintptr
+}
+
+func (v *ITypeInfo) VTable() *ITypeInfoVtbl {
+ return (*ITypeInfoVtbl)(unsafe.Pointer(v.RawVTable))
+}
diff --git a/vendor/github.com/go-ole/go-ole/itypeinfo_func.go b/vendor/github.com/go-ole/go-ole/itypeinfo_func.go
new file mode 100644
index 000000000..8364a659b
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/itypeinfo_func.go
@@ -0,0 +1,7 @@
+// +build !windows
+
+package ole
+
+func (v *ITypeInfo) GetTypeAttr() (*TYPEATTR, error) {
+ return nil, NewError(E_NOTIMPL)
+}
diff --git a/vendor/github.com/go-ole/go-ole/itypeinfo_windows.go b/vendor/github.com/go-ole/go-ole/itypeinfo_windows.go
new file mode 100644
index 000000000..54782b3da
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/itypeinfo_windows.go
@@ -0,0 +1,21 @@
+// +build windows
+
+package ole
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+func (v *ITypeInfo) GetTypeAttr() (tattr *TYPEATTR, err error) {
+ hr, _, _ := syscall.Syscall(
+ uintptr(v.VTable().GetTypeAttr),
+ 2,
+ uintptr(unsafe.Pointer(v)),
+ uintptr(unsafe.Pointer(&tattr)),
+ 0)
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
diff --git a/vendor/github.com/go-ole/go-ole/iunknown.go b/vendor/github.com/go-ole/go-ole/iunknown.go
new file mode 100644
index 000000000..108f28ea6
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/iunknown.go
@@ -0,0 +1,57 @@
+package ole
+
+import "unsafe"
+
+type IUnknown struct {
+ RawVTable *interface{}
+}
+
+type IUnknownVtbl struct {
+ QueryInterface uintptr
+ AddRef uintptr
+ Release uintptr
+}
+
+type UnknownLike interface {
+ QueryInterface(iid *GUID) (disp *IDispatch, err error)
+ AddRef() int32
+ Release() int32
+}
+
+func (v *IUnknown) VTable() *IUnknownVtbl {
+ return (*IUnknownVtbl)(unsafe.Pointer(v.RawVTable))
+}
+
+func (v *IUnknown) PutQueryInterface(interfaceID *GUID, obj interface{}) error {
+ return reflectQueryInterface(v, v.VTable().QueryInterface, interfaceID, obj)
+}
+
+func (v *IUnknown) IDispatch(interfaceID *GUID) (dispatch *IDispatch, err error) {
+ err = v.PutQueryInterface(interfaceID, &dispatch)
+ return
+}
+
+func (v *IUnknown) IEnumVARIANT(interfaceID *GUID) (enum *IEnumVARIANT, err error) {
+ err = v.PutQueryInterface(interfaceID, &enum)
+ return
+}
+
+func (v *IUnknown) QueryInterface(iid *GUID) (*IDispatch, error) {
+ return queryInterface(v, iid)
+}
+
+func (v *IUnknown) MustQueryInterface(iid *GUID) (disp *IDispatch) {
+ unk, err := queryInterface(v, iid)
+ if err != nil {
+ panic(err)
+ }
+ return unk
+}
+
+func (v *IUnknown) AddRef() int32 {
+ return addRef(v)
+}
+
+func (v *IUnknown) Release() int32 {
+ return release(v)
+}
diff --git a/vendor/github.com/go-ole/go-ole/iunknown_func.go b/vendor/github.com/go-ole/go-ole/iunknown_func.go
new file mode 100644
index 000000000..d0a62cfd7
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/iunknown_func.go
@@ -0,0 +1,19 @@
+// +build !windows
+
+package ole
+
+func reflectQueryInterface(self interface{}, method uintptr, interfaceID *GUID, obj interface{}) (err error) {
+ return NewError(E_NOTIMPL)
+}
+
+func queryInterface(unk *IUnknown, iid *GUID) (disp *IDispatch, err error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+func addRef(unk *IUnknown) int32 {
+ return 0
+}
+
+func release(unk *IUnknown) int32 {
+ return 0
+}
diff --git a/vendor/github.com/go-ole/go-ole/iunknown_windows.go b/vendor/github.com/go-ole/go-ole/iunknown_windows.go
new file mode 100644
index 000000000..ede5bb8c1
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/iunknown_windows.go
@@ -0,0 +1,58 @@
+// +build windows
+
+package ole
+
+import (
+ "reflect"
+ "syscall"
+ "unsafe"
+)
+
+func reflectQueryInterface(self interface{}, method uintptr, interfaceID *GUID, obj interface{}) (err error) {
+ selfValue := reflect.ValueOf(self).Elem()
+ objValue := reflect.ValueOf(obj).Elem()
+
+ hr, _, _ := syscall.Syscall(
+ method,
+ 3,
+ selfValue.UnsafeAddr(),
+ uintptr(unsafe.Pointer(interfaceID)),
+ objValue.Addr().Pointer())
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+func queryInterface(unk *IUnknown, iid *GUID) (disp *IDispatch, err error) {
+ hr, _, _ := syscall.Syscall(
+ unk.VTable().QueryInterface,
+ 3,
+ uintptr(unsafe.Pointer(unk)),
+ uintptr(unsafe.Pointer(iid)),
+ uintptr(unsafe.Pointer(&disp)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+func addRef(unk *IUnknown) int32 {
+ ret, _, _ := syscall.Syscall(
+ unk.VTable().AddRef,
+ 1,
+ uintptr(unsafe.Pointer(unk)),
+ 0,
+ 0)
+ return int32(ret)
+}
+
+func release(unk *IUnknown) int32 {
+ ret, _, _ := syscall.Syscall(
+ unk.VTable().Release,
+ 1,
+ uintptr(unsafe.Pointer(unk)),
+ 0,
+ 0)
+ return int32(ret)
+}
diff --git a/vendor/github.com/go-ole/go-ole/ole.go b/vendor/github.com/go-ole/go-ole/ole.go
new file mode 100644
index 000000000..e2ae4f4bb
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/ole.go
@@ -0,0 +1,157 @@
+package ole
+
+import (
+ "fmt"
+ "strings"
+)
+
+// DISPPARAMS are the arguments that passed to methods or property.
+type DISPPARAMS struct {
+ rgvarg uintptr
+ rgdispidNamedArgs uintptr
+ cArgs uint32
+ cNamedArgs uint32
+}
+
+// EXCEPINFO defines exception info.
+type EXCEPINFO struct {
+ wCode uint16
+ wReserved uint16
+ bstrSource *uint16
+ bstrDescription *uint16
+ bstrHelpFile *uint16
+ dwHelpContext uint32
+ pvReserved uintptr
+ pfnDeferredFillIn uintptr
+ scode uint32
+}
+
+// WCode return wCode in EXCEPINFO.
+func (e EXCEPINFO) WCode() uint16 {
+ return e.wCode
+}
+
+// SCODE return scode in EXCEPINFO.
+func (e EXCEPINFO) SCODE() uint32 {
+ return e.scode
+}
+
+// String convert EXCEPINFO to string.
+func (e EXCEPINFO) String() string {
+ var src, desc, hlp string
+ if e.bstrSource == nil {
+ src = "<nil>"
+ } else {
+ src = BstrToString(e.bstrSource)
+ }
+
+ if e.bstrDescription == nil {
+ desc = "<nil>"
+ } else {
+ desc = BstrToString(e.bstrDescription)
+ }
+
+ if e.bstrHelpFile == nil {
+ hlp = "<nil>"
+ } else {
+ hlp = BstrToString(e.bstrHelpFile)
+ }
+
+ return fmt.Sprintf(
+ "wCode: %#x, bstrSource: %v, bstrDescription: %v, bstrHelpFile: %v, dwHelpContext: %#x, scode: %#x",
+ e.wCode, src, desc, hlp, e.dwHelpContext, e.scode,
+ )
+}
+
+// Error implements error interface and returns error string.
+func (e EXCEPINFO) Error() string {
+ if e.bstrDescription != nil {
+ return strings.TrimSpace(BstrToString(e.bstrDescription))
+ }
+
+ src := "Unknown"
+ if e.bstrSource != nil {
+ src = BstrToString(e.bstrSource)
+ }
+
+ code := e.scode
+ if e.wCode != 0 {
+ code = uint32(e.wCode)
+ }
+
+ return fmt.Sprintf("%v: %#x", src, code)
+}
+
+// PARAMDATA defines parameter data type.
+type PARAMDATA struct {
+ Name *int16
+ Vt uint16
+}
+
+// METHODDATA defines method info.
+type METHODDATA struct {
+ Name *uint16
+ Data *PARAMDATA
+ Dispid int32
+ Meth uint32
+ CC int32
+ CArgs uint32
+ Flags uint16
+ VtReturn uint32
+}
+
+// INTERFACEDATA defines interface info.
+type INTERFACEDATA struct {
+ MethodData *METHODDATA
+ CMembers uint32
+}
+
+// Point is 2D vector type.
+type Point struct {
+ X int32
+ Y int32
+}
+
+// Msg is message between processes.
+type Msg struct {
+ Hwnd uint32
+ Message uint32
+ Wparam int32
+ Lparam int32
+ Time uint32
+ Pt Point
+}
+
+// TYPEDESC defines data type.
+type TYPEDESC struct {
+ Hreftype uint32
+ VT uint16
+}
+
+// IDLDESC defines IDL info.
+type IDLDESC struct {
+ DwReserved uint32
+ WIDLFlags uint16
+}
+
+// TYPEATTR defines type info.
+type TYPEATTR struct {
+ Guid GUID
+ Lcid uint32
+ dwReserved uint32
+ MemidConstructor int32
+ MemidDestructor int32
+ LpstrSchema *uint16
+ CbSizeInstance uint32
+ Typekind int32
+ CFuncs uint16
+ CVars uint16
+ CImplTypes uint16
+ CbSizeVft uint16
+ CbAlignment uint16
+ WTypeFlags uint16
+ WMajorVerNum uint16
+ WMinorVerNum uint16
+ TdescAlias TYPEDESC
+ IdldescType IDLDESC
+}
diff --git a/vendor/github.com/go-ole/go-ole/oleutil/connection.go b/vendor/github.com/go-ole/go-ole/oleutil/connection.go
new file mode 100644
index 000000000..60df73cda
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/oleutil/connection.go
@@ -0,0 +1,100 @@
+// +build windows
+
+package oleutil
+
+import (
+ "reflect"
+ "unsafe"
+
+ ole "github.com/go-ole/go-ole"
+)
+
+type stdDispatch struct {
+ lpVtbl *stdDispatchVtbl
+ ref int32
+ iid *ole.GUID
+ iface interface{}
+ funcMap map[string]int32
+}
+
+type stdDispatchVtbl struct {
+ pQueryInterface uintptr
+ pAddRef uintptr
+ pRelease uintptr
+ pGetTypeInfoCount uintptr
+ pGetTypeInfo uintptr
+ pGetIDsOfNames uintptr
+ pInvoke uintptr
+}
+
+func dispQueryInterface(this *ole.IUnknown, iid *ole.GUID, punk **ole.IUnknown) uint32 {
+ pthis := (*stdDispatch)(unsafe.Pointer(this))
+ *punk = nil
+ if ole.IsEqualGUID(iid, ole.IID_IUnknown) ||
+ ole.IsEqualGUID(iid, ole.IID_IDispatch) {
+ dispAddRef(this)
+ *punk = this
+ return ole.S_OK
+ }
+ if ole.IsEqualGUID(iid, pthis.iid) {
+ dispAddRef(this)
+ *punk = this
+ return ole.S_OK
+ }
+ return ole.E_NOINTERFACE
+}
+
+func dispAddRef(this *ole.IUnknown) int32 {
+ pthis := (*stdDispatch)(unsafe.Pointer(this))
+ pthis.ref++
+ return pthis.ref
+}
+
+func dispRelease(this *ole.IUnknown) int32 {
+ pthis := (*stdDispatch)(unsafe.Pointer(this))
+ pthis.ref--
+ return pthis.ref
+}
+
+func dispGetIDsOfNames(this *ole.IUnknown, iid *ole.GUID, wnames []*uint16, namelen int, lcid int, pdisp []int32) uintptr {
+ pthis := (*stdDispatch)(unsafe.Pointer(this))
+ names := make([]string, len(wnames))
+ for i := 0; i < len(names); i++ {
+ names[i] = ole.LpOleStrToString(wnames[i])
+ }
+ for n := 0; n < namelen; n++ {
+ if id, ok := pthis.funcMap[names[n]]; ok {
+ pdisp[n] = id
+ }
+ }
+ return ole.S_OK
+}
+
+func dispGetTypeInfoCount(pcount *int) uintptr {
+ if pcount != nil {
+ *pcount = 0
+ }
+ return ole.S_OK
+}
+
+func dispGetTypeInfo(ptypeif *uintptr) uintptr {
+ return ole.E_NOTIMPL
+}
+
+func dispInvoke(this *ole.IDispatch, dispid int32, riid *ole.GUID, lcid int, flags int16, dispparams *ole.DISPPARAMS, result *ole.VARIANT, pexcepinfo *ole.EXCEPINFO, nerr *uint) uintptr {
+ pthis := (*stdDispatch)(unsafe.Pointer(this))
+ found := ""
+ for name, id := range pthis.funcMap {
+ if id == dispid {
+ found = name
+ }
+ }
+ if found != "" {
+ rv := reflect.ValueOf(pthis.iface).Elem()
+ rm := rv.MethodByName(found)
+ rr := rm.Call([]reflect.Value{})
+ println(len(rr))
+ return ole.S_OK
+ }
+ return ole.E_NOTIMPL
+}
diff --git a/vendor/github.com/go-ole/go-ole/oleutil/connection_func.go b/vendor/github.com/go-ole/go-ole/oleutil/connection_func.go
new file mode 100644
index 000000000..8818fb827
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/oleutil/connection_func.go
@@ -0,0 +1,10 @@
+// +build !windows
+
+package oleutil
+
+import ole "github.com/go-ole/go-ole"
+
+// ConnectObject creates a connection point between two services for communication.
+func ConnectObject(disp *ole.IDispatch, iid *ole.GUID, idisp interface{}) (uint32, error) {
+ return 0, ole.NewError(ole.E_NOTIMPL)
+}
diff --git a/vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go b/vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go
new file mode 100644
index 000000000..ab9c0d8dc
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go
@@ -0,0 +1,58 @@
+// +build windows
+
+package oleutil
+
+import (
+ "reflect"
+ "syscall"
+ "unsafe"
+
+ ole "github.com/go-ole/go-ole"
+)
+
+// ConnectObject creates a connection point between two services for communication.
+func ConnectObject(disp *ole.IDispatch, iid *ole.GUID, idisp interface{}) (cookie uint32, err error) {
+ unknown, err := disp.QueryInterface(ole.IID_IConnectionPointContainer)
+ if err != nil {
+ return
+ }
+
+ container := (*ole.IConnectionPointContainer)(unsafe.Pointer(unknown))
+ var point *ole.IConnectionPoint
+ err = container.FindConnectionPoint(iid, &point)
+ if err != nil {
+ return
+ }
+ if edisp, ok := idisp.(*ole.IUnknown); ok {
+ cookie, err = point.Advise(edisp)
+ container.Release()
+ if err != nil {
+ return
+ }
+ }
+ rv := reflect.ValueOf(disp).Elem()
+ if rv.Type().Kind() == reflect.Struct {
+ dest := &stdDispatch{}
+ dest.lpVtbl = &stdDispatchVtbl{}
+ dest.lpVtbl.pQueryInterface = syscall.NewCallback(dispQueryInterface)
+ dest.lpVtbl.pAddRef = syscall.NewCallback(dispAddRef)
+ dest.lpVtbl.pRelease = syscall.NewCallback(dispRelease)
+ dest.lpVtbl.pGetTypeInfoCount = syscall.NewCallback(dispGetTypeInfoCount)
+ dest.lpVtbl.pGetTypeInfo = syscall.NewCallback(dispGetTypeInfo)
+ dest.lpVtbl.pGetIDsOfNames = syscall.NewCallback(dispGetIDsOfNames)
+ dest.lpVtbl.pInvoke = syscall.NewCallback(dispInvoke)
+ dest.iface = disp
+ dest.iid = iid
+ cookie, err = point.Advise((*ole.IUnknown)(unsafe.Pointer(dest)))
+ container.Release()
+ if err != nil {
+ point.Release()
+ return
+ }
+ return
+ }
+
+ container.Release()
+
+ return 0, ole.NewError(ole.E_INVALIDARG)
+}
diff --git a/vendor/github.com/go-ole/go-ole/oleutil/go-get.go b/vendor/github.com/go-ole/go-ole/oleutil/go-get.go
new file mode 100644
index 000000000..58347628f
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/oleutil/go-get.go
@@ -0,0 +1,6 @@
+// This file is here so go get succeeds as without it errors with:
+// no buildable Go source files in ...
+//
+// +build !windows
+
+package oleutil
diff --git a/vendor/github.com/go-ole/go-ole/oleutil/oleutil.go b/vendor/github.com/go-ole/go-ole/oleutil/oleutil.go
new file mode 100644
index 000000000..f7803c1e3
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/oleutil/oleutil.go
@@ -0,0 +1,127 @@
+package oleutil
+
+import ole "github.com/go-ole/go-ole"
+
+// ClassIDFrom retrieves class ID whether given is program ID or application string.
+func ClassIDFrom(programID string) (classID *ole.GUID, err error) {
+ return ole.ClassIDFrom(programID)
+}
+
+// CreateObject creates object from programID based on interface type.
+//
+// Only supports IUnknown.
+//
+// Program ID can be either program ID or application string.
+func CreateObject(programID string) (unknown *ole.IUnknown, err error) {
+ classID, err := ole.ClassIDFrom(programID)
+ if err != nil {
+ return
+ }
+
+ unknown, err = ole.CreateInstance(classID, ole.IID_IUnknown)
+ if err != nil {
+ return
+ }
+
+ return
+}
+
+// GetActiveObject retrieves active object for program ID and interface ID based
+// on interface type.
+//
+// Only supports IUnknown.
+//
+// Program ID can be either program ID or application string.
+func GetActiveObject(programID string) (unknown *ole.IUnknown, err error) {
+ classID, err := ole.ClassIDFrom(programID)
+ if err != nil {
+ return
+ }
+
+ unknown, err = ole.GetActiveObject(classID, ole.IID_IUnknown)
+ if err != nil {
+ return
+ }
+
+ return
+}
+
+// CallMethod calls method on IDispatch with parameters.
+func CallMethod(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) {
+ return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_METHOD, params)
+}
+
+// MustCallMethod calls method on IDispatch with parameters or panics.
+func MustCallMethod(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) {
+ r, err := CallMethod(disp, name, params...)
+ if err != nil {
+ panic(err.Error())
+ }
+ return r
+}
+
+// GetProperty retrieves property from IDispatch.
+func GetProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) {
+ return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_PROPERTYGET, params)
+}
+
+// MustGetProperty retrieves property from IDispatch or panics.
+func MustGetProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) {
+ r, err := GetProperty(disp, name, params...)
+ if err != nil {
+ panic(err.Error())
+ }
+ return r
+}
+
+// PutProperty mutates property.
+func PutProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) {
+ return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_PROPERTYPUT, params)
+}
+
+// MustPutProperty mutates property or panics.
+func MustPutProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) {
+ r, err := PutProperty(disp, name, params...)
+ if err != nil {
+ panic(err.Error())
+ }
+ return r
+}
+
+// PutPropertyRef mutates property reference.
+func PutPropertyRef(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) {
+ return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_PROPERTYPUTREF, params)
+}
+
+// MustPutPropertyRef mutates property reference or panics.
+func MustPutPropertyRef(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) {
+ r, err := PutPropertyRef(disp, name, params...)
+ if err != nil {
+ panic(err.Error())
+ }
+ return r
+}
+
+func ForEach(disp *ole.IDispatch, f func(v *ole.VARIANT) error) error {
+ newEnum, err := disp.GetProperty("_NewEnum")
+ if err != nil {
+ return err
+ }
+ defer newEnum.Clear()
+
+ enum, err := newEnum.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant)
+ if err != nil {
+ return err
+ }
+ defer enum.Release()
+
+ for item, length, err := enum.Next(1); length > 0; item, length, err = enum.Next(1) {
+ if err != nil {
+ return err
+ }
+ if ferr := f(&item); ferr != nil {
+ return ferr
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/go-ole/go-ole/safearray.go b/vendor/github.com/go-ole/go-ole/safearray.go
new file mode 100644
index 000000000..a5201b56c
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/safearray.go
@@ -0,0 +1,27 @@
+// Package is meant to retrieve and process safe array data returned from COM.
+
+package ole
+
+// SafeArrayBound defines the SafeArray boundaries.
+type SafeArrayBound struct {
+ Elements uint32
+ LowerBound int32
+}
+
+// SafeArray is how COM handles arrays.
+type SafeArray struct {
+ Dimensions uint16
+ FeaturesFlag uint16
+ ElementsSize uint32
+ LocksAmount uint32
+ Data uint32
+ Bounds [16]byte
+}
+
+// SAFEARRAY is obsolete, exists for backwards compatibility.
+// Use SafeArray
+type SAFEARRAY SafeArray
+
+// SAFEARRAYBOUND is obsolete, exists for backwards compatibility.
+// Use SafeArrayBound
+type SAFEARRAYBOUND SafeArrayBound
diff --git a/vendor/github.com/go-ole/go-ole/safearray_func.go b/vendor/github.com/go-ole/go-ole/safearray_func.go
new file mode 100644
index 000000000..8ff0baa41
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/safearray_func.go
@@ -0,0 +1,211 @@
+// +build !windows
+
+package ole
+
+import (
+ "unsafe"
+)
+
+// safeArrayAccessData returns raw array pointer.
+//
+// AKA: SafeArrayAccessData in Windows API.
+func safeArrayAccessData(safearray *SafeArray) (uintptr, error) {
+ return uintptr(0), NewError(E_NOTIMPL)
+}
+
+// safeArrayUnaccessData releases raw array.
+//
+// AKA: SafeArrayUnaccessData in Windows API.
+func safeArrayUnaccessData(safearray *SafeArray) error {
+ return NewError(E_NOTIMPL)
+}
+
+// safeArrayAllocData allocates SafeArray.
+//
+// AKA: SafeArrayAllocData in Windows API.
+func safeArrayAllocData(safearray *SafeArray) error {
+ return NewError(E_NOTIMPL)
+}
+
+// safeArrayAllocDescriptor allocates SafeArray.
+//
+// AKA: SafeArrayAllocDescriptor in Windows API.
+func safeArrayAllocDescriptor(dimensions uint32) (*SafeArray, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// safeArrayAllocDescriptorEx allocates SafeArray.
+//
+// AKA: SafeArrayAllocDescriptorEx in Windows API.
+func safeArrayAllocDescriptorEx(variantType VT, dimensions uint32) (*SafeArray, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// safeArrayCopy returns copy of SafeArray.
+//
+// AKA: SafeArrayCopy in Windows API.
+func safeArrayCopy(original *SafeArray) (*SafeArray, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// safeArrayCopyData duplicates SafeArray into another SafeArray object.
+//
+// AKA: SafeArrayCopyData in Windows API.
+func safeArrayCopyData(original *SafeArray, duplicate *SafeArray) error {
+ return NewError(E_NOTIMPL)
+}
+
+// safeArrayCreate creates SafeArray.
+//
+// AKA: SafeArrayCreate in Windows API.
+func safeArrayCreate(variantType VT, dimensions uint32, bounds *SafeArrayBound) (*SafeArray, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// safeArrayCreateEx creates SafeArray.
+//
+// AKA: SafeArrayCreateEx in Windows API.
+func safeArrayCreateEx(variantType VT, dimensions uint32, bounds *SafeArrayBound, extra uintptr) (*SafeArray, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// safeArrayCreateVector creates SafeArray.
+//
+// AKA: SafeArrayCreateVector in Windows API.
+func safeArrayCreateVector(variantType VT, lowerBound int32, length uint32) (*SafeArray, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// safeArrayCreateVectorEx creates SafeArray.
+//
+// AKA: SafeArrayCreateVectorEx in Windows API.
+func safeArrayCreateVectorEx(variantType VT, lowerBound int32, length uint32, extra uintptr) (*SafeArray, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// safeArrayDestroy destroys SafeArray object.
+//
+// AKA: SafeArrayDestroy in Windows API.
+func safeArrayDestroy(safearray *SafeArray) error {
+ return NewError(E_NOTIMPL)
+}
+
+// safeArrayDestroyData destroys SafeArray object.
+//
+// AKA: SafeArrayDestroyData in Windows API.
+func safeArrayDestroyData(safearray *SafeArray) error {
+ return NewError(E_NOTIMPL)
+}
+
+// safeArrayDestroyDescriptor destroys SafeArray object.
+//
+// AKA: SafeArrayDestroyDescriptor in Windows API.
+func safeArrayDestroyDescriptor(safearray *SafeArray) error {
+ return NewError(E_NOTIMPL)
+}
+
+// safeArrayGetDim is the amount of dimensions in the SafeArray.
+//
+// SafeArrays may have multiple dimensions. Meaning, it could be
+// multidimensional array.
+//
+// AKA: SafeArrayGetDim in Windows API.
+func safeArrayGetDim(safearray *SafeArray) (*uint32, error) {
+ u := uint32(0)
+ return &u, NewError(E_NOTIMPL)
+}
+
+// safeArrayGetElementSize is the element size in bytes.
+//
+// AKA: SafeArrayGetElemsize in Windows API.
+func safeArrayGetElementSize(safearray *SafeArray) (*uint32, error) {
+ u := uint32(0)
+ return &u, NewError(E_NOTIMPL)
+}
+
+// safeArrayGetElement retrieves element at given index.
+func safeArrayGetElement(safearray *SafeArray, index int64, pv unsafe.Pointer) error {
+ return NewError(E_NOTIMPL)
+}
+
+// safeArrayGetElement retrieves element at given index and converts to string.
+func safeArrayGetElementString(safearray *SafeArray, index int64) (string, error) {
+ return "", NewError(E_NOTIMPL)
+}
+
+// safeArrayGetIID is the InterfaceID of the elements in the SafeArray.
+//
+// AKA: SafeArrayGetIID in Windows API.
+func safeArrayGetIID(safearray *SafeArray) (*GUID, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// safeArrayGetLBound returns lower bounds of SafeArray.
+//
+// SafeArrays may have multiple dimensions. Meaning, it could be
+// multidimensional array.
+//
+// AKA: SafeArrayGetLBound in Windows API.
+func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (int64, error) {
+ return int64(0), NewError(E_NOTIMPL)
+}
+
+// safeArrayGetUBound returns upper bounds of SafeArray.
+//
+// SafeArrays may have multiple dimensions. Meaning, it could be
+// multidimensional array.
+//
+// AKA: SafeArrayGetUBound in Windows API.
+func safeArrayGetUBound(safearray *SafeArray, dimension uint32) (int64, error) {
+ return int64(0), NewError(E_NOTIMPL)
+}
+
+// safeArrayGetVartype returns data type of SafeArray.
+//
+// AKA: SafeArrayGetVartype in Windows API.
+func safeArrayGetVartype(safearray *SafeArray) (uint16, error) {
+ return uint16(0), NewError(E_NOTIMPL)
+}
+
+// safeArrayLock locks SafeArray for reading to modify SafeArray.
+//
+// This must be called during some calls to ensure that another process does not
+// read or write to the SafeArray during editing.
+//
+// AKA: SafeArrayLock in Windows API.
+func safeArrayLock(safearray *SafeArray) error {
+ return NewError(E_NOTIMPL)
+}
+
+// safeArrayUnlock unlocks SafeArray for reading.
+//
+// AKA: SafeArrayUnlock in Windows API.
+func safeArrayUnlock(safearray *SafeArray) error {
+ return NewError(E_NOTIMPL)
+}
+
+// safeArrayPutElement stores the data element at the specified location in the
+// array.
+//
+// AKA: SafeArrayPutElement in Windows API.
+func safeArrayPutElement(safearray *SafeArray, index int64, element uintptr) error {
+ return NewError(E_NOTIMPL)
+}
+
+// safeArrayGetRecordInfo accesses IRecordInfo info for custom types.
+//
+// AKA: SafeArrayGetRecordInfo in Windows API.
+//
+// XXX: Must implement IRecordInfo interface for this to return.
+func safeArrayGetRecordInfo(safearray *SafeArray) (interface{}, error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// safeArraySetRecordInfo mutates IRecordInfo info for custom types.
+//
+// AKA: SafeArraySetRecordInfo in Windows API.
+//
+// XXX: Must implement IRecordInfo interface for this to return.
+func safeArraySetRecordInfo(safearray *SafeArray, recordInfo interface{}) error {
+ return NewError(E_NOTIMPL)
+}
diff --git a/vendor/github.com/go-ole/go-ole/safearray_windows.go b/vendor/github.com/go-ole/go-ole/safearray_windows.go
new file mode 100644
index 000000000..b27936e24
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/safearray_windows.go
@@ -0,0 +1,337 @@
+// +build windows
+
+package ole
+
+import (
+ "unsafe"
+)
+
+var (
+ procSafeArrayAccessData, _ = modoleaut32.FindProc("SafeArrayAccessData")
+ procSafeArrayAllocData, _ = modoleaut32.FindProc("SafeArrayAllocData")
+ procSafeArrayAllocDescriptor, _ = modoleaut32.FindProc("SafeArrayAllocDescriptor")
+ procSafeArrayAllocDescriptorEx, _ = modoleaut32.FindProc("SafeArrayAllocDescriptorEx")
+ procSafeArrayCopy, _ = modoleaut32.FindProc("SafeArrayCopy")
+ procSafeArrayCopyData, _ = modoleaut32.FindProc("SafeArrayCopyData")
+ procSafeArrayCreate, _ = modoleaut32.FindProc("SafeArrayCreate")
+ procSafeArrayCreateEx, _ = modoleaut32.FindProc("SafeArrayCreateEx")
+ procSafeArrayCreateVector, _ = modoleaut32.FindProc("SafeArrayCreateVector")
+ procSafeArrayCreateVectorEx, _ = modoleaut32.FindProc("SafeArrayCreateVectorEx")
+ procSafeArrayDestroy, _ = modoleaut32.FindProc("SafeArrayDestroy")
+ procSafeArrayDestroyData, _ = modoleaut32.FindProc("SafeArrayDestroyData")
+ procSafeArrayDestroyDescriptor, _ = modoleaut32.FindProc("SafeArrayDestroyDescriptor")
+ procSafeArrayGetDim, _ = modoleaut32.FindProc("SafeArrayGetDim")
+ procSafeArrayGetElement, _ = modoleaut32.FindProc("SafeArrayGetElement")
+ procSafeArrayGetElemsize, _ = modoleaut32.FindProc("SafeArrayGetElemsize")
+ procSafeArrayGetIID, _ = modoleaut32.FindProc("SafeArrayGetIID")
+ procSafeArrayGetLBound, _ = modoleaut32.FindProc("SafeArrayGetLBound")
+ procSafeArrayGetUBound, _ = modoleaut32.FindProc("SafeArrayGetUBound")
+ procSafeArrayGetVartype, _ = modoleaut32.FindProc("SafeArrayGetVartype")
+ procSafeArrayLock, _ = modoleaut32.FindProc("SafeArrayLock")
+ procSafeArrayPtrOfIndex, _ = modoleaut32.FindProc("SafeArrayPtrOfIndex")
+ procSafeArrayUnaccessData, _ = modoleaut32.FindProc("SafeArrayUnaccessData")
+ procSafeArrayUnlock, _ = modoleaut32.FindProc("SafeArrayUnlock")
+ procSafeArrayPutElement, _ = modoleaut32.FindProc("SafeArrayPutElement")
+ //procSafeArrayRedim, _ = modoleaut32.FindProc("SafeArrayRedim") // TODO
+ //procSafeArraySetIID, _ = modoleaut32.FindProc("SafeArraySetIID") // TODO
+ procSafeArrayGetRecordInfo, _ = modoleaut32.FindProc("SafeArrayGetRecordInfo")
+ procSafeArraySetRecordInfo, _ = modoleaut32.FindProc("SafeArraySetRecordInfo")
+)
+
+// safeArrayAccessData returns raw array pointer.
+//
+// AKA: SafeArrayAccessData in Windows API.
+// Todo: Test
+func safeArrayAccessData(safearray *SafeArray) (element uintptr, err error) {
+ err = convertHresultToError(
+ procSafeArrayAccessData.Call(
+ uintptr(unsafe.Pointer(safearray)),
+ uintptr(unsafe.Pointer(&element))))
+ return
+}
+
+// safeArrayUnaccessData releases raw array.
+//
+// AKA: SafeArrayUnaccessData in Windows API.
+func safeArrayUnaccessData(safearray *SafeArray) (err error) {
+ err = convertHresultToError(procSafeArrayUnaccessData.Call(uintptr(unsafe.Pointer(safearray))))
+ return
+}
+
+// safeArrayAllocData allocates SafeArray.
+//
+// AKA: SafeArrayAllocData in Windows API.
+func safeArrayAllocData(safearray *SafeArray) (err error) {
+ err = convertHresultToError(procSafeArrayAllocData.Call(uintptr(unsafe.Pointer(safearray))))
+ return
+}
+
+// safeArrayAllocDescriptor allocates SafeArray.
+//
+// AKA: SafeArrayAllocDescriptor in Windows API.
+func safeArrayAllocDescriptor(dimensions uint32) (safearray *SafeArray, err error) {
+ err = convertHresultToError(
+ procSafeArrayAllocDescriptor.Call(uintptr(dimensions), uintptr(unsafe.Pointer(&safearray))))
+ return
+}
+
+// safeArrayAllocDescriptorEx allocates SafeArray.
+//
+// AKA: SafeArrayAllocDescriptorEx in Windows API.
+func safeArrayAllocDescriptorEx(variantType VT, dimensions uint32) (safearray *SafeArray, err error) {
+ err = convertHresultToError(
+ procSafeArrayAllocDescriptorEx.Call(
+ uintptr(variantType),
+ uintptr(dimensions),
+ uintptr(unsafe.Pointer(&safearray))))
+ return
+}
+
+// safeArrayCopy returns copy of SafeArray.
+//
+// AKA: SafeArrayCopy in Windows API.
+func safeArrayCopy(original *SafeArray) (safearray *SafeArray, err error) {
+ err = convertHresultToError(
+ procSafeArrayCopy.Call(
+ uintptr(unsafe.Pointer(original)),
+ uintptr(unsafe.Pointer(&safearray))))
+ return
+}
+
+// safeArrayCopyData duplicates SafeArray into another SafeArray object.
+//
+// AKA: SafeArrayCopyData in Windows API.
+func safeArrayCopyData(original *SafeArray, duplicate *SafeArray) (err error) {
+ err = convertHresultToError(
+ procSafeArrayCopyData.Call(
+ uintptr(unsafe.Pointer(original)),
+ uintptr(unsafe.Pointer(duplicate))))
+ return
+}
+
+// safeArrayCreate creates SafeArray.
+//
+// AKA: SafeArrayCreate in Windows API.
+func safeArrayCreate(variantType VT, dimensions uint32, bounds *SafeArrayBound) (safearray *SafeArray, err error) {
+ sa, _, err := procSafeArrayCreate.Call(
+ uintptr(variantType),
+ uintptr(dimensions),
+ uintptr(unsafe.Pointer(bounds)))
+ safearray = (*SafeArray)(unsafe.Pointer(&sa))
+ return
+}
+
+// safeArrayCreateEx creates SafeArray.
+//
+// AKA: SafeArrayCreateEx in Windows API.
+func safeArrayCreateEx(variantType VT, dimensions uint32, bounds *SafeArrayBound, extra uintptr) (safearray *SafeArray, err error) {
+ sa, _, err := procSafeArrayCreateEx.Call(
+ uintptr(variantType),
+ uintptr(dimensions),
+ uintptr(unsafe.Pointer(bounds)),
+ extra)
+ safearray = (*SafeArray)(unsafe.Pointer(sa))
+ return
+}
+
+// safeArrayCreateVector creates SafeArray.
+//
+// AKA: SafeArrayCreateVector in Windows API.
+func safeArrayCreateVector(variantType VT, lowerBound int32, length uint32) (safearray *SafeArray, err error) {
+ sa, _, err := procSafeArrayCreateVector.Call(
+ uintptr(variantType),
+ uintptr(lowerBound),
+ uintptr(length))
+ safearray = (*SafeArray)(unsafe.Pointer(sa))
+ return
+}
+
+// safeArrayCreateVectorEx creates SafeArray.
+//
+// AKA: SafeArrayCreateVectorEx in Windows API.
+func safeArrayCreateVectorEx(variantType VT, lowerBound int32, length uint32, extra uintptr) (safearray *SafeArray, err error) {
+ sa, _, err := procSafeArrayCreateVectorEx.Call(
+ uintptr(variantType),
+ uintptr(lowerBound),
+ uintptr(length),
+ extra)
+ safearray = (*SafeArray)(unsafe.Pointer(sa))
+ return
+}
+
+// safeArrayDestroy destroys SafeArray object.
+//
+// AKA: SafeArrayDestroy in Windows API.
+func safeArrayDestroy(safearray *SafeArray) (err error) {
+ err = convertHresultToError(procSafeArrayDestroy.Call(uintptr(unsafe.Pointer(safearray))))
+ return
+}
+
+// safeArrayDestroyData destroys SafeArray object.
+//
+// AKA: SafeArrayDestroyData in Windows API.
+func safeArrayDestroyData(safearray *SafeArray) (err error) {
+ err = convertHresultToError(procSafeArrayDestroyData.Call(uintptr(unsafe.Pointer(safearray))))
+ return
+}
+
+// safeArrayDestroyDescriptor destroys SafeArray object.
+//
+// AKA: SafeArrayDestroyDescriptor in Windows API.
+func safeArrayDestroyDescriptor(safearray *SafeArray) (err error) {
+ err = convertHresultToError(procSafeArrayDestroyDescriptor.Call(uintptr(unsafe.Pointer(safearray))))
+ return
+}
+
+// safeArrayGetDim is the amount of dimensions in the SafeArray.
+//
+// SafeArrays may have multiple dimensions. Meaning, it could be
+// multidimensional array.
+//
+// AKA: SafeArrayGetDim in Windows API.
+func safeArrayGetDim(safearray *SafeArray) (dimensions *uint32, err error) {
+ l, _, err := procSafeArrayGetDim.Call(uintptr(unsafe.Pointer(safearray)))
+ dimensions = (*uint32)(unsafe.Pointer(l))
+ return
+}
+
+// safeArrayGetElementSize is the element size in bytes.
+//
+// AKA: SafeArrayGetElemsize in Windows API.
+func safeArrayGetElementSize(safearray *SafeArray) (length *uint32, err error) {
+ l, _, err := procSafeArrayGetElemsize.Call(uintptr(unsafe.Pointer(safearray)))
+ length = (*uint32)(unsafe.Pointer(l))
+ return
+}
+
+// safeArrayGetElement retrieves element at given index.
+func safeArrayGetElement(safearray *SafeArray, index int64, pv unsafe.Pointer) error {
+ return convertHresultToError(
+ procSafeArrayGetElement.Call(
+ uintptr(unsafe.Pointer(safearray)),
+ uintptr(unsafe.Pointer(&index)),
+ uintptr(pv)))
+}
+
+// safeArrayGetElementString retrieves element at given index and converts to string.
+func safeArrayGetElementString(safearray *SafeArray, index int64) (str string, err error) {
+ var element *int16
+ err = convertHresultToError(
+ procSafeArrayGetElement.Call(
+ uintptr(unsafe.Pointer(safearray)),
+ uintptr(unsafe.Pointer(&index)),
+ uintptr(unsafe.Pointer(&element))))
+ str = BstrToString(*(**uint16)(unsafe.Pointer(&element)))
+ SysFreeString(element)
+ return
+}
+
+// safeArrayGetIID is the InterfaceID of the elements in the SafeArray.
+//
+// AKA: SafeArrayGetIID in Windows API.
+func safeArrayGetIID(safearray *SafeArray) (guid *GUID, err error) {
+ err = convertHresultToError(
+ procSafeArrayGetIID.Call(
+ uintptr(unsafe.Pointer(safearray)),
+ uintptr(unsafe.Pointer(&guid))))
+ return
+}
+
+// safeArrayGetLBound returns lower bounds of SafeArray.
+//
+// SafeArrays may have multiple dimensions. Meaning, it could be
+// multidimensional array.
+//
+// AKA: SafeArrayGetLBound in Windows API.
+func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (lowerBound int64, err error) {
+ err = convertHresultToError(
+ procSafeArrayGetLBound.Call(
+ uintptr(unsafe.Pointer(safearray)),
+ uintptr(dimension),
+ uintptr(unsafe.Pointer(&lowerBound))))
+ return
+}
+
+// safeArrayGetUBound returns upper bounds of SafeArray.
+//
+// SafeArrays may have multiple dimensions. Meaning, it could be
+// multidimensional array.
+//
+// AKA: SafeArrayGetUBound in Windows API.
+func safeArrayGetUBound(safearray *SafeArray, dimension uint32) (upperBound int64, err error) {
+ err = convertHresultToError(
+ procSafeArrayGetUBound.Call(
+ uintptr(unsafe.Pointer(safearray)),
+ uintptr(dimension),
+ uintptr(unsafe.Pointer(&upperBound))))
+ return
+}
+
+// safeArrayGetVartype returns data type of SafeArray.
+//
+// AKA: SafeArrayGetVartype in Windows API.
+func safeArrayGetVartype(safearray *SafeArray) (varType uint16, err error) {
+ err = convertHresultToError(
+ procSafeArrayGetVartype.Call(
+ uintptr(unsafe.Pointer(safearray)),
+ uintptr(unsafe.Pointer(&varType))))
+ return
+}
+
+// safeArrayLock locks SafeArray for reading to modify SafeArray.
+//
+// This must be called during some calls to ensure that another process does not
+// read or write to the SafeArray during editing.
+//
+// AKA: SafeArrayLock in Windows API.
+func safeArrayLock(safearray *SafeArray) (err error) {
+ err = convertHresultToError(procSafeArrayLock.Call(uintptr(unsafe.Pointer(safearray))))
+ return
+}
+
+// safeArrayUnlock unlocks SafeArray for reading.
+//
+// AKA: SafeArrayUnlock in Windows API.
+func safeArrayUnlock(safearray *SafeArray) (err error) {
+ err = convertHresultToError(procSafeArrayUnlock.Call(uintptr(unsafe.Pointer(safearray))))
+ return
+}
+
+// safeArrayPutElement stores the data element at the specified location in the
+// array.
+//
+// AKA: SafeArrayPutElement in Windows API.
+func safeArrayPutElement(safearray *SafeArray, index int64, element uintptr) (err error) {
+ err = convertHresultToError(
+ procSafeArrayPutElement.Call(
+ uintptr(unsafe.Pointer(safearray)),
+ uintptr(unsafe.Pointer(&index)),
+ uintptr(unsafe.Pointer(element))))
+ return
+}
+
+// safeArrayGetRecordInfo accesses IRecordInfo info for custom types.
+//
+// AKA: SafeArrayGetRecordInfo in Windows API.
+//
+// XXX: Must implement IRecordInfo interface for this to return.
+func safeArrayGetRecordInfo(safearray *SafeArray) (recordInfo interface{}, err error) {
+ err = convertHresultToError(
+ procSafeArrayGetRecordInfo.Call(
+ uintptr(unsafe.Pointer(safearray)),
+ uintptr(unsafe.Pointer(&recordInfo))))
+ return
+}
+
+// safeArraySetRecordInfo mutates IRecordInfo info for custom types.
+//
+// AKA: SafeArraySetRecordInfo in Windows API.
+//
+// XXX: Must implement IRecordInfo interface for this to return.
+func safeArraySetRecordInfo(safearray *SafeArray, recordInfo interface{}) (err error) {
+ err = convertHresultToError(
+ procSafeArraySetRecordInfo.Call(
+ uintptr(unsafe.Pointer(safearray)),
+ uintptr(unsafe.Pointer(&recordInfo))))
+ return
+}
diff --git a/vendor/github.com/go-ole/go-ole/safearrayconversion.go b/vendor/github.com/go-ole/go-ole/safearrayconversion.go
new file mode 100644
index 000000000..ffeb2b97b
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/safearrayconversion.go
@@ -0,0 +1,140 @@
+// Helper for converting SafeArray to array of objects.
+
+package ole
+
+import (
+ "unsafe"
+)
+
+type SafeArrayConversion struct {
+ Array *SafeArray
+}
+
+func (sac *SafeArrayConversion) ToStringArray() (strings []string) {
+ totalElements, _ := sac.TotalElements(0)
+ strings = make([]string, totalElements)
+
+ for i := int64(0); i < totalElements; i++ {
+ strings[int32(i)], _ = safeArrayGetElementString(sac.Array, i)
+ }
+
+ return
+}
+
+func (sac *SafeArrayConversion) ToByteArray() (bytes []byte) {
+ totalElements, _ := sac.TotalElements(0)
+ bytes = make([]byte, totalElements)
+
+ for i := int64(0); i < totalElements; i++ {
+ safeArrayGetElement(sac.Array, i, unsafe.Pointer(&bytes[int32(i)]))
+ }
+
+ return
+}
+
+func (sac *SafeArrayConversion) ToValueArray() (values []interface{}) {
+ totalElements, _ := sac.TotalElements(0)
+ values = make([]interface{}, totalElements)
+ vt, _ := safeArrayGetVartype(sac.Array)
+
+ for i := 0; i < int(totalElements); i++ {
+ switch VT(vt) {
+ case VT_BOOL:
+ var v bool
+ safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
+ values[i] = v
+ case VT_I1:
+ var v int8
+ safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
+ values[i] = v
+ case VT_I2:
+ var v int16
+ safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
+ values[i] = v
+ case VT_I4:
+ var v int32
+ safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
+ values[i] = v
+ case VT_I8:
+ var v int64
+ safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
+ values[i] = v
+ case VT_UI1:
+ var v uint8
+ safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
+ values[i] = v
+ case VT_UI2:
+ var v uint16
+ safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
+ values[i] = v
+ case VT_UI4:
+ var v uint32
+ safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
+ values[i] = v
+ case VT_UI8:
+ var v uint64
+ safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
+ values[i] = v
+ case VT_R4:
+ var v float32
+ safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
+ values[i] = v
+ case VT_R8:
+ var v float64
+ safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
+ values[i] = v
+ case VT_BSTR:
+ var v string
+ safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
+ values[i] = v
+ case VT_VARIANT:
+ var v VARIANT
+ safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v))
+ values[i] = v.Value()
+ default:
+ // TODO
+ }
+ }
+
+ return
+}
+
+func (sac *SafeArrayConversion) GetType() (varType uint16, err error) {
+ return safeArrayGetVartype(sac.Array)
+}
+
+func (sac *SafeArrayConversion) GetDimensions() (dimensions *uint32, err error) {
+ return safeArrayGetDim(sac.Array)
+}
+
+func (sac *SafeArrayConversion) GetSize() (length *uint32, err error) {
+ return safeArrayGetElementSize(sac.Array)
+}
+
+func (sac *SafeArrayConversion) TotalElements(index uint32) (totalElements int64, err error) {
+ if index < 1 {
+ index = 1
+ }
+
+ // Get array bounds
+ var LowerBounds int64
+ var UpperBounds int64
+
+ LowerBounds, err = safeArrayGetLBound(sac.Array, index)
+ if err != nil {
+ return
+ }
+
+ UpperBounds, err = safeArrayGetUBound(sac.Array, index)
+ if err != nil {
+ return
+ }
+
+ totalElements = UpperBounds - LowerBounds + 1
+ return
+}
+
+// Release Safe Array memory
+func (sac *SafeArrayConversion) Release() {
+ safeArrayDestroy(sac.Array)
+}
diff --git a/vendor/github.com/go-ole/go-ole/safearrayslices.go b/vendor/github.com/go-ole/go-ole/safearrayslices.go
new file mode 100644
index 000000000..a9fa885f1
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/safearrayslices.go
@@ -0,0 +1,33 @@
+// +build windows
+
+package ole
+
+import (
+ "unsafe"
+)
+
+func safeArrayFromByteSlice(slice []byte) *SafeArray {
+ array, _ := safeArrayCreateVector(VT_UI1, 0, uint32(len(slice)))
+
+ if array == nil {
+ panic("Could not convert []byte to SAFEARRAY")
+ }
+
+ for i, v := range slice {
+ safeArrayPutElement(array, int64(i), uintptr(unsafe.Pointer(&v)))
+ }
+ return array
+}
+
+func safeArrayFromStringSlice(slice []string) *SafeArray {
+ array, _ := safeArrayCreateVector(VT_BSTR, 0, uint32(len(slice)))
+
+ if array == nil {
+ panic("Could not convert []string to SAFEARRAY")
+ }
+ // SysAllocStringLen(s)
+ for i, v := range slice {
+ safeArrayPutElement(array, int64(i), uintptr(unsafe.Pointer(SysAllocStringLen(v))))
+ }
+ return array
+}
diff --git a/vendor/github.com/go-ole/go-ole/utility.go b/vendor/github.com/go-ole/go-ole/utility.go
new file mode 100644
index 000000000..99ee82dc3
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/utility.go
@@ -0,0 +1,101 @@
+package ole
+
+import (
+ "unicode/utf16"
+ "unsafe"
+)
+
+// ClassIDFrom retrieves class ID whether given is program ID or application string.
+//
+// Helper that provides check against both Class ID from Program ID and Class ID from string. It is
+// faster, if you know which you are using, to use the individual functions, but this will check
+// against available functions for you.
+func ClassIDFrom(programID string) (classID *GUID, err error) {
+ classID, err = CLSIDFromProgID(programID)
+ if err != nil {
+ classID, err = CLSIDFromString(programID)
+ if err != nil {
+ return
+ }
+ }
+ return
+}
+
+// BytePtrToString converts byte pointer to a Go string.
+func BytePtrToString(p *byte) string {
+ a := (*[10000]uint8)(unsafe.Pointer(p))
+ i := 0
+ for a[i] != 0 {
+ i++
+ }
+ return string(a[:i])
+}
+
+// UTF16PtrToString is alias for LpOleStrToString.
+//
+// Kept for compatibility reasons.
+func UTF16PtrToString(p *uint16) string {
+ return LpOleStrToString(p)
+}
+
+// LpOleStrToString converts COM Unicode to Go string.
+func LpOleStrToString(p *uint16) string {
+ if p == nil {
+ return ""
+ }
+
+ length := lpOleStrLen(p)
+ a := make([]uint16, length)
+
+ ptr := unsafe.Pointer(p)
+
+ for i := 0; i < int(length); i++ {
+ a[i] = *(*uint16)(ptr)
+ ptr = unsafe.Pointer(uintptr(ptr) + 2)
+ }
+
+ return string(utf16.Decode(a))
+}
+
+// BstrToString converts COM binary string to Go string.
+func BstrToString(p *uint16) string {
+ if p == nil {
+ return ""
+ }
+ length := SysStringLen((*int16)(unsafe.Pointer(p)))
+ a := make([]uint16, length)
+
+ ptr := unsafe.Pointer(p)
+
+ for i := 0; i < int(length); i++ {
+ a[i] = *(*uint16)(ptr)
+ ptr = unsafe.Pointer(uintptr(ptr) + 2)
+ }
+ return string(utf16.Decode(a))
+}
+
+// lpOleStrLen returns the length of Unicode string.
+func lpOleStrLen(p *uint16) (length int64) {
+ if p == nil {
+ return 0
+ }
+
+ ptr := unsafe.Pointer(p)
+
+ for i := 0; ; i++ {
+ if 0 == *(*uint16)(ptr) {
+ length = int64(i)
+ break
+ }
+ ptr = unsafe.Pointer(uintptr(ptr) + 2)
+ }
+ return
+}
+
+// convertHresultToError converts syscall to error, if call is unsuccessful.
+func convertHresultToError(hr uintptr, r2 uintptr, ignore error) (err error) {
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
diff --git a/vendor/github.com/go-ole/go-ole/variables.go b/vendor/github.com/go-ole/go-ole/variables.go
new file mode 100644
index 000000000..ebe00f1cf
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/variables.go
@@ -0,0 +1,16 @@
+// +build windows
+
+package ole
+
+import (
+ "syscall"
+)
+
+var (
+ modcombase = syscall.NewLazyDLL("combase.dll")
+ modkernel32, _ = syscall.LoadDLL("kernel32.dll")
+ modole32, _ = syscall.LoadDLL("ole32.dll")
+ modoleaut32, _ = syscall.LoadDLL("oleaut32.dll")
+ modmsvcrt, _ = syscall.LoadDLL("msvcrt.dll")
+ moduser32, _ = syscall.LoadDLL("user32.dll")
+)
diff --git a/vendor/github.com/go-ole/go-ole/variant.go b/vendor/github.com/go-ole/go-ole/variant.go
new file mode 100644
index 000000000..36969725e
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/variant.go
@@ -0,0 +1,105 @@
+package ole
+
+import "unsafe"
+
+// NewVariant returns new variant based on type and value.
+func NewVariant(vt VT, val int64) VARIANT {
+ return VARIANT{VT: vt, Val: val}
+}
+
+// ToIUnknown converts Variant to Unknown object.
+func (v *VARIANT) ToIUnknown() *IUnknown {
+ if v.VT != VT_UNKNOWN {
+ return nil
+ }
+ return (*IUnknown)(unsafe.Pointer(uintptr(v.Val)))
+}
+
+// ToIDispatch converts variant to dispatch object.
+func (v *VARIANT) ToIDispatch() *IDispatch {
+ if v.VT != VT_DISPATCH {
+ return nil
+ }
+ return (*IDispatch)(unsafe.Pointer(uintptr(v.Val)))
+}
+
+// ToArray converts variant to SafeArray helper.
+func (v *VARIANT) ToArray() *SafeArrayConversion {
+ if v.VT != VT_SAFEARRAY {
+ if v.VT&VT_ARRAY == 0 {
+ return nil
+ }
+ }
+ var safeArray *SafeArray = (*SafeArray)(unsafe.Pointer(uintptr(v.Val)))
+ return &SafeArrayConversion{safeArray}
+}
+
+// ToString converts variant to Go string.
+func (v *VARIANT) ToString() string {
+ if v.VT != VT_BSTR {
+ return ""
+ }
+ return BstrToString(*(**uint16)(unsafe.Pointer(&v.Val)))
+}
+
+// Clear the memory of variant object.
+func (v *VARIANT) Clear() error {
+ return VariantClear(v)
+}
+
+// Value returns variant value based on its type.
+//
+// Currently supported types: 2- and 4-byte integers, strings, bools.
+// Note that 64-bit integers, datetimes, and other types are stored as strings
+// and will be returned as strings.
+//
+// Needs to be further converted, because this returns an interface{}.
+func (v *VARIANT) Value() interface{} {
+ switch v.VT {
+ case VT_I1:
+ return int8(v.Val)
+ case VT_UI1:
+ return uint8(v.Val)
+ case VT_I2:
+ return int16(v.Val)
+ case VT_UI2:
+ return uint16(v.Val)
+ case VT_I4:
+ return int32(v.Val)
+ case VT_UI4:
+ return uint32(v.Val)
+ case VT_I8:
+ return int64(v.Val)
+ case VT_UI8:
+ return uint64(v.Val)
+ case VT_INT:
+ return int(v.Val)
+ case VT_UINT:
+ return uint(v.Val)
+ case VT_INT_PTR:
+ return uintptr(v.Val) // TODO
+ case VT_UINT_PTR:
+ return uintptr(v.Val)
+ case VT_R4:
+ return *(*float32)(unsafe.Pointer(&v.Val))
+ case VT_R8:
+ return *(*float64)(unsafe.Pointer(&v.Val))
+ case VT_BSTR:
+ return v.ToString()
+ case VT_DATE:
+ // VT_DATE type will either return float64 or time.Time.
+ d := float64(v.Val)
+ date, err := GetVariantDate(d)
+ if err != nil {
+ return d
+ }
+ return date
+ case VT_UNKNOWN:
+ return v.ToIUnknown()
+ case VT_DISPATCH:
+ return v.ToIDispatch()
+ case VT_BOOL:
+ return v.Val != 0
+ }
+ return nil
+}
diff --git a/vendor/github.com/go-ole/go-ole/variant_386.go b/vendor/github.com/go-ole/go-ole/variant_386.go
new file mode 100644
index 000000000..e73736bf3
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/variant_386.go
@@ -0,0 +1,11 @@
+// +build 386
+
+package ole
+
+type VARIANT struct {
+ VT VT // 2
+ wReserved1 uint16 // 4
+ wReserved2 uint16 // 6
+ wReserved3 uint16 // 8
+ Val int64 // 16
+}
diff --git a/vendor/github.com/go-ole/go-ole/variant_amd64.go b/vendor/github.com/go-ole/go-ole/variant_amd64.go
new file mode 100644
index 000000000..dccdde132
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/variant_amd64.go
@@ -0,0 +1,12 @@
+// +build amd64
+
+package ole
+
+type VARIANT struct {
+ VT VT // 2
+ wReserved1 uint16 // 4
+ wReserved2 uint16 // 6
+ wReserved3 uint16 // 8
+ Val int64 // 16
+ _ [8]byte // 24
+}
diff --git a/vendor/github.com/go-ole/go-ole/variant_s390x.go b/vendor/github.com/go-ole/go-ole/variant_s390x.go
new file mode 100644
index 000000000..9874ca66b
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/variant_s390x.go
@@ -0,0 +1,12 @@
+// +build s390x
+
+package ole
+
+type VARIANT struct {
+ VT VT // 2
+ wReserved1 uint16 // 4
+ wReserved2 uint16 // 6
+ wReserved3 uint16 // 8
+ Val int64 // 16
+ _ [8]byte // 24
+}
diff --git a/vendor/github.com/go-ole/go-ole/vt_string.go b/vendor/github.com/go-ole/go-ole/vt_string.go
new file mode 100644
index 000000000..729b4a04d
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/vt_string.go
@@ -0,0 +1,58 @@
+// generated by stringer -output vt_string.go -type VT; DO NOT EDIT
+
+package ole
+
+import "fmt"
+
+const (
+ _VT_name_0 = "VT_EMPTYVT_NULLVT_I2VT_I4VT_R4VT_R8VT_CYVT_DATEVT_BSTRVT_DISPATCHVT_ERRORVT_BOOLVT_VARIANTVT_UNKNOWNVT_DECIMAL"
+ _VT_name_1 = "VT_I1VT_UI1VT_UI2VT_UI4VT_I8VT_UI8VT_INTVT_UINTVT_VOIDVT_HRESULTVT_PTRVT_SAFEARRAYVT_CARRAYVT_USERDEFINEDVT_LPSTRVT_LPWSTR"
+ _VT_name_2 = "VT_RECORDVT_INT_PTRVT_UINT_PTR"
+ _VT_name_3 = "VT_FILETIMEVT_BLOBVT_STREAMVT_STORAGEVT_STREAMED_OBJECTVT_STORED_OBJECTVT_BLOB_OBJECTVT_CFVT_CLSID"
+ _VT_name_4 = "VT_BSTR_BLOBVT_VECTOR"
+ _VT_name_5 = "VT_ARRAY"
+ _VT_name_6 = "VT_BYREF"
+ _VT_name_7 = "VT_RESERVED"
+ _VT_name_8 = "VT_ILLEGAL"
+)
+
+var (
+ _VT_index_0 = [...]uint8{0, 8, 15, 20, 25, 30, 35, 40, 47, 54, 65, 73, 80, 90, 100, 110}
+ _VT_index_1 = [...]uint8{0, 5, 11, 17, 23, 28, 34, 40, 47, 54, 64, 70, 82, 91, 105, 113, 122}
+ _VT_index_2 = [...]uint8{0, 9, 19, 30}
+ _VT_index_3 = [...]uint8{0, 11, 18, 27, 37, 55, 71, 85, 90, 98}
+ _VT_index_4 = [...]uint8{0, 12, 21}
+ _VT_index_5 = [...]uint8{0, 8}
+ _VT_index_6 = [...]uint8{0, 8}
+ _VT_index_7 = [...]uint8{0, 11}
+ _VT_index_8 = [...]uint8{0, 10}
+)
+
+func (i VT) String() string {
+ switch {
+ case 0 <= i && i <= 14:
+ return _VT_name_0[_VT_index_0[i]:_VT_index_0[i+1]]
+ case 16 <= i && i <= 31:
+ i -= 16
+ return _VT_name_1[_VT_index_1[i]:_VT_index_1[i+1]]
+ case 36 <= i && i <= 38:
+ i -= 36
+ return _VT_name_2[_VT_index_2[i]:_VT_index_2[i+1]]
+ case 64 <= i && i <= 72:
+ i -= 64
+ return _VT_name_3[_VT_index_3[i]:_VT_index_3[i+1]]
+ case 4095 <= i && i <= 4096:
+ i -= 4095
+ return _VT_name_4[_VT_index_4[i]:_VT_index_4[i+1]]
+ case i == 8192:
+ return _VT_name_5
+ case i == 16384:
+ return _VT_name_6
+ case i == 32768:
+ return _VT_name_7
+ case i == 65535:
+ return _VT_name_8
+ default:
+ return fmt.Sprintf("VT(%d)", i)
+ }
+}
diff --git a/vendor/github.com/go-ole/go-ole/winrt.go b/vendor/github.com/go-ole/go-ole/winrt.go
new file mode 100644
index 000000000..4e9eca732
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/winrt.go
@@ -0,0 +1,99 @@
+// +build windows
+
+package ole
+
+import (
+ "reflect"
+ "syscall"
+ "unicode/utf8"
+ "unsafe"
+)
+
+var (
+ procRoInitialize = modcombase.NewProc("RoInitialize")
+ procRoActivateInstance = modcombase.NewProc("RoActivateInstance")
+ procRoGetActivationFactory = modcombase.NewProc("RoGetActivationFactory")
+ procWindowsCreateString = modcombase.NewProc("WindowsCreateString")
+ procWindowsDeleteString = modcombase.NewProc("WindowsDeleteString")
+ procWindowsGetStringRawBuffer = modcombase.NewProc("WindowsGetStringRawBuffer")
+)
+
+func RoInitialize(thread_type uint32) (err error) {
+ hr, _, _ := procRoInitialize.Call(uintptr(thread_type))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+func RoActivateInstance(clsid string) (ins *IInspectable, err error) {
+ hClsid, err := NewHString(clsid)
+ if err != nil {
+ return nil, err
+ }
+ defer DeleteHString(hClsid)
+
+ hr, _, _ := procRoActivateInstance.Call(
+ uintptr(unsafe.Pointer(hClsid)),
+ uintptr(unsafe.Pointer(&ins)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+func RoGetActivationFactory(clsid string, iid *GUID) (ins *IInspectable, err error) {
+ hClsid, err := NewHString(clsid)
+ if err != nil {
+ return nil, err
+ }
+ defer DeleteHString(hClsid)
+
+ hr, _, _ := procRoGetActivationFactory.Call(
+ uintptr(unsafe.Pointer(hClsid)),
+ uintptr(unsafe.Pointer(iid)),
+ uintptr(unsafe.Pointer(&ins)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+// HString is handle string for pointers.
+type HString uintptr
+
+// NewHString returns a new HString for Go string.
+func NewHString(s string) (hstring HString, err error) {
+ u16 := syscall.StringToUTF16Ptr(s)
+ len := uint32(utf8.RuneCountInString(s))
+ hr, _, _ := procWindowsCreateString.Call(
+ uintptr(unsafe.Pointer(u16)),
+ uintptr(len),
+ uintptr(unsafe.Pointer(&hstring)))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+// DeleteHString deletes HString.
+func DeleteHString(hstring HString) (err error) {
+ hr, _, _ := procWindowsDeleteString.Call(uintptr(hstring))
+ if hr != 0 {
+ err = NewError(hr)
+ }
+ return
+}
+
+// String returns Go string value of HString.
+func (h HString) String() string {
+ var u16buf uintptr
+ var u16len uint32
+ u16buf, _, _ = procWindowsGetStringRawBuffer.Call(
+ uintptr(h),
+ uintptr(unsafe.Pointer(&u16len)))
+
+ u16hdr := reflect.SliceHeader{Data: u16buf, Len: int(u16len), Cap: int(u16len)}
+ u16 := *(*[]uint16)(unsafe.Pointer(&u16hdr))
+ return syscall.UTF16ToString(u16)
+}
diff --git a/vendor/github.com/go-ole/go-ole/winrt_doc.go b/vendor/github.com/go-ole/go-ole/winrt_doc.go
new file mode 100644
index 000000000..52e6d74c9
--- /dev/null
+++ b/vendor/github.com/go-ole/go-ole/winrt_doc.go
@@ -0,0 +1,36 @@
+// +build !windows
+
+package ole
+
+// RoInitialize
+func RoInitialize(thread_type uint32) (err error) {
+ return NewError(E_NOTIMPL)
+}
+
+// RoActivateInstance
+func RoActivateInstance(clsid string) (ins *IInspectable, err error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// RoGetActivationFactory
+func RoGetActivationFactory(clsid string, iid *GUID) (ins *IInspectable, err error) {
+ return nil, NewError(E_NOTIMPL)
+}
+
+// HString is handle string for pointers.
+type HString uintptr
+
+// NewHString returns a new HString for Go string.
+func NewHString(s string) (hstring HString, err error) {
+ return HString(uintptr(0)), NewError(E_NOTIMPL)
+}
+
+// DeleteHString deletes HString.
+func DeleteHString(hstring HString) (err error) {
+ return NewError(E_NOTIMPL)
+}
+
+// String returns Go string value of HString.
+func (h HString) String() string {
+ return ""
+}
diff --git a/vendor/github.com/pkg/errors/LICENSE b/vendor/github.com/pkg/errors/LICENSE
new file mode 100644
index 000000000..835ba3e75
--- /dev/null
+++ b/vendor/github.com/pkg/errors/LICENSE
@@ -0,0 +1,23 @@
+Copyright (c) 2015, Dave Cheney <dave@cheney.net>
+All rights reserved.
+
+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 HOLDER 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.
diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md
new file mode 100644
index 000000000..6483ba2af
--- /dev/null
+++ b/vendor/github.com/pkg/errors/README.md
@@ -0,0 +1,52 @@
+# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge)
+
+Package errors provides simple error handling primitives.
+
+`go get github.com/pkg/errors`
+
+The traditional error handling idiom in Go is roughly akin to
+```go
+if err != nil {
+ return err
+}
+```
+which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error.
+
+## Adding context to an error
+
+The errors.Wrap function returns a new error that adds context to the original error. For example
+```go
+_, err := ioutil.ReadAll(r)
+if err != nil {
+ return errors.Wrap(err, "read failed")
+}
+```
+## Retrieving the cause of an error
+
+Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`.
+```go
+type causer interface {
+ Cause() error
+}
+```
+`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example:
+```go
+switch err := errors.Cause(err).(type) {
+case *MyError:
+ // handle specifically
+default:
+ // unknown error
+}
+```
+
+[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors).
+
+## Contributing
+
+We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high.
+
+Before proposing a change, please discuss your change by raising an issue.
+
+## License
+
+BSD-2-Clause
diff --git a/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml
new file mode 100644
index 000000000..a932eade0
--- /dev/null
+++ b/vendor/github.com/pkg/errors/appveyor.yml
@@ -0,0 +1,32 @@
+version: build-{build}.{branch}
+
+clone_folder: C:\gopath\src\github.com\pkg\errors
+shallow_clone: true # for startup speed
+
+environment:
+ GOPATH: C:\gopath
+
+platform:
+ - x64
+
+# http://www.appveyor.com/docs/installed-software
+install:
+ # some helpful output for debugging builds
+ - go version
+ - go env
+ # pre-installed MinGW at C:\MinGW is 32bit only
+ # but MSYS2 at C:\msys64 has mingw64
+ - set PATH=C:\msys64\mingw64\bin;%PATH%
+ - gcc --version
+ - g++ --version
+
+build_script:
+ - go install -v ./...
+
+test_script:
+ - set PATH=C:\gopath\bin;%PATH%
+ - go test -v ./...
+
+#artifacts:
+# - path: '%GOPATH%\bin\*.exe'
+deploy: off
diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go
new file mode 100644
index 000000000..842ee8045
--- /dev/null
+++ b/vendor/github.com/pkg/errors/errors.go
@@ -0,0 +1,269 @@
+// Package errors provides simple error handling primitives.
+//
+// The traditional error handling idiom in Go is roughly akin to
+//
+// if err != nil {
+// return err
+// }
+//
+// which applied recursively up the call stack results in error reports
+// without context or debugging information. The errors package allows
+// programmers to add context to the failure path in their code in a way
+// that does not destroy the original value of the error.
+//
+// Adding context to an error
+//
+// The errors.Wrap function returns a new error that adds context to the
+// original error by recording a stack trace at the point Wrap is called,
+// and the supplied message. For example
+//
+// _, err := ioutil.ReadAll(r)
+// if err != nil {
+// return errors.Wrap(err, "read failed")
+// }
+//
+// If additional control is required the errors.WithStack and errors.WithMessage
+// functions destructure errors.Wrap into its component operations of annotating
+// an error with a stack trace and an a message, respectively.
+//
+// Retrieving the cause of an error
+//
+// Using errors.Wrap constructs a stack of errors, adding context to the
+// preceding error. Depending on the nature of the error it may be necessary
+// to reverse the operation of errors.Wrap to retrieve the original error
+// for inspection. Any error value which implements this interface
+//
+// type causer interface {
+// Cause() error
+// }
+//
+// can be inspected by errors.Cause. errors.Cause will recursively retrieve
+// the topmost error which does not implement causer, which is assumed to be
+// the original cause. For example:
+//
+// switch err := errors.Cause(err).(type) {
+// case *MyError:
+// // handle specifically
+// default:
+// // unknown error
+// }
+//
+// causer interface is not exported by this package, but is considered a part
+// of stable public API.
+//
+// Formatted printing of errors
+//
+// All error values returned from this package implement fmt.Formatter and can
+// be formatted by the fmt package. The following verbs are supported
+//
+// %s print the error. If the error has a Cause it will be
+// printed recursively
+// %v see %s
+// %+v extended format. Each Frame of the error's StackTrace will
+// be printed in detail.
+//
+// Retrieving the stack trace of an error or wrapper
+//
+// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
+// invoked. This information can be retrieved with the following interface.
+//
+// type stackTracer interface {
+// StackTrace() errors.StackTrace
+// }
+//
+// Where errors.StackTrace is defined as
+//
+// type StackTrace []Frame
+//
+// The Frame type represents a call site in the stack trace. Frame supports
+// the fmt.Formatter interface that can be used for printing information about
+// the stack trace of this error. For example:
+//
+// if err, ok := err.(stackTracer); ok {
+// for _, f := range err.StackTrace() {
+// fmt.Printf("%+s:%d", f)
+// }
+// }
+//
+// stackTracer interface is not exported by this package, but is considered a part
+// of stable public API.
+//
+// See the documentation for Frame.Format for more details.
+package errors
+
+import (
+ "fmt"
+ "io"
+)
+
+// New returns an error with the supplied message.
+// New also records the stack trace at the point it was called.
+func New(message string) error {
+ return &fundamental{
+ msg: message,
+ stack: callers(),
+ }
+}
+
+// Errorf formats according to a format specifier and returns the string
+// as a value that satisfies error.
+// Errorf also records the stack trace at the point it was called.
+func Errorf(format string, args ...interface{}) error {
+ return &fundamental{
+ msg: fmt.Sprintf(format, args...),
+ stack: callers(),
+ }
+}
+
+// fundamental is an error that has a message and a stack, but no caller.
+type fundamental struct {
+ msg string
+ *stack
+}
+
+func (f *fundamental) Error() string { return f.msg }
+
+func (f *fundamental) Format(s fmt.State, verb rune) {
+ switch verb {
+ case 'v':
+ if s.Flag('+') {
+ io.WriteString(s, f.msg)
+ f.stack.Format(s, verb)
+ return
+ }
+ fallthrough
+ case 's':
+ io.WriteString(s, f.msg)
+ case 'q':
+ fmt.Fprintf(s, "%q", f.msg)
+ }
+}
+
+// WithStack annotates err with a stack trace at the point WithStack was called.
+// If err is nil, WithStack returns nil.
+func WithStack(err error) error {
+ if err == nil {
+ return nil
+ }
+ return &withStack{
+ err,
+ callers(),
+ }
+}
+
+type withStack struct {
+ error
+ *stack
+}
+
+func (w *withStack) Cause() error { return w.error }
+
+func (w *withStack) Format(s fmt.State, verb rune) {
+ switch verb {
+ case 'v':
+ if s.Flag('+') {
+ fmt.Fprintf(s, "%+v", w.Cause())
+ w.stack.Format(s, verb)
+ return
+ }
+ fallthrough
+ case 's':
+ io.WriteString(s, w.Error())
+ case 'q':
+ fmt.Fprintf(s, "%q", w.Error())
+ }
+}
+
+// Wrap returns an error annotating err with a stack trace
+// at the point Wrap is called, and the supplied message.
+// If err is nil, Wrap returns nil.
+func Wrap(err error, message string) error {
+ if err == nil {
+ return nil
+ }
+ err = &withMessage{
+ cause: err,
+ msg: message,
+ }
+ return &withStack{
+ err,
+ callers(),
+ }
+}
+
+// Wrapf returns an error annotating err with a stack trace
+// at the point Wrapf is call, and the format specifier.
+// If err is nil, Wrapf returns nil.
+func Wrapf(err error, format string, args ...interface{}) error {
+ if err == nil {
+ return nil
+ }
+ err = &withMessage{
+ cause: err,
+ msg: fmt.Sprintf(format, args...),
+ }
+ return &withStack{
+ err,
+ callers(),
+ }
+}
+
+// WithMessage annotates err with a new message.
+// If err is nil, WithMessage returns nil.
+func WithMessage(err error, message string) error {
+ if err == nil {
+ return nil
+ }
+ return &withMessage{
+ cause: err,
+ msg: message,
+ }
+}
+
+type withMessage struct {
+ cause error
+ msg string
+}
+
+func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
+func (w *withMessage) Cause() error { return w.cause }
+
+func (w *withMessage) Format(s fmt.State, verb rune) {
+ switch verb {
+ case 'v':
+ if s.Flag('+') {
+ fmt.Fprintf(s, "%+v\n", w.Cause())
+ io.WriteString(s, w.msg)
+ return
+ }
+ fallthrough
+ case 's', 'q':
+ io.WriteString(s, w.Error())
+ }
+}
+
+// Cause returns the underlying cause of the error, if possible.
+// An error value has a cause if it implements the following
+// interface:
+//
+// type causer interface {
+// Cause() error
+// }
+//
+// If the error does not implement Cause, the original error will
+// be returned. If the error is nil, nil will be returned without further
+// investigation.
+func Cause(err error) error {
+ type causer interface {
+ Cause() error
+ }
+
+ for err != nil {
+ cause, ok := err.(causer)
+ if !ok {
+ break
+ }
+ err = cause.Cause()
+ }
+ return err
+}
diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go
new file mode 100644
index 000000000..b485761a7
--- /dev/null
+++ b/vendor/github.com/pkg/errors/stack.go
@@ -0,0 +1,187 @@
+package errors
+
+import (
+ "fmt"
+ "io"
+ "path"
+ "runtime"
+ "strings"
+)
+
+// Frame represents a program counter inside a stack frame.
+type Frame uintptr
+
+// pc returns the program counter for this frame;
+// multiple frames may have the same PC value.
+func (f Frame) pc() uintptr { return uintptr(f) - 1 }
+
+// file returns the full path to the file that contains the
+// function for this Frame's pc.
+func (f Frame) file() string {
+ fn := runtime.FuncForPC(f.pc())
+ if fn == nil {
+ return "unknown"
+ }
+ file, _ := fn.FileLine(f.pc())
+ return file
+}
+
+// line returns the line number of source code of the
+// function for this Frame's pc.
+func (f Frame) line() int {
+ fn := runtime.FuncForPC(f.pc())
+ if fn == nil {
+ return 0
+ }
+ _, line := fn.FileLine(f.pc())
+ return line
+}
+
+// Format formats the frame according to the fmt.Formatter interface.
+//
+// %s source file
+// %d source line
+// %n function name
+// %v equivalent to %s:%d
+//
+// Format accepts flags that alter the printing of some verbs, as follows:
+//
+// %+s function name and path of source file relative to the compile time
+// GOPATH separated by \n\t (<funcname>\n\t<path>)
+// %+v equivalent to %+s:%d
+func (f Frame) Format(s fmt.State, verb rune) {
+ switch verb {
+ case 's':
+ switch {
+ case s.Flag('+'):
+ pc := f.pc()
+ fn := runtime.FuncForPC(pc)
+ if fn == nil {
+ io.WriteString(s, "unknown")
+ } else {
+ file, _ := fn.FileLine(pc)
+ fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file)
+ }
+ default:
+ io.WriteString(s, path.Base(f.file()))
+ }
+ case 'd':
+ fmt.Fprintf(s, "%d", f.line())
+ case 'n':
+ name := runtime.FuncForPC(f.pc()).Name()
+ io.WriteString(s, funcname(name))
+ case 'v':
+ f.Format(s, 's')
+ io.WriteString(s, ":")
+ f.Format(s, 'd')
+ }
+}
+
+// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
+type StackTrace []Frame
+
+// Format formats the stack of Frames according to the fmt.Formatter interface.
+//
+// %s lists source files for each Frame in the stack
+// %v lists the source file and line number for each Frame in the stack
+//
+// Format accepts flags that alter the printing of some verbs, as follows:
+//
+// %+v Prints filename, function, and line number for each Frame in the stack.
+func (st StackTrace) Format(s fmt.State, verb rune) {
+ switch verb {
+ case 'v':
+ switch {
+ case s.Flag('+'):
+ for _, f := range st {
+ fmt.Fprintf(s, "\n%+v", f)
+ }
+ case s.Flag('#'):
+ fmt.Fprintf(s, "%#v", []Frame(st))
+ default:
+ fmt.Fprintf(s, "%v", []Frame(st))
+ }
+ case 's':
+ fmt.Fprintf(s, "%s", []Frame(st))
+ }
+}
+
+// stack represents a stack of program counters.
+type stack []uintptr
+
+func (s *stack) Format(st fmt.State, verb rune) {
+ switch verb {
+ case 'v':
+ switch {
+ case st.Flag('+'):
+ for _, pc := range *s {
+ f := Frame(pc)
+ fmt.Fprintf(st, "\n%+v", f)
+ }
+ }
+ }
+}
+
+func (s *stack) StackTrace() StackTrace {
+ f := make([]Frame, len(*s))
+ for i := 0; i < len(f); i++ {
+ f[i] = Frame((*s)[i])
+ }
+ return f
+}
+
+func callers() *stack {
+ const depth = 32
+ var pcs [depth]uintptr
+ n := runtime.Callers(3, pcs[:])
+ var st stack = pcs[0:n]
+ return &st
+}
+
+// funcname removes the path prefix component of a function's name reported by func.Name().
+func funcname(name string) string {
+ i := strings.LastIndex(name, "/")
+ name = name[i+1:]
+ i = strings.Index(name, ".")
+ return name[i+1:]
+}
+
+func trimGOPATH(name, file string) string {
+ // Here we want to get the source file path relative to the compile time
+ // GOPATH. As of Go 1.6.x there is no direct way to know the compiled
+ // GOPATH at runtime, but we can infer the number of path segments in the
+ // GOPATH. We note that fn.Name() returns the function name qualified by
+ // the import path, which does not include the GOPATH. Thus we can trim
+ // segments from the beginning of the file path until the number of path
+ // separators remaining is one more than the number of path separators in
+ // the function name. For example, given:
+ //
+ // GOPATH /home/user
+ // file /home/user/src/pkg/sub/file.go
+ // fn.Name() pkg/sub.Type.Method
+ //
+ // We want to produce:
+ //
+ // pkg/sub/file.go
+ //
+ // From this we can easily see that fn.Name() has one less path separator
+ // than our desired output. We count separators from the end of the file
+ // path until it finds two more than in the function name and then move
+ // one character forward to preserve the initial path segment without a
+ // leading separator.
+ const sep = "/"
+ goal := strings.Count(name, sep) + 2
+ i := len(file)
+ for n := 0; n < goal; n++ {
+ i = strings.LastIndex(file[:i], sep)
+ if i == -1 {
+ // not enough separators found, set i so that the slice expression
+ // below leaves file unmodified
+ i = -len(sep)
+ break
+ }
+ }
+ // get back to 0 or trim the leading separator
+ file = file[i+len(sep):]
+ return file
+}
diff --git a/vendor/github.com/rjeczalik/notify/README.md b/vendor/github.com/rjeczalik/notify/README.md
index a728d1dd0..02a5f3290 100644
--- a/vendor/github.com/rjeczalik/notify/README.md
+++ b/vendor/github.com/rjeczalik/notify/README.md
@@ -18,4 +18,4 @@ Filesystem event notification library on steroids. (under active development)
- [github.com/rjeczalik/cmd/notify](https://godoc.org/github.com/rjeczalik/cmd/notify)
- [github.com/cortesi/devd](https://github.com/cortesi/devd)
- [github.com/cortesi/modd](https://github.com/cortesi/modd)
-
+- [github.com/syncthing/syncthing-inotify](https://github.com/syncthing/syncthing-inotify)
diff --git a/vendor/github.com/rjeczalik/notify/appveyor.yml b/vendor/github.com/rjeczalik/notify/appveyor.yml
index 8e762d05c..a495bd7c7 100644
--- a/vendor/github.com/rjeczalik/notify/appveyor.yml
+++ b/vendor/github.com/rjeczalik/notify/appveyor.yml
@@ -16,7 +16,7 @@ install:
build_script:
- go tool vet -all .
- go build ./...
- - go test -v -race ./...
+ - go test -v -timeout 60s -race ./...
test: off
diff --git a/vendor/github.com/rjeczalik/notify/debug.go b/vendor/github.com/rjeczalik/notify/debug.go
index bd9bc468d..2a3eb3370 100644
--- a/vendor/github.com/rjeczalik/notify/debug.go
+++ b/vendor/github.com/rjeczalik/notify/debug.go
@@ -2,10 +2,52 @@
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
-// +build !debug
-
package notify
-func dbgprint(...interface{}) {}
+import (
+ "log"
+ "os"
+ "runtime"
+ "strings"
+)
+
+var dbgprint func(...interface{})
+
+var dbgprintf func(string, ...interface{})
+
+var dbgcallstack func(max int) []string
-func dbgprintf(string, ...interface{}) {}
+func init() {
+ if _, ok := os.LookupEnv("NOTIFY_DEBUG"); ok || debugTag {
+ log.SetOutput(os.Stdout)
+ log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)
+ dbgprint = func(v ...interface{}) {
+ v = append([]interface{}{"[D] "}, v...)
+ log.Println(v...)
+ }
+ dbgprintf = func(format string, v ...interface{}) {
+ format = "[D] " + format
+ log.Printf(format, v...)
+ }
+ dbgcallstack = func(max int) []string {
+ pc, stack := make([]uintptr, max), make([]string, 0, max)
+ runtime.Callers(2, pc)
+ for _, pc := range pc {
+ if f := runtime.FuncForPC(pc); f != nil {
+ fname := f.Name()
+ idx := strings.LastIndex(fname, string(os.PathSeparator))
+ if idx != -1 {
+ stack = append(stack, fname[idx+1:])
+ } else {
+ stack = append(stack, fname)
+ }
+ }
+ }
+ return stack
+ }
+ return
+ }
+ dbgprint = func(v ...interface{}) {}
+ dbgprintf = func(format string, v ...interface{}) {}
+ dbgcallstack = func(max int) []string { return nil }
+}
diff --git a/vendor/github.com/rjeczalik/notify/debug_debug.go b/vendor/github.com/rjeczalik/notify/debug_debug.go
index f0622917f..6fca891ab 100644
--- a/vendor/github.com/rjeczalik/notify/debug_debug.go
+++ b/vendor/github.com/rjeczalik/notify/debug_debug.go
@@ -6,38 +6,4 @@
package notify
-import (
- "fmt"
- "os"
- "runtime"
- "strings"
-)
-
-func dbgprint(v ...interface{}) {
- fmt.Printf("[D] ")
- fmt.Print(v...)
- fmt.Printf("\n\n")
-}
-
-func dbgprintf(format string, v ...interface{}) {
- fmt.Printf("[D] ")
- fmt.Printf(format, v...)
- fmt.Printf("\n\n")
-}
-
-func dbgcallstack(max int) []string {
- pc, stack := make([]uintptr, max), make([]string, 0, max)
- runtime.Callers(2, pc)
- for _, pc := range pc {
- if f := runtime.FuncForPC(pc); f != nil {
- fname := f.Name()
- idx := strings.LastIndex(fname, string(os.PathSeparator))
- if idx != -1 {
- stack = append(stack, fname[idx+1:])
- } else {
- stack = append(stack, fname)
- }
- }
- }
- return stack
-}
+var debugTag bool = true
diff --git a/vendor/github.com/rjeczalik/notify/debug_nodebug.go b/vendor/github.com/rjeczalik/notify/debug_nodebug.go
new file mode 100644
index 000000000..be391a276
--- /dev/null
+++ b/vendor/github.com/rjeczalik/notify/debug_nodebug.go
@@ -0,0 +1,9 @@
+// Copyright (c) 2014-2015 The Notify Authors. All rights reserved.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+// +build !debug
+
+package notify
+
+var debugTag bool = false
diff --git a/vendor/github.com/rjeczalik/notify/doc.go b/vendor/github.com/rjeczalik/notify/doc.go
index 8a99ddda6..60543c083 100644
--- a/vendor/github.com/rjeczalik/notify/doc.go
+++ b/vendor/github.com/rjeczalik/notify/doc.go
@@ -12,11 +12,14 @@
// source file.
//
// On top of filesystem watchers notify maintains a watchpoint tree, which provides
-// strategy for creating and closing filesystem watches and dispatching filesystem
+// a strategy for creating and closing filesystem watches and dispatching filesystem
// events to user channels.
//
// An event set is just an event list joint using bitwise OR operator
// into a single event value.
+// Both the platform-independent (see Constants) and specific events can be used.
+// Refer to the event_*.go source files for information about the available
+// events.
//
// A filesystem watch or just a watch is platform-specific entity which represents
// a single path registered for notifications for specific event set. Setting a watch
@@ -35,6 +38,6 @@
// A watchpoint is a list of user channel and event set pairs for particular
// path (watchpoint tree's node). A single watchpoint can contain multiple
// different user channels registered to listen for one or more events. A single
-// user channel can be registered in one or more watchpoints, recurisve and
+// user channel can be registered in one or more watchpoints, recursive and
// non-recursive ones as well.
package notify
diff --git a/vendor/github.com/rjeczalik/notify/event.go b/vendor/github.com/rjeczalik/notify/event.go
index e045edcec..c12884197 100644
--- a/vendor/github.com/rjeczalik/notify/event.go
+++ b/vendor/github.com/rjeczalik/notify/event.go
@@ -73,7 +73,7 @@ func (e Event) String() string {
//
// https://developer.apple.com/library/mac/documentation/Darwin/Reference/FSEvents_Ref/index.html#//apple_ref/doc/constant_group/FSEventStreamEventFlags
//
-// Under Linux (inotify) Sys() always returns a non-nil *syscall.InotifyEvent
+// Under Linux (inotify) Sys() always returns a non-nil *unix.InotifyEvent
// value, defined as:
//
// type InotifyEvent struct {
diff --git a/vendor/github.com/rjeczalik/notify/event_inotify.go b/vendor/github.com/rjeczalik/notify/event_inotify.go
index 82954a9b3..1f32bb73e 100644
--- a/vendor/github.com/rjeczalik/notify/event_inotify.go
+++ b/vendor/github.com/rjeczalik/notify/event_inotify.go
@@ -6,7 +6,7 @@
package notify
-import "syscall"
+import "golang.org/x/sys/unix"
// Platform independent event values.
const (
@@ -25,18 +25,18 @@ const (
// Inotify specific masks are legal, implemented events that are guaranteed to
// work with notify package on linux-based systems.
const (
- InAccess = Event(syscall.IN_ACCESS) // File was accessed
- InModify = Event(syscall.IN_MODIFY) // File was modified
- InAttrib = Event(syscall.IN_ATTRIB) // Metadata changed
- InCloseWrite = Event(syscall.IN_CLOSE_WRITE) // Writtable file was closed
- InCloseNowrite = Event(syscall.IN_CLOSE_NOWRITE) // Unwrittable file closed
- InOpen = Event(syscall.IN_OPEN) // File was opened
- InMovedFrom = Event(syscall.IN_MOVED_FROM) // File was moved from X
- InMovedTo = Event(syscall.IN_MOVED_TO) // File was moved to Y
- InCreate = Event(syscall.IN_CREATE) // Subfile was created
- InDelete = Event(syscall.IN_DELETE) // Subfile was deleted
- InDeleteSelf = Event(syscall.IN_DELETE_SELF) // Self was deleted
- InMoveSelf = Event(syscall.IN_MOVE_SELF) // Self was moved
+ InAccess = Event(unix.IN_ACCESS) // File was accessed
+ InModify = Event(unix.IN_MODIFY) // File was modified
+ InAttrib = Event(unix.IN_ATTRIB) // Metadata changed
+ InCloseWrite = Event(unix.IN_CLOSE_WRITE) // Writtable file was closed
+ InCloseNowrite = Event(unix.IN_CLOSE_NOWRITE) // Unwrittable file closed
+ InOpen = Event(unix.IN_OPEN) // File was opened
+ InMovedFrom = Event(unix.IN_MOVED_FROM) // File was moved from X
+ InMovedTo = Event(unix.IN_MOVED_TO) // File was moved to Y
+ InCreate = Event(unix.IN_CREATE) // Subfile was created
+ InDelete = Event(unix.IN_DELETE) // Subfile was deleted
+ InDeleteSelf = Event(unix.IN_DELETE_SELF) // Self was deleted
+ InMoveSelf = Event(unix.IN_MOVE_SELF) // Self was moved
)
var osestr = map[Event]string{
@@ -56,15 +56,15 @@ var osestr = map[Event]string{
// Inotify behavior events are not **currently** supported by notify package.
const (
- inDontFollow = Event(syscall.IN_DONT_FOLLOW)
- inExclUnlink = Event(syscall.IN_EXCL_UNLINK)
- inMaskAdd = Event(syscall.IN_MASK_ADD)
- inOneshot = Event(syscall.IN_ONESHOT)
- inOnlydir = Event(syscall.IN_ONLYDIR)
+ inDontFollow = Event(unix.IN_DONT_FOLLOW)
+ inExclUnlink = Event(unix.IN_EXCL_UNLINK)
+ inMaskAdd = Event(unix.IN_MASK_ADD)
+ inOneshot = Event(unix.IN_ONESHOT)
+ inOnlydir = Event(unix.IN_ONLYDIR)
)
type event struct {
- sys syscall.InotifyEvent
+ sys unix.InotifyEvent
path string
event Event
}
@@ -72,4 +72,4 @@ type event struct {
func (e *event) Event() Event { return e.event }
func (e *event) Path() string { return e.path }
func (e *event) Sys() interface{} { return &e.sys }
-func (e *event) isDir() (bool, error) { return e.sys.Mask&syscall.IN_ISDIR != 0, nil }
+func (e *event) isDir() (bool, error) { return e.sys.Mask&unix.IN_ISDIR != 0, nil }
diff --git a/vendor/github.com/rjeczalik/notify/event_readdcw.go b/vendor/github.com/rjeczalik/notify/event_readdcw.go
index 11ead9e29..f7b82de0c 100644
--- a/vendor/github.com/rjeczalik/notify/event_readdcw.go
+++ b/vendor/github.com/rjeczalik/notify/event_readdcw.go
@@ -27,7 +27,11 @@ const (
dirmarker
)
-// ReadDirectoryChangesW filters.
+// ReadDirectoryChangesW filters
+// On Windows the following events can be passed to Watch. A different set of
+// events (see actions below) are received on the channel passed to Watch.
+// For more information refer to
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx
const (
FileNotifyChangeFileName = Event(syscall.FILE_NOTIFY_CHANGE_FILE_NAME)
FileNotifyChangeDirName = Event(syscall.FILE_NOTIFY_CHANGE_DIR_NAME)
@@ -48,7 +52,13 @@ const (
// this flag should be declared in: http://golang.org/src/pkg/syscall/ztypes_windows.go
const syscallFileNotifyChangeSecurity = 0x00000100
-// ReadDirectoryChangesW actions.
+// ReadDirectoryChangesW actions
+// The following events are returned on the channel passed to Watch, but cannot
+// be passed to Watch itself (see filters above). You can find a table showing
+// the relation between actions and filteres at
+// https://github.com/rjeczalik/notify/issues/10#issuecomment-66179535
+// The msdn documentation on actions is part of
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364391(v=vs.85).aspx
const (
FileActionAdded = Event(syscall.FILE_ACTION_ADDED) << 12
FileActionRemoved = Event(syscall.FILE_ACTION_REMOVED) << 12
diff --git a/vendor/github.com/rjeczalik/notify/node.go b/vendor/github.com/rjeczalik/notify/node.go
index 29c1bb20a..aced8b9c4 100644
--- a/vendor/github.com/rjeczalik/notify/node.go
+++ b/vendor/github.com/rjeczalik/notify/node.go
@@ -6,7 +6,6 @@ package notify
import (
"errors"
- "fmt"
"io/ioutil"
"os"
"path/filepath"
@@ -71,7 +70,11 @@ Traverse:
case errSkip:
continue Traverse
default:
- return fmt.Errorf("error while traversing %q: %v", nd.Name, err)
+ return &os.PathError{
+ Op: "error while traversing",
+ Path: nd.Name,
+ Err: err,
+ }
}
// TODO(rjeczalik): tolerate open failures - add failed names to
// AddDirError and notify users which names are not added to the tree.
diff --git a/vendor/github.com/rjeczalik/notify/watcher_fen.go b/vendor/github.com/rjeczalik/notify/watcher_fen.go
index dd069f2a2..dfe77f2f1 100644
--- a/vendor/github.com/rjeczalik/notify/watcher_fen.go
+++ b/vendor/github.com/rjeczalik/notify/watcher_fen.go
@@ -33,14 +33,7 @@ type fen struct {
// watched is a data structure representing watched file/directory.
type watched struct {
- // p is a path to watched file/directory
- p string
- // fi provides information about watched file/dir
- fi os.FileInfo
- // eDir represents events watched directly
- eDir Event
- // eNonDir represents events watched indirectly
- eNonDir Event
+ trgWatched
}
// Stop implements trigger.
@@ -55,7 +48,7 @@ func (f *fen) Close() (err error) {
// NewWatched implements trigger.
func (*fen) NewWatched(p string, fi os.FileInfo) (*watched, error) {
- return &watched{p: p, fi: fi}, nil
+ return &watched{trgWatched{p: p, fi: fi}}, nil
}
// Record implements trigger.
diff --git a/vendor/github.com/rjeczalik/notify/watcher_fsevents.go b/vendor/github.com/rjeczalik/notify/watcher_fsevents.go
index 9062c17c7..7d9b97b65 100644
--- a/vendor/github.com/rjeczalik/notify/watcher_fsevents.go
+++ b/vendor/github.com/rjeczalik/notify/watcher_fsevents.go
@@ -12,8 +12,6 @@ import (
"sync/atomic"
)
-// TODO(rjeczalik): get rid of calls to canonical, it's tree responsibility
-
const (
failure = uint32(FSEventsMustScanSubDirs | FSEventsUserDropped | FSEventsKernelDropped)
filter = uint32(FSEventsCreated | FSEventsRemoved | FSEventsRenamed |
@@ -189,9 +187,6 @@ func newWatcher(c chan<- EventInfo) watcher {
}
func (fse *fsevents) watch(path string, event Event, isrec int32) (err error) {
- if path, err = canonical(path); err != nil {
- return err
- }
if _, ok := fse.watches[path]; ok {
return errAlreadyWatched
}
@@ -211,9 +206,6 @@ func (fse *fsevents) watch(path string, event Event, isrec int32) (err error) {
}
func (fse *fsevents) unwatch(path string) (err error) {
- if path, err = canonical(path); err != nil {
- return
- }
w, ok := fse.watches[path]
if !ok {
return errNotWatched
diff --git a/vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go b/vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go
index 5be64632e..a2b332a2e 100644
--- a/vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go
+++ b/vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go
@@ -26,9 +26,9 @@ import "C"
import (
"errors"
"os"
+ "runtime"
"sync"
"sync/atomic"
- "time"
"unsafe"
)
@@ -63,6 +63,10 @@ var (
func init() {
wg.Add(1)
go func() {
+ // There is exactly one run loop per thread. Lock this goroutine to its
+ // thread to ensure that it's not rescheduled on a different thread while
+ // setting up the run loop.
+ runtime.LockOSThread()
runloop = C.CFRunLoopGetCurrent()
C.CFRunLoopAddSource(runloop, source, C.kCFRunLoopDefaultMode)
C.CFRunLoopRun()
@@ -73,7 +77,6 @@ func init() {
//export gosource
func gosource(unsafe.Pointer) {
- time.Sleep(time.Second)
wg.Done()
}
diff --git a/vendor/github.com/rjeczalik/notify/watcher_inotify.go b/vendor/github.com/rjeczalik/notify/watcher_inotify.go
index 3ceaa8f3a..d082baca0 100644
--- a/vendor/github.com/rjeczalik/notify/watcher_inotify.go
+++ b/vendor/github.com/rjeczalik/notify/watcher_inotify.go
@@ -13,14 +13,15 @@ import (
"runtime"
"sync"
"sync/atomic"
- "syscall"
"unsafe"
+
+ "golang.org/x/sys/unix"
)
// eventBufferSize defines the size of the buffer given to read(2) function. One
// should not depend on this value, since it was arbitrary chosen and may be
// changed in the future.
-const eventBufferSize = 64 * (syscall.SizeofInotifyEvent + syscall.PathMax + 1)
+const eventBufferSize = 64 * (unix.SizeofInotifyEvent + unix.PathMax + 1)
// consumersCount defines the number of consumers in producer-consumer based
// implementation. Each consumer is run in a separate goroutine and has read
@@ -43,7 +44,7 @@ type inotify struct {
fd int32 // inotify file descriptor
pipefd []int // pipe's read and write descriptors
epfd int // epoll descriptor
- epes []syscall.EpollEvent // epoll events
+ epes []unix.EpollEvent // epoll events
buffer [eventBufferSize]byte // inotify event buffer
wg sync.WaitGroup // wait group used to close main loop
c chan<- EventInfo // event dispatcher channel
@@ -56,13 +57,13 @@ func newWatcher(c chan<- EventInfo) watcher {
fd: invalidDescriptor,
pipefd: []int{invalidDescriptor, invalidDescriptor},
epfd: invalidDescriptor,
- epes: make([]syscall.EpollEvent, 0),
+ epes: make([]unix.EpollEvent, 0),
c: c,
}
runtime.SetFinalizer(i, func(i *inotify) {
i.epollclose()
if i.fd != invalidDescriptor {
- syscall.Close(int(i.fd))
+ unix.Close(int(i.fd))
}
})
return i
@@ -82,13 +83,13 @@ func (i *inotify) Rewatch(path string, _, newevent Event) error {
// one. If called for the first time, this function initializes inotify filesystem
// monitor and starts producer-consumers goroutines.
func (i *inotify) watch(path string, e Event) (err error) {
- if e&^(All|Event(syscall.IN_ALL_EVENTS)) != 0 {
+ if e&^(All|Event(unix.IN_ALL_EVENTS)) != 0 {
return errors.New("notify: unknown event")
}
if err = i.lazyinit(); err != nil {
return
}
- iwd, err := syscall.InotifyAddWatch(int(i.fd), path, encode(e))
+ iwd, err := unix.InotifyAddWatch(int(i.fd), path, encode(e))
if err != nil {
return
}
@@ -119,13 +120,13 @@ func (i *inotify) lazyinit() error {
i.Lock()
defer i.Unlock()
if atomic.LoadInt32(&i.fd) == invalidDescriptor {
- fd, err := syscall.InotifyInit()
+ fd, err := unix.InotifyInit1(unix.IN_CLOEXEC)
if err != nil {
return err
}
i.fd = int32(fd)
if err = i.epollinit(); err != nil {
- _, _ = i.epollclose(), syscall.Close(int(fd)) // Ignore errors.
+ _, _ = i.epollclose(), unix.Close(int(fd)) // Ignore errors.
i.fd = invalidDescriptor
return err
}
@@ -145,33 +146,33 @@ func (i *inotify) lazyinit() error {
// with inotify event queue and the read end of the pipe are added to epoll set.
// Note that `fd` member must be set before this function is called.
func (i *inotify) epollinit() (err error) {
- if i.epfd, err = syscall.EpollCreate1(0); err != nil {
+ if i.epfd, err = unix.EpollCreate1(0); err != nil {
return
}
- if err = syscall.Pipe(i.pipefd); err != nil {
+ if err = unix.Pipe(i.pipefd); err != nil {
return
}
- i.epes = []syscall.EpollEvent{
- {Events: syscall.EPOLLIN, Fd: i.fd},
- {Events: syscall.EPOLLIN, Fd: int32(i.pipefd[0])},
+ i.epes = []unix.EpollEvent{
+ {Events: unix.EPOLLIN, Fd: i.fd},
+ {Events: unix.EPOLLIN, Fd: int32(i.pipefd[0])},
}
- if err = syscall.EpollCtl(i.epfd, syscall.EPOLL_CTL_ADD, int(i.fd), &i.epes[0]); err != nil {
+ if err = unix.EpollCtl(i.epfd, unix.EPOLL_CTL_ADD, int(i.fd), &i.epes[0]); err != nil {
return
}
- return syscall.EpollCtl(i.epfd, syscall.EPOLL_CTL_ADD, i.pipefd[0], &i.epes[1])
+ return unix.EpollCtl(i.epfd, unix.EPOLL_CTL_ADD, i.pipefd[0], &i.epes[1])
}
// epollclose closes the file descriptor created by the call to epoll_create(2)
// and two file descriptors opened by pipe(2) function.
func (i *inotify) epollclose() (err error) {
if i.epfd != invalidDescriptor {
- if err = syscall.Close(i.epfd); err == nil {
+ if err = unix.Close(i.epfd); err == nil {
i.epfd = invalidDescriptor
}
}
for n, fd := range i.pipefd {
if fd != invalidDescriptor {
- switch e := syscall.Close(fd); {
+ switch e := unix.Close(fd); {
case e != nil && err == nil:
err = e
case e == nil:
@@ -187,10 +188,10 @@ func (i *inotify) epollclose() (err error) {
// one of the event's consumers. If pipe fd became ready, loop function closes
// all file descriptors opened by lazyinit method and returns afterwards.
func (i *inotify) loop(esch chan<- []*event) {
- epes := make([]syscall.EpollEvent, 1)
+ epes := make([]unix.EpollEvent, 1)
fd := atomic.LoadInt32(&i.fd)
for {
- switch _, err := syscall.EpollWait(i.epfd, epes, -1); err {
+ switch _, err := unix.EpollWait(i.epfd, epes, -1); err {
case nil:
switch epes[0].Fd {
case fd:
@@ -199,17 +200,17 @@ func (i *inotify) loop(esch chan<- []*event) {
case int32(i.pipefd[0]):
i.Lock()
defer i.Unlock()
- if err = syscall.Close(int(fd)); err != nil && err != syscall.EINTR {
+ if err = unix.Close(int(fd)); err != nil && err != unix.EINTR {
panic("notify: close(2) error " + err.Error())
}
atomic.StoreInt32(&i.fd, invalidDescriptor)
- if err = i.epollclose(); err != nil && err != syscall.EINTR {
+ if err = i.epollclose(); err != nil && err != unix.EINTR {
panic("notify: epollclose error " + err.Error())
}
close(esch)
return
}
- case syscall.EINTR:
+ case unix.EINTR:
continue
default: // We should never reach this line.
panic("notify: epoll_wait(2) error " + err.Error())
@@ -220,22 +221,22 @@ func (i *inotify) loop(esch chan<- []*event) {
// read reads events from an inotify file descriptor. It does not handle errors
// returned from read(2) function since they are not critical to watcher logic.
func (i *inotify) read() (es []*event) {
- n, err := syscall.Read(int(i.fd), i.buffer[:])
- if err != nil || n < syscall.SizeofInotifyEvent {
+ n, err := unix.Read(int(i.fd), i.buffer[:])
+ if err != nil || n < unix.SizeofInotifyEvent {
return
}
- var sys *syscall.InotifyEvent
- nmin := n - syscall.SizeofInotifyEvent
+ var sys *unix.InotifyEvent
+ nmin := n - unix.SizeofInotifyEvent
for pos, path := 0, ""; pos <= nmin; {
- sys = (*syscall.InotifyEvent)(unsafe.Pointer(&i.buffer[pos]))
- pos += syscall.SizeofInotifyEvent
+ sys = (*unix.InotifyEvent)(unsafe.Pointer(&i.buffer[pos]))
+ pos += unix.SizeofInotifyEvent
if path = ""; sys.Len > 0 {
endpos := pos + int(sys.Len)
path = string(bytes.TrimRight(i.buffer[pos:endpos], "\x00"))
pos = endpos
}
es = append(es, &event{
- sys: syscall.InotifyEvent{
+ sys: unix.InotifyEvent{
Wd: sys.Wd,
Mask: sys.Mask,
Cookie: sys.Cookie,
@@ -268,7 +269,7 @@ func (i *inotify) transform(es []*event) []*event {
var multi []*event
i.RLock()
for idx, e := range es {
- if e.sys.Mask&(syscall.IN_IGNORED|syscall.IN_Q_OVERFLOW) != 0 {
+ if e.sys.Mask&(unix.IN_IGNORED|unix.IN_Q_OVERFLOW) != 0 {
es[idx] = nil
continue
}
@@ -317,7 +318,7 @@ func encode(e Event) uint32 {
// can be nil when the event should not be passed on.
func decode(mask Event, e *event) (syse *event) {
if sysmask := uint32(mask) & e.sys.Mask; sysmask != 0 {
- syse = &event{sys: syscall.InotifyEvent{
+ syse = &event{sys: unix.InotifyEvent{
Wd: e.sys.Wd,
Mask: e.sys.Mask,
Cookie: e.sys.Cookie,
@@ -357,7 +358,7 @@ func (i *inotify) Unwatch(path string) (err error) {
return errors.New("notify: path " + path + " is already watched")
}
fd := atomic.LoadInt32(&i.fd)
- if _, err = syscall.InotifyRmWatch(int(fd), uint32(iwd)); err != nil {
+ if err = removeInotifyWatch(fd, iwd); err != nil {
return
}
i.Lock()
@@ -377,12 +378,12 @@ func (i *inotify) Close() (err error) {
return nil
}
for iwd := range i.m {
- if _, e := syscall.InotifyRmWatch(int(i.fd), uint32(iwd)); e != nil && err == nil {
+ if e := removeInotifyWatch(i.fd, iwd); e != nil && err == nil {
err = e
}
delete(i.m, iwd)
}
- switch _, errwrite := syscall.Write(i.pipefd[1], []byte{0x00}); {
+ switch _, errwrite := unix.Write(i.pipefd[1], []byte{0x00}); {
case errwrite != nil && err == nil:
err = errwrite
fallthrough
@@ -394,3 +395,11 @@ func (i *inotify) Close() (err error) {
}
return
}
+
+// if path was removed, notify already removed the watch and returns EINVAL error
+func removeInotifyWatch(fd int32, iwd int32) (err error) {
+ if _, err = unix.InotifyRmWatch(int(fd), uint32(iwd)); err != nil && err != unix.EINVAL {
+ return
+ }
+ return nil
+}
diff --git a/vendor/github.com/rjeczalik/notify/watcher_kqueue.go b/vendor/github.com/rjeczalik/notify/watcher_kqueue.go
index 6d500b700..22e3c2c4a 100644
--- a/vendor/github.com/rjeczalik/notify/watcher_kqueue.go
+++ b/vendor/github.com/rjeczalik/notify/watcher_kqueue.go
@@ -36,16 +36,9 @@ type kq struct {
// watched is a data structure representing watched file/directory.
type watched struct {
- // p is a path to watched file/directory.
- p string
+ trgWatched
// fd is a file descriptor for watched file/directory.
fd int
- // fi provides information about watched file/dir.
- fi os.FileInfo
- // eDir represents events watched directly.
- eDir Event
- // eNonDir represents events watched indirectly.
- eNonDir Event
}
// Stop implements trigger.
@@ -66,7 +59,10 @@ func (*kq) NewWatched(p string, fi os.FileInfo) (*watched, error) {
if err != nil {
return nil, err
}
- return &watched{fd: fd, p: p, fi: fi}, nil
+ return &watched{
+ trgWatched: trgWatched{p: p, fi: fi},
+ fd: fd,
+ }, nil
}
// Record implements trigger.
diff --git a/vendor/github.com/rjeczalik/notify/watcher_readdcw.go b/vendor/github.com/rjeczalik/notify/watcher_readdcw.go
index 5923bfdda..1494fcd79 100644
--- a/vendor/github.com/rjeczalik/notify/watcher_readdcw.go
+++ b/vendor/github.com/rjeczalik/notify/watcher_readdcw.go
@@ -284,16 +284,18 @@ func (r *readdcw) watch(path string, event Event, recursive bool) (err error) {
return
}
r.Lock()
+ defer r.Unlock()
if wd, ok = r.m[path]; ok {
- r.Unlock()
+ dbgprint("watch: exists already")
return
}
if wd, err = newWatched(r.cph, uint32(event), recursive, path); err != nil {
- r.Unlock()
return
}
r.m[path] = wd
- r.Unlock()
+ dbgprint("watch: new watch added")
+ } else {
+ dbgprint("watch: exists already")
}
return nil
}
@@ -337,33 +339,32 @@ func (r *readdcw) loop() {
continue
}
overEx := (*overlappedEx)(unsafe.Pointer(overlapped))
- if n == 0 {
- r.loopstate(overEx)
- } else {
+ if n != 0 {
r.loopevent(n, overEx)
if err = overEx.parent.readDirChanges(); err != nil {
// TODO: error handling
}
}
+ r.loopstate(overEx)
}
}
// TODO(pknap) : doc
func (r *readdcw) loopstate(overEx *overlappedEx) {
- filter := atomic.LoadUint32(&overEx.parent.parent.filter)
+ r.Lock()
+ defer r.Unlock()
+ filter := overEx.parent.parent.filter
if filter&onlyMachineStates == 0 {
return
}
if overEx.parent.parent.count--; overEx.parent.parent.count == 0 {
switch filter & onlyMachineStates {
case stateRewatch:
- r.Lock()
+ dbgprint("loopstate rewatch")
overEx.parent.parent.recreate(r.cph)
- r.Unlock()
case stateUnwatch:
- r.Lock()
+ dbgprint("loopstate unwatch")
delete(r.m, syscall.UTF16ToString(overEx.parent.pathw))
- r.Unlock()
case stateCPClose:
default:
panic(`notify: windows loopstate logic error`)
@@ -450,8 +451,8 @@ func (r *readdcw) rewatch(path string, oldevent, newevent uint32, recursive bool
}
var wd *watched
r.Lock()
- if wd, err = r.nonStateWatched(path); err != nil {
- r.Unlock()
+ defer r.Unlock()
+ if wd, err = r.nonStateWatchedLocked(path); err != nil {
return
}
if wd.filter&(onlyNotifyChanges|onlyNGlobalEvents) != oldevent {
@@ -462,21 +463,19 @@ func (r *readdcw) rewatch(path string, oldevent, newevent uint32, recursive bool
if err = wd.closeHandle(); err != nil {
wd.filter = oldevent
wd.recursive = recursive
- r.Unlock()
return
}
- r.Unlock()
return
}
// TODO : pknap
-func (r *readdcw) nonStateWatched(path string) (wd *watched, err error) {
+func (r *readdcw) nonStateWatchedLocked(path string) (wd *watched, err error) {
wd, ok := r.m[path]
if !ok || wd == nil {
err = errors.New(`notify: ` + path + ` path is unwatched`)
return
}
- if filter := atomic.LoadUint32(&wd.filter); filter&onlyMachineStates != 0 {
+ if wd.filter&onlyMachineStates != 0 {
err = errors.New(`notify: another re/unwatching operation in progress`)
return
}
@@ -497,17 +496,26 @@ func (r *readdcw) RecursiveUnwatch(path string) error {
func (r *readdcw) unwatch(path string) (err error) {
var wd *watched
r.Lock()
- if wd, err = r.nonStateWatched(path); err != nil {
- r.Unlock()
+ defer r.Unlock()
+ if wd, err = r.nonStateWatchedLocked(path); err != nil {
return
}
wd.filter |= stateUnwatch
if err = wd.closeHandle(); err != nil {
wd.filter &^= stateUnwatch
- r.Unlock()
return
}
- r.Unlock()
+ if _, attrErr := syscall.GetFileAttributes(&wd.pathw[0]); attrErr != nil {
+ for _, g := range wd.digrip {
+ if g != nil {
+ dbgprint("unwatch: posting")
+ if err = syscall.PostQueuedCompletionStatus(r.cph, 0, 0, (*syscall.Overlapped)(unsafe.Pointer(g.ovlapped))); err != nil {
+ wd.filter &^= stateUnwatch
+ return
+ }
+ }
+ }
+ }
return
}
diff --git a/vendor/github.com/rjeczalik/notify/watcher_trigger.go b/vendor/github.com/rjeczalik/notify/watcher_trigger.go
index d079d59b0..78151f909 100644
--- a/vendor/github.com/rjeczalik/notify/watcher_trigger.go
+++ b/vendor/github.com/rjeczalik/notify/watcher_trigger.go
@@ -23,6 +23,7 @@
package notify
import (
+ "fmt"
"os"
"path/filepath"
"strings"
@@ -56,6 +57,19 @@ type trigger interface {
IsStop(n interface{}, err error) bool
}
+// trgWatched is a the base data structure representing watched file/directory.
+// The platform specific full data structure (watched) must embed this type.
+type trgWatched struct {
+ // p is a path to watched file/directory.
+ p string
+ // fi provides information about watched file/dir.
+ fi os.FileInfo
+ // eDir represents events watched directly.
+ eDir Event
+ // eNonDir represents events watched indirectly.
+ eNonDir Event
+}
+
// encode Event to native representation. Implementation is to be provided by
// platform specific implementation.
var encode func(Event, bool) int64
@@ -117,6 +131,9 @@ func (t *trg) Close() (err error) {
dbgprintf("trg: closing native watch failed: %q\n", e)
err = nonil(err, e)
}
+ if remaining := len(t.pthLkp); remaining != 0 {
+ err = nonil(err, fmt.Errorf("Not all watches were removed: len(t.pthLkp) == %v", len(t.pthLkp)))
+ }
t.Unlock()
return
}
@@ -175,7 +192,7 @@ func decode(o int64, w Event) (e Event) {
func (t *trg) watch(p string, e Event, fi os.FileInfo) error {
if err := t.singlewatch(p, e, dir, fi); err != nil {
if err != errAlreadyWatched {
- return nil
+ return err
}
}
if fi.IsDir() {
@@ -361,7 +378,7 @@ func (t *trg) singleunwatch(p string, direct mode) error {
}
if w.eNonDir|w.eDir != 0 {
mod := dir
- if w.eNonDir == 0 {
+ if w.eNonDir != 0 {
mod = ndir
}
if err := t.singlewatch(p, w.eNonDir|w.eDir, mod,
diff --git a/vendor/github.com/syndtr/goleveldb/.travis.yml b/vendor/github.com/syndtr/goleveldb/.travis.yml
deleted file mode 100644
index 82de37735..000000000
--- a/vendor/github.com/syndtr/goleveldb/.travis.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-language: go
-
-go:
- - 1.4
- - 1.5
- - 1.6
- - 1.7
- - tip
-
-script:
- - go test -timeout 1h ./...
- - go test -timeout 30m -race -run "TestDB_(Concurrent|GoleveldbIssue74)" ./leveldb
diff --git a/vendor/github.com/syndtr/goleveldb/README.md b/vendor/github.com/syndtr/goleveldb/README.md
index 259286f55..41a47614c 100644
--- a/vendor/github.com/syndtr/goleveldb/README.md
+++ b/vendor/github.com/syndtr/goleveldb/README.md
@@ -10,13 +10,15 @@ Installation
Requirements
-----------
-* Need at least `go1.4` or newer.
+* Need at least `go1.5` or newer.
Usage
-----------
Create or open a database:
```go
+// The returned DB instance is safe for concurrent use. Which mean that all
+// DB's methods may be called concurrently from multiple goroutine.
db, err := leveldb.OpenFile("path/to/db", nil)
...
defer db.Close()
diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/db.go b/vendor/github.com/syndtr/goleveldb/leveldb/db.go
index b0cdcb3d0..ea5595eb3 100644
--- a/vendor/github.com/syndtr/goleveldb/leveldb/db.go
+++ b/vendor/github.com/syndtr/goleveldb/leveldb/db.go
@@ -32,6 +32,11 @@ type DB struct {
// Need 64-bit alignment.
seq uint64
+ // Stats. Need 64-bit alignment.
+ cWriteDelay int64 // The cumulative duration of write delays
+ cWriteDelayN int32 // The cumulative number of write delays
+ aliveSnaps, aliveIters int32
+
// Session.
s *session
@@ -49,9 +54,6 @@ type DB struct {
snapsMu sync.Mutex
snapsList *list.List
- // Stats.
- aliveSnaps, aliveIters int32
-
// Write.
batchPool sync.Pool
writeMergeC chan writeMerge
@@ -321,7 +323,7 @@ func recoverTable(s *session, o *opt.Options) error {
}
}
err = iter.Error()
- if err != nil {
+ if err != nil && !errors.IsCorrupted(err) {
return
}
err = tw.Close()
@@ -392,7 +394,7 @@ func recoverTable(s *session, o *opt.Options) error {
}
imax = append(imax[:0], key...)
}
- if err := iter.Error(); err != nil {
+ if err := iter.Error(); err != nil && !errors.IsCorrupted(err) {
iter.Release()
return err
}
@@ -904,6 +906,8 @@ func (db *DB) GetSnapshot() (*Snapshot, error) {
// Returns the number of files at level 'n'.
// leveldb.stats
// Returns statistics of the underlying DB.
+// leveldb.writedelay
+// Returns cumulative write delay caused by compaction.
// leveldb.sstables
// Returns sstables list for each level.
// leveldb.blockpool
@@ -955,6 +959,9 @@ func (db *DB) GetProperty(name string) (value string, err error) {
level, len(tables), float64(tables.size())/1048576.0, duration.Seconds(),
float64(read)/1048576.0, float64(write)/1048576.0)
}
+ case p == "writedelay":
+ writeDelayN, writeDelay := atomic.LoadInt32(&db.cWriteDelayN), time.Duration(atomic.LoadInt64(&db.cWriteDelay))
+ value = fmt.Sprintf("DelayN:%d Delay:%s", writeDelayN, writeDelay)
case p == "sstables":
for level, tables := range v.levels {
value += fmt.Sprintf("--- level %d ---\n", level)
diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/db_write.go b/vendor/github.com/syndtr/goleveldb/leveldb/db_write.go
index 5b6cb487d..31f4bc5ef 100644
--- a/vendor/github.com/syndtr/goleveldb/leveldb/db_write.go
+++ b/vendor/github.com/syndtr/goleveldb/leveldb/db_write.go
@@ -7,6 +7,7 @@
package leveldb
import (
+ "sync/atomic"
"time"
"github.com/syndtr/goleveldb/leveldb/memdb"
@@ -117,6 +118,8 @@ func (db *DB) flush(n int) (mdb *memDB, mdbFree int, err error) {
db.writeDelayN++
} else if db.writeDelayN > 0 {
db.logf("db@write was delayed N·%d T·%v", db.writeDelayN, db.writeDelay)
+ atomic.AddInt32(&db.cWriteDelayN, int32(db.writeDelayN))
+ atomic.AddInt64(&db.cWriteDelay, int64(db.writeDelay))
db.writeDelay = 0
db.writeDelayN = 0
}
@@ -143,7 +146,7 @@ func (db *DB) unlockWrite(overflow bool, merged int, err error) {
}
}
-// ourBatch if defined should equal with batch.
+// ourBatch is batch that we can modify.
func (db *DB) writeLocked(batch, ourBatch *Batch, merge, sync bool) error {
// Try to flush memdb. This method would also trying to throttle writes
// if it is too fast and compaction cannot catch-up.
@@ -212,6 +215,11 @@ func (db *DB) writeLocked(batch, ourBatch *Batch, merge, sync bool) error {
}
}
+ // Release ourBatch if any.
+ if ourBatch != nil {
+ defer db.batchPool.Put(ourBatch)
+ }
+
// Seq number.
seq := db.seq + 1
diff --git a/vendor/vendor.json b/vendor/vendor.json
index ddcff21fc..e938ce5e6 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -45,6 +45,12 @@
"revisionTime": "2017-02-15T19:58:14Z"
},
{
+ "checksumSHA1": "QC55lHNOv1+UAL2xtIHw17MJ8J8=",
+ "path": "github.com/StackExchange/wmi",
+ "revision": "5d049714c4a64225c3c79a7cf7d02f7fb5b96338",
+ "revisionTime": "2018-01-16T20:38:02Z"
+ },
+ {
"checksumSHA1": "USkefO0g1U9mr+8hagv3fpSkrxg=",
"path": "github.com/aristanetworks/goarista/monotime",
"revision": "ea17b1a17847fb6e4c0a91de0b674704693469b0",
@@ -87,6 +93,18 @@
"revisionTime": "2016-05-12T03:30:02Z"
},
{
+ "checksumSHA1": "Fc8BCxCoQ7ZmghDT6X1cASR10Ec=",
+ "path": "github.com/elastic/gosigar",
+ "revision": "a3814ce5008e612a0c6d027608b54e1d0d9a5613",
+ "revisionTime": "2018-01-22T22:25:45Z"
+ },
+ {
+ "checksumSHA1": "qDsgp2kAeI9nhj565HUScaUyjU4=",
+ "path": "github.com/elastic/gosigar/sys/windows",
+ "revision": "a3814ce5008e612a0c6d027608b54e1d0d9a5613",
+ "revisionTime": "2018-01-22T22:25:45Z"
+ },
+ {
"checksumSHA1": "7oFpbmDfGobwKsFLIf6wMUvVoKw=",
"path": "github.com/fatih/color",
"revision": "5ec5d9d3c2cf82e9688b34e9bc27a94d616a7193",
@@ -99,6 +117,18 @@
"revisionTime": "2017-01-17T22:23:42Z"
},
{
+ "checksumSHA1": "gxV/cPPLkByTdY8y172t7v4qcZA=",
+ "path": "github.com/go-ole/go-ole",
+ "revision": "a41e3c4b706f6ae8dfbff342b06e40fa4d2d0506",
+ "revisionTime": "2017-11-10T16:07:06Z"
+ },
+ {
+ "checksumSHA1": "PArleDBtadu2qO4hJwHR8a3IOTA=",
+ "path": "github.com/go-ole/go-ole/oleutil",
+ "revision": "a41e3c4b706f6ae8dfbff342b06e40fa4d2d0506",
+ "revisionTime": "2017-11-10T16:07:06Z"
+ },
+ {
"checksumSHA1": "KZ3QD2QgUS4RcoKiA3mn5pSlJxQ=",
"path": "github.com/go-stack/stack",
"revision": "54be5f394ed2c3e19dac9134a40a95ba5a017f7b",
@@ -262,6 +292,12 @@
"revisionTime": "2017-09-02T20:46:57Z"
},
{
+ "checksumSHA1": "xCv4GBFyw07vZkVtKF/XrUnkHRk=",
+ "path": "github.com/pkg/errors",
+ "revision": "e881fd58d78e04cf6d0de1217f8707c8cc2249bc",
+ "revisionTime": "2017-12-16T07:03:16Z"
+ },
+ {
"checksumSHA1": "LuFv4/jlrmFNnDb/5SCSEPAM9vU=",
"path": "github.com/pmezard/go-difflib/difflib",
"revision": "792786c7400a136282c1664665ae0a8db921c6c2",
@@ -286,10 +322,10 @@
"revisionTime": "2016-11-28T21:05:44Z"
},
{
- "checksumSHA1": "yOMpVYuaPAtsMIo9DvQP8WZqxQs=",
+ "checksumSHA1": "28UVHMmHx0iqO0XiJsjx+fwILyI=",
"path": "github.com/rjeczalik/notify",
- "revision": "9d5aa0c3b735c3340018a4627446c3ea5a04a097",
- "revisionTime": "2017-01-28T20:05:44Z"
+ "revision": "c31e5f2cb22b3e4ef3f882f413847669bf2652b9",
+ "revisionTime": "2018-02-03T14:01:15Z"
},
{
"checksumSHA1": "5uqO4ITTDMklKi3uNaE/D9LQ5nM=",
@@ -358,10 +394,10 @@
"revisionTime": "2017-07-05T02:17:15Z"
},
{
- "checksumSHA1": "yHbyLpI/Meh0DGrmi8x6FrDxxUY=",
+ "checksumSHA1": "rpu5ZHjXlV13UKA7L1d5MTOyQwA=",
"path": "github.com/syndtr/goleveldb/leveldb",
- "revision": "b89cc31ef7977104127d34c1bd31ebd1a9db2199",
- "revisionTime": "2017-07-25T06:48:36Z"
+ "revision": "211f780988068502fe874c44dae530528ebd840f",
+ "revisionTime": "2018-01-28T14:04:16Z"
},
{
"checksumSHA1": "EKIow7XkgNdWvR/982ffIZxKG8Y=",
diff --git a/whisper/mailserver/mailserver.go b/whisper/mailserver/mailserver.go
index 0ec6ec570..6555fd5c0 100644
--- a/whisper/mailserver/mailserver.go
+++ b/whisper/mailserver/mailserver.go
@@ -26,7 +26,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
- whisper "github.com/ethereum/go-ethereum/whisper/whisperv5"
+ whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
"github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/util"
)
diff --git a/whisper/mailserver/server_test.go b/whisper/mailserver/server_test.go
index 9155ee85a..c8e0a553a 100644
--- a/whisper/mailserver/server_test.go
+++ b/whisper/mailserver/server_test.go
@@ -26,7 +26,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
- whisper "github.com/ethereum/go-ethereum/whisper/whisperv5"
+ whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
)
const powRequirement = 0.00001
diff --git a/whisper/whisperv2/whisper.go b/whisper/whisperv2/whisper.go
index 61c36918d..e111a3414 100644
--- a/whisper/whisperv2/whisper.go
+++ b/whisper/whisperv2/whisper.go
@@ -262,7 +262,7 @@ func (self *Whisper) add(envelope *Envelope) error {
// Insert the message into the tracked pool
hash := envelope.Hash()
if _, ok := self.messages[hash]; ok {
- log.Trace(fmt.Sprintf("whisper envelope already cached: %x\n", envelope))
+ log.Trace(fmt.Sprintf("whisper envelope already cached: %x\n", hash))
return nil
}
self.messages[hash] = envelope
@@ -277,7 +277,7 @@ func (self *Whisper) add(envelope *Envelope) error {
// Notify the local node of a message arrival
go self.postEvent(envelope)
}
- log.Trace(fmt.Sprintf("cached whisper envelope %x\n", envelope))
+ log.Trace(fmt.Sprintf("cached whisper envelope %x\n", hash))
return nil
}
diff --git a/whisper/whisperv5/api.go b/whisper/whisperv5/api.go
index 96c4b0e6c..b4494d0d6 100644
--- a/whisper/whisperv5/api.go
+++ b/whisper/whisperv5/api.go
@@ -562,7 +562,7 @@ func (api *PublicWhisperAPI) NewMessageFilter(req Criteria) (string, error) {
}
if len(req.Topics) > 0 {
- topics = make([][]byte, 1)
+ topics = make([][]byte, 0, len(req.Topics))
for _, topic := range req.Topics {
topics = append(topics, topic[:])
}
diff --git a/whisper/whisperv5/filter.go b/whisper/whisperv5/filter.go
index b5e893e0f..3190334eb 100644
--- a/whisper/whisperv5/filter.go
+++ b/whisper/whisperv5/filter.go
@@ -216,8 +216,12 @@ func (f *Filter) MatchTopic(topic TopicType) bool {
}
func matchSingleTopic(topic TopicType, bt []byte) bool {
- if len(bt) > 4 {
- bt = bt[:4]
+ if len(bt) > TopicLength {
+ bt = bt[:TopicLength]
+ }
+
+ if len(bt) < TopicLength {
+ return false
}
for j, b := range bt {
diff --git a/whisper/whisperv5/filter_test.go b/whisper/whisperv5/filter_test.go
index bd35e7f20..01034a351 100644
--- a/whisper/whisperv5/filter_test.go
+++ b/whisper/whisperv5/filter_test.go
@@ -88,7 +88,7 @@ func generateTestCases(t *testing.T, SizeTestFilters int) []FilterTestCase {
for i := 0; i < SizeTestFilters; i++ {
f, _ := generateFilter(t, true)
cases[i].f = f
- cases[i].alive = (mrand.Int()&int(1) == 0)
+ cases[i].alive = mrand.Int()&int(1) == 0
}
return cases
}
@@ -122,7 +122,7 @@ func TestInstallFilters(t *testing.T) {
for i, testCase := range tst {
fil := filters.Get(testCase.id)
- exist := (fil != nil)
+ exist := fil != nil
if exist != testCase.alive {
t.Fatalf("seed %d: failed alive: %d, %v, %v", seed, i, exist, testCase.alive)
}
@@ -776,6 +776,7 @@ func TestWatchers(t *testing.T) {
func TestVariableTopics(t *testing.T) {
InitSingleTest()
+ const lastTopicByte = 3
var match bool
params, err := generateMessageParams()
if err != nil {
@@ -796,19 +797,52 @@ func TestVariableTopics(t *testing.T) {
}
for i := 0; i < 4; i++ {
- arr := make([]byte, i+1, 4)
- copy(arr, env.Topic[:i+1])
-
- f.Topics[4] = arr
+ env.Topic = BytesToTopic(f.Topics[i])
match = f.MatchEnvelope(env)
if !match {
t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed, i)
}
- f.Topics[4][i]++
+ f.Topics[i][lastTopicByte]++
match = f.MatchEnvelope(env)
if match {
t.Fatalf("MatchEnvelope symmetric with seed %d, step %d: false positive.", seed, i)
}
}
}
+
+func TestMatchSingleTopic_ReturnTrue(t *testing.T) {
+ bt := []byte("test")
+ topic := BytesToTopic(bt)
+
+ if !matchSingleTopic(topic, bt) {
+ t.FailNow()
+ }
+}
+
+func TestMatchSingleTopic_WithTail_ReturnTrue(t *testing.T) {
+ bt := []byte("test with tail")
+ topic := BytesToTopic([]byte("test"))
+
+ if !matchSingleTopic(topic, bt) {
+ t.FailNow()
+ }
+}
+
+func TestMatchSingleTopic_NotEquals_ReturnFalse(t *testing.T) {
+ bt := []byte("tes")
+ topic := BytesToTopic(bt)
+
+ if matchSingleTopic(topic, bt) {
+ t.FailNow()
+ }
+}
+
+func TestMatchSingleTopic_InsufficientLength_ReturnFalse(t *testing.T) {
+ bt := []byte("test")
+ topic := BytesToTopic([]byte("not_equal"))
+
+ if matchSingleTopic(topic, bt) {
+ t.FailNow()
+ }
+}
diff --git a/whisper/whisperv5/gen_criteria_json.go b/whisper/whisperv5/gen_criteria_json.go
index df0de85df..1c0e389ad 100644
--- a/whisper/whisperv5/gen_criteria_json.go
+++ b/whisper/whisperv5/gen_criteria_json.go
@@ -31,12 +31,12 @@ func (c Criteria) MarshalJSON() ([]byte, error) {
func (c *Criteria) UnmarshalJSON(input []byte) error {
type Criteria struct {
- SymKeyID *string `json:"symKeyID"`
- PrivateKeyID *string `json:"privateKeyID"`
- Sig hexutil.Bytes `json:"sig"`
- MinPow *float64 `json:"minPow"`
- Topics []TopicType `json:"topics"`
- AllowP2P *bool `json:"allowP2P"`
+ SymKeyID *string `json:"symKeyID"`
+ PrivateKeyID *string `json:"privateKeyID"`
+ Sig *hexutil.Bytes `json:"sig"`
+ MinPow *float64 `json:"minPow"`
+ Topics []TopicType `json:"topics"`
+ AllowP2P *bool `json:"allowP2P"`
}
var dec Criteria
if err := json.Unmarshal(input, &dec); err != nil {
@@ -49,7 +49,7 @@ func (c *Criteria) UnmarshalJSON(input []byte) error {
c.PrivateKeyID = *dec.PrivateKeyID
}
if dec.Sig != nil {
- c.Sig = dec.Sig
+ c.Sig = *dec.Sig
}
if dec.MinPow != nil {
c.MinPow = *dec.MinPow
diff --git a/whisper/whisperv5/gen_message_json.go b/whisper/whisperv5/gen_message_json.go
index 185557331..b4c4274d0 100644
--- a/whisper/whisperv5/gen_message_json.go
+++ b/whisper/whisperv5/gen_message_json.go
@@ -37,22 +37,22 @@ func (m Message) MarshalJSON() ([]byte, error) {
func (m *Message) UnmarshalJSON(input []byte) error {
type Message struct {
- Sig hexutil.Bytes `json:"sig,omitempty"`
- TTL *uint32 `json:"ttl"`
- Timestamp *uint32 `json:"timestamp"`
- Topic *TopicType `json:"topic"`
- Payload hexutil.Bytes `json:"payload"`
- Padding hexutil.Bytes `json:"padding"`
- PoW *float64 `json:"pow"`
- Hash hexutil.Bytes `json:"hash"`
- Dst hexutil.Bytes `json:"recipientPublicKey,omitempty"`
+ Sig *hexutil.Bytes `json:"sig,omitempty"`
+ TTL *uint32 `json:"ttl"`
+ Timestamp *uint32 `json:"timestamp"`
+ Topic *TopicType `json:"topic"`
+ Payload *hexutil.Bytes `json:"payload"`
+ Padding *hexutil.Bytes `json:"padding"`
+ PoW *float64 `json:"pow"`
+ Hash *hexutil.Bytes `json:"hash"`
+ Dst *hexutil.Bytes `json:"recipientPublicKey,omitempty"`
}
var dec Message
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Sig != nil {
- m.Sig = dec.Sig
+ m.Sig = *dec.Sig
}
if dec.TTL != nil {
m.TTL = *dec.TTL
@@ -64,19 +64,19 @@ func (m *Message) UnmarshalJSON(input []byte) error {
m.Topic = *dec.Topic
}
if dec.Payload != nil {
- m.Payload = dec.Payload
+ m.Payload = *dec.Payload
}
if dec.Padding != nil {
- m.Padding = dec.Padding
+ m.Padding = *dec.Padding
}
if dec.PoW != nil {
m.PoW = *dec.PoW
}
if dec.Hash != nil {
- m.Hash = dec.Hash
+ m.Hash = *dec.Hash
}
if dec.Dst != nil {
- m.Dst = dec.Dst
+ m.Dst = *dec.Dst
}
return nil
}
diff --git a/whisper/whisperv5/gen_newmessage_json.go b/whisper/whisperv5/gen_newmessage_json.go
index d0a47185e..97ffb64ad 100644
--- a/whisper/whisperv5/gen_newmessage_json.go
+++ b/whisper/whisperv5/gen_newmessage_json.go
@@ -39,16 +39,16 @@ func (n NewMessage) MarshalJSON() ([]byte, error) {
func (n *NewMessage) UnmarshalJSON(input []byte) error {
type NewMessage struct {
- SymKeyID *string `json:"symKeyID"`
- PublicKey hexutil.Bytes `json:"pubKey"`
- Sig *string `json:"sig"`
- TTL *uint32 `json:"ttl"`
- Topic *TopicType `json:"topic"`
- Payload hexutil.Bytes `json:"payload"`
- Padding hexutil.Bytes `json:"padding"`
- PowTime *uint32 `json:"powTime"`
- PowTarget *float64 `json:"powTarget"`
- TargetPeer *string `json:"targetPeer"`
+ SymKeyID *string `json:"symKeyID"`
+ PublicKey *hexutil.Bytes `json:"pubKey"`
+ Sig *string `json:"sig"`
+ TTL *uint32 `json:"ttl"`
+ Topic *TopicType `json:"topic"`
+ Payload *hexutil.Bytes `json:"payload"`
+ Padding *hexutil.Bytes `json:"padding"`
+ PowTime *uint32 `json:"powTime"`
+ PowTarget *float64 `json:"powTarget"`
+ TargetPeer *string `json:"targetPeer"`
}
var dec NewMessage
if err := json.Unmarshal(input, &dec); err != nil {
@@ -58,7 +58,7 @@ func (n *NewMessage) UnmarshalJSON(input []byte) error {
n.SymKeyID = *dec.SymKeyID
}
if dec.PublicKey != nil {
- n.PublicKey = dec.PublicKey
+ n.PublicKey = *dec.PublicKey
}
if dec.Sig != nil {
n.Sig = *dec.Sig
@@ -70,10 +70,10 @@ func (n *NewMessage) UnmarshalJSON(input []byte) error {
n.Topic = *dec.Topic
}
if dec.Payload != nil {
- n.Payload = dec.Payload
+ n.Payload = *dec.Payload
}
if dec.Padding != nil {
- n.Padding = dec.Padding
+ n.Padding = *dec.Padding
}
if dec.PowTime != nil {
n.PowTime = *dec.PowTime
diff --git a/whisper/whisperv6/api.go b/whisper/whisperv6/api.go
index 3dddb6953..a2c75a41c 100644
--- a/whisper/whisperv6/api.go
+++ b/whisper/whisperv6/api.go
@@ -36,6 +36,7 @@ const (
filterTimeout = 300 // filters are considered timeout out after filterTimeout seconds
)
+// List of errors
var (
ErrSymAsym = errors.New("specify either a symmetric or an asymmetric key")
ErrInvalidSymmetricKey = errors.New("invalid symmetric key")
@@ -116,12 +117,17 @@ func (api *PublicWhisperAPI) SetMaxMessageSize(ctx context.Context, size uint32)
return true, api.w.SetMaxMessageSize(size)
}
-// SetMinPow sets the minimum PoW for a message before it is accepted.
+// SetMinPoW sets the minimum PoW, and notifies the peers.
func (api *PublicWhisperAPI) SetMinPoW(ctx context.Context, pow float64) (bool, error) {
return true, api.w.SetMinimumPoW(pow)
}
-// MarkTrustedPeer marks a peer trusted. , which will allow it to send historic (expired) messages.
+// SetBloomFilter sets the new value of bloom filter, and notifies the peers.
+func (api *PublicWhisperAPI) SetBloomFilter(ctx context.Context, bloom hexutil.Bytes) (bool, error) {
+ return true, api.w.SetBloomFilter(bloom)
+}
+
+// MarkTrustedPeer marks a peer trusted, which will allow it to send historic (expired) messages.
// Note: This function is not adding new nodes, the node needs to exists as a peer.
func (api *PublicWhisperAPI) MarkTrustedPeer(ctx context.Context, enode string) (bool, error) {
n, err := discover.ParseNode(enode)
@@ -169,7 +175,7 @@ func (api *PublicWhisperAPI) GetPublicKey(ctx context.Context, id string) (hexut
return crypto.FromECDSAPub(&key.PublicKey), nil
}
-// GetPublicKey returns the private key associated with the given key. The key is the hex
+// GetPrivateKey returns the private key associated with the given key. The key is the hex
// encoded representation of a key in the form specified in section 4.3.6 of ANSI X9.62.
func (api *PublicWhisperAPI) GetPrivateKey(ctx context.Context, id string) (hexutil.Bytes, error) {
key, err := api.w.GetPrivateKey(id)
@@ -272,7 +278,7 @@ func (api *PublicWhisperAPI) Post(ctx context.Context, req NewMessage) (bool, er
if params.KeySym, err = api.w.GetSymKey(req.SymKeyID); err != nil {
return false, err
}
- if !validateSymmetricKey(params.KeySym) {
+ if !validateDataIntegrity(params.KeySym, aesKeyLength) {
return false, ErrInvalidSymmetricKey
}
}
@@ -378,7 +384,7 @@ func (api *PublicWhisperAPI) Messages(ctx context.Context, crit Criteria) (*rpc.
if err != nil {
return nil, err
}
- if !validateSymmetricKey(key) {
+ if !validateDataIntegrity(key, aesKeyLength) {
return nil, ErrInvalidSymmetricKey
}
filter.KeySym = key
@@ -550,7 +556,7 @@ func (api *PublicWhisperAPI) NewMessageFilter(req Criteria) (string, error) {
if keySym, err = api.w.GetSymKey(req.SymKeyID); err != nil {
return "", err
}
- if !validateSymmetricKey(keySym) {
+ if !validateDataIntegrity(keySym, aesKeyLength) {
return "", ErrInvalidSymmetricKey
}
}
@@ -562,7 +568,7 @@ func (api *PublicWhisperAPI) NewMessageFilter(req Criteria) (string, error) {
}
if len(req.Topics) > 0 {
- topics = make([][]byte, 1)
+ topics = make([][]byte, 0, len(req.Topics))
for _, topic := range req.Topics {
topics = append(topics, topic[:])
}
diff --git a/whisper/whisperv6/config.go b/whisper/whisperv6/config.go
index d7f817aa2..61419de00 100644
--- a/whisper/whisperv6/config.go
+++ b/whisper/whisperv6/config.go
@@ -16,11 +16,13 @@
package whisperv6
+// Config represents the configuration state of a whisper node.
type Config struct {
MaxMessageSize uint32 `toml:",omitempty"`
MinimumAcceptedPOW float64 `toml:",omitempty"`
}
+// DefaultConfig represents (shocker!) the default configuration.
var DefaultConfig = Config{
MaxMessageSize: DefaultMaxMessageSize,
MinimumAcceptedPOW: DefaultMinimumPoW,
diff --git a/whisper/whisperv6/doc.go b/whisper/whisperv6/doc.go
index 2a4911d65..d5d7fed60 100644
--- a/whisper/whisperv6/doc.go
+++ b/whisper/whisperv6/doc.go
@@ -27,6 +27,9 @@ Whisper is a pure identity-based messaging system. Whisper provides a low-level
or prejudiced by the low-level hardware attributes and characteristics,
particularly the notion of singular endpoints.
*/
+
+// Contains the Whisper protocol constant definitions
+
package whisperv6
import (
@@ -34,11 +37,11 @@ import (
"time"
)
+// Whisper protocol parameters
const (
- EnvelopeVersion = uint64(0)
- ProtocolVersion = uint64(6)
- ProtocolVersionStr = "6.0"
- ProtocolName = "shh"
+ ProtocolVersion = uint64(6) // Protocol version number
+ ProtocolVersionStr = "6.0" // The same, as a string
+ ProtocolName = "shh" // Nickname of the protocol in geth
// whisper protocol message codes, according to EIP-627
statusCode = 0 // used by whisper protocol
@@ -49,29 +52,31 @@ const (
p2pMessageCode = 127 // peer-to-peer message (to be consumed by the peer, but not forwarded any further)
NumberOfMessageCodes = 128
- paddingMask = byte(3)
+ SizeMask = byte(3) // mask used to extract the size of payload size field from the flags
signatureFlag = byte(4)
- TopicLength = 4
- signatureLength = 65
- aesKeyLength = 32
- AESNonceLength = 12
- keyIdSize = 32
+ TopicLength = 4 // in bytes
+ signatureLength = 65 // in bytes
+ aesKeyLength = 32 // in bytes
+ aesNonceLength = 12 // in bytes; for more info please see cipher.gcmStandardNonceSize & aesgcm.NonceSize()
+ keyIDSize = 32 // in bytes
+ bloomFilterSize = 64 // in bytes
+ flagsLength = 1
+
+ EnvelopeHeaderLength = 20
MaxMessageSize = uint32(10 * 1024 * 1024) // maximum accepted size of a message.
DefaultMaxMessageSize = uint32(1024 * 1024)
DefaultMinimumPoW = 0.2
- padSizeLimit = 256 // just an arbitrary number, could be changed without breaking the protocol (must not exceed 2^24)
+ padSizeLimit = 256 // just an arbitrary number, could be changed without breaking the protocol
messageQueueLimit = 1024
expirationCycle = time.Second
transmissionCycle = 300 * time.Millisecond
- DefaultTTL = 50 // seconds
- SynchAllowance = 10 // seconds
-
- EnvelopeHeaderLength = 20
+ DefaultTTL = 50 // seconds
+ DefaultSyncAllowance = 10 // seconds
)
type unknownVersionError uint64
diff --git a/whisper/whisperv6/envelope.go b/whisper/whisperv6/envelope.go
index 676df669b..c7bea2bb9 100644
--- a/whisper/whisperv6/envelope.go
+++ b/whisper/whisperv6/envelope.go
@@ -42,9 +42,11 @@ type Envelope struct {
Data []byte
Nonce uint64
- pow float64 // Message-specific PoW as described in the Whisper specification.
- hash common.Hash // Cached hash of the envelope to avoid rehashing every time.
- // Don't access hash directly, use Hash() function instead.
+ pow float64 // Message-specific PoW as described in the Whisper specification.
+
+ // the following variables should not be accessed directly, use the corresponding function instead: Hash(), Bloom()
+ hash common.Hash // Cached hash of the envelope to avoid rehashing every time.
+ bloom []byte
}
// size returns the size of envelope as it is sent (i.e. public fields only)
@@ -75,15 +77,19 @@ func NewEnvelope(ttl uint32, topic TopicType, msg *sentMessage) *Envelope {
// Seal closes the envelope by spending the requested amount of time as a proof
// of work on hashing the data.
func (e *Envelope) Seal(options *MessageParams) error {
- var target, bestBit int
if options.PoW == 0 {
- // adjust for the duration of Seal() execution only if execution time is predefined unconditionally
+ // PoW is not required
+ return nil
+ }
+
+ var target, bestBit int
+ if options.PoW < 0 {
+ // target is not set - the function should run for a period
+ // of time specified in WorkTime param. Since we can predict
+ // the execution time, we can also adjust Expiry.
e.Expiry += options.WorkTime
} else {
target = e.powToFirstBit(options.PoW)
- if target < 1 {
- target = 1
- }
}
buf := make([]byte, 64)
@@ -113,6 +119,8 @@ func (e *Envelope) Seal(options *MessageParams) error {
return nil
}
+// PoW computes (if necessary) and returns the proof of work target
+// of the envelope.
func (e *Envelope) PoW() float64 {
if e.pow == 0 {
e.calculatePoW(0)
@@ -139,7 +147,11 @@ func (e *Envelope) powToFirstBit(pow float64) int {
x *= float64(e.TTL)
bits := gmath.Log2(x)
bits = gmath.Ceil(bits)
- return int(bits)
+ res := int(bits)
+ if res < 1 {
+ res = 1
+ }
+ return res
}
// Hash returns the SHA3 hash of the envelope, calculating it if not yet done.
@@ -196,8 +208,7 @@ func (e *Envelope) OpenSymmetric(key []byte) (msg *ReceivedMessage, err error) {
// Open tries to decrypt an envelope, and populates the message fields in case of success.
func (e *Envelope) Open(watcher *Filter) (msg *ReceivedMessage) {
- // The API interface forbids filters doing both symmetric and
- // asymmetric encryption.
+ // The API interface forbids filters doing both symmetric and asymmetric encryption.
if watcher.expectsAsymmetricEncryption() && watcher.expectsSymmetricEncryption() {
return nil
}
@@ -215,7 +226,7 @@ func (e *Envelope) Open(watcher *Filter) (msg *ReceivedMessage) {
}
if msg != nil {
- ok := msg.Validate()
+ ok := msg.ValidateAndParse()
if !ok {
return nil
}
@@ -227,3 +238,30 @@ func (e *Envelope) Open(watcher *Filter) (msg *ReceivedMessage) {
}
return msg
}
+
+// Bloom maps 4-bytes Topic into 64-byte bloom filter with 3 bits set (at most).
+func (e *Envelope) Bloom() []byte {
+ if e.bloom == nil {
+ e.bloom = TopicToBloom(e.Topic)
+ }
+ return e.bloom
+}
+
+// TopicToBloom converts the topic (4 bytes) to the bloom filter (64 bytes)
+func TopicToBloom(topic TopicType) []byte {
+ b := make([]byte, bloomFilterSize)
+ var index [3]int
+ for j := 0; j < 3; j++ {
+ index[j] = int(topic[j])
+ if (topic[3] & (1 << uint(j))) != 0 {
+ index[j] += 256
+ }
+ }
+
+ for j := 0; j < 3; j++ {
+ byteIndex := index[j] / 8
+ bitIndex := index[j] % 8
+ b[byteIndex] = (1 << uint(bitIndex))
+ }
+ return b
+}
diff --git a/whisper/whisperv6/filter.go b/whisper/whisperv6/filter.go
index 2f52dd6b9..eb0c65fa3 100644
--- a/whisper/whisperv6/filter.go
+++ b/whisper/whisperv6/filter.go
@@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/log"
)
+// Filter represents a Whisper message filter
type Filter struct {
Src *ecdsa.PublicKey // Sender of the message
KeyAsym *ecdsa.PrivateKey // Private Key of recipient
@@ -39,12 +40,14 @@ type Filter struct {
mutex sync.RWMutex
}
+// Filters represents a collection of filters
type Filters struct {
watchers map[string]*Filter
whisper *Whisper
mutex sync.RWMutex
}
+// NewFilters returns a newly created filter collection
func NewFilters(w *Whisper) *Filters {
return &Filters{
watchers: make(map[string]*Filter),
@@ -52,6 +55,7 @@ func NewFilters(w *Whisper) *Filters {
}
}
+// Install will add a new filter to the filter collection
func (fs *Filters) Install(watcher *Filter) (string, error) {
if watcher.KeySym != nil && watcher.KeyAsym != nil {
return "", fmt.Errorf("filters must choose between symmetric and asymmetric keys")
@@ -81,6 +85,8 @@ func (fs *Filters) Install(watcher *Filter) (string, error) {
return id, err
}
+// Uninstall will remove a filter whose id has been specified from
+// the filter collection
func (fs *Filters) Uninstall(id string) bool {
fs.mutex.Lock()
defer fs.mutex.Unlock()
@@ -91,12 +97,15 @@ func (fs *Filters) Uninstall(id string) bool {
return false
}
+// Get returns a filter from the collection with a specific ID
func (fs *Filters) Get(id string) *Filter {
fs.mutex.RLock()
defer fs.mutex.RUnlock()
return fs.watchers[id]
}
+// NotifyWatchers notifies any filter that has declared interest
+// for the envelope's topic.
func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
var msg *ReceivedMessage
@@ -140,9 +149,9 @@ func (f *Filter) processEnvelope(env *Envelope) *ReceivedMessage {
msg := env.Open(f)
if msg != nil {
return msg
- } else {
- log.Trace("processing envelope: failed to open", "hash", env.Hash().Hex())
}
+
+ log.Trace("processing envelope: failed to open", "hash", env.Hash().Hex())
} else {
log.Trace("processing envelope: does not match", "hash", env.Hash().Hex())
}
@@ -157,6 +166,8 @@ func (f *Filter) expectsSymmetricEncryption() bool {
return f.KeySym != nil
}
+// Trigger adds a yet-unknown message to the filter's list of
+// received messages.
func (f *Filter) Trigger(msg *ReceivedMessage) {
f.mutex.Lock()
defer f.mutex.Unlock()
@@ -166,6 +177,8 @@ func (f *Filter) Trigger(msg *ReceivedMessage) {
}
}
+// Retrieve will return the list of all received messages associated
+// to a filter.
func (f *Filter) Retrieve() (all []*ReceivedMessage) {
f.mutex.Lock()
defer f.mutex.Unlock()
@@ -195,7 +208,7 @@ func (f *Filter) MatchMessage(msg *ReceivedMessage) bool {
return false
}
-// MatchEvelope checks if it's worth decrypting the message. If
+// MatchEnvelope checks if it's worth decrypting the message. If
// it returns `true`, client code is expected to attempt decrypting
// the message and subsequently call MatchMessage.
func (f *Filter) MatchEnvelope(envelope *Envelope) bool {
@@ -206,6 +219,7 @@ func (f *Filter) MatchEnvelope(envelope *Envelope) bool {
return f.MatchTopic(envelope.Topic)
}
+// MatchTopic checks that the filter captures a given topic.
func (f *Filter) MatchTopic(topic TopicType) bool {
if len(f.Topics) == 0 {
// any topic matches
@@ -221,8 +235,12 @@ func (f *Filter) MatchTopic(topic TopicType) bool {
}
func matchSingleTopic(topic TopicType, bt []byte) bool {
- if len(bt) > 4 {
- bt = bt[:4]
+ if len(bt) > TopicLength {
+ bt = bt[:TopicLength]
+ }
+
+ if len(bt) < TopicLength {
+ return false
}
for j, b := range bt {
@@ -233,6 +251,7 @@ func matchSingleTopic(topic TopicType, bt []byte) bool {
return true
}
+// IsPubKeyEqual checks that two public keys are equal
func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool {
if !ValidatePublicKey(a) {
return false
diff --git a/whisper/whisperv6/filter_test.go b/whisper/whisperv6/filter_test.go
index dd0de0f6e..e7230ef38 100644
--- a/whisper/whisperv6/filter_test.go
+++ b/whisper/whisperv6/filter_test.go
@@ -88,7 +88,7 @@ func generateTestCases(t *testing.T, SizeTestFilters int) []FilterTestCase {
for i := 0; i < SizeTestFilters; i++ {
f, _ := generateFilter(t, true)
cases[i].f = f
- cases[i].alive = (mrand.Int()&int(1) == 0)
+ cases[i].alive = mrand.Int()&int(1) == 0
}
return cases
}
@@ -109,7 +109,7 @@ func TestInstallFilters(t *testing.T) {
t.Fatalf("seed %d: failed to install filter: %s", seed, err)
}
tst[i].id = j
- if len(j) != keyIdSize*2 {
+ if len(j) != keyIDSize*2 {
t.Fatalf("seed %d: wrong filter id size [%d]", seed, len(j))
}
}
@@ -122,7 +122,7 @@ func TestInstallFilters(t *testing.T) {
for i, testCase := range tst {
fil := filters.Get(testCase.id)
- exist := (fil != nil)
+ exist := fil != nil
if exist != testCase.alive {
t.Fatalf("seed %d: failed alive: %d, %v, %v", seed, i, exist, testCase.alive)
}
@@ -800,6 +800,7 @@ func TestWatchers(t *testing.T) {
func TestVariableTopics(t *testing.T) {
InitSingleTest()
+ const lastTopicByte = 3
var match bool
params, err := generateMessageParams()
if err != nil {
@@ -820,19 +821,52 @@ func TestVariableTopics(t *testing.T) {
}
for i := 0; i < 4; i++ {
- arr := make([]byte, i+1, 4)
- copy(arr, env.Topic[:i+1])
-
- f.Topics[4] = arr
+ env.Topic = BytesToTopic(f.Topics[i])
match = f.MatchEnvelope(env)
if !match {
t.Fatalf("failed MatchEnvelope symmetric with seed %d, step %d.", seed, i)
}
- f.Topics[4][i]++
+ f.Topics[i][lastTopicByte]++
match = f.MatchEnvelope(env)
if match {
t.Fatalf("MatchEnvelope symmetric with seed %d, step %d: false positive.", seed, i)
}
}
}
+
+func TestMatchSingleTopic_ReturnTrue(t *testing.T) {
+ bt := []byte("test")
+ topic := BytesToTopic(bt)
+
+ if !matchSingleTopic(topic, bt) {
+ t.FailNow()
+ }
+}
+
+func TestMatchSingleTopic_WithTail_ReturnTrue(t *testing.T) {
+ bt := []byte("test with tail")
+ topic := BytesToTopic([]byte("test"))
+
+ if !matchSingleTopic(topic, bt) {
+ t.FailNow()
+ }
+}
+
+func TestMatchSingleTopic_NotEquals_ReturnFalse(t *testing.T) {
+ bt := []byte("tes")
+ topic := BytesToTopic(bt)
+
+ if matchSingleTopic(topic, bt) {
+ t.FailNow()
+ }
+}
+
+func TestMatchSingleTopic_InsufficientLength_ReturnFalse(t *testing.T) {
+ bt := []byte("test")
+ topic := BytesToTopic([]byte("not_equal"))
+
+ if matchSingleTopic(topic, bt) {
+ t.FailNow()
+ }
+}
diff --git a/whisper/whisperv6/gen_criteria_json.go b/whisper/whisperv6/gen_criteria_json.go
index 52a4d3cb6..1a428d6df 100644
--- a/whisper/whisperv6/gen_criteria_json.go
+++ b/whisper/whisperv6/gen_criteria_json.go
@@ -10,6 +10,7 @@ import (
var _ = (*criteriaOverride)(nil)
+// MarshalJSON marshals type Criteria to a json string
func (c Criteria) MarshalJSON() ([]byte, error) {
type Criteria struct {
SymKeyID string `json:"symKeyID"`
@@ -29,14 +30,15 @@ func (c Criteria) MarshalJSON() ([]byte, error) {
return json.Marshal(&enc)
}
+// UnmarshalJSON unmarshals type Criteria to a json string
func (c *Criteria) UnmarshalJSON(input []byte) error {
type Criteria struct {
- SymKeyID *string `json:"symKeyID"`
- PrivateKeyID *string `json:"privateKeyID"`
- Sig hexutil.Bytes `json:"sig"`
- MinPow *float64 `json:"minPow"`
- Topics []TopicType `json:"topics"`
- AllowP2P *bool `json:"allowP2P"`
+ SymKeyID *string `json:"symKeyID"`
+ PrivateKeyID *string `json:"privateKeyID"`
+ Sig *hexutil.Bytes `json:"sig"`
+ MinPow *float64 `json:"minPow"`
+ Topics []TopicType `json:"topics"`
+ AllowP2P *bool `json:"allowP2P"`
}
var dec Criteria
if err := json.Unmarshal(input, &dec); err != nil {
@@ -49,7 +51,7 @@ func (c *Criteria) UnmarshalJSON(input []byte) error {
c.PrivateKeyID = *dec.PrivateKeyID
}
if dec.Sig != nil {
- c.Sig = dec.Sig
+ c.Sig = *dec.Sig
}
if dec.MinPow != nil {
c.MinPow = *dec.MinPow
diff --git a/whisper/whisperv6/gen_message_json.go b/whisper/whisperv6/gen_message_json.go
index 27b46752b..6218f5df6 100644
--- a/whisper/whisperv6/gen_message_json.go
+++ b/whisper/whisperv6/gen_message_json.go
@@ -10,6 +10,7 @@ import (
var _ = (*messageOverride)(nil)
+// MarshalJSON marshals type Message to a json string
func (m Message) MarshalJSON() ([]byte, error) {
type Message struct {
Sig hexutil.Bytes `json:"sig,omitempty"`
@@ -35,24 +36,25 @@ func (m Message) MarshalJSON() ([]byte, error) {
return json.Marshal(&enc)
}
+// UnmarshalJSON unmarshals type Message to a json string
func (m *Message) UnmarshalJSON(input []byte) error {
type Message struct {
- Sig hexutil.Bytes `json:"sig,omitempty"`
- TTL *uint32 `json:"ttl"`
- Timestamp *uint32 `json:"timestamp"`
- Topic *TopicType `json:"topic"`
- Payload hexutil.Bytes `json:"payload"`
- Padding hexutil.Bytes `json:"padding"`
- PoW *float64 `json:"pow"`
- Hash hexutil.Bytes `json:"hash"`
- Dst hexutil.Bytes `json:"recipientPublicKey,omitempty"`
+ Sig *hexutil.Bytes `json:"sig,omitempty"`
+ TTL *uint32 `json:"ttl"`
+ Timestamp *uint32 `json:"timestamp"`
+ Topic *TopicType `json:"topic"`
+ Payload *hexutil.Bytes `json:"payload"`
+ Padding *hexutil.Bytes `json:"padding"`
+ PoW *float64 `json:"pow"`
+ Hash *hexutil.Bytes `json:"hash"`
+ Dst *hexutil.Bytes `json:"recipientPublicKey,omitempty"`
}
var dec Message
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Sig != nil {
- m.Sig = dec.Sig
+ m.Sig = *dec.Sig
}
if dec.TTL != nil {
m.TTL = *dec.TTL
@@ -64,19 +66,19 @@ func (m *Message) UnmarshalJSON(input []byte) error {
m.Topic = *dec.Topic
}
if dec.Payload != nil {
- m.Payload = dec.Payload
+ m.Payload = *dec.Payload
}
if dec.Padding != nil {
- m.Padding = dec.Padding
+ m.Padding = *dec.Padding
}
if dec.PoW != nil {
m.PoW = *dec.PoW
}
if dec.Hash != nil {
- m.Hash = dec.Hash
+ m.Hash = *dec.Hash
}
if dec.Dst != nil {
- m.Dst = dec.Dst
+ m.Dst = *dec.Dst
}
return nil
}
diff --git a/whisper/whisperv6/gen_newmessage_json.go b/whisper/whisperv6/gen_newmessage_json.go
index d16011a57..75a1279ae 100644
--- a/whisper/whisperv6/gen_newmessage_json.go
+++ b/whisper/whisperv6/gen_newmessage_json.go
@@ -10,6 +10,7 @@ import (
var _ = (*newMessageOverride)(nil)
+// MarshalJSON marshals type NewMessage to a json string
func (n NewMessage) MarshalJSON() ([]byte, error) {
type NewMessage struct {
SymKeyID string `json:"symKeyID"`
@@ -37,18 +38,19 @@ func (n NewMessage) MarshalJSON() ([]byte, error) {
return json.Marshal(&enc)
}
+// UnmarshalJSON unmarshals type NewMessage to a json string
func (n *NewMessage) UnmarshalJSON(input []byte) error {
type NewMessage struct {
- SymKeyID *string `json:"symKeyID"`
- PublicKey hexutil.Bytes `json:"pubKey"`
- Sig *string `json:"sig"`
- TTL *uint32 `json:"ttl"`
- Topic *TopicType `json:"topic"`
- Payload hexutil.Bytes `json:"payload"`
- Padding hexutil.Bytes `json:"padding"`
- PowTime *uint32 `json:"powTime"`
- PowTarget *float64 `json:"powTarget"`
- TargetPeer *string `json:"targetPeer"`
+ SymKeyID *string `json:"symKeyID"`
+ PublicKey *hexutil.Bytes `json:"pubKey"`
+ Sig *string `json:"sig"`
+ TTL *uint32 `json:"ttl"`
+ Topic *TopicType `json:"topic"`
+ Payload *hexutil.Bytes `json:"payload"`
+ Padding *hexutil.Bytes `json:"padding"`
+ PowTime *uint32 `json:"powTime"`
+ PowTarget *float64 `json:"powTarget"`
+ TargetPeer *string `json:"targetPeer"`
}
var dec NewMessage
if err := json.Unmarshal(input, &dec); err != nil {
@@ -58,7 +60,7 @@ func (n *NewMessage) UnmarshalJSON(input []byte) error {
n.SymKeyID = *dec.SymKeyID
}
if dec.PublicKey != nil {
- n.PublicKey = dec.PublicKey
+ n.PublicKey = *dec.PublicKey
}
if dec.Sig != nil {
n.Sig = *dec.Sig
@@ -70,10 +72,10 @@ func (n *NewMessage) UnmarshalJSON(input []byte) error {
n.Topic = *dec.Topic
}
if dec.Payload != nil {
- n.Payload = dec.Payload
+ n.Payload = *dec.Payload
}
if dec.Padding != nil {
- n.Padding = dec.Padding
+ n.Padding = *dec.Padding
}
if dec.PowTime != nil {
n.PowTime = *dec.PowTime
diff --git a/whisper/whisperv6/message.go b/whisper/whisperv6/message.go
index f8df50336..b8318cbe8 100644
--- a/whisper/whisperv6/message.go
+++ b/whisper/whisperv6/message.go
@@ -25,6 +25,7 @@ import (
crand "crypto/rand"
"encoding/binary"
"errors"
+ mrand "math/rand"
"strconv"
"github.com/ethereum/go-ethereum/common"
@@ -33,7 +34,8 @@ import (
"github.com/ethereum/go-ethereum/log"
)
-// Options specifies the exact way a message should be wrapped into an Envelope.
+// MessageParams specifies the exact way a message should be wrapped
+// into an Envelope.
type MessageParams struct {
TTL uint32
Src *ecdsa.PrivateKey
@@ -54,7 +56,7 @@ type sentMessage struct {
}
// ReceivedMessage represents a data packet to be received through the
-// Whisper protocol.
+// Whisper protocol and successfully decrypted.
type ReceivedMessage struct {
Raw []byte
@@ -70,7 +72,7 @@ type ReceivedMessage struct {
Dst *ecdsa.PublicKey // Message recipient (identity used to decode the message)
Topic TopicType
- SymKeyHash common.Hash // The Keccak256Hash of the key, associated with the Topic
+ SymKeyHash common.Hash // The Keccak256Hash of the key
EnvelopeHash common.Hash // Message envelope hash to act as a unique id
}
@@ -86,83 +88,62 @@ func (msg *ReceivedMessage) isAsymmetricEncryption() bool {
return msg.Dst != nil
}
-// NewMessage creates and initializes a non-signed, non-encrypted Whisper message.
+// NewSentMessage creates and initializes a non-signed, non-encrypted Whisper message.
func NewSentMessage(params *MessageParams) (*sentMessage, error) {
+ const payloadSizeFieldMaxSize = 4
msg := sentMessage{}
- msg.Raw = make([]byte, 1, len(params.Payload)+len(params.Padding)+signatureLength+padSizeLimit)
+ msg.Raw = make([]byte, 1,
+ flagsLength+payloadSizeFieldMaxSize+len(params.Payload)+len(params.Padding)+signatureLength+padSizeLimit)
msg.Raw[0] = 0 // set all the flags to zero
- err := msg.appendPadding(params)
- if err != nil {
- return nil, err
- }
+ msg.addPayloadSizeField(params.Payload)
msg.Raw = append(msg.Raw, params.Payload...)
- return &msg, nil
+ err := msg.appendPadding(params)
+ return &msg, err
}
-// getSizeOfLength returns the number of bytes necessary to encode the entire size padding (including these bytes)
-func getSizeOfLength(b []byte) (sz int, err error) {
- sz = intSize(len(b)) // first iteration
- sz = intSize(len(b) + sz) // second iteration
- if sz > 3 {
- err = errors.New("oversized padding parameter")
- }
- return sz, err
+// addPayloadSizeField appends the auxiliary field containing the size of payload
+func (msg *sentMessage) addPayloadSizeField(payload []byte) {
+ fieldSize := getSizeOfPayloadSizeField(payload)
+ field := make([]byte, 4)
+ binary.LittleEndian.PutUint32(field, uint32(len(payload)))
+ field = field[:fieldSize]
+ msg.Raw = append(msg.Raw, field...)
+ msg.Raw[0] |= byte(fieldSize)
}
-// sizeOfIntSize returns minimal number of bytes necessary to encode an integer value
-func intSize(i int) (s int) {
- for s = 1; i >= 256; s++ {
- i /= 256
+// getSizeOfPayloadSizeField returns the number of bytes necessary to encode the size of payload
+func getSizeOfPayloadSizeField(payload []byte) int {
+ s := 1
+ for i := len(payload); i >= 256; i /= 256 {
+ s++
}
return s
}
-// appendPadding appends the pseudorandom padding bytes and sets the padding flag.
-// The last byte contains the size of padding (thus, its size must not exceed 256).
+// appendPadding appends the padding specified in params.
+// If no padding is provided in params, then random padding is generated.
func (msg *sentMessage) appendPadding(params *MessageParams) error {
- rawSize := len(params.Payload) + 1
- if params.Src != nil {
- rawSize += signatureLength
+ if len(params.Padding) != 0 {
+ // padding data was provided by the Dapp, just use it as is
+ msg.Raw = append(msg.Raw, params.Padding...)
+ return nil
}
- if params.KeySym != nil {
- rawSize += AESNonceLength
+ rawSize := flagsLength + getSizeOfPayloadSizeField(params.Payload) + len(params.Payload)
+ if params.Src != nil {
+ rawSize += signatureLength
}
odd := rawSize % padSizeLimit
-
- if len(params.Padding) != 0 {
- padSize := len(params.Padding)
- padLengthSize, err := getSizeOfLength(params.Padding)
- if err != nil {
- return err
- }
- totalPadSize := padSize + padLengthSize
- buf := make([]byte, 8)
- binary.LittleEndian.PutUint32(buf, uint32(totalPadSize))
- buf = buf[:padLengthSize]
- msg.Raw = append(msg.Raw, buf...)
- msg.Raw = append(msg.Raw, params.Padding...)
- msg.Raw[0] |= byte(padLengthSize) // number of bytes indicating the padding size
- } else if odd != 0 {
- totalPadSize := padSizeLimit - odd
- if totalPadSize > 255 {
- // this algorithm is only valid if padSizeLimit < 256.
- // if padSizeLimit will ever change, please fix the algorithm
- // (please see also ReceivedMessage.extractPadding() function).
- panic("please fix the padding algorithm before releasing new version")
- }
- buf := make([]byte, totalPadSize)
- _, err := crand.Read(buf[1:])
- if err != nil {
- return err
- }
- if totalPadSize > 6 && !validateSymmetricKey(buf) {
- return errors.New("failed to generate random padding of size " + strconv.Itoa(totalPadSize))
- }
- buf[0] = byte(totalPadSize)
- msg.Raw = append(msg.Raw, buf...)
- msg.Raw[0] |= byte(0x1) // number of bytes indicating the padding size
+ paddingSize := padSizeLimit - odd
+ pad := make([]byte, paddingSize)
+ _, err := crand.Read(pad)
+ if err != nil {
+ return err
}
+ if !validateDataIntegrity(pad, paddingSize) {
+ return errors.New("failed to generate random padding of size " + strconv.Itoa(paddingSize))
+ }
+ msg.Raw = append(msg.Raw, pad...)
return nil
}
@@ -175,11 +156,11 @@ func (msg *sentMessage) sign(key *ecdsa.PrivateKey) error {
return nil
}
- msg.Raw[0] |= signatureFlag
+ msg.Raw[0] |= signatureFlag // it is important to set this flag before signing
hash := crypto.Keccak256(msg.Raw)
signature, err := crypto.Sign(hash, key)
if err != nil {
- msg.Raw[0] &= ^signatureFlag // clear the flag
+ msg.Raw[0] &= (0xFF ^ signatureFlag) // clear the flag
return err
}
msg.Raw = append(msg.Raw, signature...)
@@ -201,10 +182,9 @@ func (msg *sentMessage) encryptAsymmetric(key *ecdsa.PublicKey) error {
// encryptSymmetric encrypts a message with a topic key, using AES-GCM-256.
// nonce size should be 12 bytes (see cipher.gcmStandardNonceSize).
func (msg *sentMessage) encryptSymmetric(key []byte) (err error) {
- if !validateSymmetricKey(key) {
- return errors.New("invalid key provided for symmetric encryption")
+ if !validateDataIntegrity(key, aesKeyLength) {
+ return errors.New("invalid key provided for symmetric encryption, size: " + strconv.Itoa(len(key)))
}
-
block, err := aes.NewCipher(key)
if err != nil {
return err
@@ -213,20 +193,46 @@ func (msg *sentMessage) encryptSymmetric(key []byte) (err error) {
if err != nil {
return err
}
-
- // never use more than 2^32 random nonces with a given key
- salt := make([]byte, aesgcm.NonceSize())
- _, err = crand.Read(salt)
+ salt, err := generateSecureRandomData(aesNonceLength) // never use more than 2^32 random nonces with a given key
if err != nil {
return err
- } else if !validateSymmetricKey(salt) {
- return errors.New("crypto/rand failed to generate salt")
}
-
- msg.Raw = append(aesgcm.Seal(nil, salt, msg.Raw, nil), salt...)
+ encrypted := aesgcm.Seal(nil, salt, msg.Raw, nil)
+ msg.Raw = append(encrypted, salt...)
return nil
}
+// generateSecureRandomData generates random data where extra security is required.
+// The purpose of this function is to prevent some bugs in software or in hardware
+// from delivering not-very-random data. This is especially useful for AES nonce,
+// where true randomness does not really matter, but it is very important to have
+// a unique nonce for every message.
+func generateSecureRandomData(length int) ([]byte, error) {
+ x := make([]byte, length)
+ y := make([]byte, length)
+ res := make([]byte, length)
+
+ _, err := crand.Read(x)
+ if err != nil {
+ return nil, err
+ } else if !validateDataIntegrity(x, length) {
+ return nil, errors.New("crypto/rand failed to generate secure random data")
+ }
+ _, err = mrand.Read(y)
+ if err != nil {
+ return nil, err
+ } else if !validateDataIntegrity(y, length) {
+ return nil, errors.New("math/rand failed to generate secure random data")
+ }
+ for i := 0; i < length; i++ {
+ res[i] = x[i] ^ y[i]
+ }
+ if !validateDataIntegrity(res, length) {
+ return nil, errors.New("failed to generate secure random data")
+ }
+ return res, nil
+}
+
// Wrap bundles the message into an Envelope to transmit over the network.
func (msg *sentMessage) Wrap(options *MessageParams) (envelope *Envelope, err error) {
if options.TTL == 0 {
@@ -258,12 +264,11 @@ func (msg *sentMessage) Wrap(options *MessageParams) (envelope *Envelope, err er
// decryptSymmetric decrypts a message with a topic key, using AES-GCM-256.
// nonce size should be 12 bytes (see cipher.gcmStandardNonceSize).
func (msg *ReceivedMessage) decryptSymmetric(key []byte) error {
- // In v6, symmetric messages are expected to contain the 12-byte
- // "salt" at the end of the payload.
- if len(msg.Raw) < AESNonceLength {
+ // symmetric messages are expected to contain the 12-byte nonce at the end of the payload
+ if len(msg.Raw) < aesNonceLength {
return errors.New("missing salt or invalid payload in symmetric message")
}
- salt := msg.Raw[len(msg.Raw)-AESNonceLength:]
+ salt := msg.Raw[len(msg.Raw)-aesNonceLength:]
block, err := aes.NewCipher(key)
if err != nil {
@@ -273,11 +278,7 @@ func (msg *ReceivedMessage) decryptSymmetric(key []byte) error {
if err != nil {
return err
}
- if len(salt) != aesgcm.NonceSize() {
- log.Error("decrypting the message", "AES salt size", len(salt))
- return errors.New("wrong AES salt size")
- }
- decrypted, err := aesgcm.Open(nil, salt, msg.Raw[:len(msg.Raw)-AESNonceLength], nil)
+ decrypted, err := aesgcm.Open(nil, salt, msg.Raw[:len(msg.Raw)-aesNonceLength], nil)
if err != nil {
return err
}
@@ -295,8 +296,8 @@ func (msg *ReceivedMessage) decryptAsymmetric(key *ecdsa.PrivateKey) error {
return err
}
-// Validate checks the validity and extracts the fields in case of success
-func (msg *ReceivedMessage) Validate() bool {
+// ValidateAndParse checks the message validity and extracts the fields in case of success.
+func (msg *ReceivedMessage) ValidateAndParse() bool {
end := len(msg.Raw)
if end < 1 {
return false
@@ -307,41 +308,32 @@ func (msg *ReceivedMessage) Validate() bool {
if end <= 1 {
return false
}
- msg.Signature = msg.Raw[end:]
+ msg.Signature = msg.Raw[end : end+signatureLength]
msg.Src = msg.SigToPubKey()
if msg.Src == nil {
return false
}
}
- padSize, ok := msg.extractPadding(end)
- if !ok {
- return false
+ beg := 1
+ payloadSize := 0
+ sizeOfPayloadSizeField := int(msg.Raw[0] & SizeMask) // number of bytes indicating the size of payload
+ if sizeOfPayloadSizeField != 0 {
+ payloadSize = int(bytesToUintLittleEndian(msg.Raw[beg : beg+sizeOfPayloadSizeField]))
+ if payloadSize+1 > end {
+ return false
+ }
+ beg += sizeOfPayloadSizeField
+ msg.Payload = msg.Raw[beg : beg+payloadSize]
}
- msg.Payload = msg.Raw[1+padSize : end]
+ beg += payloadSize
+ msg.Padding = msg.Raw[beg:end]
return true
}
-// extractPadding extracts the padding from raw message.
-// although we don't support sending messages with padding size
-// exceeding 255 bytes, such messages are perfectly valid, and
-// can be successfully decrypted.
-func (msg *ReceivedMessage) extractPadding(end int) (int, bool) {
- paddingSize := 0
- sz := int(msg.Raw[0] & paddingMask) // number of bytes indicating the entire size of padding (including these bytes)
- // could be zero -- it means no padding
- if sz != 0 {
- paddingSize = int(bytesToUintLittleEndian(msg.Raw[1 : 1+sz]))
- if paddingSize < sz || paddingSize+1 > end {
- return 0, false
- }
- msg.Padding = msg.Raw[1+sz : 1+paddingSize]
- }
- return paddingSize, true
-}
-
-// Recover retrieves the public key of the message signer.
+// SigToPubKey returns the public key associated to the message's
+// signature.
func (msg *ReceivedMessage) SigToPubKey() *ecdsa.PublicKey {
defer func() { recover() }() // in case of invalid signature
@@ -353,7 +345,7 @@ func (msg *ReceivedMessage) SigToPubKey() *ecdsa.PublicKey {
return pub
}
-// hash calculates the SHA3 checksum of the message flags, payload and padding.
+// hash calculates the SHA3 checksum of the message flags, payload size field, payload and padding.
func (msg *ReceivedMessage) hash() []byte {
if isMessageSigned(msg.Raw[0]) {
sz := len(msg.Raw) - signatureLength
diff --git a/whisper/whisperv6/message_test.go b/whisper/whisperv6/message_test.go
index c90bcc01e..0a5c1c853 100644
--- a/whisper/whisperv6/message_test.go
+++ b/whisper/whisperv6/message_test.go
@@ -18,9 +18,12 @@ package whisperv6
import (
"bytes"
+ "crypto/aes"
+ "crypto/cipher"
mrand "math/rand"
"testing"
+ "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -90,8 +93,8 @@ func singleMessageTest(t *testing.T, symmetric bool) {
t.Fatalf("failed to encrypt with seed %d: %s.", seed, err)
}
- if !decrypted.Validate() {
- t.Fatalf("failed to validate with seed %d.", seed)
+ if !decrypted.ValidateAndParse() {
+ t.Fatalf("failed to validate with seed %d, symmetric = %v.", seed, symmetric)
}
if !bytes.Equal(text, decrypted.Payload) {
@@ -206,7 +209,7 @@ func TestEnvelopeOpen(t *testing.T) {
InitSingleTest()
var symmetric bool
- for i := 0; i < 256; i++ {
+ for i := 0; i < 32; i++ {
singleEnvelopeOpenTest(t, symmetric)
symmetric = !symmetric
}
@@ -417,30 +420,6 @@ func TestPadding(t *testing.T) {
}
}
-func TestPaddingAppendedToSymMessages(t *testing.T) {
- params := &MessageParams{
- Payload: make([]byte, 246),
- KeySym: make([]byte, aesKeyLength),
- }
-
- // Simulate a message with a payload just under 256 so that
- // payload + flag + aesnonce > 256. Check that the result
- // is padded on the next 256 boundary.
- msg := sentMessage{}
- msg.Raw = make([]byte, len(params.Payload)+1+AESNonceLength)
-
- err := msg.appendPadding(params)
-
- if err != nil {
- t.Fatalf("Error appending padding to message %v", err)
- return
- }
-
- if len(msg.Raw) != 512 {
- t.Errorf("Invalid size %d != 512", len(msg.Raw))
- }
-}
-
func TestPaddingAppendedToSymMessagesWithSignature(t *testing.T) {
params := &MessageParams{
Payload: make([]byte, 246),
@@ -456,10 +435,11 @@ func TestPaddingAppendedToSymMessagesWithSignature(t *testing.T) {
params.Src = pSrc
// Simulate a message with a payload just under 256 so that
- // payload + flag + aesnonce > 256. Check that the result
+ // payload + flag + signature > 256. Check that the result
// is padded on the next 256 boundary.
msg := sentMessage{}
- msg.Raw = make([]byte, len(params.Payload)+1+AESNonceLength+signatureLength)
+ const payloadSizeFieldMinSize = 1
+ msg.Raw = make([]byte, flagsLength+payloadSizeFieldMinSize+len(params.Payload))
err = msg.appendPadding(params)
@@ -468,7 +448,24 @@ func TestPaddingAppendedToSymMessagesWithSignature(t *testing.T) {
return
}
- if len(msg.Raw) != 512 {
+ if len(msg.Raw) != 512-signatureLength {
t.Errorf("Invalid size %d != 512", len(msg.Raw))
}
}
+
+func TestAesNonce(t *testing.T) {
+ key := hexutil.MustDecode("0x03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31")
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ t.Fatalf("NewCipher failed: %s", err)
+ }
+ aesgcm, err := cipher.NewGCM(block)
+ if err != nil {
+ t.Fatalf("NewGCM failed: %s", err)
+ }
+ // This is the most important single test in this package.
+ // If it fails, whisper will not be working.
+ if aesgcm.NonceSize() != aesNonceLength {
+ t.Fatalf("Nonce size is wrong. This is a critical error. Apparently AES nonce size have changed in the new version of AES GCM package. Whisper will not be working until this problem is resolved.")
+ }
+}
diff --git a/whisper/whisperv6/peer.go b/whisper/whisperv6/peer.go
index 65e0c77b0..4ef0f3c43 100644
--- a/whisper/whisperv6/peer.go
+++ b/whisper/whisperv6/peer.go
@@ -28,7 +28,7 @@ import (
set "gopkg.in/fatih/set.v0"
)
-// peer represents a whisper protocol peer connection.
+// Peer represents a whisper protocol peer connection.
type Peer struct {
host *Whisper
peer *p2p.Peer
@@ -36,6 +36,8 @@ type Peer struct {
trusted bool
powRequirement float64
+ bloomFilter []byte
+ fullNode bool
known *set.Set // Messages already known by the peer to avoid wasting bandwidth
@@ -52,56 +54,86 @@ func newPeer(host *Whisper, remote *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
powRequirement: 0.0,
known: set.New(),
quit: make(chan struct{}),
+ bloomFilter: makeFullNodeBloom(),
+ fullNode: true,
}
}
// start initiates the peer updater, periodically broadcasting the whisper packets
// into the network.
-func (p *Peer) start() {
- go p.update()
- log.Trace("start", "peer", p.ID())
+func (peer *Peer) start() {
+ go peer.update()
+ log.Trace("start", "peer", peer.ID())
}
// stop terminates the peer updater, stopping message forwarding to it.
-func (p *Peer) stop() {
- close(p.quit)
- log.Trace("stop", "peer", p.ID())
+func (peer *Peer) stop() {
+ close(peer.quit)
+ log.Trace("stop", "peer", peer.ID())
}
// handshake sends the protocol initiation status message to the remote peer and
// verifies the remote status too.
-func (p *Peer) handshake() error {
+func (peer *Peer) handshake() error {
// Send the handshake status message asynchronously
errc := make(chan error, 1)
go func() {
- errc <- p2p.Send(p.ws, statusCode, ProtocolVersion)
+ pow := peer.host.MinPow()
+ powConverted := math.Float64bits(pow)
+ bloom := peer.host.BloomFilter()
+ errc <- p2p.SendItems(peer.ws, statusCode, ProtocolVersion, powConverted, bloom)
}()
+
// Fetch the remote status packet and verify protocol match
- packet, err := p.ws.ReadMsg()
+ packet, err := peer.ws.ReadMsg()
if err != nil {
return err
}
if packet.Code != statusCode {
- return fmt.Errorf("peer [%x] sent packet %x before status packet", p.ID(), packet.Code)
+ return fmt.Errorf("peer [%x] sent packet %x before status packet", peer.ID(), packet.Code)
}
s := rlp.NewStream(packet.Payload, uint64(packet.Size))
+ _, err = s.List()
+ if err != nil {
+ return fmt.Errorf("peer [%x] sent bad status message: %v", peer.ID(), err)
+ }
peerVersion, err := s.Uint()
if err != nil {
- return fmt.Errorf("peer [%x] sent bad status message: %v", p.ID(), err)
+ return fmt.Errorf("peer [%x] sent bad status message (unable to decode version): %v", peer.ID(), err)
}
if peerVersion != ProtocolVersion {
- return fmt.Errorf("peer [%x]: protocol version mismatch %d != %d", p.ID(), peerVersion, ProtocolVersion)
+ return fmt.Errorf("peer [%x]: protocol version mismatch %d != %d", peer.ID(), peerVersion, ProtocolVersion)
+ }
+
+ // only version is mandatory, subsequent parameters are optional
+ powRaw, err := s.Uint()
+ if err == nil {
+ pow := math.Float64frombits(powRaw)
+ if math.IsInf(pow, 0) || math.IsNaN(pow) || pow < 0.0 {
+ return fmt.Errorf("peer [%x] sent bad status message: invalid pow", peer.ID())
+ }
+ peer.powRequirement = pow
+
+ var bloom []byte
+ err = s.Decode(&bloom)
+ if err == nil {
+ sz := len(bloom)
+ if sz != bloomFilterSize && sz != 0 {
+ return fmt.Errorf("peer [%x] sent bad status message: wrong bloom filter size %d", peer.ID(), sz)
+ }
+ peer.setBloomFilter(bloom)
+ }
}
- // Wait until out own status is consumed too
+
if err := <-errc; err != nil {
- return fmt.Errorf("peer [%x] failed to send status packet: %v", p.ID(), err)
+ return fmt.Errorf("peer [%x] failed to send status packet: %v", peer.ID(), err)
}
return nil
}
// update executes periodic operations on the peer, including message transmission
// and expiration.
-func (p *Peer) update() {
+func (peer *Peer) update() {
// Start the tickers for the updates
expire := time.NewTicker(expirationCycle)
transmit := time.NewTicker(transmissionCycle)
@@ -110,15 +142,15 @@ func (p *Peer) update() {
for {
select {
case <-expire.C:
- p.expire()
+ peer.expire()
case <-transmit.C:
- if err := p.broadcast(); err != nil {
- log.Trace("broadcast failed", "reason", err, "peer", p.ID())
+ if err := peer.broadcast(); err != nil {
+ log.Trace("broadcast failed", "reason", err, "peer", peer.ID())
return
}
- case <-p.quit:
+ case <-peer.quit:
return
}
}
@@ -152,24 +184,24 @@ func (peer *Peer) expire() {
// broadcast iterates over the collection of envelopes and transmits yet unknown
// ones over the network.
-func (p *Peer) broadcast() error {
- envelopes := p.host.Envelopes()
+func (peer *Peer) broadcast() error {
+ envelopes := peer.host.Envelopes()
bundle := make([]*Envelope, 0, len(envelopes))
for _, envelope := range envelopes {
- if !p.marked(envelope) && envelope.PoW() >= p.powRequirement {
+ if !peer.marked(envelope) && envelope.PoW() >= peer.powRequirement && peer.bloomMatch(envelope) {
bundle = append(bundle, envelope)
}
}
if len(bundle) > 0 {
// transmit the batch of envelopes
- if err := p2p.Send(p.ws, messagesCode, bundle); err != nil {
+ if err := p2p.Send(peer.ws, messagesCode, bundle); err != nil {
return err
}
// mark envelopes only if they were successfully sent
for _, e := range bundle {
- p.mark(e)
+ peer.mark(e)
}
log.Trace("broadcast", "num. messages", len(bundle))
@@ -177,12 +209,37 @@ func (p *Peer) broadcast() error {
return nil
}
-func (p *Peer) ID() []byte {
- id := p.peer.ID()
+// ID returns a peer's id
+func (peer *Peer) ID() []byte {
+ id := peer.peer.ID()
return id[:]
}
-func (p *Peer) notifyAboutPowRequirementChange(pow float64) error {
+func (peer *Peer) notifyAboutPowRequirementChange(pow float64) error {
i := math.Float64bits(pow)
- return p2p.Send(p.ws, powRequirementCode, i)
+ return p2p.Send(peer.ws, powRequirementCode, i)
+}
+
+func (peer *Peer) notifyAboutBloomFilterChange(bloom []byte) error {
+ return p2p.Send(peer.ws, bloomFilterExCode, bloom)
+}
+
+func (peer *Peer) bloomMatch(env *Envelope) bool {
+ return peer.fullNode || bloomFilterMatch(peer.bloomFilter, env.Bloom())
+}
+
+func (peer *Peer) setBloomFilter(bloom []byte) {
+ peer.bloomFilter = bloom
+ peer.fullNode = isFullNode(bloom)
+ if peer.fullNode && peer.bloomFilter == nil {
+ peer.bloomFilter = makeFullNodeBloom()
+ }
+}
+
+func makeFullNodeBloom() []byte {
+ bloom := make([]byte, bloomFilterSize)
+ for i := 0; i < bloomFilterSize; i++ {
+ bloom[i] = 0xFF
+ }
+ return bloom
}
diff --git a/whisper/whisperv6/peer_test.go b/whisper/whisperv6/peer_test.go
index 599a479be..9ce5eed8b 100644
--- a/whisper/whisperv6/peer_test.go
+++ b/whisper/whisperv6/peer_test.go
@@ -20,19 +20,21 @@ import (
"bytes"
"crypto/ecdsa"
"fmt"
+ mrand "math/rand"
"net"
"sync"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/nat"
)
-var keys []string = []string{
+var keys = []string{
"d49dcf37238dc8a7aac57dc61b9fee68f0a97f062968978b9fafa7d1033d03a9",
"73fd6143c48e80ed3c56ea159fe7494a0b6b393a392227b422f4c3e8f1b54f98",
"119dd32adb1daa7a4c7bf77f847fb28730785aa92947edf42fdd997b54de40dc",
@@ -68,9 +70,8 @@ var keys []string = []string{
"7184c1701569e3a4c4d2ddce691edd983b81e42e09196d332e1ae2f1e062cff4",
}
-const NumNodes = 16 // must not exceed the number of keys (32)
-
type TestData struct {
+ started int
counter [NumNodes]int
mutex sync.RWMutex
}
@@ -79,21 +80,32 @@ type TestNode struct {
shh *Whisper
id *ecdsa.PrivateKey
server *p2p.Server
- filerId string
+ filerID string
}
+const NumNodes = 8 // must not exceed the number of keys (32)
+
var result TestData
var nodes [NumNodes]*TestNode
-var sharedKey []byte = []byte("some arbitrary data here")
-var sharedTopic TopicType = TopicType{0xF, 0x1, 0x2, 0}
-var expectedMessage []byte = []byte("per rectum ad astra")
+var sharedKey = hexutil.MustDecode("0x03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31")
+var wrongKey = hexutil.MustDecode("0xf91156714d7ec88d3edc1c652c2181dbb3044e8771c683f3b30d33c12b986b11")
+var sharedTopic = TopicType{0xF, 0x1, 0x2, 0}
+var wrongTopic = TopicType{0, 0, 0, 0}
+var expectedMessage = []byte("per aspera ad astra")
+var unexpectedMessage = []byte("per rectum ad astra")
+var masterBloomFilter []byte
+var masterPow = 0.00000001
+var round = 1
+var debugMode = false
+var prevTime time.Time
+var cntPrev int
func TestSimulation(t *testing.T) {
// create a chain of whisper nodes,
// installs the filters with shared (predefined) parameters
initialize(t)
- // each node sends a number of random (undecryptable) messages
+ // each node sends one random (not decryptable) message
for i := 0; i < NumNodes; i++ {
sendMsg(t, false, i)
}
@@ -104,8 +116,12 @@ func TestSimulation(t *testing.T) {
// check if each node have received and decrypted exactly one message
checkPropagation(t, true)
- // send protocol-level messages (powRequirementCode) and check the new PoW requirement values
- powReqExchange(t)
+ // check if Status message was correctly decoded
+ checkBloomFilterExchange(t)
+ checkPowExchange(t)
+
+ // send new pow and bloom exchange messages
+ resetParams(t)
// node #1 sends one expected (decryptable) message
sendMsg(t, true, 1)
@@ -113,24 +129,68 @@ func TestSimulation(t *testing.T) {
// check if each node (except node #0) have received and decrypted exactly one message
checkPropagation(t, false)
+ // check if corresponding protocol-level messages were correctly decoded
+ checkPowExchangeForNodeZero(t)
+ checkBloomFilterExchange(t)
+
stopServers()
}
+func resetParams(t *testing.T) {
+ // change pow only for node zero
+ masterPow = 7777777.0
+ nodes[0].shh.SetMinimumPoW(masterPow)
+
+ // change bloom for all nodes
+ masterBloomFilter = TopicToBloom(sharedTopic)
+ for i := 0; i < NumNodes; i++ {
+ nodes[i].shh.SetBloomFilter(masterBloomFilter)
+ }
+
+ round++
+}
+
+func initBloom(t *testing.T) {
+ masterBloomFilter = make([]byte, bloomFilterSize)
+ _, err := mrand.Read(masterBloomFilter)
+ if err != nil {
+ t.Fatalf("rand failed: %s.", err)
+ }
+
+ msgBloom := TopicToBloom(sharedTopic)
+ masterBloomFilter = addBloom(masterBloomFilter, msgBloom)
+ for i := 0; i < 32; i++ {
+ masterBloomFilter[i] = 0xFF
+ }
+
+ if !bloomFilterMatch(masterBloomFilter, msgBloom) {
+ t.Fatalf("bloom mismatch on initBloom.")
+ }
+}
+
func initialize(t *testing.T) {
+ initBloom(t)
+
var err error
ip := net.IPv4(127, 0, 0, 1)
port0 := 30303
for i := 0; i < NumNodes; i++ {
var node TestNode
+ b := make([]byte, bloomFilterSize)
+ copy(b, masterBloomFilter)
node.shh = New(&DefaultConfig)
- node.shh.SetMinimumPowTest(0.00000001)
+ node.shh.SetMinimumPoW(masterPow)
+ node.shh.SetBloomFilter(b)
+ if !bytes.Equal(node.shh.BloomFilter(), masterBloomFilter) {
+ t.Fatalf("bloom mismatch on init.")
+ }
node.shh.Start(nil)
topics := make([]TopicType, 0)
topics = append(topics, sharedTopic)
f := Filter{KeySym: sharedKey}
f.Topics = [][]byte{topics[0][:]}
- node.filerId, err = node.shh.Subscribe(&f)
+ node.filerID, err = node.shh.Subscribe(&f)
if err != nil {
t.Fatalf("failed to install the filter: %s.", err)
}
@@ -143,9 +203,9 @@ func initialize(t *testing.T) {
name := common.MakeName("whisper-go", "2.0")
var peers []*discover.Node
if i > 0 {
- peerNodeId := nodes[i-1].id
+ peerNodeID := nodes[i-1].id
peerPort := uint16(port - 1)
- peerNode := discover.PubkeyID(&peerNodeId.PublicKey)
+ peerNode := discover.PubkeyID(&peerNodeID.PublicKey)
peer := discover.NewNode(peerNode, ip, peerPort, peerPort)
peers = append(peers, peer)
}
@@ -167,22 +227,29 @@ func initialize(t *testing.T) {
nodes[i] = &node
}
- for i := 1; i < NumNodes; i++ {
- go nodes[i].server.Start()
+ for i := 0; i < NumNodes; i++ {
+ go startServer(t, nodes[i].server)
}
- // we need to wait until the first node actually starts
- err = nodes[0].server.Start()
+ waitForServersToStart(t)
+}
+
+func startServer(t *testing.T, s *p2p.Server) {
+ err := s.Start()
if err != nil {
t.Fatalf("failed to start the fisrt server.")
}
+
+ result.mutex.Lock()
+ defer result.mutex.Unlock()
+ result.started++
}
func stopServers() {
for i := 0; i < NumNodes; i++ {
n := nodes[i]
if n != nil {
- n.shh.Unsubscribe(n.filerId)
+ n.shh.Unsubscribe(n.filerID)
n.shh.Stop()
n.server.Stop()
}
@@ -194,8 +261,10 @@ func checkPropagation(t *testing.T, includingNodeZero bool) {
return
}
- const cycle = 50
- const iterations = 200
+ prevTime = time.Now()
+ // (cycle * iterations) should not exceed 50 seconds, since TTL=50
+ const cycle = 200 // time in milliseconds
+ const iterations = 250
first := 0
if !includingNodeZero {
@@ -204,35 +273,35 @@ func checkPropagation(t *testing.T, includingNodeZero bool) {
for j := 0; j < iterations; j++ {
for i := first; i < NumNodes; i++ {
- f := nodes[i].shh.GetFilter(nodes[i].filerId)
+ f := nodes[i].shh.GetFilter(nodes[i].filerID)
if f == nil {
- t.Fatalf("failed to get filterId %s from node %d.", nodes[i].filerId, i)
+ t.Fatalf("failed to get filterId %s from node %d, round %d.", nodes[i].filerID, i, round)
}
mail := f.Retrieve()
- if !validateMail(t, i, mail) {
- return
- }
+ validateMail(t, i, mail)
if isTestComplete() {
+ checkTestStatus()
return
}
}
+ checkTestStatus()
time.Sleep(cycle * time.Millisecond)
}
- t.Fatalf("Test was not complete: timeout %d seconds.", iterations*cycle/1000)
-
if !includingNodeZero {
- f := nodes[0].shh.GetFilter(nodes[0].filerId)
+ f := nodes[0].shh.GetFilter(nodes[0].filerID)
if f != nil {
t.Fatalf("node zero received a message with low PoW.")
}
}
+
+ t.Fatalf("Test was not complete (%d round): timeout %d seconds. nodes=%v", round, iterations*cycle/1000, nodes)
}
-func validateMail(t *testing.T, index int, mail []*ReceivedMessage) bool {
+func validateMail(t *testing.T, index int, mail []*ReceivedMessage) {
var cnt int
for _, m := range mail {
if bytes.Equal(m.Payload, expectedMessage) {
@@ -242,14 +311,13 @@ func validateMail(t *testing.T, index int, mail []*ReceivedMessage) bool {
if cnt == 0 {
// no messages received yet: nothing is wrong
- return true
+ return
}
if cnt > 1 {
t.Fatalf("node %d received %d.", index, cnt)
- return false
}
- if cnt > 0 {
+ if cnt == 1 {
result.mutex.Lock()
defer result.mutex.Unlock()
result.counter[index] += cnt
@@ -257,7 +325,28 @@ func validateMail(t *testing.T, index int, mail []*ReceivedMessage) bool {
t.Fatalf("node %d accumulated %d.", index, result.counter[index])
}
}
- return true
+}
+
+func checkTestStatus() {
+ var cnt int
+ var arr [NumNodes]int
+
+ for i := 0; i < NumNodes; i++ {
+ arr[i] = nodes[i].server.PeerCount()
+ envelopes := nodes[i].shh.Envelopes()
+ if len(envelopes) >= NumNodes {
+ cnt++
+ }
+ }
+
+ if debugMode {
+ if cntPrev != cnt {
+ fmt.Printf(" %v \t number of nodes that have received all msgs: %d, number of peers per node: %v \n",
+ time.Since(prevTime), cnt, arr)
+ prevTime = time.Now()
+ cntPrev = cnt
+ }
+ }
}
func isTestComplete() bool {
@@ -272,7 +361,7 @@ func isTestComplete() bool {
for i := 0; i < NumNodes; i++ {
envelopes := nodes[i].shh.Envelopes()
- if len(envelopes) < 2 {
+ if len(envelopes) < NumNodes+1 {
return false
}
}
@@ -287,9 +376,10 @@ func sendMsg(t *testing.T, expected bool, id int) {
opt := MessageParams{KeySym: sharedKey, Topic: sharedTopic, Payload: expectedMessage, PoW: 0.00000001, WorkTime: 1}
if !expected {
- opt.KeySym[0]++
- opt.Topic[0]++
- opt.Payload = opt.Payload[1:]
+ opt.KeySym = wrongKey
+ opt.Topic = wrongTopic
+ opt.Payload = unexpectedMessage
+ opt.Payload[0] = byte(id)
}
msg, err := NewSentMessage(&opt)
@@ -332,34 +422,89 @@ func TestPeerBasic(t *testing.T) {
}
}
-func powReqExchange(t *testing.T) {
+func checkPowExchangeForNodeZero(t *testing.T) {
+ const iterations = 200
+ for j := 0; j < iterations; j++ {
+ lastCycle := (j == iterations-1)
+ ok := checkPowExchangeForNodeZeroOnce(t, lastCycle)
+ if ok {
+ break
+ }
+ time.Sleep(50 * time.Millisecond)
+ }
+}
+
+func checkPowExchangeForNodeZeroOnce(t *testing.T, mustPass bool) bool {
+ cnt := 0
for i, node := range nodes {
for peer := range node.shh.peers {
- if peer.powRequirement > 1000.0 {
- t.Fatalf("node %d: one of the peers' pow requirement is too big (%f).", i, peer.powRequirement)
+ if peer.peer.ID() == discover.PubkeyID(&nodes[0].id.PublicKey) {
+ cnt++
+ if peer.powRequirement != masterPow {
+ if mustPass {
+ t.Fatalf("node %d: failed to set the new pow requirement for node zero.", i)
+ } else {
+ return false
+ }
+ }
}
}
}
+ if cnt == 0 {
+ t.Fatalf("looking for node zero: no matching peers found.")
+ }
+ return true
+}
- const pow float64 = 7777777.0
- nodes[0].shh.SetMinimumPoW(pow)
-
- // wait until all the messages are delivered
- time.Sleep(64 * time.Millisecond)
+func checkPowExchange(t *testing.T) {
+ for i, node := range nodes {
+ for peer := range node.shh.peers {
+ if peer.peer.ID() != discover.PubkeyID(&nodes[0].id.PublicKey) {
+ if peer.powRequirement != masterPow {
+ t.Fatalf("node %d: failed to exchange pow requirement in round %d; expected %f, got %f",
+ i, round, masterPow, peer.powRequirement)
+ }
+ }
+ }
+ }
+}
- cnt := 0
+func checkBloomFilterExchangeOnce(t *testing.T, mustPass bool) bool {
for i, node := range nodes {
for peer := range node.shh.peers {
- if peer.peer.ID() == discover.PubkeyID(&nodes[0].id.PublicKey) {
- cnt++
- if peer.powRequirement != pow {
- t.Fatalf("node %d: failed to set the new pow requirement.", i)
+ if !bytes.Equal(peer.bloomFilter, masterBloomFilter) {
+ if mustPass {
+ t.Fatalf("node %d: failed to exchange bloom filter requirement in round %d. \n%x expected \n%x got",
+ i, round, masterBloomFilter, peer.bloomFilter)
+ } else {
+ return false
}
}
}
}
- if cnt == 0 {
- t.Fatalf("no matching peers found.")
+ return true
+}
+
+func checkBloomFilterExchange(t *testing.T) {
+ const iterations = 200
+ for j := 0; j < iterations; j++ {
+ lastCycle := (j == iterations-1)
+ ok := checkBloomFilterExchangeOnce(t, lastCycle)
+ if ok {
+ break
+ }
+ time.Sleep(50 * time.Millisecond)
+ }
+}
+
+func waitForServersToStart(t *testing.T) {
+ const iterations = 200
+ for j := 0; j < iterations; j++ {
+ time.Sleep(50 * time.Millisecond)
+ if result.started == NumNodes {
+ return
+ }
}
+ t.Fatalf("Failed to start all the servers, running: %d", result.started)
}
diff --git a/whisper/whisperv6/topic.go b/whisper/whisperv6/topic.go
index bf5da01e3..4dd8f283c 100644
--- a/whisper/whisperv6/topic.go
+++ b/whisper/whisperv6/topic.go
@@ -23,11 +23,13 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
)
-// Topic represents a cryptographically secure, probabilistic partial
+// TopicType represents a cryptographically secure, probabilistic partial
// classifications of a message, determined as the first (left) 4 bytes of the
// SHA3 hash of some arbitrary data given by the original author of the message.
type TopicType [TopicLength]byte
+// BytesToTopic converts from the byte array representation of a topic
+// into the TopicType type.
func BytesToTopic(b []byte) (t TopicType) {
sz := TopicLength
if x := len(b); x < TopicLength {
diff --git a/whisper/whisperv6/whisper.go b/whisper/whisperv6/whisper.go
index 492591486..600f9cb28 100644
--- a/whisper/whisperv6/whisper.go
+++ b/whisper/whisperv6/whisper.go
@@ -19,7 +19,6 @@ package whisperv6
import (
"bytes"
"crypto/ecdsa"
- crand "crypto/rand"
"crypto/sha256"
"fmt"
"math"
@@ -39,6 +38,8 @@ import (
set "gopkg.in/fatih/set.v0"
)
+// Statistics holds several message-related counter for analytics
+// purposes.
type Statistics struct {
messagesCleared int
memoryCleared int
@@ -48,9 +49,12 @@ type Statistics struct {
}
const (
- minPowIdx = iota // Minimal PoW required by the whisper node
- maxMsgSizeIdx = iota // Maximal message length allowed by the whisper node
- overflowIdx = iota // Indicator of message queue overflow
+ maxMsgSizeIdx = iota // Maximal message length allowed by the whisper node
+ overflowIdx // Indicator of message queue overflow
+ minPowIdx // Minimal PoW required by the whisper node
+ minPowToleranceIdx // Minimal PoW tolerated by the whisper node for a limited time
+ bloomFilterIdx // Bloom filter for topics of interest for this node
+ bloomFilterToleranceIdx // Bloom filter tolerated by the whisper node for a limited time
)
// Whisper represents a dark communication interface through the Ethereum
@@ -76,7 +80,7 @@ type Whisper struct {
settings syncmap.Map // holds configuration settings that can be dynamically changed
- reactionAllowance int // maximum time in seconds allowed to process the whisper-related messages
+ syncAllowance int // maximum time in seconds allowed to process the whisper-related messages
statsMu sync.Mutex // guard stats
stats Statistics // Statistics of whisper node
@@ -91,15 +95,15 @@ func New(cfg *Config) *Whisper {
}
whisper := &Whisper{
- privateKeys: make(map[string]*ecdsa.PrivateKey),
- symKeys: make(map[string][]byte),
- envelopes: make(map[common.Hash]*Envelope),
- expirations: make(map[uint32]*set.SetNonTS),
- peers: make(map[*Peer]struct{}),
- messageQueue: make(chan *Envelope, messageQueueLimit),
- p2pMsgQueue: make(chan *Envelope, messageQueueLimit),
- quit: make(chan struct{}),
- reactionAllowance: SynchAllowance,
+ privateKeys: make(map[string]*ecdsa.PrivateKey),
+ symKeys: make(map[string][]byte),
+ envelopes: make(map[common.Hash]*Envelope),
+ expirations: make(map[uint32]*set.SetNonTS),
+ peers: make(map[*Peer]struct{}),
+ messageQueue: make(chan *Envelope, messageQueueLimit),
+ p2pMsgQueue: make(chan *Envelope, messageQueueLimit),
+ quit: make(chan struct{}),
+ syncAllowance: DefaultSyncAllowance,
}
whisper.filters = NewFilters(whisper)
@@ -126,30 +130,74 @@ func New(cfg *Config) *Whisper {
return whisper
}
-func (w *Whisper) MinPow() float64 {
- val, _ := w.settings.Load(minPowIdx)
+// MinPow returns the PoW value required by this node.
+func (whisper *Whisper) MinPow() float64 {
+ val, exist := whisper.settings.Load(minPowIdx)
+ if !exist || val == nil {
+ return DefaultMinimumPoW
+ }
+ v, ok := val.(float64)
+ if !ok {
+ log.Error("Error loading minPowIdx, using default")
+ return DefaultMinimumPoW
+ }
+ return v
+}
+
+// MinPowTolerance returns the value of minimum PoW which is tolerated for a limited
+// time after PoW was changed. If sufficient time have elapsed or no change of PoW
+// have ever occurred, the return value will be the same as return value of MinPow().
+func (whisper *Whisper) MinPowTolerance() float64 {
+ val, exist := whisper.settings.Load(minPowToleranceIdx)
+ if !exist || val == nil {
+ return DefaultMinimumPoW
+ }
return val.(float64)
}
+// BloomFilter returns the aggregated bloom filter for all the topics of interest.
+// The nodes are required to send only messages that match the advertised bloom filter.
+// If a message does not match the bloom, it will tantamount to spam, and the peer will
+// be disconnected.
+func (whisper *Whisper) BloomFilter() []byte {
+ val, exist := whisper.settings.Load(bloomFilterIdx)
+ if !exist || val == nil {
+ return nil
+ }
+ return val.([]byte)
+}
+
+// BloomFilterTolerance returns the bloom filter which is tolerated for a limited
+// time after new bloom was advertised to the peers. If sufficient time have elapsed
+// or no change of bloom filter have ever occurred, the return value will be the same
+// as return value of BloomFilter().
+func (whisper *Whisper) BloomFilterTolerance() []byte {
+ val, exist := whisper.settings.Load(bloomFilterToleranceIdx)
+ if !exist || val == nil {
+ return nil
+ }
+ return val.([]byte)
+}
+
// MaxMessageSize returns the maximum accepted message size.
-func (w *Whisper) MaxMessageSize() uint32 {
- val, _ := w.settings.Load(maxMsgSizeIdx)
+func (whisper *Whisper) MaxMessageSize() uint32 {
+ val, _ := whisper.settings.Load(maxMsgSizeIdx)
return val.(uint32)
}
// Overflow returns an indication if the message queue is full.
-func (w *Whisper) Overflow() bool {
- val, _ := w.settings.Load(overflowIdx)
+func (whisper *Whisper) Overflow() bool {
+ val, _ := whisper.settings.Load(overflowIdx)
return val.(bool)
}
// APIs returns the RPC descriptors the Whisper implementation offers
-func (w *Whisper) APIs() []rpc.API {
+func (whisper *Whisper) APIs() []rpc.API {
return []rpc.API{
{
Namespace: ProtocolName,
Version: ProtocolVersionStr,
- Service: NewPublicWhisperAPI(w),
+ Service: NewPublicWhisperAPI(whisper),
Public: true,
},
}
@@ -157,63 +205,77 @@ func (w *Whisper) APIs() []rpc.API {
// RegisterServer registers MailServer interface.
// MailServer will process all the incoming messages with p2pRequestCode.
-func (w *Whisper) RegisterServer(server MailServer) {
- w.mailServer = server
+func (whisper *Whisper) RegisterServer(server MailServer) {
+ whisper.mailServer = server
}
// Protocols returns the whisper sub-protocols ran by this particular client.
-func (w *Whisper) Protocols() []p2p.Protocol {
- return []p2p.Protocol{w.protocol}
+func (whisper *Whisper) Protocols() []p2p.Protocol {
+ return []p2p.Protocol{whisper.protocol}
}
// Version returns the whisper sub-protocols version number.
-func (w *Whisper) Version() uint {
- return w.protocol.Version
+func (whisper *Whisper) Version() uint {
+ return whisper.protocol.Version
}
// SetMaxMessageSize sets the maximal message size allowed by this node
-func (w *Whisper) SetMaxMessageSize(size uint32) error {
+func (whisper *Whisper) SetMaxMessageSize(size uint32) error {
if size > MaxMessageSize {
return fmt.Errorf("message size too large [%d>%d]", size, MaxMessageSize)
}
- w.settings.Store(maxMsgSizeIdx, size)
+ whisper.settings.Store(maxMsgSizeIdx, size)
+ return nil
+}
+
+// SetBloomFilter sets the new bloom filter
+func (whisper *Whisper) SetBloomFilter(bloom []byte) error {
+ if len(bloom) != bloomFilterSize {
+ return fmt.Errorf("invalid bloom filter size: %d", len(bloom))
+ }
+
+ b := make([]byte, bloomFilterSize)
+ copy(b, bloom)
+
+ whisper.settings.Store(bloomFilterIdx, b)
+ whisper.notifyPeersAboutBloomFilterChange(b)
+
+ go func() {
+ // allow some time before all the peers have processed the notification
+ time.Sleep(time.Duration(whisper.syncAllowance) * time.Second)
+ whisper.settings.Store(bloomFilterToleranceIdx, b)
+ }()
+
return nil
}
// SetMinimumPoW sets the minimal PoW required by this node
-func (w *Whisper) SetMinimumPoW(val float64) error {
+func (whisper *Whisper) SetMinimumPoW(val float64) error {
if val < 0.0 {
return fmt.Errorf("invalid PoW: %f", val)
}
- w.notifyPeersAboutPowRequirementChange(val)
+ whisper.settings.Store(minPowIdx, val)
+ whisper.notifyPeersAboutPowRequirementChange(val)
go func() {
// allow some time before all the peers have processed the notification
- time.Sleep(time.Duration(w.reactionAllowance) * time.Second)
- w.settings.Store(minPowIdx, val)
+ time.Sleep(time.Duration(whisper.syncAllowance) * time.Second)
+ whisper.settings.Store(minPowToleranceIdx, val)
}()
return nil
}
-// SetMinimumPoW sets the minimal PoW in test environment
-func (w *Whisper) SetMinimumPowTest(val float64) {
- w.notifyPeersAboutPowRequirementChange(val)
- w.settings.Store(minPowIdx, val)
+// SetMinimumPowTest sets the minimal PoW in test environment
+func (whisper *Whisper) SetMinimumPowTest(val float64) {
+ whisper.settings.Store(minPowIdx, val)
+ whisper.notifyPeersAboutPowRequirementChange(val)
+ whisper.settings.Store(minPowToleranceIdx, val)
}
-func (w *Whisper) notifyPeersAboutPowRequirementChange(pow float64) {
- arr := make([]*Peer, len(w.peers))
- i := 0
-
- w.peerMu.Lock()
- for p := range w.peers {
- arr[i] = p
- i++
- }
- w.peerMu.Unlock()
-
+func (whisper *Whisper) notifyPeersAboutPowRequirementChange(pow float64) {
+ arr := whisper.getPeers()
for _, p := range arr {
err := p.notifyAboutPowRequirementChange(pow)
if err != nil {
@@ -221,16 +283,42 @@ func (w *Whisper) notifyPeersAboutPowRequirementChange(pow float64) {
err = p.notifyAboutPowRequirementChange(pow)
}
if err != nil {
- log.Warn("oversized message received", "peer", p.ID(), "error", err)
+ log.Warn("failed to notify peer about new pow requirement", "peer", p.ID(), "error", err)
}
}
}
+func (whisper *Whisper) notifyPeersAboutBloomFilterChange(bloom []byte) {
+ arr := whisper.getPeers()
+ for _, p := range arr {
+ err := p.notifyAboutBloomFilterChange(bloom)
+ if err != nil {
+ // allow one retry
+ err = p.notifyAboutBloomFilterChange(bloom)
+ }
+ if err != nil {
+ log.Warn("failed to notify peer about new bloom filter", "peer", p.ID(), "error", err)
+ }
+ }
+}
+
+func (whisper *Whisper) getPeers() []*Peer {
+ arr := make([]*Peer, len(whisper.peers))
+ i := 0
+ whisper.peerMu.Lock()
+ for p := range whisper.peers {
+ arr[i] = p
+ i++
+ }
+ whisper.peerMu.Unlock()
+ return arr
+}
+
// getPeer retrieves peer by ID
-func (w *Whisper) getPeer(peerID []byte) (*Peer, error) {
- w.peerMu.Lock()
- defer w.peerMu.Unlock()
- for p := range w.peers {
+func (whisper *Whisper) getPeer(peerID []byte) (*Peer, error) {
+ whisper.peerMu.Lock()
+ defer whisper.peerMu.Unlock()
+ for p := range whisper.peers {
id := p.peer.ID()
if bytes.Equal(peerID, id[:]) {
return p, nil
@@ -241,8 +329,8 @@ func (w *Whisper) getPeer(peerID []byte) (*Peer, error) {
// AllowP2PMessagesFromPeer marks specific peer trusted,
// which will allow it to send historic (expired) messages.
-func (w *Whisper) AllowP2PMessagesFromPeer(peerID []byte) error {
- p, err := w.getPeer(peerID)
+func (whisper *Whisper) AllowP2PMessagesFromPeer(peerID []byte) error {
+ p, err := whisper.getPeer(peerID)
if err != nil {
return err
}
@@ -255,8 +343,8 @@ func (w *Whisper) AllowP2PMessagesFromPeer(peerID []byte) error {
// request and respond with a number of peer-to-peer messages (possibly expired),
// which are not supposed to be forwarded any further.
// The whisper protocol is agnostic of the format and contents of envelope.
-func (w *Whisper) RequestHistoricMessages(peerID []byte, envelope *Envelope) error {
- p, err := w.getPeer(peerID)
+func (whisper *Whisper) RequestHistoricMessages(peerID []byte, envelope *Envelope) error {
+ p, err := whisper.getPeer(peerID)
if err != nil {
return err
}
@@ -265,22 +353,22 @@ func (w *Whisper) RequestHistoricMessages(peerID []byte, envelope *Envelope) err
}
// SendP2PMessage sends a peer-to-peer message to a specific peer.
-func (w *Whisper) SendP2PMessage(peerID []byte, envelope *Envelope) error {
- p, err := w.getPeer(peerID)
+func (whisper *Whisper) SendP2PMessage(peerID []byte, envelope *Envelope) error {
+ p, err := whisper.getPeer(peerID)
if err != nil {
return err
}
- return w.SendP2PDirect(p, envelope)
+ return whisper.SendP2PDirect(p, envelope)
}
// SendP2PDirect sends a peer-to-peer message to a specific peer.
-func (w *Whisper) SendP2PDirect(peer *Peer, envelope *Envelope) error {
+func (whisper *Whisper) SendP2PDirect(peer *Peer, envelope *Envelope) error {
return p2p.Send(peer.ws, p2pMessageCode, envelope)
}
// NewKeyPair generates a new cryptographic identity for the client, and injects
// it into the known identities for message decryption. Returns ID of the new key pair.
-func (w *Whisper) NewKeyPair() (string, error) {
+func (whisper *Whisper) NewKeyPair() (string, error) {
key, err := crypto.GenerateKey()
if err != nil || !validatePrivateKey(key) {
key, err = crypto.GenerateKey() // retry once
@@ -297,55 +385,55 @@ func (w *Whisper) NewKeyPair() (string, error) {
return "", fmt.Errorf("failed to generate ID: %s", err)
}
- w.keyMu.Lock()
- defer w.keyMu.Unlock()
+ whisper.keyMu.Lock()
+ defer whisper.keyMu.Unlock()
- if w.privateKeys[id] != nil {
+ if whisper.privateKeys[id] != nil {
return "", fmt.Errorf("failed to generate unique ID")
}
- w.privateKeys[id] = key
+ whisper.privateKeys[id] = key
return id, nil
}
// DeleteKeyPair deletes the specified key if it exists.
-func (w *Whisper) DeleteKeyPair(key string) bool {
- w.keyMu.Lock()
- defer w.keyMu.Unlock()
+func (whisper *Whisper) DeleteKeyPair(key string) bool {
+ whisper.keyMu.Lock()
+ defer whisper.keyMu.Unlock()
- if w.privateKeys[key] != nil {
- delete(w.privateKeys, key)
+ if whisper.privateKeys[key] != nil {
+ delete(whisper.privateKeys, key)
return true
}
return false
}
// AddKeyPair imports a asymmetric private key and returns it identifier.
-func (w *Whisper) AddKeyPair(key *ecdsa.PrivateKey) (string, error) {
+func (whisper *Whisper) AddKeyPair(key *ecdsa.PrivateKey) (string, error) {
id, err := GenerateRandomID()
if err != nil {
return "", fmt.Errorf("failed to generate ID: %s", err)
}
- w.keyMu.Lock()
- w.privateKeys[id] = key
- w.keyMu.Unlock()
+ whisper.keyMu.Lock()
+ whisper.privateKeys[id] = key
+ whisper.keyMu.Unlock()
return id, nil
}
// HasKeyPair checks if the the whisper node is configured with the private key
// of the specified public pair.
-func (w *Whisper) HasKeyPair(id string) bool {
- w.keyMu.RLock()
- defer w.keyMu.RUnlock()
- return w.privateKeys[id] != nil
+func (whisper *Whisper) HasKeyPair(id string) bool {
+ whisper.keyMu.RLock()
+ defer whisper.keyMu.RUnlock()
+ return whisper.privateKeys[id] != nil
}
// GetPrivateKey retrieves the private key of the specified identity.
-func (w *Whisper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) {
- w.keyMu.RLock()
- defer w.keyMu.RUnlock()
- key := w.privateKeys[id]
+func (whisper *Whisper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) {
+ whisper.keyMu.RLock()
+ defer whisper.keyMu.RUnlock()
+ key := whisper.privateKeys[id]
if key == nil {
return nil, fmt.Errorf("invalid id")
}
@@ -354,12 +442,11 @@ func (w *Whisper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) {
// GenerateSymKey generates a random symmetric key and stores it under id,
// which is then returned. Will be used in the future for session key exchange.
-func (w *Whisper) GenerateSymKey() (string, error) {
- key := make([]byte, aesKeyLength)
- _, err := crand.Read(key)
+func (whisper *Whisper) GenerateSymKey() (string, error) {
+ key, err := generateSecureRandomData(aesKeyLength)
if err != nil {
return "", err
- } else if !validateSymmetricKey(key) {
+ } else if !validateDataIntegrity(key, aesKeyLength) {
return "", fmt.Errorf("error in GenerateSymKey: crypto/rand failed to generate random data")
}
@@ -368,18 +455,18 @@ func (w *Whisper) GenerateSymKey() (string, error) {
return "", fmt.Errorf("failed to generate ID: %s", err)
}
- w.keyMu.Lock()
- defer w.keyMu.Unlock()
+ whisper.keyMu.Lock()
+ defer whisper.keyMu.Unlock()
- if w.symKeys[id] != nil {
+ if whisper.symKeys[id] != nil {
return "", fmt.Errorf("failed to generate unique ID")
}
- w.symKeys[id] = key
+ whisper.symKeys[id] = key
return id, nil
}
// AddSymKeyDirect stores the key, and returns its id.
-func (w *Whisper) AddSymKeyDirect(key []byte) (string, error) {
+func (whisper *Whisper) AddSymKeyDirect(key []byte) (string, error) {
if len(key) != aesKeyLength {
return "", fmt.Errorf("wrong key size: %d", len(key))
}
@@ -389,23 +476,23 @@ func (w *Whisper) AddSymKeyDirect(key []byte) (string, error) {
return "", fmt.Errorf("failed to generate ID: %s", err)
}
- w.keyMu.Lock()
- defer w.keyMu.Unlock()
+ whisper.keyMu.Lock()
+ defer whisper.keyMu.Unlock()
- if w.symKeys[id] != nil {
+ if whisper.symKeys[id] != nil {
return "", fmt.Errorf("failed to generate unique ID")
}
- w.symKeys[id] = key
+ whisper.symKeys[id] = key
return id, nil
}
// AddSymKeyFromPassword generates the key from password, stores it, and returns its id.
-func (w *Whisper) AddSymKeyFromPassword(password string) (string, error) {
+func (whisper *Whisper) AddSymKeyFromPassword(password string) (string, error) {
id, err := GenerateRandomID()
if err != nil {
return "", fmt.Errorf("failed to generate ID: %s", err)
}
- if w.HasSymKey(id) {
+ if whisper.HasSymKey(id) {
return "", fmt.Errorf("failed to generate unique ID")
}
@@ -416,60 +503,81 @@ func (w *Whisper) AddSymKeyFromPassword(password string) (string, error) {
return "", err
}
- w.keyMu.Lock()
- defer w.keyMu.Unlock()
+ whisper.keyMu.Lock()
+ defer whisper.keyMu.Unlock()
// double check is necessary, because deriveKeyMaterial() is very slow
- if w.symKeys[id] != nil {
+ if whisper.symKeys[id] != nil {
return "", fmt.Errorf("critical error: failed to generate unique ID")
}
- w.symKeys[id] = derived
+ whisper.symKeys[id] = derived
return id, nil
}
// HasSymKey returns true if there is a key associated with the given id.
// Otherwise returns false.
-func (w *Whisper) HasSymKey(id string) bool {
- w.keyMu.RLock()
- defer w.keyMu.RUnlock()
- return w.symKeys[id] != nil
+func (whisper *Whisper) HasSymKey(id string) bool {
+ whisper.keyMu.RLock()
+ defer whisper.keyMu.RUnlock()
+ return whisper.symKeys[id] != nil
}
// DeleteSymKey deletes the key associated with the name string if it exists.
-func (w *Whisper) DeleteSymKey(id string) bool {
- w.keyMu.Lock()
- defer w.keyMu.Unlock()
- if w.symKeys[id] != nil {
- delete(w.symKeys, id)
+func (whisper *Whisper) DeleteSymKey(id string) bool {
+ whisper.keyMu.Lock()
+ defer whisper.keyMu.Unlock()
+ if whisper.symKeys[id] != nil {
+ delete(whisper.symKeys, id)
return true
}
return false
}
// GetSymKey returns the symmetric key associated with the given id.
-func (w *Whisper) GetSymKey(id string) ([]byte, error) {
- w.keyMu.RLock()
- defer w.keyMu.RUnlock()
- if w.symKeys[id] != nil {
- return w.symKeys[id], nil
+func (whisper *Whisper) GetSymKey(id string) ([]byte, error) {
+ whisper.keyMu.RLock()
+ defer whisper.keyMu.RUnlock()
+ if whisper.symKeys[id] != nil {
+ return whisper.symKeys[id], nil
}
return nil, fmt.Errorf("non-existent key ID")
}
// Subscribe installs a new message handler used for filtering, decrypting
// and subsequent storing of incoming messages.
-func (w *Whisper) Subscribe(f *Filter) (string, error) {
- return w.filters.Install(f)
+func (whisper *Whisper) Subscribe(f *Filter) (string, error) {
+ s, err := whisper.filters.Install(f)
+ if err == nil {
+ whisper.updateBloomFilter(f)
+ }
+ return s, err
+}
+
+// updateBloomFilter recalculates the new value of bloom filter,
+// and informs the peers if necessary.
+func (whisper *Whisper) updateBloomFilter(f *Filter) {
+ aggregate := make([]byte, bloomFilterSize)
+ for _, t := range f.Topics {
+ top := BytesToTopic(t)
+ b := TopicToBloom(top)
+ aggregate = addBloom(aggregate, b)
+ }
+
+ if !bloomFilterMatch(whisper.BloomFilter(), aggregate) {
+ // existing bloom filter must be updated
+ aggregate = addBloom(whisper.BloomFilter(), aggregate)
+ whisper.SetBloomFilter(aggregate)
+ }
}
// GetFilter returns the filter by id.
-func (w *Whisper) GetFilter(id string) *Filter {
- return w.filters.Get(id)
+func (whisper *Whisper) GetFilter(id string) *Filter {
+ return whisper.filters.Get(id)
}
// Unsubscribe removes an installed message handler.
-func (w *Whisper) Unsubscribe(id string) error {
- ok := w.filters.Uninstall(id)
+func (whisper *Whisper) Unsubscribe(id string) error {
+ ok := whisper.filters.Uninstall(id)
if !ok {
return fmt.Errorf("Unsubscribe: Invalid ID")
}
@@ -478,8 +586,8 @@ func (w *Whisper) Unsubscribe(id string) error {
// Send injects a message into the whisper send queue, to be distributed in the
// network in the coming cycles.
-func (w *Whisper) Send(envelope *Envelope) error {
- ok, err := w.add(envelope)
+func (whisper *Whisper) Send(envelope *Envelope) error {
+ ok, err := whisper.add(envelope)
if err != nil {
return err
}
@@ -491,13 +599,13 @@ func (w *Whisper) Send(envelope *Envelope) error {
// Start implements node.Service, starting the background data propagation thread
// of the Whisper protocol.
-func (w *Whisper) Start(*p2p.Server) error {
+func (whisper *Whisper) Start(*p2p.Server) error {
log.Info("started whisper v." + ProtocolVersionStr)
- go w.update()
+ go whisper.update()
numCPU := runtime.NumCPU()
for i := 0; i < numCPU; i++ {
- go w.processQueue()
+ go whisper.processQueue()
}
return nil
@@ -505,26 +613,26 @@ func (w *Whisper) Start(*p2p.Server) error {
// Stop implements node.Service, stopping the background data propagation thread
// of the Whisper protocol.
-func (w *Whisper) Stop() error {
- close(w.quit)
+func (whisper *Whisper) Stop() error {
+ close(whisper.quit)
log.Info("whisper stopped")
return nil
}
// HandlePeer is called by the underlying P2P layer when the whisper sub-protocol
// connection is negotiated.
-func (wh *Whisper) HandlePeer(peer *p2p.Peer, rw p2p.MsgReadWriter) error {
+func (whisper *Whisper) HandlePeer(peer *p2p.Peer, rw p2p.MsgReadWriter) error {
// Create the new peer and start tracking it
- whisperPeer := newPeer(wh, peer, rw)
+ whisperPeer := newPeer(whisper, peer, rw)
- wh.peerMu.Lock()
- wh.peers[whisperPeer] = struct{}{}
- wh.peerMu.Unlock()
+ whisper.peerMu.Lock()
+ whisper.peers[whisperPeer] = struct{}{}
+ whisper.peerMu.Unlock()
defer func() {
- wh.peerMu.Lock()
- delete(wh.peers, whisperPeer)
- wh.peerMu.Unlock()
+ whisper.peerMu.Lock()
+ delete(whisper.peers, whisperPeer)
+ whisper.peerMu.Unlock()
}()
// Run the peer handshake and state updates
@@ -534,11 +642,11 @@ func (wh *Whisper) HandlePeer(peer *p2p.Peer, rw p2p.MsgReadWriter) error {
whisperPeer.start()
defer whisperPeer.stop()
- return wh.runMessageLoop(whisperPeer, rw)
+ return whisper.runMessageLoop(whisperPeer, rw)
}
// runMessageLoop reads and processes inbound messages directly to merge into client-global state.
-func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
+func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
for {
// fetch the next packet
packet, err := rw.ReadMsg()
@@ -546,7 +654,7 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
log.Warn("message loop", "peer", p.peer.ID(), "err", err)
return err
}
- if packet.Size > wh.MaxMessageSize() {
+ if packet.Size > whisper.MaxMessageSize() {
log.Warn("oversized message received", "peer", p.peer.ID())
return errors.New("oversized message received")
}
@@ -565,7 +673,7 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
trouble := false
for _, env := range envelopes {
- cached, err := wh.add(env)
+ cached, err := whisper.add(env)
if err != nil {
trouble = true
log.Error("bad envelope received, peer will be disconnected", "peer", p.peer.ID(), "err", err)
@@ -592,7 +700,17 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
}
p.powRequirement = f
case bloomFilterExCode:
- // to be implemented
+ var bloom []byte
+ err := packet.Decode(&bloom)
+ if err == nil && len(bloom) != bloomFilterSize {
+ err = fmt.Errorf("wrong bloom filter size %d", len(bloom))
+ }
+
+ if err != nil {
+ log.Warn("failed to decode bloom filter exchange message, peer will be disconnected", "peer", p.peer.ID(), "err", err)
+ return errors.New("invalid bloom filter exchange message")
+ }
+ p.setBloomFilter(bloom)
case p2pMessageCode:
// peer-to-peer message, sent directly to peer bypassing PoW checks, etc.
// this message is not supposed to be forwarded to other peers, and
@@ -604,17 +722,17 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
log.Warn("failed to decode direct message, peer will be disconnected", "peer", p.peer.ID(), "err", err)
return errors.New("invalid direct message")
}
- wh.postEvent(&envelope, true)
+ whisper.postEvent(&envelope, true)
}
case p2pRequestCode:
// Must be processed if mail server is implemented. Otherwise ignore.
- if wh.mailServer != nil {
+ if whisper.mailServer != nil {
var request Envelope
if err := packet.Decode(&request); err != nil {
log.Warn("failed to decode p2p request message, peer will be disconnected", "peer", p.peer.ID(), "err", err)
return errors.New("invalid p2p request")
}
- wh.mailServer.DeliverMail(p, &request)
+ whisper.mailServer.DeliverMail(p, &request)
}
default:
// New message types might be implemented in the future versions of Whisper.
@@ -628,117 +746,126 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
// add inserts a new envelope into the message pool to be distributed within the
// whisper network. It also inserts the envelope into the expiration pool at the
// appropriate time-stamp. In case of error, connection should be dropped.
-func (wh *Whisper) add(envelope *Envelope) (bool, error) {
+func (whisper *Whisper) add(envelope *Envelope) (bool, error) {
now := uint32(time.Now().Unix())
sent := envelope.Expiry - envelope.TTL
if sent > now {
- if sent-SynchAllowance > now {
+ if sent-DefaultSyncAllowance > now {
return false, fmt.Errorf("envelope created in the future [%x]", envelope.Hash())
- } else {
- // recalculate PoW, adjusted for the time difference, plus one second for latency
- envelope.calculatePoW(sent - now + 1)
}
+ // recalculate PoW, adjusted for the time difference, plus one second for latency
+ envelope.calculatePoW(sent - now + 1)
}
if envelope.Expiry < now {
- if envelope.Expiry+SynchAllowance*2 < now {
+ if envelope.Expiry+DefaultSyncAllowance*2 < now {
return false, fmt.Errorf("very old message")
- } else {
- log.Debug("expired envelope dropped", "hash", envelope.Hash().Hex())
- return false, nil // drop envelope without error
}
+ log.Debug("expired envelope dropped", "hash", envelope.Hash().Hex())
+ return false, nil // drop envelope without error
}
- if uint32(envelope.size()) > wh.MaxMessageSize() {
+ if uint32(envelope.size()) > whisper.MaxMessageSize() {
return false, fmt.Errorf("huge messages are not allowed [%x]", envelope.Hash())
}
- if envelope.PoW() < wh.MinPow() {
- log.Debug("envelope with low PoW dropped", "PoW", envelope.PoW(), "hash", envelope.Hash().Hex())
- return false, nil // drop envelope without error for now
+ if envelope.PoW() < whisper.MinPow() {
+ // maybe the value was recently changed, and the peers did not adjust yet.
+ // in this case the previous value is retrieved by MinPowTolerance()
+ // for a short period of peer synchronization.
+ if envelope.PoW() < whisper.MinPowTolerance() {
+ return false, fmt.Errorf("envelope with low PoW received: PoW=%f, hash=[%v]", envelope.PoW(), envelope.Hash().Hex())
+ }
+ }
- // once the status message includes the PoW requirement, an error should be returned here:
- //return false, fmt.Errorf("envelope with low PoW dropped: PoW=%f, hash=[%v]", envelope.PoW(), envelope.Hash().Hex())
+ if !bloomFilterMatch(whisper.BloomFilter(), envelope.Bloom()) {
+ // maybe the value was recently changed, and the peers did not adjust yet.
+ // in this case the previous value is retrieved by BloomFilterTolerance()
+ // for a short period of peer synchronization.
+ if !bloomFilterMatch(whisper.BloomFilterTolerance(), envelope.Bloom()) {
+ return false, fmt.Errorf("envelope does not match bloom filter, hash=[%v], bloom: \n%x \n%x \n%x",
+ envelope.Hash().Hex(), whisper.BloomFilter(), envelope.Bloom(), envelope.Topic)
+ }
}
hash := envelope.Hash()
- wh.poolMu.Lock()
- _, alreadyCached := wh.envelopes[hash]
+ whisper.poolMu.Lock()
+ _, alreadyCached := whisper.envelopes[hash]
if !alreadyCached {
- wh.envelopes[hash] = envelope
- if wh.expirations[envelope.Expiry] == nil {
- wh.expirations[envelope.Expiry] = set.NewNonTS()
+ whisper.envelopes[hash] = envelope
+ if whisper.expirations[envelope.Expiry] == nil {
+ whisper.expirations[envelope.Expiry] = set.NewNonTS()
}
- if !wh.expirations[envelope.Expiry].Has(hash) {
- wh.expirations[envelope.Expiry].Add(hash)
+ if !whisper.expirations[envelope.Expiry].Has(hash) {
+ whisper.expirations[envelope.Expiry].Add(hash)
}
}
- wh.poolMu.Unlock()
+ whisper.poolMu.Unlock()
if alreadyCached {
log.Trace("whisper envelope already cached", "hash", envelope.Hash().Hex())
} else {
log.Trace("cached whisper envelope", "hash", envelope.Hash().Hex())
- wh.statsMu.Lock()
- wh.stats.memoryUsed += envelope.size()
- wh.statsMu.Unlock()
- wh.postEvent(envelope, false) // notify the local node about the new message
- if wh.mailServer != nil {
- wh.mailServer.Archive(envelope)
+ whisper.statsMu.Lock()
+ whisper.stats.memoryUsed += envelope.size()
+ whisper.statsMu.Unlock()
+ whisper.postEvent(envelope, false) // notify the local node about the new message
+ if whisper.mailServer != nil {
+ whisper.mailServer.Archive(envelope)
}
}
return true, nil
}
// postEvent queues the message for further processing.
-func (w *Whisper) postEvent(envelope *Envelope, isP2P bool) {
+func (whisper *Whisper) postEvent(envelope *Envelope, isP2P bool) {
if isP2P {
- w.p2pMsgQueue <- envelope
+ whisper.p2pMsgQueue <- envelope
} else {
- w.checkOverflow()
- w.messageQueue <- envelope
+ whisper.checkOverflow()
+ whisper.messageQueue <- envelope
}
}
// checkOverflow checks if message queue overflow occurs and reports it if necessary.
-func (w *Whisper) checkOverflow() {
- queueSize := len(w.messageQueue)
+func (whisper *Whisper) checkOverflow() {
+ queueSize := len(whisper.messageQueue)
if queueSize == messageQueueLimit {
- if !w.Overflow() {
- w.settings.Store(overflowIdx, true)
+ if !whisper.Overflow() {
+ whisper.settings.Store(overflowIdx, true)
log.Warn("message queue overflow")
}
} else if queueSize <= messageQueueLimit/2 {
- if w.Overflow() {
- w.settings.Store(overflowIdx, false)
+ if whisper.Overflow() {
+ whisper.settings.Store(overflowIdx, false)
log.Warn("message queue overflow fixed (back to normal)")
}
}
}
// processQueue delivers the messages to the watchers during the lifetime of the whisper node.
-func (w *Whisper) processQueue() {
+func (whisper *Whisper) processQueue() {
var e *Envelope
for {
select {
- case <-w.quit:
+ case <-whisper.quit:
return
- case e = <-w.messageQueue:
- w.filters.NotifyWatchers(e, false)
+ case e = <-whisper.messageQueue:
+ whisper.filters.NotifyWatchers(e, false)
- case e = <-w.p2pMsgQueue:
- w.filters.NotifyWatchers(e, true)
+ case e = <-whisper.p2pMsgQueue:
+ whisper.filters.NotifyWatchers(e, true)
}
}
}
// update loops until the lifetime of the whisper node, updating its internal
// state by expiring stale messages from the pool.
-func (w *Whisper) update() {
+func (whisper *Whisper) update() {
// Start a ticker to check for expirations
expire := time.NewTicker(expirationCycle)
@@ -746,9 +873,9 @@ func (w *Whisper) update() {
for {
select {
case <-expire.C:
- w.expire()
+ whisper.expire()
- case <-w.quit:
+ case <-whisper.quit:
return
}
}
@@ -756,46 +883,46 @@ func (w *Whisper) update() {
// expire iterates over all the expiration timestamps, removing all stale
// messages from the pools.
-func (w *Whisper) expire() {
- w.poolMu.Lock()
- defer w.poolMu.Unlock()
+func (whisper *Whisper) expire() {
+ whisper.poolMu.Lock()
+ defer whisper.poolMu.Unlock()
- w.statsMu.Lock()
- defer w.statsMu.Unlock()
- w.stats.reset()
+ whisper.statsMu.Lock()
+ defer whisper.statsMu.Unlock()
+ whisper.stats.reset()
now := uint32(time.Now().Unix())
- for expiry, hashSet := range w.expirations {
+ for expiry, hashSet := range whisper.expirations {
if expiry < now {
// Dump all expired messages and remove timestamp
hashSet.Each(func(v interface{}) bool {
- sz := w.envelopes[v.(common.Hash)].size()
- delete(w.envelopes, v.(common.Hash))
- w.stats.messagesCleared++
- w.stats.memoryCleared += sz
- w.stats.memoryUsed -= sz
+ sz := whisper.envelopes[v.(common.Hash)].size()
+ delete(whisper.envelopes, v.(common.Hash))
+ whisper.stats.messagesCleared++
+ whisper.stats.memoryCleared += sz
+ whisper.stats.memoryUsed -= sz
return true
})
- w.expirations[expiry].Clear()
- delete(w.expirations, expiry)
+ whisper.expirations[expiry].Clear()
+ delete(whisper.expirations, expiry)
}
}
}
// Stats returns the whisper node statistics.
-func (w *Whisper) Stats() Statistics {
- w.statsMu.Lock()
- defer w.statsMu.Unlock()
+func (whisper *Whisper) Stats() Statistics {
+ whisper.statsMu.Lock()
+ defer whisper.statsMu.Unlock()
- return w.stats
+ return whisper.stats
}
// Envelopes retrieves all the messages currently pooled by the node.
-func (w *Whisper) Envelopes() []*Envelope {
- w.poolMu.RLock()
- defer w.poolMu.RUnlock()
+func (whisper *Whisper) Envelopes() []*Envelope {
+ whisper.poolMu.RLock()
+ defer whisper.poolMu.RUnlock()
- all := make([]*Envelope, 0, len(w.envelopes))
- for _, envelope := range w.envelopes {
+ all := make([]*Envelope, 0, len(whisper.envelopes))
+ for _, envelope := range whisper.envelopes {
all = append(all, envelope)
}
return all
@@ -803,13 +930,13 @@ func (w *Whisper) Envelopes() []*Envelope {
// Messages iterates through all currently floating envelopes
// and retrieves all the messages, that this filter could decrypt.
-func (w *Whisper) Messages(id string) []*ReceivedMessage {
+func (whisper *Whisper) Messages(id string) []*ReceivedMessage {
result := make([]*ReceivedMessage, 0)
- w.poolMu.RLock()
- defer w.poolMu.RUnlock()
+ whisper.poolMu.RLock()
+ defer whisper.poolMu.RUnlock()
- if filter := w.filters.Get(id); filter != nil {
- for _, env := range w.envelopes {
+ if filter := whisper.filters.Get(id); filter != nil {
+ for _, env := range whisper.envelopes {
msg := filter.processEnvelope(env)
if msg != nil {
result = append(result, msg)
@@ -820,11 +947,11 @@ func (w *Whisper) Messages(id string) []*ReceivedMessage {
}
// isEnvelopeCached checks if envelope with specific hash has already been received and cached.
-func (w *Whisper) isEnvelopeCached(hash common.Hash) bool {
- w.poolMu.Lock()
- defer w.poolMu.Unlock()
+func (whisper *Whisper) isEnvelopeCached(hash common.Hash) bool {
+ whisper.poolMu.Lock()
+ defer whisper.poolMu.Unlock()
- _, exist := w.envelopes[hash]
+ _, exist := whisper.envelopes[hash]
return exist
}
@@ -850,9 +977,16 @@ func validatePrivateKey(k *ecdsa.PrivateKey) bool {
return ValidatePublicKey(&k.PublicKey)
}
-// validateSymmetricKey returns false if the key contains all zeros
-func validateSymmetricKey(k []byte) bool {
- return len(k) > 0 && !containsOnlyZeros(k)
+// validateDataIntegrity returns false if the data have the wrong or contains all zeros,
+// which is the simplest and the most common bug.
+func validateDataIntegrity(k []byte, expectedSize int) bool {
+ if len(k) != expectedSize {
+ return false
+ }
+ if expectedSize > 3 && containsOnlyZeros(k) {
+ return false
+ }
+ return true
}
// containsOnlyZeros checks if the data contain only zeros.
@@ -886,14 +1020,49 @@ func BytesToUintBigEndian(b []byte) (res uint64) {
// GenerateRandomID generates a random string, which is then returned to be used as a key id
func GenerateRandomID() (id string, err error) {
- buf := make([]byte, keyIdSize)
- _, err = crand.Read(buf)
+ buf, err := generateSecureRandomData(keyIDSize)
if err != nil {
return "", err
}
- if !validateSymmetricKey(buf) {
+ if !validateDataIntegrity(buf, keyIDSize) {
return "", fmt.Errorf("error in generateRandomID: crypto/rand failed to generate random data")
}
id = common.Bytes2Hex(buf)
return id, err
}
+
+func isFullNode(bloom []byte) bool {
+ if bloom == nil {
+ return true
+ }
+ for _, b := range bloom {
+ if b != 255 {
+ return false
+ }
+ }
+ return true
+}
+
+func bloomFilterMatch(filter, sample []byte) bool {
+ if filter == nil {
+ return true
+ }
+
+ for i := 0; i < bloomFilterSize; i++ {
+ f := filter[i]
+ s := sample[i]
+ if (f | s) != f {
+ return false
+ }
+ }
+
+ return true
+}
+
+func addBloom(a, b []byte) []byte {
+ c := make([]byte, bloomFilterSize)
+ for i := 0; i < bloomFilterSize; i++ {
+ c[i] = a[i] | b[i]
+ }
+ return c
+}
diff --git a/whisper/whisperv6/whisper_test.go b/whisper/whisperv6/whisper_test.go
index b391a1161..99e5f0bbb 100644
--- a/whisper/whisperv6/whisper_test.go
+++ b/whisper/whisperv6/whisper_test.go
@@ -81,7 +81,7 @@ func TestWhisperBasic(t *testing.T) {
}
derived := pbkdf2.Key([]byte(peerID), nil, 65356, aesKeyLength, sha256.New)
- if !validateSymmetricKey(derived) {
+ if !validateDataIntegrity(derived, aesKeyLength) {
t.Fatalf("failed validateSymmetricKey with param = %v.", derived)
}
if containsOnlyZeros(derived) {
@@ -448,24 +448,12 @@ func TestWhisperSymKeyManagement(t *testing.T) {
if !w.HasSymKey(id2) {
t.Fatalf("HasSymKey(id2) failed.")
}
- if k1 == nil {
- t.Fatalf("k1 does not exist.")
- }
- if k2 == nil {
- t.Fatalf("k2 does not exist.")
+ if !validateDataIntegrity(k2, aesKeyLength) {
+ t.Fatalf("key validation failed.")
}
if !bytes.Equal(k1, k2) {
t.Fatalf("k1 != k2.")
}
- if len(k1) != aesKeyLength {
- t.Fatalf("wrong length of k1.")
- }
- if len(k2) != aesKeyLength {
- t.Fatalf("wrong length of k2.")
- }
- if !validateSymmetricKey(k2) {
- t.Fatalf("key validation failed.")
- }
}
func TestExpiry(t *testing.T) {
@@ -843,3 +831,64 @@ func TestSymmetricSendKeyMismatch(t *testing.T) {
t.Fatalf("received a message when keys weren't matching")
}
}
+
+func TestBloom(t *testing.T) {
+ topic := TopicType{0, 0, 255, 6}
+ b := TopicToBloom(topic)
+ x := make([]byte, bloomFilterSize)
+ x[0] = byte(1)
+ x[32] = byte(1)
+ x[bloomFilterSize-1] = byte(128)
+ if !bloomFilterMatch(x, b) || !bloomFilterMatch(b, x) {
+ t.Fatalf("bloom filter does not match the mask")
+ }
+
+ _, err := mrand.Read(b)
+ if err != nil {
+ t.Fatalf("math rand error")
+ }
+ _, err = mrand.Read(x)
+ if err != nil {
+ t.Fatalf("math rand error")
+ }
+ if !bloomFilterMatch(b, b) {
+ t.Fatalf("bloom filter does not match self")
+ }
+ x = addBloom(x, b)
+ if !bloomFilterMatch(x, b) {
+ t.Fatalf("bloom filter does not match combined bloom")
+ }
+ if !isFullNode(nil) {
+ t.Fatalf("isFullNode did not recognize nil as full node")
+ }
+ x[17] = 254
+ if isFullNode(x) {
+ t.Fatalf("isFullNode false positive")
+ }
+ for i := 0; i < bloomFilterSize; i++ {
+ b[i] = byte(255)
+ }
+ if !isFullNode(b) {
+ t.Fatalf("isFullNode false negative")
+ }
+ if bloomFilterMatch(x, b) {
+ t.Fatalf("bloomFilterMatch false positive")
+ }
+ if !bloomFilterMatch(b, x) {
+ t.Fatalf("bloomFilterMatch false negative")
+ }
+
+ w := New(&DefaultConfig)
+ f := w.BloomFilter()
+ if f != nil {
+ t.Fatalf("wrong bloom on creation")
+ }
+ err = w.SetBloomFilter(x)
+ if err != nil {
+ t.Fatalf("failed to set bloom filter: %s", err)
+ }
+ f = w.BloomFilter()
+ if !bloomFilterMatch(f, x) || !bloomFilterMatch(x, f) {
+ t.Fatalf("retireved wrong bloom filter")
+ }
+}