From af7792c01aa62d1b2d8e2919656bb9cc8664277a Mon Sep 17 00:00:00 2001 From: Pedro Pombeiro Date: Thu, 15 Feb 2018 10:32:29 +0100 Subject: [PATCH] Update `github.com/ethereum/go-ethereum` package to 1.8.0 branch. Part of #665 --- Gopkg.lock | 53 +- Gopkg.toml | 2 +- _assets/patches/geth/0006-latest-cht.patch | 4 +- .../geth/0011-geth-17-whisperv6-70fbc87.patch | 2553 - _assets/patches/geth/README.md | 1 - vendor/github.com/StackExchange/wmi/LICENSE | 20 + vendor/github.com/StackExchange/wmi/README.md | 6 + .../StackExchange/wmi/swbemservices.go | 260 + vendor/github.com/StackExchange/wmi/wmi.go | 486 + .../github.com/elastic/gosigar/.appveyor.yml | 84 + vendor/github.com/elastic/gosigar/.gitignore | 41 + vendor/github.com/elastic/gosigar/.travis.yml | 36 + .../github.com/elastic/gosigar/CHANGELOG.md | 92 + vendor/github.com/elastic/gosigar/LICENSE | 201 + vendor/github.com/elastic/gosigar/NOTICE | 9 + vendor/github.com/elastic/gosigar/README.md | 57 + vendor/github.com/elastic/gosigar/Vagrantfile | 25 + vendor/github.com/elastic/gosigar/codecov.yml | 21 + .../elastic/gosigar/concrete_sigar.go | 83 + .../elastic/gosigar/sigar_darwin.go | 494 + .../elastic/gosigar/sigar_format.go | 126 + .../elastic/gosigar/sigar_freebsd.go | 108 + .../elastic/gosigar/sigar_interface.go | 197 + .../github.com/elastic/gosigar/sigar_linux.go | 84 + .../elastic/gosigar/sigar_linux_common.go | 468 + .../elastic/gosigar/sigar_openbsd.go | 418 + .../github.com/elastic/gosigar/sigar_stub.go | 71 + .../github.com/elastic/gosigar/sigar_unix.go | 69 + .../github.com/elastic/gosigar/sigar_util.go | 22 + .../elastic/gosigar/sigar_windows.go | 437 + .../elastic/gosigar/sys/windows/doc.go | 2 + .../elastic/gosigar/sys/windows/ntquery.go | 132 + .../elastic/gosigar/sys/windows/privileges.go | 272 + .../gosigar/sys/windows/syscall_windows.go | 385 + .../elastic/gosigar/sys/windows/version.go | 43 + .../gosigar/sys/windows/zsyscall_windows.go | 260 + .../go-ethereum/.github/CONTRIBUTING.md | 2 +- .../ethereum/go-ethereum/.gitignore | 3 +- .../github.com/ethereum/go-ethereum/.mailmap | 14 +- .../ethereum/go-ethereum/.travis.yml | 39 +- .../github.com/ethereum/go-ethereum/AUTHORS | 92 +- .../github.com/ethereum/go-ethereum/Makefile | 6 +- .../github.com/ethereum/go-ethereum/README.md | 29 +- .../github.com/ethereum/go-ethereum/VERSION | 2 +- .../ethereum/go-ethereum/accounts/abi/abi.go | 59 +- .../go-ethereum/accounts/abi/argument.go | 207 +- .../go-ethereum/accounts/abi/bind/backend.go | 29 +- .../accounts/abi/bind/backends/simulated.go | 169 +- .../go-ethereum/accounts/abi/bind/base.go | 125 +- .../go-ethereum/accounts/abi/bind/bind.go | 98 +- .../go-ethereum/accounts/abi/bind/template.go | 169 +- .../go-ethereum/accounts/abi/bind/topics.go | 189 + .../go-ethereum/accounts/abi/event.go | 104 +- .../go-ethereum/accounts/abi/method.go | 150 +- .../ethereum/go-ethereum/accounts/abi/pack.go | 3 +- .../go-ethereum/accounts/abi/reflect.go | 25 + .../ethereum/go-ethereum/accounts/abi/type.go | 114 +- .../go-ethereum/accounts/abi/unpack.go | 26 +- .../ethereum/go-ethereum/accounts/errors.go | 2 +- .../go-ethereum/accounts/keystore/presale.go | 3 + .../usbwallet/internal/trezor/messages.proto | 2 + .../usbwallet/internal/trezor/trezor.go | 2 +- .../usbwallet/internal/trezor/types.proto | 2 + .../go-ethereum/accounts/usbwallet/trezor.go | 2 +- .../ethereum/go-ethereum/appveyor.yml | 4 +- .../ethereum/go-ethereum/bmt/bmt.go | 3 +- .../ethereum/go-ethereum/build/ci.go | 62 +- .../go-ethereum/build/update-license.go | 5 +- .../ethereum/go-ethereum/cmd/bootnode/main.go | 30 +- .../ethereum/go-ethereum/cmd/ethkey/README.md | 41 + .../go-ethereum/cmd/ethkey/generate.go | 118 + .../go-ethereum/cmd/ethkey/inspect.go | 91 + .../ethereum/go-ethereum/cmd/ethkey/main.go | 67 + .../go-ethereum/cmd/ethkey/message.go | 159 + .../ethereum/go-ethereum/cmd/ethkey/utils.go | 83 + .../go-ethereum/cmd/evm/json_logger.go | 24 +- .../ethereum/go-ethereum/cmd/evm/runner.go | 4 +- .../ethereum/go-ethereum/cmd/faucet/faucet.go | 38 +- .../go-ethereum/cmd/faucet/faucet.html | 17 +- .../go-ethereum/cmd/faucet/website.go | 27 +- .../ethereum/go-ethereum/cmd/geth/chaincmd.go | 4 +- .../ethereum/go-ethereum/cmd/geth/config.go | 19 +- .../go-ethereum/cmd/geth/consolecmd.go | 19 +- .../ethereum/go-ethereum/cmd/geth/main.go | 9 +- .../ethereum/go-ethereum/cmd/geth/misccmd.go | 3 +- .../ethereum/go-ethereum/cmd/geth/usage.go | 7 +- .../ethereum/go-ethereum/cmd/p2psim/main.go | 16 + .../go-ethereum/cmd/puppeth/genesis.go | 379 + .../cmd/puppeth/module_dashboard.go | 336 +- .../cmd/puppeth/module_ethstats.go | 34 +- .../cmd/puppeth/module_explorer.go | 211 + .../go-ethereum/cmd/puppeth/module_faucet.go | 87 +- .../go-ethereum/cmd/puppeth/module_nginx.go | 19 +- .../go-ethereum/cmd/puppeth/module_node.go | 96 +- .../go-ethereum/cmd/puppeth/module_wallet.go | 200 + .../go-ethereum/cmd/puppeth/puppeth.go | 2 +- .../ethereum/go-ethereum/cmd/puppeth/ssh.go | 5 +- .../go-ethereum/cmd/puppeth/wizard.go | 13 +- .../cmd/puppeth/wizard_dashboard.go | 40 +- .../cmd/puppeth/wizard_ethstats.go | 70 +- .../cmd/puppeth/wizard_explorer.go | 117 + .../go-ethereum/cmd/puppeth/wizard_faucet.go | 84 +- .../go-ethereum/cmd/puppeth/wizard_genesis.go | 54 +- .../go-ethereum/cmd/puppeth/wizard_intro.go | 40 +- .../cmd/puppeth/wizard_netstats.go | 387 +- .../go-ethereum/cmd/puppeth/wizard_network.go | 16 +- .../go-ethereum/cmd/puppeth/wizard_nginx.go | 11 +- .../go-ethereum/cmd/puppeth/wizard_node.go | 42 +- .../go-ethereum/cmd/puppeth/wizard_wallet.go | 113 + .../ethereum/go-ethereum/cmd/swarm/config.go | 321 + .../ethereum/go-ethereum/cmd/swarm/main.go | 172 +- .../go-ethereum/cmd/swarm/manifest.go | 8 +- .../ethereum/go-ethereum/cmd/utils/cmd.go | 26 +- .../go-ethereum/cmd/utils/fdlimit_unix.go | 50 - .../go-ethereum/cmd/utils/fdlimit_windows.go | 41 - .../ethereum/go-ethereum/cmd/utils/flags.go | 200 +- .../ethereum/go-ethereum/cmd/wnode/main.go | 61 +- .../go-ethereum/common/bitutil/bitutil.go | 8 +- .../ethereum/go-ethereum/common/bytes.go | 35 +- .../fdlimit}/fdlimit_freebsd.go | 34 +- .../common/fdlimit/fdlimit_unix.go | 60 + .../common/fdlimit/fdlimit_windows.go | 47 + .../ethereum/go-ethereum/common/size.go | 27 +- .../ethereum/go-ethereum/common/types.go | 9 +- .../go-ethereum/consensus/clique/clique.go | 30 +- .../go-ethereum/consensus/consensus.go | 5 + .../ethereum/go-ethereum/consensus/errors.go | 4 + .../go-ethereum/consensus/ethash/algorithm.go | 6 +- .../consensus/ethash/algorithm_go1.7.go | 4 +- .../consensus/ethash/algorithm_go1.8.go | 34 +- .../go-ethereum/consensus/ethash/consensus.go | 80 +- .../go-ethereum/consensus/ethash/ethash.go | 381 +- .../go-ethereum/consensus/ethash/sealer.go | 19 +- .../ethereum/go-ethereum/console/console.go | 20 +- .../ethereum/go-ethereum/console/prompter.go | 11 +- .../docker/develop-alpine/Dockerfile | 2 +- .../docker/develop-ubuntu/Dockerfile | 6 +- .../docker/master-alpine/Dockerfile | 4 +- .../docker/master-ubuntu/Dockerfile | 8 +- .../contracts/chequebook/cheque.go | 6 +- .../chequebook/contract/chequebook.go | 418 +- .../chequebook/contract/chequebook.sol | 10 +- .../contracts/chequebook/contract/code.go | 2 +- .../contracts/chequebook/contract/mortal.sol | 10 + .../contracts/chequebook/contract/owned.sol | 15 + .../contracts/chequebook/gencode.go | 9 +- .../contracts/ens/contract/AbstractENS.sol | 23 + .../contracts/ens/contract/ENS.sol | 94 + .../contracts/ens/contract/FIFSRegistrar.sol | 39 + .../contracts/ens/contract/PublicResolver.sol | 212 + .../go-ethereum/contracts/ens/contract/ens.go | 1086 +- .../contracts/ens/contract/ens.sol | 226 - .../contracts/ens/contract/fifsregistrar.go | 195 + .../contracts/ens/contract/publicresolver.go | 1321 + .../ethereum/go-ethereum/contracts/ens/ens.go | 37 +- .../go-ethereum/contracts/release/contract.go | 432 - .../contracts/release/contract.sol | 249 - .../go-ethereum/contracts/release/release.go | 164 - .../ethereum/go-ethereum/core/asm/asm.go | 5 +- .../ethereum/go-ethereum/core/asm/compiler.go | 5 +- .../go-ethereum/core/block_validator.go | 45 +- .../ethereum/go-ethereum/core/blockchain.go | 375 +- .../go-ethereum/core/chain_indexer.go | 5 +- .../ethereum/go-ethereum/core/chain_makers.go | 82 +- .../ethereum/go-ethereum/core/evm.go | 2 +- .../ethereum/go-ethereum/core/gaspool.go | 34 +- .../ethereum/go-ethereum/core/gen_genesis.go | 6 +- .../go-ethereum/core/gen_genesis_account.go | 8 +- .../ethereum/go-ethereum/core/genesis.go | 28 +- .../go-ethereum/core/genesis_alloc.go | 1 + .../go-ethereum/core/state/database.go | 51 +- .../go-ethereum/core/state/journal.go | 2 +- .../go-ethereum/core/state/state_object.go | 5 +- .../go-ethereum/core/state/statedb.go | 57 +- .../go-ethereum/core/state_processor.go | 34 +- .../go-ethereum/core/state_transition.go | 131 +- .../ethereum/go-ethereum/core/tx_list.go | 13 +- .../ethereum/go-ethereum/core/tx_pool.go | 21 +- .../ethereum/go-ethereum/core/types.go | 6 +- .../ethereum/go-ethereum/core/types/block.go | 27 +- .../go-ethereum/core/types/gen_header_json.go | 22 +- .../go-ethereum/core/types/gen_log_json.go | 6 +- .../core/types/gen_receipt_json.go | 23 +- .../go-ethereum/core/types/gen_tx_json.go | 14 +- .../go-ethereum/core/types/receipt.go | 40 +- .../go-ethereum/core/types/transaction.go | 71 +- .../ethereum/go-ethereum/core/vm/evm.go | 49 +- .../ethereum/go-ethereum/core/vm/gas_table.go | 52 +- .../go-ethereum/core/vm/gen_structlog.go | 34 +- .../go-ethereum/core/vm/instructions.go | 78 +- .../ethereum/go-ethereum/core/vm/interface.go | 4 +- .../go-ethereum/core/vm/interpreter.go | 49 +- .../ethereum/go-ethereum/core/vm/logger.go | 50 +- .../ethereum/go-ethereum/core/vm/noop.go | 4 +- .../go-ethereum/core/vm/runtime/env.go | 4 +- .../go-ethereum/crypto/bn256/curve.go | 2 +- .../ethereum/go-ethereum/crypto/crypto.go | 15 +- .../go-ethereum/crypto/ecies/ecies.go | 2 +- .../go-ethereum/crypto/secp256k1/curve.go | 46 +- .../go-ethereum/crypto/secp256k1/ext.h | 63 +- .../go-ethereum/crypto/secp256k1/secp256.go | 51 +- .../go-ethereum/crypto/signature_cgo.go | 23 + .../go-ethereum/crypto/signature_nocgo.go | 40 + .../ethereum/go-ethereum/dashboard/README.md | 21 +- .../ethereum/go-ethereum/dashboard/assets.go | 38475 ++++++- .../go-ethereum/dashboard/assets/.eslintrc | 100 +- .../go-ethereum/dashboard/assets/.flowconfig | 9 + .../go-ethereum/dashboard/assets/common.jsx | 71 + .../dashboard/assets/components/Body.jsx | 61 + .../dashboard/assets/components/ChartRow.jsx | 57 + .../dashboard/assets/components/Common.jsx | 52 - .../assets/components/CustomTooltip.jsx | 95 + .../dashboard/assets/components/Dashboard.jsx | 360 +- .../dashboard/assets/components/Footer.jsx | 173 + .../dashboard/assets/components/Header.jsx | 134 +- .../dashboard/assets/components/Home.jsx | 89 - .../dashboard/assets/components/Main.jsx | 142 +- .../dashboard/assets/components/SideBar.jsx | 170 +- .../assets/{public => }/dashboard.html | 12 +- .../dashboard/assets/fa-only-woff-loader.js | 25 + .../go-ethereum/dashboard/assets/index.jsx | 37 +- .../dashboard/assets/package-lock.json | 7678 ++ .../go-ethereum/dashboard/assets/package.json | 58 +- .../dashboard/assets/types/content.jsx | 70 + .../dashboard/assets/webpack.config.js | 70 +- .../ethereum/go-ethereum/dashboard/config.go | 2 +- .../ethereum/go-ethereum/dashboard/cpu.go | 35 + .../go-ethereum/dashboard/cpu_windows.go | 23 + .../go-ethereum/dashboard/dashboard.go | 225 +- .../ethereum/go-ethereum/dashboard/message.go | 72 + .../ethereum/go-ethereum/eth/api.go | 257 +- .../ethereum/go-ethereum/eth/api_tracer.go | 646 + .../ethereum/go-ethereum/eth/backend.go | 45 +- .../ethereum/go-ethereum/eth/bind.go | 138 - .../ethereum/go-ethereum/eth/config.go | 49 +- .../go-ethereum/eth/downloader/downloader.go | 356 +- .../go-ethereum/eth/downloader/peer.go | 2 +- .../go-ethereum/eth/downloader/queue.go | 169 +- .../go-ethereum/eth/downloader/statesync.go | 36 +- .../ethereum/go-ethereum/eth/filters/api.go | 7 +- .../go-ethereum/eth/filters/filter_system.go | 11 +- .../go-ethereum/eth/gasprice/gasprice.go | 49 +- .../ethereum/go-ethereum/eth/gen_config.go | 67 +- .../ethereum/go-ethereum/eth/handler.go | 40 +- .../ethereum/go-ethereum/eth/sync.go | 15 +- .../tracers/internal/tracers/4byte_tracer.js | 86 + .../eth/tracers/internal/tracers/assets.go | 350 + .../tracers/internal/tracers/call_tracer.js | 246 + .../tracers/internal/tracers/evmdis_tracer.js | 93 + .../tracers/internal/tracers/noop_tracer.js | 29 + .../internal/tracers/opcount_tracer.js | 32 + .../internal/tracers/prestate_tracer.js | 103 + .../eth/tracers/internal/tracers/tracers.go | 21 + .../tracers/testdata/call_tracer_create.json | 58 + .../testdata/call_tracer_deep_calls.json | 415 + .../testdata/call_tracer_delegatecall.json | 97 + ...l_tracer_inner_create_oog_outer_throw.json | 77 + .../call_tracer_inner_throw_outer_revert.json | 81 + .../eth/tracers/testdata/call_tracer_oog.json | 60 + .../tracers/testdata/call_tracer_revert.json | 58 + .../tracers/testdata/call_tracer_simple.json | 78 + .../tracers/testdata/call_tracer_throw.json | 62 + .../go-ethereum/eth/tracers/tracer.go | 618 + .../go-ethereum/eth/tracers/tracers.go | 53 + .../go-ethereum/ethclient/ethclient.go | 12 +- .../ethereum/go-ethereum/ethdb/database.go | 9 + .../ethereum/go-ethereum/ethdb/interface.go | 2 + .../go-ethereum/ethdb/memory_database.go | 21 +- .../ethereum/go-ethereum/ethstats/ethstats.go | 14 +- .../ethereum/go-ethereum/interfaces.go | 4 +- .../go-ethereum/internal/build/env.go | 2 +- .../go-ethereum/internal/cmdtest/test_cmd.go | 24 +- .../go-ethereum/internal/ethapi/addrlock.go | 2 +- .../go-ethereum/internal/ethapi/api.go | 161 +- .../go-ethereum/internal/ethapi/backend.go | 3 +- .../go-ethereum/internal/ethapi/tracer.go | 365 - .../go-ethereum/internal/jsre/deps/bindata.go | 28 +- .../go-ethereum/internal/web3ext/web3ext.go | 50 +- .../ethereum/go-ethereum/les/backend.go | 12 +- .../ethereum/go-ethereum/les/handler.go | 263 +- .../ethereum/go-ethereum/les/odr_requests.go | 26 +- .../ethereum/go-ethereum/les/peer.go | 5 +- .../ethereum/go-ethereum/les/protocol.go | 9 +- .../ethereum/go-ethereum/les/retrieve.go | 2 +- .../ethereum/go-ethereum/les/server.go | 38 +- .../ethereum/go-ethereum/les/serverpool.go | 2 +- .../ethereum/go-ethereum/light/lightchain.go | 42 +- .../ethereum/go-ethereum/light/nodeset.go | 37 +- .../ethereum/go-ethereum/light/odr_util.go | 9 +- .../ethereum/go-ethereum/light/postprocess.go | 103 +- .../ethereum/go-ethereum/light/trie.go | 20 +- .../ethereum/go-ethereum/light/txpool.go | 9 +- .../ethereum/go-ethereum/miner/unconfirmed.go | 2 +- .../ethereum/go-ethereum/miner/worker.go | 10 +- .../ethereum/go-ethereum/mobile/big.go | 10 + .../ethereum/go-ethereum/mobile/bind.go | 6 +- .../ethereum/go-ethereum/mobile/ethclient.go | 4 +- .../ethereum/go-ethereum/mobile/ethereum.go | 5 +- .../ethereum/go-ethereum/mobile/geth.go | 1 - .../ethereum/go-ethereum/mobile/types.go | 28 +- .../ethereum/go-ethereum/node/api.go | 12 +- .../ethereum/go-ethereum/node/config.go | 12 + .../ethereum/go-ethereum/node/defaults.go | 7 +- .../ethereum/go-ethereum/node/node.go | 40 +- .../ethereum/go-ethereum/p2p/dial.go | 27 +- .../go-ethereum/p2p/discover/database.go | 6 +- .../ethereum/go-ethereum/p2p/discover/node.go | 6 +- .../go-ethereum/p2p/discover/table.go | 484 +- .../ethereum/go-ethereum/p2p/discover/udp.go | 116 +- .../go-ethereum/p2p/discv5/database.go | 6 +- .../ethereum/go-ethereum/p2p/discv5/net.go | 99 +- .../ethereum/go-ethereum/p2p/discv5/node.go | 5 + .../p2p/discv5/nodeevent_string.go | 6 +- .../ethereum/go-ethereum/p2p/discv5/ntp.go | 8 +- .../ethereum/go-ethereum/p2p/discv5/ticket.go | 243 +- .../ethereum/go-ethereum/p2p/discv5/topic.go | 3 +- .../ethereum/go-ethereum/p2p/discv5/udp.go | 67 +- .../ethereum/go-ethereum/p2p/enr/enr.go | 290 + .../ethereum/go-ethereum/p2p/enr/entries.go | 160 + .../ethereum/go-ethereum/p2p/netutil/net.go | 131 + .../ethereum/go-ethereum/p2p/peer.go | 11 + .../ethereum/go-ethereum/p2p/server.go | 232 +- .../p2p/simulations/adapters/docker.go | 2 + .../p2p/simulations/adapters/exec.go | 1 + .../p2p/simulations/adapters/inproc.go | 4 +- .../p2p/simulations/adapters/state.go | 36 + .../p2p/simulations/adapters/types.go | 6 + .../go-ethereum/p2p/simulations/http.go | 64 +- .../go-ethereum/p2p/simulations/mocker.go | 192 + .../go-ethereum/p2p/simulations/network.go | 86 +- .../ethereum/go-ethereum/params/bootnodes.go | 23 +- .../go-ethereum/params/protocol_params.go | 20 +- .../ethereum/go-ethereum/params/version.go | 4 +- .../ethereum/go-ethereum/rlp/raw.go | 2 +- .../ethereum/go-ethereum/rpc/http.go | 78 +- .../ethereum/go-ethereum/swarm/api/api.go | 2 +- .../go-ethereum/swarm/api/client/client.go | 6 +- .../ethereum/go-ethereum/swarm/api/config.go | 131 +- .../swarm/api/http/roundtripper.go | 4 +- .../go-ethereum/swarm/api/http/server.go | 67 +- .../go-ethereum/swarm/api/http/templates.go | 2 +- .../go-ethereum/swarm/api/manifest.go | 10 + .../ethereum/go-ethereum/swarm/api/uri.go | 33 +- .../swarm/dev/scripts/random-uploads.sh | 2 +- .../go-ethereum/swarm/network/hive.go | 12 +- .../swarm/network/kademlia/kaddb.go | 2 +- .../swarm/network/kademlia/kademlia.go | 2 +- .../go-ethereum/swarm/network/syncer.go | 9 +- .../go-ethereum/swarm/services/swap/swap.go | 28 +- .../go-ethereum/swarm/storage/netstore.go | 10 +- .../go-ethereum/swarm/storage/pyramid.go | 18 +- .../ethereum/go-ethereum/swarm/swarm.go | 12 +- .../go-ethereum/tests/block_test_util.go | 24 +- .../go-ethereum/tests/difficulty_test_util.go | 1 - .../go-ethereum/tests/gen_btheader.go | 20 +- .../ethereum/go-ethereum/tests/gen_stenv.go | 8 +- .../go-ethereum/tests/gen_sttransaction.go | 4 +- .../go-ethereum/tests/gen_tttransaction.go | 12 +- .../ethereum/go-ethereum/tests/gen_vmexec.go | 8 +- .../ethereum/go-ethereum/tests/init.go | 2 +- .../go-ethereum/tests/state_test_util.go | 20 +- .../tests/transaction_test_util.go | 8 +- .../go-ethereum/tests/vm_test_util.go | 2 +- .../ethereum/go-ethereum/trie/database.go | 355 + .../ethereum/go-ethereum/trie/hasher.go | 61 +- .../ethereum/go-ethereum/trie/proof.go | 47 +- .../ethereum/go-ethereum/trie/secure_trie.go | 62 +- .../ethereum/go-ethereum/trie/sync.go | 14 +- .../ethereum/go-ethereum/trie/trie.go | 92 +- .../whisper/mailserver/mailserver.go | 2 +- .../go-ethereum/whisper/whisperv2/whisper.go | 4 +- .../go-ethereum/whisper/whisperv5/api.go | 2 +- .../go-ethereum/whisper/whisperv5/filter.go | 8 +- .../whisper/whisperv5/gen_criteria_json.go | 14 +- .../whisper/whisperv5/gen_message_json.go | 28 +- .../whisper/whisperv5/gen_newmessage_json.go | 26 +- vendor/github.com/go-ole/go-ole/.travis.yml | 9 + vendor/github.com/go-ole/go-ole/ChangeLog.md | 49 + vendor/github.com/go-ole/go-ole/LICENSE | 21 + vendor/github.com/go-ole/go-ole/README.md | 46 + vendor/github.com/go-ole/go-ole/appveyor.yml | 54 + vendor/github.com/go-ole/go-ole/com.go | 329 + vendor/github.com/go-ole/go-ole/com_func.go | 174 + vendor/github.com/go-ole/go-ole/connect.go | 192 + vendor/github.com/go-ole/go-ole/constants.go | 153 + vendor/github.com/go-ole/go-ole/error.go | 51 + vendor/github.com/go-ole/go-ole/error_func.go | 8 + .../github.com/go-ole/go-ole/error_windows.go | 24 + vendor/github.com/go-ole/go-ole/guid.go | 284 + .../go-ole/go-ole/iconnectionpoint.go | 20 + .../go-ole/go-ole/iconnectionpoint_func.go | 21 + .../go-ole/go-ole/iconnectionpoint_windows.go | 43 + .../go-ole/iconnectionpointcontainer.go | 17 + .../go-ole/iconnectionpointcontainer_func.go | 11 + .../iconnectionpointcontainer_windows.go | 25 + vendor/github.com/go-ole/go-ole/idispatch.go | 94 + .../go-ole/go-ole/idispatch_func.go | 19 + .../go-ole/go-ole/idispatch_windows.go | 197 + .../github.com/go-ole/go-ole/ienumvariant.go | 19 + .../go-ole/go-ole/ienumvariant_func.go | 19 + .../go-ole/go-ole/ienumvariant_windows.go | 63 + .../github.com/go-ole/go-ole/iinspectable.go | 18 + .../go-ole/go-ole/iinspectable_func.go | 15 + .../go-ole/go-ole/iinspectable_windows.go | 72 + .../go-ole/go-ole/iprovideclassinfo.go | 21 + .../go-ole/go-ole/iprovideclassinfo_func.go | 7 + .../go-ole/iprovideclassinfo_windows.go | 21 + vendor/github.com/go-ole/go-ole/itypeinfo.go | 34 + .../go-ole/go-ole/itypeinfo_func.go | 7 + .../go-ole/go-ole/itypeinfo_windows.go | 21 + vendor/github.com/go-ole/go-ole/iunknown.go | 57 + .../github.com/go-ole/go-ole/iunknown_func.go | 19 + .../go-ole/go-ole/iunknown_windows.go | 58 + vendor/github.com/go-ole/go-ole/ole.go | 157 + .../go-ole/go-ole/oleutil/connection.go | 100 + .../go-ole/go-ole/oleutil/connection_func.go | 10 + .../go-ole/oleutil/connection_windows.go | 58 + .../go-ole/go-ole/oleutil/go-get.go | 6 + .../go-ole/go-ole/oleutil/oleutil.go | 127 + vendor/github.com/go-ole/go-ole/safearray.go | 27 + .../go-ole/go-ole/safearray_func.go | 211 + .../go-ole/go-ole/safearray_windows.go | 337 + .../go-ole/go-ole/safearrayconversion.go | 140 + .../go-ole/go-ole/safearrayslices.go | 33 + vendor/github.com/go-ole/go-ole/utility.go | 101 + vendor/github.com/go-ole/go-ole/variables.go | 16 + vendor/github.com/go-ole/go-ole/variant.go | 105 + .../github.com/go-ole/go-ole/variant_386.go | 11 + .../github.com/go-ole/go-ole/variant_amd64.go | 12 + .../github.com/go-ole/go-ole/variant_s390x.go | 12 + vendor/github.com/go-ole/go-ole/vt_string.go | 58 + vendor/github.com/go-ole/go-ole/winrt.go | 99 + vendor/github.com/go-ole/go-ole/winrt_doc.go | 36 + vendor/github.com/pkg/errors/.gitignore | 24 + vendor/github.com/pkg/errors/.travis.yml | 11 + vendor/github.com/pkg/errors/LICENSE | 23 + vendor/github.com/pkg/errors/README.md | 52 + vendor/github.com/pkg/errors/appveyor.yml | 32 + vendor/github.com/pkg/errors/errors.go | 269 + vendor/github.com/pkg/errors/stack.go | 178 + .../x/sys/windows/asm_windows_386.s | 13 + .../x/sys/windows/asm_windows_amd64.s | 13 + .../golang.org/x/sys/windows/dll_windows.go | 378 + .../golang.org/x/sys/windows/env_windows.go | 29 + vendor/golang.org/x/sys/windows/eventlog.go | 20 + .../golang.org/x/sys/windows/exec_windows.go | 97 + .../x/sys/windows/memory_windows.go | 26 + vendor/golang.org/x/sys/windows/mksyscall.go | 7 + vendor/golang.org/x/sys/windows/race.go | 30 + vendor/golang.org/x/sys/windows/race0.go | 25 + .../x/sys/windows/security_windows.go | 476 + vendor/golang.org/x/sys/windows/service.go | 164 + vendor/golang.org/x/sys/windows/str.go | 22 + vendor/golang.org/x/sys/windows/syscall.go | 71 + .../x/sys/windows/syscall_windows.go | 1153 + .../golang.org/x/sys/windows/types_windows.go | 1333 + .../x/sys/windows/types_windows_386.go | 22 + .../x/sys/windows/types_windows_amd64.go | 22 + .../x/sys/windows/zsyscall_windows.go | 2687 + .../olebedev/go-duktape.v3/.gitattributes | 2 + .../olebedev/go-duktape.v3/.gitignore | 5 + .../olebedev/go-duktape.v3/.travis.yml | 36 + .../olebedev/go-duktape.v3/Gopkg.lock | 21 + .../olebedev/go-duktape.v3/Gopkg.toml | 3 + .../olebedev/go-duktape.v3/LICENSE.md | 21 + .../gopkg.in/olebedev/go-duktape.v3/README.md | 124 + vendor/gopkg.in/olebedev/go-duktape.v3/api.go | 1616 + .../olebedev/go-duktape.v3/appveyor.yml | 34 + .../gopkg.in/olebedev/go-duktape.v3/conts.go | 121 + .../olebedev/go-duktape.v3/duk_alloc_pool.c | 612 + .../olebedev/go-duktape.v3/duk_alloc_pool.h | 223 + .../olebedev/go-duktape.v3/duk_config.h | 3672 + .../olebedev/go-duktape.v3/duk_console.c | 163 + .../olebedev/go-duktape.v3/duk_console.h | 14 + .../olebedev/go-duktape.v3/duk_logging.c | 380 + .../olebedev/go-duktape.v3/duk_logging.h | 20 + .../go-duktape.v3/duk_minimal_printf.c | 312 + .../go-duktape.v3/duk_minimal_printf.h | 12 + .../go-duktape.v3/duk_module_duktape.c | 471 + .../go-duktape.v3/duk_module_duktape.h | 14 + .../olebedev/go-duktape.v3/duk_module_node.c | 333 + .../olebedev/go-duktape.v3/duk_module_node.h | 9 + .../olebedev/go-duktape.v3/duk_print_alert.c | 127 + .../olebedev/go-duktape.v3/duk_print_alert.h | 10 + .../olebedev/go-duktape.v3/duk_v1_compat.c | 131 + .../olebedev/go-duktape.v3/duk_v1_compat.h | 28 + .../gopkg.in/olebedev/go-duktape.v3/duktape.c | 95118 ++++++++++++++++ .../olebedev/go-duktape.v3/duktape.go | 357 + .../gopkg.in/olebedev/go-duktape.v3/duktape.h | 1349 + .../gopkg.in/olebedev/go-duktape.v3/timers.go | 136 + .../gopkg.in/olebedev/go-duktape.v3/utils.go | 10 + .../olebedev/go-duktape.v3/wercker.yml | 14 + 492 files changed, 184855 insertions(+), 10032 deletions(-) delete mode 100644 _assets/patches/geth/0011-geth-17-whisperv6-70fbc87.patch create mode 100644 vendor/github.com/StackExchange/wmi/LICENSE create mode 100644 vendor/github.com/StackExchange/wmi/README.md create mode 100644 vendor/github.com/StackExchange/wmi/swbemservices.go create mode 100644 vendor/github.com/StackExchange/wmi/wmi.go create mode 100644 vendor/github.com/elastic/gosigar/.appveyor.yml create mode 100644 vendor/github.com/elastic/gosigar/.gitignore create mode 100644 vendor/github.com/elastic/gosigar/.travis.yml create mode 100644 vendor/github.com/elastic/gosigar/CHANGELOG.md create mode 100644 vendor/github.com/elastic/gosigar/LICENSE create mode 100644 vendor/github.com/elastic/gosigar/NOTICE create mode 100644 vendor/github.com/elastic/gosigar/README.md create mode 100644 vendor/github.com/elastic/gosigar/Vagrantfile create mode 100644 vendor/github.com/elastic/gosigar/codecov.yml create mode 100644 vendor/github.com/elastic/gosigar/concrete_sigar.go create mode 100644 vendor/github.com/elastic/gosigar/sigar_darwin.go create mode 100644 vendor/github.com/elastic/gosigar/sigar_format.go create mode 100644 vendor/github.com/elastic/gosigar/sigar_freebsd.go create mode 100644 vendor/github.com/elastic/gosigar/sigar_interface.go create mode 100644 vendor/github.com/elastic/gosigar/sigar_linux.go create mode 100644 vendor/github.com/elastic/gosigar/sigar_linux_common.go create mode 100644 vendor/github.com/elastic/gosigar/sigar_openbsd.go create mode 100644 vendor/github.com/elastic/gosigar/sigar_stub.go create mode 100644 vendor/github.com/elastic/gosigar/sigar_unix.go create mode 100644 vendor/github.com/elastic/gosigar/sigar_util.go create mode 100644 vendor/github.com/elastic/gosigar/sigar_windows.go create mode 100644 vendor/github.com/elastic/gosigar/sys/windows/doc.go create mode 100644 vendor/github.com/elastic/gosigar/sys/windows/ntquery.go create mode 100644 vendor/github.com/elastic/gosigar/sys/windows/privileges.go create mode 100644 vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go create mode 100644 vendor/github.com/elastic/gosigar/sys/windows/version.go create mode 100644 vendor/github.com/elastic/gosigar/sys/windows/zsyscall_windows.go create mode 100644 vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/topics.go create mode 100644 vendor/github.com/ethereum/go-ethereum/cmd/ethkey/README.md create mode 100644 vendor/github.com/ethereum/go-ethereum/cmd/ethkey/generate.go create mode 100644 vendor/github.com/ethereum/go-ethereum/cmd/ethkey/inspect.go create mode 100644 vendor/github.com/ethereum/go-ethereum/cmd/ethkey/main.go create mode 100644 vendor/github.com/ethereum/go-ethereum/cmd/ethkey/message.go create mode 100644 vendor/github.com/ethereum/go-ethereum/cmd/ethkey/utils.go create mode 100644 vendor/github.com/ethereum/go-ethereum/cmd/puppeth/genesis.go create mode 100644 vendor/github.com/ethereum/go-ethereum/cmd/puppeth/module_explorer.go create mode 100644 vendor/github.com/ethereum/go-ethereum/cmd/puppeth/module_wallet.go create mode 100644 vendor/github.com/ethereum/go-ethereum/cmd/puppeth/wizard_explorer.go create mode 100644 vendor/github.com/ethereum/go-ethereum/cmd/puppeth/wizard_wallet.go create mode 100644 vendor/github.com/ethereum/go-ethereum/cmd/swarm/config.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/cmd/utils/fdlimit_unix.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/cmd/utils/fdlimit_windows.go rename vendor/github.com/ethereum/go-ethereum/{cmd/utils => common/fdlimit}/fdlimit_freebsd.go (50%) create mode 100644 vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_unix.go create mode 100644 vendor/github.com/ethereum/go-ethereum/common/fdlimit/fdlimit_windows.go create mode 100644 vendor/github.com/ethereum/go-ethereum/contracts/chequebook/contract/mortal.sol create mode 100644 vendor/github.com/ethereum/go-ethereum/contracts/chequebook/contract/owned.sol create mode 100644 vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/AbstractENS.sol create mode 100644 vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/ENS.sol create mode 100644 vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/FIFSRegistrar.sol create mode 100644 vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/PublicResolver.sol delete mode 100644 vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/ens.sol create mode 100644 vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/fifsregistrar.go create mode 100644 vendor/github.com/ethereum/go-ethereum/contracts/ens/contract/publicresolver.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/contracts/release/contract.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/contracts/release/contract.sol delete mode 100644 vendor/github.com/ethereum/go-ethereum/contracts/release/release.go create mode 100644 vendor/github.com/ethereum/go-ethereum/dashboard/assets/.flowconfig create mode 100644 vendor/github.com/ethereum/go-ethereum/dashboard/assets/common.jsx create mode 100644 vendor/github.com/ethereum/go-ethereum/dashboard/assets/components/Body.jsx create mode 100644 vendor/github.com/ethereum/go-ethereum/dashboard/assets/components/ChartRow.jsx delete mode 100644 vendor/github.com/ethereum/go-ethereum/dashboard/assets/components/Common.jsx create mode 100644 vendor/github.com/ethereum/go-ethereum/dashboard/assets/components/CustomTooltip.jsx create mode 100644 vendor/github.com/ethereum/go-ethereum/dashboard/assets/components/Footer.jsx delete mode 100644 vendor/github.com/ethereum/go-ethereum/dashboard/assets/components/Home.jsx rename vendor/github.com/ethereum/go-ethereum/dashboard/assets/{public => }/dashboard.html (69%) create mode 100644 vendor/github.com/ethereum/go-ethereum/dashboard/assets/fa-only-woff-loader.js create mode 100644 vendor/github.com/ethereum/go-ethereum/dashboard/assets/package-lock.json create mode 100644 vendor/github.com/ethereum/go-ethereum/dashboard/assets/types/content.jsx create mode 100644 vendor/github.com/ethereum/go-ethereum/dashboard/cpu.go create mode 100644 vendor/github.com/ethereum/go-ethereum/dashboard/cpu_windows.go create mode 100644 vendor/github.com/ethereum/go-ethereum/dashboard/message.go create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/api_tracer.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/eth/bind.go create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/internal/tracers/4byte_tracer.js create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/internal/tracers/assets.go create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/internal/tracers/call_tracer.js create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/internal/tracers/evmdis_tracer.js create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/internal/tracers/noop_tracer.js create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/internal/tracers/opcount_tracer.js create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/internal/tracers/prestate_tracer.js create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/internal/tracers/tracers.go create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/testdata/call_tracer_create.json create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/testdata/call_tracer_deep_calls.json create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/testdata/call_tracer_delegatecall.json create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/testdata/call_tracer_inner_create_oog_outer_throw.json create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/testdata/call_tracer_inner_throw_outer_revert.json create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/testdata/call_tracer_oog.json create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/testdata/call_tracer_revert.json create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/testdata/call_tracer_simple.json create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/testdata/call_tracer_throw.json create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/tracer.go create mode 100644 vendor/github.com/ethereum/go-ethereum/eth/tracers/tracers.go delete mode 100644 vendor/github.com/ethereum/go-ethereum/internal/ethapi/tracer.go create mode 100644 vendor/github.com/ethereum/go-ethereum/p2p/enr/enr.go create mode 100644 vendor/github.com/ethereum/go-ethereum/p2p/enr/entries.go create mode 100644 vendor/github.com/ethereum/go-ethereum/p2p/simulations/adapters/state.go create mode 100644 vendor/github.com/ethereum/go-ethereum/p2p/simulations/mocker.go create mode 100644 vendor/github.com/ethereum/go-ethereum/trie/database.go create mode 100644 vendor/github.com/go-ole/go-ole/.travis.yml create mode 100644 vendor/github.com/go-ole/go-ole/ChangeLog.md create mode 100644 vendor/github.com/go-ole/go-ole/LICENSE create mode 100644 vendor/github.com/go-ole/go-ole/README.md create mode 100644 vendor/github.com/go-ole/go-ole/appveyor.yml create mode 100644 vendor/github.com/go-ole/go-ole/com.go create mode 100644 vendor/github.com/go-ole/go-ole/com_func.go create mode 100644 vendor/github.com/go-ole/go-ole/connect.go create mode 100644 vendor/github.com/go-ole/go-ole/constants.go create mode 100644 vendor/github.com/go-ole/go-ole/error.go create mode 100644 vendor/github.com/go-ole/go-ole/error_func.go create mode 100644 vendor/github.com/go-ole/go-ole/error_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/guid.go create mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpoint.go create mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go create mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go create mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go create mode 100644 vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/idispatch.go create mode 100644 vendor/github.com/go-ole/go-ole/idispatch_func.go create mode 100644 vendor/github.com/go-ole/go-ole/idispatch_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/ienumvariant.go create mode 100644 vendor/github.com/go-ole/go-ole/ienumvariant_func.go create mode 100644 vendor/github.com/go-ole/go-ole/ienumvariant_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/iinspectable.go create mode 100644 vendor/github.com/go-ole/go-ole/iinspectable_func.go create mode 100644 vendor/github.com/go-ole/go-ole/iinspectable_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/iprovideclassinfo.go create mode 100644 vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go create mode 100644 vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/itypeinfo.go create mode 100644 vendor/github.com/go-ole/go-ole/itypeinfo_func.go create mode 100644 vendor/github.com/go-ole/go-ole/itypeinfo_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/iunknown.go create mode 100644 vendor/github.com/go-ole/go-ole/iunknown_func.go create mode 100644 vendor/github.com/go-ole/go-ole/iunknown_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/ole.go create mode 100644 vendor/github.com/go-ole/go-ole/oleutil/connection.go create mode 100644 vendor/github.com/go-ole/go-ole/oleutil/connection_func.go create mode 100644 vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/oleutil/go-get.go create mode 100644 vendor/github.com/go-ole/go-ole/oleutil/oleutil.go create mode 100644 vendor/github.com/go-ole/go-ole/safearray.go create mode 100644 vendor/github.com/go-ole/go-ole/safearray_func.go create mode 100644 vendor/github.com/go-ole/go-ole/safearray_windows.go create mode 100644 vendor/github.com/go-ole/go-ole/safearrayconversion.go create mode 100644 vendor/github.com/go-ole/go-ole/safearrayslices.go create mode 100644 vendor/github.com/go-ole/go-ole/utility.go create mode 100644 vendor/github.com/go-ole/go-ole/variables.go create mode 100644 vendor/github.com/go-ole/go-ole/variant.go create mode 100644 vendor/github.com/go-ole/go-ole/variant_386.go create mode 100644 vendor/github.com/go-ole/go-ole/variant_amd64.go create mode 100644 vendor/github.com/go-ole/go-ole/variant_s390x.go create mode 100644 vendor/github.com/go-ole/go-ole/vt_string.go create mode 100644 vendor/github.com/go-ole/go-ole/winrt.go create mode 100644 vendor/github.com/go-ole/go-ole/winrt_doc.go create mode 100644 vendor/github.com/pkg/errors/.gitignore create mode 100644 vendor/github.com/pkg/errors/.travis.yml create mode 100644 vendor/github.com/pkg/errors/LICENSE create mode 100644 vendor/github.com/pkg/errors/README.md create mode 100644 vendor/github.com/pkg/errors/appveyor.yml create mode 100644 vendor/github.com/pkg/errors/errors.go create mode 100644 vendor/github.com/pkg/errors/stack.go create mode 100644 vendor/golang.org/x/sys/windows/asm_windows_386.s create mode 100644 vendor/golang.org/x/sys/windows/asm_windows_amd64.s create mode 100644 vendor/golang.org/x/sys/windows/dll_windows.go create mode 100644 vendor/golang.org/x/sys/windows/env_windows.go create mode 100644 vendor/golang.org/x/sys/windows/eventlog.go create mode 100644 vendor/golang.org/x/sys/windows/exec_windows.go create mode 100644 vendor/golang.org/x/sys/windows/memory_windows.go create mode 100644 vendor/golang.org/x/sys/windows/mksyscall.go create mode 100644 vendor/golang.org/x/sys/windows/race.go create mode 100644 vendor/golang.org/x/sys/windows/race0.go create mode 100644 vendor/golang.org/x/sys/windows/security_windows.go create mode 100644 vendor/golang.org/x/sys/windows/service.go create mode 100644 vendor/golang.org/x/sys/windows/str.go create mode 100644 vendor/golang.org/x/sys/windows/syscall.go create mode 100644 vendor/golang.org/x/sys/windows/syscall_windows.go create mode 100644 vendor/golang.org/x/sys/windows/types_windows.go create mode 100644 vendor/golang.org/x/sys/windows/types_windows_386.go create mode 100644 vendor/golang.org/x/sys/windows/types_windows_amd64.go create mode 100644 vendor/golang.org/x/sys/windows/zsyscall_windows.go create mode 100644 vendor/gopkg.in/olebedev/go-duktape.v3/.gitattributes create mode 100644 vendor/gopkg.in/olebedev/go-duktape.v3/.gitignore create mode 100644 vendor/gopkg.in/olebedev/go-duktape.v3/.travis.yml create mode 100644 vendor/gopkg.in/olebedev/go-duktape.v3/Gopkg.lock create mode 100644 vendor/gopkg.in/olebedev/go-duktape.v3/Gopkg.toml create mode 100644 vendor/gopkg.in/olebedev/go-duktape.v3/LICENSE.md create mode 100644 vendor/gopkg.in/olebedev/go-duktape.v3/README.md create mode 100644 vendor/gopkg.in/olebedev/go-duktape.v3/api.go create mode 100644 vendor/gopkg.in/olebedev/go-duktape.v3/appveyor.yml create mode 100644 vendor/gopkg.in/olebedev/go-duktape.v3/conts.go create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_alloc_pool.c create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_alloc_pool.h create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_config.h create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_console.c create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_console.h create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_logging.c create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_logging.h create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_minimal_printf.c create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_minimal_printf.h create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_module_duktape.c create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_module_duktape.h create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_module_node.c create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_module_node.h create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_print_alert.c create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_print_alert.h create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_v1_compat.c create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duk_v1_compat.h create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duktape.c create mode 100644 vendor/gopkg.in/olebedev/go-duktape.v3/duktape.go create mode 100755 vendor/gopkg.in/olebedev/go-duktape.v3/duktape.h create mode 100644 vendor/gopkg.in/olebedev/go-duktape.v3/timers.go create mode 100644 vendor/gopkg.in/olebedev/go-duktape.v3/utils.go create mode 100644 vendor/gopkg.in/olebedev/go-duktape.v3/wercker.yml diff --git a/Gopkg.lock b/Gopkg.lock index 5ba527eb182..0e5d6131f5d 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -7,6 +7,12 @@ packages = ["."] revision = "2a6c4f48b49f0d5dbfe621589da4c5405157d7c9" +[[projects]] + branch = "master" + name = "github.com/StackExchange/wmi" + packages = ["."] + revision = "5d049714c4a64225c3c79a7cf7d02f7fb5b96338" + [[projects]] name = "github.com/aristanetworks/goarista" packages = ["monotime"] @@ -46,6 +52,15 @@ packages = ["."] revision = "935e0e8a636ca4ba70b713f3e38a19e1b77739e8" +[[projects]] + name = "github.com/elastic/gosigar" + packages = [ + ".", + "sys/windows" + ] + revision = "16df19fe5efee4ea2938bde5f56c02d9929dc054" + version = "v0.8.0" + [[projects]] name = "github.com/ethereum/go-ethereum" packages = [ @@ -57,6 +72,7 @@ "cmd/utils", "common", "common/bitutil", + "common/fdlimit", "common/hexutil", "common/math", "common/mclock", @@ -81,6 +97,8 @@ "eth/fetcher", "eth/filters", "eth/gasprice", + "eth/tracers", + "eth/tracers/internal/tracers", "ethdb", "ethstats", "event", @@ -104,10 +122,20 @@ "rpc", "trie", "whisper/mailserver", - "whisper/whisperv5" + "whisper/whisperv5", + "whisper/whisperv6" + ] + revision = "5f54075760748ae7f249bf735565924ea885c477" + version = "v1.8.0" + +[[projects]] + name = "github.com/go-ole/go-ole" + packages = [ + ".", + "oleutil" ] - revision = "4bb3c89d44e372e6a9ab85a8be0c9345265c763a" - version = "v1.7.3" + revision = "a41e3c4b706f6ae8dfbff342b06e40fa4d2d0506" + version = "v1.2.1" [[projects]] name = "github.com/go-playground/locales" @@ -200,6 +228,12 @@ packages = ["."] revision = "1b00554d822231195d1babd97ff4a781231955c9" +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "645ef00459ed84a119197bfb8d8205042c6df63d" + version = "v0.8.0" + [[projects]] name = "github.com/pmezard/go-difflib" packages = ["difflib"] @@ -340,7 +374,10 @@ [[projects]] branch = "master" name = "golang.org/x/sys" - packages = ["unix"] + packages = [ + "unix", + "windows" + ] revision = "2c42eef0765b9837fbdab12011af7830f55f88f0" [[projects]] @@ -394,6 +431,12 @@ packages = ["."] revision = "c1b8fa8bdccecb0b8db834ee0b92fdbcfa606dd6" +[[projects]] + branch = "v3" + name = "gopkg.in/olebedev/go-duktape.v3" + packages = ["."] + revision = "3c4db4ad4f2db84859454dc805d6eb7d8051a8ce" + [[projects]] name = "gopkg.in/sourcemap.v1" packages = [ @@ -412,6 +455,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "15f735a948b26a34148ed3fa3a1d21cb1a3c45d0b87eb490a2ca1a514e4b1250" + inputs-digest = "607ea9c619b417bcb42e03b9cc84cb6916db143559595373fe6d23520d17a0eb" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 51bb5bc87d9..b9f549b4be8 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -24,7 +24,7 @@ ignored = ["github.com/ethereum/go-ethereum/whisper/notifications"] [[constraint]] name = "github.com/ethereum/go-ethereum" - branch = "release/1.7" + branch = "release/1.8" [[constraint]] name = "github.com/prometheus/client_golang" diff --git a/_assets/patches/geth/0006-latest-cht.patch b/_assets/patches/geth/0006-latest-cht.patch index c9152a9e99f..17c041a4264 100644 --- a/_assets/patches/geth/0006-latest-cht.patch +++ b/_assets/patches/geth/0006-latest-cht.patch @@ -3,8 +3,8 @@ index e7e513880..dc6562be8 100644 --- a/light/postprocess.go +++ b/light/postprocess.go @@ -66,12 +66,20 @@ var ( - chtRoot: common.HexToHash("6f56dc61936752cc1f8c84b4addabdbe6a1c19693de3f21cb818362df2117f03"), - bloomTrieRoot: common.HexToHash("aca7d7c504d22737242effc3fdc604a762a0af9ced898036b5986c3a15220208"), + chtRoot: common.HexToHash("71d60207af74e5a22a3e1cfbfc89f9944f91b49aa980c86fba94d568369eaf44"), + bloomTrieRoot: common.HexToHash("70aca4b3b6d08dde8704c95cedb1420394453c1aec390947751e69ff8c436360"), } + + statusRopstenCheckpoint = trustedCheckpoint{ diff --git a/_assets/patches/geth/0011-geth-17-whisperv6-70fbc87.patch b/_assets/patches/geth/0011-geth-17-whisperv6-70fbc87.patch deleted file mode 100644 index 859cd77e813..00000000000 --- a/_assets/patches/geth/0011-geth-17-whisperv6-70fbc87.patch +++ /dev/null @@ -1,2553 +0,0 @@ -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 e64dd2f42..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,39 +37,46 @@ import ( - "time" - ) - -+// Whisper protocol parameters - const ( -- EnvelopeVersion = uint64(0) -- ProtocolVersion = uint64(5) -- ProtocolVersionStr = "5.0" -- ProtocolName = "shh" -- -- statusCode = 0 // used by whisper protocol -- messagesCode = 1 // normal whisper message -- p2pCode = 2 // peer-to-peer message (to be consumed by the peer, but not forwarded any further) -- p2pRequestCode = 3 // peer-to-peer message, used by Dapp protocol -- NumberOfMessageCodes = 64 -- -- paddingMask = byte(3) -+ 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 -+ messagesCode = 1 // normal whisper message -+ powRequirementCode = 2 // PoW requirement -+ bloomFilterExCode = 3 // bloom filter exchange -+ p2pRequestCode = 126 // peer-to-peer message, used by Dapp protocol -+ p2pMessageCode = 127 // peer-to-peer message (to be consumed by the peer, but not forwarded any further) -+ NumberOfMessageCodes = 128 -+ -+ 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 -+ DefaultTTL = 50 // seconds -+ DefaultSyncAllowance = 10 // seconds - ) - - type unknownVersionError uint64 -diff --git a/whisper/whisperv6/envelope.go b/whisper/whisperv6/envelope.go -index a5f4770b0..c7bea2bb9 100644 ---- a/whisper/whisperv6/envelope.go -+++ b/whisper/whisperv6/envelope.go -@@ -36,76 +36,60 @@ import ( - // Envelope represents a clear-text data packet to transmit through the Whisper - // network. Its contents may or may not be encrypted and signed. - type Envelope struct { -- Version []byte -- Expiry uint32 -- TTL uint32 -- Topic TopicType -- AESNonce []byte -- Data []byte -- EnvNonce 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. -+ Expiry uint32 -+ TTL uint32 -+ Topic TopicType -+ Data []byte -+ Nonce uint64 -+ -+ 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) - func (e *Envelope) size() int { -- return 20 + len(e.Version) + len(e.AESNonce) + len(e.Data) -+ return EnvelopeHeaderLength + len(e.Data) - } - - // rlpWithoutNonce returns the RLP encoded envelope contents, except the nonce. - func (e *Envelope) rlpWithoutNonce() []byte { -- res, _ := rlp.EncodeToBytes([]interface{}{e.Version, e.Expiry, e.TTL, e.Topic, e.AESNonce, e.Data}) -+ res, _ := rlp.EncodeToBytes([]interface{}{e.Expiry, e.TTL, e.Topic, e.Data}) - return res - } - - // NewEnvelope wraps a Whisper message with expiration and destination data - // included into an envelope for network forwarding. --func NewEnvelope(ttl uint32, topic TopicType, aesNonce []byte, msg *sentMessage) *Envelope { -+func NewEnvelope(ttl uint32, topic TopicType, msg *sentMessage) *Envelope { - env := Envelope{ -- Version: make([]byte, 1), -- Expiry: uint32(time.Now().Add(time.Second * time.Duration(ttl)).Unix()), -- TTL: ttl, -- Topic: topic, -- AESNonce: aesNonce, -- Data: msg.Raw, -- EnvNonce: 0, -- } -- -- if EnvelopeVersion < 256 { -- env.Version[0] = byte(EnvelopeVersion) -- } else { -- panic("please increase the size of Envelope.Version before releasing this version") -+ Expiry: uint32(time.Now().Add(time.Second * time.Duration(ttl)).Unix()), -+ TTL: ttl, -+ Topic: topic, -+ Data: msg.Raw, -+ Nonce: 0, - } - - return &env - } - --func (e *Envelope) IsSymmetric() bool { -- return len(e.AESNonce) > 0 --} -- --func (e *Envelope) isAsymmetric() bool { -- return !e.IsSymmetric() --} -- --func (e *Envelope) Ver() uint64 { -- return bytesToUintLittleEndian(e.Version) --} -- - // 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) -@@ -119,7 +103,7 @@ func (e *Envelope) Seal(options *MessageParams) error { - d := new(big.Int).SetBytes(crypto.Keccak256(buf)) - firstBit := math.FirstBitSet(d) - if firstBit > bestBit { -- e.EnvNonce, bestBit = nonce, firstBit -+ e.Nonce, bestBit = nonce, firstBit - if target > 0 && bestBit >= target { - return nil - } -@@ -135,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) -@@ -146,7 +132,7 @@ func (e *Envelope) calculatePoW(diff uint32) { - buf := make([]byte, 64) - h := crypto.Keccak256(e.rlpWithoutNonce()) - copy(buf[:32], h) -- binary.BigEndian.PutUint64(buf[56:], e.EnvNonce) -+ binary.BigEndian.PutUint64(buf[56:], e.Nonce) - d := new(big.Int).SetBytes(crypto.Keccak256(buf)) - firstBit := math.FirstBitSet(d) - x := gmath.Pow(2, float64(firstBit)) -@@ -161,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. -@@ -209,7 +199,7 @@ func (e *Envelope) OpenAsymmetric(key *ecdsa.PrivateKey) (*ReceivedMessage, erro - // OpenSymmetric tries to decrypt an envelope, potentially encrypted with a particular key. - func (e *Envelope) OpenSymmetric(key []byte) (msg *ReceivedMessage, err error) { - msg = &ReceivedMessage{Raw: e.Data} -- err = msg.decryptSymmetric(key, e.AESNonce) -+ err = msg.decryptSymmetric(key) - if err != nil { - msg = nil - } -@@ -218,12 +208,17 @@ 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) { -- if e.isAsymmetric() { -+ // The API interface forbids filters doing both symmetric and asymmetric encryption. -+ if watcher.expectsAsymmetricEncryption() && watcher.expectsSymmetricEncryption() { -+ return nil -+ } -+ -+ if watcher.expectsAsymmetricEncryption() { - msg, _ = e.OpenAsymmetric(watcher.KeyAsym) - if msg != nil { - msg.Dst = &watcher.KeyAsym.PublicKey - } -- } else if e.IsSymmetric() { -+ } else if watcher.expectsSymmetricEncryption() { - msg, _ = e.OpenSymmetric(watcher.KeySym) - if msg != nil { - msg.SymKeyHash = crypto.Keccak256Hash(watcher.KeySym) -@@ -231,7 +226,7 @@ func (e *Envelope) Open(watcher *Filter) (msg *ReceivedMessage) { - } - - if msg != nil { -- ok := msg.Validate() -+ ok := msg.ValidateAndParse() - if !ok { - return nil - } -@@ -240,7 +235,33 @@ func (e *Envelope) Open(watcher *Filter) (msg *ReceivedMessage) { - msg.TTL = e.TTL - msg.Sent = e.Expiry - e.TTL - msg.EnvelopeHash = e.Hash() -- msg.EnvelopeVersion = e.Ver() - } - 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 5cb371b7d..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,7 +55,12 @@ 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") -+ } -+ - if watcher.Messages == nil { - watcher.Messages = make(map[common.Hash]*ReceivedMessage) - } -@@ -77,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() -@@ -87,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 - -@@ -136,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()) - } -@@ -153,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() -@@ -162,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() -@@ -175,6 +192,9 @@ func (f *Filter) Retrieve() (all []*ReceivedMessage) { - return all - } - -+// MatchMessage checks if the filter matches an already decrypted -+// message (i.e. a Message that has already been handled by -+// MatchEnvelope when checked by a previous filter) - func (f *Filter) MatchMessage(msg *ReceivedMessage) bool { - if f.PoW > 0 && msg.PoW < f.PoW { - return false -@@ -188,19 +208,18 @@ func (f *Filter) MatchMessage(msg *ReceivedMessage) bool { - return false - } - -+// 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 { - if f.PoW > 0 && envelope.pow < f.PoW { - return false - } - -- if f.expectsAsymmetricEncryption() && envelope.isAsymmetric() { -- return f.MatchTopic(envelope.Topic) -- } else if f.expectsSymmetricEncryption() && envelope.IsSymmetric() { -- return f.MatchTopic(envelope.Topic) -- } -- return false -+ 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 -@@ -216,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 { -@@ -228,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/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 0815f07a2..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,13 +56,14 @@ 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 - - Payload []byte - Padding []byte - Signature []byte -+ Salt []byte - - PoW float64 // Proof of work as described in the Whisper spec - Sent uint32 // Time when the message was posted into the network -@@ -69,9 +72,8 @@ 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 -- EnvelopeHash common.Hash // Message envelope hash to act as a unique id -- EnvelopeVersion uint64 -+ SymKeyHash common.Hash // The Keccak256Hash of the key -+ EnvelopeHash common.Hash // Message envelope hash to act as a unique id - } - - func isMessageSigned(flags byte) bool { -@@ -86,79 +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 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 -+ } -+ -+ 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 - } - -@@ -171,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...) -@@ -196,31 +181,56 @@ 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) (nonce []byte, err error) { -- if !validateSymmetricKey(key) { -- return nil, errors.New("invalid key provided for symmetric encryption") -+func (msg *sentMessage) encryptSymmetric(key []byte) (err error) { -+ 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 nil, err -+ return err - } - aesgcm, err := cipher.NewGCM(block) - if err != nil { -- return nil, err -+ return err -+ } -+ salt, err := generateSecureRandomData(aesNonceLength) // never use more than 2^32 random nonces with a given key -+ if err != nil { -+ return err - } -+ encrypted := aesgcm.Seal(nil, salt, msg.Raw, nil) -+ msg.Raw = append(encrypted, salt...) -+ return nil -+} - -- // never use more than 2^32 random nonces with a given key -- nonce = make([]byte, aesgcm.NonceSize()) -- _, err = crand.Read(nonce) -+// 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 !validateSymmetricKey(nonce) { -- return nil, errors.New("crypto/rand failed to generate nonce") -+ } else if !validateDataIntegrity(x, length) { -+ return nil, errors.New("crypto/rand failed to generate secure random data") - } -- -- msg.Raw = aesgcm.Seal(nil, nonce, msg.Raw, nil) -- return nonce, nil -+ _, 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. -@@ -233,11 +243,10 @@ func (msg *sentMessage) Wrap(options *MessageParams) (envelope *Envelope, err er - return nil, err - } - } -- var nonce []byte - if options.Dst != nil { - err = msg.encryptAsymmetric(options.Dst) - } else if options.KeySym != nil { -- nonce, err = msg.encryptSymmetric(options.KeySym) -+ err = msg.encryptSymmetric(options.KeySym) - } else { - err = errors.New("unable to encrypt the message: neither symmetric nor assymmetric key provided") - } -@@ -245,7 +254,7 @@ func (msg *sentMessage) Wrap(options *MessageParams) (envelope *Envelope, err er - return nil, err - } - -- envelope = NewEnvelope(options.TTL, options.Topic, nonce, msg) -+ envelope = NewEnvelope(options.TTL, options.Topic, msg) - if err = envelope.Seal(options); err != nil { - return nil, err - } -@@ -254,7 +263,13 @@ 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, nonce []byte) error { -+func (msg *ReceivedMessage) decryptSymmetric(key []byte) error { -+ // 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:] -+ - block, err := aes.NewCipher(key) - if err != nil { - return err -@@ -263,15 +278,12 @@ func (msg *ReceivedMessage) decryptSymmetric(key []byte, nonce []byte) error { - if err != nil { - return err - } -- if len(nonce) != aesgcm.NonceSize() { -- log.Error("decrypting the message", "AES nonce size", len(nonce)) -- return errors.New("wrong AES nonce size") -- } -- decrypted, err := aesgcm.Open(nil, nonce, msg.Raw, nil) -+ decrypted, err := aesgcm.Open(nil, salt, msg.Raw[:len(msg.Raw)-aesNonceLength], nil) - if err != nil { - return err - } - msg.Raw = decrypted -+ msg.Salt = salt - return nil - } - -@@ -284,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 -@@ -296,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 - -@@ -342,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/peer.go b/whisper/whisperv6/peer.go -index ac7b3b12b..4ef0f3c43 100644 ---- a/whisper/whisperv6/peer.go -+++ b/whisper/whisperv6/peer.go -@@ -18,6 +18,7 @@ package whisperv6 - - import ( - "fmt" -+ "math" - "time" - - "github.com/ethereum/go-ethereum/common" -@@ -27,12 +28,16 @@ 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 -- ws p2p.MsgReadWriter -- trusted bool -+ host *Whisper -+ peer *p2p.Peer -+ ws p2p.MsgReadWriter -+ -+ trusted bool -+ powRequirement float64 -+ bloomFilter []byte -+ fullNode bool - - known *set.Set // Messages already known by the peer to avoid wasting bandwidth - -@@ -42,62 +47,93 @@ type Peer struct { - // newPeer creates a new whisper peer object, but does not run the handshake itself. - func newPeer(host *Whisper, remote *p2p.Peer, rw p2p.MsgReadWriter) *Peer { - return &Peer{ -- host: host, -- peer: remote, -- ws: rw, -- trusted: false, -- known: set.New(), -- quit: make(chan struct{}), -+ host: host, -+ peer: remote, -+ ws: rw, -+ trusted: false, -+ 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) -@@ -106,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 - } - } -@@ -148,27 +184,62 @@ func (peer *Peer) expire() { - - // broadcast iterates over the collection of envelopes and transmits yet unknown - // ones over the network. --func (p *Peer) broadcast() error { -- var cnt int -- 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) { -- err := p2p.Send(p.ws, messagesCode, envelope) -- if err != nil { -- return err -- } else { -- p.mark(envelope) -- cnt++ -- } -+ if !peer.marked(envelope) && envelope.PoW() >= peer.powRequirement && peer.bloomMatch(envelope) { -+ bundle = append(bundle, envelope) - } - } -- if cnt > 0 { -- log.Trace("broadcast", "num. messages", cnt) -+ -+ if len(bundle) > 0 { -+ // transmit the batch of envelopes -+ if err := p2p.Send(peer.ws, messagesCode, bundle); err != nil { -+ return err -+ } -+ -+ // mark envelopes only if they were successfully sent -+ for _, e := range bundle { -+ peer.mark(e) -+ } -+ -+ log.Trace("broadcast", "num. messages", len(bundle)) - } - 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 (peer *Peer) notifyAboutPowRequirementChange(pow float64) error { -+ i := math.Float64bits(pow) -+ 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/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 e2b884f3d..600f9cb28 100644 ---- a/whisper/whisperv6/whisper.go -+++ b/whisper/whisperv6/whisper.go -@@ -19,9 +19,9 @@ package whisperv6 - import ( - "bytes" - "crypto/ecdsa" -- crand "crypto/rand" - "crypto/sha256" - "fmt" -+ "math" - "runtime" - "sync" - "time" -@@ -30,6 +30,7 @@ import ( - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/p2p" -+ "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/rpc" - "github.com/syndtr/goleveldb/leveldb/errors" - "golang.org/x/crypto/pbkdf2" -@@ -37,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 -@@ -46,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 -@@ -74,6 +80,8 @@ type Whisper struct { - - settings syncmap.Map // holds configuration settings that can be dynamically changed - -+ syncAllowance int // maximum time in seconds allowed to process the whisper-related messages -+ - statsMu sync.Mutex // guard stats - stats Statistics // Statistics of whisper node - -@@ -87,14 +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{}), -+ 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) -@@ -121,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, - }, - } -@@ -152,43 +205,120 @@ 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 { -- if val <= 0.0 { -+func (whisper *Whisper) SetMinimumPoW(val float64) error { -+ if val < 0.0 { - return fmt.Errorf("invalid PoW: %f", val) - } -- w.settings.Store(minPowIdx, 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(whisper.syncAllowance) * time.Second) -+ whisper.settings.Store(minPowToleranceIdx, val) -+ }() -+ - return nil - } - -+// 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 (whisper *Whisper) notifyPeersAboutPowRequirementChange(pow float64) { -+ arr := whisper.getPeers() -+ for _, p := range arr { -+ err := p.notifyAboutPowRequirementChange(pow) -+ if err != nil { -+ // allow one retry -+ err = p.notifyAboutPowRequirementChange(pow) -+ } -+ if err != nil { -+ 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 -@@ -199,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 - } -@@ -213,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 - } -@@ -223,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 { -- return p2p.Send(peer.ws, p2pCode, envelope) -+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 -@@ -255,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") - } -@@ -312,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") - } - -@@ -326,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)) - } -@@ -347,85 +476,108 @@ 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") - } - -- derived, err := deriveKeyMaterial([]byte(password), EnvelopeVersion) -+ // kdf should run no less than 0.1 seconds on an average computer, -+ // because it's an once in a session experience -+ derived := pbkdf2.Key([]byte(password), nil, 65356, aesKeyLength, sha256.New) - if err != nil { - 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") - } -@@ -434,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 - } -@@ -447,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 -@@ -461,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 -@@ -490,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() -@@ -502,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") - } -@@ -513,20 +665,53 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { - log.Warn("unxepected status message received", "peer", p.peer.ID()) - case messagesCode: - // decode the contained envelopes -- var envelope Envelope -- if err := packet.Decode(&envelope); err != nil { -- log.Warn("failed to decode envelope, peer will be disconnected", "peer", p.peer.ID(), "err", err) -+ var envelopes []*Envelope -+ if err := packet.Decode(&envelopes); err != nil { -+ log.Warn("failed to decode envelopes, peer will be disconnected", "peer", p.peer.ID(), "err", err) -+ return errors.New("invalid envelopes") -+ } -+ -+ trouble := false -+ for _, env := range envelopes { -+ 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) -+ } -+ if cached { -+ p.mark(env) -+ } -+ } -+ -+ if trouble { - return errors.New("invalid envelope") - } -- cached, err := wh.add(&envelope) -+ case powRequirementCode: -+ s := rlp.NewStream(packet.Payload, uint64(packet.Size)) -+ i, err := s.Uint() - if err != nil { -- log.Warn("bad envelope received, peer will be disconnected", "peer", p.peer.ID(), "err", err) -- return errors.New("invalid envelope") -+ log.Warn("failed to decode powRequirementCode message, peer will be disconnected", "peer", p.peer.ID(), "err", err) -+ return errors.New("invalid powRequirementCode message") -+ } -+ f := math.Float64frombits(i) -+ if math.IsInf(f, 0) || math.IsNaN(f) || f < 0.0 { -+ log.Warn("invalid value in powRequirementCode message, peer will be disconnected", "peer", p.peer.ID(), "err", err) -+ return errors.New("invalid value in powRequirementCode message") -+ } -+ p.powRequirement = f -+ case bloomFilterExCode: -+ var bloom []byte -+ err := packet.Decode(&bloom) -+ if err == nil && len(bloom) != bloomFilterSize { -+ err = fmt.Errorf("wrong bloom filter size %d", len(bloom)) - } -- if cached { -- p.mark(&envelope) -+ -+ 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") - } -- case p2pCode: -+ 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 - // therefore might not satisfy the PoW, expiry and other requirements. -@@ -537,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. -@@ -561,130 +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 len(envelope.Version) > 4 { -- return false, fmt.Errorf("oversized version [%x]", envelope.Hash()) -- } -- -- aesNonceSize := len(envelope.AESNonce) -- if aesNonceSize != 0 && aesNonceSize != AESNonceLength { -- // the standard AES GCM nonce size is 12 bytes, -- // but constant gcmStandardNonceSize cannot be accessed (not exported) -- return false, fmt.Errorf("wrong size of AESNonce: %d bytes [env: %x]", aesNonceSize, envelope.Hash()) -+ 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()) -+ } - } - -- 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 -+ 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) { -- // if the version of incoming message is higher than -- // currently supported version, we can not decrypt it, -- // and therefore just ignore this message -- if envelope.Ver() <= EnvelopeVersion { -- if isP2P { -- w.p2pMsgQueue <- envelope -- } else { -- w.checkOverflow() -- w.messageQueue <- envelope -- } -+func (whisper *Whisper) postEvent(envelope *Envelope, isP2P bool) { -+ if isP2P { -+ whisper.p2pMsgQueue <- envelope -+ } else { -+ 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) - -@@ -692,9 +873,9 @@ func (w *Whisper) update() { - for { - select { - case <-expire.C: -- w.expire() -+ whisper.expire() - -- case <-w.quit: -+ case <-whisper.quit: - return - } - } -@@ -702,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 -@@ -749,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) -@@ -766,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 - } - -@@ -796,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. -@@ -830,29 +1018,51 @@ func BytesToUintBigEndian(b []byte) (res uint64) { - return res - } - --// deriveKeyMaterial derives symmetric key material from the key or password. --// pbkdf2 is used for security, in case people use password instead of randomly generated keys. --func deriveKeyMaterial(key []byte, version uint64) (derivedKey []byte, err error) { -- if version == 0 { -- // kdf should run no less than 0.1 seconds on average compute, -- // because it's a once in a session experience -- derivedKey := pbkdf2.Key(key, nil, 65356, aesKeyLength, sha256.New) -- return derivedKey, nil -- } else { -- return nil, unknownVersionError(version) -- } --} -- - // 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/_assets/patches/geth/README.md b/_assets/patches/geth/README.md index ff9ce7aa4cc..bb18dfdd731 100644 --- a/_assets/patches/geth/README.md +++ b/_assets/patches/geth/README.md @@ -35,7 +35,6 @@ Instructions for creating a patch from the command line: - [`0006-latest-cht.patch`](./0006-latest-cht.patch) – updates CHT root hashes, should be updated regularly to keep sync fast, until proper Trusted Checkpoint sync is not implemented as part of LES/2 protocol. - [`0009-whisper-envelopes-tracing.patch`](./0009-whisper-envelopes-tracing.patch) — adds Whisper envelope tracing (need to be reviewed and documented) - [`0010-geth-17-fix-npe-in-filter-system.patch`](./0010-geth-17-fix-npe-in-filter-system.patch) - Temp patch for 1.7.x to fix a NPE in the filter system. -- [`0011-geth-17-whisperv6-70fbc87.patch`](./0011-geth-17-whisperv6-70fbc87.patch) - Temp patch for 1.7.x to update whisper v6 to the upstream version at the `70fbc87` SHA1. - [`0013-whisperv6-notifications-envelopeversion.patch`](./0013-whisperv6-notifications-envelopeversion.patch) — replaces usage of EnvelopeVersion with ProtocolVersion in notifications for Whisper v6 - [`0014-whisperv6-notifications.patch`](./0014-whisperv6-notifications.patch) — adds Whisper v6 notifications (need to be reviewed and documented) - [`0015-whisperv6-envelopes-tracing.patch`](./0015-whisperv6-envelopes-tracing.patch) — adds Whisper v6 envelope tracing (need to be reviewed and documented) diff --git a/vendor/github.com/StackExchange/wmi/LICENSE b/vendor/github.com/StackExchange/wmi/LICENSE new file mode 100644 index 00000000000..ae80b67209e --- /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 00000000000..426d1a46b4a --- /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 00000000000..9765a53f74d --- /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 00000000000..a951b1258b0 --- /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/.appveyor.yml b/vendor/github.com/elastic/gosigar/.appveyor.yml new file mode 100644 index 00000000000..ff467086d2d --- /dev/null +++ b/vendor/github.com/elastic/gosigar/.appveyor.yml @@ -0,0 +1,84 @@ +# Version format +version: "{build}" + +# Operating system (build VM template) +os: Windows Server 2012 R2 + +# Environment variables +environment: + GOPATH: c:\gopath + GVM_GO_VERSION: 1.8.3 + GVM_DL: https://github.com/andrewkroh/gvm/releases/download/v0.0.1/gvm-windows-amd64.exe + +# Custom clone folder (variables are not expanded here). +clone_folder: c:\gopath\src\github.com\elastic\gosigar + +# Cache mingw install until appveyor.yml is modified. +cache: +- C:\ProgramData\chocolatey\bin -> .appveyor.yml +- C:\ProgramData\chocolatey\lib -> .appveyor.yml +- C:\Users\appveyor\.gvm -> .appveyor.yml +- C:\Windows\System32\gvm.exe -> .appveyor.yml +- C:\tools\mingw64 -> .appveyor.yml + +# Scripts that run after cloning repository +install: + - ps: >- + if(!(Test-Path "C:\Windows\System32\gvm.exe")) { + wget "$env:GVM_DL" -Outfile C:\Windows\System32\gvm.exe + } + - ps: gvm --format=powershell "$env:GVM_GO_VERSION" | Invoke-Expression + # AppVeyor installed mingw is 32-bit only so install 64-bit version. + - ps: >- + if(!(Test-Path "C:\tools\mingw64\bin\gcc.exe")) { + cinst mingw > mingw-install.txt + Push-AppveyorArtifact mingw-install.txt + } + - set PATH=C:\tools\mingw64\bin;%GOROOT%\bin;%PATH% + - set PATH=%GOPATH%\bin;%PATH% + - go version + - go env + - python --version + - go get github.com/elastic/beats/vendor/github.com/pierrre/gotestcover + +# To run your custom scripts instead of automatic MSBuild +build_script: + # Compile + - appveyor AddCompilationMessage "Starting Compile" + - cd c:\gopath\src\github.com\elastic\gosigar + - go get -v -t -d ./... + - go build + - go build -o examples/df/df.exe ./examples/df + - go build -o examples/free/free.exe ./examples/free + - go build -o examples/ps/ps.exe ./examples/ps + - go build -o examples/uptime/uptime.exe ./examples/uptime + - appveyor AddCompilationMessage "Compile Success" + +# To run your custom scripts instead of automatic tests +test_script: + # Unit tests + - ps: Add-AppveyorTest "Unit Tests" -Outcome Running + - mkdir build\coverage + - gotestcover -v -coverprofile=build/coverage/unit.cov github.com/elastic/gosigar/... + - ps: Update-AppveyorTest "Unit Tests" -Outcome Passed + - ps: Add-AppveyorTest "Running Examples" -Outcome Running + - .\examples\df\df.exe + - .\examples\free\free.exe + - .\examples\ps\ps.exe + - .\examples\uptime\uptime.exe + - ps: Update-AppveyorTest "Running Examples" -Outcome Passed + +after_test: + - go tool cover -html=build\coverage\unit.cov -o build\coverage\unit.html + - ps: Push-AppveyorArtifact build\coverage\unit.cov + - ps: Push-AppveyorArtifact build\coverage\unit.html + # Upload coverage report. + - "SET PATH=C:\\Python34;C:\\Python34\\Scripts;%PATH%" + - pip install codecov + - codecov -X gcov -f "build\coverage\unit.cov" + +# To disable deployment +deploy: off + +# Notifications should only be setup using the AppVeyor UI so that +# forks can be created without inheriting the settings. diff --git a/vendor/github.com/elastic/gosigar/.gitignore b/vendor/github.com/elastic/gosigar/.gitignore new file mode 100644 index 00000000000..6f145056f4b --- /dev/null +++ b/vendor/github.com/elastic/gosigar/.gitignore @@ -0,0 +1,41 @@ +# Directories +/.vagrant +/.idea +/build + +# Files +.DS_Store +/*.iml +*.h + +# Editor swap files +*.swp +*.swo +*.swn + +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so +*.exe +*.test +*.prof +*.pyc +*.swp + +# Example binaries +examples/df/df +examples/df/df.exe +examples/free/free +examples/free/free.exe +examples/ps/ps +examples/ps/ps.exe +examples/ss/ss +examples/ss/ss.exe +examples/uptime/uptime +examples/uptime/uptime.exe + +# Test Data +cgroup/testdata/* +!cgroup/testdata/*.zip + diff --git a/vendor/github.com/elastic/gosigar/.travis.yml b/vendor/github.com/elastic/gosigar/.travis.yml new file mode 100644 index 00000000000..30f58bfcf44 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/.travis.yml @@ -0,0 +1,36 @@ +language: go + +os: + - linux + - osx + +go: + - 1.8.3 + +env: + global: + - PROJ="github.com/elastic/gosigar" + +sudo: false + +before_install: + # Put project into proper GOPATH location (important for forks). + - mkdir -p $HOME/gopath/src/${PROJ} + - rsync -az ${TRAVIS_BUILD_DIR}/ $HOME/gopath/src/${PROJ}/ + - export TRAVIS_BUILD_DIR=$HOME/gopath/src/${PROJ} + - cd $HOME/gopath/src/${PROJ} + +install: + - go get -v -t -d ./... + - go get github.com/elastic/beats/vendor/github.com/pierrre/gotestcover + +script: + - gofmt -l . | read && echo "Code differs from gofmt's style. Run 'gofmt -w .'" 1>&2 && exit 1 || true + - go vet + - go build + - mkdir -p build/coverage + - gotestcover -v -coverprofile=build/coverage/unit.cov github.com/elastic/gosigar/... + - for i in $(ls examples); do go build -o examples/$i/$i ./examples/$i; ./examples/$i/$i; done + +after_success: + - bash <(curl -s https://codecov.io/bash) -f build/coverage/unit.cov diff --git a/vendor/github.com/elastic/gosigar/CHANGELOG.md b/vendor/github.com/elastic/gosigar/CHANGELOG.md new file mode 100644 index 00000000000..01d603784eb --- /dev/null +++ b/vendor/github.com/elastic/gosigar/CHANGELOG.md @@ -0,0 +1,92 @@ +# Change Log +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## [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 00000000000..11069edd790 --- /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 00000000000..fda553b5c38 --- /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 00000000000..2482620a834 --- /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 00000000000..6fd990c1416 --- /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 00000000000..76ade0fdb0e --- /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 00000000000..685aa6dedd1 --- /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 00000000000..f989f51608b --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sigar_darwin.go @@ -0,0 +1,494 @@ +// Copyright (c) 2012 VMware, Inc. + +package gosigar + +/* +#include +#include +#include +#include +#include +#include +#include +#include +#include +*/ +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 00000000000..ac56c9873c5 --- /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 00000000000..602b4a0aad9 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +*/ +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 00000000000..a956af604af --- /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 00000000000..cb1d3525b51 --- /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 00000000000..8e5e7856f69 --- /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 00000000000..4f1383a6ba9 --- /dev/null +++ b/vendor/github.com/elastic/gosigar/sigar_openbsd.go @@ -0,0 +1,418 @@ +// Copyright (c) 2016 Jasper Lievisse Adriaanse . + +// +build openbsd + +package gosigar + +/* +#include +#include +#include +#include +#include +#include +#include +#include +*/ +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 00000000000..0b858f1c0cf --- /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 00000000000..3f3a9f7ff2c --- /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 00000000000..bf93b02b247 --- /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 00000000000..0cdf928d16a --- /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 00000000000..dda57aa830a --- /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 00000000000..85de365e1a8 --- /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, ×[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 00000000000..28c78fd228e --- /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 00000000000..88df0febfa0 --- /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 00000000000..d0bca89c141 --- /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 00000000000..53fae4e3ba8 --- /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/ethereum/go-ethereum/.github/CONTRIBUTING.md b/vendor/github.com/ethereum/go-ethereum/.github/CONTRIBUTING.md index a332b815d09..9f2dbfcb805 100644 --- a/vendor/github.com/ethereum/go-ethereum/.github/CONTRIBUTING.md +++ b/vendor/github.com/ethereum/go-ethereum/.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/vendor/github.com/ethereum/go-ethereum/.gitignore b/vendor/github.com/ethereum/go-ethereum/.gitignore index 3a5acef9f3d..0763d8492cc 100644 --- a/vendor/github.com/ethereum/go-ethereum/.gitignore +++ b/vendor/github.com/ethereum/go-ethereum/.gitignore @@ -35,6 +35,7 @@ profile.cov .idea # dashboard +/dashboard/assets/flow-typed /dashboard/assets/node_modules /dashboard/assets/stats.json -/dashboard/assets/public/bundle.js +/dashboard/assets/bundle.js diff --git a/vendor/github.com/ethereum/go-ethereum/.mailmap b/vendor/github.com/ethereum/go-ethereum/.mailmap index d51c7b6093a..cc4b871a3cb 100644 --- a/vendor/github.com/ethereum/go-ethereum/.mailmap +++ b/vendor/github.com/ethereum/go-ethereum/.mailmap @@ -65,7 +65,8 @@ Enrique Fynn Vincent G -RJ Catalano +RJ Catalano +RJ Catalano Nchinda Nchinda @@ -109,3 +110,14 @@ Frank Wang Gary Rong Guillaume Nicolas + +Sorin Neacsu +Sorin Neacsu + +Valentin Wüstholz +Valentin Wüstholz + +Armin Braun + +Ernesto del Toro +Ernesto del Toro diff --git a/vendor/github.com/ethereum/go-ethereum/.travis.yml b/vendor/github.com/ethereum/go-ethereum/.travis.yml index 1bd69da347a..3941fa785b4 100644 --- a/vendor/github.com/ethereum/go-ethereum/.travis.yml +++ b/vendor/github.com/ethereum/go-ethereum/.travis.yml @@ -8,7 +8,6 @@ matrix: sudo: required go: 1.7.x script: - - sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install fuse - sudo modprobe fuse - sudo chmod 666 /dev/fuse - sudo chown root:$USER /etc/fuse.conf @@ -20,7 +19,6 @@ matrix: sudo: required go: 1.8.x script: - - sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install fuse - sudo modprobe fuse - sudo chmod 666 /dev/fuse - sudo chown root:$USER /etc/fuse.conf @@ -33,7 +31,6 @@ matrix: sudo: required go: 1.9.x script: - - sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install fuse - sudo modprobe fuse - sudo chmod 666 /dev/fuse - sudo chown root:$USER /etc/fuse.conf @@ -42,8 +39,8 @@ matrix: - os: osx go: 1.9.x - sudo: required 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 @@ -53,15 +50,12 @@ matrix: # This builder only tests code linters on latest version of Go - os: linux dist: trusty - sudo: required go: 1.9.x env: - lint + git: + submodules: false # avoid cloning ethereum/tests script: - - sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install fuse - - sudo modprobe fuse - - sudo chmod 666 /dev/fuse - - sudo chown root:$USER /etc/fuse.conf - go run build/ci.go lint # This builder does the Ubuntu PPA and Linux Azure uploads @@ -72,6 +66,8 @@ matrix: env: - ubuntu-ppa - azure-linux + git: + submodules: false # avoid cloning ethereum/tests addons: apt: packages: @@ -92,24 +88,25 @@ 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 - os: linux dist: trusty - sudo: required services: - docker go: 1.9.x env: - azure-linux-mips + git: + submodules: false # avoid cloning ethereum/tests script: - go run build/ci.go xgo --alltools -- --targets=linux/mips --ldflags '-extldflags "-static"' -v - for bin in build/bin/*-linux-mips; do mv -f "${bin}" "${bin/-linux-mips/}"; done @@ -146,6 +143,8 @@ matrix: env: - azure-android - maven-android + git: + submodules: false # avoid cloning ethereum/tests before_install: - curl https://storage.googleapis.com/golang/go1.9.2.linux-amd64.tar.gz | tar -xz - export PATH=`pwd`/go/bin:$PATH @@ -169,6 +168,8 @@ matrix: - azure-osx - azure-ios - cocoapods-ios + git: + submodules: false # avoid cloning ethereum/tests script: - go run build/ci.go install - go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -upload gethstore/builds @@ -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 @@ -193,15 +196,11 @@ matrix: go: 1.9.x env: - azure-purge + git: + submodules: false # avoid cloning ethereum/tests script: - go run build/ci.go purge -store gethstore/builds -days 14 -install: - - go get golang.org/x/tools/cmd/cover -script: - - go run build/ci.go install - - go run build/ci.go test -coverage - notifications: webhooks: urls: diff --git a/vendor/github.com/ethereum/go-ethereum/AUTHORS b/vendor/github.com/ethereum/go-ethereum/AUTHORS index faa19d281cf..bd44a3de553 100644 --- a/vendor/github.com/ethereum/go-ethereum/AUTHORS +++ b/vendor/github.com/ethereum/go-ethereum/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 +Airead +Alan Chen +Alejandro Isaza Ales Katona Alex Leverington +Alex Wu Alexandre Van de Sande +Ali Hajimirza +Anton Evangelatov +Arba Sasmoyo +Armani Ferrante +Armin Braun Aron Fischer Bas van Kervel Benjamin Brent +Benoit Verkindt +Bo +Bo Ye +Bob Glickstein Brian Schroeder Casey Detrio +Chase Wright Christoph Jentzsch Daniel A. Nagy +Daniel Sloof +Darrel Herbst +Dave Appleton Diego Siqueira +Dmitry Shulyak +Egon Elbre +Elias Naur Elliot Shepherd Enrique Fynn +Ernesto del Toro Ethan Buchman +Eugene Valeyev +Evangelos Pappas +Evgeny Danilenko <6655321@bk.ru> Fabian Vogelsteller +Fabio Barone Fabio Berger +FaceHo Felix Lange +Fiisio Frank Wang +Furkan KAMACI Gary Rong +George Ornbo Gregg Dourgarian +Guillaume Ballet Guillaume Nicolas Gustav Simonsson Hao Bryan Cheng Henning Diedrich Isidoro Ghezzi +Ivan Daniluk Jae Kwon Jamie Pitts +Janoš Guljaš Jason Carver +Jay Guo Jeff R. Allen Jeffrey Wilcke Jens Agerberg +Jia Chenhui +Jim McDonald +Joel Burget Jonathan Brown Joseph Chow Justin Clark-Casey Justin Drake Kenji Siu Kobi Gurkan +Konrad Feldmeier +Kurkó Mihály +Kyuntae Ethan Kim Lefteris Karapetsas Leif Jurvetson +Leo Shklovskii Lewis Marshall +Lio李欧 Louis Holbrook Luca Zeug +Magicking Maran Hidskes Marek Kotewicz +Mark Martin Holst Swende Matthew Di Ferrante Matthew Wampler-Doty +Maximilian Meister Micah Zoltu +Michael Ruminer +Miguel Mota +Miya Chen Nchinda Nchinda Nick Dodson Nick Johnson +Nicolas Guillaume +Noman +Oli Bye +Paul Litvak Paulo L F Casaretto +Paweł Bylica Peter Pratscher +Petr Mikusek Péter Szilágyi -RJ Catalano +RJ Catalano Ramesh Nair Ricardo Catalinas Jiménez +Ricardo Domingos +Richard Hart +Rob +Robert Zaremba +Russ Cox Rémy Roy +S. Matthew English Shintaro Kaneko +Sorin Neacsu Stein Dekker +Steve Waldman Steven Roose Taylor Gerring Thomas Bocek +Ti Zhou Tosh Camille -Valentin Wüstholz +Valentin Wüstholz Victor Farazdagi Victor Tran Viktor Trón Ville Sundell Vincent G Vitalik Buterin +Vitaly V Vivek Anand Vlad Gluhovsky Yohann Léon Yoichi Hirai +Yondon Fu +Zach Zahoor Mohamed +Zoe Nolan Zsolt Felföldi +am2rican5 +ayeowch +b00ris +bailantaotao +baizhenxuan +bloonfield +changhong +evgk +ferhat elmas holisticode +jtakalai ken10100147 ligi +mark.lin +necaremus +njupt-moon <1015041018@njupt.edu.cn> +nkbai +rhaps107 +slumber1122 +sunxiaojun2014 +terasum +tsarpaul xiekeyang +yoza ΞTHΞЯSPHΞЯΞ <{viktor.tron,nagydani,zsfelfoldi}@gmail.com> Максим Чусовлянов diff --git a/vendor/github.com/ethereum/go-ethereum/Makefile b/vendor/github.com/ethereum/go-ethereum/Makefile index 2cfd1110ec8..3922d6015bb 100644 --- a/vendor/github.com/ethereum/go-ethereum/Makefile +++ b/vendor/github.com/ethereum/go-ethereum/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/vendor/github.com/ethereum/go-ethereum/README.md b/vendor/github.com/ethereum/go-ethereum/README.md index 61e36afec4b..527ea048a30 100644 --- a/vendor/github.com/ethereum/go-ethereum/README.md +++ b/vendor/github.com/ethereum/go-ethereum/README.md @@ -56,16 +56,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 +78,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 +99,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 +130,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/vendor/github.com/ethereum/go-ethereum/VERSION b/vendor/github.com/ethereum/go-ethereum/VERSION index 661e7aeadf3..27f9cd322bb 100644 --- a/vendor/github.com/ethereum/go-ethereum/VERSION +++ b/vendor/github.com/ethereum/go-ethereum/VERSION @@ -1 +1 @@ -1.7.3 +1.8.0 diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go index 205dc300b0e..abcb403db27 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/abi.go @@ -17,6 +17,7 @@ package abi import ( + "bytes" "encoding/json" "fmt" "io" @@ -50,57 +51,52 @@ func JSON(reader io.Reader) (ABI, error) { // methods string signature. (signature = baz(uint32,string32)) func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) { // Fetch the ABI of the requested method - var method Method - if name == "" { - method = abi.Constructor - } else { - m, exist := abi.Methods[name] - if !exist { - return nil, fmt.Errorf("method '%s' not found", name) + // constructor + arguments, err := abi.Constructor.Inputs.Pack(args...) + if err != nil { + return nil, err } - method = m + return arguments, nil + } - arguments, err := method.pack(args...) + method, exist := abi.Methods[name] + if !exist { + return nil, fmt.Errorf("method '%s' not found", name) + } + + arguments, err := method.Inputs.Pack(args...) if err != nil { return nil, err } // Pack up the method ID too if not a constructor and return - if name == "" { - return arguments, nil - } return append(method.Id(), arguments...), nil } // Unpack output in v according to the abi specification func (abi ABI) Unpack(v interface{}, name string, output []byte) (err error) { - if err = bytesAreProper(output); err != nil { - return err + if len(output) == 0 { + return fmt.Errorf("abi: unmarshalling empty output") } // since there can't be naming collisions with contracts and events, // we need to decide whether we're calling a method or an event - var unpack unpacker if method, ok := abi.Methods[name]; ok { - unpack = method + if len(output)%32 != 0 { + return fmt.Errorf("abi: improperly formatted output") + } + return method.Outputs.Unpack(v, output) } else if event, ok := abi.Events[name]; ok { - unpack = event - } else { - return fmt.Errorf("abi: could not locate named method or event.") - } - - // requires a struct to unpack into for a tuple return... - if unpack.isTupleReturn() { - return unpack.tupleUnpack(v, output) + return event.Inputs.Unpack(v, output) } - return unpack.singleUnpack(v, output) + return fmt.Errorf("abi: could not locate named method or event") } +// UnmarshalJSON implements json.Unmarshaler interface func (abi *ABI) UnmarshalJSON(data []byte) error { var fields []struct { Type string Name string Constant bool - Indexed bool Anonymous bool Inputs []Argument Outputs []Argument @@ -137,3 +133,14 @@ func (abi *ABI) UnmarshalJSON(data []byte) error { return nil } + +// MethodById looks up a method by the 4-byte id +// returns nil if none found +func (abi *ABI) MethodById(sigdata []byte) *Method { + for _, method := range abi.Methods { + if bytes.Equal(method.Id(), sigdata[:4]) { + return &method + } + } + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go index 4691318ce72..04ca6150ad3 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/argument.go @@ -19,6 +19,8 @@ package abi import ( "encoding/json" "fmt" + "reflect" + "strings" ) // Argument holds the name of the argument and the corresponding type. @@ -29,7 +31,10 @@ type Argument struct { Indexed bool // indexed is only used by events } -func (a *Argument) UnmarshalJSON(data []byte) error { +type Arguments []Argument + +// UnmarshalJSON implements json.Unmarshaler interface +func (argument *Argument) UnmarshalJSON(data []byte) error { var extarg struct { Name string Type string @@ -40,12 +45,206 @@ func (a *Argument) UnmarshalJSON(data []byte) error { return fmt.Errorf("argument json err: %v", err) } - a.Type, err = NewType(extarg.Type) + argument.Type, err = NewType(extarg.Type) if err != nil { return err } - a.Name = extarg.Name - a.Indexed = extarg.Indexed + argument.Name = extarg.Name + argument.Indexed = extarg.Indexed + + return nil +} + +// LengthNonIndexed returns the number of arguments when not counting 'indexed' ones. Only events +// can ever have 'indexed' arguments, it should always be false on arguments for method input/output +func (arguments Arguments) LengthNonIndexed() int { + out := 0 + for _, arg := range arguments { + if !arg.Indexed { + out++ + } + } + return out +} + +// isTuple returns true for non-atomic constructs, like (uint,uint) or uint[] +func (arguments Arguments) isTuple() bool { + return len(arguments) > 1 +} + +// 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() { + return fmt.Errorf("abi: Unpack(non-pointer %T)", v) + } + + var ( + value = valueOf.Elem() + typ = value.Type() + kind = value.Kind() + ) + + if err := requireUnpackKind(value, typ, kind, arguments); err != nil { + return err + } + // 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 + } + } + // `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 + } + + reflectValue := reflect.ValueOf(marshalledValue) + + switch kind { + case reflect.Struct: + name := capitalise(arg.Name) + for j := 0; j < typ.NumField(); j++ { + // TODO read tags: `abi:"fieldName"` + if typ.Field(j).Name == name { + if err := set(value.Field(j), reflectValue, arg); err != nil { + return err + } + } + } + case reflect.Slice, reflect.Array: + if value.Len() < i { + return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len()) + } + v := value.Index(i) + if err := requireAssignable(v, reflectValue); err != nil { + return err + } + if err := set(v.Elem(), reflectValue, arg); err != nil { + return err + } + default: + return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", typ) + } + } return nil } + +// 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.") + } + + value := valueOf.Elem() + + marshalledValue, err := toGoType(0, arg.Type, output) + if err != nil { + return err + } + return set(value, reflect.ValueOf(marshalledValue), arg) +} + +// Unpack 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 + + // input offset is the bytes offset for packed output + inputOffset := 0 + for _, abiArg := range abiArgs { + if abiArg.Type.T == ArrayTy { + inputOffset += 32 * abiArg.Type.Size + } else { + inputOffset += 32 + } + } + + var ret []byte + for i, a := range args { + input := abiArgs[i] + // pack the input + packed, err := input.Type.pack(reflect.ValueOf(a)) + if err != nil { + return nil, err + } + + // check for a slice type (string, bytes, slice) + if input.Type.requiresLengthPrefix() { + // calculate the offset + offset := inputOffset + len(variableInput) + // set the offset + ret = append(ret, packNum(reflect.ValueOf(offset))...) + // Append the packed output to the variable input. The variable input + // will be appended at the end of the input. + variableInput = append(variableInput, packed...) + } else { + // append the packed value to the input + ret = append(ret, packed...) + } + } + // append the variable input at the end of the packed input + ret = append(ret, variableInput...) + + 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/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backend.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backend.go index 25b61928e12..ca60cc1b432 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backend.go +++ b/vendor/github.com/ethereum/go-ethereum/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/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go index 09288d401ec..bd342a8cb99 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/backends/simulated.go +++ b/vendor/github.com/ethereum/go-ethereum/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 } @@ -89,9 +101,11 @@ func (b *SimulatedBackend) Rollback() { } func (b *SimulatedBackend) rollback() { - blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), b.database, 1, func(int, *core.BlockGen) {}) + 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. @@ -291,29 +305,95 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa panic(fmt.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce)) } - blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) { + blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) { for _, tx := range b.pendingBlock.Transactions() { block.AddTx(tx) } 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() - blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) { + blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) { for _, tx := range b.pendingBlock.Transactions() { block.AddTx(tx) } 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/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/base.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/base.go index b40bd65e802..83ad1c8ae7f 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/base.go +++ b/vendor/github.com/ethereum/go-ethereum/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/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/bind.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/bind.go index f5875808841..e31b454812e 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/bind.go +++ b/vendor/github.com/ethereum/go-ethereum/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 { @@ -129,11 +154,11 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La return string(code), nil } // For all others just return as is for now - return string(buffer.Bytes()), nil + return buffer.String(), nil } // 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/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/template.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/template.go index d07610e7c24..7202ee67a10 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/template.go +++ b/vendor/github.com/ethereum/go-ethereum/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/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/topics.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/bind/topics.go new file mode 100644 index 00000000000..600dfcda973 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/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 . + +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/vendor/github.com/ethereum/go-ethereum/accounts/abi/event.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/event.go index 44ed7b8df25..595f169f3a9 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/event.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/event.go @@ -18,7 +18,6 @@ package abi import ( "fmt" - "reflect" "strings" "github.com/ethereum/go-ethereum/common" @@ -31,7 +30,18 @@ import ( type Event struct { Name string Anonymous bool - Inputs []Argument + 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 @@ -45,93 +55,3 @@ func (e Event) Id() common.Hash { } return common.BytesToHash(crypto.Keccak256([]byte(fmt.Sprintf("%v(%v)", e.Name, strings.Join(types, ","))))) } - -// unpacks an event return tuple into a struct of corresponding go types -// -// Unpacking can be done into a struct or a slice/array. -func (e Event) tupleUnpack(v interface{}, output []byte) error { - // make sure the passed value is a pointer - valueOf := reflect.ValueOf(v) - if reflect.Ptr != valueOf.Kind() { - return fmt.Errorf("abi: Unpack(non-pointer %T)", v) - } - - var ( - value = valueOf.Elem() - typ = value.Type() - ) - - if value.Kind() != reflect.Struct { - return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ) - } - - j := 0 - for i := 0; i < len(e.Inputs); i++ { - input := e.Inputs[i] - if input.Indexed { - // can't read, continue - continue - } else if input.Type.T == ArrayTy { - // need to move this up because they read sequentially - j += input.Type.Size - } - marshalledValue, err := toGoType((i+j)*32, input.Type, output) - if err != nil { - return err - } - reflectValue := reflect.ValueOf(marshalledValue) - - switch value.Kind() { - case reflect.Struct: - for j := 0; j < typ.NumField(); j++ { - field := typ.Field(j) - // TODO read tags: `abi:"fieldName"` - if field.Name == strings.ToUpper(e.Inputs[i].Name[:1])+e.Inputs[i].Name[1:] { - if err := set(value.Field(j), reflectValue, e.Inputs[i]); err != nil { - return err - } - } - } - case reflect.Slice, reflect.Array: - if value.Len() < i { - return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(e.Inputs), value.Len()) - } - v := value.Index(i) - if v.Kind() != reflect.Ptr && v.Kind() != reflect.Interface { - return fmt.Errorf("abi: cannot unmarshal %v in to %v", v.Type(), reflectValue.Type()) - } - reflectValue := reflect.ValueOf(marshalledValue) - if err := set(v.Elem(), reflectValue, e.Inputs[i]); err != nil { - return err - } - default: - return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ) - } - } - return nil -} - -func (e Event) isTupleReturn() bool { return len(e.Inputs) > 1 } - -func (e Event) singleUnpack(v interface{}, output []byte) error { - // make sure the passed value is a pointer - valueOf := reflect.ValueOf(v) - if reflect.Ptr != valueOf.Kind() { - return fmt.Errorf("abi: Unpack(non-pointer %T)", v) - } - - if e.Inputs[0].Indexed { - return fmt.Errorf("abi: attempting to unpack indexed variable into element.") - } - - value := valueOf.Elem() - - marshalledValue, err := toGoType(0, e.Inputs[0].Type, output) - if err != nil { - return err - } - if err := set(value, reflect.ValueOf(marshalledValue), e.Inputs[0]); err != nil { - return err - } - return nil -} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/method.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/method.go index d8838e9ed68..f434ffdbef6 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/method.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/method.go @@ -18,13 +18,12 @@ package abi import ( "fmt" - "reflect" "strings" "github.com/ethereum/go-ethereum/crypto" ) -// Callable method given a `Name` and whether the method is a constant. +// Method represents a callable given a `Name` and whether the method is a constant. // If the method is `Const` no transaction needs to be created for this // particular Method call. It can easily be simulated using a local VM. // For example a `Balance()` method only needs to retrieve something @@ -35,125 +34,8 @@ import ( type Method struct { Name string Const bool - Inputs []Argument - Outputs []Argument -} - -func (method Method) pack(args ...interface{}) ([]byte, error) { - // Make sure arguments match up and pack them - if len(args) != len(method.Inputs) { - return nil, fmt.Errorf("argument count mismatch: %d for %d", len(args), len(method.Inputs)) - } - // variable input is the output appended at the end of packed - // output. This is used for strings and bytes types input. - var variableInput []byte - - var ret []byte - for i, a := range args { - input := method.Inputs[i] - // pack the input - packed, err := input.Type.pack(reflect.ValueOf(a)) - if err != nil { - return nil, fmt.Errorf("`%s` %v", method.Name, err) - } - - // check for a slice type (string, bytes, slice) - if input.Type.requiresLengthPrefix() { - // calculate the offset - offset := len(method.Inputs)*32 + len(variableInput) - // set the offset - ret = append(ret, packNum(reflect.ValueOf(offset))...) - // Append the packed output to the variable input. The variable input - // will be appended at the end of the input. - variableInput = append(variableInput, packed...) - } else { - // append the packed value to the input - ret = append(ret, packed...) - } - } - // append the variable input at the end of the packed input - ret = append(ret, variableInput...) - - return ret, nil -} - -// unpacks a method return tuple into a struct of corresponding go types -// -// Unpacking can be done into a struct or a slice/array. -func (method Method) tupleUnpack(v interface{}, output []byte) error { - // make sure the passed value is a pointer - valueOf := reflect.ValueOf(v) - if reflect.Ptr != valueOf.Kind() { - return fmt.Errorf("abi: Unpack(non-pointer %T)", v) - } - - var ( - value = valueOf.Elem() - typ = value.Type() - ) - - j := 0 - for i := 0; i < len(method.Outputs); i++ { - toUnpack := method.Outputs[i] - if toUnpack.Type.T == ArrayTy { - // need to move this up because they read sequentially - j += toUnpack.Type.Size - } - marshalledValue, err := toGoType((i+j)*32, toUnpack.Type, output) - if err != nil { - return err - } - reflectValue := reflect.ValueOf(marshalledValue) - - switch value.Kind() { - case reflect.Struct: - for j := 0; j < typ.NumField(); j++ { - field := typ.Field(j) - // TODO read tags: `abi:"fieldName"` - if field.Name == strings.ToUpper(method.Outputs[i].Name[:1])+method.Outputs[i].Name[1:] { - if err := set(value.Field(j), reflectValue, method.Outputs[i]); err != nil { - return err - } - } - } - case reflect.Slice, reflect.Array: - if value.Len() < i { - return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(method.Outputs), value.Len()) - } - v := value.Index(i) - if v.Kind() != reflect.Ptr && v.Kind() != reflect.Interface { - return fmt.Errorf("abi: cannot unmarshal %v in to %v", v.Type(), reflectValue.Type()) - } - reflectValue := reflect.ValueOf(marshalledValue) - if err := set(v.Elem(), reflectValue, method.Outputs[i]); err != nil { - return err - } - default: - return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ) - } - } - return nil -} - -func (method Method) isTupleReturn() bool { return len(method.Outputs) > 1 } - -func (method Method) singleUnpack(v interface{}, output []byte) error { - // make sure the passed value is a pointer - valueOf := reflect.ValueOf(v) - if reflect.Ptr != valueOf.Kind() { - return fmt.Errorf("abi: Unpack(non-pointer %T)", v) - } - - value := valueOf.Elem() - - marshalledValue, err := toGoType(0, method.Outputs[0].Type, output) - if err != nil { - return err - } - if err := set(value, reflect.ValueOf(marshalledValue), method.Outputs[0]); err != nil { - return err - } - return nil + Inputs Arguments + Outputs Arguments } // Sig returns the methods string signature according to the ABI spec. @@ -163,35 +45,35 @@ func (method Method) singleUnpack(v interface{}, output []byte) error { // function foo(uint32 a, int b) = "foo(uint32,int256)" // // Please note that "int" is substitute for its canonical representation "int256" -func (m Method) Sig() string { - types := make([]string, len(m.Inputs)) +func (method Method) Sig() string { + types := make([]string, len(method.Inputs)) i := 0 - for _, input := range m.Inputs { + for _, input := range method.Inputs { types[i] = input.Type.String() i++ } - return fmt.Sprintf("%v(%v)", m.Name, strings.Join(types, ",")) + return fmt.Sprintf("%v(%v)", method.Name, strings.Join(types, ",")) } -func (m Method) String() string { - inputs := make([]string, len(m.Inputs)) - for i, input := range m.Inputs { +func (method Method) String() string { + inputs := make([]string, len(method.Inputs)) + for i, input := range method.Inputs { inputs[i] = fmt.Sprintf("%v %v", input.Name, input.Type) } - outputs := make([]string, len(m.Outputs)) - for i, output := range m.Outputs { + outputs := make([]string, len(method.Outputs)) + for i, output := range method.Outputs { if len(output.Name) > 0 { outputs[i] = fmt.Sprintf("%v ", output.Name) } outputs[i] += output.Type.String() } constant := "" - if m.Const { + if method.Const { constant = "constant " } - return fmt.Sprintf("function %v(%v) %sreturns(%v)", m.Name, strings.Join(inputs, ", "), constant, strings.Join(outputs, ", ")) + return fmt.Sprintf("function %v(%v) %sreturns(%v)", method.Name, strings.Join(inputs, ", "), constant, strings.Join(outputs, ", ")) } -func (m Method) Id() []byte { - return crypto.Keccak256([]byte(m.Sig()))[:4] +func (method Method) Id() []byte { + return crypto.Keccak256([]byte(method.Sig()))[:4] } diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/pack.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/pack.go index 072e805368d..36c58265bd4 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/pack.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/pack.go @@ -48,9 +48,8 @@ func packElement(t Type, reflectValue reflect.Value) []byte { case BoolTy: if reflectValue.Bool() { return math.PaddedBigBytes(common.Big1, 32) - } else { - return math.PaddedBigBytes(common.Big0, 32) } + return math.PaddedBigBytes(common.Big0, 32) case BytesTy: if reflectValue.Kind() == reflect.Array { reflectValue = mustArrayToByteSlice(reflectValue) diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/reflect.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/reflect.go index e953b77c184..7a9cdacd54a 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/reflect.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/reflect.go @@ -85,3 +85,28 @@ func set(dst, src reflect.Value, output Argument) error { } return nil } + +// requireAssignable assures that `dest` is a pointer and it's not an interface. +func requireAssignable(dst, src reflect.Value) error { + if dst.Kind() != reflect.Ptr && dst.Kind() != reflect.Interface { + return fmt.Errorf("abi: cannot unmarshal %v into %v", src.Type(), dst.Type()) + } + return nil +} + +// requireUnpackKind verifies preconditions for unpacking `args` into `kind` +func requireUnpackKind(v reflect.Value, t reflect.Type, k reflect.Kind, + args Arguments) error { + + switch k { + case reflect.Struct: + case reflect.Slice, reflect.Array: + if minLen := args.LengthNonIndexed(); v.Len() < minLen { + return fmt.Errorf("abi: insufficient number of elements in the list/array for unpack, want %d, got %d", + minLen, v.Len()) + } + default: + return fmt.Errorf("abi: cannot unmarshal tuple into %v", t) + } + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go index fba10b96d2f..a1f13ffa29f 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/abi/type.go @@ -24,6 +24,7 @@ import ( "strings" ) +// Type enumerator const ( IntTy byte = iota UintTy @@ -100,68 +101,65 @@ func NewType(t string) (typ Type, err error) { return Type{}, fmt.Errorf("invalid formatting of array type") } return typ, err + } + // parse the type and size of the abi-type. + parsedType := typeRegex.FindAllStringSubmatch(t, -1)[0] + // varSize is the size of the variable + var varSize int + if len(parsedType[3]) > 0 { + var err error + varSize, err = strconv.Atoi(parsedType[2]) + if err != nil { + return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err) + } } else { - // parse the type and size of the abi-type. - parsedType := typeRegex.FindAllStringSubmatch(t, -1)[0] - // varSize is the size of the variable - var varSize int - if len(parsedType[3]) > 0 { - var err error - varSize, err = strconv.Atoi(parsedType[2]) - if err != nil { - return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err) - } - } else { - if parsedType[0] == "uint" || parsedType[0] == "int" { - // this should fail because it means that there's something wrong with - // the abi type (the compiler should always format it to the size...always) - return Type{}, fmt.Errorf("unsupported arg type: %s", t) - } + if parsedType[0] == "uint" || parsedType[0] == "int" { + // this should fail because it means that there's something wrong with + // the abi type (the compiler should always format it to the size...always) + return Type{}, fmt.Errorf("unsupported arg type: %s", t) } - // varType is the parsed abi type - varType := parsedType[1] - - switch varType { - case "int": - typ.Kind, typ.Type = reflectIntKindAndType(false, varSize) - typ.Size = varSize - typ.T = IntTy - case "uint": - typ.Kind, typ.Type = reflectIntKindAndType(true, varSize) - typ.Size = varSize - typ.T = UintTy - case "bool": - typ.Kind = reflect.Bool - typ.T = BoolTy - typ.Type = reflect.TypeOf(bool(false)) - case "address": - typ.Kind = reflect.Array - typ.Type = address_t - typ.Size = 20 - typ.T = AddressTy - case "string": - typ.Kind = reflect.String - typ.Type = reflect.TypeOf("") - typ.T = StringTy - case "bytes": - if varSize == 0 { - typ.T = BytesTy - typ.Kind = reflect.Slice - typ.Type = reflect.SliceOf(reflect.TypeOf(byte(0))) - } else { - typ.T = FixedBytesTy - typ.Kind = reflect.Array - typ.Size = varSize - typ.Type = reflect.ArrayOf(varSize, reflect.TypeOf(byte(0))) - } - case "function": + } + // varType is the parsed abi type + switch varType := parsedType[1]; varType { + case "int": + typ.Kind, typ.Type = reflectIntKindAndType(false, varSize) + typ.Size = varSize + typ.T = IntTy + case "uint": + typ.Kind, typ.Type = reflectIntKindAndType(true, varSize) + typ.Size = varSize + typ.T = UintTy + case "bool": + typ.Kind = reflect.Bool + typ.T = BoolTy + typ.Type = reflect.TypeOf(bool(false)) + case "address": + typ.Kind = reflect.Array + typ.Type = address_t + typ.Size = 20 + typ.T = AddressTy + case "string": + typ.Kind = reflect.String + typ.Type = reflect.TypeOf("") + typ.T = StringTy + case "bytes": + if varSize == 0 { + typ.T = BytesTy + typ.Kind = reflect.Slice + typ.Type = reflect.SliceOf(reflect.TypeOf(byte(0))) + } else { + typ.T = FixedBytesTy typ.Kind = reflect.Array - typ.T = FunctionTy - typ.Size = 24 - typ.Type = reflect.ArrayOf(24, reflect.TypeOf(byte(0))) - default: - return Type{}, fmt.Errorf("unsupported arg type: %s", t) + typ.Size = varSize + typ.Type = reflect.ArrayOf(varSize, reflect.TypeOf(byte(0))) } + case "function": + typ.Kind = reflect.Array + typ.T = FunctionTy + typ.Size = 24 + typ.Type = reflect.ArrayOf(24, reflect.TypeOf(byte(0))) + default: + return Type{}, fmt.Errorf("unsupported arg type: %s", t) } return diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/abi/unpack.go b/vendor/github.com/ethereum/go-ethereum/accounts/abi/unpack.go index 57732797b6e..33424566185 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/abi/unpack.go +++ b/vendor/github.com/ethereum/go-ethereum/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 @@ -25,15 +25,6 @@ import ( "github.com/ethereum/go-ethereum/common" ) -// unpacker is a utility interface that enables us to have -// abstraction between events and methods and also to properly -// "unpack" them; e.g. events use Inputs, methods use Outputs. -type unpacker interface { - tupleUnpack(v interface{}, output []byte) error - singleUnpack(v interface{}, output []byte) error - isTupleReturn() bool -} - // reads the integer based on its kind func readInteger(kind reflect.Kind, b []byte) interface{} { switch kind { @@ -79,7 +70,7 @@ func readBool(word []byte) (bool, error) { // This enforces that standard by always presenting it as a 24-array (address + sig = 24 bytes) func readFunctionType(t Type, word []byte) (funcTy [24]byte, err error) { if t.T != FunctionTy { - return [24]byte{}, fmt.Errorf("abi: invalid type in call to make function type byte array.") + return [24]byte{}, fmt.Errorf("abi: invalid type in call to make function type byte array") } if garbage := binary.BigEndian.Uint64(word[24:32]); garbage != 0 { err = fmt.Errorf("abi: got improperly encoded function type, got %v", word) @@ -92,7 +83,7 @@ func readFunctionType(t Type, word []byte) (funcTy [24]byte, err error) { // through reflection, creates a fixed array to be read from func readFixedBytes(t Type, word []byte) (interface{}, error) { if t.T != FixedBytesTy { - return nil, fmt.Errorf("abi: invalid type in call to make fixed byte array.") + return nil, fmt.Errorf("abi: invalid type in call to make fixed byte array") } // convert array := reflect.New(t.Type).Elem() @@ -203,14 +194,3 @@ func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err //fmt.Printf("LENGTH PREFIX INFO: \nsize: %v\noffset: %v\nstart: %v\n", length, offset, start) return } - -// checks for proper formatting of byte output -func bytesAreProper(output []byte) error { - if len(output) == 0 { - return fmt.Errorf("abi: unmarshalling empty output") - } else if len(output)%32 != 0 { - return fmt.Errorf("abi: improperly formatted output") - } else { - return nil - } -} diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/errors.go b/vendor/github.com/ethereum/go-ethereum/accounts/errors.go index 64da8821c80..40b21ed179c 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/errors.go +++ b/vendor/github.com/ethereum/go-ethereum/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/vendor/github.com/ethereum/go-ethereum/accounts/keystore/presale.go b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/presale.go index ed900ad085e..1554294e14e 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/keystore/presale.go +++ b/vendor/github.com/ethereum/go-ethereum/accounts/keystore/presale.go @@ -58,6 +58,9 @@ func decryptPreSaleKey(fileContent []byte, password string) (key *Key, err error if err != nil { return nil, errors.New("invalid hex in encSeed") } + if len(encSeedBytes) < 16 { + return nil, errors.New("invalid encSeed, too short") + } iv := encSeedBytes[:16] cipherText := encSeedBytes[16:] /* diff --git a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/messages.proto b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/messages.proto index 178956457eb..8cb9c8cc25c 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/messages.proto +++ b/vendor/github.com/ethereum/go-ethereum/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/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/trezor.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/trezor.go index 487aeb5f819..8ae9e726e46 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/trezor.go +++ b/vendor/github.com/ethereum/go-ethereum/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/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/types.proto b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/types.proto index 3a358a584dc..acbe79e3ffd 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor/types.proto +++ b/vendor/github.com/ethereum/go-ethereum/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/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor.go b/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor.go index 159cb2ea970..b84a955992f 100644 --- a/vendor/github.com/ethereum/go-ethereum/accounts/usbwallet/trezor.go +++ b/vendor/github.com/ethereum/go-ethereum/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/vendor/github.com/ethereum/go-ethereum/appveyor.yml b/vendor/github.com/ethereum/go-ethereum/appveyor.yml index 78b11fa9d66..99029f553d2 100644 --- a/vendor/github.com/ethereum/go-ethereum/appveyor.yml +++ b/vendor/github.com/ethereum/go-ethereum/appveyor.yml @@ -23,8 +23,8 @@ environment: install: - git submodule update --init - rmdir C:\go /s /q - - appveyor DownloadFile https://storage.googleapis.com/golang/go1.9.windows-%GETH_ARCH%.zip - - 7z x go1.9.windows-%GETH_ARCH%.zip -y -oC:\ > NUL + - appveyor DownloadFile https://storage.googleapis.com/golang/go1.9.2.windows-%GETH_ARCH%.zip + - 7z x go1.9.2.windows-%GETH_ARCH%.zip -y -oC:\ > NUL - go version - gcc --version diff --git a/vendor/github.com/ethereum/go-ethereum/bmt/bmt.go b/vendor/github.com/ethereum/go-ethereum/bmt/bmt.go index d62365bb1f5..4b65b1d94aa 100644 --- a/vendor/github.com/ethereum/go-ethereum/bmt/bmt.go +++ b/vendor/github.com/ethereum/go-ethereum/bmt/bmt.go @@ -260,8 +260,7 @@ func NewTree(hasher BaseHasher, segmentSize, segmentCount int) *Tree { for d := 1; d <= depth(segmentCount); d++ { nodes := make([]*Node, count) for i := 0; i < len(nodes); i++ { - var parent *Node - parent = prevlevel[i/2] + parent := prevlevel[i/2] t := NewNode(level, i, parent) nodes[i] = t } diff --git a/vendor/github.com/ethereum/go-ethereum/build/ci.go b/vendor/github.com/ethereum/go-ethereum/build/ci.go index 0c825ef31e6..544483c42ca 100644 --- a/vendor/github.com/ethereum/go-ethereum/build/ci.go +++ b/vendor/github.com/ethereum/go-ethereum/build/ci.go @@ -19,11 +19,11 @@ /* The ci command is called from Continuous Integration scripts. -Usage: go run ci.go +Usage: go run build/ci.go 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{"./..."} @@ -199,7 +207,7 @@ func doInstall(cmdline []string) { build.MustRun(goinstall) return } - // If we are cross compiling to ARMv5 ARMv6 or ARMv7, clean any prvious builds + // If we are cross compiling to ARMv5 ARMv6 or ARMv7, clean any previous builds if *arch == "arm" { os.RemoveAll(filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_arm")) for _, path := range filepath.SplitList(build.GOPATH()) { @@ -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 @@ -319,17 +333,25 @@ func doLint(cmdline []string) { packages = flag.CommandLine.Args() } // Get metalinter and install all supported linters - build.MustRun(goTool("get", "gopkg.in/alecthomas/gometalinter.v1")) - build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v1"), "--install") + build.MustRun(goTool("get", "gopkg.in/alecthomas/gometalinter.v2")) + build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v2"), "--install") // Run fast linters batched together - configs := []string{"--vendor", "--disable-all", "--enable=vet", "--enable=gofmt", "--enable=misspell"} - build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v1"), append(configs, packages...)...) + configs := []string{ + "--vendor", + "--disable-all", + "--enable=vet", + "--enable=gofmt", + "--enable=misspell", + "--enable=goconst", + "--min-occurrences=6", // for goconst + } + build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v2"), append(configs, packages...)...) // Run slow linters one by one - for _, linter := range []string{"unconvert"} { + for _, linter := range []string{"unconvert", "gosimple"} { configs = []string{"--vendor", "--deadline=10m", "--disable-all", "--enable=" + linter} - build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v1"), append(configs, packages...)...) + build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v2"), append(configs, packages...)...) } } diff --git a/vendor/github.com/ethereum/go-ethereum/build/update-license.go b/vendor/github.com/ethereum/go-ethereum/build/update-license.go index 3d69598b754..22e40334280 100644 --- a/vendor/github.com/ethereum/go-ethereum/build/update-license.go +++ b/vendor/github.com/ethereum/go-ethereum/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/vendor/github.com/ethereum/go-ethereum/cmd/bootnode/main.go b/vendor/github.com/ethereum/go-ethereum/cmd/bootnode/main.go index e1734d89ac8..2e93cc04d22 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/bootnode/main.go +++ b/vendor/github.com/ethereum/go-ethereum/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/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/README.md b/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/README.md new file mode 100644 index 00000000000..cf72ba43d7d --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/README.md @@ -0,0 +1,41 @@ +ethkey +====== + +ethkey is a simple command-line tool for working with Ethereum keyfiles. + + +# Usage + +### `ethkey generate` + +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. + + +### `ethkey inspect ` + +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! + + +### `ethkey sign ` + +Sign the message with a keyfile. +It is possible to refer to a file containing the message. + + +### `ethkey verify
` + +Verify the signature of the message. +It is possible to refer to a file containing the message. + + +## Passphrases + +For every command that uses a keyfile, you will be prompted to provide the +passphrase for decrypting the keyfile. To avoid this message, it is possible +to pass the passphrase by using the `--passphrase` flag pointing to a file that +contains the passphrase. diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/generate.go b/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/generate.go new file mode 100644 index 00000000000..6d57d17fb4e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/generate.go @@ -0,0 +1,118 @@ +// 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 . + +package main + +import ( + "crypto/ecdsa" + "fmt" + "io/ioutil" + "os" + "path/filepath" + + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/crypto" + "github.com/pborman/uuid" + "gopkg.in/urfave/cli.v1" +) + +type outputGenerate struct { + Address string + AddressEIP55 string +} + +var commandGenerate = cli.Command{ + Name: "generate", + Usage: "generate new keyfile", + ArgsUsage: "[ ]", + Description: ` +Generate a new keyfile. + +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: "file containing a raw private key to encrypt", + }, + }, + Action: func(ctx *cli.Context) error { + // Check if keyfile path given and make sure it doesn't already exist. + keyfilepath := ctx.Args().First() + if keyfilepath == "" { + keyfilepath = defaultKeyfileName + } + if _, err := os.Stat(keyfilepath); err == nil { + utils.Fatalf("Keyfile already exists at %s.", keyfilepath) + } else if !os.IsNotExist(err) { + utils.Fatalf("Error checking if keyfile exists: %v", err) + } + + var privateKey *ecdsa.PrivateKey + var err error + if file := ctx.String("privatekey"); file != "" { + // Load private key from file. + privateKey, err = crypto.LoadECDSA(file) + if err != nil { + utils.Fatalf("Can't load private key: %v", err) + } + } else { + // If not loaded, generate random. + privateKey, err = crypto.GenerateKey() + if err != nil { + utils.Fatalf("Failed to generate random private key: %v", err) + } + } + + // Create the keyfile object with a random UUID. + id := uuid.NewRandom() + key := &keystore.Key{ + Id: id, + Address: crypto.PubkeyToAddress(privateKey.PublicKey), + PrivateKey: privateKey, + } + + // Encrypt key with passphrase. + passphrase := getPassPhrase(ctx, true) + keyjson, err := keystore.EncryptKey(key, passphrase, keystore.StandardScryptN, keystore.StandardScryptP) + if err != nil { + utils.Fatalf("Error encrypting key: %v", err) + } + + // Store the file to disk. + if err := os.MkdirAll(filepath.Dir(keyfilepath), 0700); err != nil { + utils.Fatalf("Could not create directory %s", filepath.Dir(keyfilepath)) + } + if err := ioutil.WriteFile(keyfilepath, keyjson, 0600); err != nil { + utils.Fatalf("Failed to write keyfile to %s: %v", keyfilepath, err) + } + + // Output some information. + out := outputGenerate{ + Address: key.Address.Hex(), + } + if ctx.Bool(jsonFlag.Name) { + mustPrintJSON(out) + } else { + fmt.Println("Address:", out.Address) + } + return nil + }, +} diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/inspect.go b/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/inspect.go new file mode 100644 index 00000000000..dbf5afc0cee --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/inspect.go @@ -0,0 +1,91 @@ +// 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 . + +package main + +import ( + "encoding/hex" + "fmt" + "io/ioutil" + + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/crypto" + "gopkg.in/urfave/cli.v1" +) + +type outputInspect struct { + Address string + PublicKey string + PrivateKey string +} + +var commandInspect = cli.Command{ + Name: "inspect", + Usage: "inspect a keyfile", + ArgsUsage: "", + 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{ + passphraseFlag, + jsonFlag, + cli.BoolFlag{ + Name: "private", + Usage: "include the private key in the output", + }, + }, + Action: func(ctx *cli.Context) error { + keyfilepath := ctx.Args().First() + + // Read key from file. + keyjson, err := ioutil.ReadFile(keyfilepath) + if err != nil { + utils.Fatalf("Failed to read the keyfile at '%s': %v", keyfilepath, err) + } + + // Decrypt key with passphrase. + passphrase := getPassPhrase(ctx, false) + key, err := keystore.DecryptKey(keyjson, passphrase) + if err != nil { + utils.Fatalf("Error decrypting key: %v", err) + } + + // Output all relevant information we can retrieve. + showPrivate := ctx.Bool("private") + out := outputInspect{ + Address: key.Address.Hex(), + PublicKey: hex.EncodeToString( + crypto.FromECDSAPub(&key.PrivateKey.PublicKey)), + } + if showPrivate { + out.PrivateKey = hex.EncodeToString(crypto.FromECDSA(key.PrivateKey)) + } + + if ctx.Bool(jsonFlag.Name) { + mustPrintJSON(out) + } else { + fmt.Println("Address: ", out.Address) + fmt.Println("Public key: ", out.PublicKey) + if showPrivate { + fmt.Println("Private key: ", out.PrivateKey) + } + } + return nil + }, +} diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/main.go b/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/main.go new file mode 100644 index 00000000000..2a9e5ee4838 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/main.go @@ -0,0 +1,67 @@ +// 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 . + +package main + +import ( + "fmt" + "os" + + "github.com/ethereum/go-ethereum/cmd/utils" + "gopkg.in/urfave/cli.v1" +) + +const ( + defaultKeyfileName = "keyfile.json" +) + +// Git SHA1 commit hash of the release (set via linker flags) +var gitCommit = "" + +var app *cli.App + +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", + } +) + +func main() { + if err := app.Run(os.Args); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/message.go b/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/message.go new file mode 100644 index 00000000000..531a931c82f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/message.go @@ -0,0 +1,159 @@ +// 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 . + +package main + +import ( + "encoding/hex" + "fmt" + "io/ioutil" + + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "gopkg.in/urfave/cli.v1" +) + +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: " ", + Description: ` +Sign the message with a keyfile. + +To sign a message contained in a file, use the --msgfile flag. +`, + Flags: []cli.Flag{ + passphraseFlag, + jsonFlag, + msgfileFlag, + }, + Action: func(ctx *cli.Context) error { + 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) + } + + // Decrypt key with passphrase. + passphrase := getPassPhrase(ctx, false) + key, err := keystore.DecryptKey(keyjson, passphrase) + if err != nil { + utils.Fatalf("Error decrypting key: %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)} + if ctx.Bool(jsonFlag.Name) { + mustPrintJSON(out) + } else { + fmt.Println("Signature:", out.Signature) + } + return nil + }, +} + +type outputVerify struct { + Success bool + RecoveredAddress string + RecoveredPublicKey string +} + +var commandVerifyMessage = cli.Command{ + Name: "verifymessage", + Usage: "verify the signature of a signed message", + ArgsUsage: "
", + 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 := getMessage(ctx, 2) + + 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) + } + + 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: recoveredAddress.Hex(), + } + if ctx.Bool(jsonFlag.Name) { + mustPrintJSON(out) + } else { + if out.Success { + fmt.Println("Signature verification successful!") + } else { + fmt.Println("Signature verification failed!") + } + 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/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/utils.go b/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/utils.go new file mode 100644 index 00000000000..0e563bf9225 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/cmd/ethkey/utils.go @@ -0,0 +1,83 @@ +// 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 . + +package main + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "strings" + + "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/console" + "github.com/ethereum/go-ethereum/crypto" + "gopkg.in/urfave/cli.v1" +) + +// getPassPhrase obtains a passphrase given by the user. It first checks the +// --passphrase command line flag and ultimately prompts the user for a +// passphrase. +func getPassPhrase(ctx *cli.Context, confirmation bool) string { + // Look for the --passphrase flag. + passphraseFile := ctx.String(passphraseFlag.Name) + if passphraseFile != "" { + content, err := ioutil.ReadFile(passphraseFile) + if err != nil { + utils.Fatalf("Failed to read passphrase file '%s': %v", + passphraseFile, err) + } + return strings.TrimRight(string(content), "\r\n") + } + + // Otherwise prompt the user for the passphrase. + passphrase, err := console.Stdin.PromptPassword("Passphrase: ") + if err != nil { + utils.Fatalf("Failed to read passphrase: %v", err) + } + if confirmation { + confirm, err := console.Stdin.PromptPassword("Repeat passphrase: ") + if err != nil { + utils.Fatalf("Failed to read passphrase confirmation: %v", err) + } + if passphrase != confirm { + utils.Fatalf("Passphrases do not match") + } + } + return passphrase +} + +// signHash is a helper function that calculates a hash for the given message +// that can be safely used to calculate a signature from. +// +// The hash is calulcated as +// keccak256("\x19Ethereum Signed Message:\n"${message length}${message}). +// +// This gives context to the signed message and prevents signing of transactions. +func signHash(data []byte) []byte { + msg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(data), data) + return crypto.Keccak256([]byte(msg)) +} + +// mustPrintJSON prints the JSON encoding of the given object and +// exits the program with an error message when the marshaling fails. +func mustPrintJSON(jsonObject interface{}) { + str, err := json.MarshalIndent(jsonObject, "", " ") + if err != nil { + utils.Fatalf("Failed to marshal JSON object: %v", err) + } + fmt.Println(string(str)) +} diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/evm/json_logger.go b/vendor/github.com/ethereum/go-ethereum/cmd/evm/json_logger.go index eb7b0c46600..0e7a9118968 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/evm/json_logger.go +++ b/vendor/github.com/ethereum/go-ethereum/cmd/evm/json_logger.go @@ -1,24 +1,25 @@ // 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 . +// You should have received a copy of the GNU General Public License +// along with go-ethereum. If not, see . package main import ( "encoding/json" "io" + "math/big" "time" "github.com/ethereum/go-ethereum/common" @@ -35,6 +36,10 @@ func NewJSONLogger(cfg *vm.LogConfig, writer io.Writer) *JSONLogger { return &JSONLogger{json.NewEncoder(writer), cfg} } +func (l *JSONLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error { + return nil +} + // CaptureState outputs state information on the logger. func (l *JSONLogger) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error { log := vm.StructLog{ @@ -56,6 +61,11 @@ func (l *JSONLogger) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cos return l.encoder.Encode(log) } +// CaptureFault outputs state information on the logger. +func (l *JSONLogger) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error { + return nil +} + // CaptureEnd is triggered at end of execution. func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error { type endLog struct { diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/evm/runner.go b/vendor/github.com/ethereum/go-ethereum/cmd/evm/runner.go index 96de0c76ac7..a9a2e5420f4 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/evm/runner.go +++ b/vendor/github.com/ethereum/go-ethereum/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/vendor/github.com/ethereum/go-ethereum/cmd/faucet/faucet.go b/vendor/github.com/ethereum/go-ethereum/cmd/faucet/faucet.go index 72098e68d28..99527f9d1e0 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/faucet/faucet.go +++ b/vendor/github.com/ethereum/go-ethereum/cmd/faucet/faucet.go @@ -18,10 +18,10 @@ package main //go:generate go-bindata -nometadata -o website.go faucet.html +//go:generate gofmt -w -s website.go import ( "bytes" - "compress/zlib" "context" "encoding/json" "errors" @@ -83,7 +83,8 @@ var ( captchaToken = flag.String("captcha.token", "", "Recaptcha site key to authenticate client side") captchaSecret = flag.String("captcha.secret", "", "Recaptcha secret key to authenticate server side") - logFlag = flag.Int("loglevel", 3, "Log level to use for Ethereum and the faucet") + noauthFlag = flag.Bool("noauth", false, "Enables funding requests without authentication") + logFlag = flag.Int("loglevel", 3, "Log level to use for Ethereum and the faucet") ) var ( @@ -132,6 +133,7 @@ func main() { "Amounts": amounts, "Periods": periods, "Recaptcha": *captchaToken, + "NoAuth": *noauthFlag, }) if err != nil { log.Crit("Failed to render the faucet template", "err", err) @@ -221,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, }, @@ -374,7 +375,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) { if err = websocket.JSON.Receive(conn, &msg); err != nil { return } - if !strings.HasPrefix(msg.URL, "https://gist.github.com/") && !strings.HasPrefix(msg.URL, "https://twitter.com/") && + if !*noauthFlag && !strings.HasPrefix(msg.URL, "https://gist.github.com/") && !strings.HasPrefix(msg.URL, "https://twitter.com/") && !strings.HasPrefix(msg.URL, "https://plus.google.com/") && !strings.HasPrefix(msg.URL, "https://www.facebook.com/") { if err = sendError(conn, errors.New("URL doesn't link to supported services")); err != nil { log.Warn("Failed to send URL error to client", "err", err) @@ -435,13 +436,19 @@ func (f *faucet) apiHandler(conn *websocket.Conn) { ) switch { case strings.HasPrefix(msg.URL, "https://gist.github.com/"): - username, avatar, address, err = authGitHub(msg.URL) + if err = sendError(conn, errors.New("GitHub authentication discontinued at the official request of GitHub")); err != nil { + log.Warn("Failed to send GitHub deprecation to client", "err", err) + return + } + continue case strings.HasPrefix(msg.URL, "https://twitter.com/"): username, avatar, address, err = authTwitter(msg.URL) case strings.HasPrefix(msg.URL, "https://plus.google.com/"): username, avatar, address, err = authGooglePlus(msg.URL) case strings.HasPrefix(msg.URL, "https://www.facebook.com/"): username, avatar, address, err = authFacebook(msg.URL) + case *noauthFlag: + username, avatar, address, err = authNoAuth(msg.URL) default: err = errors.New("Something funky happened, please open an issue at https://github.com/ethereum/go-ethereum/issues") } @@ -466,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() @@ -498,7 +505,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) { // Send an error if too frequent funding, othewise a success if !fund { - if err = sendError(conn, fmt.Errorf("%s left until next allowance", common.PrettyDuration(timeout.Sub(time.Now())))); err != nil { + if err = sendError(conn, fmt.Errorf("%s left until next allowance", common.PrettyDuration(timeout.Sub(time.Now())))); err != nil { // nolint: gosimple log.Warn("Failed to send funding error to client", "err", err) return } @@ -690,11 +697,7 @@ func authTwitter(url string) (string, string, common.Address, error) { } defer res.Body.Close() - reader, err := zlib.NewReader(res.Body) - if err != nil { - return "", "", common.Address{}, err - } - body, err := ioutil.ReadAll(reader) + body, err := ioutil.ReadAll(res.Body) if err != nil { return "", "", common.Address{}, err } @@ -776,3 +779,14 @@ func authFacebook(url string) (string, string, common.Address, error) { } return username + "@facebook", avatar, address, nil } + +// authNoAuth tries to interpret a faucet request as a plain Ethereum address, +// without actually performing any remote authentication. This mode is prone to +// Byzantine attack, so only ever use for truly private networks. +func authNoAuth(url string) (string, string, common.Address, error) { + address := common.HexToAddress(regexp.MustCompile("0x[0-9a-fA-F]{40}").FindString(url)) + if address == (common.Address{}) { + return "", "", common.Address{}, errors.New("No Ethereum address found to fund") + } + return address.Hex() + "@noauth", "", address, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/faucet/faucet.html b/vendor/github.com/ethereum/go-ethereum/cmd/faucet/faucet.html index 5d3b8741baa..ab41b2c8717 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/faucet/faucet.html +++ b/vendor/github.com/ethereum/go-ethereum/cmd/faucet/faucet.html @@ -80,11 +80,8 @@

{{

How does this work?

-

This Ether faucet is running on the {{.Network}} network. To prevent malicious actors from exhausting all available funds or accumulating enough Ether to mount long running spam attacks, requests are tied to certain common 3rd party accounts. Anyone having a GitHub, Twitter, Google+ or Facebook account may request funds within the permitted limits.

+

This Ether faucet is running on the {{.Network}} network. To prevent malicious actors from exhausting all available funds or accumulating enough Ether to mount long running spam attacks, requests are tied to common 3rd party social network accounts. Anyone having a Twitter, Google+ or Facebook account may request funds within the permitted limits.

-
-
To request funds via GitHub, create a gist with your Ethereum address embedded into the content (the file name doesn't matter).
Copy-paste the gists URL into the above input box and fire away!
-
To request funds via Twitter, make a tweet with your Ethereum address pasted into the contents (surrounding text doesn't matter).
Copy-paste the tweets URL into the above input box and fire away!
@@ -93,6 +90,11 @@

How does this work?

To request funds via Facebook, publish a new public post with your Ethereum address embedded into the content (surrounding text doesn't matter).
Copy-paste the posts URL into the above input box and fire away!
+ + {{if .NoAuth}} +
+
To request funds without authentication, simply copy-paste your Ethereum address into the above input box (surrounding text doesn't matter) and fire away.
This mode is susceptible to Byzantine attacks. Only use for debugging or private networks!
+ {{end}}

You can track the current pending requests below the input field to see how much you have to wait until your turn comes.

{{if .Recaptcha}}The faucet is running invisible reCaptcha protection against bots.{{end}} @@ -126,12 +128,7 @@

How does this work?

}; // Define a method to reconnect upon server loss var reconnect = function() { - if (attempt % 2 == 0) { - server = new WebSocket("wss://" + location.host + "/api"); - } else { - server = new WebSocket("ws://" + location.host + "/api"); - } - attempt++; + server = new WebSocket(((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + "/api"); server.onmessage = function(event) { var msg = JSON.parse(event.data); diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/faucet/website.go b/vendor/github.com/ethereum/go-ethereum/cmd/faucet/website.go index 6a99f8c6f89..fab1d43460b 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/faucet/website.go +++ b/vendor/github.com/ethereum/go-ethereum/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 @@ -68,7 +67,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _faucetHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x3a\x7f\x73\xdb\xb6\x92\x7f\x3b\x9f\x62\xcb\x8b\x9f\xa4\xb3\x48\xca\x76\x92\xe7\x93\x48\x75\x72\x79\x7d\x7d\xb9\xb9\xeb\xeb\xb4\xe9\xdc\xbd\x69\x3b\x37\x20\xb1\x12\x11\x83\x00\x0b\x80\x92\x55\x8f\xbe\xfb\x0d\x00\x92\xa2\x7e\xd8\x71\x9a\xdc\x5d\xfc\x87\x4c\x00\x8b\xdd\xc5\xfe\xc6\x92\xc9\x57\x7f\xf9\xfb\x9b\x77\xff\xf8\xfe\x1b\x28\x4c\xc9\xe7\xcf\x12\xfb\x0f\x38\x11\xcb\x34\x40\x11\xcc\x9f\x9d\x25\x05\x12\x3a\x7f\x76\x76\x96\x94\x68\x08\xe4\x05\x51\x1a\x4d\x1a\xd4\x66\x11\xde\x04\xbb\x85\xc2\x98\x2a\xc4\xdf\x6a\xb6\x4a\x83\xff\x0a\x7f\x7a\x1d\xbe\x91\x65\x45\x0c\xcb\x38\x06\x90\x4b\x61\x50\x98\x34\x78\xfb\x4d\x8a\x74\x89\xbd\x7d\x82\x94\x98\x06\x2b\x86\xeb\x4a\x2a\xd3\x03\x5d\x33\x6a\x8a\x94\xe2\x8a\xe5\x18\xba\xc1\x18\x98\x60\x86\x11\x1e\xea\x9c\x70\x4c\x2f\x83\xf9\x33\x8b\xc7\x30\xc3\x71\x7e\x7f\x1f\x7d\x87\x66\x2d\xd5\xed\x76\x3b\x85\xd7\xb5\x29\x50\x18\x96\x13\x83\x14\xfe\x4a\xea\x1c\x4d\x12\x7b\x48\xb7\x89\x33\x71\x0b\x85\xc2\x45\x1a\x58\xd6\xf5\x34\x8e\x73\x2a\xde\xeb\x28\xe7\xb2\xa6\x0b\x4e\x14\x46\xb9\x2c\x63\xf2\x9e\xdc\xc5\x9c\x65\x3a\x36\x6b\x66\x0c\xaa\x30\x93\xd2\x68\xa3\x48\x15\x5f\x47\xd7\xd1\x9f\xe3\x5c\xeb\xb8\x9b\x8b\x4a\x26\xa2\x5c\xeb\x00\x14\xf2\x34\xd0\x66\xc3\x51\x17\x88\x26\x80\x78\xfe\xc7\xe8\x2e\xa4\x30\x21\x59\xa3\x96\x25\xc6\x2f\xa2\x3f\x47\x13\x47\xb2\x3f\xfd\x38\x55\x4b\x56\xe7\x8a\x55\x06\xb4\xca\x9f\x4c\xf7\xfd\x6f\x35\xaa\x4d\x7c\x1d\x5d\x46\x97\xcd\xc0\xd1\x79\xaf\x83\x79\x12\x7b\x84\xf3\x4f\xc2\x1d\x0a\x69\x36\xf1\x55\xf4\x22\xba\x8c\x2b\x92\xdf\x92\x25\xd2\x96\x92\x5d\x8a\xda\xc9\xcf\x46\xf7\x21\x1d\xbe\x3f\x54\xe1\xe7\x20\x56\xca\x12\x85\x89\xde\xeb\xf8\x2a\xba\xbc\x89\x26\xed\xc4\x31\x7e\x47\xc0\x2a\xcd\x92\x3a\x8b\x56\xa8\xac\xe5\xf2\x30\x47\x61\x50\xc1\xbd\x9d\x3d\x2b\x99\x08\x0b\x64\xcb\xc2\x4c\xe1\x72\x32\x39\x9f\x9d\x9a\x5d\x15\x7e\x9a\x32\x5d\x71\xb2\x99\xc2\x82\xe3\x9d\x9f\x22\x9c\x2d\x45\xc8\x0c\x96\x7a\x0a\x1e\xb3\x5b\xd8\x3a\x9a\x95\x92\x4b\x85\x5a\x37\xc4\x2a\xa9\x99\x61\x52\x4c\xad\x45\x11\xc3\x56\x78\x0a\x56\x57\x44\x1c\x6d\x20\x99\x96\xbc\x36\x78\xc0\x48\xc6\x65\x7e\xeb\xe7\x9c\x37\xf7\x0f\x91\x4b\x2e\xd5\x14\xd6\x05\x6b\xb6\x81\x23\x04\x95\xc2\x06\x3d\x54\x84\x52\x26\x96\x53\x78\x55\x35\xe7\x81\x92\xa8\x25\x13\x53\x98\xec\xb6\x24\x71\x2b\xc6\x24\xf6\x81\xeb\xd9\x59\x92\x49\xba\x71\x3a\xa4\x6c\x05\x39\x27\x5a\xa7\xc1\x81\x88\x5d\x40\xda\x03\xb0\x71\x88\x30\xd1\x2e\xed\xad\x29\xb9\x0e\xc0\x11\x4a\x03\xcf\x44\x98\x49\x63\x64\x39\x85\x4b\xcb\x5e\xb3\xe5\x00\x1f\x0f\xf9\x32\xbc\xbc\x6a\x17\xcf\x92\xe2\xb2\x45\x62\xf0\xce\x84\x4e\x3f\x9d\x66\x82\x79\xc2\xda\xbd\x0b\x02\x0b\x12\x66\xc4\x14\x01\x10\xc5\x48\x58\x30\x4a\x51\xa4\x81\x51\x35\x5a\x3b\x62\x73\xe8\x87\xbf\x07\xa2\x5f\x71\xd9\xf2\x15\x53\xb6\x6a\x8e\xd5\x7b\x3c\x38\xe1\xc3\x87\xb8\x81\xe6\x41\x2e\x16\x1a\x4d\xd8\x3b\x53\x0f\x98\x89\xaa\x36\xe1\x52\xc9\xba\xea\xd6\xcf\x12\x37\x0b\x8c\xa6\x41\xad\x78\xd0\x84\x7f\xf7\x68\x36\x55\x23\x8a\xa0\x3b\xb8\x54\x65\x68\x35\xa1\x24\x0f\xa0\xe2\x24\xc7\x42\x72\x8a\x2a\x0d\x7e\x94\x39\x23\x1c\x84\x3f\x33\xfc\xf4\xc3\xbf\x43\xa3\x32\x26\x96\xb0\x91\xb5\x82\x6f\x4c\x81\x0a\xeb\x12\x08\xa5\xd6\x5c\xa3\x28\xea\x31\xe2\x6c\xf7\x98\xd5\x30\x33\x62\x07\x75\x96\x64\xb5\x31\xb2\x03\xcc\x8c\x80\xcc\x88\x90\xe2\x82\xd4\xdc\x00\x55\xb2\xa2\x72\x2d\x42\x23\x97\x4b\x9b\xe9\xfc\x21\xfc\xa6\x00\x28\x31\xa4\x59\x4a\x83\x16\xb6\xd5\x21\xd1\x95\xac\xea\xaa\xd1\xa2\x9f\xc4\xbb\x8a\x08\x8a\xd4\xea\x9c\x6b\x0c\xe6\xdf\xb2\x15\x42\x89\xfe\x2c\x67\x87\x26\x91\x13\x85\x26\xec\x23\x3d\x32\x8c\x24\xf6\xcc\xf8\x23\x41\xf3\x97\xd4\xbc\xc5\xd4\x1d\xa1\x44\x51\xc3\xde\x28\x54\x36\xae\x04\xf3\xfb\x7b\x45\xc4\x12\xe1\x39\xa3\x77\x63\x78\x4e\x4a\x59\x0b\x03\xd3\x14\xa2\xd7\xee\x51\x6f\xb7\x7b\xd8\x01\x12\xce\xe6\x09\x79\xcc\xbc\x41\x8a\x9c\xb3\xfc\x36\x0d\x0c\x43\x95\xde\xdf\x5b\xe4\xdb\xed\x0c\xee\xef\xd9\x02\x9e\x47\x3f\x60\x4e\x2a\x93\x17\x64\xbb\x5d\xaa\xf6\x39\xc2\x3b\xcc\x6b\x83\xc3\xd1\xfd\x3d\x72\x8d\xdb\xad\xae\xb3\x92\x99\x61\xbb\xdd\xce\x0b\xba\xdd\x5a\x9e\x1b\x3e\xb7\x5b\x88\x2d\x52\x41\xf1\x0e\x9e\x47\xdf\xa3\x62\x92\x6a\xf0\xf0\x49\x4c\xe6\x49\xcc\xd9\xbc\xd9\xb7\x2f\xa4\xb8\xe6\x3b\x7b\x89\xad\xc1\x74\x76\xee\xdc\xc6\xb1\xda\xe7\xf4\x84\x17\x2c\xc3\x8e\xfb\xc6\x1e\x34\x33\x78\x8b\x9b\x34\xb8\xbf\xef\xef\x6d\x56\x73\xc2\x79\x46\xac\x5c\xfc\xd1\xba\x4d\xbf\xa3\xb5\xd3\x15\xd3\xae\xa4\x9a\xb7\x1c\xec\xd8\x7e\xa2\x5b\x1f\x04\x2e\x23\xab\x29\x5c\x5f\xf5\xa2\xd6\x29\x8f\x7f\x75\xe0\xf1\xd7\x27\x81\x2b\x22\x90\x83\xfb\x0d\x75\x49\x78\xfb\xdc\x78\x4b\xcf\xf9\x0e\x37\x85\x36\x46\x77\xac\x75\xb1\x7e\x32\x03\xb9\x42\xb5\xe0\x72\x3d\x05\x52\x1b\x39\x83\x92\xdc\x75\xf9\xee\x7a\x32\xe9\xf3\x6d\x4b\x41\x92\x71\x74\xd1\x45\xe1\x6f\x35\x6a\xa3\xbb\x58\xe2\x97\xdc\xaf\x0d\x29\x14\x85\x46\x7a\x20\x0d\x4b\xd1\x8a\xd6\x41\xf5\x54\xdf\x09\xf3\x24\xef\x0b\x29\xbb\x14\xd2\x67\xa3\x41\xdd\xcb\x76\xc1\x3c\x31\x6a\x07\x77\x96\x18\xfa\x51\x29\x40\xd9\x12\xef\xa1\x0c\xe0\x23\x9a\x3d\x7b\x85\xa8\x7c\x7d\x61\x4d\x16\xdc\x30\x89\x0d\xfd\x04\xca\xd6\x08\x33\xa2\xf1\x29\xe4\x5d\xa6\xdf\x91\x77\xc3\x4f\xa5\x5f\x20\x51\x26\x43\x62\x9e\xc2\xc0\xa2\x16\xb4\x77\x7e\x17\x3b\x3f\x95\x81\x5a\xb0\x15\x2a\xcd\xcc\xe6\xa9\x1c\x20\xdd\xb1\xe0\xc7\xfb\x2c\x24\xb1\x51\x8f\xdb\x5a\x7f\xf0\x99\x9c\xfb\x43\x25\xc9\xf5\xfc\x6f\x72\x0d\x54\xa2\x06\x53\x30\x0d\x36\xb9\x7e\x9d\xc4\xc5\x75\x07\x52\xcd\xdf\xd9\x05\x27\x54\x58\xb8\xd2\x02\x98\x06\x55\x0b\x97\x79\xa5\x00\x53\xe0\x7e\x39\xd2\x24\xe9\x08\xde\x49\x5b\xd2\xad\x50\x18\x28\x09\x67\x39\x93\xb5\x06\x92\x1b\xa9\x34\x2c\x94\x2c\x01\xef\x0a\x52\x6b\x63\x11\xd9\xf0\x41\x56\x84\x71\xe7\x4b\x4e\xa5\x20\x15\x90\x3c\xaf\xcb\xda\x96\xa4\x62\x09\x28\x64\xbd\x2c\x1a\x5e\x8c\x04\x9f\x98\xb8\x14\xcb\x8e\x1f\x5d\x91\x12\x88\x31\x24\xbf\xd5\x63\x68\xa3\x02\x10\x85\x60\x18\x52\xbb\x2b\x47\x65\xeb\x06\xc8\x65\x59\x4a\x01\xd7\x8a\x42\x45\x94\xd9\x58\x5a\x2e\xbd\x45\xf0\x5a\x6c\xa4\x40\x28\xc8\xca\xb1\x06\xdf\x32\xf3\xb7\x3a\x1b\xc3\x3b\x7f\x9f\x18\xc3\xb7\x52\x2e\x39\x5e\x58\x0e\xff\x4a\x72\xcc\xa4\xbc\x6d\xb7\x43\x49\x36\x2d\xe1\xe6\x1c\x6b\x66\x0a\xe6\x05\x55\xa1\x2a\x2d\x0e\x0a\x9c\x95\xcc\xe8\x28\x89\xab\x5d\x6c\xdd\x65\x69\x1e\x16\x52\xb1\xdf\x6d\x89\xc3\x3b\x7d\x01\x24\xd4\x1c\xc4\x99\x36\x4c\x3a\x03\xe0\xb8\x30\x53\x78\xe1\xc3\xe4\xa1\x49\x2f\x99\x29\xea\x2c\x24\xfc\xa4\x53\xb5\x68\xdd\x3d\xd3\xa6\x9f\x29\x5c\xfb\xe2\xd6\x97\x15\xd4\xf4\x42\x22\x3d\x30\x3c\x4f\xf7\xe6\xa6\xba\xeb\x58\xe9\x2a\xe4\x49\x87\xc4\xda\xc3\xbe\x60\x56\x6c\x27\xdb\x5c\x21\x31\x08\x04\x12\x72\x70\x61\x5e\x32\x6d\x22\xcf\xbd\xbb\x72\x05\x60\x88\x5a\xa2\x49\x83\xff\x26\x99\xac\xcd\x34\xe3\x44\xdc\x06\x73\x0b\x67\x33\xbc\x93\xf7\xe9\x9a\x10\xb0\xcc\x90\x52\xa4\xc0\x84\x91\x4e\x23\x4d\x07\x02\x86\x76\xb0\x60\x1c\x5d\x91\xea\x7c\x42\x0c\xac\x36\xad\xc6\x47\x51\x92\xa9\x78\xfe\x46\x56\x9b\xb0\x22\xda\xa0\xdb\x6a\x09\x6a\x57\x8b\x76\xd8\x48\x26\x57\x08\xbe\xea\xcd\xe4\x1d\x10\x41\x61\xc1\x14\x02\x59\x93\xcd\x57\x49\x4c\xdd\x1d\xa5\x95\xe3\x1f\x57\x66\x73\xb3\xfd\xa2\x34\xd9\x79\x47\x49\x6e\x4f\x2a\xb2\x61\xda\x29\x91\x39\xa9\xc7\x66\x8d\x68\xbe\xb6\x21\x39\xfd\xc1\x23\x64\x62\x79\x7e\x35\xf1\x91\xc6\x3e\x58\xf4\xe7\x57\x13\x2b\xe1\xf3\xab\xc9\xe4\x6e\xf2\xc4\xbf\xf3\xab\x89\x14\xe7\x57\x13\x53\xe0\xf9\xd5\xe4\xfc\xea\xba\x1f\xa3\xfc\x4c\x6b\x1d\x16\x0a\xb5\xa5\xd6\x86\xae\x87\x4c\xcc\xb1\xfb\x21\x1b\x73\x06\x72\x6c\x61\x1a\x86\xba\x56\x4a\xd6\xc2\x56\x3b\x60\xcf\xfc\x24\x2b\x3b\x12\xa3\xae\xab\x4a\x2a\x13\xf5\xc5\x49\xec\xfd\x96\xa3\x8e\x6f\x26\x2f\x6f\x5e\x3d\xca\xbe\xb3\x58\x77\x86\xff\x73\xab\x5d\xba\xb0\x19\x56\xbc\xd6\xb6\xb4\x64\xf6\x4e\xf7\x45\x99\xb0\x8f\xeb\xf0\x3d\xaf\xf5\x18\xaa\x3a\xe3\x4c\x17\x40\x40\xe0\x1a\x12\x6d\x94\x14\xcb\xb9\x9b\xcd\x93\xb8\x19\x42\x25\xb5\xf9\x83\x11\xe7\x0f\x99\x83\xa5\xf7\xff\x14\x74\x16\x4d\xaa\xfb\xa2\x54\xd6\xe6\xdf\x2f\x55\x5f\x47\xee\xbb\x5e\xaf\xa3\x56\x92\xce\x77\x0b\xe4\x55\x6c\xab\x91\x5a\x30\xb3\x89\x7d\x14\x94\x22\xfe\x9a\xd1\xf4\xea\xe6\xea\xd5\xab\xab\x17\xff\x72\xf3\xf2\xe5\xd5\xcd\x8b\x97\x0f\x39\x76\x67\x14\x1f\xef\xd7\x5d\xed\xc9\x7b\x35\xdf\x3f\x64\x0d\x39\x11\x60\x14\xc9\x6f\xbd\x10\x6a\xa5\xac\x10\x2a\xf4\xe7\xef\x4a\xab\x0c\xb9\x5c\x3b\x10\x4f\x67\xc1\x90\xbb\x3a\x4b\x23\x42\x21\xd7\x50\xd6\xb9\x93\xb5\x2d\xa7\xd0\x2e\xac\x09\x33\x50\x0b\xc3\xb8\x57\x81\xa9\x95\xab\xc6\x70\xaf\x1a\x3a\xba\x6d\x27\x58\xce\xdf\xd9\x1c\x7d\x54\x84\x76\xf7\x64\x50\xf8\xc6\x83\x43\xa5\xa4\xc1\xdc\xca\x11\xc8\x92\x30\xa1\xad\x04\x5c\xbd\x85\xe5\x13\xee\xd1\xdd\x53\xf3\xb0\xeb\x09\xbb\xe5\x38\x86\x6f\xb9\xcc\x08\x87\x95\x75\x85\x8c\xdb\x02\x5a\x42\x21\xed\xd1\x7b\xd2\xd2\x86\x98\x5a\x83\x5c\xb8\x59\xcf\xb9\xdd\xbf\x22\xca\x56\xa9\x58\x56\x06\xd2\xa6\xa3\x69\xe7\x34\xaa\x55\xd3\xa7\xb5\x43\xc3\x50\xed\xad\x77\x52\x4f\xe1\xe7\x5f\x67\xcf\x1a\x56\xfe\x82\x0b\x26\x6c\xc6\x5d\xd4\xc2\x1f\xd9\x14\xc4\x34\x15\x95\x86\x9c\x4b\x5d\x2b\xcf\x21\x55\xb2\x02\xcb\x65\x8b\xa9\xc5\x6c\x17\x2a\x47\xad\x45\x32\x2c\x88\x2e\x46\x4d\x43\x56\xa1\xd3\x52\xb7\xd6\xce\x9f\x2d\xa4\x82\xa1\x45\xc0\xd2\xc9\x0c\x58\xd2\xe2\x8d\x38\x8a\xa5\x29\x66\xc0\x2e\x2e\x3a\xe0\x33\xb6\x80\x61\x0b\xf1\x33\xfb\x35\x32\x77\x91\xa5\x02\x69\x0a\x7d\x6a\x8e\x60\x83\x47\x57\x9c\xe5\x38\x64\x63\xb8\x1c\xcd\xda\xd5\x4c\x21\xb9\x6d\x47\x8d\x1e\xfd\x3f\xf7\xbb\x9d\xed\x4b\xc6\x09\x7f\x4f\x36\xbe\xdb\xa2\x81\xb8\x22\x0e\x6a\xc5\xa1\xf1\x19\xaf\x82\x4e\x21\x0e\xae\x2f\x95\x23\xbb\x6c\x1e\x1a\x9b\x6a\x8f\xe0\xd1\x44\x1a\x05\x1d\xfe\xdb\x8f\x7f\xff\x2e\xd2\x46\x31\xb1\x64\x8b\xcd\xf0\xbe\x56\x7c\x0a\xcf\x87\xc1\x3f\xd5\x8a\x07\xa3\x9f\x27\xbf\x46\x2b\xc2\x6b\x1c\x3b\x7d\x4f\xdd\xef\x11\x95\x31\x34\x8f\x53\xd8\x27\xb8\x1d\x8d\x66\xa7\x3b\x53\xbd\x46\x9a\x42\x8d\x66\x68\x01\x3b\xc3\x3f\x94\x11\x81\x12\x4d\x21\x9d\xeb\x2a\xcc\xa5\x10\x98\x1b\xa8\x2b\x29\x1a\x91\x00\x97\x5a\xef\x0c\xb1\x85\x48\x8f\x8d\xc2\x6a\xb9\xb5\xee\x73\xb8\xb2\xda\x9d\x74\xaa\x6d\x90\xa5\x2e\x48\xff\x27\x66\x3f\xca\xfc\x16\xcd\x30\x58\x6b\x1b\x1c\x03\xb8\x00\x2e\x73\x62\xf1\x45\x85\x0d\xd5\x17\x10\xc4\xa4\x62\x41\xa3\xfc\x2d\x20\xd7\xf8\x61\x64\x4f\xc2\xe5\x5f\x94\x78\x4e\x2f\x2e\xbc\x3f\xb5\x9a\x93\xa2\x44\xad\xc9\x12\xfb\x27\x74\x97\xd9\xee\x28\x56\x10\xa5\x5e\x42\x0a\x4e\xc3\x15\x51\x1a\x3d\x48\x44\x89\x21\xad\xb9\x5a\x71\x38\xb0\x34\x05\x51\x73\xbe\xb3\x72\xef\x55\xb3\xd6\x7e\xf7\xc0\x23\x9f\xe2\xbe\x4a\x53\xa8\x05\x75\x3a\xa2\xbb\x9d\xd6\x7a\x7c\xdf\x63\x14\xd9\x54\xb4\xdb\x31\x9a\xf5\xdd\x61\x0f\x1b\xd2\x0f\xa1\x43\x7a\x88\x0f\xe9\x03\x08\x5d\x9b\xe9\x31\x7c\xbe\x2d\xd5\x43\xe7\x26\x1e\xc0\x26\xea\x32\x43\xf5\x18\x3a\xdf\x66\x6a\xd0\x39\x51\xbf\x15\xa6\xb7\x77\x0c\x97\xaf\x46\x0f\x60\x47\xa5\xe4\x83\xc8\x85\x34\x9b\xe1\x3d\x27\x1b\x9b\x4f\x61\x60\x64\xf5\xc6\x75\x85\x06\x63\x97\xe4\xa7\xd0\x61\x18\xbb\x7e\xff\x14\x06\x6e\x64\xd7\x59\x89\x6e\xd7\xcb\xc9\x64\x32\x86\xf6\x45\xd9\xbf\x12\xeb\xc5\xaa\xc6\xed\x03\xfc\xe8\x3a\xcf\x6d\xad\xf1\x29\x1c\x35\x38\x3a\x9e\x9a\xf1\x27\x70\xd5\x25\x97\x3d\xb6\xe0\x4f\x7f\x82\xa3\xd5\x7d\x33\x8e\x63\xf8\x0f\xa2\x6e\x5d\x0f\xa7\x52\xb8\x72\x7d\x9e\x0e\xbe\x64\x5a\xbb\x36\x8a\x06\x2a\x05\x36\x7b\x3e\x2e\x6f\x1c\xf1\xd8\x80\xc1\x1c\x26\x87\x0c\xda\x78\xda\xcb\x2b\x27\xd2\x4d\x0f\xef\x7e\x26\x69\x25\x72\x22\x51\xb1\x12\xe1\xab\x14\x82\xa0\xbf\xf9\x08\xc2\x02\x74\xc8\xce\x34\x9a\x77\x5e\x17\xc3\x26\xbd\x9e\x4a\x7e\xa3\x31\x5c\x4f\x26\x93\xd1\x11\x13\xdb\x9d\x78\x5f\x57\xb6\xee\x02\x22\x36\x2e\xd2\x75\xb2\x75\x95\x9e\xad\xa1\x6c\x9c\xe3\x90\x4b\xce\x7d\xd1\xd3\x6c\xb5\x02\x6e\xfa\x5c\x29\x84\x97\xb3\x13\x69\xb8\x27\xc9\xde\xd1\x0e\xd5\x73\x42\xf6\x87\x2a\xda\x97\xd9\x01\x70\x78\xb9\xa7\x94\x3d\x7d\x9d\x56\xcc\x59\xc7\x37\xdb\x49\xf4\x40\x5d\x3b\x7d\x1d\xca\xac\xc7\xbf\xc7\x73\x71\xf9\xc4\x63\x74\xcb\x55\xad\x8b\xe1\x01\xa3\xa3\xd9\xb1\x6e\xde\x1a\x54\xc4\xa0\x7b\x75\xe1\x74\x81\xc2\xd8\x1a\xfb\x50\x25\xae\xfa\x56\x18\x2a\x14\x14\x55\x5b\x93\xf8\xcb\x84\xad\x20\xf7\x54\xe6\x6f\x1c\x7d\x73\xfa\x48\x87\x71\x35\x9d\x14\x08\x00\x70\xe0\x04\xce\x50\xf7\x2c\xd5\x02\x23\x27\x95\x46\x0a\x29\xf8\xef\x16\x86\xa3\xa8\x16\xec\x6e\x38\x0a\x9b\xf1\x21\x8e\x76\x7d\xd6\xdd\x2d\x5b\xb6\x2f\x52\x08\x12\xa3\x80\xd1\x74\x60\x93\xf0\xa9\x8a\xef\x02\x82\xc1\x7c\xc7\x41\x7f\x2b\x40\x62\xe8\xdc\xb5\xae\xfd\x35\xf1\x97\x20\x23\xf9\xed\xd2\xdd\xbd\xa6\xb6\x56\x1b\x1e\xa1\x25\x2b\x62\x88\x72\x58\x47\x33\xd8\x81\x37\x57\xd1\xdc\x2a\x67\x06\xfe\xc6\xeb\x3a\xe4\xd0\xbd\x55\x72\xa3\x4c\x2a\x8a\x2a\x54\x84\xb2\x5a\x4f\xe1\x45\x75\x37\xfb\xa5\x7d\xeb\xe6\xfa\xf8\x8f\xb2\x5a\x29\x9c\x1f\x71\xd4\xb4\x83\x2f\x20\x48\x62\x0b\xf0\x21\x34\xdd\x61\xfb\xdf\x4b\xc0\x89\xb7\x15\xd0\x7d\xcd\xd0\xcc\x97\x8c\x52\x8e\x96\xe1\x1d\x7a\xeb\x8c\x56\xff\x7d\x97\xda\x27\x09\xcd\x6b\x8a\xdd\x9e\xfd\xda\xea\xc4\x86\xee\x8d\xc7\xc0\x1a\x40\x68\x8f\xcc\x9c\xcc\x9b\x3e\x81\x9b\x56\x03\x27\x8b\xe6\xeb\x17\x5a\x2b\x57\x80\x0d\xc3\xc6\xc0\xc6\x30\xd0\xb6\x78\xa4\x7a\x30\x8a\x8a\xba\x24\x82\xfd\x8e\x43\x9b\x97\x46\x5e\x56\xee\x15\x4a\x70\x1c\x92\x8f\x98\xd9\xbd\xdb\x18\xb4\x39\x6e\xd0\x08\x71\xd0\x6a\xf7\xc5\xae\xa5\x30\x85\xc9\x6c\xf0\x91\x12\x3a\x4d\x25\xcc\x88\x82\xfe\x20\x6c\x93\x2f\x28\x69\xa9\xb7\x6b\x19\x51\x03\xdf\x2b\x71\x05\xbe\x90\xeb\x74\x70\x3d\xe9\x98\xf4\x8a\x76\x7a\x1e\x34\xb6\x76\xa4\x0c\xcb\x65\xeb\x9a\x73\xb8\x9e\x7c\x0e\x6e\x29\x11\x4b\x3c\x3c\x81\x51\xac\x42\x0a\x24\x37\x6c\x85\xff\x0b\x07\xf9\x0c\x42\xfe\x68\x16\xad\x1d\xb6\xc2\x73\x66\xba\xc7\xaf\x5d\xed\x64\xfb\xcf\xd6\xdf\x20\x76\x12\xbe\x80\xe0\xe4\x41\x1e\xb4\xc4\x03\xc0\x03\xd7\x7e\xd8\xef\xdd\x3b\xc1\xe0\x30\xa7\xd8\x6a\xb7\x7b\x9f\x3d\x8a\x0a\x53\xf2\x61\x90\x18\xf7\x5d\x93\xe5\xb9\xc3\xe0\x10\xf8\xe9\xfd\x92\x6e\xbb\x7f\x91\xc9\xb9\xd4\x78\x70\x51\x83\x5e\x71\xd2\x5d\xe6\xda\x4a\x04\xb6\xbb\xcf\xbf\xe2\x18\x7e\x34\x44\x19\x20\xf0\xd3\x5b\xa8\x2b\x4a\x8c\x7f\xfb\x66\xf3\xa3\xef\x48\xb6\xdf\x87\x65\x44\x69\x58\x48\xb5\x26\x8a\x36\x0d\x1e\x53\xe0\xc6\xbd\x7d\x6b\x4b\x3f\x8d\xe6\xad\x8d\x62\x2b\xc2\x87\x47\x17\xc7\xe7\xc3\x41\xd4\x57\xf9\x60\x14\x21\xc9\x8b\x63\x40\x97\xb1\x3a\xba\x29\x7c\xe7\xae\x00\xc3\xe7\x43\x53\x30\x3d\x8a\x88\x31\x6a\x38\xd8\x33\x86\xc1\xc8\xea\xf5\xb2\x77\x25\xeb\xb6\x27\x7b\x6e\xf5\x18\x8e\x5d\x31\xdd\x15\x02\x2d\x78\xae\xf5\xd0\xdb\xd5\x60\xdc\xc3\xbd\x6f\x56\x83\xf3\x41\xa7\xa8\x9d\x7b\xef\xce\x91\x9e\xe4\x64\x0f\xf5\xc0\x7a\xd9\xe0\x88\x3c\xa1\xf4\x8d\xf5\x9f\x61\x70\xc2\xd3\x0f\xad\x63\xd4\x09\xdb\xc7\xeb\x47\xa5\xec\xbf\xa4\x79\x40\xc4\x8c\x0e\x46\x91\xae\x33\xdf\xdc\x18\xbe\xec\x2e\x60\x2d\x98\x33\xde\xc3\x54\x70\x54\x50\x58\x12\xfb\x45\x45\x78\x50\x84\x3c\x92\x35\xda\xcb\xbc\x3b\xd5\x76\x6c\x05\x3e\x19\x75\xbd\xb1\x6f\xb4\x2d\xae\x7c\x5b\x78\x8d\x99\x76\x0d\x02\x68\xec\xdd\xb5\x83\x7c\xdb\xe7\xf5\xf7\x6f\x7b\xad\x9f\xce\x23\x86\x0e\x7b\xf7\xe9\xe6\xa9\x46\xcb\xc9\x6f\x45\xd7\xeb\x75\xe4\xdf\x76\xb8\x16\x6f\xd7\x89\x89\x49\xc5\xa2\xf7\x3a\x00\xa2\x37\x22\x07\x8a\x0b\x54\xf3\x1e\xfa\xa6\x3d\x93\xc4\xfe\x2b\xc6\x24\xf6\x1f\x6a\xff\x4f\x00\x00\x00\xff\xff\xf1\xa6\xb6\xb8\xb9\x2d\x00\x00") +var _faucetHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x5a\x71\x73\xdb\xb6\x92\xff\xdb\xf9\x14\x5b\x5e\xfc\x24\x9d\x4d\x52\xb6\x93\x3c\x9f\x44\xaa\x93\x97\xd7\xd7\xcb\xcd\x5d\xdb\x69\xd3\xb9\x7b\xd3\xd7\xb9\x01\x89\x95\x88\x18\x04\x58\x00\x94\xac\x7a\xf4\xdd\x6f\x00\x90\x14\x29\xc9\x6e\xd2\xe4\xde\x34\x7f\x38\x24\xb0\xd8\x5d\xec\xfe\x16\xbb\x58\x2a\xf9\xe2\xaf\xdf\xbe\x79\xf7\xf7\xef\xbe\x82\xc2\x94\x7c\xf1\x2c\xb1\xff\x01\x27\x62\x95\x06\x28\x82\xc5\xb3\xb3\xa4\x40\x42\x17\xcf\xce\xce\x92\x12\x0d\x81\xbc\x20\x4a\xa3\x49\x83\xda\x2c\xc3\xdb\x60\x3f\x51\x18\x53\x85\xf8\x4b\xcd\xd6\x69\xf0\x3f\xe1\x8f\xaf\xc3\x37\xb2\xac\x88\x61\x19\xc7\x00\x72\x29\x0c\x0a\x93\x06\x6f\xbf\x4a\x91\xae\xb0\xb7\x4e\x90\x12\xd3\x60\xcd\x70\x53\x49\x65\x7a\xa4\x1b\x46\x4d\x91\x52\x5c\xb3\x1c\x43\xf7\x72\x09\x4c\x30\xc3\x08\x0f\x75\x4e\x38\xa6\x57\xc1\xe2\x99\xe5\x63\x98\xe1\xb8\x78\x78\x88\xbe\x41\xb3\x91\xea\x6e\xb7\x9b\xc1\xeb\xda\x14\x28\x0c\xcb\x89\x41\x0a\x7f\x23\x75\x8e\x26\x89\x3d\xa5\x5b\xc4\x99\xb8\x83\x42\xe1\x32\x0d\xac\xea\x7a\x16\xc7\x39\x15\xef\x75\x94\x73\x59\xd3\x25\x27\x0a\xa3\x5c\x96\x31\x79\x4f\xee\x63\xce\x32\x1d\x9b\x0d\x33\x06\x55\x98\x49\x69\xb4\x51\xa4\x8a\x6f\xa2\x9b\xe8\xcf\x71\xae\x75\xdc\x8d\x45\x25\x13\x51\xae\x75\x00\x0a\x79\x1a\x68\xb3\xe5\xa8\x0b\x44\x13\x40\xbc\xf8\x7d\x72\x97\x52\x98\x90\x6c\x50\xcb\x12\xe3\x17\xd1\x9f\xa3\xa9\x13\xd9\x1f\x7e\x5a\xaa\x15\xab\x73\xc5\x2a\x03\x5a\xe5\x1f\x2c\xf7\xfd\x2f\x35\xaa\x6d\x7c\x13\x5d\x45\x57\xcd\x8b\x93\xf3\x5e\x07\x8b\x24\xf6\x0c\x17\x9f\xc4\x3b\x14\xd2\x6c\xe3\xeb\xe8\x45\x74\x15\x57\x24\xbf\x23\x2b\xa4\xad\x24\x3b\x15\xb5\x83\x9f\x4d\xee\x63\x3e\x7c\x7f\xe8\xc2\xcf\x21\xac\x94\x25\x0a\x13\xbd\xd7\xf1\x75\x74\x75\x1b\x4d\xdb\x81\x63\xfe\x4e\x80\x75\x9a\x15\x75\x16\xad\x51\x59\xe4\xf2\x30\x47\x61\x50\xc1\x83\x1d\x3d\x2b\x99\x08\x0b\x64\xab\xc2\xcc\xe0\x6a\x3a\x3d\x9f\x9f\x1a\x5d\x17\x7e\x98\x32\x5d\x71\xb2\x9d\xc1\x92\xe3\xbd\x1f\x22\x9c\xad\x44\xc8\x0c\x96\x7a\x06\x9e\xb3\x9b\xd8\x39\x99\x95\x92\x2b\x85\x5a\x37\xc2\x2a\xa9\x99\x61\x52\xcc\x2c\xa2\x88\x61\x6b\x3c\x45\xab\x2b\x22\x8e\x16\x90\x4c\x4b\x5e\x1b\x3c\x50\x24\xe3\x32\xbf\xf3\x63\x2e\x9a\xfb\x9b\xc8\x25\x97\x6a\x06\x9b\x82\x35\xcb\xc0\x09\x82\x4a\x61\xc3\x1e\x2a\x42\x29\x13\xab\x19\xbc\xaa\x9a\xfd\x40\x49\xd4\x8a\x89\x19\x4c\xf7\x4b\x92\xb8\x35\x63\x12\xfb\x83\xeb\xd9\x59\x92\x49\xba\x75\x3e\xa4\x6c\x0d\x39\x27\x5a\xa7\xc1\x81\x89\xdd\x81\x34\x20\xb0\xe7\x10\x61\xa2\x9d\x1a\xcc\x29\xb9\x09\xc0\x09\x4a\x03\xaf\x44\x98\x49\x63\x64\x39\x83\x2b\xab\x5e\xb3\xe4\x80\x1f\x0f\xf9\x2a\xbc\xba\x6e\x27\xcf\x92\xe2\xaa\x65\x62\xf0\xde\x84\xce\x3f\x9d\x67\x82\x45\xc2\xda\xb5\x4b\x02\x4b\x12\x66\xc4\x14\x01\x10\xc5\x48\x58\x30\x4a\x51\xa4\x81\x51\x35\x5a\x1c\xb1\x05\xf4\x8f\xbf\x47\x4e\xbf\xe2\xaa\xd5\x2b\xa6\x6c\xdd\x6c\xab\xf7\x78\xb0\xc3\xc7\x37\x71\x0b\xcd\x83\x5c\x2e\x35\x9a\xb0\xb7\xa7\x1e\x31\x13\x55\x6d\xc2\x95\x92\x75\xd5\xcd\x9f\x25\x6e\x14\x18\x4d\x83\x5a\xf1\xa0\x39\xfe\xdd\xa3\xd9\x56\x8d\x29\x82\x6e\xe3\x52\x95\xa1\xf5\x84\x92\x3c\x80\x8a\x93\x1c\x0b\xc9\x29\xaa\x34\xf8\x41\xe6\x8c\x70\x10\x7e\xcf\xf0\xe3\xf7\xff\x09\x8d\xcb\x98\x58\xc1\x56\xd6\x0a\xbe\x32\x05\x2a\xac\x4b\x20\x94\x5a\xb8\x46\x51\xd4\x53\xc4\x61\xf7\x58\xd5\x30\x33\x62\x4f\x75\x96\x64\xb5\x31\xb2\x23\xcc\x8c\x80\xcc\x88\x90\xe2\x92\xd4\xdc\x00\x55\xb2\xa2\x72\x23\x42\x23\x57\x2b\x9b\xe9\xfc\x26\xfc\xa2\x00\x28\x31\xa4\x99\x4a\x83\x96\xb6\xf5\x21\xd1\x95\xac\xea\xaa\xf1\xa2\x1f\xc4\xfb\x8a\x08\x8a\xd4\xfa\x9c\x6b\x0c\x16\x5f\xb3\x35\x42\x89\x7e\x2f\x67\x87\x90\xc8\x89\x42\x13\xf6\x99\x1e\x01\x23\x89\xbd\x32\x7e\x4b\xd0\xfc\x4b\x6a\xde\x72\xea\xb6\x50\xa2\xa8\x61\xf0\x16\x2a\x7b\xae\x04\x8b\x87\x07\x45\xc4\x0a\xe1\x39\xa3\xf7\x97\xf0\x9c\x94\xb2\x16\x06\x66\x29\x44\xaf\xdd\xa3\xde\xed\x06\xdc\x01\x12\xce\x16\x09\x79\x0a\xde\x20\x45\xce\x59\x7e\x97\x06\x86\xa1\x4a\x1f\x1e\x2c\xf3\xdd\x6e\x0e\x0f\x0f\x6c\x09\xcf\xa3\xef\x31\x27\x95\xc9\x0b\xb2\xdb\xad\x54\xfb\x1c\xe1\x3d\xe6\xb5\xc1\xf1\xe4\xe1\x01\xb9\xc6\xdd\x4e\xd7\x59\xc9\xcc\xb8\x5d\x6e\xc7\x05\xdd\xed\xac\xce\x8d\x9e\xbb\x1d\xc4\x96\xa9\xa0\x78\x0f\xcf\xa3\xef\x50\x31\x49\x35\x78\xfa\x24\x26\x8b\x24\xe6\x6c\xd1\xac\x1b\x1a\x29\xae\xf9\x1e\x2f\xb1\x05\x4c\x87\x73\x17\x36\x4e\xd5\xbe\xa6\x27\xa2\x60\x15\x76\xda\x37\x78\xd0\xcc\xe0\x1d\x6e\xd3\xe0\xe1\xa1\xbf\xb6\x99\xcd\x09\xe7\x19\xb1\x76\xf1\x5b\xeb\x16\xfd\x8a\x16\xa7\x6b\xa6\x5d\x49\xb5\x68\x35\xd8\xab\xfd\x81\x61\x7d\x70\x70\x19\x59\xcd\xe0\xe6\xba\x77\x6a\x9d\x8a\xf8\x57\x07\x11\x7f\x73\x92\xb8\x22\x02\x39\xb8\xbf\xa1\x2e\x09\x6f\x9f\x9b\x68\xe9\x05\xdf\xe1\xa2\xd0\x9e\xd1\x9d\x6a\xdd\x59\x3f\x9d\x83\x5c\xa3\x5a\x72\xb9\x99\x01\xa9\x8d\x9c\x43\x49\xee\xbb\x7c\x77\x33\x9d\xf6\xf5\xb6\xa5\x20\xc9\x38\xba\xd3\x45\xe1\x2f\x35\x6a\xa3\xbb\xb3\xc4\x4f\xb9\xbf\xf6\x48\xa1\x28\x34\xd2\x03\x6b\x58\x89\xd6\xb4\x8e\xaa\xe7\xfa\xce\x98\x27\x75\x5f\x4a\xd9\xa5\x90\xbe\x1a\x0d\xeb\x5e\xb6\x0b\x16\x89\x51\x7b\xba\xb3\xc4\xd0\x8f\x4a\x01\xca\x96\x78\x8f\x65\x00\x7f\xa2\xd9\xbd\x57\x88\xca\xd7\x17\x16\xb2\xe0\x5e\x93\xd8\xd0\x4f\x90\x6c\x41\x98\x11\x8d\x1f\x22\xde\x65\xfa\xbd\x78\xf7\xfa\xa9\xf2\x0b\x24\xca\x64\x48\xcc\x87\x28\xb0\xac\x05\xed\xed\xdf\x9d\x9d\x9f\xaa\x40\x2d\xd8\x1a\x95\x66\x66\xfb\xa1\x1a\x20\xdd\xab\xe0\xdf\x87\x2a\x24\xb1\x51\x4f\x63\xad\xff\xf2\x99\x82\xfb\xb7\x4a\x92\x9b\xc5\xbf\xcb\x0d\x50\x89\x1a\x4c\xc1\x34\xd8\xe4\xfa\x65\x12\x17\x37\x1d\x49\xb5\x78\x67\x27\x9c\x51\x61\xe9\x4a\x0b\x60\x1a\x54\x2d\x5c\xe6\x95\x02\x4c\x81\xc3\x72\xa4\x49\xd2\x11\xbc\x93\xb6\xa4\x5b\xa3\x30\x50\x12\xce\x72\x26\x6b\x0d\x24\x37\x52\x69\x58\x2a\x59\x02\xde\x17\xa4\xd6\xc6\x32\xb2\xc7\x07\x59\x13\xc6\x5d\x2c\x39\x97\x82\x54\x40\xf2\xbc\x2e\x6b\x5b\x92\x8a\x15\xa0\x90\xf5\xaa\x68\x74\x31\x12\x7c\x62\xe2\x52\xac\x3a\x7d\x74\x45\x4a\x20\xc6\x90\xfc\x4e\x5f\x42\x7b\x2a\x00\x51\x08\x86\x21\xb5\xab\x72\x59\x96\x52\xc0\x8d\xa2\x50\x11\x65\xb6\xa0\x87\xb5\x05\xc9\x73\x97\xe5\x22\x78\x2d\xb6\x52\x20\x14\x64\xed\x34\x84\x77\xfe\x3a\x71\x09\x5f\x4b\xb9\xe2\x78\x61\x15\xfc\x1b\xc9\x31\x93\xb2\x5b\x06\x25\xd9\xb6\x72\x9b\x6d\x6c\x98\x29\x98\xb7\x53\x85\xaa\xb4\x3c\x28\x70\x56\x32\xa3\xa3\x24\xae\xf6\x47\xeb\x3e\x49\xf3\xb0\x90\x8a\xfd\x6a\x2b\x1c\xde\x3f\x47\xcd\xc1\x29\xd3\x1e\x92\xce\xfd\x1c\x97\x66\x06\x2f\xfc\x21\x79\x08\xe8\xe6\x2a\x74\x0a\xcd\x2d\x4f\x77\xc5\xb4\x99\x67\x06\x37\xbe\xae\xf5\x15\x05\x35\x3d\x0d\xe8\x01\xe6\xbc\xd0\xdb\xdb\xea\xbe\xd3\xa3\x2b\x8e\xa7\x1d\x13\x0b\x85\xa1\x51\xd6\xac\x67\xcf\x92\xdc\x21\x10\x48\xc8\xc1\x55\xb9\x51\xda\x5d\xb4\x98\x6b\x14\xc4\x66\x83\x68\xbe\xb4\x31\x9c\x7e\xef\x19\x32\xb1\x3a\xbf\x9e\x7a\x68\xda\x07\xcb\xfe\xfc\x7a\xca\x84\x91\xe7\xd7\xd3\xe9\xfd\xf4\x03\xff\x9d\x5f\x4f\xa5\x38\xbf\x9e\x9a\x02\xcf\xaf\xa7\xe7\xd7\x37\x7d\x50\xfb\x91\xb6\xc4\xb4\x54\xa8\xad\xb4\x16\xeb\x01\x18\xa2\x56\x68\xd2\xe0\x7f\x49\x26\x6b\x33\xcb\x38\x11\x77\xc1\xc2\xa9\x6b\xcb\x0e\x87\x82\xd3\x85\x2a\x54\x44\x5b\x48\x58\x8d\x1d\x4a\x9a\xa6\x88\x86\xb1\xae\x95\x92\xb5\xb0\xe9\x11\xec\x9e\x5d\xa8\x8a\x91\x45\x99\x35\xcc\x24\x4a\x32\x15\x2f\xde\xc8\x6a\x1b\x3a\x26\x6e\xf9\x91\x19\x75\x5d\x55\x52\x99\xa8\x6f\x4e\x62\x2f\x44\x1c\x75\x7c\x3b\x7d\x79\xfb\xea\x49\xf5\xb5\x2d\xb7\xdd\x1e\x3a\x0d\x49\x26\xd7\x08\xbe\xb8\xcf\xe4\x3d\x10\x41\x61\xc9\x14\x02\xd9\x90\xed\x17\x49\x4c\xdd\x55\xec\xd3\x51\xbb\x72\x81\x16\x56\xbc\xd6\xb6\x16\x61\x36\x50\xff\x50\x10\xf6\x27\x01\x7c\xc7\x6b\x7d\x09\x55\x9d\x71\xa6\x0b\x20\x20\x70\x03\x89\x36\x4a\x8a\xd5\xc2\x8d\xe6\xf6\xaa\xea\x5e\xa1\x92\xda\x3c\x85\x06\x2c\x33\xa4\xf4\x04\x1e\x7e\x27\x1c\xac\x3c\xe7\xc2\x7f\xbe\xfb\x96\xcd\xe1\xf8\x87\x72\x59\x7b\x62\xff\x51\xfd\x75\x14\xbe\x9b\xcd\x26\x6a\x2d\xe9\x62\xb7\x40\x5e\xc5\x36\x8d\xd5\x82\x99\x6d\xec\x4f\x41\x29\xe2\x2f\x19\x4d\xaf\x6f\xaf\x5f\xbd\xba\x7e\xf1\x6f\xb7\x2f\x5f\x5e\xdf\xbe\x78\xf9\x58\x60\x77\xa0\xf8\xfd\x71\xed\xaf\x43\xdf\xc8\xd7\xb5\x29\xba\xbb\x90\xc7\x4b\x5b\x83\xdb\x4a\x8b\xda\xbb\xa4\x0a\x7e\x37\x86\x6a\x61\x0b\xca\x90\xf0\x93\xb5\xe0\x47\xa0\xc8\xc1\xe8\x09\xcd\x3e\x11\x5a\x2d\x7c\x2c\x52\x64\x6d\xec\x0e\xdb\xa6\x0c\x93\xa2\x83\xd3\x25\x68\x56\x56\x7c\x0b\xf9\xde\xeb\xa7\x71\xf5\xa8\x53\x7e\x13\x56\x43\xb7\x79\x90\xb9\x2a\xae\x94\x14\x6d\xf5\xa6\x6b\x9d\x63\xe5\xba\xf5\xb6\x22\xfa\xcb\xf6\x57\x22\x0c\x13\xd8\x56\x4e\x11\x7c\x2b\xf8\x16\x6a\x8d\xb0\x94\x0a\x28\x66\xf5\x6a\xe5\xca\x3d\x05\x95\x62\x6b\x62\xb0\x2d\x97\x74\x83\x8a\x0e\x14\xbd\x1b\xaa\x2d\x5d\x79\xaf\x92\xfc\xbb\xac\x21\x27\x02\x8c\x22\xf9\x9d\x8f\x94\x5a\x29\x1b\x29\x15\xfa\xdd\x74\x05\x5b\x86\x5c\x6e\x1c\x89\xdf\xf7\x92\x21\x77\xd5\x9b\x46\x84\x42\x6e\xa0\xac\x73\x17\x90\xb6\x3a\x73\x9b\xd8\x10\x66\xa0\x16\x86\x71\x6f\x4f\x53\x2b\x61\x6b\x3d\x1c\x14\x59\x47\x77\xf8\x04\xcb\xc5\xbb\x02\x4f\x94\xb6\xdd\xed\x1b\x14\xbe\xf1\xe4\x50\x29\x69\x30\xb7\x0e\x05\xb2\x22\x4c\x68\xeb\x11\x57\xc6\x61\xf9\x01\xb7\xf3\xee\xa9\x79\xd8\x77\x9a\xdd\x74\x1c\xc3\xd7\x5c\x66\x84\xc3\xda\x22\x3d\xe3\xb6\x2c\x97\x50\x48\xbb\xf5\x9e\xb5\xb4\x21\xa6\xd6\x20\x97\x6e\xd4\x6b\x6e\xd7\xaf\x89\xb2\x1e\xc4\xb2\x32\x90\x36\x7d\x52\x3b\xa6\x51\xad\x9b\xee\xaf\x7d\x35\x0c\xd5\x60\xbe\xb3\x7a\x0a\x3f\xfd\x3c\x7f\xd6\xa8\xf2\x57\x5c\x3a\x48\x58\x7c\xfb\x2d\x9b\x82\x18\xc8\x15\x12\x83\x1a\x72\x2e\x75\xad\xbc\x86\x54\xc9\x0a\xac\x96\x2d\xa7\x96\xb3\x9d\xa8\x9c\xb4\x96\xc9\xb8\x20\xba\x98\x34\x6d\x5e\x85\xce\x4b\xdd\x5c\x3b\x7e\x66\x51\x37\xb6\x0c\x58\x3a\x9d\x03\x4b\x5a\xbe\x11\x47\xb1\x32\xc5\x1c\xd8\xc5\x45\x47\x7c\xc6\x96\x30\x6e\x29\x7e\x62\x3f\x47\xe6\x3e\xb2\x52\x20\x4d\xa1\x2f\xcd\x09\x6c\xf8\xe8\x8a\xb3\x1c\xc7\xec\x12\xae\x26\xf3\x76\x36\x53\x48\xee\xda\xb7\xc6\x8f\xfe\x3f\xf7\x77\x37\x1f\x5a\xc6\x19\x7f\x60\x1b\xdf\xc3\xd1\x40\x60\xc5\xb4\x81\x5a\x71\x68\x62\xd8\xbb\xa0\x73\x88\xa3\xeb\x5b\xe5\x08\x97\xcd\x43\x83\xa9\x76\x0b\x9e\x4d\xa4\x51\xd0\xf1\x7f\xfc\xf0\xed\x37\x91\x36\x8a\x89\x15\x5b\x6e\xc7\x0f\xb5\xe2\x33\x78\x3e\x0e\xfe\xa5\x56\x3c\x98\xfc\x34\xfd\x39\x5a\x13\x5e\xe3\xa5\xf3\xf7\xcc\xfd\x3d\x92\x72\x09\xcd\xe3\x0c\x86\x02\x77\x93\xc9\xfc\x74\xbf\xab\xd7\x9e\x53\xa8\xd1\x8c\x2d\x61\x07\xfc\x43\x1b\x11\x28\xd1\x14\xd2\x85\xae\xc2\x5c\x0a\x81\xb9\x81\xba\x92\xa2\x31\x09\x70\xa9\xf5\x1e\x88\x2d\x45\x7a\x0c\x8a\x86\x3e\x75\xc9\xfa\xbf\x31\xfb\x41\xe6\x77\x68\xc6\xe3\xf1\x86\x09\x2a\x37\x11\x97\xfe\xa8\x8d\x6c\x90\xca\x5c\x72\x48\xd3\x14\x9a\x2c\x1a\x4c\xe0\x4b\x08\x36\xda\xe6\xd3\x00\x66\xf6\xd1\x3e\x4d\xe0\x02\x0e\x97\x17\x36\xdf\x5f\x40\x10\x93\x8a\x05\x13\x1f\x0e\xad\xe1\xa5\x28\x51\x6b\xb2\xc2\xbe\x82\xee\x86\xdb\x81\xcc\xee\xa3\xd4\x2b\x48\xc1\x39\xa8\x22\x4a\xa3\x27\x89\x28\x31\xa4\x45\x9b\xc5\xac\x23\x4b\x53\x10\x35\xe7\x7b\x90\xfa\xa0\x98\xb7\xf0\x1b\x90\x47\x3e\xd7\x7c\x91\xa6\x50\x0b\xea\x4c\x4c\xf7\x2b\xad\xf3\x7d\x33\x64\x12\xd9\xbc\xb0\x5f\x31\x99\xf7\xd1\x3c\xe0\x86\xf4\xb7\xd8\x21\x3d\xe4\x87\xf4\x11\x86\xae\xf7\xf4\x14\x3f\xdf\xab\xea\xb1\x73\x03\x8f\x70\x13\x75\x99\xa1\x7a\x8a\x9d\xef\x3d\x35\xec\x9c\xa9\xdf\x0a\xd3\x5b\x7b\x09\x57\xaf\x26\x8f\x70\x47\xa5\xe4\xa3\xcc\x85\x34\xdb\xf1\x03\x27\x5b\x5b\x33\xc1\xc8\xc8\xea\x8d\x6b\x15\x8d\x2e\x5d\xc6\x9d\x41\xc7\xe1\xd2\x7d\x04\x98\xc1\xc8\xbd\xd9\x79\x56\xa2\x5b\xf5\x72\x3a\x9d\x5e\x42\xfb\xf5\xec\x2f\xc4\x06\xa1\xaa\x71\xf7\x88\x3e\xba\xce\x73\x9b\xf7\x3f\x45\xa3\x86\x47\xa7\x53\xf3\xfe\x09\x5a\x75\xb9\x61\xa0\x16\xfc\xe9\x4f\x70\x34\x3b\x84\x71\x1c\xc3\x7f\x11\x75\xe7\x1a\x3b\x95\xc2\xb5\x6b\xfe\x74\xf4\x25\xd3\xda\x35\x55\x34\x50\x29\xb0\x59\xf3\x71\xc7\xfe\x91\x8e\x0d\x19\x2c\x60\x7a\xa8\xa0\x3d\x0e\x7b\x69\xe1\x44\xb6\xe8\xf1\x1d\x26\x82\xb3\x5d\x5f\xde\x60\x25\x2b\x11\xbe\x48\x21\x08\xfa\x8b\x8f\x28\x2c\x41\xc7\xec\x4c\xa3\x79\xe7\x7d\x31\x6e\xb2\xe3\xa9\xdc\x35\xb9\x84\x9b\xe9\x74\x3a\x39\x52\x62\xb7\x37\xef\xeb\xca\x96\x4d\x40\xc4\xd6\x1d\x89\x9d\x6d\x5d\xe1\x68\x4b\x20\x7b\xa4\x71\xc8\x25\xe7\xbe\x66\x69\x96\x5a\x03\x37\x4d\xb0\x14\xc2\xab\xf9\x89\x2c\xda\xb3\x64\x6f\x6b\x87\xee\x39\x61\xfb\x43\x17\x0d\x6d\x76\x40\x1c\x5e\x0d\x9c\x32\xf0\xd7\x69\xc7\x9c\x75\x7a\xb3\xbd\x45\x0f\xdc\xb5\xf7\xd7\xa1\xcd\x7a\xfa\x7b\x3e\x17\x57\x1f\xb8\x8d\x6e\xba\xaa\x75\x31\x3e\x50\x74\x32\x3f\xf6\xcd\x5b\x83\xca\x56\xc9\xd2\xa6\x2c\xeb\x0b\x7b\x15\x50\x78\xe4\x12\x57\xaa\x2b\x0c\x15\x0a\x8a\xaa\x2d\x29\x7c\x65\x6f\x0b\xc0\x81\xcb\xfc\xad\xb2\x0f\xa7\x8f\x0c\x18\x57\x92\x49\x81\x00\x00\x07\x41\xe0\x80\x3a\x40\xaa\x25\x46\x4e\x2a\x8d\x14\x52\xf0\x3f\x66\x18\x4f\xa2\x5a\xb0\xfb\xf1\x24\x6c\xde\x0f\x79\xb4\xf3\xf3\xee\x9a\xd8\xaa\x7d\x91\x42\x90\x18\x05\x8c\xa6\xa3\x00\x2e\x4e\x85\xa0\xcd\xba\xa3\xc5\x5e\x83\xfe\x52\x80\xc4\xd0\x85\xeb\x67\xfb\xfb\xda\x3f\x82\x8c\xe4\x77\x2b\x77\x11\x9a\xd9\x52\x6b\x7c\xc4\x96\xac\x89\x21\xca\x71\x9d\xcc\x61\x4f\xde\x5c\x14\x73\xeb\x9c\x39\xf8\x1b\xa9\x6b\x9b\x43\xf7\xa9\xc9\xbd\x65\x52\x51\x54\xa1\x22\x94\xd5\x7a\x06\x2f\xaa\xfb\xf9\x3f\xda\x4f\x71\xae\xb9\xff\xa4\xaa\x95\xc2\xc5\x91\x46\x4d\x93\xf8\x02\x82\x24\xb6\x04\xbf\xc5\xa6\xdb\x6c\xff\x47\x14\x70\xe2\x13\x06\x74\x3f\x71\x68\xc6\x4b\x46\x29\x47\xab\xf0\x9e\xbd\x0d\x46\xeb\xff\x7e\x48\x0d\x45\x42\xf3\xed\x62\xbf\x66\x07\xc8\x35\x3e\xb1\xa0\xfb\x0c\x32\xb2\x00\x08\xed\x96\x99\xb3\x79\x73\xd9\x76\xc3\x6a\xe4\x6c\xd1\xfc\x24\x86\xd6\xca\xd5\x5a\xe3\xb0\x01\xd8\x25\x8c\xb4\xad\xfd\xa8\x1e\x4d\xa2\xa2\x2e\x89\x60\xbf\xe2\xd8\xe6\xa5\x89\xb7\x95\xfb\xae\x12\x1c\x1f\xc9\x47\xca\xec\x3f\x78\x8c\xda\x1c\x37\x6a\x8c\x38\x6a\xbd\xfb\x62\x7f\xb7\x9f\xc1\x74\x3e\xfa\x48\x0b\x9d\x96\x12\x66\x44\x41\xff\x25\x6c\x93\x2f\x28\x69\xa5\xb7\x73\x19\x51\x23\xdf\xc9\x70\xf5\xb9\x90\x9b\x74\x74\x33\xed\x94\xf4\x8e\x76\x7e\x1e\x35\x58\x3b\x72\x86\xd5\xb2\x0d\xcd\x05\xdc\x4c\x3f\x87\xb6\xbe\x1b\x72\xb0\x03\xa3\x58\x85\x14\x48\x6e\xd8\x1a\xff\x1f\x36\xf2\x19\x8c\xfc\xd1\x2a\x5a\x1c\xb6\xc6\x73\x30\x1d\xe8\x6b\x67\x3b\xdb\xfe\xab\x8d\x37\x88\x9d\x85\x2f\x20\x38\xb9\x91\x47\x91\x78\x40\x78\x10\xda\x8f\xc7\xbd\xfb\x50\x18\x1c\xe6\x14\x5b\xed\x76\x1f\xb9\x27\x51\x61\x4a\x3e\x0e\x12\xe3\x7e\xec\x64\x75\xee\x38\x38\x06\x7e\x78\x58\xd2\xed\x86\x17\x19\x7b\x7f\xc7\x83\x7b\x16\xf4\x8a\x93\xee\x2e\xd6\x56\x22\xb0\xdb\xff\x26\x2c\x8e\xe1\x07\x43\x94\x01\x02\x3f\xbe\x85\xba\xa2\xc4\xf8\x4f\x72\x36\x3f\xfa\xae\x73\xfb\xa3\xb1\x8c\x28\x0d\x4b\xa9\x36\x44\xd1\xa6\x3f\x63\x0a\xdc\xba\x4f\x72\x6d\xe9\xa7\xd1\xbc\xb5\xa7\xd8\x9a\xf0\xf1\xd1\xbd\xef\xf9\x78\x14\xf5\x5d\x3e\x9a\x44\x48\xf2\xe2\x98\xd0\x65\xac\x4e\x6e\x0a\xdf\xb8\x2b\xc0\xf8\xf9\xd8\x14\x4c\x4f\x22\x62\x8c\x1a\x8f\x06\x60\x18\x4d\xac\x5f\xaf\x7a\x57\xb2\x6e\x79\x32\x08\xab\xa7\x78\xec\x8b\xe9\xae\x10\x68\xc9\x73\xad\xc7\x1e\x57\xa3\xcb\x1e\xef\x21\xac\x46\xe7\xa3\xce\x51\xfb\xf0\xde\xef\x23\x3d\xa9\xc9\x80\xf5\xc8\x46\xd9\xe8\x48\x3c\xa1\xf4\x8d\x8d\x9f\x71\x70\x22\xd2\x0f\xd1\x31\xe9\x8c\xed\xcf\xeb\x27\xad\xec\x7f\x5e\xf3\x88\x89\x19\x1d\x4d\x22\x5d\x67\xbe\x37\x31\x7e\xd9\x5d\xc0\x5a\x32\x07\xde\xc3\x54\x70\x54\x50\x58\x11\xc3\xa2\x22\x3c\x28\x42\x9e\xc8\x1a\x8d\x48\xbf\xab\xdd\xa5\x35\xf8\x74\xd2\xb5\xb6\xbe\xd2\xb6\xb8\xf2\xad\xff\x0d\x66\xda\x75\x12\xa0\xc1\xbb\xeb\xe6\xf8\xae\xcd\xeb\xef\xde\xf6\x3a\x37\x5d\x44\x8c\x1d\xf7\xee\xf7\x9c\xa7\xfa\x24\x27\x7f\x40\xba\xd9\x6c\x22\xff\x45\xcb\xb5\xf1\xbb\x46\x4a\x4c\x2a\x16\xbd\xd7\x01\x10\xbd\x15\x39\x50\x5c\xa2\x5a\xf4\xd8\x37\xdd\x95\x24\xf6\x3f\x6d\x4c\x62\xff\xeb\xed\xff\x0b\x00\x00\xff\xff\x56\xf8\xb5\xef\xce\x2d\x00\x00") func faucetHtmlBytes() ([]byte, error) { return bindataRead( @@ -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/vendor/github.com/ethereum/go-ethereum/cmd/geth/chaincmd.go b/vendor/github.com/ethereum/go-ethereum/cmd/geth/chaincmd.go index 4a9a7b11b5e..35bf576e1d9 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/geth/chaincmd.go +++ b/vendor/github.com/ethereum/go-ethereum/cmd/geth/chaincmd.go @@ -202,7 +202,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 +211,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/vendor/github.com/ethereum/go-ethereum/cmd/geth/config.go b/vendor/github.com/ethereum/go-ethereum/cmd/geth/config.go index 27490c40486..50e4de2e787 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/geth/config.go +++ b/vendor/github.com/ethereum/go-ethereum/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/vendor/github.com/ethereum/go-ethereum/cmd/geth/consolecmd.go b/vendor/github.com/ethereum/go-ethereum/cmd/geth/consolecmd.go index 2bb452d7361..9d5cc38a1bb 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/geth/consolecmd.go +++ b/vendor/github.com/ethereum/go-ethereum/cmd/geth/consolecmd.go @@ -17,8 +17,10 @@ package main import ( + "fmt" "os" "os/signal" + "path/filepath" "strings" "github.com/ethereum/go-ethereum/cmd/utils" @@ -112,7 +114,22 @@ func localConsole(ctx *cli.Context) error { // console to it. func remoteConsole(ctx *cli.Context) error { // Attach to a remotely running geth instance and start the JavaScript console - client, err := dialRPC(ctx.Args().First()) + endpoint := ctx.Args().First() + if endpoint == "" { + path := node.DefaultDataDir() + if ctx.GlobalIsSet(utils.DataDirFlag.Name) { + path = ctx.GlobalString(utils.DataDirFlag.Name) + } + if path != "" { + if ctx.GlobalBool(utils.TestnetFlag.Name) { + path = filepath.Join(path, "testnet") + } else if ctx.GlobalBool(utils.RinkebyFlag.Name) { + path = filepath.Join(path, "rinkeby") + } + } + endpoint = fmt.Sprintf("%s/geth.ipc", path) + } + client, err := dialRPC(endpoint) if err != nil { utils.Fatalf("Unable to attach to remote geth: %v", err) } diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/geth/main.go b/vendor/github.com/ethereum/go-ethereum/cmd/geth/main.go index bdb7fad62af..a82e5c89cf1 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/geth/main.go +++ b/vendor/github.com/ethereum/go-ethereum/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(ðereum); 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/vendor/github.com/ethereum/go-ethereum/cmd/geth/misccmd.go b/vendor/github.com/ethereum/go-ethereum/cmd/geth/misccmd.go index 2e68dcda326..aa9b1ee568e 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/geth/misccmd.go +++ b/vendor/github.com/ethereum/go-ethereum/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 . -`) +along with geth. If not, see .`) return nil } diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/geth/usage.go b/vendor/github.com/ethereum/go-ethereum/cmd/geth/usage.go index a834d5b7aec..a1558c2330c 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/geth/usage.go +++ b/vendor/github.com/ethereum/go-ethereum/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/vendor/github.com/ethereum/go-ethereum/cmd/p2psim/main.go b/vendor/github.com/ethereum/go-ethereum/cmd/p2psim/main.go index 56b74d135be..0c8ed038d5b 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/p2psim/main.go +++ b/vendor/github.com/ethereum/go-ethereum/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 . + // 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/vendor/github.com/ethereum/go-ethereum/cmd/puppeth/genesis.go b/vendor/github.com/ethereum/go-ethereum/cmd/puppeth/genesis.go new file mode 100644 index 00000000000..f747f473958 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/cmd/puppeth/genesis.go @@ -0,0 +1,379 @@ +// 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 . + +package main + +import ( + "encoding/binary" + "errors" + "math" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/params" +) + +// cppEthereumGenesisSpec represents the genesis specification format used by the +// C++ Ethereum implementation. +type cppEthereumGenesisSpec struct { + SealEngine string `json:"sealEngine"` + Params struct { + AccountStartNonce hexutil.Uint64 `json:"accountStartNonce"` + HomesteadForkBlock hexutil.Uint64 `json:"homesteadForkBlock"` + EIP150ForkBlock hexutil.Uint64 `json:"EIP150ForkBlock"` + EIP158ForkBlock hexutil.Uint64 `json:"EIP158ForkBlock"` + ByzantiumForkBlock hexutil.Uint64 `json:"byzantiumForkBlock"` + ConstantinopleForkBlock hexutil.Uint64 `json:"constantinopleForkBlock"` + NetworkID hexutil.Uint64 `json:"networkID"` + ChainID hexutil.Uint64 `json:"chainID"` + MaximumExtraDataSize hexutil.Uint64 `json:"maximumExtraDataSize"` + MinGasLimit hexutil.Uint64 `json:"minGasLimit"` + MaxGasLimit hexutil.Uint64 `json:"maxGasLimit"` + GasLimitBoundDivisor hexutil.Uint64 `json:"gasLimitBoundDivisor"` + MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"` + DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"` + DurationLimit *hexutil.Big `json:"durationLimit"` + BlockReward *hexutil.Big `json:"blockReward"` + } `json:"params"` + + Genesis struct { + Nonce hexutil.Bytes `json:"nonce"` + Difficulty *hexutil.Big `json:"difficulty"` + MixHash common.Hash `json:"mixHash"` + Author common.Address `json:"author"` + Timestamp hexutil.Uint64 `json:"timestamp"` + ParentHash common.Hash `json:"parentHash"` + ExtraData hexutil.Bytes `json:"extraData"` + GasLimit hexutil.Uint64 `json:"gasLimit"` + } `json:"genesis"` + + Accounts map[common.Address]*cppEthereumGenesisSpecAccount `json:"accounts"` +} + +// cppEthereumGenesisSpecAccount is the prefunded genesis account and/or precompiled +// contract definition. +type cppEthereumGenesisSpecAccount struct { + Balance *hexutil.Big `json:"balance"` + Nonce uint64 `json:"nonce,omitempty"` + Precompiled *cppEthereumGenesisSpecBuiltin `json:"precompiled,omitempty"` +} + +// cppEthereumGenesisSpecBuiltin is the precompiled contract definition. +type cppEthereumGenesisSpecBuiltin struct { + Name string `json:"name,omitempty"` + StartingBlock hexutil.Uint64 `json:"startingBlock,omitempty"` + Linear *cppEthereumGenesisSpecLinearPricing `json:"linear,omitempty"` +} + +type cppEthereumGenesisSpecLinearPricing struct { + Base uint64 `json:"base"` + Word uint64 `json:"word"` +} + +// newCppEthereumGenesisSpec converts a go-ethereum genesis block into a Parity specific +// chain specification format. +func newCppEthereumGenesisSpec(network string, genesis *core.Genesis) (*cppEthereumGenesisSpec, error) { + // Only ethash is currently supported between go-ethereum and cpp-ethereum + if genesis.Config.Ethash == nil { + return nil, errors.New("unsupported consensus engine") + } + // Reconstruct the chain spec in Parity's format + spec := &cppEthereumGenesisSpec{ + SealEngine: "Ethash", + } + spec.Params.AccountStartNonce = 0 + spec.Params.HomesteadForkBlock = (hexutil.Uint64)(genesis.Config.HomesteadBlock.Uint64()) + spec.Params.EIP150ForkBlock = (hexutil.Uint64)(genesis.Config.EIP150Block.Uint64()) + spec.Params.EIP158ForkBlock = (hexutil.Uint64)(genesis.Config.EIP158Block.Uint64()) + spec.Params.ByzantiumForkBlock = (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()) + spec.Params.ConstantinopleForkBlock = (hexutil.Uint64)(math.MaxUint64) + + spec.Params.NetworkID = (hexutil.Uint64)(genesis.Config.ChainId.Uint64()) + spec.Params.ChainID = (hexutil.Uint64)(genesis.Config.ChainId.Uint64()) + + spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize) + 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.Uint64)(params.GasLimitBoundDivisor) + spec.Params.DurationLimit = (*hexutil.Big)(params.DurationLimit) + spec.Params.BlockReward = (*hexutil.Big)(ethash.FrontierBlockReward) + + spec.Genesis.Nonce = (hexutil.Bytes)(make([]byte, 8)) + binary.LittleEndian.PutUint64(spec.Genesis.Nonce[:], genesis.Nonce) + + spec.Genesis.MixHash = genesis.Mixhash + spec.Genesis.Difficulty = (*hexutil.Big)(genesis.Difficulty) + spec.Genesis.Author = genesis.Coinbase + spec.Genesis.Timestamp = (hexutil.Uint64)(genesis.Timestamp) + spec.Genesis.ParentHash = genesis.ParentHash + spec.Genesis.ExtraData = (hexutil.Bytes)(genesis.ExtraData) + spec.Genesis.GasLimit = (hexutil.Uint64)(genesis.GasLimit) + + spec.Accounts = make(map[common.Address]*cppEthereumGenesisSpecAccount) + for address, account := range genesis.Alloc { + spec.Accounts[address] = &cppEthereumGenesisSpecAccount{ + Balance: (*hexutil.Big)(account.Balance), + Nonce: account.Nonce, + } + } + spec.Accounts[common.BytesToAddress([]byte{1})].Precompiled = &cppEthereumGenesisSpecBuiltin{ + Name: "ecrecover", Linear: &cppEthereumGenesisSpecLinearPricing{Base: 3000}, + } + spec.Accounts[common.BytesToAddress([]byte{2})].Precompiled = &cppEthereumGenesisSpecBuiltin{ + Name: "sha256", Linear: &cppEthereumGenesisSpecLinearPricing{Base: 60, Word: 12}, + } + spec.Accounts[common.BytesToAddress([]byte{3})].Precompiled = &cppEthereumGenesisSpecBuiltin{ + Name: "ripemd160", Linear: &cppEthereumGenesisSpecLinearPricing{Base: 600, Word: 120}, + } + spec.Accounts[common.BytesToAddress([]byte{4})].Precompiled = &cppEthereumGenesisSpecBuiltin{ + Name: "identity", Linear: &cppEthereumGenesisSpecLinearPricing{Base: 15, Word: 3}, + } + if genesis.Config.ByzantiumBlock != nil { + spec.Accounts[common.BytesToAddress([]byte{5})].Precompiled = &cppEthereumGenesisSpecBuiltin{ + Name: "modexp", StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()), + } + spec.Accounts[common.BytesToAddress([]byte{6})].Precompiled = &cppEthereumGenesisSpecBuiltin{ + Name: "alt_bn128_G1_add", StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()), Linear: &cppEthereumGenesisSpecLinearPricing{Base: 500}, + } + spec.Accounts[common.BytesToAddress([]byte{7})].Precompiled = &cppEthereumGenesisSpecBuiltin{ + Name: "alt_bn128_G1_mul", StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()), Linear: &cppEthereumGenesisSpecLinearPricing{Base: 40000}, + } + spec.Accounts[common.BytesToAddress([]byte{8})].Precompiled = &cppEthereumGenesisSpecBuiltin{ + Name: "alt_bn128_pairing_product", StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()), + } + } + return spec, nil +} + +// parityChainSpec is the chain specification format used by Parity. +type parityChainSpec struct { + Name string `json:"name"` + Engine struct { + Ethash struct { + Params struct { + 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.Uint64 `json:"minGasLimit"` + NetworkID hexutil.Uint64 `json:"networkID"` + MaxCodeSize uint64 `json:"maxCodeSize"` + EIP155Transition uint64 `json:"eip155Transition"` + EIP98Transition uint64 `json:"eip98Transition"` + EIP86Transition uint64 `json:"eip86Transition"` + EIP140Transition uint64 `json:"eip140Transition"` + EIP211Transition uint64 `json:"eip211Transition"` + EIP214Transition uint64 `json:"eip214Transition"` + EIP658Transition uint64 `json:"eip658Transition"` + } `json:"params"` + + Genesis struct { + Seal struct { + Ethereum struct { + Nonce hexutil.Bytes `json:"nonce"` + MixHash hexutil.Bytes `json:"mixHash"` + } `json:"ethereum"` + } `json:"seal"` + + Difficulty *hexutil.Big `json:"difficulty"` + Author common.Address `json:"author"` + Timestamp hexutil.Uint64 `json:"timestamp"` + ParentHash common.Hash `json:"parentHash"` + ExtraData hexutil.Bytes `json:"extraData"` + GasLimit hexutil.Uint64 `json:"gasLimit"` + } `json:"genesis"` + + Nodes []string `json:"nodes"` + Accounts map[common.Address]*parityChainSpecAccount `json:"accounts"` +} + +// parityChainSpecAccount is the prefunded genesis account and/or precompiled +// contract definition. +type parityChainSpecAccount struct { + Balance *hexutil.Big `json:"balance"` + Nonce uint64 `json:"nonce,omitempty"` + Builtin *parityChainSpecBuiltin `json:"builtin,omitempty"` +} + +// parityChainSpecBuiltin is the precompiled contract definition. +type parityChainSpecBuiltin struct { + Name string `json:"name,omitempty"` + ActivateAt uint64 `json:"activate_at,omitempty"` + Pricing *parityChainSpecPricing `json:"pricing,omitempty"` +} + +// parityChainSpecPricing represents the different pricing models that builtin +// contracts might advertise using. +type parityChainSpecPricing struct { + Linear *parityChainSpecLinearPricing `json:"linear,omitempty"` + ModExp *parityChainSpecModExpPricing `json:"modexp,omitempty"` + AltBnPairing *parityChainSpecAltBnPairingPricing `json:"alt_bn128_pairing,omitempty"` +} + +type parityChainSpecLinearPricing struct { + Base uint64 `json:"base"` + Word uint64 `json:"word"` +} + +type parityChainSpecModExpPricing struct { + Divisor uint64 `json:"divisor"` +} + +type parityChainSpecAltBnPairingPricing struct { + Base uint64 `json:"base"` + Pair uint64 `json:"pair"` +} + +// newParityChainSpec converts a go-ethereum genesis block into a Parity specific +// chain specification format. +func newParityChainSpec(network string, genesis *core.Genesis, bootnodes []string) (*parityChainSpec, error) { + // Only ethash is currently supported between go-ethereum and Parity + if genesis.Config.Ethash == nil { + return nil, errors.New("unsupported consensus engine") + } + // Reconstruct the chain spec in Parity's format + spec := &parityChainSpec{ + Name: network, + Nodes: bootnodes, + } + spec.Engine.Ethash.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty) + spec.Engine.Ethash.Params.DifficultyBoundDivisor = (*hexutil.Big)(params.DifficultyBoundDivisor) + 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() + spec.Engine.Ethash.Params.EIP150Transition = genesis.Config.EIP150Block.Uint64() + spec.Engine.Ethash.Params.EIP160Transition = genesis.Config.EIP155Block.Uint64() + spec.Engine.Ethash.Params.EIP161abcTransition = genesis.Config.EIP158Block.Uint64() + spec.Engine.Ethash.Params.EIP161dTransition = genesis.Config.EIP158Block.Uint64() + spec.Engine.Ethash.Params.EIP649Reward = (*hexutil.Big)(ethash.ByzantiumBlockReward) + spec.Engine.Ethash.Params.EIP100bTransition = genesis.Config.ByzantiumBlock.Uint64() + spec.Engine.Ethash.Params.EIP649Transition = genesis.Config.ByzantiumBlock.Uint64() + + spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize) + 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() + spec.Params.EIP98Transition = math.MaxUint64 + spec.Params.EIP86Transition = math.MaxUint64 + spec.Params.EIP140Transition = genesis.Config.ByzantiumBlock.Uint64() + spec.Params.EIP211Transition = genesis.Config.ByzantiumBlock.Uint64() + spec.Params.EIP214Transition = genesis.Config.ByzantiumBlock.Uint64() + spec.Params.EIP658Transition = genesis.Config.ByzantiumBlock.Uint64() + + spec.Genesis.Seal.Ethereum.Nonce = (hexutil.Bytes)(make([]byte, 8)) + binary.LittleEndian.PutUint64(spec.Genesis.Seal.Ethereum.Nonce[:], genesis.Nonce) + + spec.Genesis.Seal.Ethereum.MixHash = (hexutil.Bytes)(genesis.Mixhash[:]) + spec.Genesis.Difficulty = (*hexutil.Big)(genesis.Difficulty) + spec.Genesis.Author = genesis.Coinbase + spec.Genesis.Timestamp = (hexutil.Uint64)(genesis.Timestamp) + spec.Genesis.ParentHash = genesis.ParentHash + spec.Genesis.ExtraData = (hexutil.Bytes)(genesis.ExtraData) + spec.Genesis.GasLimit = (hexutil.Uint64)(genesis.GasLimit) + + spec.Accounts = make(map[common.Address]*parityChainSpecAccount) + for address, account := range genesis.Alloc { + spec.Accounts[address] = &parityChainSpecAccount{ + Balance: (*hexutil.Big)(account.Balance), + Nonce: account.Nonce, + } + } + spec.Accounts[common.BytesToAddress([]byte{1})].Builtin = &parityChainSpecBuiltin{ + Name: "ecrecover", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 3000}}, + } + spec.Accounts[common.BytesToAddress([]byte{2})].Builtin = &parityChainSpecBuiltin{ + Name: "sha256", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 60, Word: 12}}, + } + spec.Accounts[common.BytesToAddress([]byte{3})].Builtin = &parityChainSpecBuiltin{ + Name: "ripemd160", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 600, Word: 120}}, + } + spec.Accounts[common.BytesToAddress([]byte{4})].Builtin = &parityChainSpecBuiltin{ + Name: "identity", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 15, Word: 3}}, + } + if genesis.Config.ByzantiumBlock != nil { + spec.Accounts[common.BytesToAddress([]byte{5})].Builtin = &parityChainSpecBuiltin{ + Name: "modexp", ActivateAt: genesis.Config.ByzantiumBlock.Uint64(), Pricing: &parityChainSpecPricing{ModExp: &parityChainSpecModExpPricing{Divisor: 20}}, + } + spec.Accounts[common.BytesToAddress([]byte{6})].Builtin = &parityChainSpecBuiltin{ + Name: "alt_bn128_add", ActivateAt: genesis.Config.ByzantiumBlock.Uint64(), Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 500}}, + } + spec.Accounts[common.BytesToAddress([]byte{7})].Builtin = &parityChainSpecBuiltin{ + Name: "alt_bn128_mul", ActivateAt: genesis.Config.ByzantiumBlock.Uint64(), Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 40000}}, + } + spec.Accounts[common.BytesToAddress([]byte{8})].Builtin = &parityChainSpecBuiltin{ + Name: "alt_bn128_pairing", ActivateAt: genesis.Config.ByzantiumBlock.Uint64(), Pricing: &parityChainSpecPricing{AltBnPairing: &parityChainSpecAltBnPairingPricing{Base: 100000, Pair: 80000}}, + } + } + return spec, nil +} + +// pyEthereumGenesisSpec represents the genesis specification format used by the +// Python Ethereum implementation. +type pyEthereumGenesisSpec struct { + Nonce hexutil.Bytes `json:"nonce"` + Timestamp hexutil.Uint64 `json:"timestamp"` + ExtraData hexutil.Bytes `json:"extraData"` + GasLimit hexutil.Uint64 `json:"gasLimit"` + Difficulty *hexutil.Big `json:"difficulty"` + Mixhash common.Hash `json:"mixhash"` + Coinbase common.Address `json:"coinbase"` + Alloc core.GenesisAlloc `json:"alloc"` + ParentHash common.Hash `json:"parentHash"` +} + +// newPyEthereumGenesisSpec converts a go-ethereum genesis block into a Parity specific +// chain specification format. +func newPyEthereumGenesisSpec(network string, genesis *core.Genesis) (*pyEthereumGenesisSpec, error) { + // Only ethash is currently supported between go-ethereum and pyethereum + if genesis.Config.Ethash == nil { + return nil, errors.New("unsupported consensus engine") + } + spec := &pyEthereumGenesisSpec{ + Timestamp: (hexutil.Uint64)(genesis.Timestamp), + ExtraData: genesis.ExtraData, + GasLimit: (hexutil.Uint64)(genesis.GasLimit), + Difficulty: (*hexutil.Big)(genesis.Difficulty), + Mixhash: genesis.Mixhash, + Coinbase: genesis.Coinbase, + Alloc: genesis.Alloc, + ParentHash: genesis.ParentHash, + } + spec.Nonce = (hexutil.Bytes)(make([]byte, 8)) + binary.LittleEndian.PutUint64(spec.Nonce[:], genesis.Nonce) + + return spec, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/puppeth/module_dashboard.go b/vendor/github.com/ethereum/go-ethereum/cmd/puppeth/module_dashboard.go index 1cf6cab799f..1cb2d45491e 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/puppeth/module_dashboard.go +++ b/vendor/github.com/ethereum/go-ethereum/cmd/puppeth/module_dashboard.go @@ -18,10 +18,12 @@ package main import ( "bytes" + "encoding/json" "fmt" "html/template" "math/rand" "path/filepath" + "strconv" "strings" "github.com/ethereum/go-ethereum/log" @@ -76,25 +78,26 @@ var dashboardContent = `
-
-